I try to get the fd of the BPF_MAP_TYPE_XSKMAP
in my user-space program.
This is the code:
ret = bpf_get_link_xdp_id(cfg->ifindex, &cfg->prog_id, cfg->xdp_flags); if (ret) { fprintf(stderr, "`bpf_get_link_xdp_id` returned error: %sn", strerror(errno)); exit(-ret); } cfg->prog_fd = bpf_prog_get_fd_by_id(cfg->prog_id); if(cfg->prog_fd < 0) { fprintf(stderr, "Failed to obtain prog_fd: %sn", strerror(errno)); exit(1); } struct bpf_prog_info prog_info; uint32_t prog_info_len = sizeof(struct bpf_prog_info); uint32_t map_info_len = sizeof(struct bpf_map_info); if(bpf_obj_get_info_by_fd(cfg->prog_fd, &prog_info, &prog_info_len) == 0) { const uint32_t amnt_of_maps = prog_info.nr_map_ids; uint32_t *map_ids = (uint32_t*)malloc(sizeof(uint32_t) * prog_info.nr_map_ids); memset(&prog_info, 0, prog_info_len); prog_info.nr_map_ids = amnt_of_maps; prog_info.map_ids = (uint64_t)(unsigned long)map_ids; if(bpf_obj_get_info_by_fd(cfg->prog_fd, &prog_info, &prog_info_len) == 0) { for(uint32_t i = 0; i < prog_info.nr_map_ids; i++) { const int map_fd = bpf_map_get_fd_by_id(map_ids[i]); if(map_fd >= 0) { struct bpf_map_info map_info; if(bpf_obj_get_info_by_fd(map_fd, &map_info, &map_info_len) == 0) { if(strcmp(map_info.name, "xsks_map") == 0) { cfg->xsks_map_fd = map_fd; printf("Got fd of xsks_map!n"); break; } } else { close(map_fd); } } else { fprintf(stderr, "Failed to obtain map_fd for id %d: %sn", i, strerror(errno)); } } } else { fprintf(stderr, "Failed to obtain prog_info 2: %sn", strerror(errno)); } } else { fprintf(stderr, "Failed to obtain prog_info 1: %sn", strerror(errno)); }
But unfortunately, I get an error for calling bpf_obj_get_info_by_fd(cfg->prog_fd, &prog_info, &prog_info_len)
: Failed to obtain prog_info 1: Invalid argument
.
I don’t know if this is because the XDP-program is loaded from another process? Does the same process have to obtain program information which also loaded the AF-XDP program?
Edit: The only thing I changed in my user-space program was to populate a BPF_MAP_TYPE_HASH
via bpf_map_update_elem
(the entries are in there, observed with bpftool map dump id <id>
) and to use bpf_map_lookup_elem
in my XDP-program (same hash map).
And suddenly, the error changes to:
Failed to obtain prog_info 1: Bad address
Advertisement
Answer
There is a comment in a function from the kernel code called when you try to retrieve information about your program, stating:
/* If we’re handed a bigger struct than we know of, ensure all the unknown bits are 0 – i.e. new user-space does not rely on any kernel feature extensions we don’t know about yet. […] */
I think this is what you hit in your case. Your libbpf version might use some attributes in struct bpf_prog_info
that the kernel is not aware of.
To ensure that the kernel accepts it, simply try to zero-initialise your struct:
struct bpf_prog_info prog_info = {};