Computer NetworkNotes

第 27 章:内核网络栈

zjc 于 2026-01-27 发布

这是《计算机网络 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 应用发送一个字节到网卡收到数据,中间会经历系统调用、协议栈、路由、Netfilter、qdisc、DMA、硬中断、软中断和协议解析。理解内核网络栈,才能解释 softirq 高、丢包、队列延迟、conntrack 满和 CPU 分布不均。

27.1 接收路径

网卡收到帧
  -> DMA 到 RX Ring Buffer
  -> 硬中断
  -> NAPI 轮询
  -> 软中断 NET_RX
  -> IP 层
  -> Netfilter / Conntrack
  -> TCP / UDP
  -> Socket Receive Queue
  -> 应用 read()

关键点:

  1. Ring Buffer 大小有限;
  2. 硬中断只做通知,处理在软中断;
  3. NAPI 在高负载下从中断切换到轮询;
  4. 应用读取慢会造成 socket 队列堆积;
  5. conntrack 会增加每包成本;
  6. softnet 丢包说明 CPU 来不及处理。

查看:

cat /proc/interrupts
cat /proc/net/softnet_stat
ethtool -S eth0

27.2 发送路径

应用 write()
  -> Socket Send Buffer
  -> TCP 分段
  -> IP 路由
  -> Netfilter
  -> QDisc
  -> NIC TX Ring
  -> 网卡发送

如果发送缓冲满,write 可能阻塞或返回 EAGAIN,取决于文件描述符模式。

查看:

ss -i
tc -s qdisc show dev eth0
ethtool -S eth0

27.3 NAPI

NAPI 是中断和轮询的混合机制:

低流量:中断驱动,延迟低
高流量:关闭或减少中断,批量轮询,减少 CPU 开销

收益:

  1. 减少每个包一次中断的开销;
  2. 批量处理描述符;
  3. 提升高包量吞吐;

调优通常不是直接修改 NAPI,而是关注:

  1. RSS 队列;
  2. 中断亲和;
  3. Ring Buffer;
  4. softnet 分布;
  5. 协议处理 CPU。

27.4 RSS 与中断亲和

RSS 将流量哈希到多个网卡队列:

NIC RX Queue 0 -> CPU 0
NIC RX Queue 1 -> CPU 1
NIC RX Queue 2 -> CPU 2
NIC RX Queue 3 -> CPU 3

查看队列:

ethtool -l eth0

查看中断:

grep eth0 /proc/interrupts
cat /proc/irq/<irq>/smp_affinity_list

问题:

  1. 只有单队列,单核 softirq 高;
  2. 中断集中在少数 CPU;
  3. 队列数超过业务需要;
  4. NUMA 跨节点访问;
  5. 云实例规格限流。

可配合 RPS / RFS 将包调度到其他 CPU:

cat /sys/class/net/eth0/queues/rx-0/rps_cpus

27.5 QDisc

QDisc 是内核流量调度队列。

查看:

tc qdisc show
tc -s qdisc show dev eth0

常见:

QDisc 特点
fq_codel 控制队列延迟
fq 公平队列,配合 BBR
pfifo_fast 先进先出
tbf 限速
htb 层级带宽控制

生产可用 tc 做备份限速或测试,但大规模策略应由云网络、CNI 或专用网关管理。

27.6 Netfilter 与 conntrack

Netfilter 钩子:

PREROUTING
INPUT
FORWARD
OUTPUT
POSTROUTING

conntrack 记录连接状态:

src=10.0.1.10 dst=1.2.3.4 sport=50000 dport=443 state=ESTABLISHED

查看:

cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/sys/net/netfilter/nf_conntrack_max
conntrack -S

高并发容器宿主机要监控:

  1. conntrack count;
  2. insert failed;
  3. drop;
  4. table full;
  5. 新建连接速率;
  6. 空闲超时。

27.7 常用观测工具

系统层:

mpstat -P ALL 1
vmstat 1
watch -d cat /proc/net/softnet_stat

网络层:

ss -s
ss -antp
ss -i
nstat -az
netstat -s

追踪工具:

工具 用途
tcpdump 包级事实
bpftrace 内核函数追踪
perf CPU 热点和软中断
ethtool 网卡统计和队列
biolatency / biosnoop 存储侧排查

27.8 调优原则

先定位:

丢包发生在哪里?
CPU 忙在哪里?
队列堆积在哪里?
延迟来自哪里?

再行动:

  1. softnet 丢包:增加队列、调整 RSS、优化应用;
  2. Ring Buffer 溢出:适度增大,同时关注延迟;
  3. conntrack 满:扩容或减少连接;
  4. 中断集中:设置亲和;
  5. 应用读取慢:优化 IO 模型;
  6. 带宽打满:限流或扩容;
  7. 队列延迟:更换 qdisc;
  8. 云实例限流:升级规格。

本章小结

Linux 网络栈接收路径经过网卡 DMA、硬中断、NAPI、软中断、协议栈、Netfilter 和 socket 队列;发送路径经过 socket 缓冲、协议栈、QDisc 和网卡队列。softnet、Ring Buffer、RSS、中断亲和、conntrack 和 qdisc 是内核层排障重点。调优必须基于丢包位置和 CPU 热点,而不是盲目改参数。

思考题

  1. 硬中断和软中断在网络收包中分别负责什么?
  2. NAPI 为什么能降低高流量下的 CPU 开销?
  3. conntrack 表满会造成什么?
  4. fq_codel 对缓冲膨胀有什么帮助?
  5. 写一份高 PPS 宿主机的内核网络观测清单。