免费注册 查看新帖 |

Chinaunix

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

[网络子系统] 调用dev_queue_xmit死机 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-06-01 05:21 |只看该作者 |倒序浏览
本帖最后由 lawrence2013 于 2013-06-04 15:21 编辑

大家好,我netfilter的local out hook钩到数据包,然后通过dev_queue_xmit发送出去。数据包能正常发送出去,而且对段也能正常收到,但目前的问题是机器频繁死机。如果我把函数dev_queue_xmit禁了,机器就比较稳定了。请你们帮我看下是不是的代码有什么问题?是不是可能在dev_queue_xmit有死锁了?谢谢!

static unsigned int modify(unsigned int hooknum, struct sk_buff * skb,
                                      const struct net_device * in, const struct net_device * out,
                                      int (*okfn)(struct sk_buff *))
{
        struct sk_buff* nskb = NULL;
        struct iphdr* nip_hdr = NULL;
        struct ethhdr* neth_hdr = NULL;
        struct icmphdr *icmph = NULL;
        int tot_len;
        int iph_len;
        int iph_off;

        int ret = 0;

        nskb = skb;
               
        nip_hdr = ip_hdr(nskb);
        iph_len = ip_hdrlen(nskb);
        iph_off = nip_hdr->ihl << 2;
        tot_len = ntohs(nip_hdr->tot_len);      

        if((nip_hdr->protocol != IPPROTO_ICMP))
        {
                return NF_ACCEPT;
        }
      
        skb_pull(nskb, iph_len);
        skb_reset_transport_header(nskb);


        if(nip_hdr->protocol == IPPROTO_ICMP)
        {
                icmph = icmp_hdr(nskb);
                    icmph->checksum = 0;
                nskb->csum = 0;
                nskb->csum = csum_partial((unsigned char *)icmph, tot_len - iph_len, 0);
                icmph->checksum = in_cksum((unsigned short *)icmph,  
                            ntohs(nip_hdr->tot_len) - sizeof(struct iphdr));
       
        }

        nip_hdr->check = 0;
        nip_hdr->check = ip_fast_csum((unsigned char *)nip_hdr, nip_hdr->ihl);
       
        nskb->ip_summed = CHECKSUM_NONE;
        nskb->pkt_type  = PACKET_OUTGOING;
       
        nskb->dev = dev_get_by_name(&init_net,ETH);
        if(nskb->dev==NULL)
        {
                printk("%s\n", "dev_get_by_name return NULL");
                //kfree_skb(nskb);
                return NF_ACCEPT;
        }
        dev_put(nskb->dev);

        skb_push(nskb, iph_len);
        
        neth_hdr = (struct ethhdr *)skb_push(nskb, ETH_HLEN);
        skb_reset_mac_header(nskb);
        nskb->protocol = neth_hdr->h_proto = htons(ETH_P_IP);
        memcpy(neth_hdr->h_source, nskb->dev->dev_addr, ETH_ALEN);
        memcpy(neth_hdr->h_dest, DEST, ETH_ALEN);
  
   
        ret = dev_queue_xmit(nskb);
  
        if(ret !=  NET_XMIT_SUCCESS){
                printk("ret:%d\n", ret);
        }
        return NF_STOLEN;
}

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
2 [报告]
发表于 2013-06-01 09:59 |只看该作者
回复 1# lawrence2013

LOCALOUT 的话,MAC header 还没构建吧,你从那里获取这些信息啊。我看你代码中是通过 skb 取出的,你打印出来看看 MAC header 是否正确。
   

论坛徽章:
1
15-16赛季CBA联赛之新疆
日期:2017-03-09 12:33:45
3 [报告]
发表于 2013-06-01 11:42 |只看该作者
回复 1# lawrence2013


    你的死机,是不是什么反应都没有,如果是这样,那就是表明你这个是死机了,是因为死锁,这个现在最简单的处理方法,是把你的这个nskb加入到一个队列,在另一个内核线程来处理,这样就可能解决了。

论坛徽章:
0
4 [报告]
发表于 2013-06-02 02:37 |只看该作者
本帖最后由 lawrence2013 于 2013-06-02 03:29 编辑

回复 2# Godbach

多谢版主的回复。我从ARP表里面取得目的MAC地址赋值到DEST数组,目前的这个程序一般的时候都能通,就是时而会死机。所以,我觉得可能不是这个问题,有可能是哪里发生死锁了。

   

论坛徽章:
0
5 [报告]
发表于 2013-06-02 02:44 |只看该作者
回复 3# jeppeter

多谢jeppeter的回复!是的,我的模块加载以后时而就会死机,一点反应都没有。用队列处理是不是比较会影响想能?你觉得一般是哪里会发生死锁,是不是可能dev_queue_xmit被反复调用了,有没什么办法可以调试出来?谢谢!

   

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
6 [报告]
发表于 2013-06-03 09:45 |只看该作者
回复 1# lawrence2013
用kdump跑一次,打印一下crash后的堆栈情况看看

   

论坛徽章:
0
7 [报告]
发表于 2013-06-04 11:22 |只看该作者
  1. ret = dev_queue_xmit(nskb);
复制代码
后会释放nskb,你再调用
  1. dev_put(nskb->dev);
复制代码
会有问题

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
8 [报告]
发表于 2013-06-04 11:54 |只看该作者
回复 7# whaaat



嗯,我也想说这块呢。记得以前调用 dev_queue_xmit() 的时候,从未调用 dev_put().


   

论坛徽章:
0
9 [报告]
发表于 2013-06-04 14:10 |只看该作者
回复 8# Godbach

Sorry, dev_put是我后面加的,删除这个代码效果似乎一样。我之前这行代码在dev_get_by_name后面的。多谢你们的意见!


   

论坛徽章:
0
10 [报告]
发表于 2013-06-04 15:22 |只看该作者
回复 7# whaaat

多谢你的提醒,我已经改回来了。但问题还是依旧。。。


   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP