On Tue, Jul 27, 2021 at 8:05 PM G <chapterk93@xxxxxxx> wrote: > > Hi BPF Experts > > I'm having an issue with using "BPF_MAP_TYPE_DEVMAP" when pinning it to a global path for sharing with multiple programs. > I used iproute2 to load the program, the parameters for creating a map are as follows: > ---------------------------------------------------------------------------------- > struct bpf_elf_map BPFM_SEC_MAPS dev_map_test = { > .type = BPF_MAP_TYPE_DEVMAP, > .size_key = sizeof(int32), > .size_value = sizeof(int32), > .max_elem = 1, > .flags = 0, > .pinning = PIN_GLOBAL_NS, > }; > ---------------------------------------------------------------------------------- > > Here I set the flags to 0, but the actual map is created with flags 0x80, so when the second program is loaded, map parameter check is incorrect. > When I tried to set the flags directly to 0x80, I failed with the parameter error `-EINVA` when the first program was loaded > The general process for iproute2 to create a map with a pin tag is as follows: > ----------------------------------------------------------------------------------- > bpf_map_attach > -> bpf_probe_pinned > bpf_map_selfcheck_pinned > -> bpf_derive_elf_map_from_fdinfo > bpf_map_pin_report > -> if (obj->flags != pin->flags) > fprintf(stderr, " - Flags: %#x (obj) != %#x (pin)\n", obj->flags, pin->flags); > ----------------------------------------------------------------------------------- > > I have tried to read the relevant kernel code : > ----------------------------------------------------------------------------------- > // kernel/bpf/devmap.c > #define DEV_CREATE_FLAG_MASK \ > (BPF_F_NUMA_NODE | BPF_F_RDONLY | BPF_F_WRONLY) > > static int dev_map_init_map(struct bpf_dtab *dtab, union bpf_attr *attr) > { > ... > /* check sanity of attributes */ > if (attr->max_entries == 0 || attr->key_size != 4 || > attr->value_size != 4 || attr->map_flags & ~DEV_CREATE_FLAG_MASK) > return -EINVAL; > > /* Lookup returns a pointer straight to dev->ifindex, so make sure the > * verifier prevents writes from the BPF side > */ > attr->map_flags |= BPF_F_RDONLY_PROG; > ... > } > ----------------------------------------------------------------------------------- > > At the time of check , it does not allow 0x80 to be set (DEV_CREATE_FLAG_MASK) , but then the code sets the 0x80 flag itself. It looks like the kernel itself is setting the flags to 0x80 when it initializes a devmap[1]. (Note: BPF_PROG_READONLY is 0x80.[2]) I believe you do not need to worry about setting this flag when you call the BPF_MAP_CREATE syscall. [1] https://elixir.bootlin.com/linux/v5.13.5/source/kernel/bpf/devmap.c#L126 [2] https://elixir.bootlin.com/linux/v5.13.5/source/include/uapi/linux/bpf.h#L1179 > So I'm not sure if we should allow 0x80 on the check here as well ? If anyone has suggestions please let me know, thanks. > ----------------------------------------------------------------------------------- > #define DEV_CREATE_FLAG_MASK \ > (BPF_F_NUMA_NODE | BPF_F_RDONLY | BPF_F_WRONLY | BPF_F_RDONLY_PROG) > ----------------------------------------------------------------------------------- > > Best regards > W.Gao