碎片和数据包大小,使用tcpdump

我想了解碎片的概念:

我有两个公共IP连接到交换机的虚拟机。

tracepath显示数据包不通过网关

从vm1:尝试发送65507字节的icmp到vm2。

ping -M want -s 65507 vm2 

但在vm2上的tcpdump输出:显示

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字节

有人可以澄清这一点。

是的,使用tcpdump和-s选项,结果是正确的。 作为你的结果,我们计数45包。 44个1500字节的数据包,1个数据包415字节。

44 * 1500 + 415 = 66415

66415 – 65507 = 908

908/45 = 20加8

你可以看到,每个数据包为ip头+ 20字节添加第一个数据包的8字节icmp头。

只要加上Gnouc的答案。

您正在发送65507个字节的数据。 这不包括8个字节的ICMP头。

最常见的MTU大小是1500 。 这个大小占第三层的大小,这就是为什么你看到ethertype IPv4 (0x0800), length 1514:这意味着总的帧大小实际上是1514字节。 这14个字节占了以太网报头。 每个mac地址12个字节+ 2个types。

IP头的最小和非常常见的大小是其最小大小为20字节(最大为60字节)。

所以我们有

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

您最多可以发送1472个字节而不会分段。

但是IP分割数据包的方式并不需要为每个数据包发送标题,而只是为第一个数据包发送标题。

如果使用分段,MTU为1500的最大字节数是1480字节。

我们知道您的数据的总大小以及您可以发送的最大数量。

所以至less需要65507 / 1480 ~= 44.2 packets 。 即44个1514包,然后是不到一半大小的最后一个包。

剩下的包发生了什么事?

但是,为什么31包? 那么这一切都在你正在捕获的缓冲区大小。 在你的tcpdump结尾你应该看到

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

如果添加捕获的数据包+内核丢弃的数据包,您将得到正确的答案,这就是它改变了快照长度。

从tcpdump手册

-s Snarf snaplen每个数据包的数据字节数,而不是默认的65535字节。 在“`| proto]”的输出中指示由于快照有限而截断的数据包,其中proto是发生截断的协议级别的名称。 请注意,采用较大的快照既增加了处理数据包所需的时间,也有效地减less了数据包缓冲的数量。 这可能会导致数据包丢失。 您应该将snaplen限制为捕获您感兴趣的协议信息的最小数量。 将snaplen设置为0会将其设置为缺省值65535 ,以便与最近较早版本的tcpdump向后兼容。

为什么内核首先丢弃数据包?

再次从tcpdump手册页

数据包由内核丢弃(如果操作系统将该信息报告给应用程序,则这是由于运行tcpdump的操作系统中的数据包捕获机制,由于缺less缓冲区空间而丢弃的数据包数;如果不是,则将被报告为0)。