]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
ucode-mod-bpf: add map-in-map and prog array support
authorFelix Fietkau <nbd@nbd.name>
Thu, 16 Jul 2026 18:26:30 +0000 (20:26 +0200)
committerFelix Fietkau <nbd@nbd.name>
Mon, 20 Jul 2026 08:43:36 +0000 (10:43 +0200)
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 <nbd@nbd.name>
package/utils/ucode-mod-bpf/src/bpf.c

index d32c7ec45eb4800261e4626cace3e29c99da5166..8e1c9b219e97066ea58ca9ba64c4f7047e4de189 100644 (file)
@@ -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 },
 };