一个iperf3打udp流量上不去的问题分析

问题现象

在某个嵌入式平台做UDP反向流量测试的时候,发现流量上不去,并且丢包率非常高。

iperf3 -c 162.16.0.1 -b 600m -u -R
Connecting to host 162.16.0.1, port 5201
Reverse mode, remote host 162.16.0.1 is sending
[ 6] local 162.16.0.215 port 45228 connected to 162.16.0.1 port 5201
[ ID] Interval Transfer Bitrate Jitter Lost/Total Datagrams
[ 6] 0.00-1.00 sec 2.06 MBytes 17.3 Mbits/sec 0.600 ms 93125/94616 (98%)
[ 6] 1.00-2.00 sec 2.23 MBytes 18.7 Mbits/sec 0.636 ms 51638/53256 (97%)
[ 6] 2.00-3.00 sec 1.86 MBytes 15.6 Mbits/sec 0.659 ms 50717/52064 (97%)
[ 6] 3.00-4.20 sec 1.28 MBytes 8.96 Mbits/sec 20.741 ms 49359/50287 (98%)
[ 6] 4.20-5.00 sec 1.19 MBytes 12.5 Mbits/sec 0.945 ms 53518/54382 (98%)
[ 6] 5.00-6.12 sec 2.04 MBytes 15.3 Mbits/sec 16.536 ms 47297/48777 (97%)
[ 6] 6.12-7.00 sec 1.45 MBytes 13.8 Mbits/sec 8.949 ms 44629/45679 (98%)
[ 6] 7.00-8.00 sec 1.73 MBytes 14.5 Mbits/sec 0.901 ms 59480/60735 (98%)
[ 6] 8.00-9.05 sec 2.00 MBytes 16.1 Mbits/sec 9.359 ms 50948/52397 (97%)
[ 6] 9.05-10.00 sec 1.45 MBytes 12.7 Mbits/sec 1.580 ms 50707/51756 (98%)

                                                • -

[ ID] Interval Transfer Bitrate Jitter Lost/Total Datagrams
[ 6] 0.00-10.99 sec 786 MBytes 600 Mbits/sec 0.000 ms 0/569210 (0%) sender
[ 6] 0.00-10.00 sec 17.3 MBytes 14.5 Mbits/sec 1.580 ms 551418/563949 (98%) receiver

iperf Done.

调整一些参数的尝试

调整linux的一些参数

echo 4194240 > /proc/sys/net/core/rmem_max
echo 4194240 > /proc/sys/net/core/wmem_max
echo '4096 87380 4194240' > /proc/sys/net/ipv4/tcp_rmem
echo '4096 65538 4194240' > /proc/sys/net/ipv4/tcp_wmem
echo '4194240 4194240 4194240' > /proc/sys/net/ipv4/tcp_mem
echo 196608 > /proc/sys/net/core/rmem_default
echo 196608 > /proc/sys/net/core/wmem_default
echo 1000 > /proc/sys/net/core/netdev_budget
echo 3000 > /proc/sys/net/core/netdev_max_backlog

调整这些参数都不起作用。

调整iperf3的参数

使用iper3的 -W参数调大socket缓冲区大小也没用。

调试分析

linux的一些参数的观察

中断

通过cat /proc/interrupts观察到,这个系统网络中断只发生在CPU0上面,该系统不支持smp irq affinity.

softirq

通过cat /proc/softirqs观察到,NET_RX软中断主要发生在CPU0上面。
通过mpstat命令发现软中断占用CPU0达到100%

15:20:24 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle
15:20:25 all 1.06 0.00 4.76 0.00 0.00 53.97 0.00 0.00 40.21
15:20:25 0 0.00 0.00 0.00 0.00 0.00 100.00 0.00 0.00 0.00
15:20:25 1 3.33 0.00 10.00 0.00 0.00 2.22 0.00 0.00 84.44

使用perf分析cpu耗在哪里

perf record -e cpu-clock iperf3 -c 162.16.0.1 -b 200m -u -R -t 100
perf report

得到的结果

35.87% iperf3 [kernel.kallsyms] [k] nf_inet_local_in
8.62% iperf3 [kernel.kallsyms] [k] __arch_local_irq_restore
3.61% iperf3 [kernel.kallsyms] [k] __copy_user_common
3.41% iperf3 [kernel.kallsyms] [k] handle_sys
3.21% iperf3 [kernel.kallsyms] [k] do_select
3.21% iperf3 [kernel.kallsyms] [k] tcp_poll
2.81% iperf3 libc-2.24.so [.] memcpy
2.61% iperf3 [kernel.kallsyms] [k] __bzero
2.61% iperf3 [kernel.kallsyms] [k] ipt_do_table

可以看到nf_inet_local_in占用了最多的cpubian。经过排查,这是某个netfilter内核模块注册的hook函数。把该模块移除后性能变好。
除了nf_inet_local_in,ipt_do_table也占用了很多CPU,这是因为该系统设置了大量的iptables rule,把他们清空,情况变得更好。

iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
iptables -t nat -F
iptables -t mangle -F
iptables -F
iptables -X
iptables -X -t nat
iptables -X -t raw

更进一步的尝试

irq smp affinity

该系统不知道硬中断的smp affinity

soft irq

如果启用RPS并且设置RFS,iperf3用参数'-P 2'的话,流量能提高30-50M。

echo 3 > /sys/class/net/waninterface/queues/rx-x/rps_cpus
echo 32768 > /sys/class/net/waninterface/queues/rx-X/rps_flow_cnt

这个时候如果查看/proc/softirqs,发现两个CPU上面的软中断都有增加。
在这个基础上如果在调整上文提到的linux的一些参数,流量能达到300Mbits/sec

参考文章

https://ylgrgyq.github.io/201...
https://ylgrgyq.github.io/201...
https://blog.packagecloud.io/...
https://colobu.com/2019/12/09...
http://www.brendangregg.com/p...
https://tqr.ink/2017/07/09/im...

你可能感兴趣的:(linux-kernel,networking)