From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=209.85.128.41 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1793648517; b=d94f6BBN7mstV9YBn8RyHk0pHHBadlJjKZ7AiFoqOcx+SS9O/Usl/Gu5LhuNJT1IGOCz b5oZOya3i+URt3BOCNtZq0z5kGJzKcd7qpV4367FX4Ftr74kcRA20v91Z6B07/zUB04sl 7Iiq1vfNGxmzrfdaB9SV1eJVYNHWZRZjs3GnGcD0I9LyXV1eHfdWvL/wrunVVBlaV3/LW LTtCU0mqBANParr+aajDEehh0Aj5NfhTrqEEXKGtgPW2IlKTXGwlmcp9vpGjwZi1qfa0u Jsclmtb7gCZp0IOTWAH5WHww/Kr1g91azQmzI8L2x8v/Nqx3kHrcUH4ixwql7gS6Q3A== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1793648517; h=DMARC-Filter:Received:DKIM-Signature:X-Google-DKIM-Signature: X-Forwarded-Encrypted:X-Gm-Message-State:X-Gm-Gg:X-Received:Received: From:To:Cc:Subject:Date:Message-ID:X-Mailer:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding; bh=EHCQadAY8CNjmskwtsv6n18ePfbYCbVyW2mXEHaCPTM=; b=alAke8xZLoiTd2V+zkRbOLKQ2e+LkTv5qycWtIC7WkCDDi5kqt7ZpUs7W4Rzabkrxehb qPEjuVhSMluvsj1+Kdlfj1ZOWhPv5VjqoR7OSb8j9qKRB6c6HdycsnT9TYy0bQ9OVI1qA w1C+tBLkGiCxnAFFIjCFZTl4yHcf1syGZZoL7MD3K8TcRLL3pWw1+ijx8tAOt4hJvYb9n uvj/FXSw+cEI2Lu2JRYOmX9qBU1spM9PYHvFf6t36Yb7fkFeLEw11x9RkVimkHdO71We0 TOzZvfAZQ3qVZb0dL6Wz3SorvLbX3SYHx4pM20SRbOIm0/qVmWZL+Z++yB3F99HNM7w== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20260707 header.b=d3IyOa+c; arc=none smtp.remote-ip=209.85.128.41 Received: from mail-wm1-f41.google.com (mail-wm1-f41.google.com [209.85.128.41]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 30B24606A335 for ; Mon, 2 Nov 2026 19:41:56 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org 30B24606A335 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20260707 header.b=d3IyOa+c Received: by mail-wm1-f41.google.com with SMTP id 5b1f17b1804b1-4a2153c8525so22266375e9.3 for ; Mon, 02 Nov 2026 11:41:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20260707; t=1793648514; x=1794253314; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=EHCQadAY8CNjmskwtsv6n18ePfbYCbVyW2mXEHaCPTM=; b=d3IyOa+cN8IHiU1jJTCvKuvEgfzIhHKMurrMCck+6wb9hLLc4vNWoSnY7unJ8jdd5V QHx9MWPxIJG8V+XCZdmRC92ve+em5nYCwCEx4iJVkSJ1iPIhfwKPltFC7nA1yhiudFiI /i0zJp+5gW0GhokuW7ihhmwEg3/f6K6gWv0g87MuPom7Xq4kMBq+f3D5tulr0qCywPK2 g7C2Sudqnm+jKMjSWW1q7ncTRxiGZaNcUSoPNmPzAhcCfNa/W712Ars1Tv/bsqSmAtyy f0Tj96jVS8CCxwaamIx7+f6tcMAOHOL9EaYsgu7RIUeoPRBL7LFcELWgQSPSL154TV/J +qeA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1793648514; x=1794253314; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=EHCQadAY8CNjmskwtsv6n18ePfbYCbVyW2mXEHaCPTM=; b=weg2An5ET1AbbaQmaERiIZ/D86FM+P73UdH2EHVCet6exgJ4xJG6iGZl6qDNExLvro RleB+IGzcx/d5ZCfCaavD3AJS3RWs/zbaEwGNzeDO9r80MYT9+/V+PB+r3BVCIs8I2Fw U591xISR/nF4rleYV4GKN1pnIg1rO4N4AScasIcF4SaQtTFCggZnll/90eChm/H/QGfR abSdXl8HRMKYwUL3BSi+a2DJcVa2Cf4WcXIWVeYZp4plzaqRN2gUo0HCBilUxsKgUc46 PWkV4fZC9FN4fseymgiMpO7znunsGl3FBxzgjs3gCzfGoesEgV+PpZNwJY/YN29+OFaZ P5HQ== X-Forwarded-Encrypted: i=1; AKwUvBzne4ClWRhvhcX+oB5R0qwd450pOu48YPBxtmMABBBNNl8ZKRM8qdKzvDDT80JAJ2ID+NdYjwdJxurYQJM=@vger.kernel.org X-Gm-Message-State: AFq9FYIkj3O1kQRTEWqWFRQ7Kyp7B7vvS1pN70pgcfxFDYJgOpxr82Pu o10yB5irA1jK12gNKC1vQsWu0j5fcq8BGxWat5ZaSCGwsoYykYQ8dKLt X-Gm-Gg: AYBFou0nleeCOJMcwX9cj/1wzx0j14gvM46S1ow+kzTsuICHBUg5txN/+rwEqzrxQ7Y dnaTEtYyIY5I09EJ+d3reEff2uhPexg0G8zRkL0plz3H1I5QaGVCld0nQPAUPT1wgCJ4hc0LzT7 xP4Aohk3e94PZ8rze7ORnlTQdW7btKDDQg91jDGnNH48JOGpO7foefS8ThqE1XW3e8OSgHgfl6D qRdoJx0Cm8bfy7QeNTpCu5nnircRulQV6HJkI1saVkMWAGQgqNtQcEr9AbgsvD6YS6kOk/bBEMO Vg0baS5+TRfQvcxFJv6sgq4m20YVToFB75wXXy1ISWtQNbWKxqwvEty8cWe+VE/n9vnjzHVFTUE jc2yo1B2xQTFE9Vw/sHE2awgVcNH8hWsXBR2+5ci2QOLJsK3iTtG901CknKq+YCKLlvosNqN8pw DgiN7jvdQ8D5gTYQVgbsztUhgEGe4bSqKBQMjxUqNjTJVlDcVtEHSe1UFig8traM8yiZktfItL5 GfyxUrn7+P4DfC6/p6yWAb6ner7iRrgr++FWaBfxApkeT8l/EnJdoAQlNohFgcUDJALVphqZ8Nx 19KkSEZnEgBDRGlTMmW+OuZc9FEyeLc/NppaXGTePIFRY+eyH6/Iagn4K397tzQR3N9IwWyEDlH b X-Received: by 2002:a05:600c:a00b:b0:4a7:b304:253e with SMTP id 5b1f17b1804b1-4ac1765d8abmr259473095e9.22.1793648514574; Mon, 02 Nov 2026 11:41:54 -0800 (PST) Received: from mtardy-friendly-lvh-runner.europe-west1-c.c.cilium-dev.internal ([2600:1900:4010:1a8::]) by smtp.googlemail.com with ESMTPSA id 5b1f17b1804b1-4ac0a0a3495sm231386345e9.4.2026.11.02.11.41.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 02 Nov 2026 11:41:54 -0800 (PST) From: Mahe Tardy To: bpf@vger.kernel.org Cc: Quentin Monnet , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Eduard Zingerman , Kumar Kartikeya Dwivedi , Martin KaFai Lau , Song Liu , Yonghong Song , Jiri Olsa , Emil Tsalapatis , Ihor Solodrai , Shuah Khan , Mahe Tardy , Tianyi Chen , Gyutae Bae , Hui Su , Josef Bacik , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH bpf-next v2 4/5] bpftool: Add attach option for light skeleton generation Date: Mon, 2 Nov 2026 19:41:43 +0000 Message-ID: <20261102194145.620210-5-mahe.tardy@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20261102194145.620210-1-mahe.tardy@gmail.com> References: <20261102194145.620210-1-mahe.tardy@gmail.com> X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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 --- .../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