dropwatch:抓内核协议栈在哪里丢包
更新时间:2026-09-19。当
netstat -s、网卡统计显示有丢包,却分不清是在驱动、协议栈还是防火墙丢的,dropwatch 能监控内核释放 skb(kfree_skb)的位置,给出「丢在哪个内核函数」,把丢包定位从猜变成看。
一、它监测什么
内核在协议栈各层决定丢弃一个报文时,最终都会释放对应的 socket buffer(kfree_skb / skb_drop_reason)。dropwatch 通过内核 trace 机制采样这些事件,输出丢弃点的内核符号/地址和次数:
bash
dropwatch> start
1 drops at tcp_v4_rcv+... # TCP 层丢弃(如监听队列满、校验错误)
24 drops at nf_hook_slow+... # netfilter/nftables 规则丢弃
8 drops at __netif_receive_skb... # 网卡接收路径(队列/RPS)命令行直接监控一段时间:
bash
sudo dropwatch -l kas # 交互式(kas = 解析内核符号)
dropwatch> start
dropwatch> stop
dropwatch> exit
# 非交互:监控 30 秒输出一次
sudo dropwatch -l kas <<EOF
start
exit
EOF依赖:需要内核符号(vmlinux/debuginfo 或 kallsyms)和相关内核模块,部分发行版需安装 dropwatch 包;现代内核也可用 perf trace、eBPF(如 tracepoint:skb:kfree_skb)达到类似效果。
二、常见丢弃点与含义
| 内核位置(近似) | 典型原因 | 进一步确认 |
|---|---|---|
__netif_receive_skb_core/驱动 NAPI | 软中断处理不过来、ring 满、RPS 不均 | mpstat 看 %soft、ethtool -S |
nf_hook_slow/iptable/nft | 防火墙规则 DROP、安全组 | 检查 iptables/nftables、conntrack 表 |
nf_conntrack 满 | conntrack 表溢出、超时 | nf_conntrack_count/max、dmesg |
tcp_v4_rcv/listen 路径 | accept 队列(backlog)满、半连接队列满、RST | ss -l 看 Recv-Q、backlog 调优 |
ip_forward/路由 | 路由不可达、reverse path filter | 路由表、rp_filter、MTU |
| socket 缓冲区 | 接收 buffer 满、应用读得慢 | ss -m、netstat -su(UDP) |
三、定位流程
- 先确认确实在丢:
netstat -s看packet receive errors、times the listen queue...overflowed;ethtool -S eth0 | grep -i drop看是网卡丢还是进栈后丢。 - dropwatch 看丢弃函数:定位到层(驱动/netfilter/TCP/socket)。
- 结合针对性工具:
- 网卡/软中断层 →
mpstat -P ALL、/proc/net/softnet_stat、网卡队列统计(多队列 RSS)。 - 防火墙 → 临时把可疑 DROP 改 LOG/REJECT 验证。
- 监听队列满 →
ss -ltn看 Recv-Q 与 backlog。
- 网卡/软中断层 →
- 抓包对照:在入口和本机同时 tcpdump,确认报文是否到达、是否回 RST。
四、与 perf/eBPF 的关系
dropwatch 适合快速定位「丢在哪个内核函数」;若要带调用栈、按进程/五元组细分,可用:
bash
# perf 监听 skb 释放点
sudo perf trace -e skb:kfree_skb
# bpftrace 一行统计丢弃原因(较新内核有 reason)
sudo bpftrace -e 'tracepoint:skb:kfree_skb { @[kstack] = count(); }'bpftrace 用法见 bpftrace 一行命令。
坑
- 没装内核符号,输出只有裸地址看不懂;先准备好 debuginfo/kallsyms。
- 看到 kfree_skb 就当成异常:正常 RST、TTL 到期、重复包也会释放,需结合 reason 和业务判断。
- 只在稳态短采样,错过周期性丢包;应在故障复现时或延长监控窗口。
- 容器/overlay 网络下丢弃点可能在 bridge/veth/conntrack,需结合网络命名空间分析。
总结
dropwatch 通过监控内核释放报文的 kfree_skb 事件并解析出丢弃发生的函数位置,把笼统的「有丢包」细分到网卡 NAPI、netfilter、conntrack、TCP backlog 或 socket 缓冲等具体层级;定位时先用 netstat -s 和 ethtool -S 确认丢包存在与大致层,再用 dropwatch 锁定函数,最后配合 mpstat、ss、iptables 和 tcpdump 查根因,需要更细调用栈时可用 perf trace 或 bpftrace 的 skb:kfree_skb 跟踪点。