From: Felix Fietkau Date: Thu, 16 Jul 2026 18:26:30 +0000 (+0200) Subject: ucode-mod-bpf: add map-in-map and prog array support X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9b7ddbaef9a5f9da1e41f85431bb7c9b74aaae18;p=thirdparty%2Fopenwrt.git ucode-mod-bpf: add map-in-map and prog array support Updates on array/hash-of-maps and prog array maps take the fd of the inner object as a 4-byte value. Accept bpf.map and bpf.program resources as map values and convert them to their fd. Lookups on map-in-map types return the inner map id; add open_map_id and open_program_id to obtain a usable object from such an id. Signed-off-by: Felix Fietkau --- diff --git a/package/utils/ucode-mod-bpf/src/bpf.c b/package/utils/ucode-mod-bpf/src/bpf.c index d32c7ec45eb..8e1c9b219e9 100644 --- a/package/utils/ucode-mod-bpf/src/bpf.c +++ b/package/utils/ucode-mod-bpf/src/bpf.c @@ -220,12 +220,26 @@ uc_bpf_prog_create(uc_vm_t *vm, uc_value_t *mod, int fd, bool close) } static uc_value_t * -uc_bpf_open_map(uc_vm_t *vm, size_t nargs) +uc_bpf_open_map_fd(uc_vm_t *vm, int fd) { struct bpf_map_info info; - uc_value_t *path = uc_fn_arg(0); __u32 len = sizeof(info); int err; + + err = bpf_obj_get_info_by_fd(fd, &info, &len); + if (err) { + close(fd); + err_return(errno, NULL); + } + + return uc_bpf_map_create(vm, NULL, fd, info.type, info.key_size, + info.value_size, true); +} + +static uc_value_t * +uc_bpf_open_map(uc_vm_t *vm, size_t nargs) +{ + uc_value_t *path = uc_fn_arg(0); int fd; if (ucv_type(path) != UC_STRING) @@ -235,14 +249,23 @@ uc_bpf_open_map(uc_vm_t *vm, size_t nargs) if (fd < 0) err_return(errno, NULL); - err = bpf_obj_get_info_by_fd(fd, &info, &len); - if (err) { - close(fd); + return uc_bpf_open_map_fd(vm, fd); +} + +static uc_value_t * +uc_bpf_open_map_id(uc_vm_t *vm, size_t nargs) +{ + uc_value_t *id = uc_fn_arg(0); + int fd; + + if (ucv_type(id) != UC_INTEGER) + err_return(EINVAL, "map id"); + + fd = bpf_map_get_fd_by_id(ucv_int64_get(id)); + if (fd < 0) err_return(errno, NULL); - } - return uc_bpf_map_create(vm, NULL, fd, info.type, info.key_size, - info.value_size, true); + return uc_bpf_open_map_fd(vm, fd); } static uc_value_t * @@ -261,6 +284,22 @@ uc_bpf_open_program(uc_vm_t *vm, size_t nargs) return uc_bpf_prog_create(vm, NULL, fd, true); } +static uc_value_t * +uc_bpf_open_program_id(uc_vm_t *vm, size_t nargs) +{ + uc_value_t *id = uc_fn_arg(0); + int fd; + + if (ucv_type(id) != UC_INTEGER) + err_return(EINVAL, "program id"); + + fd = bpf_prog_get_fd_by_id(ucv_int64_get(id)); + if (fd < 0) + err_return(errno, NULL); + + return uc_bpf_prog_create(vm, NULL, fd, true); +} + static uc_value_t * uc_bpf_module_get_maps(uc_vm_t *vm, size_t nargs) { @@ -362,6 +401,22 @@ uc_bpf_map_arg(uc_value_t *val, const char *kind, unsigned int size, break; return ucv_string_get(val); + case UC_RESOURCE: { + struct uc_bpf_fd *f; + + f = ucv_resource_data(val, "bpf.map"); + if (!f) + f = ucv_resource_data(val, "bpf.program"); + if (!f) + err_return(EINVAL, "%s type", kind); + + if (size != 4) + break; + + *(uint32_t *)val_int = f->fd; + + return val_int; + } default: err_return(EINVAL, "%s type", kind); } @@ -962,7 +1017,9 @@ static const uc_function_list_t global_fns[] = { { "set_debug_handler", uc_bpf_set_debug_handler }, { "open_module", uc_bpf_open_module }, { "open_map", uc_bpf_open_map }, + { "open_map_id", uc_bpf_open_map_id }, { "open_program", uc_bpf_open_program }, + { "open_program_id", uc_bpf_open_program_id }, { "tc_detach", uc_bpf_tc_detach }, };