У меня есть приложение на Linux С++, которое получает последовательные UDP-пакеты. Из-за последовательности, я могу легко определить, когда пакет потерян или переупорядочен, т.е. Когда встречается "пробел". Система имеет механизм восстановления для устранения пробелов, однако лучше всего избегать пробелов в первую очередь. Используя простой пакетный сниффер на основе libpcap, я определил, что в данных на аппаратном уровне нет пробелов. Тем не менее, я вижу много пробелов в своем приложении. Это говорит о том, что ядро отбрасывает пакеты; это подтверждается просмотром файла /proc/net/snmp. Когда мое приложение встречает пробел, счетчик Udp InErrors увеличивается.
На системном уровне мы увеличили максимальный буфер приема:
# sysctl net.core.rmem_max
net.core.rmem_max = 33554432
На уровне приложения мы увеличили размер буфера приема:
int sockbufsize = 33554432
int ret = setsockopt(my_socket_fd, SOL_SOCKET, SO_RCVBUF,
(char *)&sockbufsize, (int)sizeof(sockbufsize));
// check return code
sockbufsize = 0;
ret = getsockopt(my_socket_fd, SOL_SOCKET, SO_RCVBUF,
(char*)&sockbufsize, &size);
// print sockbufsize
После вызова метода getsockopt() печатное значение всегда равно 2x, на которое оно установлено (67108864 в приведенном выше примере), но я считаю, что этого следует ожидать.
Я знаю, что неспособность быстро потреблять данные может привести к потере пакетов. Тем не менее, все это приложение выполняет проверку последовательности, а затем выталкивает данные в очередь; фактическая обработка выполняется в другом потоке. Кроме того, машина современная (Dual Xeon X5560, 8 ГБ оперативной памяти) и очень легко загружена. У нас буквально десятки идентичных приложений, получающих данные с гораздо более высокой скоростью, которые не испытывают этой проблемы.
Помимо слишком медленного использования приложений, существуют ли другие причины, по которым ядро Linux может отказаться от пакетов UDP?
FWIW, это на CentOS 4, с ядром 2.6.9-89.0.25.ELlargesmp.