通过 tcpcopy(pf_ring) 对 BCM 5719 小包做的多组 benchmark

tcpcopy 在文档化、用户参与方式方面有很大的提升空间这个问题在之前已经专门说过。最终,在我们自己阅读代码的情况下,结合 pf_ring,坚持跑通了整个流程,用其对目前 BCM 5719 型号的网卡做了多组对比,结论见结尾。
使用 tcpcopy 做 benchmark,务必确定 tcpcopy 语法使用的正确性, 尽管互联网上绝大多数的文档以及官方文档都写的含糊不清。
比如,我们之前把过滤条件 -F "tcp and dst port 80" 写成了 -F "tcp and src port 80",造成的结果是在错误的基础上得出了一些奇葩的数据以及无法解释的现象,比如到 target server 的流量特别小,并且及其的不稳定,得到的 pps 也是非常的不稳定大到 400kpps/s,小到 20k  甚至 0。

这里列举我们测试环境使用的一组配置。
所有机器都是 RedHat 6.2 2.6.32-279.el6.x86_64,Tcpcopy 1.0 版本,PF_RING 6.0.1,BCM 5719,双网卡 bonding。另外,我们单台生产机器的流量都比较大,并且绝大多数都是 100B 以下的小包,所以对系统的要求还是比较高的。
为了避免后续的误解,先确定几个用语:
1. online server(OS): 即我们线上生产环境的机器
2. target server(TS): 是我们想做 benchmark 的那台机器,以测试其究竟能支撑多大的量
3. assistant server(AS): 是安装了 intercept 的机器
4. mirror server(MS): 通过 tcpcopy 的 mirror 工具把 OS 的流量复制到该台机器上

我们一共做了三大组 benchmark,每组下面包含若干小的 benchmark,包括:
1. tcpcopy + intercept
2. tcpcopy + intercept + tcpcopy mirror,加一个 mirror 是为了减少对 OS 的负载,这样 tcpcopy 在 MS 上运行
3. tcpcopy + intercept + 交换机 mirror,更直接的方式复制线上流量,保证对 OS 没有干扰,并且能保证 100% 全量复制 OS 的流量

Continue reading

50M 流量搞死 BCM57xx(NetXtreme I Server) 网卡

BCM 网卡质量渣的问题已经延续好多年了,12 年我写过一篇《BCM 5709 网卡》的博客记录 BCM 驱动的各种问题。
最近我们又遇到因为 BCM 扛不住小包(small packet)导致 nic 狂 drop 的问题,即使升级到最新的版本依然不行。当然这个很大一部分责任归结于我们,在产品上线之初没有做一个这方面的调研。
为什么 BCM 网卡会有这么多关注?目前主流的服务器厂商默认情况下都是 ship 的 broadcom 的网卡,市场占有率最大的 Dell,HP 无一都不是跟他们合作的,如果要使用其他品牌比如 Intel igb,大部分情况下需要单独采购,并且成本相比 Broadcom 会高出不少。这里是官方的价格列表(1, 2)。  
在正常情况下,BCM 的也能凑活着用,并不会引起很大的问题,比如跑的是一些正常服务。但是如果大量的小包,BCM 就彻底废了,尤其遇到只有 4 个队列的 BCM5719。所以,我标题写的并不是那么准确,仅仅是为了强调下其性能的巨大弱势。

上一篇博客我推荐了几款做发包测试的工具,通过他们,可以很明显的对比出差异。对于网卡的性能测试,收发包的性能跟带宽的吞吐相比更加重要,当然二者还是要看适用的场景。
以发 64B 的小包为例,BCM 的在 200Kpps/s 的时候就都废了,相比之下,同样的环境,I350 在 600Kpps/s 的时候仅仅有很少的丢包,准确的说是伴随着 rx_fifo_errors 的 overruns,各个厂家实现的方式不大一样,反映到 OS 层面就比较麻烦了,有的是 dropped 有的是 overruns。

下面两张图是我们某台接受大量小包(~70B)的服务器,可以看到,200Kpps/s 时候表现就一塌糊涂了,导致系统的 rt 非常大甚至直接 timeout。

50M 就能搞死一台 BCM5719/20 机器的说法毫不夸张。

服务器网卡收包性能测试

之前写过不少跟网络相关的 benchmark,比如:
* 《网络质量评估
* 《10G(82599EB) 网卡测试优化(总)

上面的更多的是放在带宽使用率上,即如何尽可能的打满,但是都遗漏一个重要的细节,那就是 packet/s,这个论坛的作者一语中的:
– how many packets/sec you have. In fact, network throughput mostly depends on packets/sec, not bytes/sec

可能对于大部分的应用来说,根本无需关注每秒钟到达的包的数量甚至大小,但是对于某些应用来说,这些指标是至关重要的。

要对包(大小、数量、时间)方面的指标做 benchmark,iperf, netperf 之类的就没法用了,他们只能测试带宽,经过一天的使用比较发现下面的一些工具能基本满足需求。要快速的上手的话还是需要对 tcp/ip 有比较深入的了解,比如 ip header,tcp header 之类的,再比如最小的 frame 应该是 64B,这也是众多网络设备厂商做包转发测试的基础,不明白的看下面两张(1, 2)图就清楚了。

跟网络厂商一样,我们也重点关注小包(0-75)的性能,至于小包如何定义,没有严格的标注,我上面的 0-75 也仅仅是从 iptraf 拿到的一个范围,最终还是要根据业务来定。
一般而言,frame(fps) 是针对 data-link(Ethernet) 而言,packet(pps) 是针对 IP 层而言,segment 是针对 TCP 层而言。

Continue reading

千兆网卡(bnx2, tg3, igb) 的 MSI/MSI-X

几个主流网卡的 lspci 都列在了 gist 上:
* Intel 350 igb
* Broadcom 5709 bnx2
* Broadcom 5716 bnx2
* Broadcom 5720 tg3

broadcom 网卡,bnx2(BCM5706/5708/5709/5716), tg3(BCM5720) 驱动的有一个叫 MSI, MSI-X(Message Signaled Interrupt) MSI/MSI-X 的功能,可以取代原有的 Pin-based(8259A?) 的中断方式,在一定程度上提高系统的性能。 对于 MSI/MSI-X 来说,可能由于各种各样的原因没有被开启,比如在 bnx2 在 rhel 5 上就无法使用。 所以在使用这个特性之前,需要先确认清楚。如何确定 PCIe 使用了 MSI/MSI-X?通过 lspci 即可,一般情况下,在跟 MSI 相关的条目后面都会有个 "Enable" 的 flag,后面的 "+" 代表开启,"-" 代表禁用,下面这个是 rh6.2(2.6.32-279.el6.x86_64, 3.122 tg3):
# lspci  -v  | grep -i msi
        Capabilities: [90] Express Root Port (Slot-), MSI 00
        Capabilities: [60] MSI: Enable+ Count=1/2 Maskable+ 64bit-
        Capabilities: [90] Express Root Port (Slot-), MSI 00
        Capabilities: [60] MSI: Enable+ Count=1/2 Maskable+ 64bit-
        Capabilities: [90] Express Root Port (Slot-), MSI 00
        Capabilities: [60] MSI: Enable+ Count=1/2 Maskable+ 64bit-
        Capabilities: [90] Express Root Port (Slot-), MSI 00
        Capabilities: [60] MSI: Enable+ Count=1/2 Maskable+ 64bit-

或者通过 dmesg 也能看出来。
tg3 的 driver, rh6.2(2.6.32-279.el6.x86_64, 3.122 tg3):
# lspci | grep -i msi
[    3.660959] ahci 0000:00:1f.2: irq 116 for MSI/MSI-X
[    4.133211] megaraid_sas 0000:03:00.0: irq 117 for MSI/MSI-X
[    4.133226] megaraid_sas 0000:03:00.0: irq 118 for MSI/MSI-X

[    7.029578] tg3 0000:01:00.0: irq 134 for MSI/MSI-X
[    7.029598] tg3 0000:01:00.0: irq 135 for MSI/MSI-X
[    7.029612] tg3 0000:01:00.0: irq 136 for MSI/MSI-X
[    7.029627] tg3 0000:01:00.0: irq 137 for MSI/MSI-X
[    7.029641] tg3 0000:01:00.0: irq 138 for MSI/MSI-X

bnx2 的 driver, ubuntu 10.04.2(2.6.32-38-server, 2.0.2 bnx2):
# dmesg  | grep -i msi

[    4.691776] bnx2 0000:01:00.1: irq 61 for MSI/MSI-X
[    4.691785] bnx2 0000:01:00.1: irq 62 for MSI/MSI-X
[    4.691793] bnx2 0000:01:00.1: irq 63 for MSI/MSI-X
[    4.691801] bnx2 0000:01:00.1: irq 64 for MSI/MSI-X
[    4.691810] bnx2 0000:01:00.1: irq 65 for MSI/MSI-X
[    4.691819] bnx2 0000:01:00.1: irq 66 for MSI/MSI-X
[    4.691827] bnx2 0000:01:00.1: irq 67 for MSI/MSI-X
[    4.691836] bnx2 0000:01:00.1: irq 68 for MSI/MSI-X
[    4.691844] bnx2 0000:01:00.1: irq 69 for MSI/MSI-X
[    4.755025] bnx2: eth1: using MSIX


还有种通用的方式,直接查看 interrupts 文件,看关键字 MSI 就知道了:
# grep -i msi /proc/interrupts

由于之前遇到不少 bug,以上的内核都是升级过的,并非发行版本默认的内核。

但是到目前为止,很不幸的是,在主流的硬件厂商中,都表现的不是很好,各种 bug,需要禁用。可以从 kernel 的 config 中禁用再编译(CONFIG_PCI_MSI, X86_UP_APIC/SMP),或者从 driver 层面禁用。

最简单的关闭方式可以直接写到 modeprobe 里面:
# cat /etc/modprobe.d/msi.conf
options bnx2 disable_msi=1
# modprobe -r bnx2
# modprobe bnx2

以上仅仅是针对 bnx2 这个 driver 的,对于 tg3 的 driver,不支持像 bnx2 那样关闭,可以直接传递到内核的启动参数里面::
pci=nomsi
上面这个是对整个系统生效而非仅仅 tg3,所以如果使用了上面的方式,其他诸如使用到 MSI 的 megasas 也会失效。

最后,intel 的网卡也存在类似的问题

其实,要使用 MSI/MSI-X 无非是为了做 affinity,如果是多队列的网卡就没有这个问题了。如何查看网卡是否支持多队列,最简单的是从 interrupts 文件查看,或者看产品手册,一般都会写的很明确,multiple queue, rss 等关键字。如果该 NIC 不支持 MSI-X,那显然就不支持多队列了。目前主流的千兆应该都是支持的,最起码上面提到的几个都是支持的,差别在于支持多少的问题,比如 5720 只支持 5 个 queue,这个是写死在 driver 里面,无法改变的,有兴趣的可以看看 drivers/net/tg3.h 文件的宏定义:
#define TG3_IRQ_MAX_VECS_RSS        5

至于那些 bitmask 该怎么设置的问题,参考这个文档就好了。在具体设置的时候,还是发现不少问题,接下来一篇博客会解释。

基础网络升级(三)

前两篇(1, 2)基本覆盖了此次升级的整个思想以及操作过程包括一些细节的涉及,不过在升级完之后,我们部署在老机房的监控系统发现,从老到新的中间的链路的质量比较差,三层之间路由接口的丢包很严重:
# ping IP_NEW repeat 8000

平均会丢 100+ 个包,丢包率超过了 1%,从监控到对端服务器的丢包就更严重了,平均都在 10%,峰值能达到 80%,注意这是两个打通的内网,我们也因此几乎无法登录到新机房的服务器进行操作,即使进去了,ssh 也是『卡』的让人随时受不了,网页完全打不开。丢包没有任何的时间特征,几乎是全天候。花了很长的时间 debug 确认了应该不是我们的问题之后,目光转移到了我们的服务商那里,猜测可能是中间链路的光纤或者连接器之类的问题。

期间,由于不稳定造成了几次很严重的网络中断。后来,对方的工程师也承认这根光纤衰减跟正常的偏差较大。最终决定更换这根光纤。

结果可想而知,下图是我们新机房某台交换机的 ping latency,效果很明显。

有时候我们会太天真的认为,光纤是很稳定的,正常情况下,是不可能出问题的,不过偏偏就是中了。

事后也进行了一些讨论包括 post-mortem,不过都是些治标不治本的点到为止,尽管我对此事非常的关注甚至『恼火』,在跟对方的邮件沟通中措辞非常的严厉,不过也只是搔搔痒罢了,我能做的就这么多。
当然,上面一系列的工作不属于我的工作范畴,既然做了就把他做好,至于有些不该知道的,就装作不知道好了。这个基础升级就写到这里为止,再下去就真的要到非技术层面了。

r8169 网卡驱动

某台 11.10  3.0.0-12-generic 的机器网络异常,ifconfig 有大量的丢包,ssh 时不时 hung 住:
# ifconfig
eth0      Link encap:Ethernet  HWaddr 44:44:d6:b4:1e:7e
          inet addr:10.18.102.201  Bcast:10.18.102.255  Mask:255.255.255.0
          inet6 addr: fe80::5604:a6ff:feb4:1e7e/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:21274 errors:0 dropped:21274 overruns:0 frame:21274
          TX packets:12028 errors:0 dropped:81 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:9653617 (9.6 MB)  TX bytes:2188437 (2.1 MB)
          Interrupt:46 Base address:0xc000

syslog 有大量的如下信息:
Oct 10 11:21:29 jaseywang kernel: [  905.012397] r8169 0000:04:00.0: eth0: link up
Oct 10 11:21:32 jaseywang kernel: [  908.289727] r8169 0000:04:00.0: eth0: link up
Oct 10 11:22:19 jaseywang kernel: [  954.627060] r8169 0000:04:00.0: eth0: link up
Oct 10 11:23:20 jaseywang kernel: [ 1015.182140] r8169 0000:04:00.0: eth0: link up
Oct 10 11:23:37 jaseywang kernel: [ 1033.004186] r8169 0000:04:00.0: eth0: link up
Oct 10 11:24:16 jaseywang kernel: [ 1071.335548] r8169 0000:04:00.0: eth0: link up
Oct 10 11:25:02 jaseywang kernel: [ 1117.070819] r8169 0000:04:00.0: eth0: link up
Oct 10 11:25:42 jaseywang kernel: [ 1156.881366] r8169 0000:04:00.0: eth0: link up
Oct 10 11:26:13 jaseywang kernel: [ 1188.351029] r8169 0000:04:00.0: eth0: link up
Oct 10 11:26:43 jaseywang kernel: [ 1217.619851] r8169 0000:04:00.0: eth0: link up
Oct 10 11:26:50 jaseywang kernel: [ 1225.107516] r8169 0000:04:00.0: eth0: link up
Oct 10 11:26:52 jaseywang kernel: [ 1227.069138] r8169 0000:04:00.0: eth0: link up
Oct 10 11:26:54 jaseywang kernel: [ 1228.735701] r8169 0000:04:00.0: eth0: link up
Oct 10 11:26:56 jaseywang kernel: [ 1231.040210] r8169 0000:04:00.0: eth0: link up
Oct 10 11:27:28 jaseywang kernel: [ 1262.864740] r8169 0000:04:00.0: eth0: link up
Oct 10 11:28:07 jaseywang kernel: [ 1302.013430] r8169 0000:04:00.0: eth0: link up

更换网线无果,想到可能是网卡驱动的问题,确实是 r8169 这个驱动惹得祸,10 年就有人发现此类问题了。 将其更换为 r8168。下载这个链接的驱动。

卸载当前的 r8169:
# rmmod r8169

解压安装:
# tar zjvf r8168-8.032.00.tar.bz2
# cd r8168-8.032.00/
# ./autorun.sh

完毕,检查确认:
# lsmod  | grep r8168
r8168                 244911  0

将 r8169 加入 blacklist:
$ cat /etc/modprobe.d/blacklist-r8169.conf:
blacklist r8169

基本是把这个的链接翻译了一遍。这篇文章也确认了在 Ubuntu 的 10.10, 11.04, 11.10 版本在使用 kernel 默认的驱动时上会出现此类的问题。