ping正常但业务丢包是因为ICMP与业务流量路径不同,前者走完整协议栈,后者可能在网卡驱动、XDP、TC ingress或softirq前被丢弃;tracepoint:net:netif_receive_skb仅记录skb进入点,不反映后续过滤或静默丢弃,需结合bpftrace验证是否到达该点,并排查上游环节。

为什么 ping 正常但业务流量丢包?
因为 ping 走的是 ICMP 协议栈,而业务流量(如 HTTP、TCP 连接)在进入协议栈前可能被更早的路径丢弃——比如网卡驱动、XDP、TC ingress、甚至 netif_receive_skb 之前的 softirq 上下文。该 tracepoint 触发点虽在「接收软中断入口」,但已跳过 DMA 拷贝完成、NAPI poll、GRO 合并等前置环节,所以看到它被触发,说明 skb 至少已成功从驱动队列取出;但若这里没被 trace 到,问题大概率出在更上游。
tracepoint:net:netif_receive_skb 能捕获到哪些丢包?
它只记录最终调用 netif_receive_skb 的那一刻,不反映后续是否被过滤、重定向或静默丢弃。真正丢包发生在其内部:比如 tc_classify() 返回 TC_ACT_SHOT、ip_rcv() 因 checksum 错误返回 NET_RX_DROP、或被 iptables 的 -j DROP 截断。因此,仅靠这个 tracepoint 统计「进入次数」和「业务包数量对比」只能辅助判断是否在入口前就丢失,不能定位具体丢弃点。
怎么用 bpftrace 实时验证是否真没走到这个 tracepoint?
运行以下脚本观察是否有匹配输出:
bpftrace -e '
tracepoint:net:netif_receive_skb {
$skb = (struct sk_buff*)arg0;
$len = ((struct sk_buff*)arg0)->len;
$proto = ((struct sk_buff*)arg0)->protocol;
printf("skb=%p len=%d proto=0x%x\\n", $skb, $len, $proto);
}
'
如果业务请求发出后长期无输出,说明包根本没到达该 hook 点,应排查:
- NIC 驱动是否启用 RPS/RFS/XPS 不当,导致部分 CPU 核心未处理对应队列
- 是否启用了 XDP 程序且在
xdp_drop或xdp_abort -
/proc/sys/net/core/netdev_max_backlog是否过小,引发 softirq 处理延迟甚至丢包 - 网卡 ring buffer 溢出(
ethtool -S eth0 | grep -i "drop\|over"查rx_missed_errors或rx_over_errors)
偶发丢包时 tracepoint 数据怎么看?
加时间戳与 CPU ID 可辅助关联上下文:
bpftrace -e '
tracepoint:net:netif_receive_skb /pid == 0/ {
@count[comm, cpu] = count();
@len[comm] = hist((int) ((struct sk_buff*)arg0)->len);
}
interval:s:1 { print(@count); clear(@count); print(@len); clear(@len); }
'
重点关注:
- 是否某 CPU 上
@count明显偏低(指向 RPS 分布不均或 softirq 压力大) - 是否大量小包(
len在 60–70 字节)集中出现,却无对应应用日志(暗示 ARP、ICMP 或探测包干扰) -
comm中是否出现ksoftirqd占比异常高(说明 net rx softirq 处理不过来)
真正棘手的偶发丢包,往往不在 netif_receive_skb 这一层暴露,而是藏在驱动收包中断响应延迟、ring buffer 溢出、或 XDP/TC 规则中无日志的静默 drop 里。别只盯着这个 tracepoint 数数,先确认它到底有没有机会被调用。








