From: David Vernet <void@manifault.com>
To: Dave Marchevsky <davemarchevsky@fb.com>
Cc: bpf@vger.kernel.org, Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Andrii Nakryiko <andrii@kernel.org>,
Martin KaFai Lau <martin.lau@kernel.org>,
Kernel Team <kernel-team@fb.com>
Subject: Re: [PATCH v3 bpf-next 1/2] libbpf: Support triple-underscore flavors for kfunc relocation
Date: Fri, 18 Aug 2023 10:19:55 -0500 [thread overview]
Message-ID: <20230818151955.GA14411@maniforge> (raw)
In-Reply-To: <20230817225353.2570845-1-davemarchevsky@fb.com>
On Thu, Aug 17, 2023 at 03:53:52PM -0700, Dave Marchevsky wrote:
> The function signature of kfuncs can change at any time due to their
> intentional lack of stability guarantees. As kfuncs become more widely
> used, BPF program writers will need facilities to support calling
> different versions of a kfunc from a single BPF object. Consider this
> simplified example based on a real scenario we ran into at Meta:
>
> /* initial kfunc signature */
> int some_kfunc(void *ptr)
>
> /* Oops, we need to add some flag to modify behavior. No problem,
> change the kfunc. flags = 0 retains original behavior */
> int some_kfunc(void *ptr, long flags)
>
> If the initial version of the kfunc is deployed on some portion of the
> fleet and the new version on the rest, a fleetwide service that uses
> some_kfunc will currently need to load different BPF programs depending
> on which some_kfunc is available.
>
> Luckily CO-RE provides a facility to solve a very similar problem,
> struct definition changes, by allowing program writers to declare
> my_struct___old and my_struct___new, with ___suffix being considered a
> 'flavor' of the non-suffixed name and being ignored by
> bpf_core_type_exists and similar calls.
>
> This patch extends the 'flavor' facility to the kfunc extern
> relocation process. BPF program writers can now declare
>
> extern int some_kfunc___old(void *ptr)
> extern int some_kfunc___new(void *ptr, int flags)
>
> then test which version of the kfunc exists with bpf_ksym_exists.
> Relocation and verifier's dead code elimination will work in concert as
> expected, allowing this pattern:
>
> if (bpf_ksym_exists(some_kfunc___old))
> some_kfunc___old(ptr);
> else
> some_kfunc___new(ptr, 0);
>
> Changelog:
>
> v1 -> v2: https://lore.kernel.org/bpf/20230811201346.3240403-1-davemarchevsky@fb.com/
> * No need to check obj->externs[i].essent_name before zfree (Jiri)
> * Use strndup instead of replicating same functionality (Jiri)
> * Properly handle memory allocation falure (Stanislav)
>
> v2 -> v3: https://lore.kernel.org/bpf/20230816165813.3718580-1-davemarchevsky@fb.com/
> * Move if (ext->is_weak) test above pr_warn to match existing similar behavior
> (David Vernet)
>
> Signed-off-by: Dave Marchevsky <davemarchevsky@fb.com>
LGTM, thanks for working on this.
Acked-by: David Vernet <void@manifault.com>
> ---
> tools/lib/bpf/libbpf.c | 20 +++++++++++++++++++-
> 1 file changed, 19 insertions(+), 1 deletion(-)
>
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index b14a4376a86e..2178b28878e2 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -550,6 +550,7 @@ struct extern_desc {
> int btf_id;
> int sec_btf_id;
> const char *name;
> + char *essent_name;
> bool is_set;
> bool is_weak;
> union {
> @@ -3770,6 +3771,7 @@ static int bpf_object__collect_externs(struct bpf_object *obj)
> struct extern_desc *ext;
> int i, n, off, dummy_var_btf_id;
> const char *ext_name, *sec_name;
> + size_t ext_essent_len;
> Elf_Scn *scn;
> Elf64_Shdr *sh;
>
> @@ -3819,6 +3821,14 @@ static int bpf_object__collect_externs(struct bpf_object *obj)
> ext->sym_idx = i;
> ext->is_weak = ELF64_ST_BIND(sym->st_info) == STB_WEAK;
>
> + ext_essent_len = bpf_core_essential_name_len(ext->name);
> + ext->essent_name = NULL;
> + if (ext_essent_len != strlen(ext->name)) {
> + ext->essent_name = strndup(ext->name, ext_essent_len);
> + if (!ext->essent_name)
> + return -ENOMEM;
> + }
> +
> ext->sec_btf_id = find_extern_sec_btf_id(obj->btf, ext->btf_id);
> if (ext->sec_btf_id <= 0) {
> pr_warn("failed to find BTF for extern '%s' [%d] section: %d\n",
> @@ -7624,7 +7634,8 @@ static int bpf_object__resolve_ksym_func_btf_id(struct bpf_object *obj,
>
> local_func_proto_id = ext->ksym.type_id;
>
> - kfunc_id = find_ksym_btf_id(obj, ext->name, BTF_KIND_FUNC, &kern_btf, &mod_btf);
> + kfunc_id = find_ksym_btf_id(obj, ext->essent_name ?: ext->name, BTF_KIND_FUNC, &kern_btf,
> + &mod_btf);
> if (kfunc_id < 0) {
> if (kfunc_id == -ESRCH && ext->is_weak)
> return 0;
> @@ -7639,6 +7650,9 @@ static int bpf_object__resolve_ksym_func_btf_id(struct bpf_object *obj,
> ret = bpf_core_types_are_compat(obj->btf, local_func_proto_id,
> kern_btf, kfunc_proto_id);
> if (ret <= 0) {
> + if (ext->is_weak)
> + return 0;
> +
> pr_warn("extern (func ksym) '%s': func_proto [%d] incompatible with %s [%d]\n",
> ext->name, local_func_proto_id,
> mod_btf ? mod_btf->name : "vmlinux", kfunc_proto_id);
> @@ -8370,6 +8384,10 @@ void bpf_object__close(struct bpf_object *obj)
>
> zfree(&obj->btf_custom_path);
> zfree(&obj->kconfig);
> +
> + for (i = 0; i < obj->nr_extern; i++)
> + zfree(&obj->externs[i].essent_name);
> +
> zfree(&obj->externs);
> obj->nr_extern = 0;
>
> --
> 2.34.1
>
>
next prev parent reply other threads:[~2023-08-18 15:20 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-08-17 22:53 [PATCH v3 bpf-next 1/2] libbpf: Support triple-underscore flavors for kfunc relocation Dave Marchevsky
2023-08-17 22:53 ` [PATCH v3 bpf-next 2/2] selftests/bpf: Add CO-RE relocs kfunc flavors tests Dave Marchevsky
2023-08-18 15:20 ` David Vernet
2023-08-18 15:19 ` David Vernet [this message]
2023-08-18 16:10 ` [PATCH v3 bpf-next 1/2] libbpf: Support triple-underscore flavors for kfunc relocation Jiri Olsa
2023-08-18 16:20 ` patchwork-bot+netdevbpf
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=20230818151955.GA14411@maniforge \
--to=void@manifault.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=davemarchevsky@fb.com \
--cc=kernel-team@fb.com \
--cc=martin.lau@kernel.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.