多网卡场景下eBPF tracepoint netif_receive_skb追踪异常咨询
问题分析与解决方案
核心结论
netif_receive_skb tracepoint是全局共享的,并非每个网卡对应独立实例。所有网卡的数据包只要进入Linux网络栈的接收路径,都会触发该tracepoint。你遇到的双网卡下部分数据包无法捕获的问题,核心原因是代码中使用了错误的tracepoint参数结构体,导致无法正确获取sk_buff(skb)指针,进而没有执行后续的捕获逻辑。
问题根源
你的代码中,SEC("tp/net/netif_receive_skb")对应的tracepoint参数结构体应该是struct trace_event_raw_netif_receive_skb,但你错误地使用了struct trace_event_raw_consume_skb——这两个结构体属于不同的tracepoint,字段定义完全不同,导致BPF_CORE_READ(args, skbaddr)读取的skb地址无效,后续trace_skb逻辑无法正常执行,表现为部分数据包无法被捕获。
修正后的代码示例
#include <vmlinux.h> #include <bpf/bpf_helpers.h> #include <bpf/bpf_core_read.h> #define TP_NETIF_RECEIVE_SKB 1 static int trace_skb(struct sk_buff *skb, int tp_type) { // 读取数据包所属的网卡索引,用于验证是否捕获到多网卡的包 __u32 ifindex = BPF_CORE_READ(skb, dev, ifindex); bpf_printk("Captured packet on interface: %d", ifindex); // 这里添加你原有的数据包处理逻辑 return 0; } SEC("tp/net/netif_receive_skb") int net_netif_receive_skb(struct trace_event_raw_netif_receive_skb *args) { // 正确读取netif_receive_skb tracepoint的skb指针 struct sk_buff *skb = BPF_CORE_READ(args, skb); return trace_skb(skb, TP_NETIF_RECEIVE_SKB); } char _license[] SEC("license") = "GPL";
额外排查点
如果修正后仍存在部分网卡数据包无法捕获的情况,可以检查以下内容:
- XDP程序干扰:如果次要网卡加载了XDP程序(如
XDP_DROP或XDP_REDIRECT),数据包会在进入netif_receive_skb之前被处理,不会触发该tracepoint。 - 硬件卸载配置:部分网卡开启的硬件卸载功能(如TCP分段卸载、巨型帧合并)可能导致数据包绕过
netif_receive_skb路径,但这种情况非常罕见。 - 内核版本兼容性:不同内核版本的tracepoint结构体可能存在差异,确保使用
bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h生成对应内核版本的头文件,并通过BPF CORE特性兼容不同版本。
内容的提问来源于stack exchange,提问作者hundredmiles
相关产品推荐
相关产品推荐

