10G(82599EB) 网卡测试优化(中断处理)

这里主要涉及的是 core 的绑定问题,有时候不是简单的算几个 bitmask,写几个数字到 smp_affinity/smf_affinity_list 里面就完事了。

在做 affinity 的时候,有下面几点需要注意:
1. 千万千万在不要在做 affinity 的时候开启 irqbalance,否则你刚把 irq 给人肉指定好,他就自动给你給恢复成他那套了
2. 使用 iperf 或者其他的工具做 benchmark 时,需要开启多线程(-P),以满足多个 stream 的要求,否则不管你怎么分布,都只能压在某一个 core 上,造成 affinity 无效的幻觉
3. 能不用 HT 尽量别用,尤其对于 affinity 来说,效果并不明显,比较好的做法是以物理 core 的数量为参照,比如单路 6-core(开启 HT 则 12 core),设置 queue 的数量为 6 而非 12 比较好,具体的还是需要测试

目前,要对 NIC 做 affinity,最好的方式还是 NIC 支持 RSS(Receive Side Scaling) 也就是 multiqueue RX,这样可以很方便的将 irq(RSS) 映射到 core 上。基本上主流的千兆 NIC(bnx2, igb) 都支持,10G 的更是默认配置了,这个上篇已经说过。 各个 bitmask 的问题,不在这里说了。

在 interrupts 文件里面,能看到不少的诸如 IO-APIC-level, IO-APIC-edge, PCI-MSI-X 等术语,这些其实是跟各个设备支持的特性相关的,要看他们之间的演变过程,可以看这里

关于 IO-APIC-level 跟 PCI-MSI-X  的区别,是两个完全不同的产生中断的方式,前者(1, 2)  是使用硬件实现,比如 8259A,后者则是往某个特定的 address 里面进行写操作实现中断。
因此,要判断一个设备使用使用了 MSI/MSI-X 很简单,只要查看 interrputs 文件就可以了,IO-APIC-level 非 MSI,PCI-MSI 表示试用了 MSI,这个不仅仅限于 NIC。

而 IO-APIC-fasteoi 跟 IO-APIC-edge 的区别,很好解释。interrupts 触发的方式不同而已,一个是边缘(edge)触发,一个是条件(level)触发。

理解了上面了,可以发现,可能的中断方式基本是下面两种:
1. 将某个 irq 绑定到所有的 core 上
2. 将某个 irq 绑定到某几个 core 上,第一个只是第二个的一个特例
3. 将某个 irq 绑定到指定的某个 core 上

先来看前两种情况。其实就是 RR(round-robin) 的方式,或许能解决一些 bottleneck,但是更严重的问题来了,尤其对于网卡这种中断很频繁的设备来说,会造成 cpu cache missed,造成影响是直接访问内存比访问 cache 里面的内容慢 30x;并且对于流媒体来说,还可能造成 congestion collapse。另外,由于 APIC 的问题,可能无法实现上面的要求,比如,我想将 irq 60 绑定到 core 0 以及  core 1 上,或者想把 irq 67 分布到所有的 core 中,将 3 写入到 60 的 smp_affinity 不就可以了吗?实事是做不到的,并且上面已经说明了这样做没有意义的原因。将 CONFIG_HITPLUG_CPU 由原先的 yes 设置成 no 可能会解决问题,不过我并没有试过,尤其明白了上面将 irq 分布到多个 core 的不合理之处之后更没有必要这样做了。

明白了上面了问题,第三点说的将 irq 绑定到一个特定的 core 上的意义就很明显了。