ipv6 分片_C/C++_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > C/C++ > ipv6 分片

ipv6 分片

 2010/12/8 10:17:00  shaojiashuai123456  http://shaojiashuai123456.javaeye.com  我要评论(0)
  • 摘要:519staticintip6_fragment(structsk_buff*skb,int(*output)(structsk_buff*))520{521structnet_device*dev;522structsk_buff*frag;523structrt6_info*rt=(structrt6_info*)skb->dst;524structipv6hdr*tmp_hdr;525structfrag_hdr*fh;526unsignedintmtu,hlen,left,len
  • 标签:ipv6
519 static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
520 {
521         struct net_device *dev;
522         struct sk_buff *frag;
523         struct rt6_info *rt = (struct rt6_info*)skb->dst;
524         struct ipv6hdr *tmp_hdr;
525         struct frag_hdr *fh;
526         unsigned int mtu, hlen, left, len;
527         u32 frag_id = 0;
528         int ptr, offset = 0, err=0;
529         u8 *prevhdr, nexthdr = 0;
530 
531         dev = rt->u.dst.dev;                           //取得路由项中的设备
532         hlen = ip6_find_1stfragopt(skb, &prevhdr);//
533         nexthdr = *prevhdr;
534         //去掉分片头和ip头
535         mtu = dst_pmtu(&rt->u.dst) - hlen - sizeof(struct frag_hdr);
1 快分片
          //如果已经在tcp分片,先查验第一个分片是否满足不用分片的条件,如果满足快速查验其他分片,有问题就跳到慢分片处处理
537         if (skb_shinfo(skb)->frag_list) {
     1.1 查看第一个分片
538                 int first_len = skb_pagelen(skb); //取得第一个分片长度
539                //查看第一个分片是否已经满足不用分片条件
540                 if (first_len - hlen > mtu ||       //是否大于MTU
541                     ((first_len - hlen) & 7) ||      //是否8字节对齐
542                     skb_cloned(skb))                   //是否克隆包
543                         goto slow_path;
     1.2 查看其他分片
545           for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) 
546            {             /* Correct geometry. */
547                         if (frag->len > mtu ||
548                             ((frag->len & 7) && frag->next) ||
549                             skb_headroom(frag) < hlen)
550                             goto slow_path;
551 
552                         /* Correct socket ownership. */
553                         if (frag->sk == NULL)
554                                 goto slow_path;
555 
556                         /* Partially cloned skb? */
557                         if (skb_shared(frag))  //如果是共享数据包,不能被修改
558                                 goto slow_path;
559               }
560 
561                 err = 0;
562                 offset = 0;
563                 frag = skb_shinfo(skb)->frag_list; 
564                 skb_shinfo(skb)->frag_list = NULL;
     1.3 设置主数据包头部
565                 /* BUILD HEADER */
        1.3.1 将头部放在临时区域
567                 tmp_hdr = kmalloc(hlen, GFP_ATOMIC);
568                 if (!tmp_hdr) {
569                         IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS);
570                         return -ENOMEM;
571                 }
572 
573                 *prevhdr = NEXTHDR_FRAGMENT;
574                 memcpy(tmp_hdr, skb->nh.raw, hlen);
        1.3.2 加入分片头部
575                 __skb_pull(skb, hlen);
576         fh = (struct frag_hdr*)__skb_push(skb, sizeof(struct frag_hdr));
        1.3.3 原头部放回
577                 skb->nh.raw = __skb_push(skb, hlen);
578                 memcpy(skb->nh.raw, tmp_hdr, hlen); 
        1.3.4 设置分片头部
580                 ipv6_select_ident(skb, fh);
581                 fh->nexthdr = nexthdr;
582                 fh->reserved = 0;
583                 fh->frag_off = htons(IP6_MF);
584                 frag_id = fh->identification;
585 
586                 first_len = skb_pagelen(skb);
587                 skb->data_len = first_len - skb_headlen(skb);
588                 skb->len = first_len;
589                 skb->nh.ipv6h->payload_len = htons(first_len - sizeof(struct ipv6hdr));
590  
     1.4 发送所有分片
592                 for (;;) {
593                         /* Prepare header of the next frame,
594                          * before previous one went down. */
595                         if (frag) {
        1.4.1 设置个分段数据包头部
596                                 frag->ip_summed = CHECKSUM_NONE;
597                                 frag->h.raw = frag->data;
598                                 fh = (struct frag_hdr*)__skb_push(frag, sizeof(struct frag_hdr));
599                                 frag->nh.raw = __skb_push(frag, hlen);
600                                 memcpy(frag->nh.raw, tmp_hdr, hlen);
601                                 offset += skb->len - hlen - sizeof(struct frag_hdr);
602                                 fh->nexthdr = nexthdr;
603                                 fh->reserved = 0;
604                                 fh->frag_off = htons(offset);
605                                 if (frag->next != NULL)
606                                         fh->frag_off |= htons(IP6_MF);
607                                 fh->identification = frag_id;
608                                 frag->nh.ipv6h->payload_len = htons(frag->len - sizeof(struct ipv6hdr));
609                                 ip6_copy_metadata(frag, skb);
610                         }
        1.4.2 发送数据报
612                         err = output(skb);
613                         if (err || !frag)
614                                 break;
615 
616                         skb = frag;
617                         frag = skb->next;
618                         skb->next = NULL;
619                 }
620 
621                 if (tmp_hdr)
622                         kfree(tmp_hdr);
623 
624                 if (err == 0) {
625                         IP6_INC_STATS(IPSTATS_MIB_FRAGOKS);
626                         return 0;
627                 }
        1.4.3 释放节点
629                 while (frag) {
630                         skb = frag->next;
631                         kfree_skb(frag);
632                         frag = skb;
633                 }
634 
635                 IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS);
636                 return err;
637         }
2 慢分片
639 slow_path:
640         left = skb->len - hlen;         /* Space per frame */
641         ptr = hlen;                     /* Where to start from */
642 
643         /*
644          *      Fragment the datagram.
645          */
646 
647         *prevhdr = NEXTHDR_FRAGMENT;
648 
649         /*
650          *      Keep copying data until we run out.
651          */
652         while(left > 0) {
     2.1 分片
          2.1.1 设置分片长度
653                 len = left;
654                 /* IF: it doesn't fit, use 'mtu' - the data space left */
655                 if (len > mtu)
656                         len = mtu;
657                 /* IF: we are not sending upto and including the packet end
658                    then align the next start on an eight byte boundary */
659                 if (len < left) {
660                         len &= ~7;
661                 }
662                 /*
663                  *      Allocate buffer.
664                  */
          2.1.2 分配分片数据报空间
665 
666                 if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_RESERVED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) {
667                         NETDEBUG(printk(KERN_INFO "IPv6: frag: no memory for new fragment!\n"));
668                         IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS);
669                         err = -ENOMEM;
670                         goto fail;
671                 }
672 
673                 /*
674                  *      Set up data on packet
675                  */
676 
          2.1.3 初始化数据包结构
677                 ip6_copy_metadata(frag, skb);
678                 skb_reserve(frag, LL_RESERVED_SPACE(rt->u.dst.dev));
679                 skb_put(frag, len + hlen + sizeof(struct frag_hdr));
680                 frag->nh.raw = frag->data;
681                 fh = (struct frag_hdr*)(frag->data + hlen);
682                 frag->h.raw = frag->data + hlen + sizeof(struct frag_hdr);
683 
684                 /*
685                  *      Charge the memory for the fragment to any owner
686                  *      it might possess
687                  */
688                 if (skb->sk)
689                         skb_set_owner_w(frag, skb->sk);
690 
691                 /*
692                  *      Copy the packet header into the new buffer.
693                  */
          2.1.4 设置数据包内容
694                 memcpy(frag->nh.raw, skb->data, hlen);  //拷贝数据报头
695 
696                 /*
697                  *      Build fragment header.
698                  */
699                 fh->nexthdr = nexthdr;
700                 fh->reserved = 0;
701                 if (frag_id) {
702                         ipv6_select_ident(skb, fh);
703                         frag_id = fh->identification;
704                 } else
705                         fh->identification = frag_id;
706 
707                 /*
708                  *      Copy a block of the IP datagram.
709                  */
710                 if (skb_copy_bits(skb, ptr, frag->h.raw, len)) //拷贝数据
711                         BUG();
712                 left -= len;
713 
714                 fh->frag_off = htons(offset);
715                 if (left > 0)
716                         fh->frag_off |= htons(IP6_MF);
717                 frag->nh.ipv6h->payload_len = htons(frag->len - sizeof(struct ipv6hdr));
718 
719                 ptr += len;
720                 offset += len;
721 
722                 /*
723                  *      Put this fragment into the sending queue.
724                  */
725 
726                 IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES);
727 

     2.2 发送
728                 err = output(frag);
729                 if (err)
730                         goto fail;
731         }
732         kfree_skb(skb);
733         IP6_INC_STATS(IPSTATS_MIB_FRAGOKS);
734         return err;
735 
736 fail:
737         kfree_skb(skb); 
738         IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS);
739         return err;
740 }

?

  • 相关文章
发表评论
用户名: 匿名