我有一个 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)
...
它有效!