WEBKT

100G网卡下通过硬件Symmetric RSS优化eBPF网络包分流效率的实践指南

3 0 0 0

在100G(如Mellanox ConnectX-6或Intel E810)的高吞吐网络环境下,单核CPU根本无法应对每秒上千万、甚至上亿个数据包(Mpps)的挑战。为此,我们通常会借助eBPF/XDP进行内核前置收包分流,并依赖RSS(Receive Side Scaling,接收端缩放)将流量分摊到多个CPU核心上。

然而,传统的RSS采用Toeplitz哈希算法,默认情况下,TCP连接的来回双向流量(Inbound和Outbound)通常会被分流到不同的CPU核心上。这种“非对称分流”在运行有状态eBPF程序(如L4负载均衡、防火墙、有状态连接跟踪Conntrack)时,会导致极其严重的性能瓶颈:

  1. 跨核Cache Bouncing:CPU A写入的连接状态,被收到回程包的CPU B读取/更新,导致L1/L2 Cache频繁失效。
  2. 锁竞争:为了保护eBPF Map中的共享连接状态,不得不引入并发控制(如bpf_spin_lock),在100G线速下,锁竞争会直接导致CPU利用率飙升、吞吐量急剧下滑。

通过配置硬件对称RSS(Symmetric RSS),可以强行保证同一条TCP/UDP流的双向数据包始终落入同一个CPU核心,从而实现eBPF的有状态无锁(Lock-Free)处理。以下是完整的优化配置与落地指南。


一、 硬件对称RSS的数学原理与配置核心

传统Toeplitz哈希公式为:
$$\text{Hash} = \text{Toeplitz}(\text{SIP}, \text{DIP}, \text{SPort}, \text{DPort}, \text{Key})$$

当来回路径的源/目的IP、源/目的端口对调时,计算出来的哈希值在默认Key下是不相等的。
要实现对称哈希,关键在于替换网卡的Toeplitz Hash Key(通常为40字节或52字节),使其在输入字段对调时,输出相同的哈希结果。

常用的对称Toeplitz Key(微软推荐标准)为:

6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a
6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a
6d:5a:6d:5a:6d:5a:6d:5a

二、 100G网卡硬件配置实操

在100G网卡环境下,我们主要通过 ethtool 命令行工具或网卡专属驱动工具来修改哈希配置。

1. Intel E810 (ice 驱动) 配置对称 RSS

Intel E810网卡支持通过修改Toeplitz Key或直接启用对称哈希算法(Symmetric Toeplitz)来实现双向流量同核。

首先,检查当前网卡的哈希字段配置:

ethtool -n eth0 rx-flow-hash tcp4

通过以下命令,将TCP/IPv4和TCP/IPv6的哈希策略设置为对称模式(需要驱动与固件支持):

# 写入对称Toeplitz Key
ethtool -X eth0 hkey 6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a

验证哈希是否生效:

ethtool -x eth0

2. NVIDIA / Mellanox ConnectX-6 Dx 配置对称 RSS

Mellanox网卡不仅支持Key替换,还提供了更高级的硬件级对称配置选项。可以通过 mlx5cmd 或通过修改系统内对应的配置模块实现。

使用 ethtool 修改 mlx5_core 驱动网卡的哈希规则:

# 开启四元组哈希(SDFN),确保IP和Port均参与计算
ethtool -N eth0 rx-flow-hash tcp4 sdfn

# 写入Mellanox对称优化Key
ethtool -X eth0 hkey 6d:5a:56:da:25:5b:0e:c2:41:67:25:3d:43:a3:8f:b0:d0:ca:2b:cb:ae:7b:30:b4:77:cb:2d:a3:80:30:f2:0c:6a:42:b7:3b:be:ac:01:fa

对于部分Mellanox网卡,还可以通过修改内核加载模块参数直接开启对称哈希模式(修改 /etc/modprobe.d/mlx5.conf):

options mlx5_core rss_symmetric=1

重新加载驱动后生效。


三、 配合对称RSS优化eBPF/XDP代码

当硬件层面确保了同一条流的双向包进入同一个CPU后,eBPF端的代码设计需要进行相应重构,以发挥硬件的最大潜能。

1. 规避 bpf_spin_lock

在非对称RSS下,多个CPU会同时读写同一个连接的状态,不得不使用锁:

// 传统非对称场景:需要加锁
struct connection_state *state = bpf_map_lookup_elem(&conntrack_map, &flow_key);
if (state) {
    bpf_spin_lock(&state->lock);
    state->packets++;
    state->last_seen = bpf_ktime_get_ns();
    bpf_spin_unlock(&state->lock);
}

启用对称RSS后,由于同一条流的包(无论是去程还是回程)绝对不可能同时在两个不同的CPU上被处理,我们可以安全地移除 bpf_spin_lock,直接进行无锁读写:

// 对称RSS场景:安全的无锁更新
struct connection_state *state = bpf_map_lookup_elem(&conntrack_map, &flow_key);
if (state) {
    // 100% 确定当前CPU是独占该flow数据的,无需bpf_spin_lock
    state->packets++; 
    state->last_seen = bpf_ktime_get_ns();
}

注:在极端高并发下,去除 bpf_spin_lock 可以使单核包处理时延降低 20%~30% 左右。

2. 使用 Per-CPU Map 的优化考量

虽然双向流量归于同核,但我们仍然需要维护一个全局的 BPF_MAP_TYPE_HASH 来存储跨连接的全局状态。不过,对于某些统计数据(如每核包计数、临时缓冲区),强烈建议配合使用 BPF_MAP_TYPE_PERCPU_ARRAYBPF_MAP_TYPE_PERCPU_HASH

对于需要全局汇总的数据,采用 Per-CPU 局部写 + 用户态全局读 的模式:

struct {
    __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
    __type(key, __u32);
    __type(value, __u64);
    __uint(max_entries, 1);
} pps_stats SEC(".maps");

// 在XDP中无锁递增,绝无跨核冲突
__u32 key = 0;
__u64 *count = bpf_map_lookup_elem(&pps_stats, &key);
if (count) {
    (*count)++;
}

四、 性能调优验证方法

配置完成后,必须通过基准测试和监控指标验证对称RSS是否真正生效:

  1. 利用 mpstat 观察CPU均衡度
    在百G流量打入时,观察各CPU核的软中断(%soft)是否均衡。如果出现极个别核跑满,其他核空闲,说明RSS Key配置或网卡Queue绑定(irqbalance)存在缺陷。

    mpstat -P ALL 1
    
  2. 验证双向同核性
    在eBPF程序中,打印处理特定连接的 bpf_get_smp_processor_id()

    bpf_printk("Flow [%pI4:%d -> %pI4:%d] on CPU %d", 
               &ip->saddr, bpf_ntohs(tcp->source), 
               &ip->daddr, bpf_ntohs(tcp->dest), 
               bpf_get_smp_processor_id());
    

    通过 /sys/kernel/debug/tracing/trace_pipe 查看双向包的 CPU ID 是否完全一致。

  3. 吞吐量与丢包率对比
    在100G测试仪(如Keysight或Trex)上发送双向100%线速小包:

    • 未开启对称RSS:由于跨核锁冲突与Cache失效,通常在40Mpps-60Mpps时开始丢包。
    • 开启对称RSS + eBPF无锁化:吞吐量可逼近物理网卡极限(>100Mpps),且CPU延迟大幅收敛,尾部延迟(P99)显著降低。

五、 总结与注意事项

  1. 虚拟化与容器环境限制:如果eBPF部署在虚拟机(KVM/VMware)内,由于虚拟网卡(virtio-net)通常不支持物理级的Symmetric RSS,优化效果会大打折扣。建议在裸金属服务器或通过SR-IOV直接将VF直通给容器/虚机。
  2. 非TCP/UDP流量:对称RSS主要针对含有4元组的TCP/UDP流量。对于ICMP或分片IP报文,网卡会自动降级到2元组(仅IP)哈希,对称性依然保持,但分流粒度会变粗。
  3. 网卡通道数设置:确保网卡的RX Queue数量与绑定的物理CPU核心数呈1:1对应,避免多个Queue中断绑定到同一个CPU核心,从而最大化发挥Symmetric RSS的分流价值。
网路深核 eBPF100G网卡

评论点评