Netpath
学习路径10 / 49 · 以太网与协议栈看全程 →
原理预计 30 分钟

网络观测工具箱:ss、ethtool、tcpdump、nstat

一套固定顺序的命令清单,让你在陌生机器上十分钟内摸清网络状态。

学完这节你能做到

  • 按接口、连接、协议栈、丢包四个维度各挑一条命令快速体检
  • 用 tcpdump 精确抓到目标流量而不是抓一堆无关包
  • 看懂 ethtool -S 和 nstat 里最常用的那几个计数器

建议先学

跳过这几节会看不懂本节的部分推导

按层次排队,不要随机试

工具多不是好事,顺序固定才是。四层从下往上,每层挑一条命令,走完基本就定位了:

第 1 层  接口与链路   → 网线通不通、速率对不对、有没有硬件错误
第 2 层  连接与队列   → 连接状态、谁在排队、窗口多大
第 3 层  协议栈计数   → 重传、丢弃、conntrack、监听队列
第 4 层  抓包         → 前三层给不出结论时才用

抓包放最后不是因为它没用,而是因为它信息量太大。前三层通常已经能收敛到某一段, 带着假设去抓包,效率比一上来就抓高一个数量级。

第 1 层:接口与链路

# 一眼看全:状态、MTU、收发计数、错误与丢弃
ip -s link show bond0

# 协商结果:速率、双工、自协商
ethtool bond0 | grep -E 'Speed|Duplex|Link detected'

# 网卡自己的详细计数器(各厂家字段名不同,用 grep 捞关键词)
ethtool -S bond0 | grep -iE 'err|drop|discard|missed|pause'

# 队列深度与中断合并的当前设置
ethtool -g bond0
ethtool -c bond0
ethtool -l bond0        # 有几个收发队列(RSS)

ethtool -S 是这一层最有价值的命令。三类关键词的含义:

关键词含义
rx_missed / rx_no_buffer网卡想放但 ring 里没位置 —— CPU 侧跟不上
rx_crc_errors / rx_frame_errors物理层问题 —— 光模块、光纤、端口
pause / pfc流控帧计数 —— 在 RoCE 场景下极其重要
✓MTU 端到端一致性的验证命令
# -M do 禁止分片,-s 8972 = 9000 − 28 字节头部
ping -M do -s 8972 10.10.1.103

通了才说明整条路径的巨帧都对。症状很有迷惑性:小包能通、ping 能通、大文件传输卡死。 这条命令能省下你半天时间。

第 2 层:连接与队列

# 某个对端的连接明细:cwnd、rtt、重传、发送速率
ss -tim dst 10.10.1.103

# LISTEN socket 的 accept 队列积压与上限
ss -lnt

# 按状态统计,快速发现 TIME_WAIT / CLOSE_WAIT 堆积
ss -s

# 谁占着这个端口
ss -tlnp | grep :8080

三个高频判断:

  • Send-Q 高 → 发不出去,问题在对端或路径
  • Recv-Q 高(ESTAB 连接上)→ 应用读得慢,问题在本机应用
  • Recv-Q 顶到 Send-Q(LISTEN 行上)→ accept 队列满了

第 3 层:协议栈计数器

# 只显示自上次调用以来有变化的计数器 —— 这是它最好用的地方
nstat

# 显示全部(含为 0 的),配合 grep 用
nstat -az | grep -iE 'retrans|drop|listen|overflow|ecn'

# 按秒采样看趋势
sar -n DEV 1 5      # 每网卡的收发包与字节
sar -n ETCP 1 5     # TCP 重传与错误
sar -n SOCK 1 5     # socket 数量
instat 比 netstat -s 好用在哪

nstat 默认只打印有变化的计数器,等于自带了一次差分。 排障时先跑一次清零,再复现问题,第二次的输出就只剩下和这次故障相关的项。 netstat -s 每次都把上千行全打出来,得自己找差异。

# conntrack 是容器环境的高频嫌疑
conntrack -S             # 每 CPU 的 drop / insert_failed
sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max

insert_failed 或 drop 在涨 = conntrack 表撑不住,表现为新连接随机失败。

# 软中断侧:第 2 列 dropped,第 3 列 time_squeeze
cat /proc/net/softnet_stat

# 中断落在哪些 CPU 上
cat /proc/interrupts | grep -i mlx
mpstat -P ALL 1

第 4 层:抓包

带着假设抓,而不是抓完再想。

# 只抓这个对端这个端口,限 200 个包,落盘
tcpdump -i bond0 -nn -c 200 -w /tmp/a.pcap \
  'host 10.10.1.103 and tcp port 8080'

# 只看握手与异常包(SYN / FIN / RST)
tcpdump -i bond0 -nn 'tcp[tcpflags] & (tcp-syn|tcp-fin|tcp-rst) != 0'

# overlay 隧道流量(VXLAN 8472 / Geneve 6081)
tcpdump -i bond0 -nn 'udp port 8472 or udp port 6081'

# RoCEv2 流量
tcpdump -i bond0 -nn 'udp port 4791' -c 20

几条纪律:

  • 一定要加过滤条件。生产机上 tcpdump -i any 能瞬间产生几 GB 文件并显著影响性能。
  • 一定要限量:-c 限包数、-W/-C 做滚动切分。
  • 落盘再分析:-w 存文件,用 Wireshark 慢慢看,不要在终端里肉眼滚屏。
  • 只关心包头就加 -s 96,能大幅减小文件。

压测工具:选对了才有意义

工具测什么注意
iperf -c <ip> -P 8(iperf2)TCP 吞吐,高速网卡首选每条流一个真线程,能吃满多核
iperf -u -c <ip> -l 64 -b 10G -P 8小包 PPSUDP 小包才打得出 PPS 瓶颈
iperf3 -c <ip> -P 8TCP 吞吐界面好看,但线程模型有坑,见下
qperf / sockperf延迟(含 RDMA)关注 P99 而不是平均
ib_send_bw / ib_write_latRDMA 带宽与延迟L2 会专门讲
!40G 以上别用 iperf3 —— 它压不满

iperf3 在 3.16 之前是单线程的:-P 8 只是在同一个线程里轮着跑 8 条流, 所有收发和校验都挤在一个核上。单核处理 TCP 的天花板大致在 20~30 Gbps, 所以 40G / 100G 网卡上用 iperf3 测出来的"上限"往往是那个核的上限,不是网卡的。 典型症状:结果卡在某个数字上不动,同时 mpstat -P ALL 1 显示某个核 100%。

iperf (iperf2) 从设计上就是多线程 —— -P N 起 N 个真线程,散到 N 个核上, 这才是 40G 以上唯一靠得住的姿势:

# 服务端(注意 iperf2 默认端口是 5001,iperf3 是 5201)
iperf -s

# 客户端:8 条流,每 2 秒报一次,-e 打开增强统计(含重传、CPU 占用)
iperf -c 10.10.1.103 -P 8 -t 30 -i 2 -e

# 看 [SUM] 行,不要看单条流

如果环境里只有 iperf3,替代姿势是起多个进程、每个进程绑不同核和不同端口,再手工求和:

# 服务端起 4 个实例
for p in 5201 5202 5203 5204; do iperf3 -s -p $p -D; done

# 客户端 4 个进程分别绑核
for i in 0 1 2 3; do
  taskset -c $((i+2)) iperf3 -c 10.10.1.103 -p $((5201+i)) -t 30 &
done; wait

无论用哪个,都要把结果和 ethtool -S 的计数、mpstat -P ALL 1 的 %soft 对照, 才知道瓶颈是链路、是单流窗口,还是压测工具自己的 CPU。

iiperf3 3.16 之后呢?

iperf3 3.16(2023 年)加入了多线程,每条流一个线程,情况好了很多。 但生产机上装的往往是发行版自带的老版本 —— 先 iperf3 --version 看一眼。 低于 3.16 就直接换 iperf2,不要在参数上浪费时间。

60 秒网络体检清单

拿到一台陌生机器,按顺序敲:

ip -s link show                       # 1. 哪些网卡在用,有没有错误/丢弃
ethtool <dev> | grep Speed            # 2. 速率协商对不对
ethtool -S <dev> | grep -iE 'err|drop|missed|pause'   # 3. 网卡级异常
ss -s                                 # 4. 连接总量与状态分布
nstat                                 # 5. 自上次以来变化的计数器
cat /proc/net/softnet_stat            # 6. 软中断有没有丢包/预算耗尽
mpstat -P ALL 1 3                     # 7. %soft 是否集中在单核
ip route; ip neigh                    # 8. 路由与 ARP 是否正常

八条命令,一分钟。跑完还没有线索,才轮到抓包。

检查点

Checkpoint单选

要判断「丢包发生在网卡还是协议栈」,最直接的一组命令是?

Checkpoint单选

生产机上排查间歇性连接失败,下面哪种抓包方式是可接受的?

这节课的落点

  • 固定顺序:接口 → 连接 → 协议栈 → 抓包,抓包永远放最后
  • ethtool -S 三类关键词:missed/no_buffer(CPU 跟不上)、crc/frame(物理层)、pause/pfc(流控)
  • ss -tim 看单连接,ss -lnt 看 accept 队列,ss -s 看全局分布
  • nstat 只打印有变化的计数器,天然适合"清零 → 复现 → 再看"
  • 抓包四要素:过滤、限量、只抓包头、落盘
  • 压测选 iperf(2.x) 而不是老版 iperf3:多线程才吃得满 40G 以上的网卡
  • 记住 60 秒体检的八条命令,比记住一百个参数有用

延伸资料

  • Systems Performance, 2nd Edition — Brendan Gregg
  • k8s-in-actionos/os.md