network-stack

从网卡到 socket 排查 Linux 网络栈的丢包、重传与队列

补充说明

一个包大致经过:网卡/驱动 → 内核协议栈(GRO、netfilter/conntrack、路由)→ qdisc → socket 接收队列 → 应用。排查时要先确定丢在哪一层,再选工具,而不是一上来就抓包。

常用示例

# 查看协议栈计数:重传、监听溢出、UDP 接收错误
nstat -az | grep -E 'TcpRetransSegs|TcpExtListenOverflows|TcpExtListenDrops|UdpRcvbufErrors'

# 查看 socket 队列、拥塞窗口和重传信息(-i 内部信息,-m 内存,-n 数字)
ss -tinm

# 查看网卡队列与驱动丢包计数
ethtool -S eth0 | grep -iE 'drop|miss|error|no_buffer'
ip -s link show eth0

# 查看 qdisc 排队、丢包和 backlog
tc -s qdisc show dev eth0

# 只抓 SYN/RST,减少抓包量和隐私数据
sudo tcpdump -ni eth0 -c 200 'tcp[tcpflags] & (tcp-syn|tcp-rst) != 0'

# 检查常见内核网络参数
sysctl net.core.somaxconn net.ipv4.tcp_max_syn_backlog net.ipv4.tcp_congestion_control

易错点与排错

读完自测

  1. 抓包看到 checksum incorrect,为什么可能是假象?
  2. 如何区分 NIC ring 丢包、backlog 丢包和 socket 队列溢出?
  3. 容器内看到的网络队列和宿主机有什么不同?
答案
  1. 校验和卸载会把计算推迟到网卡,抓包点在内核协议栈看到的包可能还没填充正确校验和。
  2. 分别看 ethtool -S 的 ring miss/no_buffer、nstat 的 backlog 丢弃计数、ss 的 Recv-Q 与应用读取速度。
  3. 容器只看到自己 net namespace 的接口、路由和 qdisc;veth 对端、宿主机 qdisc、物理网卡和 conntrack 都在宿主机侧。

相关条目