Использование ASIO для захвата большого количества пакетов UDP

Я использую библиотеку asio (не бустер версия) для захвата входящих пакетов UDP через адаптер Ethernet 10 ГБ.
150 тыс. Пакетов в секунду — это хорошо, но я начинаю получать пропущенные пакеты, когда добираюсь до более высоких скоростей, таких как 300 тыс. Пакетов в секунду.

Я почти уверен, что узким местом является отдельная передача DMA на 300 тыс. С сетевой карты на хост-систему. Передачи не большие, всего 1400 байт на передачу, поэтому проблема с пропускной способностью не возникает.

В идеале я хотел бы механизм объединения данных из нескольких пакетов в одну передачу DMA на хост. В настоящее время я использую asio :: receive для синхронной передачи, которая дает лучшую производительность, чем async_receive.

Я пытался использовать команду получения с большим буфером или массив из нескольких буферов, но я всегда получаю одно чтение 1400 байт.

Есть ли способ обойти это?

В идеале я хотел бы прочитать несколько кратных из 1400 байтов за раз, при условии, что это не займет слишком много времени для заполнения всего.
то есть. подождите до 4 мс, а затем верните 4 х 1400 байт или просто вернитесь через 4 мс, если доступно много байт …

Я не контролирую всю сеть, поэтому я не могу форсировать гигантские кадры 🙁

Ура,

1

Решение

может быть, вы можете попробовать обходной путь с tcpdump, используя библиотеку libcap http://www.tcpdump.org/ и фильтрация для получения пакетов UDP

1

Другие решения

Я бы удалил asio слой и идти прямо к металлу.

Если вы используете Linux, вы должны использовать recvmmsg (2) скорее, чем recvmsg() или же recvfrom(), поскольку это по крайней мере допускает возможность одновременной передачи нескольких сообщений в ядре, чего нет у других.

Если вы не можете сделать ни одну из этих вещей, вам нужно как минимум смягчить свои ожидания. recvfrom() а также recvmsg() и все, что лежит над ними в asio никогда не доставит более одной дейтаграммы UDP одновременно. Вам нужно:

  • максимально ускорить ваш цикл приема, устраняя все возможные издержки, особенно динамическое выделение памяти и ввод / вывод для других сокетов или файлов.
  • убедитесь, что приемный буфер сокета максимально большой, по крайней мере, мегабайт, через setsockopt()/SO_RCVBUFSIZи не думайте, что вы установили то, что получили: верните через getsockopt() чтобы увидеть, ограничивает ли вас платформа каким-то образом.
2

По вопросам рекламы [email protected]