IP分片使用UDP很容易导致IP分片,下面就详细说一下IP分片的过程。
看如下的IP首部格式(图4-1):
图4-1
其中中间的5~8个字节是与分片最相关的,下面分别来介绍。 首先介绍16位的标识符字段,对于发送端发送的每份IP数据报来说,标识符是唯一的值,这个值在数据报分片时被复制到每个片中,IP数据报到达目的地重新组装就是依靠这个标识符字段来识别各个分片是否是一个数据报,来看一下下面的场景: 一个用UDP发送数据报的应用程序,它把数据报分成4个数据报片。假定第1片和第2片到达目的端,而第3片和第4片丢失了。应用程序在10秒后超时重发该UDP数据报,分片方式与前一次相同,当重发的第3片和第4片到达目的端时,如果原先收到的第1片和第2片还没有被丢弃,但这4片是不能组成一个完整的数据包的,尽管它们的内容合起来是原先的完整数据包的数据,原因就是重发的第3片和第4片分组与原先的第1片和第2片标识符不同。
然后是3位标志字段,参考RFC文档: 标志字段含义如下:
Bit 0: reserved, must be zero /* 保留位,必须是0 */
Bit 1: (DF) 0 = May Fragment, 1 = Don't Fragment. /* 0=可以分片, 1=不分片,
很好理解,当=1就不可以分片,那么host或者router当IP报文大于MTU时,就不会分片,而直接丢弃。 */
Bit 2: (MF) 0 = Last Fragment, 1 = More Fragments. /* 1=最后的分片,1 = 更多分片 */
最后的片偏移字段指的是分片偏移原始数据报开始处的位置。另外数据报分片后,每个片的总长度值(IP首部3~4字节)要改为该片的长度值。 看一个实际分片的例子,假设网络的MTU是1500B,用UDP发送数据包,这样实际每个IP数据包实际可承载的数据长度是1472B(IP首部:20B,UDP首部:8B),应用层分别发送长度为1471B,1472B,1473B,1474B的数据包,看一下tcpdump的输出:
图4-2
打红框的就是具体的分片情况,“26304”就是标识符,“:”与“@”号之间的1480是除IP首部外的片长,后面的“+”号表明MF标志已设置。仔细观察第1片与第2片的区别发现第2片没有打出协议号,也没有打出端口号,协议号在IP首部中有,由于UDP首部信息是作为数据形式存放在IP数据包中的,所以分片时它只存在于第1片分片中,而后面的所有分片都没有该信息,因此也无法输出端口号。 为了更形象一些,看一下该数据包分片的图解:
图4-3
另外还有一点说明,在分片时,除最后一片外,其他每一片的数据部分(除IP首部外的其余部分)必须是8字节的整数倍。
为了彻底了解这个概念,再看一个更为复杂的例子,有一份8192B的UDP数据报,经以太网发出(MTU 1500B),需要分成多少个数据报片如?果这些数据报片途中需要经过一条MTU为552的SLIP链路,又会分成多少个数据报片?下面列出其分片的偏移与长度:
UDP数据报总长度:8192B+8B = 8200B,经过以太网每个数据帧最大值是1480B(1500B-20B)
1. 1480@0+
2. 1480@1480+
3. 1480@2960+
4. 1480@4440+
5. 1480@5920+
6. 800@7400
再经过SLIP链路,则每个1480B的帧,又再继续分:
(1) 528@0+
(2) 528@528+
(3) 424@1056
最后一个800B的数据报拆分如下:
(1) 528@0+
(2) 272@528
之所以拆分成528B,而不是532B(552B - 20B),就是要满足每个数据包是8B的整数倍
当设置了DF标志,而该段网络的路径MTU又小于数据包的大小时,会产生ICMP不可达差错,其报文格式如下:
其中下一站网络的MTU可以是0,这样就需要用路径MTU发现机制来确定正确的MTU值。还是看一个具体的例子,有如下的网络:
solaris主机向bsdi主机发送600B长度的数据报文,在bsdi主机上抓包得到如下的输出:
solaris主机是不可能收到应答报文的,尽管bsdi已经发出响应,因为它无法通过sun主机的链路(MTU = 552),sun主机已向bsdi主机回复了需分片的报文。
关于分片还有最后一个问题,就是IP首部中的选项如何处理,查阅RFC791,最后的结论是,严格和宽松的源站路由信息被复制于每一个IP数据报中,而记录路由,时间戳等信息只出现在分片的第一个数据包中。
阅读(2915) | 评论(0) | 转发(0) |