Комментарии 14
Поделюсь своим (откровенно говоря небольшим) опытом. Сама библиотека pcap действительно работает более менее одинаково на винде и линуксе, разве что в WinPCap есть дополнительные функции с приставкой _ex, которых в libpcap нету.
Но там есть нюансы (как я понимаю на уровне ниже, в реализации сетевого стека). Например функция для чтения pcap_next_ex на винде разблокируется, после прохождения таймаута, заданного в pcap_open_live. В линуксе это не так, она не разблокируется пока на pcap девайс не придет хотя бы один пакет в текущем окне ожидания (справедливости ради, в документации указано, что таймаут не гарантирует разблокировку, но все равно неожиданно). Много функционала я не писал, но подозреваю, что подобных нюансов ещё куча.
Смотрю на все эти пляски с бубнами и понимаю, что под Linux писать гораздо проще. Можно даже не использовать libpcap, а сразу открывать пакетный сокет (man 7 packet).
Лет 15 назад в моей работе, когда был выбор использовать дальше libpcap, с новой версией которого перестала работать программа после обновления морально устаревшего дистрибутива Linux, мой выбор всё же пал именно на пакетный сокет, т.к. развесистая функциональность pcap была не нужна. Фактически, задача стояла только принимать пакеты одинакового размера и извлекать массивы данных по заданному смещению. Сам формат пакетов не был стандартным протоколом (не только не TCP/UDP, но даже не IP), потому что разработчик железки пожалел ресурсы ПЛИС. Подтверждение получения пакета (ACK) передавалось через другую аппаратуру с гарантированной доставкой.
Для ускорения можно использовать packet mmap, до чего у меня руки не дошли, т.к. всё замечательно работало и без него.
О да, на линуксе с этим обстоит куда приятнее. Вообще на винде тоже есть raw sockets, но они как-то сильно обрезаны (как говорят, для безопасности). Самая проблема там - очень ограниченная возможность устанавливать фильтрацию трафика в ядре. По крайней мере у меня в свое время так и не получилось фильтровать udp broadcast по порту, все в юзерленд сваливалось.
Тут кроме самого функционала, как я отметил, очень важно, что когда все галки сняты - к адаптеру никто не полезет. Их просто не пустит система. Если же поставить буквально одну галку IPv4, то тут же начинают лезть всяческие пакеты от различных протоколов в больших количествах.
В реальной жизни это не так страшно. Но во время отладки, особенно когда на том конце подключён логический анализатор с не самой развитой системой фильтрации (а при работе с ПЛИС Lattice под Open Source средствами разработки особого выбора нет) - все эти пакеты портят жизнь.
При таком же подходе, получил сетевушку в монопольный доступ и отлаживай всё, контролируя каждый пакет в кабеле. Даже ARP пакеты - только вручную. Чтобы проверить поведение отлаживаемой системы при разных сценариях. Собственно, сейчас мне предстоит чинить реализацию этого ARP, так как при требуемой частоте 125 МГц, штатное (по мнению Заказчика) решение с Гитхаба даёт на требуемой ПЛИС параметр FMax = 64 МГц, и критические цепи относятся как раз к ARP. Эту подсистему придётся сильно перепахивать.
Вот когда будет отлажено - тогда уже можно выпускать всё в реальный мир, с кучей левого трафика и автоматической работой с той же ARP.
С пронырливыми сервисами, лезущими куда не попадя, проблема и на Linux есть. Можно резать трафик используя фаервол на сервере или аппаратным фаерволом на openwrt.
С ARP - для своих некоммерческих проектов его можно просто не имплементировать: что Window, что Linux позволяют задать соответствие MAC-IP консольной магией "arp -s ip mac".
На Linux поинтереснее. Есть такое понятие как Gratuitous ARP - когда устройство при включении или периодически рассылает всем свой ARP-ответ, хотя его никто не спрашивал. Естественно, на этом можно построить атаку, перехватив чужой IP на свой MAC. Почему, собственно, gratuitous ARP не используется. Однако, в настройках sysctl для ядра Linux можно разрешить gratuitous ARP для своих интерфейсов.
Впрочем, ARP очень простой протокол, не понимаю как для него сфитировалось 64МГц Fmax. Вот, для DHCP я бы однозначно сказал "верю".
Пока только могу сказать, что там у автора идёт две ОЗУшины ARP кэша, потом - куча логики и только потом результат защёлкивается. Кое-что уже удалось конвейеризировать, уже FMax не 64, а 83 МГц. Завтра продолжим разбираться, что можно сделать. На данный момент, я не понимаю, как имеющаяся ветка вносит нынешнюю задержку. Возможно, это вообще транспортная задержка, возникающая при разводке.
Впрочем, ARP очень простой протокол, не понимаю как для него сфитировалось 64МГц Fmax. Вот, для DHCP я бы однозначно сказал "верю".
Всё, разогнал. Теперь могу вкратце сказать, кто был виноват в том конкретном случае, помимо задержек от ОЗУ. Многобитные функции. 48 битное сравнение MAC, 32 битное сравнение IP с текущим, а также с FFFFFFFF для бродкаста. А ещё и с наложением маски подсети... Всё пришлось конвейеризировать.
Штатный опенсорсный проект собирает 48 и 32 битное значение MAC и IP соответственно, потом - сравнивает. Чтобы разогнать - по мере прихода байтов сравниваем. Потом - просто операцию "И" над шестью или четырьмя битами результатов побайтного сравнения выполняем.
Но это ещё не всё. У ARP таймауты есть. 2 секунды для ретрейнов и 30 для последней попытки. Они задавались в тиках 125 мегагерцового таймера. Итого у автора использовался 36 битный счётчик. Пришлось разбить его на три. Один генерит мегагерцовые тики, второй - килогерцовые, третий уже в миллисекундах таймауты отсчитывает. При такой разрядности каждого счётчика, быстродействие выходит в приемлемый диапазон
Ну, и прочие подобные уменьшения разрядности. Латтис и Yosys/NextPNR иначе не позволяют официальное решение найти. При этом проект с плохим FMax по факту работал. Но без гарантий.
64MHz*2=128MHz, т.е. даже вполовину уменьшив сложность комбинаторной функции в боттлнеке, можно уместиться в 125МГц. Что вы успешно и проделали.
Хорошая работа, поздравляю!
Опенсорсную реализацию ARP, скорее всего, делали на Altera или Xilinx, там достаточно просто выбрать чип с соответствующим speed grade. Не знаю как обстоит дело со speed grade в Lattice, всё-таки их традиционно считают более энергоэффективными и дешевыми, чем производительными. А я больше работаю с Altera.
В отчете Fmax всегда пессимистичный. Реальный Fmax чаще выше, даже при минимальном охлаждении чипа. Ну и среднее качество чипов FPGA выше минимума. Потому в штучных экземплярах еще можно рассчитывать на удачу, а в массовых образцах нет.
Но это все довольно банальные и очевидные факторы.
В общем, можно было бы рассмотреть всё это дело в виде нескольких статей. Но будет ли это интересно?
Мне было бы интересно.
Можно поставить Nmap, там есть библиотека для сырых (raw) пакетов, а писать скрипты придётся на Lua (язык простой и приятный, Wireshark его тоже поддерживает).
Мне его пришлось поставить, чтобы запускать ncat, так как исходный проект для ПЛИС рекомендует вести тестирование с помощью netcat. Гугль сказал, чтобы я под Windows использовал ncat и не мучился.
Я точно не изучал, как там всё устроено, но при установке NMap, он предлагает поставить всё тот же NPap. Так что не удивлюсь, если он через этот же драйвер всё и реализует. Но и не поручусь.
Конечно, через него же, но там удобные библиотеки для разных сетевых протоколов (для сырых пакетов, опять же, обёртка WinPcap, но гораздо проще писать на Lua, чем на С++).
В 2006-м внедряли мы в систему для газоанализатора поддержку LUA. И потом переписывали плюсовые алгоритмы, сделанные на первом этапе, на этот скрипт. Обработка ошибок стала занимать 2/3 кода и загромождать пространство так, что основной алгоритм стало не видно. Может, с тех пор что-то и поменялось, но мой опыт говорит, что вряд ли "гораздо проще на нём писать". Скорее, кто к чему привык.
Работаем с сетевыми адаптерами через Pcap-драйверы