ksoftirqd 长期占用 20-40% 的 softnet backlog 与网卡参数调整

8次阅读

ksoftirqd 持续高 CPU 是因网卡收包积压导致 sof.net backlog 过高,非软中断本身繁忙;真实瓶颈在 NIC 驱动或硬件收包路径,如 RSS 不均、GRO 开启但应用不消费、NAPI 轮询不足。

ksoftirqd 长期占用 20-40% 的 softnet backlog 与网卡参数调整

为什么 ksoftirqd 持续吃高 CPU 且 softnet backlog 居高不下

这不是软中断本身太忙,而是网卡收包后来不及处理,导致 softnet_data->input_pkt_queue 积压。一旦 backlog 超过 net.core.netdev_max_backlog(默认 1000),内核会丢包并触发更频繁的 softirq 调度,形成恶性循环——ksoftirqd 看似“忙”,实则是被积压队列拖住的救火队员。

  • 典型现象:cat /proc/net/softnet_stat 中每行第 2 列(drop)持续增长,第 1 列(processed)远高于第 3 列(time_squeeze)
  • 真实瓶颈往往在 NIC 驱动层或硬件收包路径,比如 RSS 队列未均分、GRO 开启但应用不消费、NAPI poll 轮询量不足
  • ksoftirqd 占用率高只是表象,不能靠调高 vm.swappiness 或关 irqbalance 来解决

net.core.netdev_max_backlog 改大就能缓解吗

不能盲目调大。该值只是队列上限,不是性能加速器。设得过大反而延长延迟、掩盖真实瓶颈,还可能因内存碎片导致分配失败(见 dmesgsoftnet_alloc_recv_skb_failed)。

  • 合理范围:2000–5000,需配合 net.core.dev_weight 和 NAPI weight 同步调整
  • 必须确认硬件支持:部分老网卡(如 e1000e)在 backlog > 2048 时触发额外锁竞争,CPU 反而更卡
  • 改完要验证:watch -n1 'cat /proc/net/softnet_stat | cut -d" " -f1,2,3',观察 drop 是否下降、time_squeeze 是否减少

RSS、RPS、RFS 该怎么配才不打架

RSS(硬件多队列)优先级最高,RPS 是软件模拟,RFS 是流亲和增强。三者混用易冲突,尤其 RPS 在开启 RSS 后基本无用,还增加 cache miss。

  • 有 RSS 支持(ixgbe、i40e、mlx5):关闭 RPS(echo 0 > /sys/class/net/eth0/queues/rx-0/rps_cpus),只调 RSS 队列数和 IRQ 绑核
  • 无 RSS(如 vmxnet3、virtio):启用 RPS + RFS,但 rps_sock_flow_entries 至少设为 32768,否则流哈希碰撞严重
  • RFS 依赖 net.core.rps_flow_cnt,若应用短连接多,建议设为 65536;否则默认 32768 即可

哪些网卡参数改动最立竿见影

别碰 txqueuelenethtool -G ring buffer 大小——它们影响的是发包或 DMA 缓存,对 softnet backlog 几乎无感。真正关键的是 NAPI 和 GRO/GSO 控制点。

  • 降低单次 NAPI 处理上限:echo 64 > /sys/class/net/eth0/napi_defer_hard_irqs(仅支持较新驱动),或调小 net.core.dev_weight(默认 64 → 32)
  • 禁用 GRO(如果上层是 udp 或 TLS 流量):ethtool -K eth0 gro off,避免大包重组后无法及时分发
  • 确认 net.ipv4.tcp_rmem 第三项(max)不低于 4M,否则 socket 接收缓冲区小,会卡住 softnet 消费链路

真正卡点常在驱动与协议交界处:比如 ixgbe 的 InterruptThrottleRate 设太高会导致中断合并过度,RSS 队列空转;而 virtio-net 的 vq_rx ring size 不够则直接堵死 vhost 内核线程。这些细节比 sysctl 参数更值得盯住。

text=ZqhQzanResources