博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
从veth看虚拟网络设备的qdisc
阅读量:6471 次
发布时间:2019-06-23

本文共 3333 字,大约阅读时间需要 11 分钟。

从veth看虚拟网络设备的qdisc

背景

前段时间在测试docker的网络性能的时候,发现了一个veth的性能问题,后来给docker官方提交了一个PR,参考,引起了一些讨论。再后来,RedHat的网络专家 出来详细的讨论了一下这个问题。

141941365298477.png

可以看到,veth设备qdisc队列,而环回设备/桥接设备是没qdisc队列的,参考br_dev_setup函数。

内核实现

在注册(创建)设备时,qdisc设置为noop_qdisc,

register_netdevice -> dev_init_scheduler

void dev_init_scheduler(struct net_device *dev){    dev->qdisc = &noop_qdisc;    netdev_for_each_tx_queue(dev, dev_init_scheduler_queue, &noop_qdisc);    dev_init_scheduler_queue(dev, &dev->rx_queue, &noop_qdisc);    setup_timer(&dev->watchdog_timer, dev_watchdog, (unsigned long)dev);}

打开设备时,如果没有配置qdisc时,就指定为默认的pfifo_fast队列:

dev_open -> dev_activate,

void dev_activate(struct net_device *dev){    int need_watchdog;    /* No queueing discipline is attached to device;       create default one i.e. pfifo_fast for devices,       which need queueing and noqueue_qdisc for       virtual interfaces     */    if (dev->qdisc == &noop_qdisc)        attach_default_qdiscs(dev);...}static void attach_default_qdiscs(struct net_device *dev){    struct netdev_queue *txq;    struct Qdisc *qdisc;    txq = netdev_get_tx_queue(dev, 0);    if (!netif_is_multiqueue(dev) || dev->tx_queue_len == 0) {        netdev_for_each_tx_queue(dev, attach_one_default_qdisc, NULL);        dev->qdisc = txq->qdisc_sleeping;        atomic_inc(&dev->qdisc->refcnt);    } else {///multi queue        qdisc = qdisc_create_dflt(dev, txq, &mq_qdisc_ops, TC_H_ROOT);        if (qdisc) {            qdisc->ops->attach(qdisc);            dev->qdisc = qdisc;        }    }}static void attach_one_default_qdisc(struct net_device *dev,                     struct netdev_queue *dev_queue,                     void *_unused){    struct Qdisc *qdisc;    if (dev->tx_queue_len) {        qdisc = qdisc_create_dflt(dev, dev_queue,                      &pfifo_fast_ops, TC_H_ROOT);        if (!qdisc) {            printk(KERN_INFO "%s: activation failed\n", dev->name);            return;        }        /* Can by-pass the queue discipline for default qdisc */        qdisc->flags |= TCQ_F_CAN_BYPASS;    } else {        qdisc =  &noqueue_qdisc;    }    dev_queue->qdisc_sleeping = qdisc;}

创建noqueue

开始尝试直接删除设备默认的pfifo_fast队列,发现会出错:

# tc qdisc del dev vethd4ea rootRTNETLINK answers: No such file or directory# tc  -s qdisc ls dev vethd4eaqdisc pfifo_fast 0: root refcnt 2 bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1 Sent 29705382 bytes 441562 pkt (dropped 0, overlimits 0 requeues 0)  backlog 0b 0p requeues 0

后来看到Jesper Brouer给出一个替换默认队列的方式,尝试了一下,成功完成。

替换默认的qdisc队列

# tc qdisc replace dev vethd4ea root pfifo limit 100# tc  -s qdisc ls dev vethd4ea                      qdisc pfifo 8001: root refcnt 2 limit 100p Sent 264 bytes 4 pkt (dropped 0, overlimits 0 requeues 0)  backlog 0b 0p requeues 0 # ip link show vethd4ea9: vethd4ea: 
mtu 1500 qdisc pfifo master docker0 state UP mode DEFAULT qlen 1000link/ether 3a:15:3b:e1:d7:6d brd ff:ff:ff:ff:ff:ff

修改队列长度

# ifconfig vethd4ea txqueuelen 0

删除qdisc

# tc qdisc del dev vethd4ea root                    # ip link show vethd4ea                9: vethd4ea: 
mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT link/ether 3a:15:3b:e1:d7:6d brd ff:ff:ff:ff:ff:ff

可以看到,UP的veth设备成功修改成noqueue。

小结

总之,给虚拟网络设备创建默认的qdisc,是不太合理的。这会让虚拟机(或者容器)的网络瓶颈过早的出现在qdisc,而不是真实的物理设备(除非应用需要创建qdisc)。更多详细参考。

转载于:https://www.cnblogs.com/hustcat/p/4025070.html

你可能感兴趣的文章
SVN服务器使用(二)
查看>>
反射获取内部类以及调用内部类方法
查看>>
C语言 - pthread
查看>>
App里面如何正确显示用户头像
查看>>
DATAGUARD维护:从库宕机后如何恢复到管理恢复模式
查看>>
U-BOOT之一:BootLoader 的概念与功能
查看>>
我的路上
查看>>
Velocity处理多余空白和多余空白行问题
查看>>
java值传递
查看>>
DB2与oracle有什么区别
查看>>
创建一个多级文件目录
查看>>
Picasa生成图片幻灯片页面图文教程
查看>>
js获取当前时间的前一天/后一天
查看>>
Python字符串的格式化
查看>>
C#反射---属性
查看>>
服务器常用的状态码及其对应的含义如下
查看>>
zoom和transform:scale的区别
查看>>
黄聪:PHP 防护XSS,SQL,代码执行,文件包含等多种高危漏洞
查看>>
svn status 显示 ~xx
查看>>
常用HiveQL总结
查看>>