问题场景描述:
在 nanopi R2S
这个设备上通过 OpenWRT
的 kmod-macvlan
模块来在原有 WAN
口上实现通过 macvlan
模拟多个网卡实现多播并通过 mwan3
实现负载均衡。但这个软路由在一些 fps
游戏中丢包率很高,最高甚至能达到 30%
。
这个设备本身的配置较高,具体如下:
- CPU: Rockchip RK3328, Quad-core Cortex-A53
- DDR4 RAM: 1GB
- Network:
- 10/100/1000M以太网口 x 1
- USB3.0转10/100/1000M以太网口 x 1
- USB2.0 Host: Type-A x1
- MicroSD Slot x 1
- MicroUSB: 供电和Slave功能
- … …
原因分析:
一:初步分析
这里刚开始也是很糊涂,首先查看 MWAN3
的接口管理,15
个接口全部在线。然后查看流量分布,每一个接口负载的流量基本一致,说明负载均衡本身没有问题。命令 cat /proc/net/dev
输出如下所示
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
lo: 74170835 732756 0 0 0 0 0 0 74170835 732756 0 0 0 0 0 0
eth0: 325175502010 226278269 0 23557 0 0 0 0 15931720378 106684540 0 0 0 0 0 0
eth1: 15784791469 106444962 0 3 0 0 0 0 325136286568 225897364 41 514 0 0 0 0
br-lan: 90829588 1155256 0 0 0 0 0 24600 204808310 748262 0 0 0 0 0 0
eth0mac0: 22761792506 8267494 0 18835 0 0 0 44198 1273756523 6714025 0 0 0 0 0 0
eth0mac1: 19861569956 7955932 0 18835 0 0 0 44198 958045924 7012008 0 0 0 0 0 0
eth0mac10: 21453436952 8600099 0 18835 0 0 0 44198 1025429140 6928150 0 0 0 0 0 0
eth0mac11: 21847458680 9345796 0 18835 0 0 0 44198 929173333 7459704 0 0 0 0 0 0
eth0mac12: 21633255469 8759785 0 18835 0 0 0 44198 951617579 6919324 0 0 0 0 0 0
eth0mac13: 24211019558 9461148 0 18835 0 0 0 44198 955575402 7652436 0 0 0 0 0 0
eth0mac14: 17611027039 7553882 0 18835 0 0 0 44198 1042052613 6553982 0 0 0 0 0 0
eth0mac2: 21567948241 9395587 0 18835 0 0 0 44198 1063569099 7724192 0 0 0 0 0 0
eth0mac3: 22445291725 8780407 0 18835 0 0 0 44198 967782642 6721036 0 0 0 0 0 0
eth0mac4: 18900937143 8274493 0 18835 0 0 0 44198 1080188355 6895844 0 0 0 0 0 0
eth0mac5: 19301032365 7725841 0 18835 0 0 0 44198 1013945982 6103718 0 0 0 0 0 0
eth0mac6: 22719026234 9712388 0 18835 0 0 0 44198 1263183388 7773352 0 0 0 0 0 0
eth0mac7: 23295780562 9363182 0 18835 0 0 0 44198 1095561892 7715493 0 0 0 0 0 0
eth0mac8: 23173291311 9593304 0 18835 0 0 0 44198 1249741481 8127114 0 0 0 0 0 0
eth0mac9: 19446767186 7648102 0 18835 0 0 0 44198 1062932733 6393233 0 0 0 0 0 0
二:所有 macvlan
接口都显示相同的丢包数 (18835)
,这表明可能存在系统级别的限制或瓶颈。
通过以下命令:cat /proc/interrupts | grep eth
查看中断服务情况。结果还真发现了问题:所有中断都被第二个核心处理。
命令输出:24: 0 35476273 0 0 GICv2 56 Level eth0
这里我们肯定想,能不能把中断平均到每一个核心上,这样四核完全发挥起来。这其实是做不到的,因为我们物理网卡的限制。
三:尝试中断平衡第一步
opkg update
opkg install irqbalance
/etc/init.d/irqbalance enable
/etc/init.d/irqbalance start
通过上面的命令来平衡中断,发现并没有生效。
四:尝试中断平衡第二步
# 启用所有CPU核心处理网络数据包echo f > /sys/class/net/eth0/queues/rx-0/rps_cpusecho f > /sys/class/net/eth0/queues/tx-0/xps_cpus
执行这东西之后,我们再次 cat /proc/interrupts | grep eth
查看中断服务情况。
结果如下(中间我还做了别的尝试导致核心3也有处理过中断,但不影响):
24: 2508 35519243 0 127182 GICv2 56 Level eth0
root@ImmortalWrt:~# cat /proc/interrupts | grep eth
24: 2951 35519243 0 127182 GICv2 56 Level eth0
root@ImmortalWrt:~# cat /proc/interrupts | grep eth
24: 3362 35519243 0 127182 GICv2 56 Level eth0
root@ImmortalWrt:~# cat /proc/interrupts | grep eth
24: 4339 35519243 0 127182 GICv2 56 Level eth0
root@ImmortalWrt:~# cat /proc/interrupts | grep eth
24: 4549 35519243 0 127182 GICv2 56 Level eth0
root@ImmortalWrt:~# cat /proc/interrupts | grep eth
24: 4751 35519243 0 127182 GICv2 56 Level eth0
root@ImmortalWrt:~# cat /proc/interrupts | grep eth
24: 5463 35519243 0 127182 GICv2 56 Level eth0
root@ImmortalWrt:~# cat /proc/interrupts | grep eth
24: 5914 35519243 0 127182 GICv2 56 Level eth0
root@ImmortalWrt:~# cat /proc/interrupts | grep eth
24: 6282 35519243 0 127182 GICv2 56 Level eth0
root@ImmortalWrt:~# cat /proc/interrupts | grep eth
24: 6621 35519243 0 127182 GICv2 56 Level eth0
root@ImmortalWrt:~# cat /proc/interrupts | grep eth
24: 7103 35519243 0 127182 GICv2 56 Level eth0
root@ImmortalWrt:~# cat /proc/interrupts | grep eth
24: 7270 35519243 0 127182 GICv2 56 Level eth0
结果就是,改了之后中断就全都被核心 0 处理掉了,并没有实现中断平均。哎,这就很奇怪了。
解决方案:
通过命令:ethtool -l eth0
输出:
Pre-set maximums:
RX: 0
TX: 0
Other: 0
Combined: 0
Current hardware settings:
RX: 1
TX: 1
Other: 0
Combined: 0
即:咱们的 eth0 网卡接口只有单一接收队列和单一发送队列。这就是为什么多核心中断分配不起作用的主要原因。只能一个核干活,别的就站着看。
那现在只能通过软件手段来控制一下,调整一下内核的参数,尽可能让别的核心都动起来。
启用软件RPS(接收包分流),让内核在中断处理后分散处理网络包:
echo f > /sys/class/net/eth0/queues/rx-0/rps_cpus
echo 8192 > /proc/sys/net/core/rps_sock_flow_entries
echo 8192 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt
这里的值从小开始尝试,比如 4096,过大可能反倒网速会变慢。嗯,就这样吧。
以后再有需求,优先考虑网卡的 RSS
队列这个参数,相对来说更重要一点。
失败尝试
环形缓冲区设置
root@ImmortalWrt:~# ethtool -g eth0
Ring parameters for eth0:
Pre-set maximums:
RX: 1024
RX Mini: 0
RX Jumbo: 0
TX: 1024
Current hardware settings:
RX: 512
RX Mini: 0
RX Jumbo: 0
TX: 512
这里我通过命令发现缓冲区还有可增大的空间,ethtool -G eth0 rx 1024 tx 1024
通过该命令修改之后就崩掉了,所有接口全部下线了,包括拨号到的IP也没有了,遂放弃。
总结
完结撒花!!!