繁体   English   中英

bpf_map_lookup_elem 中的空值,而“bpftool map dump”确实如此

[英]Empty value from bpf_map_lookup_elem while 'bpftool map dump' does

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

我们可以在 key 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)

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

我使用ip link将我的程序附加到我的界面。 在我的 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/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)
        ...

它有效!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM