libbpf: Support attaching struct_ops to a cgroup

Add bpf_map__attach_cgroup_opts() to attach a struct_ops map to a cgroup
through a BPF link.

Also extend struct bpf_prog_query_opts with a type_id field so a
BPF_STRUCT_OPS query on a cgroup can select the struct_ops type to
enumerate.

Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
Signed-off-by: Amery Hung <ameryhung@gmail.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
Link: https://patch.msgid.link/20260917200542.3689605-14-ameryhung@gmail.com
This commit is contained in:
Martin KaFai Lau authored and Andrii Nakryiko committed 2026-10-02 05:41:50 -07:00
1 parent bc48d4e164
commit ab48c6f1ba
5 files changed
+72 -1

No files matched your search

+2
View File
@@ -934,6 +934,7 @@ int bpf_link_create(int prog_fd, int target_fd,
case BPF_CGROUP_GETSOCKOPT:
case BPF_CGROUP_SETSOCKOPT:
case BPF_LSM_CGROUP:
case BPF_STRUCT_OPS:
relative_fd = OPTS_GET(opts, cgroup.relative_fd, 0);
relative_id = OPTS_GET(opts, cgroup.relative_id, 0);
if (relative_fd && relative_id)
@@ -1056,6 +1057,7 @@ int bpf_prog_query_opts(int target, enum bpf_attach_type type,
attr.query.attach_type = type;
attr.query.query_flags = OPTS_GET(opts, query_flags, 0);
attr.query.count = OPTS_GET(opts, count, 0);
attr.query.type_id = OPTS_GET(opts, type_id, 0);
attr.query.prog_ids = ptr_to_u64(OPTS_GET(opts, prog_ids, NULL));
attr.query.link_ids = ptr_to_u64(OPTS_GET(opts, link_ids, NULL));
attr.query.prog_attach_flags = ptr_to_u64(OPTS_GET(opts, prog_attach_flags, NULL));
+2 -1
View File
@@ -637,9 +637,10 @@ struct bpf_prog_query_opts {
__u32 *link_ids;
__u32 *link_attach_flags;
__u64 revision;
__u32 type_id;
size_t :0;
};
#define bpf_prog_query_opts__last_field revision
#define bpf_prog_query_opts__last_field type_id
/**
* @brief **bpf_prog_query_opts()** queries the BPF programs and BPF links
+64
View File
@@ -14174,6 +14174,70 @@ struct bpf_link *bpf_map__attach_struct_ops(const struct bpf_map *map)
return &link->link;
}
struct bpf_link *bpf_map__attach_cgroup_opts(const struct bpf_map *map, int cgroup_fd,
const struct bpf_cgroup_opts *opts)
{
LIBBPF_OPTS(bpf_link_create_opts, link_create_opts);
struct bpf_link_struct_ops *link;
__u32 relative_id, zero = 0;
int err, fd, relative_fd;
if (!OPTS_VALID(opts, bpf_cgroup_opts))
return libbpf_err_ptr(-EINVAL);
if (!bpf_map__is_struct_ops(map)) {
pr_warn("map '%s': can't attach non-struct_ops map\n", map->name);
return libbpf_err_ptr(-EINVAL);
}
if (map->fd < 0) {
pr_warn("map '%s': can't attach BPF map without FD (was it created?)\n", map->name);
return libbpf_err_ptr(-EINVAL);
}
if (!(map->def.map_flags & BPF_F_LINK)) {
pr_warn("map '%s': can't attach to cgroup without BPF_F_LINK\n", map->name);
return libbpf_err_ptr(-EINVAL);
}
relative_id = OPTS_GET(opts, relative_id, 0);
relative_fd = OPTS_GET(opts, relative_fd, 0);
if (relative_fd && relative_id) {
pr_warn("map '%s': relative_fd and relative_id cannot be set at the same time\n",
map->name);
return libbpf_err_ptr(-EINVAL);
}
link_create_opts.cgroup.expected_revision = OPTS_GET(opts, expected_revision, 0);
link_create_opts.cgroup.relative_fd = relative_fd;
link_create_opts.cgroup.relative_id = relative_id;
link_create_opts.flags = OPTS_GET(opts, flags, 0);
link = calloc(1, sizeof(*link));
if (!link)
return libbpf_err_ptr(-ENOMEM);
err = bpf_map_update_elem(map->fd, &zero, map->st_ops->kern_vdata, 0);
if (err && err != -EBUSY) {
free(link);
return libbpf_err_ptr(err);
}
link->link.detach = bpf_link__detach_struct_ops;
fd = bpf_link_create(map->fd, cgroup_fd, BPF_STRUCT_OPS, &link_create_opts);
if (fd < 0) {
free(link);
return libbpf_err_ptr(fd);
}
link->link.fd = fd;
link->map_fd = map->fd;
return &link->link;
}
/*
* Swap the back struct_ops of a link with a new struct_ops map.
*/
+3
View File
@@ -960,6 +960,9 @@ bpf_program__attach_cgroup_opts(const struct bpf_program *prog, int cgroup_fd,
struct bpf_map;
LIBBPF_API struct bpf_link *bpf_map__attach_struct_ops(const struct bpf_map *map);
LIBBPF_API struct bpf_link *bpf_map__attach_cgroup_opts(const struct bpf_map *map,
int cgroup_fd,
const struct bpf_cgroup_opts *opts);
LIBBPF_API int bpf_link__update_map(struct bpf_link *link, const struct bpf_map *map);
struct bpf_iter_attach_opts {
+1
View File
@@ -458,6 +458,7 @@ LIBBPF_1.7.0 {
LIBBPF_1.8.0 {
global:
bpf_map__attach_cgroup_opts;
bpf_program__add_flags;
bpf_program__attach_tracing_multi;
bpf_program__clear_flags;