我有一个在 Linux 4.4.0 中运行的多线程服务器应用程序,带有 X540-AT2 NIC(服务器每个核心有一个线程)。由于 Linux 启用了 RSS,因此系统中的每个核心都使用一个 NIC 接收队列(16 个核心,因此有 16 个 RX 队列)。
我的目标是让在单独主机上运行的客户端应用程序“提示”数据包应定向到哪个队列(即某种客户端定向的接收队列负载平衡)。
为了实现这一目标,我一直在使用 NIC 的流控制器表,但没有成功(有什么想法吗?):
VLAN 标记:服务器主机将每个 VLAN 标识符分配给一个单独的 RX 队列(使用
ethtool --config-ntuple
),客户端应用程序为每个数据包分配一个 VLAN 标记,以识别目标接收队列(从而实现我想要的客户端定向平衡)。不幸的是,服务器永远不会收到任何客户端的数据包,因为它正在侦听主 NIC 接口,而系统中没有为其分配 VLAN。有没有办法在收到数据包后丢弃 VLAN 标记,以便它们仅用于我的平衡需求?
TOS 字段(IPv4 标头的第 8-15 位):我也尝试过使用 IPv4 的 TOS 字段来执行相同的操作。服务器主机使用 ethtool 将每个 TOS 值定向到单独的队列,并且客户端根据服务器上所需的目标接收队列制作发送的数据包以具有 TOS 值。
不幸的是,ethtool 似乎忽略了过滤器上的 TOS 值(规则上的 TOS 始终为 0):
$ sudo ethtool -U em2 流类型 tcp4 tos 1 操作 10 添加了 ID 2045 的规则 $ ethtool --show-ntuple em2 16 个 RX 环可用 共 1 条规则 筛选:2045 规则类型:基于 IPv4 的 TCP 源 IP 地址:0.0.0.0 掩码:255.255.255.255 目标 IP 地址:0.0.0.0 掩码:255.255.255.255 TOS:0x0 掩码:0xff 源端口:0 掩码:0xffff 目标端口:0 掩码:0xffff VLAN 以太网类型:0x0 掩码:0xffff VLAN:0x0 掩码:0xffff 用户定义:0x0 掩码:0xffffffffffffffff 操作:直接进入队列 10
user-def:我也尝试使用 user-def 来克服 TOS 字段“问题”,但似乎我只能在最后两个字节上使用它:
$ sudo ethtool -U em2 流类型 tcp4 用户定义 2 操作 10 添加了 ID 2045 的规则 $ ethtool --show-ntuple em2 16 个 RX 环可用 共 1 条规则 筛选:2045 规则类型:基于 IPv4 的 TCP 源 IP 地址:0.0.0.0 掩码:255.255.255.255 目标 IP 地址:0.0.0.0 掩码:255.255.255.255 TOS:0x0 掩码:0xff 源端口:0 掩码:0xffff 目标端口:0 掩码:0xffff VLAN 以太网类型:0x0 掩码:0xffff VLAN:0x0 掩码:0xffff 用户定义:0x2 掩码:0xffffffffffffff00 操作:直接进入队列 10
当我尝试匹配其他一些字节时,它会被忽略(用户定义的始终为零并且掩码已满):
$ sudo ethtool -U em2 流类型 tcp4 用户定义 2 m 0xf0ffffffffffffff 操作 10 添加了 ID 2045 的规则 $ ethtool --show-ntuple em2 16 个 RX 环可用 共 1 条规则 筛选:2045 规则类型:基于 IPv4 的 TCP 源 IP 地址:0.0.0.0 掩码:255.255.255.255 目标 IP 地址:0.0.0.0 掩码:255.255.255.255 TOS:0x0 掩码:0xff 源端口:0 掩码:0xffff 目标端口:0 掩码:0xffff VLAN 以太网类型:0x0 掩码:0xffff VLAN:0x0 掩码:0xffff 用户定义:0x0 掩码:0xffffffffffffffff 操作:直接进入队列 10
知道如何解决上述问题吗? (任何 VLAN 或 TOS 方法都适合我)。
编辑:按照@Hauke Laging 的要求澄清了问题。
答案1
你应该明确你想要平衡什么样的队列以及达到什么效果。
此外,您应该提及可以在服务器上配置的内容。你提到了VLAN。看来你不能在服务器上配置VLAN。
有多种可能以不同的方式将数据包发送到同一系统:
- 使用不同的 TCP/UDP 端口(如果使用 TCP/UDP)。通过在客户端和服务器上使用 DNAT,可以对应用程序透明地完成此操作。
- 在服务器上使用不同的 IP 地址。通过在客户端和服务器上使用 DNAT,可以对应用程序透明地完成此操作。
- 在客户端和服务器上创建多个隧道接口 (
ip link add type ipip
) 并通过多个接口发送数据包。 - 入口排队可以使用 ifb 设备和流量整形(基于上述“信息”)来完成。