From: Slava Imameev This commit is in preparation for the next commit that introduces manual program loading. 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. New getter and setter API is also declared for this enum handling. Signed-off-by: Slava Imameev Signed-off-by: Andrey Grodzovsky --- tools/lib/bpf/libbpf.c | 53 +++++++++++++++++++++++++--------------- tools/lib/bpf/libbpf.h | 33 +++++++++++++++++++++++++ tools/lib/bpf/libbpf.map | 3 +++ 3 files changed, 69 insertions(+), 20 deletions(-) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index ff04718d47c1..e2cea1bca1d2 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; /* the program or a function that it calls has callx */ @@ -956,11 +956,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; @@ -1247,7 +1247,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; @@ -1338,7 +1339,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; } @@ -1376,7 +1377,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; @@ -3811,7 +3812,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; @@ -6500,7 +6501,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 @@ -8171,7 +8172,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); @@ -8207,7 +8208,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 */ @@ -9299,8 +9300,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; @@ -10092,7 +10093,8 @@ static int bpf_object_load(struct bpf_object *obj, int extra_log_level, const ch prog_has_callx(&obj->programs[i])) text_has_callx = true; for (i = 0; i < obj->nr_programs; i++) - if (obj->programs[i].autoload && !prog_is_subprog(obj, &obj->programs[i]) && + if (obj->programs[i].load_strategy != BPF_PROG_LOAD_STRATEGY_DISABLED && + !prog_is_subprog(obj, &obj->programs[i]) && (text_has_callx || prog_has_callx(&obj->programs[i]))) nr_progs++; bpf_gen__init(obj->gen_loader, obj->log_level | extra_log_level, @@ -10776,16 +10778,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) @@ -16174,7 +16173,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 */ @@ -16284,3 +16283,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_PREPARED) + 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..a91e43cbba20 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 prepared. + * + * @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 prepared + */ +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 eeba4072a5da..c06fc6b68efd 100644 --- a/tools/lib/bpf/libbpf.map +++ b/tools/lib/bpf/libbpf.map @@ -475,4 +475,7 @@ LIBBPF_1.8.0 { } LIBBPF_1.7.0; LIBBPF_1.9.0 { + global: + bpf_program__load_strategy; + bpf_program__set_load_strategy; } LIBBPF_1.8.0; -- 2.34.1