Фрагментация и размер пакета, используя tcpdump

Я пытаюсь понять концепцию фрагментации:

У меня есть две виртуальные машины с публичным IP-адресом, подключенным к коммутатору.

tracepath показывает, что пакет не проходит через шлюз

из vm1: Попытка отправить icmp с 65507 байтами в vm2.

ping -M want -s 65507 vm2 

но в выводе tcpdump на vm2: его показ

tcpdump -evvv icmp

12:48:44.635551 42:43:30:b4:89:0c (oui Unknown) > b6:7a:6b:7d:54:32 (oui Unknown), ethertype IPv4 (0x0800), length 1514: (tos 0x0, ttl 64, id 10843, offset 1480, flags [+], proto ICMP (1), length 1500)
VM1 > VM2: icmp
12:48:44.635568 42:43:30:b4:89:0c (oui Unknown) > b6:7a:6b:7d:54:32 (oui Unknown), ethertype IPv4 (0x0800), length 1514: (tos 0x0, ttl 64, id 10843, offset 2960, flags [+], proto ICMP (1), length 1500)
VM1 > Vm2: icmp
12:48:44.635572 42:43:30:b4:89:0c (oui Unknown) > b6:7a:6b:7d:54:32 (oui Unknown), ethertype IPv4 (0x0800), length 1514: (tos 0x0, ttl 64, id 10843, offset 4440, flags [+], proto ICMP (1), length 1500)
VM1>VM2 icmp
12:48:44.635575 42:43:30:b4:89:0c (oui Unknown) > b6:7a:6b:7d:54:32 (oui Unknown), ethertype IPv4 (0x0800), length 1514: (tos 0x0, ttl 64, id 10843, offset 5920, flags [+], proto ICMP (1), length 1500)
VM1>VM2: icmp
12:48:44.635578 42:43:30:b4:89:0c (oui Unknown) > b6:7a:6b:7d:54:32 (oui Unknown), ethertype IPv4 (0x0800), length 1514: (tos 0x0, ttl 64, id 10843, offset 7400, flags [+], proto ICMP (1), length 1500)
**Vm1 > VM2**: icmp
12:48:44.635581 42:43:30:b4:89:0c (oui Unknown) > b6:7a:6b:7d:54:32 (oui Unknown), ethertype IPv4 (0x0800), length 1514: (tos 0x0, ttl 64, id 10843, offset 8880, flags [+], proto ICMP (1), length 1500)

Это повторяется 31 раз, пока не будет получено полностью. полная вставка: http://pastebin.com/cnQhn8dK

Так почему же получается, что общее количество полученных данных составляет 1500*31=46500 байт, а то, что случилось с 65507-46500=19007 байт.

Может кто-нибудь, пожалуйста, уточнить это.

2 ответа

Решение

Да, используя tcpdump с опцией -s, результат теперь правильный. В качестве вашего результата мы считаем 45 пакетов. 44 пакета с 1500 байтами, 1 пакет 415 байтов.

44 * 1500 + 415 = 66415

66415 - 65507 = 908

908/45 = 20 плюс 8

Как видите, к каждому пакету добавляется 20 байтов для заголовка ip + 8 байтов для заголовка icmp для первого пакета.

Просто чтобы добавить ответ Gnouc.

Вы отправляете 65507 байты данных. Это не включает заголовки ICMP, которые составляют 8 байтов.

Самый распространенный размер MTU 1500, Этот размер соответствует размеру уровня 3, поэтому вы видите ethertype IPv4 (0x0800), length 1514: Это означает, что общий размер кадра на самом деле составляет 1514 байт. Эти 14 байтов составляют заголовок Ethernet. 12 байтов на mac-адрес + 2 для типа.

Минимальным и очень распространенным размером для заголовка IP является его минимальный размер 20 байтов (максимальный - 60 байтов).

Итак, мы имеем

1514 bytes - Ethernet header = 1500 bytes
1500 - IP header = 1480 bytes
1480 - ICMP header = 1472 bytes

Вы можете отправить максимум 1472 байта без фрагментации.

НО способ, которым IP фрагментирует пакеты, не требует отправки заголовка для каждого пакета, а только для первого пакета.

С фрагментацией максимальное количество байтов, которое вы можете отправить с MTU 1500, составляет 1480 байтов.

Мы знаем общий размер ваших данных и максимальный размер, который вы можете отправить.

Так что это займет как минимум 65507 / 1480 ~= 44.2 packets, Т.е. 44 пакета по 1514, а затем окончательный пакет размером менее половины.

Что случилось с остальными пакетами?

Но почему 31 пакет? Ну, это все в размере буфера, который вы захватываете. В конце вашего tcpdump вы должны увидеть

31 packets captured 
57 packets received by filter
14 packets dropped by kernel

Если вы добавите захваченные пакеты + пакеты, отброшенные ядром, вы получите правильный ответ, и вот что -s это изменяет длину привязки.

Из руководства по tcpdump

-s Snarf Snaplen байтов данных из каждого пакета, а не по умолчанию 65535 байтов. Пакеты, усеченные из-за ограниченного снимка, указываются в выходных данных ``[|proto]'', где proto - это имя уровня протокола, на котором произошло усечение. Обратите внимание, что создание больших моментальных снимков увеличивает время обработки пакетов и фактически уменьшает объем буферизации пакетов. Это может привести к потере пакетов. Вы должны ограничить snaplen наименьшим числом, которое будет захватывать интересующую вас информацию о протоколе. При установке snaplen в 0 устанавливается значение по умолчанию 65535 для обратной совместимости с последними более старыми версиями tcpdump.

Почему ядро ​​отбросило пакеты в первую очередь?

Снова из справочной страницы tcpdump

пакеты, отброшенные ядром (это количество пакетов, которые были отброшены из-за недостатка места в буфере механизмом захвата пакетов в ОС, в которой работает tcpdump, если ОС сообщает эту информацию приложениям; если нет, то будет сообщено как 0).

Другие вопросы по тегам