内核丢包点追踪
接口计数只能告诉你「丢了多少」,不能告诉你「丢在哪一步」。当怀疑协议栈内部丢包时,可以追踪 skb 释放的时机:在 kfree_skb 上统计丢弃原因或记录调用栈,直接定位到具体子系统。较新内核在该追踪点提供了丢弃原因字段,老内核则需要依靠调用栈推断。
基本信息
| 工具 | bpftrace、perf 等基于内核追踪点的工具 |
|---|---|
| 追踪点 | tracepoint:skb:kfree_skb |
| 原因字段 | 较新内核提供 reason 参数,旧内核无此字段 |
| 替代方式 | 旧内核用 kprobe:kfree_skb 配合调用栈统计 |
| 开销 | 与命中次数成正比,需限定时间窗与过滤条件 |
典型使用场景
- 接口计数显示丢包,但网卡侧没有丢弃记录,怀疑丢在协议栈内部
- 连接跟踪表满导致的丢包定位
- 路由或策略丢弃的确认,例如被防火墙规则拦下
- 发送队列满导致的丢弃,与队列统计互相印证
- 内核升级前后对比丢弃原因分布的变化
统计丢弃原因
统计丢弃原因
bpftrace -e 'tracepoint:skb:kfree_skb { @[args->reason] = count(); }'
# 旧内核没有 reason 字段时,改用调用栈统计:
bpftrace -e 'kprobe:kfree_skb { @[kstack(5)] = count(); }'
# 只观察特定地址的丢弃:在表达式中加入地址过滤再统计常见丢弃来源
| 丢弃位置 | 典型原因 | 排查方向 |
|---|---|---|
| 连接跟踪 | 表容量达到上限 | 查看条目数与上限水线 |
| 路由与策略 | 无可用路由或被规则拒绝 | 核对路由表与策略配置 |
| 发送队列 | 队列已满 | 查看 qdisc 统计与队列长度 |
| 接收路径 | 内存不足或校验失败 | 检查内存压力与网卡计数 |
使用注意
- 先限定时间窗与流量条件,避免全量统计带来不可控开销
- 在测试环境先验证脚本写法,再用于生产观测
- 原因枚举随内核版本演进,解读时以本机内核为准
- 把追踪结果与接口计数、队列统计相互印证
长期在线全量统计不适合做为常态监控:追踪点命中次数与流量成正比,在丢包严重的故障机上反而会加重负担,应限定窗口并按需启用。
在无 reason 字段的内核上照搬新写法会直接报错;确认内核是否支持该字段最省事的办法是查看追踪点定义,而不是凭版本号猜测。