免费注册 查看新帖 |

Chinaunix

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

[内核入门] dev_queue_xmit发送数据包很慢 如何解决【解决】 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-07-05 12:03 |只看该作者 |倒序浏览
本帖最后由 yiyuandao 于 2012-07-05 17:23 编辑

在prerouting新分配一个new_skb,从old_skb拷贝ip头,传输层及负载,查找路由填充mac地址,最后调用dev_queue_xmit发出去,抓包发现
包发出去的速度很慢:

正常来说直接发送应该很快啊

代码:
  1. void build_ipv4_packet(struct sk_buff* sock_skb, struct sk_buff* new_skb)
  2. {
  3.         struct iphdr* iph;

  4.         iph = ip_hdr(sock_skb);
  5.         if(!iph){
  6.                 printk("iph error\n");
  7.                 return NF_ACCEPT;
  8.         }

  9.         new_skb = dev_alloc_skb(sock_skb->len + ETH_HLEN + 40 + 5);
  10.         if(!new_skb){
  11.                 printk("low memory....\n");
  12.         }

  13.         skb_reserve(new_skb, 2);

  14.         skb_put(new_skb, ETH_HLEN + sock_skb->len);

  15.         construct_eth_header(sock_skb, new_skb, 0x800);

  16.         memcpy((new_skb->data + ETH_HLEN), sock_skb->data, sock_skb->len);


  17.         new_skb->ip_summed = CHECKSUM_UNNECESSARY;
  18.         //new_skb->pkt_type = PACKET_HOST;
  19.         //new_skb->pkt_type = PACKET_OUTGOING;
  20.         new_skb->pkt_type = PACKET_OTHERHOST;
  21.         new_skb->protocol = htons(ETH_P_IP);
  22.         new_skb->dev = sock_skb->dev;

  23.         skb_pull(new_skb, ETH_HLEN);
  24.         if (skb_dst(new_skb) == NULL)
  25.         {
  26.                 //printk("##############ipv4 not found route###begin#########\n");
  27.         }

  28.         struct timeval tv;
  29.         struct timeval end_tv;
  30.         do_gettimeofday(&tv);
  31.         printk("before lookup route: second: %ld mircsecond: %ld\n", tv.tv_sec, tv.tv_usec);
  32.         //struct net *net = dev_net(sock_skb->dev);
  33.         int flags = RT6_LOOKUP_F_HAS_SADDR;
  34.         struct rtable *rt;
  35.         struct flowi fl = {
  36.                 .nl_u = {
  37.                         .ip4_u = {
  38.                                 .daddr =  iph->daddr
  39.                         }
  40.                 }
  41.         };
  42.                // lookup ipv4 route
  43.         __be32 dest = 0;
  44.         if (ip_route_output_key(&init_net, &rt, &fl) != 0)
  45.         {
  46.                 kfree_skb(sock_skb);
  47.                 printk("not found  ipv4 route-----------------------------------######\n");
  48.                 return;
  49.         }
  50.         dest = rt->rt_gateway;
  51.         struct neighbour *neighbor_entry = neigh_lookup(&arp_tbl, &dest, sock_skb->dev);

  52.         if (neighbor_entry != NULL)
  53.         {
  54.                 //printk("##############found  ipv4 route############\n");
  55.                 //print_buf(neighbor_entry->ha, 6);
  56.         }

  57.         skb_push(new_skb, ETH_HLEN);

  58.         //print_buf(new_skb->data, 14);
  59.         memcpy(new_skb->data, neighbor_entry->ha, 6);
  60.         //print_buf(new_skb->data, 34);

  61.         do_gettimeofday(&end_tv);
  62.         printk("before send: second: %ld mircsecond: %ld\n", end_tv.tv_sec, end_tv.tv_usec);
  63.         dev_queue_xmit(new_skb);

  64.         do_gettimeofday(&end_tv);
  65.         printk("after send: second: %ld mircsecond: %ld\n", end_tv.tv_sec, end_tv.tv_usec);
  66.         //kfree_skb(sock_skb);
  67. }
复制代码
测试log:
!!!!!!!!!!!!!!start: second: 1341398275 mircsecond: 201298
Jul  4 18:37:55 ubuntu kernel: [ 7232.734796] ------!!!!!!!!!!!!!!!!!!!!!!!!!!------------------------------ipv4 ICMP Data Recv:
Jul  4 18:37:55 ubuntu kernel: [ 7232.734800] before lookup route: second: 1341398275 mircsecond: 201308
Jul  4 18:37:55 ubuntu kernel: [ 7232.734805] before send: second: 1341398275 mircsecond: 201313
Jul  4 18:37:55 ubuntu kernel: [ 7232.734843] after send: second: 1341398275 mircsecond: 201349

从log看到 dev_queue_xmit处理完成并没有花什么时间。
是不是dev_queue_xmit处理过程中把skb添加到发送队列去了,等待发送浪费了时间?

解决方法:
在32行以前添加:skb_reset_network_header(new_skb);
设置网络层头

但是不知道为什么添加了就能快速发送出去,估计在dev_queue_xmit中会需要skb->network_header

论坛徽章:
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 [报告]
发表于 2012-07-05 13:20 |只看该作者
回复 1# yiyuandao

你这是两次发包的间隔比较大一些。

这个应该和你整个的处理流程有关,而不是 dev_queue_xmit 的问题吧。你这里面还要打日志啥的,都会影响到发包的速度。

   

论坛徽章:
0
3 [报告]
发表于 2012-07-05 13:31 |只看该作者
回复 2# Godbach
谢谢。

第二个包是在prerouting抓到第一个包后经过处理发送的包,而第一个包已经被drop掉了
打日志是为了测试时间:基本上不花费时间
从第一个包收到第二包发出的时间间隔明显很长。

理论上是直接用dev_queue_xmit更快啊

另外在prerouting用netif_rx()发送的时候绕了一圈的速度也比dev_queue_xmit快的多
是否有什么优先级相关啊?



   

论坛徽章:
2
CU大牛徽章
日期:2013-04-17 11:46:28CU大牛徽章
日期:2013-04-17 11:46:39
4 [报告]
发表于 2012-07-05 13:40 |只看该作者
貌似 printk 比 dev_queue_xmit 花的时间更多吧

论坛徽章:
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
5 [报告]
发表于 2012-07-05 13:49 |只看该作者
回复 4# cdtits

LZ 可以听一下 4 楼的意见,屏蔽掉所有  printk 的地方,然后再试试


   

论坛徽章:
0
6 [报告]
发表于 2012-07-05 14:00 |只看该作者
本帖最后由 yiyuandao 于 2012-07-05 14:02 编辑

回复 4# cdtits


    printk快。

printk+dev_queue_xmit:

Jul  5 13:52:23 ubuntu kernel: [76359.312630] before send: second: 1341467543 mircsecond: 627186
Jul  5 13:52:23 ubuntu kernel: [76359.312669] TEST printk time
Jul  5 13:52:23 ubuntu kernel: [76359.312671] after send: second: 1341467543 mircsecond: 627228

only printk:
Jul  5 13:56:05 ubuntu kernel: [76581.139220] before send: second: 1341467765 mircsecond: 908965
Jul  5 13:56:05 ubuntu kernel: [76581.139222] TEST printk time
Jul  5 13:56:05 ubuntu kernel: [76581.139224] after send: second: 1341467765 mircsecond: 908969

对比很明显
printk就 3-4usec左右

屏蔽了printk。还是慢

论坛徽章:
0
7 [报告]
发表于 2012-07-05 14:06 |只看该作者
回复 5# Godbach

屏蔽printk了。还是慢,
从log上看:
Jul  4 18:37:55 ubuntu kernel: [ 7232.734805] before send: second: 1341398275 mircsecond: 201313
Jul  4 18:37:55 ubuntu kernel: [ 7232.734843] after send: second: 1341398275 mircsecond: 201349
执行完dev_queue_xmit只花了36usec

但从最后包发出的时间看相差太多了,
所以想是不是dev_queue_xmit执行完后包并没有发出去,还在等待中


   

论坛徽章:
2
申猴
日期:2013-12-26 22:11:31天秤座
日期:2014-12-23 10:23:19
8 [报告]
发表于 2012-07-05 14:38 |只看该作者
没检查校验和?

论坛徽章:
0
9 [报告]
发表于 2012-07-05 15:03 |只看该作者
回复 8# goter

没有修改ip层,传输层,负载。
只修改了mac地址

不涉及到校验和


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

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP