IP分片
ip的分片操作主要在ip_output函数中完成,其中ip头的ip_off字段代表了关于分片的各种信息,其结构如下图所示:
------------------------------------
| 0 | DF | MF | fragment offset |
------------------------------------
1 1 1 13
DF: 标志该IP包是否可以被分片
MF:标志是否是最后一个数据包
fragment offset: 该数据包的数据偏移,单位为8bytes
首先进行ip_len的判定,如果其大于ifp->if_mtu,则需要分片;然后检测DF标志位,看是否支持分片,如果不支持则丢弃该包,并且返回。同时,计算len = (ifp->mtu - hlen)& ~7 来判定剩余的长度,如果len<8,则返回。因为,ip_off的单位是8bytes,所以剩余的字节长度不能小于8bytes。
IP的重组
ip的重组操作主要在ipintr函数中完成,最核心的函数为ip_reass。
在重组操作时,主要会涉及多个结构体,分别是ipq,ipasfrag。其中ipq是一个头指针,所连接的链表为每个ip帧的头指针,其内保存有可以标志出一个独特帧的所有信息,如ip_p,ip_id,ip_src,ip_dst。每个ipq都包含有next和prev指针,以组成一个双向链表。ipq中的ipq_next和ipq_prev指针指向ipasfrag结构体,代表一个IP包的分片。
在ipq结构体中也有一个TTL成员,它指示等待同一帧数据到达的时间,在系统每500ms执行一次的ip_slowo函数中,会递减TTL成员,如果它达到了0,就要删除它所指向的所有数据包,并释放相应的资源,同时会返回一个ICMP的超时数据包。
在传输时,要尽量减少分片。在TCP层有确保减少分片的机制,而UDP却没有,所以需要应用层自己要做相应的保证。