- 原理介绍
-
- 为一个数据包片再次分片
为数据包分片和为数据包片再次分片之间的细微差别就在于网关处理MF比特的不同。但一个网关为原来为分片的数据包分片时,除了末尾的数据包片,它将其余所有分片上的MF比特都置为一,最后一片为0。然而,当网关为一个非末尾的数据包片再次分片时,它会把生成的所有子分片中的MF比特全部设置为1,因为所有这些子分片都不可能是整个数据包的末尾的数据包片。
对于分片,需要拷贝IP首部和选项,以及数据。而选项的拷贝要注意:根据协议标准,某些选项只应当出现在的一个数据包片中,而其他一些则必须出现在所有的数据包中。
-
- 数据包重组
-
-
- 数据结构
-
为了使数据包的重组效率更高,用于保存数据包的数据结构必须能够做到:
- 为构成某一个特定数据包的一组数据包片快速定位;
- 在一组数据包片中快速插入新的数据包片;
- 有效地判断一个完整的数据包是否已经全部抵达;
- 具有数据包片超时机制(ip_expire),并且,如果在重组完成之前定时器溢出,则删除数据包片。
-
-
- 互斥操作
-
重组程序代码使用了一个互斥信号量。Ipfrag_lock
-
-
- 在链表中加入一个数据包片
-
查找方式:链表的线性查找
-
-
- 溢出时的丢弃
-
分片列表空间以全满的情况下:丢弃对应的数据包的所有分片。Ip_evictor
-
- 测试是否组成一个完整的数据包ip_frag_queue
判断IP_MF位是否为0!
-
-
- 将数据包片组装成完整的数据包LAST_IN,ip_frag_reasm
-
-
- 数据包片链表的维护管理
为了使丢失数据包片的数据包不再浪费存储资源 ,并防止因为标示符字段的重新使用而给IP带来混乱,但已经不可能再受到剩余数据包片时,IP必须定期检查数据包片列表。
Ipq_unlink
Ipq_put
Ipq_kill
Ipqhashfn
- Linux下的实现
-
- IP分片
如何提高分片处理的效率
-
-
- ip_fragment(非UDP使用)
-
-
-
-
- 典型调用者
-
-
ip_sendà ip_fragment(skb, ip_finish_output);一般从转发来
ip_queue_xmit2à ip_fragment(skb, skb->dst->output)一般从TCP来
因为IP报太大而将其分片以适合于一个帧的传输。
-
-
-
- 处理过程
-
-
获取外出设备(由skb决定)
dev = rt->u.dst.dev; 出口路由设备
!!!skb->dst=rt=rt->u.dstàdst_entry
取IP包头
raw = skb->nh.raw;
iph = (struct iphdr*)raw; 取IP头
设定开始值
hlen=IP头长
left = ntohs(iph->tot_len) - hlen; 包总长度减去IP头长度――需要分片的数据长度
mtu = rt->u.dst.pmtu - hlen; 物理MTU减去IP头长度――除去IP头的分片长度
ptr = raw + hlen; 取数据区指针
将数据包分片
- 分片算法很简单,但由于对sk_buff结构和链的操作时的实现非常复杂。
- 如果DF比特禁止分片,则ip_output丢弃分组并返回错误消息。
- 如果该数据包是在本地生成的,则传输层协议把该错误传回该进程
- 如果分组是被转发的,则