在许多商业应用场景下,使用linux来搭建路由器是一种可选的方案。在这篇博文中,我们将探讨在对称多处理器(SMP)架构下,对多队列网卡进行调优,以使其获得最佳的包转发性能。在这个过程中,我们将利用linux内核的一些特性,比如Receive Packet Steering (RPS)、Transmit Packet Steering (XPS)、IRQ affinity(均中断)。
i350网卡实现了自己的hash逻辑,以至于(在接受端)同一个流的数据包将会有同一个队列持续分发。在发送端,则是由网络协议栈来完成这个工作。通过建立这个流/队列的亲和性,把队列绑定到不同的cpu上,从而实现流/cpu的亲和性。这种方法能够换来性能上的提高,是因为,它在根本上导致了网络流与cpu缓存的亲和性,减轻了每个cpu cache的压力。因为每个队列(或者是在这某些情况下出现的队列对)与一个硬中断相关联,处理这些中断响应会同样的分布在不同的cpu上。
igb驱动明智地将每个网口-方向的(rx或tx)队列数据减小到逻辑cpu的数量。减少的原因是每个队列都会导致cpu的性能瓶颈,如果队列的数据比cpu的数量大,将不会对性能提升带来好处。在我们的测试系统中,我们使用一个支持超线程的6核志强cpu,默认情况下就会呈现出来的12个逻辑cpu。因为实际上,在cpu芯片上只有6个物理的L1缓存,并且我们的目的是创建网络流与cpu缓存的亲和性,于是我们禁用了超线程。这样就给我们剩下了6个逻辑cpu,每个网卡上则设置了与之相对应的各个方向(发送和接收)上的6条队列。
让我们先开始配置网卡RPS,首先以eth1的队列0为例,与RPS功能相关的配置项在/sys/class/net/eth1/queues/rx-0/rps_cpus。在这个路径中,eth1是网卡名,rx-0为接收队列0,rps自然是代表RPS。对于XPS来说,对于相应的发送队列,rx-0变为tx-0,rps则变为xps。为了显示eth1下的可用队列,可用简单的列出目录/sys/class/net/eth1/queues下的文件。
继续讨论中断的亲和性,相关的配置文件在/proc/irq/*/smp_affinity,其中*代表(硬)中断号。你可以通过阅读/proc/inerrupts中的内容找到相应的硬件中断号。在一些情况下,发送和接收队列搭配起来平分中断作业。无论如何,我们关心的是控制网络队列的cpu亲和力,而不是主网络设备。在/proc/interrupts的输出中,可以很直观的通过队列名来定位中断号。对于未成对搭配的队列,它们会简单的命名为eth1-rx-0和eth1-tx-0,搭配成对的队列则会显示为eth1-TxRx-0.
RPS、XPS和IRQ亲和性的配置很简单,直接向相关的配置文件中写入一个16进制数字,代表cpu分配网络队列中断响应的位图。0是默认值,其含义根据不同的内核版本有所差异(之后将讨论)。在我们的测试路由器上,拥有6个cpu核,可以向配置文件中写入的范围是二进制的000000到二进制的111111。最右侧(最小值)位代表第0号cpu。例如,我们想分配第5号cpu,则需要向相关的配置文件中以16进制的形式20,写入二进制值100000。
我们使用内核版本是3.2.39-2的Debian发行版,默认情况下,这个内核将所有的网络负载交给第一个cpu处理,导致了低下的包转发性能,当网络流量达到558k包/秒的时候,就会开始发生丢包现象。到了1.6M包/秒的输入,丢包率高达20%。之后,我们通过修改CPU、中断、队列相关的亲和性进行对比测试。将网卡的负载分配到6个不同的cpu,获得了最好的包转发性能,并且消除了丢包的现象:
然后,这样的配置导致了用户态性能开销的大幅度增大,包括ssh终端会话的操作时延变长,其实这时网络并没有出现拥塞。将网络负载分发到6个cpu中的5个上(留下一个cpu用来运行其他程序),减轻了用户态的性能问题,但是,将问题留给了如何去处理剩下的第6号队列。
Intel的官方igb驱动支持减少队列数,通过加装驱动的时候设置RSS参数。但是,在当前的官方linux内核中的igb驱动,并不支持这个调优参数。所以,我们自己在驱动程序中实现了一个等价的参数,以便允许减少队列的数据到5,实现如下的分发方式:
通过释放第一个cpu,戏剧性的提高了用户态的性能。然而,另外一个问题,我们认识到Linux路由cache(即目的[dst]cache,或者路由信息库[rib])的性能.我们认识到,当大量的数据包携带端点地址通过这个系统,这个cache很容易被堵塞,产生了目的cache溢出的内核信息警告。这个cache看起来不能提供持续性能的性能。与普通的路由表查找相比较。
我们得知,在linux内核版本3.8,将会弃用并删除掉路由cache,所以我们在3.8版本的内核上继续我们的实验。在vanilla linux 3.8.5内核版本上,默认情况下,cpu、中断已经被优化了。我们注意到/proc/interrupts中,出现了一些奇怪的配置,说明已经被优化了:
在fedora 18发行版,使用了3.8.5-201.fc18内核,我们发现了更优化的一个默认配置,每个网卡都相同:
这些表格显示配置cpu/中断亲和性,而cpu/队列的亲和性不是必需的。因为cpu/队列亲和性(RPS和XPS)的sysfs文件显示它们的默认值为0,并且,通过观察网络负载下的cpu工作情况,可以发现已经处于平衡状态,这说明在默认的cpu/队列亲和性与上述的cpu/中断亲和性相似或者相同。
https://greenhost.nl/2013/04/10/multi-queue-network-interfaces-with-smp-on-linux/