bpf_map_lookup_elem的空值while' bpftool map dump'做

发布于 2025-01-30 06:53:56 字数 1830 浏览 3 评论 0原文

我有一个通过bpf_type_map_array在地图中存储一些统计数据的BPF程序。代码的那一侧似乎可以正常工作,我可以使用bpftool查看我的地图。

# bpftool map show
31: array  name xdp_stats_map  flags 0x0
        key 4B  value 16B  max_entries 16  memlock 4096B

# bpftool map dump id 31
key: 00 00 00 00  value: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
key: 01 00 00 00  value: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
key: 02 00 00 00  value: e3 a6 00 00 00 00 00 00  99 38 b3 00 00 00 00 00
key: 03 00 00 00  value: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
[...] 

我们可以看到有关密钥2的一些数据,并且这些数据数据已正确更新。 但是,当我尝试使用libbpf在用户空间中收集这些数据时,我只有无效的值。我不知道怎么了。

如果我伪造FD,请呼叫失败,如果我尝试获取超过16个元素,则稍后会失败,因此一切听起来都正确。

struct counters {
    __u64 rx_packets;
    __u64 rx_bytes;
};

void dies(char *str) {
    fprintf(stderr, "[-] %s", str);
    exit(EXIT_FAILURE);
}

int main(int argc, char *argv[]) {
    struct counters value;
    char *filename = "./xdp_pass.o";
    int fd;

    if(argc > 1)
        filename = argv[1];

    struct bpf_object *obj = bpf_object__open(filename);
    if(libbpf_get_error(obj))
        dies("could not open bpf object");

    bpf_object__load(obj);
    if(libbpf_get_error(obj))
        dies("could not load bpf object");

    if((fd = bpf_object__find_map_fd_by_name(obj, "xdp_stats_map")) < 0)
        dies("could not find map in the object");

    for(__u32 key = 0; key < 16; key++) {
        if((bpf_map_lookup_elem(fd, &key, &value)) != 0)
            dies("could not key in map");

        printf("ID % 3d: %llu, %llu\n", key, value.rx_packets, value.rx_bytes);
    }

    return 0;
}

返回:

ID   0: 0, 0
ID   1: 0, 0
ID   2: 0, 0
ID   3: 0, 0
ID   4: 0, 0
[...] (all zero)

I have a bpf program storing some stats in a map via BPF_TYPE_MAP_ARRAY. That side of code seems to works correctly, I can use bpftool to see my map.

# bpftool map show
31: array  name xdp_stats_map  flags 0x0
        key 4B  value 16B  max_entries 16  memlock 4096B

# bpftool map dump id 31
key: 00 00 00 00  value: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
key: 01 00 00 00  value: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
key: 02 00 00 00  value: e3 a6 00 00 00 00 00 00  99 38 b3 00 00 00 00 00
key: 03 00 00 00  value: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
[...] 

We can see some data on key 2 and theses data are updated correctly.
However when I try to collect theses data in userspace with libbpf, I only have null values. I have no clue what's wrong.

If I fake the fd, call fails, if I try to fetch more than 16 elements, it fails later, so everything sounds correct.

struct counters {
    __u64 rx_packets;
    __u64 rx_bytes;
};

void dies(char *str) {
    fprintf(stderr, "[-] %s", str);
    exit(EXIT_FAILURE);
}

int main(int argc, char *argv[]) {
    struct counters value;
    char *filename = "./xdp_pass.o";
    int fd;

    if(argc > 1)
        filename = argv[1];

    struct bpf_object *obj = bpf_object__open(filename);
    if(libbpf_get_error(obj))
        dies("could not open bpf object");

    bpf_object__load(obj);
    if(libbpf_get_error(obj))
        dies("could not load bpf object");

    if((fd = bpf_object__find_map_fd_by_name(obj, "xdp_stats_map")) < 0)
        dies("could not find map in the object");

    for(__u32 key = 0; key < 16; key++) {
        if((bpf_map_lookup_elem(fd, &key, &value)) != 0)
            dies("could not key in map");

        printf("ID % 3d: %llu, %llu\n", key, value.rx_packets, value.rx_bytes);
    }

    return 0;
}

Returns:

ID   0: 0, 0
ID   1: 0, 0
ID   2: 0, 0
ID   3: 0, 0
ID   4: 0, 0
[...] (all zero)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

绝對不後悔。 2025-02-06 06:53:56

感谢@Qeole在我的原始帖子的评论中。这是解决问题的方法:

我使用IP链接将我的程序附加到接口。在我的BPF地图的定义中,我添加了一个固定选项libbpf_pin_by_name

struct {
    __uint(type, BPF_MAP_TYPE_ARRAY);
    __uint(key_size, sizeof(__u32));
    __uint(value_size, sizeof(struct xdp_stats));
    __uint(pinning, LIBBPF_PIN_BY_NAME);
    __uint(max_entries, 16);

} xdp_stats_map SEC(".maps");

这样,tc将自动pin> pin> pin将映射到> /sys/fs/bpf/tc/globals/xdp_stats_map

在我的用户空间程序中,我现在可以直接获取该FD:

int fd = bpf_obj_get("/sys/fs/bpf/tc/globals/xdp_stats_map");

for(__u32 key = 0; key < 16; key++) {
    if((bpf_map_lookup_elem(fd, &key, &value)) != 0)
        ...

它可以使用!

Thanks to @Qeole in the comment of my original post. Here is how I solved my problem:

I use ip link to attach my program to my interface. In the definition of my bpf map, I added a pinning option LIBBPF_PIN_BY_NAME:

struct {
    __uint(type, BPF_MAP_TYPE_ARRAY);
    __uint(key_size, sizeof(__u32));
    __uint(value_size, sizeof(struct xdp_stats));
    __uint(pinning, LIBBPF_PIN_BY_NAME);
    __uint(max_entries, 16);

} xdp_stats_map SEC(".maps");

With this way, tc will automatically pin the map to /sys/fs/bpf/tc/globals/xdp_stats_map.

In my userspace program, I can directly fetch that fd now:

int fd = bpf_obj_get("/sys/fs/bpf/tc/globals/xdp_stats_map");

for(__u32 key = 0; key < 16; key++) {
    if((bpf_map_lookup_elem(fd, &key, &value)) != 0)
        ...

And it works !

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文