千兆网卡(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 该怎么设置的问题,参考这个文档就好了。在具体设置的时候,还是发现不少问题,接下来一篇博客会解释。

  • Pingback: 10G(82599EB) 测试优化(中断处理) | Jasey Wang()

  • eleven.i386

    “其实,要使用 MSI/MSI-X 无非是为了做 affinity,如果是多队列的网卡就没有这个问题了” 不是很明白, 是多队列网卡就不需要做亲和力,还是什么, 另外我想问下, tg3驱动是否支持udp协议的 ip+port 的hash, 我看网上bnx2 是不支持这样的hash , 结果导致 做了亲和力之后 udp协议下 网卡中断依然集中在一个cpu core上, 有啥解决办法么?

    • http://jaseywang.me/ Jasey Wang

      1. 多队列相对高端,比如千兆的 tg3,以及绝大多数的 10G,这个做 affinity 就很简单,一个 core 一个 interrupt 就好了。
      2. tg3 可能是支持你说的那种情况的,具体的还要看下官方的 spec,我们用的都是 tcp 的没用过 udp 的。

      • eleven.i386

        我的BCM5720 默认没开启rxhash 功能. 而且貌似也不支持这个功能, ethtool -K eth1 rxhash on 提示我操作不被支持.. 唉,