免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4706 | 回复: 13
打印 上一主题 下一主题

[网络子系统] ip_frag_queue的问题【已解决】 [复制链接]

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-03-04 22:16 |只看该作者 |倒序浏览
本帖最后由 jiufei19 于 2014-03-10 18:53 编辑

内核版本v2.6.23,在阅读IP报文分段重组函数ip_frag_queue时,发现以前没有太仔细阅读如下红色代码,现在回头看时,不懂这段代码适应什么样的场景

static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
{
    ...
    if (!(IPCB(skb)->flags & IPSKB_FRAG_COMPLETE) &&
          unlikely(ip_frag_too_far(qp)) && unlikely(ip_frag_reinit(qp))) {
          ipq_kill(qp);
          goto err;
    }
    ...
}

IPSKB_FRAG_COMPLETE这个标记明明是在对外出分组进行分段时才打上的标记,为啥这里在进入分组的处理中会检查到这个标记呢?

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
2 [报告]
发表于 2014-03-04 23:08 |只看该作者
本帖最后由 jiufei19 于 2014-03-04 23:18 编辑

自己又搜索了下代码,发现有下面几个地方调用了ip_defrag函数,而ip_frag_queue又在ip_defrag中被调用,看来可能是这个原因导致的:

/home/admin/linux-2.6.23.1/net/ipv4/ip_input.c|175| <<ip_call_ra_chain>> skb = ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN);
/home/admin/linux-2.6.23.1/net/ipv4/ip_input.c|307| <<ip_local_deliver>> skb = ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER);                              
/home/admin/linux-2.6.23.1/net/ipv4/ipvs/ip_vs_core.c|547| <<ip_vs_gather_frags>> skb = ip_defrag(skb, user);
/home/admin/linux-2.6.23.1/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c|72| <<nf_ct_ipv4_gather_frags>> skb = ip_defrag(skb, user);

我之所以产生疑问的原因是只看到上面红色语句对应的场景了,我猜测是至少蓝色语句对应的场景可能会发生外出分组在打上IPSKB_FRAG_COMPLETE标记后,被连接跟踪模块处理时会出现我描述的疑问,因为连接跟踪代码没有读过,所以无法完全理解,还请各位解惑!

论坛徽章:
15
射手座
日期:2014-02-26 13:45:082015年迎新春徽章
日期:2015-03-04 09:54:452015年辞旧岁徽章
日期:2015-03-03 16:54:15羊年新春福章
日期:2015-02-26 08:47:552015年亚洲杯之卡塔尔
日期:2015-02-03 08:33:45射手座
日期:2014-12-31 08:36:51水瓶座
日期:2014-06-04 08:33:52天蝎座
日期:2014-05-14 14:30:41天秤座
日期:2014-04-21 08:37:08处女座
日期:2014-04-18 16:57:05戌狗
日期:2014-04-04 12:21:33技术图书徽章
日期:2014-03-25 09:00:29
3 [报告]
发表于 2014-03-05 09:12 |只看该作者
代码看得真仔细,值得学习~~

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
4 [报告]
发表于 2014-03-05 10:29 |只看该作者
本帖最后由 jiufei19 于 2014-03-05 10:36 编辑

回复 2# jiufei19


   同样,在ip_frag_reasm对报文分段进行重组时,也出现了类似的问题,即有如下代码:

static struct sk_buff *ip_frag_reasm(struct ipq *qp, struct net_device *dev)
{
     ...
    if (skb_shinfo(head)->frag_list) {
        ...
     }
     ...
}

显然,一个skb的frag_list如果不为空,则似乎只能出现在经过本地外出的ip_append_data的处理后才有可能,也就是说该skb连同其frag_list后面链接的所有skb都属于同一个原始IP报文。那么ip_frag_reasm这个重组报文分段的函数,如果在正常情况下是对网络上收到的分段进行重组的话,那么是不可能有某个skb->frag_list为真的情况的。

因此重组IP报文时,代码一再判断这些根本不可能发生于正常的从网络收到skb的处理过程中,到底是为什么?

请各位了解这个细节的大侠点拨下,谢谢!

论坛徽章:
0
5 [报告]
发表于 2014-03-05 10:50 |只看该作者
接收和发送 都会有 分片的
要不
tso、gso
lro、gro
岂不是没有意义了 :)

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
6 [报告]
发表于 2014-03-05 10:55 |只看该作者
本帖最后由 jiufei19 于 2014-03-05 10:57 编辑

回复 5# kkddkkdd11

谢谢答复,不过我仍然没有理解哈!

比如以tso为例(这个我没有研读过代码,包括提到的其他几个xxo, ),kkddkkdd11的意思是说会发生如果从网络收到一个skb,那么这个skb的frag_list上面就有可能挂着其他的从属skb吗? 这似乎有点不好理解,愿闻其详,谢谢!
   

论坛徽章:
0
7 [报告]
发表于 2014-03-05 11:05 |只看该作者
jiufei19 发表于 2014-03-05 10:55
回复 5# kkddkkdd11

谢谢答复,不过我仍然没有理解哈!


这块 我回答的 有点 文不对题 :)
sorry啊 呵呵

gro开启的话 是网卡驱动上的 见笑了
这块 我以前抓收包
都是 skb的buf放头 tcp的数据 放在分片里边
然后 再线性化

这块 共同研究 我也学习一下 :)

论坛徽章:
0
8 [报告]
发表于 2014-03-05 14:58 |只看该作者
楼主 看看源代码
http://blog.sina.com.cn/s/blog_52355d840100b6s7.html
有人分析过,

另外,iphdr->frag_off的高3位
(1) 比特0是保留的,必须为0;
(2) 比特1是“不分片”(DF -- Don't Fragment)标志,如果将这一比特置1,IP将不对数据报进行分片,这时如果有需要进行分片的数据报到来,会丢弃此数据报并发送一个ICMP差错报文给起始端。
(3) 比特2是“更多分片”(MF -- More Fragment)标志。除了最后一片外,其他每个组成数据报的片都要把该比特置1。

:——)

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
9 [报告]
发表于 2014-03-05 15:19 |只看该作者
回复 8# kkddkkdd11


    感谢kkddkkdd11的热心,虽然仍没有解决我的问题

论坛徽章:
0
10 [报告]
发表于 2014-03-05 17:36 |只看该作者
jiufei19 发表于 2014-03-05 10:29
回复 2# jiufei19


      /* If the first fragment is fragmented itself, we split
         * it to two chunks: the first with data and paged part
         * and the second, holding only fragments. */
        if (skb_has_frag_list(head)) {   //我的3.10.5内核版本这句变成了函数,上面有注释 :)if (skb_shinfo(head)->frag_list)
                struct sk_buff *clone;
                int i, plen = 0;

                if ((clone = alloc_skb(0, GFP_ATOMIC)) == NULL)
                        goto out_nomem;
                clone->next = head->next;
                head->next = clone;
                skb_shinfo(clone)->frag_list = skb_shinfo(head)->frag_list;
                skb_frag_list_init(head);
                for (i = 0; i < skb_shinfo(head)->nr_frags; i++)
                        plen += skb_frag_size(&skb_shinfo(head)->frags);
                clone->len = clone->data_len = head->data_len - plen;
                head->data_len -= clone->len;
                head->len -= clone->len;
                clone->csum = 0;
                clone->ip_summed = head->ip_summed;
                add_frag_mem_limit(&qp->q, clone->truesize);
        }
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP