Каков максимальный эффективный размер буфера отправки сокета в Linux? - PullRequest
0 голосов
/ 02 ноября 2018

Мне известен параметр net.core.wmem_max для sysctl, который управляет максимальным размером буфера сокета, который я могу запросить через setsockopt(). Однако, кажется, есть более фундаментальное ограничение, с которым я сталкиваюсь. Краткое описание моего сценария:

У меня есть устройство, на которое я пытаюсь отправить UDP-дейтаграммы с высокой скоростью. Устройство и мой сетевой адаптер поддерживают управление потоком Ethernet, поэтому он может обмениваться данными с моей системой, когда не может принимать больше данных для ограничения скорости потока. Это должно сделать так, чтобы мое приложение могло просто как можно быстрее помещать данные в сокет, и вызовы send() должны блокироваться, когда буфер отправки заполнится, пока не останется место для очереди дейтаграммы.

В некоторой степени это работает как ожидалось; система (через netstat, системный монитор GNOME и т. д.) сообщает, что общий исходящий сетевой трафик в среднем равен ожидаемой скорости. Однако я заметил, что в зависимости от размера запрашиваемого буфера я могу получить или не получить ожидаемое обратное давление.

Во всех моих тестах я установил net.core_wmem_max = 100000000 (100 МБ). Я использую Ubuntu 18.04. Я заметил два режима работы, основанные на размере буфера отправки, который я запрашиваю через setsockopt() с SO_SNDBUF в качестве опции:

  • размер = 10 МБ: В этом случае тест работает правильно; как только буфер отправки сокета достигнет своего предела, send() блокируется, как и ожидалось.

  • размер = 100 МБ: В этом случае я вижу желаемую скорость вывода в сеть через netstat, но если сравнить это с количеством данных, которые я передаю в через send(), ясно, что некоторые данные сбрасываются. Например, у меня может быть скорость передачи данных в сети 640 МБ / с, но если я суммирую возвращаемые значения всех успешных вызовов в send(), я фактически вставляю 800 МБ / с в сокет. Я правильно проверяю на ошибки все мои send() звонки, чтобы убедиться, что ни один из них не сработал.

    Если я использую /proc/net/udp для контроля размера буфера отправки (через столбец tx_queue), это показывает, что буфер отправки только когда-либо достигает примерно 32 МБ, и никогда больше не увеличивается. Это подразумевает, что существует некоторое фундаментальное ограничение на длину очереди отправки, но, поскольку она никогда не достигает сконфигурированной емкости в 100 МБ, send() не блокируется, и вместо этого данные выбрасываются на пол. Справочная страница по send() ссылается на эту возможность:

   ENOBUFS
          The  output queue for a network interface was full.  This generally indicates that the inter‐
          face has stopped sending, but may be caused by transient congestion.   (Normally,  this  does
          not occur in Linux.  Packets are just silently dropped when a device queue overflows.)

Однако я не могу найти какую-либо достоверную информацию о том, какие сценарии могут привести к автоматическому удалению пакетов. Похоже, я не могу доверять объему буфера отправки, который я запрашиваю, так каков максимальный эффективный размер буфера отправки сокета в Linux?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...