]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
libbpf: Add support for associating BPF program with struct_ops
authorAmery Hung <ameryhung@gmail.com>
Wed, 3 Dec 2025 23:37:45 +0000 (15:37 -0800)
committerAndrii Nakryiko <andrii@kernel.org>
Sat, 6 Dec 2025 00:17:57 +0000 (16:17 -0800)
Add low-level wrapper and libbpf API for BPF_PROG_ASSOC_STRUCT_OPS
command in the bpf() syscall.

Signed-off-by: Amery Hung <ameryhung@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20251203233748.668365-4-ameryhung@gmail.com
tools/lib/bpf/bpf.c
tools/lib/bpf/bpf.h
tools/lib/bpf/libbpf.c
tools/lib/bpf/libbpf.h
tools/lib/bpf/libbpf.map

index b66f5fbfbbb291c1d6b5b2c98613712f2b0b8115..21b57a62991677d0a1f2f689fa0807b98f3ae5f8 100644 (file)
@@ -1397,3 +1397,22 @@ int bpf_prog_stream_read(int prog_fd, __u32 stream_id, void *buf, __u32 buf_len,
        err = sys_bpf(BPF_PROG_STREAM_READ_BY_FD, &attr, attr_sz);
        return libbpf_err_errno(err);
 }
+
+int bpf_prog_assoc_struct_ops(int prog_fd, int map_fd,
+                             struct bpf_prog_assoc_struct_ops_opts *opts)
+{
+       const size_t attr_sz = offsetofend(union bpf_attr, prog_assoc_struct_ops);
+       union bpf_attr attr;
+       int err;
+
+       if (!OPTS_VALID(opts, bpf_prog_assoc_struct_ops_opts))
+               return libbpf_err(-EINVAL);
+
+       memset(&attr, 0, attr_sz);
+       attr.prog_assoc_struct_ops.map_fd = map_fd;
+       attr.prog_assoc_struct_ops.prog_fd = prog_fd;
+       attr.prog_assoc_struct_ops.flags = OPTS_GET(opts, flags, 0);
+
+       err = sys_bpf(BPF_PROG_ASSOC_STRUCT_OPS, &attr, attr_sz);
+       return libbpf_err_errno(err);
+}
index e983a3e40d61204dabf6ce1d21bea6d08636ff8a..1f9c28d27795cd09180f11a29ff016adef88693e 100644 (file)
@@ -733,6 +733,27 @@ struct bpf_prog_stream_read_opts {
 LIBBPF_API int bpf_prog_stream_read(int prog_fd, __u32 stream_id, void *buf, __u32 buf_len,
                                    struct bpf_prog_stream_read_opts *opts);
 
+struct bpf_prog_assoc_struct_ops_opts {
+       size_t sz;
+       __u32 flags;
+       size_t :0;
+};
+#define bpf_prog_assoc_struct_ops_opts__last_field flags
+
+/**
+ * @brief **bpf_prog_assoc_struct_ops** associates a BPF program with a
+ * struct_ops map.
+ *
+ * @param prog_fd FD for the BPF program
+ * @param map_fd FD for the struct_ops map to be associated with the BPF program
+ * @param opts optional options, can be NULL
+ *
+ * @return 0 on success; negative error code, otherwise (errno is also set to
+ * the error code)
+ */
+LIBBPF_API int bpf_prog_assoc_struct_ops(int prog_fd, int map_fd,
+                                        struct bpf_prog_assoc_struct_ops_opts *opts);
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
index 3dc8a807881551bae23447033f8a7ed276a8e269..c7c79014d46cf43551017776f72aa442330f1ff8 100644 (file)
@@ -14133,6 +14133,37 @@ int bpf_program__set_attach_target(struct bpf_program *prog,
        return 0;
 }
 
+int bpf_program__assoc_struct_ops(struct bpf_program *prog, struct bpf_map *map,
+                                 struct bpf_prog_assoc_struct_ops_opts *opts)
+{
+       int prog_fd, map_fd;
+
+       prog_fd = bpf_program__fd(prog);
+       if (prog_fd < 0) {
+               pr_warn("prog '%s': can't associate BPF program without FD (was it loaded?)\n",
+                       prog->name);
+               return libbpf_err(-EINVAL);
+       }
+
+       if (prog->type == BPF_PROG_TYPE_STRUCT_OPS) {
+               pr_warn("prog '%s': can't associate struct_ops program\n", prog->name);
+               return libbpf_err(-EINVAL);
+       }
+
+       map_fd = bpf_map__fd(map);
+       if (map_fd < 0) {
+               pr_warn("map '%s': can't associate BPF map without FD (was it created?)\n", map->name);
+               return libbpf_err(-EINVAL);
+       }
+
+       if (!bpf_map__is_struct_ops(map)) {
+               pr_warn("map '%s': can't associate non-struct_ops map\n", map->name);
+               return libbpf_err(-EINVAL);
+       }
+
+       return bpf_prog_assoc_struct_ops(prog_fd, map_fd, opts);
+}
+
 int parse_cpu_mask_str(const char *s, bool **mask, int *mask_sz)
 {
        int err = 0, n, len, start, end = -1;
index 65e68e964b89894c2f5c4b19c58f0e1c150ea8a8..e14d9e349f9c1759230549707517441584dd8dce 100644 (file)
@@ -1006,6 +1006,22 @@ LIBBPF_API int
 bpf_program__set_attach_target(struct bpf_program *prog, int attach_prog_fd,
                               const char *attach_func_name);
 
+struct bpf_prog_assoc_struct_ops_opts; /* defined in bpf.h */
+
+/**
+ * @brief **bpf_program__assoc_struct_ops()** associates a BPF program with a
+ * struct_ops map.
+ *
+ * @param prog BPF program
+ * @param map struct_ops map to be associated with the BPF program
+ * @param opts optional options, can be NULL
+ *
+ * @return 0, on success; negative error code, otherwise
+ */
+LIBBPF_API int
+bpf_program__assoc_struct_ops(struct bpf_program *prog, struct bpf_map *map,
+                             struct bpf_prog_assoc_struct_ops_opts *opts);
+
 /**
  * @brief **bpf_object__find_map_by_name()** returns BPF map of
  * the given name, if it exists within the passed BPF object
index 8ed8749907d472c9e8da781be4ee79c7199324db..84fb90a016c9c042179e42ef521ee714d4123c5f 100644 (file)
@@ -451,4 +451,6 @@ LIBBPF_1.7.0 {
        global:
                bpf_map__set_exclusive_program;
                bpf_map__exclusive_program;
+               bpf_prog_assoc_struct_ops;
+               bpf_program__assoc_struct_ops;
 } LIBBPF_1.6.0;