1、 IP分片
任何IP层接收到一份要发送的IP数据报时,它要判断向本地哪个接口发送数据,并查询该接口的MTU。IP把MTU与数据报的长度进行比较,如果需要则进行分片。分片可以发生在原始发送端主机上,也可以发送在中间路由器上。IP数据报分片后,只有到达目的主机后才进行重装。
IP首部与分片有关的字段:
(1)对于每份IP数据报来说,都有一个标识字段,该值在分片时被复制到每个片中。
(2)标志字段用其中一个bit表示
“
更多的片
”
,除最后一片外,其他每个分片都要设置为1。
(3)片偏移字段指的是该片偏移原始数据报开始处的位置。
(4)数据报被分片后,每个片的总长度要改为该片的长度值。
(5)标志字段中有一个bit表示
“
不分片
”
,如果该位1,IP将不对数据报进行分片。
IP报即使丢失一片数据报也要重传整个数据报。为什么呢?因为IP层没有超时重传的机制,必须由更高层负责超时重传。
总结:
三个字段
标识字段(ip_id):标识特定数据报的分片
标志字段(ip_off的3个高位比特)
偏移字段(ip_off的13个低位比特)
几个区别
普通IP包:ip_off、MF 为 0
最后一个分片包: ip_off > 0、MF 为 0
其它分片包:ip_off ≥ 0、MF 为 1
2、 数据结构设计
链表_FRAG
结点结构ipfrag,保存一个分片
作用:保存同属于一个IP包的所有分片数据
链表中各结点按ip_off由小到大排序
链表_IPQ
结点结构ipq,作为_FRAG的头结点,描述属于同一个IP包的所有分片数据的共同特征
作用:将目的地址相同的分片组织到一起
链表_HOSTFRAG
结点结构hostfrags,作为_IPQ的头结点
作用:将目的地址不同但hash值相同的分片数据组织到地起
hash表fragtable
实现:struct hostfrags **fragtable
作用: fragtable[index]为_HOSTFRAG的头结点
hash表及三个链表之间的关系图
3、 分片重组流程
4、 代码及相关注释
5、 几个细节
5.1 Step 14:在_FRAG链表中插入的位置
代码:
if (next->offset >= offset)
break;
当prev和next结点都存在时满足的条件
offset
∊
(
prev->offset
,
next->offset
]
隐含意思:当前分片与prev之前的结点无重叠,与prev可能有重叠
5.2 step 15:和prev有重叠,调整当前分片
调整前图