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

    技术2022-05-19  19

    转自:http://blog.csdn.net/sandrain_zeq/archive/2007/06/13/1651246.aspx 作者:sandrain_zeq 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、 代码及相关注释  

    http://blog.csdn.net/wangdm0826/archive/2011/03/08/6232177.aspx

      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有重叠,调整当前分片   调整前图   调整后图 step 15:和prev有重叠,调整当前分片后没有判断当前数据的长度,之后会创建一个无用结点!   2.6.17内核已处理! ~ [  source navigation  ] ~ [  diff markup  ] ~ [  identifier search  ] ~ [  freetextsearch  ] ~ [  file search  ] ~ Linux Cross ReferenceLinux-2.6.17/net/ipv4/ip_fragment.c Version: ~ [  2.6.16  ] ~ [  2.6.17  ] ~ Architecture: ~ [  ia64  ] ~ [  i386  ] ~ [  arm  ] ~ [  ppc  ] ~ [  sparc64  ] ~   1 /*   2  * INET         An implementation of the TCP/IP protocol suite for the LINUX   3  *              operating system. INET is implemented using the BSD Socket   4  *              interface as the means of communication with the user level.   5  *   6  *              The IP fragmentation functionality.   7  *                8  * Version:     $Id: ip_fragment.c,v 1.59 2002/01/12 07:54:56 davem Exp $   9  *   10  * Authors:     Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG>   11  *              Alan Cox <Alan.Cox@linux.org>   12  *   13  * Fixes:   14  *              Alan Cox        :    Split from ip.c , see ip_input.c for history.   15  *              David S. Miller :       Begin massive cleanup...   16  *              Andi Kleen      :       Add sysctls.   17  *              xxxx            :       Overlapfrag bug.   18  *              Ultima          :       ip_expire() kernel panic.   19  *              Bill Hawes      :       Frag accounting and evictor fixes.   20  *              John McDonald   :       0 length frag bug.  21  *              Alexey Kuznetsov:       SMP races, threading, cleanup.  22  *              Patrick McHardy :       LRU queue of frag heads for evictor.  23  */  24 465 466 /* Add new segment to existing queue. */ 467 static void ip_frag_queue (struct ipq * qp , struct sk_buff * skb ) 468 { 469         struct sk_buff *prev, * next ; 470         int flags , offset ; ........................ ........................ ........................ ........................ 522         /* Find out which fragments are in front and at the back of us 523          * in the chain of fragments so far. We must know where to put 524          * this fragment, right? 525          */ 526         prev = NULL ; 527         for( next = qp -> fragments ; next != NULL ; next = next -> next ) { 528                 if ( FRAG_CB ( next )-> offset >= offset ) 529                         break; /* bingo! */ 530                 prev = next ; 531         } 532 533         /* We found where to put this one. Check for overlap with 534          * preceding fragment, and, if needed, align things so that 535          * any overlaps are eliminated. 536          */ 537         if (prev) { 538                 int i = ( FRAG_CB (prev)-> offset + prev-> len ) - offset ; 539 540                 if ( i > 0) { 541                         offset += i ; 542                          if (end <= offset) 543                                 goto err; 544                         if (! pskb_pull ( skb , i )) 545                                 goto err ; 546                         if ( skb ->ip_summed != CHECKSUM_UNNECESSARY ) 547                                 skb ->ip_summed = CHECKSUM_NONE ; 548                 } 549         } 550 551         while ( next && FRAG_CB ( next )-> offset < end ) { 552                 int i = end - FRAG_CB ( next )-> offset ; /* overlap is 'i' bytes */ 553 554                 if ( i < next -> len ) { 555                         /* Eat head of the next overlapped fragment 556                          * and leave the loop. The next ones cannot overlap. 557                          */ 558                         if (! pskb_pull ( next , i )) 559                                 goto err ; 560                         FRAG_CB ( next )-> offset += i ; 561                         qp ->meat -= i ; ........................ ........................ ........................ ........................        ~ [  source navigation  ] ~ [  diff markup  ] ~ [  identifier search  ] ~ [  freetext search  ] ~ [  file search  ] ~       This page was automatically generated by the LXR engine . Visit the LXR main site for more information.     5.3 step 18:     i = end - next->offset     tmp->len -= i     tmp->offset += i     tmp->ptr += i     和next有重叠时的两种情况:       1:       2: 5.4    ipq结构中的特殊成员timer     作用:描述已经收到的属于同一IP包的所有分片的存活期限     创建:step 8     初始设置:step 10     expires为当前时间+30秒     function:失效时的处理函数地址     data:失效时的处理函数的参数,即timer所在的ipq结点首地址     5.5    ipq结构中的特殊成员timer     更新:         所有ipq结点中的timer成员组成一个双向链表_TIMER,链首:timer_head,链尾:timer_tail         分片链表超时处理 step 1 : 当一个_IPQ链表在30秒内没有再收到分片数据时,放弃重组         timer的更新step 13 :当收到一个分片时,重新设置失效时间,并将该分片所属ipq中的timer移到_TIMER的尾部     5.6    分片数据是否可重组的判断       借助ipq结构中的成员变量len         初始值:0         更新:仅当收到最后一个分片时才设置len     判断:         当ipq.len为0时直接返回         当收到最后一个分片后才检查_FRAG链表中的各分片是否相连 (ip_done函数中)判断     代码:         参tag: zeq_final_frag

    最新回复(0)