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 点,应排查: