RSS用于使用散列函数在 CPU 内核上分发数据包——为卸载散列的硬件或软件提供支持。启用接收方缩放 (RSS) 时,特定TCP连接的所有接收数据处理都在多个处理器或处理器内核之间共享。如果没有 RSS,所有处理都由单个处理器执行,导致系统缓存利用率低下,影响网络的吞吐量。
注意:为提升硬件的兼容性,默认情况下在OPNsense中RSS被禁用。
网卡/驱动
如果驱动程序支持启用/禁用 RSS选项,则可以使用sysctl可调参数来设置。
查看是否启用或禁用RSS,可以执行以下命令:
sysctl -a | grep rss
这会显示任何通过可调参数公开该选项的驱动程序。
也有可能驱动程序没有向用户公开此功能,在这种情况下,需要使用在线数据表或谷歌搜索来查找NIC/驱动程序是否完全支持 RSS。例如,igb默认启用 RSS,dut不会在任何配置参数中反映这一点。但是,由于它使用多个队列:
# dmesg | grep vectors
igb0: Using MSI-X interrupts with 5 vectors
igb1: Using MSI-X interrupts with 5 vectors
igb2: Using MSI-X interrupts with 5 vectors
igb3: Using MSI-X interrupts with 5 vectors
很可能有某种形式的数据包过滤来在硬件队列上分发数据包。事实上,igb默认会做RSS。
RSS内核实现必须有驱动程序的支持。合适的驱动程序支持将确保在硬件中设置正确的密钥和间接表。以下是各种NIC驱动程序支持情况(大部分未经测试):
- em
- igb -> 已测试可以正常工作
- axgbe -> 已测试可以正常工作
- netvsc
- ixgbe
- ixl
- cxgbe
- lio
- mlx5
- sfxge
内核支持
在内部,FreeBSD使用netisr 作为抽象层来将数据包分派给上层协议。在实现中,默认设置是将数据包处理限制为仅一个线程。由于RSS现在提供了一种将流保持在CPU 本地的方法,因此可以在系统->设置>可调参数中调整以下选项的值:
net.isr.bindthreads = 1
net.isr.maxthreads = -1
第一个选项设置一个线程绑定到一个 CPU,下面一个选项为每个可用的核心分配一个工作流。
要启用RSS,必须将以下参数修改为1:
net.inet.rss.enabled = 1
默认情况下该参数为0,禁用RSS,以防止出现未知的问题。
net.inet.rss.bits = X
取决于CPU拥有的内核数量。默认情况下,此处的位数表示内核数 x 2(二进制)。这样做是为了提供负载平衡,但目前还没有实现,因此我们建议将此值设置为表示CPU内核数的位数。
- 4核系统,使用“2”
- 8核系统,使用“3”
- 16核系统,使用“4”
- 等等。
修改后重新启动防火墙。
测试
启用RSS后,数据包分发策略将从“直接”变为“混合”。将在允许的情况下直接在当前上下文中发送数据包,否则它将在数据包所在的绑定CPU上排队。注意会增加中断负载,如“top -P”所示。这只是意味着数据包在CPU调度程序中以最高优先级进行处理——这并不意味着CPU的负载比正常情况下高。
netisr 的正确工作可以通过运行以下命令来验证:
netstat -Q
经群内网友测试,在启用RSS后,并调整kern.ipc.maxsockbuf参数的值后,cx341a网卡转发可以跑满万兆。
未启用RSS测试数据:
启用RSS后测试数据:
注意事项
当Suricata在IPS模式下运行时,Netmap用于从线上获取数据包来供检查。默认情况下,OPNsense已将Suricata配置为将通过检查的数据包重新注入主机网络堆栈以用于路由/防火墙目的。当前的Suricata/Netmap实现将这种重新注入仅限于一个线程。解决此问题的工作正在进行中,因为新的Netmap API (V14+) 现在能够增加此线程数。在此之前,使用IPS时,启用RSS不会带来任何好处。
原文地址。