c - 从 bpf_map_lookup_elem 清空 value 而 'bpftool map dump' 确实

我有一个 bpf 程序通过 BPF_TYPE_MAP_ARRAY 在 map 中存储一些统计信息。代码的那一边似乎工作正常,我可以使用 bpftool 来查看我的 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
[...]

我们可以在 key 2 上看到一些数据,并且这些数据已正确更新。但是,当我尝试使用 libbpf 在用户空间中收集这些数据时,我只有 null values。我不知道出了什么问题。

如果我伪造 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)

回答1

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

我使用 ip link 将我的程序附加到我的界面。在我的 bpf map 的定义中,我添加了一个固定选项 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 的map 转为/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)
        ...

它有效!

相似文章

twilio - DevTools 无法加载源 map

我知道Chrome开发工具中有很多关于这些警告的帖子。对于所有这些,解决方案是关闭通知“启用javascript源maps”和“启用CSS源maps”。我想知道的是如何解决这个问题,以及导致这些警告的...

最新文章