多队列网卡及RPS/RFS/XPS设置

您所在的位置:网站首页 rps使用气体 多队列网卡及RPS/RFS/XPS设置

多队列网卡及RPS/RFS/XPS设置

2024-07-16 23:42| 来源: 网络整理| 查看: 265

1、关于多队列网卡

通过lspci方式查看网卡信息,如果有MSI-X, Enable+ 并且Count > 1,则该网卡是多队列网卡,多队列网卡内部会有多个 Ring Buffer。

[root@localhost ~]# lspci -vvv | grep -A50 "Ethernet controller" | grep -E "Capabilities|Ethernet controller" 01:00.0 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01) Capabilities: [40] Power Management version 3 Capabilities: [50] MSI: Enable- Count=1/1 Maskable+ 64bit+ Capabilities: [70] MSI-X: Enable+ Count=10 Masked- Capabilities: [a0] Express (v2) Endpoint, MSI 00 Capabilities: [e0] Vital Product Data

从以上信息可见,我们的这张网卡是支持多队列的。

2、网卡支持最大队列数及当前使用队列

我们可以通过ethtool命令查看网卡支持的最大队列数,

[root@localhost ~]# ethtool -l eth0 Channel parameters for eth0: Pre-set maximums: RX: 0 TX: 0 Other: 1 Combined: 63 Current hardware settings: RX: 0 TX: 0 Other: 1 Combined: 40

由上可见,该网卡最多支持63个队列,当前使用了40个队列。为什么不开启63个队列呢,因为机器的CPU数没那么多,

[root@localhost ~]# cat /proc/cpuinfo | grep processor | wc -l 40

我们开启多队列的初衷就是为了利用多核。队列数和CPU相等,正好可以每个CPU处理一个队列,这样效率比较高。

3、修改网卡队列数

有时候网卡支持多队列却没有开启,那么就要手动设置网卡队列数,

ethtool -L eth0 combined 8

其中combined指的是网卡收发队列共用的情况,有些网卡可单独设置收发队列,

ethtool -L eth0 rx 8 ethtool -L eth0 tx 8

设置后可以在/sys/class/net/eth0/queues/目录下看到对应的队列,

[root@localhost ~]# cd /sys/class/net/eth0/queues/ [root@localhost queues]# ls rx-0 rx-2 rx-4 rx-6 tx-0 tx-2 tx-4 tx-6 rx-1 rx-3 rx-5 rx-7 tx-1 tx-3 tx-5 tx-7 4、多队列网卡绑核

为了保证CPU均衡,也即是网卡中断能分配到各个CPU,我们通常会将网卡中断绑核,具体操作见——网卡中断均衡设置

5、单队列网卡

上面说的都是多队列网卡,那单队列的怎么搞呢,不能厚此薄彼吧。这时候就出现RPS和RFS了。简单来说就是在软件层面模拟多队列的情况,从而达到CPU均衡。

RPS(Receive Packet Steering)把软中断的负载均衡到各个cpu,是在单个CPU将数据从Ring Buffer取出来之后开始工作,网卡驱动通过四元组(SIP,SPORT,DIP,DPORT)生成一个hash值,然后根据这个hash值分配到对应的CPU上处理,从而发挥多核的能力。

但是还有个问题,由于RPS只是把数据包均衡到不同的cpu,但是收包的应用程序和软中断处理不一定是在同一个CPU,这样对于cpu cache的影响会很大。因此就出现RFS(Receive flow steering),它确保应用程序和软中断处理的cpu是同一个,从而能充分利用cpu的cache,这两个补丁往往都是一起设置,以达到最好的优化效果。

6、设置RPS

首先内核要开启CONFIG_RPS编译选项,然后设置需要将中断分配到哪些CPU,

/sys/class/net//queues/rx-/rps_cpus

比如,要将eth0上0号收包软中断均匀分配到64个CPU上(假设机器上有这么多CPU),那么可以如下操作,

echo "ffffffff,ffffffff" > /sys/class/net/eth0/queues/rx-0/rps_cpus

和多队列中断绑定规则类似,每个CPU用1位表示,因此1,2,4,8分别对应0-3号CPU,分配到这些CPU,相加就是15,即f。

如果只想分配到前32个CPU,则可以如下操作,

echo "00000000,ffffffff" > /sys/class/net/eth0/queues/rx-0/rps_cpus 7、设置RFS

上面我们说过RPS和RFS一般要配合使用,效果才最优,因此RFS同样需要开启CONFIG_RPS编译选项,同时设置每个队列的数据流表总数才能真正生效。

这里我们了解一下RFS的细节:

RFS的实现需要依赖两个表——全局socket流表(rps_sock_flow_table)和设备流表(rps_dev_flow_table)。全局socket流表记录的是每个流由上面RPS计算通过hash分配的CPU号,也就是期望的CPU号;设备流表存在于每个网络设备的每个接收队列,表中记录的是每个未完成流使用的CPU号,也就是当前流使用的CPU号。具体使用哪个CPU简单来说有以下规则,

如果两个表中记录的对应流使用的是同一个CPU号,就使用这个CPU如果当前流使用的CPU未设置或者CPU处于离线状态,那就使用期望CPU表中的CPU号,也就是RPS计算而得的CPU号如果两个表中对应流记录的CPU核不是同一个:a)如果同一流的前一段数据包未处理完,为了避免乱序,不更换CPU,继续使用当前流使用的CPU号b)如果同一流的前一段数据包已经处理完,那就可以使用期望CPU表中的CPU号

因此我们需要设置这两个表中记录的entry,对于全局socket流表(rps_sock_flow_table),该配置接口是

/proc/sys/net/core/rps_sock_flow_entries

而设备流表(rps_dev_flow_table)则通过以下接口设置,

/sys/class/net//queues/rx-/rps_flow_cnt

两者的关系如下,

rps_sock_flow_entries = rps_flow_cnt * N

其中,N就是队列数量。因此,对于单队列网卡,两个值是一样的。

8、XPS(Transmit Packet Steering)

上面说的都是关于接收队列,那对于发送队列呢,这就需要用到XPS了。

XPS通过创建CPU到网卡发送队列的对应关系,来保证处理发送软中断请求的CPU和向外发送数据包的CPU是同一个CPU,用来保证发送数据包时候的局部性。

对于发送队列到CPU的映射有两种选择:

1、使用CPU映射 这种方式是通过指定发送队列在某几个CPU上处理,通过减小分发的CPU范围来减少锁开销以及cache miss。最常见的就是1对1,和上面说到的接收软中断绑核类似,通过以下接口设置,

/sys/class/net//queues/tx-/xps_cpus

同样是bitmaps方式。

2、接收队列映射方式 这种方式基于接收队列的映射来选择CPU,也就是说让接收队列和发送队列在同一个CPU,或指定范围的几个CPU来处理。这种方式对于多线程一直收发包的系统效果比较明显,收发包队列处理在同一个CPU,不仅减少了对其他CPU的打断,同时提高应用处理效率,收完包后直接在同个CPU继续发包,从而减小CPU消耗,同时减小包的时延。

这种方式映射,可通过一下接口设置(不是所有网卡都支持),

/sys/class/net//queues/tx-/xps_rxqs

另外,XPS对于单发送队列网卡没有效果,这个可想而知。

参考资料: 1、https://www.kernel.org/doc/Documentation/networking/scaling.txt



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3