您的位置:首页 > 理论基础 > 数据结构算法

libnids-1.21 中 IP 分片重组分析 之数据结构与处理流程

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



[align=left][/align]
[align=left]3、 分片重组流程[/align]



[align=left][/align]



[align=left]4、 代码及相关注释[/align]

http://blog.csdn.net/sandrain_zeq/archive/2007/06/13/1651258.aspx

[align=left] [/align]
[align=left]5、 几个细节[/align]
[align=left] [/align]
[align=left]5.1 Step 14:在_FRAG链表中插入的位置[/align]
[align=left]代码:[/align]
[align=left]if (next->offset >= offset)[/align]
[align=left] break;[/align]
[align=left]当prev和next结点都存在时满足的条件[/align]
[align=left]offset ( prev->offsetnext->offset[/align]
[align=left]隐含意思:当前分片与prev之前的结点无重叠,与prev可能有重叠[/align]
[align=left][/align]
[align=left][/align]
[align=left][/align]
[align=left]5.2 step 15:和prev有重叠,调整当前分片[/align]
[align=left] [/align]
[align=left]调整前图[/align]



[align=left]调整后图[/align]



[align=left]step 15:和prev有重叠,调整当前分片后没有判断当前数据的长度,之后会创建一个无用结点![/align]



[align=left][/align]



[align=left]2.6.17内核已处理![/align]
[align=left]////////////////////////////////////////////////////////////////////////[/align]
[align=center]~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetextsearch ] ~ [ file search ] ~ [/align]
[align=center]Linux Cross Reference
Linux-2.6.17/net/ipv4/ip_fragment.c
[/align]
[align=center]Version: ~ [ 2.6.16 ] ~ [ 2.6.17 ] ~
Architecture: ~ [ ia64 ] ~ [ i386 ] ~ [ arm ] ~ [ ppc ] ~ [ sparc64 ] ~ [/align]
[align=left] 1 /*[/align]
[align=left] 2 * INET An implementation of the TCP/IP protocol suite for the LINUX[/align]
[align=left] 3 * operating system. INET is implemented using the BSD Socket[/align]
[align=left] 4 * interface as the means of communication with the user level.[/align]
[align=left] 5 *[/align]
[align=left] 6 * The IP fragmentation functionality.[/align]
[align=left] 7 * [/align]
[align=left] 8 * Version: $Id: ip_fragment.c,v 1.59 2002/01/12 07:54:56 davem Exp $[/align]
[align=left] 9 *[/align]
[align=left] 10 * Authors: Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG>[/align]
[align=left] 11 * Alan Cox <Alan.Cox@linux.org>[/align]
[align=left] 12 *[/align]
[align=left] 13 * Fixes:[/align]
[align=left] 14 * Alan Cox : Split from ip.c , see ip_input.c for history.[/align]
[align=left] 15 * David S. Miller : Begin massive cleanup...[/align]
[align=left] 16 * Andi Kleen : Add sysctls.[/align]
[align=left] 17 * xxxx : Overlapfrag bug.[/align]
[align=left] 18 * Ultima : ip_expire() kernel panic.[/align]
[align=left] 19 * Bill Hawes : Frag accounting and evictor fixes.[/align]
[align=left] 20 * John McDonald : 0 length frag bug.[/align]
[align=left] 21 * Alexey Kuznetsov: SMP races, threading, cleanup.[/align]
[align=left] 22 * Patrick McHardy : LRU queue of frag heads for evictor.[/align]
[align=left] 23 */[/align]
[align=left] 24 [/align]
[align=left]465 [/align]
[align=left]466 /* Add new segment to existing queue. */[/align]
[align=left]467 static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)[/align]
[align=left]468 {[/align]
[align=left]469 struct sk_buff *prev, *next;[/align]
[align=left]470 int flags, offset;[/align]
[align=left]........................[/align]
[align=left]........................[/align]
[align=left]........................[/align]
[align=left]........................[/align]
[align=left]522 /* Find out which fragments are in front and at the back of us[/align]
[align=left]523 * in the chain of fragments so far. We must know where to put[/align]
[align=left]524 * this fragment, right?[/align]
[align=left]525 */[/align]
[align=left]526 prev = NULL;[/align]
[align=left]527 for(next = qp->fragments; next != NULL; next = next->next) {[/align]
[align=left]528 if (FRAG_CB(next)->offset >= offset)[/align]
[align=left]529 break; /* bingo! */[/align]
[align=left]530 prev = next;[/align]
[align=left]531 }[/align]
[align=left]532 [/align]
[align=left]533 /* We found where to put this one. Check for overlap with[/align]
[align=left]534 * preceding fragment, and, if needed, align things so that[/align]
[align=left]535 * any overlaps are eliminated.[/align]
[align=left]536 */[/align]
[align=left]537 if (prev) {[/align]
[align=left]538 int i = (FRAG_CB(prev)->offset + prev->len) - offset;[/align]
[align=left]539 [/align]
[align=left]540 if (i > 0) {[/align]
[align=left]541 offset += i;[/align]
[align=left]542 if (end <= offset)[/align]
[align=left]543 goto err;[/align]
[align=left]544 if (!pskb_pull(skb, i))[/align]
[align=left]545 goto err;[/align]
[align=left]546 if (skb->ip_summed != CHECKSUM_UNNECESSARY)[/align]
[align=left]547 skb->ip_summed = CHECKSUM_NONE;[/align]
[align=left]548 }[/align]
[align=left]549 }[/align]
[align=left]550 [/align]
[align=left]551 while (next && FRAG_CB(next)->offset < end) {[/align]
[align=left]552 int i = end - FRAG_CB(next)->offset; /* overlap is 'i' bytes */[/align]
[align=left]553 [/align]
[align=left]554 if (i < next->len) {[/align]
[align=left]555 /* Eat head of the next overlapped fragment[/align]
[align=left]556 * and leave the loop. The next ones cannot overlap.[/align]
[align=left]557 */[/align]
[align=left]558 if (!pskb_pull(next, i))[/align]
[align=left]559 goto err;[/align]
[align=left]560 FRAG_CB(next)->offset += i;[/align]
[align=left]561 qp->meat -= i;[/align]
[align=left]........................[/align]
[align=left]........................[/align]
[align=left]........................[/align]
[align=left]........................[/align]
[align=left] [/align]
[align=center] [/align]
[align=center] ~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~[/align]
[align=left] [/align]
[align=left] [/align]
[align=left] [/align]
[align=left]This page was automatically generated by the [/align]
[align=left]LXR engine.[/align]
[align=left]

[/align]
[align=left]Visit the LXR main site for more[/align]
[align=left]information.[/align]
[align=left] [/align]
[align=left]////////////////////////////////////////////////////////////////////////[/align]
[align=left] [/align]
[align=left]5.3 step 18:[/align]
[align=left] i = end - next->offset[/align]
[align=left] tmp->len -= i[/align]
[align=left] tmp->offset += i[/align]
[align=left] tmp->ptr += i[/align]
[align=left] 和next有重叠时的两种情况:[/align]
[align=left] 1:[/align]



[align=left] 2:[/align]



[align=left][/align]
[align=left][/align]
[align=left]5.4 ipq结构中的特殊成员timer[/align]
[align=left] 作用:描述已经收到的属于同一IP包的所有分片的存活期限[/align]
[align=left] 创建:step 8[/align]
[align=left] 初始设置:step 10[/align]
[align=left] expires为当前时间+30秒[/align]
[align=left] function:失效时的处理函数地址[/align]
[align=left] data:失效时的处理函数的参数,即timer所在的ipq结点首地址[/align]
[align=left][/align]
[align=left][/align]
[align=left]5.5 ipq结构中的特殊成员timer[/align]
[align=left] 更新:[/align]
[align=left] 所有ipq结点中的timer成员组成一个双向链表_TIMER,链首:timer_head,链尾:timer_tail[/align]
[align=left] 分片链表超时处理 step 1 : 当一个_IPQ链表在30秒内没有再收到分片数据时,放弃重组[/align]
[align=left] timer的更新step 13 :当收到一个分片时,重新设置失效时间,并将该分片所属ipq中的timer移到_TIMER的尾部[/align]
[align=left][/align]
[align=left] [/align]
[align=left]5.6 分片数据是否可重组的判断[/align]
[align=left] [/align]
[align=left] 借助ipq结构中的成员变量len[/align]
[align=left] 初始值:0[/align]
[align=left] 更新:仅当收到最后一个分片时才设置len[/align]
[align=left] 判断:[/align]
[align=left] 当ipq.len为0时直接返回[/align]
[align=left] 当收到最后一个分片后才检查_FRAG链表中的各分片是否相连 (ip_done函数中)判断[/align]
[align=left] 代码:[/align]
[align=left] 参tag: zeq_final_frag[/align]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: