eBPF XDP程序加载出现bad map relocation错误,内核升级至6.5.0后触发
问题分析与解决方法
问题原因
内核6.5.0版本对eBPF程序中XSKMAP的使用逻辑做了严格更新,当程序同时存在多个map时,libbpf的重定位处理逻辑与新内核的校验规则不兼容,尤其是对XSKMAP同时执行bpf_map_lookup_elem查询和bpf_redirect_map重定向操作时,极易触发bad map relo错误。
解决方法
方法1:移除不必要的XSKMAP查询操作
bpf_redirect_map本身会自动校验指定队列索引是否关联了AF_XDP套接字,无需提前调用bpf_map_lookup_elem判断。修改后的代码如下:
struct { __uint(type, BPF_MAP_TYPE_XSKMAP); __type(key, __u32); __type(value, __u32); __uint(max_entries, 64); } xsks_map SEC(".maps"); struct { __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); __type(key, __u32); __type(value, __u32); __uint(max_entries, 64); } xdp_stats_map SEC(".maps"); SEC("xdp") int xdp_sock_prog(struct xdp_md *ctx) { int index = ctx->rx_queue_index; __u32 *pkt_count = bpf_map_lookup_elem(&xdp_stats_map, &index); // 补充统计计数逻辑(可选) if (pkt_count) { (*pkt_count)++; } // 直接执行重定向,无需提前查询XSKMAP int ret = bpf_redirect_map(&xsks_map, index, 0); if (ret == XDP_REDIRECT) { return ret; } return XDP_PASS; }
方法2:调整map声明顺序
将XSKMAP的声明放在所有其他map之后,让libbpf生成的重定位信息符合新内核的校验要求:
// 先声明统计map struct { __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); __type(key, __u32); __type(value, __u32); __uint(max_entries, 64); } xdp_stats_map SEC(".maps"); // 后声明XSKMAP struct { __uint(type, BPF_MAP_TYPE_XSKMAP); __type(key, __u32); __type(value, __u32); __uint(max_entries, 64); } xsks_map SEC(".maps"); SEC("xdp") int xdp_sock_prog(struct xdp_md *ctx) { int index = ctx->rx_queue_index; __u32 *pkt_count; pkt_count = bpf_map_lookup_elem(&xdp_stats_map, &index); if (bpf_map_lookup_elem(&xsks_map, &index)) { return bpf_redirect_map(&xsks_map, index, 0); } return XDP_PASS; }
方法3:升级libbpf到最新版本
旧版本libbpf未适配6.5内核的eBPF重定位规则,升级到v1.2.0及以上版本的libbpf,可从根源上解决这类兼容性问题。
内容的提问来源于stack exchange,提问作者pedro_m
相关产品推荐
相关产品推荐

