From: Slava Imameev Replacing the boolean field with an enum simplifies the addition of new load strategies. Currently, the bpf_program structure defines the autoload behavior using a boolean field. This field is now replaced with an enum, allowing new BPF program loading strategies to be introduced by extending the enum value range. Signed-off-by: Slava Imameev Signed-off-by: Andrey Grodzovsky --- tools/lib/bpf/libbpf.c | 50 +++++++++++++++++++++++++--------------- tools/lib/bpf/libbpf.h | 33 ++++++++++++++++++++++++++ tools/lib/bpf/libbpf.map | 2 ++ 3 files changed, 66 insertions(+), 19 deletions(-) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index cd1ea1bb53cb..a3085847cb97 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -494,7 +494,7 @@ struct bpf_program { struct bpf_object *obj; int fd; - bool autoload; + enum bpf_prog_load_strategy load_strategy; bool autoattach; bool sym_global; bool mark_btf_static; @@ -874,11 +874,11 @@ bpf_object__init_prog(struct bpf_object *obj, struct bpf_program *prog, * autoload set to false. */ if (sec_name[0] == '?') { - prog->autoload = false; + prog->load_strategy = BPF_PROG_LOAD_STRATEGY_DISABLED; /* from now on forget there was ? in section name */ sec_name++; } else { - prog->autoload = true; + prog->load_strategy = BPF_PROG_LOAD_STRATEGY_AUTO; } prog->autoattach = true; @@ -1165,7 +1165,8 @@ static int bpf_object_adjust_struct_ops_autoload(struct bpf_object *obj) } } if (use_cnt) - prog->autoload = should_load; + prog->load_strategy = should_load ? BPF_PROG_LOAD_STRATEGY_AUTO + : BPF_PROG_LOAD_STRATEGY_DISABLED; } return 0; @@ -1256,7 +1257,7 @@ static int bpf_map__init_kern_struct_ops(struct bpf_map *map) * then bpf_object_adjust_struct_ops_autoload() will update its * autoload accordingly. */ - st_ops->progs[i]->autoload = false; + st_ops->progs[i]->load_strategy = BPF_PROG_LOAD_STRATEGY_DISABLED; st_ops->progs[i] = NULL; } @@ -1294,7 +1295,7 @@ static int bpf_map__init_kern_struct_ops(struct bpf_map *map) * if user replaced it with another program or NULL */ if (st_ops->progs[i] && st_ops->progs[i] != prog) - st_ops->progs[i]->autoload = false; + st_ops->progs[i]->load_strategy = BPF_PROG_LOAD_STRATEGY_DISABLED; /* Update the value from the shadow type */ st_ops->progs[i] = prog; @@ -3594,7 +3595,7 @@ static bool obj_needs_vmlinux_btf(const struct bpf_object *obj) } bpf_object__for_each_program(prog, obj) { - if (!prog->autoload) + if (prog->load_strategy == BPF_PROG_LOAD_STRATEGY_DISABLED) continue; if (prog_needs_vmlinux_btf(prog)) return true; @@ -6214,7 +6215,7 @@ bpf_object__relocate_core(struct bpf_object *obj, const char *targ_btf_path) /* no need to apply CO-RE relocation if the program is * not going to be loaded */ - if (!prog->autoload) + if (prog->load_strategy == BPF_PROG_LOAD_STRATEGY_DISABLED) continue; /* adjust insn_idx from section frame of reference to the local @@ -7558,7 +7559,7 @@ static int bpf_object__relocate(struct bpf_object *obj, const char *targ_btf_pat */ if (prog_is_subprog(obj, prog)) continue; - if (!prog->autoload) + if (prog->load_strategy == BPF_PROG_LOAD_STRATEGY_DISABLED) continue; err = bpf_object__relocate_calls(obj, prog); @@ -7594,7 +7595,7 @@ static int bpf_object__relocate(struct bpf_object *obj, const char *targ_btf_pat prog = &obj->programs[i]; if (prog_is_subprog(obj, prog)) continue; - if (!prog->autoload) + if (prog->load_strategy == BPF_PROG_LOAD_STRATEGY_DISABLED) continue; /* Process data relos for main programs */ @@ -8433,8 +8434,8 @@ bpf_object__load_progs(struct bpf_object *obj, int log_level) prog = &obj->programs[i]; if (prog_is_subprog(obj, prog)) continue; - if (!prog->autoload) { - pr_debug("prog '%s': skipped loading\n", prog->name); + if (prog->load_strategy != BPF_PROG_LOAD_STRATEGY_AUTO) { + pr_debug("prog '%s': skipped auto-loading\n", prog->name); continue; } prog->log_level |= log_level; @@ -9877,16 +9878,13 @@ const char *bpf_program__section_name(const struct bpf_program *prog) bool bpf_program__autoload(const struct bpf_program *prog) { - return prog->autoload; + return prog->load_strategy == BPF_PROG_LOAD_STRATEGY_AUTO; } int bpf_program__set_autoload(struct bpf_program *prog, bool autoload) { - if (prog->obj->state >= OBJ_LOADED) - return libbpf_err(-EINVAL); - - prog->autoload = autoload; - return 0; + return bpf_program__set_load_strategy(prog, + autoload ? BPF_PROG_LOAD_STRATEGY_AUTO : BPF_PROG_LOAD_STRATEGY_DISABLED); } bool bpf_program__autoattach(const struct bpf_program *prog) @@ -15264,7 +15262,7 @@ int bpf_object__attach_skeleton(struct bpf_object_skeleton *s) struct bpf_program *prog = *prog_skel->prog; struct bpf_link **link = prog_skel->link; - if (!prog->autoload || !prog->autoattach) + if (prog->load_strategy != BPF_PROG_LOAD_STRATEGY_AUTO || !prog->autoattach) continue; /* auto-attaching not supported for this program */ @@ -15374,3 +15372,17 @@ void bpf_object__destroy_skeleton(struct bpf_object_skeleton *s) free(s->progs); free(s); } + +int bpf_program__set_load_strategy(struct bpf_program *prog, enum bpf_prog_load_strategy strategy) +{ + if (prog->obj->state >= OBJ_LOADED) + return libbpf_err(-EINVAL); + + prog->load_strategy = strategy; + return 0; +} + +enum bpf_prog_load_strategy bpf_program__load_strategy(const struct bpf_program *prog) +{ + return prog->load_strategy; +} diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index 03f794f4adb0..e7255bd4247f 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -2117,6 +2117,39 @@ LIBBPF_API int libbpf_unregister_prog_handler(int handler_id); */ LIBBPF_API int bpf_program__clone(struct bpf_program *prog, const struct bpf_prog_load_opts *opts); +/** + * The program load strategy: + * + * - BPF_PROG_LOAD_STRATEGY_DISABLED: the program is not loaded. + * - BPF_PROG_LOAD_STRATEGY_AUTO: the program is autoloaded when the bpf_object is loaded. + */ +enum bpf_prog_load_strategy { + BPF_PROG_LOAD_STRATEGY_DISABLED = 0, + BPF_PROG_LOAD_STRATEGY_AUTO, +}; + +/** + * @brief **bpf_program__set_load_strategy()** sets the load strategy of a + * BPF program, controlling whether and when it gets loaded into the kernel. + * + * Can only be called before the enclosing bpf_object is loaded. + * + * @param prog BPF program to update + * @param strategy new load strategy for the program + * @return 0 on success; negative error code if the object was already loaded + */ +LIBBPF_API int bpf_program__set_load_strategy(struct bpf_program *prog, + enum bpf_prog_load_strategy strategy); + +/** + * @brief **bpf_program__load_strategy()** returns the current load strategy + * of a BPF program. + * + * @param prog BPF program to query + * @return current load strategy of the program + */ +LIBBPF_API enum bpf_prog_load_strategy bpf_program__load_strategy(const struct bpf_program *prog); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map index 7a84dd00ce95..03c3d2bd15bf 100644 --- a/tools/lib/bpf/libbpf.map +++ b/tools/lib/bpf/libbpf.map @@ -463,6 +463,8 @@ LIBBPF_1.8.0 { bpf_program__attach_tracing_multi; bpf_program__clear_flags; bpf_program__clone; + bpf_program__load_strategy; + bpf_program__set_load_strategy; btf__find_by_name_kind_own; btf__new_empty_opts; } LIBBPF_1.7.0; -- 2.34.1