From: Mahe Tardy <mahe.tardy@gmail.com>
To: bpf@vger.kernel.org
Cc: Quentin Monnet <qmo@kernel.org>,
Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Andrii Nakryiko <andrii@kernel.org>,
Eduard Zingerman <eddyz87@gmail.com>,
Kumar Kartikeya Dwivedi <memxor@gmail.com>,
Martin KaFai Lau <martin.lau@linux.dev>,
Song Liu <song@kernel.org>,
Yonghong Song <yonghong.song@linux.dev>,
Jiri Olsa <jolsa@kernel.org>,
Emil Tsalapatis <emil@etsalapatis.com>,
Ihor Solodrai <ihor.solodrai@linux.dev>,
Shuah Khan <shuah@kernel.org>, Mahe Tardy <mahe.tardy@gmail.com>,
Tianyi Chen <hi@tychen.cc>, Gyutae Bae <gyutae.bae@navercorp.com>,
Hui Su <sh_def@163.com>, Josef Bacik <josef@toxicpanda.com>,
linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org
Subject: [PATCH bpf-next 4/5] bpftool: Add attach option for light skeleton generation
Date: Mon, 2 Nov 2026 17:43:49 +0000 [thread overview]
Message-ID: <20261102174350.472592-5-mahe.tardy@gmail.com> (raw)
In-Reply-To: <20261102174350.472592-1-mahe.tardy@gmail.com>
Add an optional attach keyword to gen skeleton when the loader backend
is selected, and pass the request through gen_loader_opts.gen_attach.
Extend the loader context to receive link FDs, using zero for empty slots.
Generate attach functions that check the returned links, and detach
functions that close and reset the FDs. Document the option and add shell
completion.
Signed-off-by: Mahe Tardy <mahe.tardy@gmail.com>
---
.../bpf/bpftool/Documentation/bpftool-gen.rst | 11 ++-
tools/bpf/bpftool/bash-completion/bpftool | 2 +-
tools/bpf/bpftool/gen.c | 67 +++++++++++++------
3 files changed, 56 insertions(+), 24 deletions(-)
diff --git a/tools/bpf/bpftool/Documentation/bpftool-gen.rst b/tools/bpf/bpftool/Documentation/bpftool-gen.rst
index d0a36f442db7..4bf8b0b99ea2 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-gen.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-gen.rst
@@ -24,7 +24,7 @@ GEN COMMANDS
=============
| **bpftool** **gen object** *OUTPUT_FILE* *INPUT_FILE* [*INPUT_FILE*...]
-| **bpftool** **gen skeleton** *FILE* [**name** *OBJECT_NAME*]
+| **bpftool** **gen skeleton** *FILE* [**name** *OBJECT_NAME*] [**attach**]
| **bpftool** **gen subskeleton** *FILE* [**name** *OBJECT_NAME*]
| **bpftool** **gen min_core_btf** *INPUT* *OUTPUT* *OBJECT* [*OBJECT*...]
| **bpftool** **gen help**
@@ -51,6 +51,15 @@ bpftool gen object *OUTPUT_FILE* *INPUT_FILE* [*INPUT_FILE*...]
bpftool gen skeleton *FILE*
Generate BPF skeleton C header file for a given *FILE*.
+ With **-L**, **attach** requests attachment during execution of the
+ generated loader. Supported programs are ordinary LSM programs and
+ BTF-based tracing programs using **fentry**, **fexit**, **fmod_ret**, or
+ **tp_btf** sections, with kernel targets resolved during loading.
+ The generated **__load()** function loads and attaches the programs;
+ **__attach()** checks that the links exist, and **__detach()** closes them.
+ Reattaching after detachment is not supported in this mode. Without
+ **attach**, loading and attachment remain separate operations.
+
BPF skeleton is an alternative interface to existing libbpf APIs for
working with BPF objects. Skeleton code is intended to significantly
shorten and simplify code to load and work with BPF programs from userspace
diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool
index a28af31937ad..9247a9fdcaef 100644
--- a/tools/bpf/bpftool/bash-completion/bpftool
+++ b/tools/bpf/bpftool/bash-completion/bpftool
@@ -1021,7 +1021,7 @@ _bpftool()
return 0
;;
*)
- _bpftool_once_attr 'name'
+ _bpftool_once_attr 'name attach'
return 0
;;
esac
diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c
index 74c2c949458a..19670b3454ec 100644
--- a/tools/bpf/bpftool/gen.c
+++ b/tools/bpf/bpftool/gen.c
@@ -567,7 +567,8 @@ static void codegen_asserts(struct bpf_object *obj, const char *obj_name)
");
}
-static void codegen_attach_detach(struct bpf_object *obj, const char *obj_name)
+static void codegen_attach_detach(struct bpf_object *obj, const char *obj_name,
+ bool gen_attach)
{
struct bpf_program *prog;
@@ -583,21 +584,30 @@ static void codegen_attach_detach(struct bpf_object *obj, const char *obj_name)
int prog_fd = skel->progs.%2$s.prog_fd; \n\
", obj_name, bpf_program__name(prog));
- switch (bpf_program__type(prog)) {
- case BPF_PROG_TYPE_RAW_TRACEPOINT:
- tp_name = strchr(bpf_program__section_name(prog), '/') + 1;
- printf("\tint fd = skel_raw_tracepoint_open(\"%s\", prog_fd);\n", tp_name);
- break;
- case BPF_PROG_TYPE_TRACING:
- case BPF_PROG_TYPE_LSM:
- if (bpf_program__expected_attach_type(prog) == BPF_TRACE_ITER)
- printf("\tint fd = skel_link_create(prog_fd, 0, BPF_TRACE_ITER);\n");
+ if (gen_attach) {
+ if (bpf_program__autoload(prog) && bpf_program__autoattach(prog))
+ printf("\tint fd = ((void)prog_fd, skel->links.%s_fd <= 0 ? -ENOLINK : 0);\n",
+ bpf_program__name(prog));
else
- printf("\tint fd = skel_raw_tracepoint_open(NULL, prog_fd);\n");
- break;
- default:
- printf("\tint fd = ((void)prog_fd, 0); /* auto-attach not supported */\n");
- break;
+ printf("\tint fd = ((void)prog_fd, 0);\n");
+ } else {
+ switch (bpf_program__type(prog)) {
+ case BPF_PROG_TYPE_RAW_TRACEPOINT:
+ tp_name = strchr(bpf_program__section_name(prog), '/') + 1;
+ printf("\tint fd = skel_raw_tracepoint_open(\"%s\", prog_fd);\n",
+ tp_name);
+ break;
+ case BPF_PROG_TYPE_TRACING:
+ case BPF_PROG_TYPE_LSM:
+ if (bpf_program__expected_attach_type(prog) == BPF_TRACE_ITER)
+ printf("\tint fd = skel_link_create(prog_fd, 0, BPF_TRACE_ITER);\n");
+ else
+ printf("\tint fd = skel_raw_tracepoint_open(NULL, prog_fd);\n");
+ break;
+ default:
+ printf("\tint fd = ((void)prog_fd, 0); /* auto-attach not supported */\n");
+ break;
+ }
}
codegen("\
\n\
@@ -641,6 +651,8 @@ static void codegen_attach_detach(struct bpf_object *obj, const char *obj_name)
\n\
skel_closenz(skel->links.%1$s_fd); \n\
", bpf_program__name(prog));
+ if (gen_attach)
+ printf("\tskel->links.%s_fd = 0;\n", bpf_program__name(prog));
}
codegen("\
@@ -692,7 +704,8 @@ static void codegen_destroy(struct bpf_object *obj, const char *obj_name)
obj_name);
}
-static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *header_guard)
+static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *header_guard,
+ bool gen_attach)
{
DECLARE_LIBBPF_OPTS(gen_loader_opts, opts);
struct bpf_load_and_run_opts sopts = {};
@@ -703,6 +716,7 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h
char ident[256];
int err = 0;
+ opts.gen_attach = gen_attach;
if (sign_progs)
opts.gen_hash = true;
@@ -739,7 +753,7 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h
}
#endif
- codegen_attach_detach(obj, obj_name);
+ codegen_attach_detach(obj, obj_name, gen_attach);
codegen_destroy(obj, obj_name);
@@ -756,6 +770,8 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h
skel->ctx.sz = (char *)&skel->links - (char *)skel; \n\
",
obj_name, opts.data_sz);
+ if (gen_attach)
+ printf("\tskel->ctx.sz += sizeof(skel->links);\n");
bpf_object__for_each_map(map, obj) {
const void *mmap_data = NULL;
size_t mmap_size = 0;
@@ -1262,6 +1278,7 @@ static int do_skeleton(int argc, char **argv)
struct bpf_map *map;
struct btf *btf;
struct stat st;
+ bool gen_attach = false;
if (!REQ_ARGS(1)) {
usage();
@@ -1270,10 +1287,9 @@ static int do_skeleton(int argc, char **argv)
file = GET_ARG();
while (argc) {
- if (!REQ_ARGS(2))
- return -1;
-
if (is_prefix(*argv, "name")) {
+ if (!REQ_ARGS(2))
+ return -1;
NEXT_ARG();
if (obj_name[0] != '\0') {
@@ -1283,6 +1299,8 @@ static int do_skeleton(int argc, char **argv)
strncpy(obj_name, *argv, MAX_OBJ_NAME_LEN - 1);
obj_name[MAX_OBJ_NAME_LEN - 1] = '\0';
+ } else if (is_prefix(*argv, "attach")) {
+ gen_attach = true;
} else {
p_err("unknown arg %s", *argv);
return -1;
@@ -1291,6 +1309,11 @@ static int do_skeleton(int argc, char **argv)
NEXT_ARG();
}
+ if (gen_attach && !use_loader) {
+ p_err("attach requires a light skeleton (-L)");
+ return -1;
+ }
+
if (argc) {
p_err("extra unknown arguments");
return -1;
@@ -1454,7 +1477,7 @@ static int do_skeleton(int argc, char **argv)
goto out;
}
if (use_loader) {
- err = gen_trace(obj, obj_name, header_guard);
+ err = gen_trace(obj, obj_name, header_guard, gen_attach);
goto out;
}
@@ -2018,7 +2041,7 @@ static int do_help(int argc, char **argv)
fprintf(stderr,
"Usage: %1$s %2$s object OUTPUT_FILE INPUT_FILE [INPUT_FILE...]\n"
- " %1$s %2$s skeleton FILE [name OBJECT_NAME]\n"
+ " %1$s %2$s skeleton FILE [name OBJECT_NAME] [attach]\n"
" %1$s %2$s subskeleton FILE [name OBJECT_NAME]\n"
" %1$s %2$s min_core_btf INPUT OUTPUT OBJECT [OBJECT...]\n"
" %1$s %2$s help\n"
--
2.43.0
next prev parent reply other threads:[~2026-11-02 17:44 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-02 17:43 [PATCH bpf-next 0/5] libbpf: Support gen loader attach Mahe Tardy
2026-11-02 17:43 ` [PATCH bpf-next 1/5] libbpf: Count entry programs for bpf_gen__init() Mahe Tardy
2026-11-02 17:43 ` [PATCH bpf-next 2/5] libbpf: Track generated loader link FDs Mahe Tardy
2026-11-02 17:43 ` [PATCH bpf-next 3/5] libbpf: Emit BPF_LINK_CREATE calls in generated loaders Mahe Tardy
2026-11-02 17:43 ` Mahe Tardy [this message]
2026-11-02 17:43 ` [PATCH bpf-next 5/5] selftests/bpf: Test gen loader attach Mahe Tardy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261102174350.472592-5-mahe.tardy@gmail.com \
--to=mahe.tardy@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=emil@etsalapatis.com \
--cc=gyutae.bae@navercorp.com \
--cc=hi@tychen.cc \
--cc=ihor.solodrai@linux.dev \
--cc=jolsa@kernel.org \
--cc=josef@toxicpanda.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=martin.lau@linux.dev \
--cc=memxor@gmail.com \
--cc=qmo@kernel.org \
--cc=sh_def@163.com \
--cc=shuah@kernel.org \
--cc=song@kernel.org \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®