4.2.3 Fragmentation and Reassembly
IP的MTU是65536bytes;而Ethernet的MTU为1518bytes,所以需要分片,而router可能会对packet再次分片。
注意:分片的payload部分一定是8bytes的倍数。
属于同一个packet的所有分片的identifier field(位于IP header)的值相同,在flags field中的more fragments bit(位于IP header)设置为0表示是最后一个分片。fragmentation offset field(位于IP header)表示了该分片在IP packet中的位置,以8bytes为单位。要组装分片就是要用到以上3中信息。
分片的实现
TCPlayer调用ip_queue_ximit()将packet发送到IP layer,routing完成之后,会调用ip_queue_xmit2(),它检查packet的长度是否超过了link layer的
MTU,如果超过了,就调用ip_fragment(),它负责分片,分片时需要让每个分片的payload部分是8bytes的倍数。这些函数位于src/net/ipv4/ip_output.c。
组包的实现
大部分的函数位于src/net/ipv4/ip_fragment.c,当数据包来自于link layer时,ip_rcv()被调用,它调用ip_route_input()来做routing,routing后发现该packet需要提交给TCPlayer,ip_local_deliver()被调用,如果more bit和fragmentation offset不为0,则ip_defrag()被调用。
每个packet的分片被存放在一个叫做ipq_hash的hash table中,该ipq_hash是一个iqp structure
的数组,而hash用的hash function叫做ipqhashfn(),ipqhashfn()的参数:identifier, source IP address, destination IP address和上层协议的服务类型。ip_defrag()先调用ip_find(),ip_find()调用ipqhashfn()来定位ipq structure,如果定位失败,ipq_frag_create() 会产生一个新的ipq queue,ipq_frag_intern()会将该queue插入到hash table中。ip_defrag() 调用 ip_frag_queue() 来将分片放到queue中。如果所有的分片都已收到,则ip_frag_reasm()被调用,用来组装数据包。
[此为原创,转载请标明出处,谢谢!]