Я пытаюсь постоянно захватывать трафик примерно 20 Мбит / с с помощью tshark. Если я захватываю пакеты с помощью tshark в CentOS 6.5, я получаю от 4% до 66% пакетов. Если я сделаю то же самое в CentOS 7, он никогда не сообщит об отброшенных пакетах. Я действительно пытался заставить его отбрасывать пакеты, делая сумасшедшие вещи, например, выводя большие объемы трафика в xml. Насколько я могу судить, это не отбрасывание пакетов. Мой вопрос: есть ли в CentOS 7 какая-то функция, которая делает невозможным сброс пакетов? Или это сбрасывает пакеты и не говорит мне?
В качестве примера я выполняю такие команды:
tshark -i ens224 -c 100000 -w /tmp/delme.pcap
tshark -i ens224 -c 100000 -T pdml > /tmp/delme.pcap
Для первой команды CentOS 6 сообщает о 4% отброшенных пакетов, CentOS 7 - об отсутствии. Для второй команды CentOS сообщает о 66% отброшенных пакетов, но CentOS 7 не сообщает ни об одном.
Обратите внимание, что обе машины работают под управлением tshark 1.12.7, скомпилированного из исходных текстов.
Мой вопрос: есть ли в CentOS 7 какая-то функция, которая делает невозможным сброс пакетов?
Нет, но у него есть две функции, которые значительно снижают вероятность отбрасывания пакетов:
TPACKET_V3
для PF_PACKET
Розетки;TPACKET_V3
для PF_PACKET
Розетки.Libpcap использует PF_PACKET
сокеты для захвата в Linux 2.2 и новее (в Linux 1.x и 2.0 не было PF_PACKET
Розетки). Оригинал PF_PACKET
сокеты доставляли пакеты, используя обычные механизмы сокетов, то есть libpcap (или любая другая программа, перехватывающая трафик) должна была сделать один recvmsg()
вызывать этот сокет для каждого пакета. Это было дороже, чем, например, способ работы механизма BPF в * BSD и OS X, где множественный пакеты доставляются при каждом чтении, поэтому при высоком уровне трафика выполняется меньше системных вызовов.
Linux 2.4, я думаю, представил механизм "турбо-пакетов" (это то, что означает "T" в "TPACKET" - "турбо"), который предоставляет буфер с отображением памяти, совместно используемый ядром и пользовательской средой. При этом при доставке пакетов требуется меньше копий, а цикл чтения пакетов в пользовательском пространстве может обрабатывать несколько пакетов за один пробуждение (чтобы дождаться прибытия пакетов, пользовательское пространство делает select()
, poll()
, или epoll()
вызов). К сожалению, этот механизм предоставил кольцо буферов фиксированного размера, и libpcap должен выбрать размер, достаточно большой для максимально возможного пакета. Более ранние версии выбирали пакеты того же размера, что и предоставленная длина снимка, то есть, вероятно, 64 КБ-1 для версии Wireshark, которую вы используете, т.е. вполне расточительно - в буфере не хватает слотов для пакетов, чтобы избежать переполнения. Некоторые более поздние версии пытались использовать MTU для определения размера слота, но это не всегда могло быть сделано, и даже если это возможно, это может быть расточительным.
В какой-то версии 3.x (3.6?) TPACKET_V3
, был добавлен существенно другой механизм турбопакета. Это больше похоже на BPF, поскольку буфер не содержит один пакет, в него может быть упаковано несколько пакетов. Это позволяет намного лучше использовать память для захвата и отбрасывать намного меньше пакетов.