LinuxNotes

第 18 章:网络栈

zjc 于 2026-01-18 发布

这是《Linux 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 Linux 网络栈从网卡收包开始,经过中断、软中断、协议栈、socket、进程读写,再到路由和发包。应用网络慢可能是协议问题,也可能是丢包、队列、conntrack、CPU 或缓冲区问题。

18.1 收发包路径

NIC
  -> DMA / Ring Buffer
     -> Hard IRQ
        -> Soft IRQ
           -> IP / TCP / UDP
              -> Socket Receive Queue
                 -> Application read

发包:

Application write
  -> Socket Send Buffer
     -> TCP / IP
        -> QDisc
           -> NIC Ring
              -> Send

18.2 基础命令

地址与路由:

ip -br addr
ip route
ip -s link
ethtool eth0
ethtool -S eth0

连接:

ss -s
ss -antp
ss -lntp
ss -ti
ss -m

统计:

netstat -s
nstat -az
cat /proc/net/softnet_stat
cat /proc/net/snmp

18.3 网卡统计

ethtool -S eth0 | grep -Ei 'drop|err|fifo|miss|overflow'
ip -s link show eth0

常见字段:

指标 含义
rx_dropped 採收丢弃
tx_dropped 发送丢弃
rx_errors 接收错误
tx_errors 发送错误
rx_missed Ring Buffer 缺失
rx_no_buffer 缓冲不足

不同网卡驱动字段名称可能不同。要关注持续增长值,而不是只看单次累计值。

18.4 软中断

查看:

mpstat -P ALL 1
cat /proc/interrupts
cat /proc/net/softnet_stat
watch -n1 'cat /proc/softirqs'

softnet 第二列丢弃:

cat /proc/net/softnet_stat

处理方向:

  1. 开启 RSS / 多队列;
  2. 调整队列亲和;
  3. 增加缓冲;
  4. 降低单 CPU 中断压力;
  5. 扩容或限流。

18.5 Ring Buffer 与队列

查看:

ethtool -g eth0
ethtool -l eth0
ethtool -x eth0

调整:

sudo ethtool -G eth0 rx 4096 tx 4096

RSS:

cat /proc/irq/<irq>/smp_affinity_list
echo 2 | sudo tee /proc/irq/<irq>/smp_affinity_list

增大缓冲会增加内存和排队延迟,必须结合延迟指标评估。

18.6 TCP 缓冲与拥塞

查看:

ss -ti
ss -m
sysctl net.core.rmem_max
sysctl net.core.wmem_max
sysctl net.ipv4.tcp_rmem
sysctl net.ipv4.tcp_wmem
sysctl net.ipv4.tcp_congestion_control

关键观察:

字段 含义
cwnd 拥塞窗口
ssthresh 慢启动阈值
retrans 重传
rto 重传超时
rtt 往返时间
Send-Q / Recv-Q socket 队列

网络参数优化必须基于路径 RTT、丢包率和吞吐目标,不能照抄所谓万能参数。

18.7 防火墙与 conntrack

查看:

sudo iptables -L -n -v
sudo nft list ruleset
sudo conntrack -S
sudo conntrack -C
sysctl net.netfilter.nf_conntrack_max

表满时新建连接可能失败:

dmesg -T | grep -i conntrack

处理:

  1. 监控使用率;
  2. 评估表上限;
  3. 缩短不合理超时;
  4. 优化规则顺序;
  5. 控制短连接风暴。

18.8 Loopback 与本地通信

ip addr show lo
ss -lntup
curl -v http://127.0.0.1:8080/healthz

本地通信仍会经过协议栈和 socket。排查时可用:

sudo tcpdump -i lo -nn port 8080
strace -e trace=network -p <pid>

18.9 eBPF 与高级观测

常用工具:

工具 场景
tcpretrans TCP 重传
tcplife 连接生命周期
tcpconnect 主动连接
tcpaccept 被动连接
biolatency IO 延迟
execsnoop 新进程
opensnoop 文件打开

安装:

sudo apt install bpfcc-tools
sudo dnf install bcc-tools

工具名在不同包中可能带 -bpfcc 后缀。

18.10 常见故障

丢包

ip -s link show eth0
ethtool -S eth0
cat /proc/net/softnet_stat
nstat -az | grep -Ei 'drop|err'

定位层次:

网卡 / 驱动
  -> softirq
     -> conntrack / firewall
        -> socket buffer
           -> application

连接队列溢出

ss -lnt
netstat -s | grep -Ei 'listen|overflow'
sysctl net.core.somaxconn
sysctl net.ipv4.tcp_max_syn_backlog

处理:

  1. 增大应用 accept backlog;
  2. 调整系统 backlog;
  3. 优化应用 accept 速度;
  4. 扩容。

重传高

nstat -az | grep -i retrans
ss -ti
mtr -rwzc 100 <peer>

区分本机丢包、路径丢包和对端处理慢。

本章小结

Linux 网络栈排障要沿收发包路径分层:网卡、中断、协议栈、conntrack、socket 和应用。ethtool 看设备层,ss 看连接和缓冲,netstat / nstat 看协议统计,tcpdump 和 eBPF 提供证据。调优前必须先定位丢包和队列瓶颈。

思考题

  1. 硬中断和软中断分别做什么?
  2. rx_droppedListen Overflows 有什么区别?
  3. Ring Buffer 增大会带来什么权衡?
  4. conntrack 表满会表现为什么?
  5. 如何证明一次重传发生在本机、路径还是对端?