参考:
【1】https://www.cnblogs.com/xingmuxin/p/10826703.html
【2】https://blog.csdn.net/dog250/article/details/40680765 dog250大神对ifb的理解
1.使用ifb进行容器的出向限速
创建ifb,并mirror流量至ifb网卡上,限制发送侧5G的发送流量 modprobe ifb //支持参数,默认创建ifbx网卡的数目 ifconfig ifb1 up # tc qdisc add dev cor3cb4dbf9d2f ingress # tc qdisc add dev ifb1 root handle 1: htb default 10 # tc class add dev ifb1 parent 1: classid 1:1 htb rate 10000mbit
# tc -s qdisc ls dev cor3cb4dbf9d2f |
---|
cor3cb4dbf9d2f是宿主机上的一个容器对应的veth卡,bond0位宿主机物理卡,可以看到,虽然限速了10G,但是虚拟网卡由于mirror到了ifb网卡,导致丢包严重,性能急剧下降。
测试使用在容器中iperf发送udp包,实际可发送110wpps,但使用ifb后,只能发送到40wpps左右
2.使用tc ingress进行容器的出向限速
# tc qdisc add dev cor3cb4dbf9d2f ingress # tc filter del dev cor3cb4dbf9d2f parent ffff: protocol all prio 49 basic police rate 20000mbit burst 1mb mtu 65535 drop # tc -s qdisc ls dev cor3cb4dbf9d2f |
---|
可以看出,加上ingress限速规则前后,对PPS的影响很小。
3. 性能为何相差这么大
3.1 先看下tc ingress
tc ingress在linux中使用了act_police模块,对应于act_police.c文件,该文件实现了令牌桶方式的限速功能
man tc-police:
The police action allows to limit bandwidth of traffic matched by the filter it is attached to. Basically there are two different algorithms available to measure the packet rate: The first one uses an internal dual token
bucket and is configured using the rate, burst, mtu, peakrate, overhead and linklayer parameters. The second one uses an in-kernel sampling mechanism. It can be fine-tuned using the estimator filter parameter.
|
接收的限速流程为:__netif_receive_skb_core -> sch_handle_ingress -> tcf_classify -> basic_classify -> tcf_action_exec -> tcf_act_police
在tcf_act_police函数中对报文进行令牌桶限速,允许出现burst尖峰流量,当超过限速时,drop统计会增加,性能损耗主要在:
1)增加了tc处理逻辑,classify
2)令牌桶处理逻辑
3.2 再看下ifb的流程
ifb通常是和tc ingress使用,tc filter规则中创建的规则是mirred到ifb网卡,然后再ifb网卡上创建限速功能,man tc-mirred :
The mirred action allows packet mirroring (copying) or redirecting (stealing) the packet it receives. Mirroring is what is sometimes referred to as Switch Port Analyzer (SPAN) and is commonly used to analyze and/or debug flows
在内核中处理流程为:
|
接收的限速流程为:__netif_receive_skb_core -> sch_handle_ingress -> tcf_classify -> basic_classify -> tcf_action_exec -> tcf_mirred 到ifb 网卡,进入ifb网卡的xmit流程,
ifb驱动模拟一块虚拟网卡,它可以被看作是一个只有TC过滤功能的虚拟网卡,说它只有过滤功能,是因为它并不改变数据包的方向,即对于往外发的数据包被重定向到ifb之后,经过ifb的TC过滤之后,依然是通过重定向之前的网卡发出去,对于一个网卡接收的数据包,被重定向到ifb之后,经过ifb的TC过滤之后,依然被重定向之前的网卡继续进行接收处理,不管是从一块网卡发送数据包还是从一块网卡接收数据包,重定向到ifb之后,都要经过一个经由ifb虚拟网卡的dev_queue_xmit操作。参考[2]
以上图左边使用Ingress方向的Ifb为例,从网卡A收到的报文,经过tc mirred规则后,重新镜像到ifb网卡,ifb网卡经过一些列的处理后,最终会将流量“转发”至网卡A,代码层面来看:
|
结合上面对ifb处理流程,可以看出ifb性能损耗如下几个地方:
1)tcf_mirred函数中存在skb_clone(skb, GFP_ATOMIC)操作,在perf查看中也可以看见此部分占据了一定的热点;
2)ifb网卡的入队,出队,tasklet调度;
3)ifb网卡后续的tc规则处理,整流;
4)重新enque至网卡的收队列,重新触发__netif_receive_skb_core
4. 结果
根据上述实际测试结果来看,只从入向限速的性能来看,tc police方式要比ifb方式性能高出很多。
=================================================================================
以上均为个人理解,若有错误欢迎各位指正批评,欢迎交流。Shawn