From 9b7ddbaef9a5f9da1e41f85431bb7c9b74aaae18 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 16 Jul 2026 20:26:30 +0200 Subject: [PATCH] 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 --- package/utils/ucode-mod-bpf/src/bpf.c | 77 +++++++++++++++++++++++---- 1 file changed, 67 insertions(+), 10 deletions(-) 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,20 +220,11 @@ 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; - int fd; - - if (ucv_type(path) != UC_STRING) - err_return(EINVAL, "module path"); - - fd = bpf_obj_get(ucv_string_get(path)); - if (fd < 0) - err_return(errno, NULL); err = bpf_obj_get_info_by_fd(fd, &info, &len); if (err) { @@ -245,6 +236,38 @@ uc_bpf_open_map(uc_vm_t *vm, size_t nargs) 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) + err_return(EINVAL, "module path"); + + fd = bpf_obj_get(ucv_string_get(path)); + if (fd < 0) + err_return(errno, NULL); + + 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_open_map_fd(vm, fd); +} + static uc_value_t * uc_bpf_open_program(uc_vm_t *vm, size_t nargs) { @@ -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 }, };