Message ID | 20250122171359.232791-2-chen.dylane@gmail.com (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | BPF |
Headers | show |
Series | Add prog_kfunc feature probe | expand |
On Wed, Jan 22, 2025 at 9:14 AM Tao Chen <chen.dylane@gmail.com> wrote: > > Similarly to libbpf_probe_bpf_helper, the libbpf_probe_bpf_kfunc > used to test the availability of the different eBPF kfuncs on the > current system. > > Signed-off-by: Tao Chen <chen.dylane@gmail.com> > --- > tools/lib/bpf/libbpf.h | 16 +++++++++++++++- > tools/lib/bpf/libbpf.map | 1 + > tools/lib/bpf/libbpf_probes.c | 36 +++++++++++++++++++++++++++++++++++ > 3 files changed, 52 insertions(+), 1 deletion(-) > > diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h > index 3020ee45303a..3b6d33578a16 100644 > --- a/tools/lib/bpf/libbpf.h > +++ b/tools/lib/bpf/libbpf.h > @@ -1680,7 +1680,21 @@ LIBBPF_API int libbpf_probe_bpf_map_type(enum bpf_map_type map_type, const void > */ > LIBBPF_API int libbpf_probe_bpf_helper(enum bpf_prog_type prog_type, > enum bpf_func_id helper_id, const void *opts); > - > +/** > + * @brief **libbpf_probe_bpf_kfunc()** detects if host kernel supports the > + * use of a given BPF kfunc from specified BPF program type. > + * @param prog_type BPF program type used to check the support of BPF kfunc > + * @param kfunc_id The btf ID of BPF kfunc to check support for > + * @param opts reserved for future extensibility, should be NULL > + * @return 1, if given combination of program type and kfunc is supported; 0, > + * if the combination is not supported; negative error code if feature > + * detection for provided input arguments failed or can't be performed > + * > + * Make sure the process has required set of CAP_* permissions (or runs as > + * root) when performing feature checking. > + */ > +LIBBPF_API int libbpf_probe_bpf_kfunc(enum bpf_prog_type prog_type, > + int kfunc_id, const void *opts); > /** > * @brief **libbpf_num_possible_cpus()** is a helper function to get the > * number of possible CPUs that the host kernel supports and expects. > diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map > index a8b2936a1646..e93fae101efd 100644 > --- a/tools/lib/bpf/libbpf.map > +++ b/tools/lib/bpf/libbpf.map > @@ -436,4 +436,5 @@ LIBBPF_1.6.0 { > bpf_linker__add_buf; > bpf_linker__add_fd; > bpf_linker__new_fd; > + libbpf_probe_bpf_kfunc; > } LIBBPF_1.5.0; > diff --git a/tools/lib/bpf/libbpf_probes.c b/tools/lib/bpf/libbpf_probes.c > index 9dfbe7750f56..bc1cf2afbe87 100644 > --- a/tools/lib/bpf/libbpf_probes.c > +++ b/tools/lib/bpf/libbpf_probes.c > @@ -413,6 +413,42 @@ int libbpf_probe_bpf_map_type(enum bpf_map_type map_type, const void *opts) > return libbpf_err(ret); > } > > +int libbpf_probe_bpf_kfunc(enum bpf_prog_type prog_type, int kfunc_id, > + const void *opts) > +{ > + struct bpf_insn insns[] = { > + BPF_EXIT_INSN(), > + BPF_EXIT_INSN(), > + }; > + const size_t insn_cnt = ARRAY_SIZE(insns); > + int err; > + char buf[4096]; > + > + if (opts) > + return libbpf_err(-EINVAL); note how libbpf_probe_bpf_helper() rejects some program types because they can't be really loaded. Let's keep it consistent? pw-bot: cr > + > + insns[0].code = BPF_JMP | BPF_CALL; > + insns[0].src_reg = BPF_PSEUDO_KFUNC_CALL; > + insns[0].imm = kfunc_id; > + > + /* Now only support kfunc from vmlinux */ > + insns[0].off = 0; why not support modules from the very beginning? > + > + buf[0] = '\0'; > + err = probe_prog_load(prog_type, insns, insn_cnt, buf, sizeof(buf)); > + if (err < 0) > + return libbpf_err(err); > + > + /* If BPF verifier recognizes BPF kfunc but it's not supported for > + * given BPF program type, it will emit "calling kernel function > + * bpf_cpumask_create is not allowed" > + */ > + if (err == 0 && strstr(buf, "not allowed")) Looking at kernel code, if kfunc ID is not recognized, it seems like the verifier won't print anything, is that right? If that's the case, then this API will behave differently from libbpf_probe_bpf_helper(), which isn't great. > + return 0; > + > + return 1; /* assume supported */ > +} > + > int libbpf_probe_bpf_helper(enum bpf_prog_type prog_type, enum bpf_func_id helper_id, > const void *opts) > { > -- > 2.43.0 >
在 2025/1/23 06:22, Andrii Nakryiko 写道: > On Wed, Jan 22, 2025 at 9:14 AM Tao Chen <chen.dylane@gmail.com> wrote: >> >> Similarly to libbpf_probe_bpf_helper, the libbpf_probe_bpf_kfunc >> used to test the availability of the different eBPF kfuncs on the >> current system. >> >> Signed-off-by: Tao Chen <chen.dylane@gmail.com> >> --- >> tools/lib/bpf/libbpf.h | 16 +++++++++++++++- >> tools/lib/bpf/libbpf.map | 1 + >> tools/lib/bpf/libbpf_probes.c | 36 +++++++++++++++++++++++++++++++++++ >> 3 files changed, 52 insertions(+), 1 deletion(-) >> >> diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h >> index 3020ee45303a..3b6d33578a16 100644 >> --- a/tools/lib/bpf/libbpf.h >> +++ b/tools/lib/bpf/libbpf.h >> @@ -1680,7 +1680,21 @@ LIBBPF_API int libbpf_probe_bpf_map_type(enum bpf_map_type map_type, const void >> */ >> LIBBPF_API int libbpf_probe_bpf_helper(enum bpf_prog_type prog_type, >> enum bpf_func_id helper_id, const void *opts); >> - >> +/** >> + * @brief **libbpf_probe_bpf_kfunc()** detects if host kernel supports the >> + * use of a given BPF kfunc from specified BPF program type. >> + * @param prog_type BPF program type used to check the support of BPF kfunc >> + * @param kfunc_id The btf ID of BPF kfunc to check support for >> + * @param opts reserved for future extensibility, should be NULL >> + * @return 1, if given combination of program type and kfunc is supported; 0, >> + * if the combination is not supported; negative error code if feature >> + * detection for provided input arguments failed or can't be performed >> + * >> + * Make sure the process has required set of CAP_* permissions (or runs as >> + * root) when performing feature checking. >> + */ >> +LIBBPF_API int libbpf_probe_bpf_kfunc(enum bpf_prog_type prog_type, >> + int kfunc_id, const void *opts); >> /** >> * @brief **libbpf_num_possible_cpus()** is a helper function to get the >> * number of possible CPUs that the host kernel supports and expects. >> diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map >> index a8b2936a1646..e93fae101efd 100644 >> --- a/tools/lib/bpf/libbpf.map >> +++ b/tools/lib/bpf/libbpf.map >> @@ -436,4 +436,5 @@ LIBBPF_1.6.0 { >> bpf_linker__add_buf; >> bpf_linker__add_fd; >> bpf_linker__new_fd; >> + libbpf_probe_bpf_kfunc; >> } LIBBPF_1.5.0; >> diff --git a/tools/lib/bpf/libbpf_probes.c b/tools/lib/bpf/libbpf_probes.c >> index 9dfbe7750f56..bc1cf2afbe87 100644 >> --- a/tools/lib/bpf/libbpf_probes.c >> +++ b/tools/lib/bpf/libbpf_probes.c >> @@ -413,6 +413,42 @@ int libbpf_probe_bpf_map_type(enum bpf_map_type map_type, const void *opts) >> return libbpf_err(ret); >> } >> >> +int libbpf_probe_bpf_kfunc(enum bpf_prog_type prog_type, int kfunc_id, >> + const void *opts) >> +{ >> + struct bpf_insn insns[] = { >> + BPF_EXIT_INSN(), >> + BPF_EXIT_INSN(), >> + }; >> + const size_t insn_cnt = ARRAY_SIZE(insns); >> + int err; >> + char buf[4096]; >> + >> + if (opts) >> + return libbpf_err(-EINVAL); > > note how libbpf_probe_bpf_helper() rejects some program types because > they can't be really loaded. Let's keep it consistent? > Hi andrii, thank you for your guidance, i will add it later. > pw-bot: cr > >> + >> + insns[0].code = BPF_JMP | BPF_CALL; >> + insns[0].src_reg = BPF_PSEUDO_KFUNC_CALL; >> + insns[0].imm = kfunc_id; >> + >> + /* Now only support kfunc from vmlinux */ >> + insns[0].off = 0; > > why not support modules from the very beginning? > So can we add a new parameter named like "off"? If it's a module, pass the BTF offset to insns[0].off. If it's vmlinux, pass 0. >> + >> + buf[0] = '\0'; >> + err = probe_prog_load(prog_type, insns, insn_cnt, buf, sizeof(buf)); >> + if (err < 0) >> + return libbpf_err(err); >> + >> + /* If BPF verifier recognizes BPF kfunc but it's not supported for >> + * given BPF program type, it will emit "calling kernel function >> + * bpf_cpumask_create is not allowed" >> + */ >> + if (err == 0 && strstr(buf, "not allowed")) > > Looking at kernel code, if kfunc ID is not recognized, it seems like > the verifier won't print anything, is that right? If that's the case, > then this API will behave differently from libbpf_probe_bpf_helper(), > which isn't great. > You mean kfunc id is invalid? i try set kfunc id with -1 ret = libbpf_probe_bpf_kfunc(BPF_PROG_TYPE_SYSCALL, -1, NULL); And the verifier will print like: "kernel btf_id 4294967295 is not a function" So "not a function" may also be checked, i will add it in v2. >> + return 0; >> + >> + return 1; /* assume supported */ >> +} >> + >> int libbpf_probe_bpf_helper(enum bpf_prog_type prog_type, enum bpf_func_id helper_id, >> const void *opts) >> { >> -- >> 2.43.0 >>
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index 3020ee45303a..3b6d33578a16 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -1680,7 +1680,21 @@ LIBBPF_API int libbpf_probe_bpf_map_type(enum bpf_map_type map_type, const void */ LIBBPF_API int libbpf_probe_bpf_helper(enum bpf_prog_type prog_type, enum bpf_func_id helper_id, const void *opts); - +/** + * @brief **libbpf_probe_bpf_kfunc()** detects if host kernel supports the + * use of a given BPF kfunc from specified BPF program type. + * @param prog_type BPF program type used to check the support of BPF kfunc + * @param kfunc_id The btf ID of BPF kfunc to check support for + * @param opts reserved for future extensibility, should be NULL + * @return 1, if given combination of program type and kfunc is supported; 0, + * if the combination is not supported; negative error code if feature + * detection for provided input arguments failed or can't be performed + * + * Make sure the process has required set of CAP_* permissions (or runs as + * root) when performing feature checking. + */ +LIBBPF_API int libbpf_probe_bpf_kfunc(enum bpf_prog_type prog_type, + int kfunc_id, const void *opts); /** * @brief **libbpf_num_possible_cpus()** is a helper function to get the * number of possible CPUs that the host kernel supports and expects. diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map index a8b2936a1646..e93fae101efd 100644 --- a/tools/lib/bpf/libbpf.map +++ b/tools/lib/bpf/libbpf.map @@ -436,4 +436,5 @@ LIBBPF_1.6.0 { bpf_linker__add_buf; bpf_linker__add_fd; bpf_linker__new_fd; + libbpf_probe_bpf_kfunc; } LIBBPF_1.5.0; diff --git a/tools/lib/bpf/libbpf_probes.c b/tools/lib/bpf/libbpf_probes.c index 9dfbe7750f56..bc1cf2afbe87 100644 --- a/tools/lib/bpf/libbpf_probes.c +++ b/tools/lib/bpf/libbpf_probes.c @@ -413,6 +413,42 @@ int libbpf_probe_bpf_map_type(enum bpf_map_type map_type, const void *opts) return libbpf_err(ret); } +int libbpf_probe_bpf_kfunc(enum bpf_prog_type prog_type, int kfunc_id, + const void *opts) +{ + struct bpf_insn insns[] = { + BPF_EXIT_INSN(), + BPF_EXIT_INSN(), + }; + const size_t insn_cnt = ARRAY_SIZE(insns); + int err; + char buf[4096]; + + if (opts) + return libbpf_err(-EINVAL); + + insns[0].code = BPF_JMP | BPF_CALL; + insns[0].src_reg = BPF_PSEUDO_KFUNC_CALL; + insns[0].imm = kfunc_id; + + /* Now only support kfunc from vmlinux */ + insns[0].off = 0; + + buf[0] = '\0'; + err = probe_prog_load(prog_type, insns, insn_cnt, buf, sizeof(buf)); + if (err < 0) + return libbpf_err(err); + + /* If BPF verifier recognizes BPF kfunc but it's not supported for + * given BPF program type, it will emit "calling kernel function + * bpf_cpumask_create is not allowed" + */ + if (err == 0 && strstr(buf, "not allowed")) + return 0; + + return 1; /* assume supported */ +} + int libbpf_probe_bpf_helper(enum bpf_prog_type prog_type, enum bpf_func_id helper_id, const void *opts) {
Similarly to libbpf_probe_bpf_helper, the libbpf_probe_bpf_kfunc used to test the availability of the different eBPF kfuncs on the current system. Signed-off-by: Tao Chen <chen.dylane@gmail.com> --- tools/lib/bpf/libbpf.h | 16 +++++++++++++++- tools/lib/bpf/libbpf.map | 1 + tools/lib/bpf/libbpf_probes.c | 36 +++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-)