免费注册 查看新帖 |

Chinaunix

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

Linux内核如何防止快速的CPU要求网卡发送过多的UDP包? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-10-10 13:33 |只看该作者 |倒序浏览
本人最近研究一个直接使用Linux网卡驱动程序发送数据包的方法,其中发送的大致代码是这样的(内核态代码):


  1. ssize_t mysend(struct sk_buff *skb)
  2. {
  3.     struct net_device *odev = skb->dev;
  4.     if( odev->flags & IFF_UP ) {
  5.         ret = dev_queue_xmit(skb);
  6.         return (ssize_t) ret;
  7.     }
  8.     else return -ENETDOWN;
  9. }
复制代码


其中skb是在调用mysend之前构造好的。我在一个10Gbps的网卡上测试,目前的问题是:似乎dev_queue_xmit() 不会返回错误(负值)。因为,当我用一个进程调用这段代码时,能发送大约413MBps左右的流量,跟dstat显示的差不多。

但是如果有四个进程并发执行,问题就来了:dstat显示发送的流量是1138MBps——这个数值比较合理因为差不多到了10Gbps网卡的能力上限。而我的程序中,自己统计成功发送的次数——也就是mysend返回值大于等于0时——然后计算流量,四个进程总流量居然达到了1474MBps,这显然是不可能的。

我个人的理解是,一个进程的时候,CPU单核“不如网卡快”,因此程序统计流量与dstat相近;但是在四核下,CPU调用mysend的次数过快,而网卡实际上发送不了这么多数据,怪的是dev_queue_xmit()为什么不能报错呢?

怎么才能在mysend中加入一种阻塞机制(类似socket的send),当mysend返回非负值时一定意味着发送真的成功了。

[ 本帖最后由 libra_z 于 2009-10-10 13:36 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2009-10-12 10:05 |只看该作者
自己顶一下,求高手指点啊。
在1Gbps网卡下面,Linux Socket的send发送数据流,在较强的CPU下系统调用send的次数是比网卡处理能力强的,Linux内核如何保证数据总是能发出去呢?

论坛徽章:
0
3 [报告]
发表于 2009-10-12 10:15 |只看该作者

回复 #1 libra_z 的帖子

dev_queue_xmit会把skb queue进net_device所对应的Qdisc里,包并没有真正的发出去。

所以你统计的并不是网卡真正的发送速度。

论坛徽章:
0
4 [报告]
发表于 2009-10-12 10:31 |只看该作者
原帖由 eexplorer 于 2009-10-12 10:15 发表
dev_queue_xmit会把skb queue进net_device所对应的Qdisc里,包并没有真正的发出去。

所以你统计的并不是网卡真正的发送速度。


的确如此。所以我才觉得问题比较棘手:如果我的程序调用dev_queue_xmit()速度非常快,已经超过了网卡的硬件能力,我如何才能知道网卡不能发送数据出去呢?

论坛徽章:
0
5 [报告]
发表于 2009-10-12 13:05 |只看该作者
原帖由 libra_z 于 2009-10-12 10:31 发表


的确如此。所以我才觉得问题比较棘手:如果我的程序调用dev_queue_xmit()速度非常快,已经超过了网卡的硬件能力,我如何才能知道网卡不能发送数据出去呢?


这个在驱动这一层是无法控制的,应该由传输层以上的协议控制。tcp有congestion control, udp的话,需要在application层自己实现。

论坛徽章:
0
6 [报告]
发表于 2009-10-12 21:35 |只看该作者
我的想法是,如果queue 满了,那就用netif_stop_queue ,等不满的时候在netif_wake_queue
不知道这样行不行。

论坛徽章:
0
7 [报告]
发表于 2009-10-12 23:45 |只看该作者
原帖由 llzzccc 于 2009-10-12 21:35 发表
我的想法是,如果queue 满了,那就用netif_stop_queue ,等不满的时候在netif_wake_queue
不知道这样行不行。


这个机制一般在网卡里都已经有了。实际上,网卡硬件上还有一个缓冲,如果这个缓冲满了,那么驱动应该自动调用 netif_stop_queue 来停止OS的缓冲。至少在我看的 8139TOO.C 里有这么一段:

static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
{
.....

if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) //说明硬件的可以用的DMA发送描述符已经满了。
                netif_stop_queue (dev);

....
}

另外,我觉得数据总是能发出去的,区别在于快慢而已。一般的设计是,有几个BUFFER来放要发的数据。在BUFFER没满之前,你可以尽情的发。但是如果BUFFER满了,那么你就不可以发了。但是这个BUFFER有好几个。OS里有,NIC上也有。所以你很难说你的数据到底是啥时候发出去的。
我猜那个 DEV_QUEUE_XMIT只是告诉你BUFFER是否满,是否能继续发的情况。应该说,只要写到BUFFER里,一般来说都会成功发送出去的。如果CPU太快,要发的数据太多,网卡驱动自然会让它时不时停下来一会儿。

论坛徽章:
0
8 [报告]
发表于 2009-10-13 10:15 |只看该作者

回复 #7 accessory 的帖子

通过netif_stop_queue是停止OS向网卡发送数据(OS不会调用网卡的发送函数),但是新的数据还是会queue到qdisc里,除非到达了qdisc里设置的上限,dev_queue_xmit才会返回错误。

所以只要你有足够的os buffer,数据是会按照网卡的发送速度把数据发送出去。但是如果你queue的数据太多的话,os那一层就会丢数据。

所以,如果dev_queue_xmit返回正确的话,可以认为数据最终总会发送出去,
要最终确定数据有没有真正的发送到接收方的话,只能通过协议来控制。

论坛徽章:
7
丑牛
日期:2013-10-18 14:43:21技术图书徽章
日期:2013-11-03 09:58:03辰龙
日期:2014-01-15 22:57:50午马
日期:2014-09-15 07:04:39丑牛
日期:2014-10-16 14:25:222015年亚洲杯之伊朗
日期:2015-03-16 10:24:352015亚冠之城南
日期:2015-05-31 09:52:32
9 [报告]
发表于 2009-10-13 10:45 |只看该作者
验证dev_queue_xmit最后是不是保证帮你把数据包发送出去,很简单.
不停的发,等一个较长时间,它会达到一个平衡,如果这时上层发现数据大概小于10G,就是保证了,如果上层远大于10G就是他偷偷把包丢了.

论坛徽章:
7
丑牛
日期:2013-10-18 14:43:21技术图书徽章
日期:2013-11-03 09:58:03辰龙
日期:2014-01-15 22:57:50午马
日期:2014-09-15 07:04:39丑牛
日期:2014-10-16 14:25:222015年亚洲杯之伊朗
日期:2015-03-16 10:24:352015亚冠之城南
日期:2015-05-31 09:52:32
10 [报告]
发表于 2009-10-13 10:55 |只看该作者
lz,
这个问题最后的原因是什么呢?找到了吗?
http://linux.chinaunix.net/bbs/viewthread.php?tid=1124034
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP