首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Linux收发包绑定CPU

Linux收发包绑定CPU

原创
作者头像
poi11451
发布2025-06-25 17:09:51
发布2025-06-25 17:09:51
2920
举报

TX

对于tx方向,发包使用的cpu和队列可以通过taskset和xps指定.

tx完成的中断则通过中断亲和性绑定:

代码语言:bash
复制
echo 8 > /proc/irq/<tx-irq-number>/smp_affinity

✅ 方法 1:绑定线程到指定 CPU —— CPU affinity 控制发包

代码语言:bash
复制
taskset -c 2 ./your_server`

将你的发包进程绑定在 CPU 2,那么所有 send() 都会在 CPU 2 上执行,TX 流量也就自然从 CPU 2 发出。

这是最直接、最常见的方法,也是高性能多核服务器中常用的做法。


✅ 方法 2:基于 XPS(Transmit Packet Steering)

XPS 是 Linux 提供的一种优化机制,用于将不同 CPU 发起的 TX 操作 映射到特定的 TX 队列

配置方式:
代码语言:bash
复制
ls /sys/class/net/eth0/queues/tx-*/xps_cpus`

你可以为每个 TX queue 设置允许哪个 CPU 使用:

代码语言:bash
复制
# 将 tx-0 绑定到 CPU0 
echo 1 > /sys/class/net/eth0/queues/tx-0/xps_cpus  
将 tx-1 绑定到 CPU1 
echo 2 > /sys/class/net/eth0/queues/tx-1/xps_cpus`

其中1,2为cpu位图,即1代表0001, 2代表0010

✅ 方法 3:使用 SO_BINDTODEVICE / 多 socket / BPF

更高级的策略可以用:

  • 多个 socket,每个绑定一个端口或 IP;
  • 使用 SO_BINDTODEVICE 强制走特定网卡;
  • 使用 eBPF + SO_REUSEPORT 来实现 CPU-based socket 路由;
  • 使用 AF_XDP 实现用户态发包 → 硬件队列映射(完全由你控制 TX ring)。

EBPF不太了解.待研究...

RX

RX方向通过绑定流到队列,然后将队列中断绑定到对应cpu实现了流和中断cpu的绑定,然后中断cpu在完成skb建立后会触发对应cpu的软中断,上处理协议栈流程,最后送到socket进行应用层处理.

代码语言:bash
复制
# 查看中断在 CPU 分布 (硬中断的cpu)
cat /proc/interrupts | grep eth0

# 查看软中断执行在哪些 CPU 上 (软中断的cpu)
cat /proc/softirqs | grep NET_RX

1.流绑定队列:

1.ARS:

在ARS(auto-receive-scaling)中,流的txrx队列是对称的,所以只需要将之前tx方向配置的队列队列的rx队列的中断和软中断绑定到和tx绑定的cpu即可实现应用的tx和rx方向使用同一cpu处理.

代码语言:bash
复制
	grep eth0 /proc/interrupts`
	echo 2 > /proc/irq/XX/smp_affinity  # 绑定队列中断到 CPU 1`
	
	echo 2 > /sys/class/net/eth0/queues/rx-0/rps_cpus # 配置队列软中断到 cpu 1

对于ARS来说,如果一个流是单向的(server模式),首包会随机到一个rx队列,然后tx方向则通过选定的cpu的tx队列发送,后续的包则通过tx对应的rx队列来收包,rx队列环形对应的irq cpu完成中断收包,xps绑定的中断cpu进行协议栈收包,收包处理,整个流程中,流处理能很快收敛到同一个cpu上.

2.RSS

RSS将流量根据五元组or三元组(only ip)hash值和间接表得出对应的rx队列,理论上只是负载均衡的手段,无法控制某个流固定绑定在固定队列上,也就是说没办法将流量和队列绑定到对应的中断cpu上.

因此我们只能尝试使用aRFS(auto-receive-flow-scaling)将流的软中断cpu配置成和应用处理的cpu一致,来提升cpu的cache命中率;

如果网卡支持3中的ntuple等基于流量的队列控制,那aRFS通过下发硬件流表的形式让网卡硬件将该流量送到与软中断相同cpu对应的硬件队列上去,从而实现完整的rx流cpu亲和性全自动绑定.

需要注意的是aRFS不会更改收包硬中断的cpu,如果rps和irq affinity对于同一队列的cpu绑定不一样,需要手动将对应队列的irq affinity设置和rps保持一致.

aRFS明显可以利用硬件上报的网卡hash值进行分流

代码语言:bash
复制
	ethtool -k eth0 | grep ntuple # 确定网卡是否支持ntuple

aRFS配置方法:

代码语言:bash
复制
	echo 32768 > /proc/sys/net/core/rps_sock_flow_entries # 启用aRFS并设置最大缓存流数量
	echo f > /sys/class/net/eth0/queues/rx-0/rps_cpus  # f = CPU 0~3 需要设定为需要的值

3.Flow Director / ntuple

ntuple 和flow director可以将确定的流送到指定的队列,然后通过队列irq和cpu绑定,能实现流和中断cpu的绑定,然后使用RPS将队列和软中断cpu绑定,从而让流处理在同一个cpu处理,和2中方法相比,如果没有启用aRFS,属于是手动配置.

整体流程涉及的技术分类

  • 应用层 - taskset设置进程或者线程的cpu亲和性(TX/RX)
  • 协议栈 - (TX) taskset 应用发包的协议栈处理仍然由taskset的cpu处理 - (RX) RPS可以通过队列判断触发软中断的cpu - (RX) aRFS则通过获取对应socket的cpu来确定该流触发的软irq的cpu,如果硬件支持,它会获取该软中断的队列并要求硬件将后续流送到该队列上,注意队列的硬中断应该和rps保持一致.
  • 网卡驱动和硬件队列 - (TX)XPS 要求从哪个cpu使用哪个队列 - (RX / TX) rx_poll和tx_poll的irq affinity

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • TX
    • ✅ 方法 1:绑定线程到指定 CPU —— CPU affinity 控制发包
    • ✅ 方法 2:基于 XPS(Transmit Packet Steering)
    • ✅ 方法 3:使用 SO_BINDTODEVICE / 多 socket / BPF
  • RX
    • 1.流绑定队列:
      • 1.ARS:
      • 2.RSS
      • 3.Flow Director / ntuple
  • 整体流程涉及的技术分类
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档