Пакет UDP-пакетов - INErrors Vs.RcvbufErrors
Я написал простую программу UDP Server, чтобы больше узнать о возможных узких местах сети.
Сервер UDP: создает сокет UDP, привязывает его к указанному порту и addr и добавляет дескриптор файла сокета в список интересов epoll. Тогда его epoll ждет входящего пакета. При приеме входящего пакета (EPOLLIN) он считывает пакет и просто печатает полученную длину пакета. Довольно просто, правильно:)
Клиент UDP: я использовал hping, как показано ниже:
hping3 192.168.1.2 --udp -p 9996 --flood -d 100
Когда я отправляю пакеты udp со 100 пакетами в секунду, я не нахожу потери UDP-пакета. Но когда я заливаю пакеты udp (как показано в приведенной выше команде), я вижу значительную потерю пакетов.
Test1:
Когда из UDP-клиента заливается 26356 пакетов, моя примерная программа получает ТОЛЬКО 12127 пакетов, а остальные 14230 пакетов отбрасываются ядром, как показано в /proc/net/snmp.
cat/proc/net/snmp | grep Udp:
Udp: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors
Udp: 12372 0 14230 218 14230 0
Процент потери пакетов Test1 составляет ~ 53%.
Я подтвердил, что на аппаратном уровне не так много потерь, используя команду ethtool -S eспасибо как на стороне клиента, так и на стороне сервера, тогда как на уровне апплета я вижу потерю 53%, как было сказано выше.
Следовательно, чтобы уменьшить потерю пакетов, я пробовал:
- Увеличен приоритет моей выборки с помощью renice.
- Увеличенный размер буфера приема (как на уровне системы, так и на уровне процесса)
Повысьте приоритет до -20:
renice -20 2022
2022 (идентификатор процесса) старый приоритет 0, новый приоритет -20
Увеличьте размер буфера приема до 16 МБ:
На уровне процесса:
int sockbufsize = 16777216;
setockopt (sockfd, SOL_SOCKET, SO_RCVBUF, (char *) & sockbufsize, (int) sizeof (sockbufsize))
На уровне ядра:
cat/proc/sys/net/core/rmem_default
16777216
cat/proc/sys/net/core/rmem_max
16777216
После этих изменений выполняется Test2.
Test2:
Когда из UDP-клиента заливается 1985076 пакетов, моя примерная программа получает пакеты 1848791, а оставшиеся пакеты 136286 получает ядро, как показано в /proc/net/snmp.
cat/proc/net/snmp | grep Udp:
Udp: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors
Udp: 1849064 0 136286 236 0 0
Для Test2 процент потери пакетов составляет 6%.
Потеря пакетов значительно снижается. Но у меня есть следующие вопросы:
- Можно ли уменьшить потери пакетов?!? Я знаю, что я жадный здесь:) Но я просто пытаюсь выяснить, возможно ли уменьшить потери пакетов.
- В отличие от Test1, в Test2 InErrors не соответствует RcvbufErrors и RcvbufErrors всегда равен нулю. Может кто-нибудь объяснить причину этого, пожалуйста?!? В чем же разница между InErrors и RcvbufErrors. Я понимаю RcvbufErrors, но не InErrors.
Спасибо за вашу помощь и время!!!
Ответы
Ответ 1
Настройка сетевого сетевого ядра Linux для снижения пакетов снижается, так как есть много параметров настройки от драйвера, вплоть до сетевого стека.
Я написал длинный пост , объясняющий все параметры настройки сверху вниз и объясняющие, что означает каждое из полей в /proc/net/snmp
вы можете понять, почему эти ошибки происходят. Взгляните, я думаю, это должно помочь вам снизить вашу сеть до 0.
Ответ 2
Если на аппаратном уровне нет капель, то в основном речь должна идти о памяти, вы должны настроить параметры конфигурации ядра, чтобы достичь 0 капель (очевидно, вам нужно разумное сбалансированное оборудование для сетевого трафика, recv'ing).
Я думаю, что вам не хватает netdev_max_backlog, что важно для входящих пакетов:
Максимальное количество пакетов, поставленных в очередь на стороне INPUT, когда интерфейс получает пакеты быстрее, чем ядро, может обрабатывать их.
Ответ 3
InErrors состоит из:
- поврежденные пакеты (неправильные заголовки или контрольная сумма)
- полный размер буфера RCV
Итак, я предполагаю, что вы исправили проблему переполнения буфера (RcvbufErrors - 0), а оставшиеся - это пакеты с неправильными контрольными суммами.