You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

加载《Learning eBPF》示例eBPF/XDP程序至内核失败,求解决方案

问题描述

尝试加载《Learning eBPF》中的XDP示例程序时失败,执行加载命令:

sudo bpftool prog load hello.bpf.o /sys/fs/bpf/hello

核心报错信息:

libbpf: bpf: relocation: not yet supported relo for non-static global 'counter' variable found in insns[0].code 0x18

原示例代码:

#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>

int counter = 0;

SEC("xdp")
int hello(struct xdp_md *ctx) {
    bpf_printk("Hello World %d", counter);
    counter++;
    return XDP_PASS;
}

char LICENSE[] SEC("license") = "Dual BSD/GPL";
解决方法

1. 修改代码适配eBPF状态存储规则

内核不支持非静态全局变量的重定位,且普通全局变量无法跨eBPF调用持久化状态,需改用eBPF数组Map存储计数器。修改后的代码:

#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>

// 定义数组Map,用于存储计数器,仅需1个条目
struct {
    __uint(type, BPF_MAP_TYPE_ARRAY);
    __uint(max_entries, 1);
    __type(key, int);
    __type(value, int);
} counter_map SEC(".maps");

SEC("xdp")
int hello(struct xdp_md *ctx) {
    int key = 0;
    int *counter = bpf_map_lookup_elem(&counter_map, &key);
    
    // 确保成功获取计数器指针后再操作
    if (counter) {
        bpf_printk("Hello World %d", *counter);
        (*counter)++;
    }
    
    return XDP_PASS;
}

char LICENSE[] SEC("license") = "Dual BSD/GPL";

2. 重新编译与加载

用clang重新编译代码(以x86架构为例):

clang -target bpf -D__TARGET_ARCH_x86_64 -I/usr/include/x86_64-linux-gnu -O2 -c hello.bpf.c -o hello.bpf.o

执行加载命令:

sudo bpftool prog load hello.bpf.o /sys/fs/bpf/hello

3. 验证运行效果

通过内核日志查看程序输出:

sudo dmesg -w

当有数据包流经绑定该XDP程序的网卡时,会看到递增的Hello World X日志。

关键原因
  • eBPF内核加载器不支持非静态全局变量的重定位操作,必须改用静态变量或Map存储数据。
  • 普通静态全局变量无法在eBPF程序的多次调用间保持状态,而eBPF Map是内核维护的持久化存储结构,适合跨调用保存计数这类状态数据。

内容的提问来源于stack exchange,提问作者Andy R

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 23:47:50