10G(82599EB) 网卡测试优化(ethtool)

 

ethtool,主要涉及 NIC 的本身比如 ring buffer,内容还是蛮多,不少跟硬件的特性相关,分几个大方向说。

speed,duplex 这类的是非常基本的设置,不在这里说了。需要注意的是,能 auto 的尽量 auto,因此,正常情况下,Auto-negotiation 应该是 on 状态。这里说明了原因。
上面这些就是不加任何的参数获取到的基本的设置。


1. receive(RX) ring buffer size:
# ethtool -g eth2
这个 gist 列举了几个主流设备的 rx 值,包括 BCM5720, I350 在内,当然还有 82599EB。

buffer 越小 latency 也越低,与之带来的是 throughput 的下降,也就是说,buffer 小带来的是丢包而大了带来的则是 latency。丢包的问题,一个是在 nic 层面丢了,也就是 ifconfig 看到的,一个则是在 tcp 协议栈看到的丢包。前者产生丢包很有可能就是 ring buffer 设置的太小的缘故。但是,并不是越大越好,尤其对于实时的流媒体流量来说。

可以适当的增加 ring buffer:
# ethtool -G eth0 rx 1020

一般来说,在 latency 本来就比较小的情况下,适当的增大 buffer 并不会带来明显的影响,除非是一些对 latency 极度敏感的交易场所、流媒体等。因此,这又是一个 throughput 跟 latency 的 tradeoff。 对于 rx, tx 的设置,并没有一个通用的公式,还是需要在实际环境中测试。
注意: -g 看到的只是 buffers 的数量,而非 size。


2. coalescing
interrupt coalescing 主要是用来做 latency 跟 cpu overhead 之间的 trade-off。当 adapter 收到一个 frame 之后,不会立即的对系统产生中断,而是等一段时间,收集到更多的包之后再一次性的处理,这会降低 cpu 的负载,但是会产生 latency。要查看当前的 coalescing,可以:
# ethtool  -c eth2 | grep "rx-usecs:"
rx-usecs: 1

interrupt coalescence 也叫 interrupt Moderation, Interrupt Blanking, or Interrupt Throttling。这个在 ixgbe 的参数列表里面也可以看到:
parm:           InterruptThrottleRate:Maximum interrupts per second, per vector, (0,1,956-488281), default 1 (array of int)


关于 rx-frames[-irq] rx-usecs[-irq] tx-frames[-irq] tx-usecs[-irq] 的解释,可以看这里

可以使用下面这个命令来修改当前的值:
# ethtool -C eth2 rx-usecs VALUE
rx-usecs 会同时控制 tx 以及 rx 方向的 coalescing。值越低的,interrupt coalescence 越不容易发生,latency 越小,相应的,cpu 负载也会越大。如果增加了 rx-usecs,对于 bulk traffic 会比较好,但是会对 tcp 的性能造成大的损失,可以通过调大 TSO window divisor(默认为 3) 来弥补:
net.ipv4.tcp_tso_win_divisor = 30

前提需要开启 tso:
# ethtool -K eth2 tso on


下面这组 coalescing 测试关闭了 tcp win scaling, jumbo frame。在开启了 tcp win scaling 的情况下几乎看不到什么效果,如果关闭了这个特性,可以很明显的看到效果:
# sysctl net.ipv4.tcp_window_scaling = 0
# ifconfig eth2 mtu 1500

# for j in $(cat remote); do ssh root@10.18.103.202 ethtool -C eth2 rx-usecs $j; sleep 20; time for i in $(cat rx-usecs); do ethtool -C eth2 rx-usecs $i; sleep 60; netperf  -H 192.168.10.2  -t TCP_STREAM -c -C -l 10 >> $j ;  done; done
横行代表 server rx-usecs 的值,从 1 到 99 变化,竖行代表 client 的值,这里仅列出几列的 server 的值,完整的可以看这里:
c\s      1      5       10     15     20        25      30      35   
1  2041.01 4077.18 4075.96 4077.64 4078.49 4078.23 4077.77 4077.55
5  4076.88 8840.97 8806.59 8570.26 6482.82 6517.91 5526.49 5658.80
10 4065.66 4953.04 8212.56 7655.45 6282.05 6270.99 5515.62 4999.63
15 4073.37 4933.31 7706.01 7030.65 6336.81 6136.97 5518.46 5028.43
20 4074.41 6919.17 6797.47 6601.73 6026.18 5814.38 5529.56 5025.87
25 3979.94 4850.50 6356.66 5837.68 5938.91 5455.21 5445.15 5145.08
30 4074.61 4782.81 5620.04 5523.55 5691.91 5536.58 5438.79 4973.76
35 4074.41 4735.46 6397.14 5435.40 5749.65 5370.08 4969.28 4878.18
40 4074.48 4145.26 5970.30 5824.36 5831.48 5558.44 4649.09 4897.97
45 3627.53 3788.03 5380.55 5589.18 5643.71 5611.31 5374.13 5079.22
50 3676.16 4778.47 4978.26 4992.63 4982.98 4974.82 4968.44 4961.27
55 4060.51 4608.55 4608.00 4678.30 4812.71 4610.97 4606.00 4606.49
60 4068.55 4145.90 4146.48 4666.78 4621.57 4154.13 4148.21 4148.93
65 3196.90 3887.22 3890.80 4271.96 4624.30 3911.47 3891.01 3898.07
70 2878.17 3565.00 3716.94 4315.24 4666.79 4541.56 3655.19 3556.43
75 2749.26 3362.23 3753.65 4650.59 5003.18 4475.72 3899.56 3377.73
80 2812.24 3127.96 3990.63 5196.36 5130.97 4713.21 4208.55 3751.47
85 2664.55 3049.08 4190.36 4871.45 5059.99 4746.92 4125.30 4029.49
90 2722.91 3130.98 4371.66 5446.47 5345.96 4901.87 4504.94 3866.35
95 2667.74 3551.08 5040.66 5195.68 5220.28 4991.77 4624.82 4356.83
99 2588.83 3736.98 4776.17 5061.36 5064.94 4829.90 4880.19 4471.49

默认情况下,rh6.2 的大部分机器的值为 20,少部分的为 3,这个差距可以先放一边,上面的测试可以看到:
* 在没有开启 tcp win scaling, jumbo frame(hd support) 的情况下,效果提升的比较明显,最大的能打到接近 9G(c=5, s=5);当 s 的 rx-usecs 的值达到 100 之后(到 20 就比较明显了),不管 c 调成什么样的值,效果都很差,吞吐基本是在 1G 以下
* 如果同时开启了上面两项,再修改 cs 的值,几乎没有变化,维持在 9.9G 左右,测试没有贴在这里


3. offload
也就是原先由 CPU 完成事被 NIC offload 了。一般用来做 offload 的包括 segmentation 和 checksum。
这篇文档非常详细的说明了 GRO 开启关闭的情况下 TCP/IP 包的结构问题。
假设需要发送一个 7300Bytes 的包,如果在没有开启 GRO,MTU 为 1500 的情况下,减掉 20 Byte 的  IP header 以及 20 Byte TCP header,TCP segment(MSS) 还剩 1460 Byte。因此,7300 的话需要分为 5 个包,并且这 5 个包是从 application layer 到 TCP layer 的过程中就开始切割分装,依次加上 TCP header,IP header 直到最后的 Ethernet frames 发送出去,因此对于 tcpdump 来说是可以抓取到这 5 个包的;但是如果采用了 GRO,由于 7300 被当成一个整数据,依次向下加上 header,而这两个 header 其实一个  template headers,当 driver 生成完这个单一的 Ethernet frame 之后就会发给 NIC,而 tcpdump 最多也只能到 Ethernet frame 这一层,因此接下去由 NIC 负责分割成 5 个包,根据那个 template 为 5 个包分别加上 header 最后发出去。

至于 GRO, TSO 等并不是开启就好,需要根据不同的产品型号结合上面的 app 来判定,比如 Chelsio 的网卡在开启 TSO, TOE 的情况下,WAN 的性能会急剧下降,而在 LAN 里面则不存在此类情况。包括之前 RH6.2 的机器运行 LVS,在开启 GRO 的情况下,同样会出现比较严重的问题。

至于,rx/tx 的 checksum,目前主流的系统都是开启,只有好处没有坏处。


4. nic statics
主要用来做诊断之用,如果网络情况不是很好,可以通过 -S 看看目前的 Diagnostics 包括丢包的情况等等:
# ethtool -S eth2

根据之前经验总结,一般情况下,如果看到了不少 rx_no_buffer_count,则表明需要增加 ring buffer;而如果看到 tx_deferred_ok 表示传输被延迟,不算 errors; rx_missed_errors, rx_fw_discards 这个表示包满了,多出的全被 drop 掉了。

最后,注意,ethtool 只能针对物理端口有效,至于 bond0, tun0 等接口则是无效的。