Before this patch libbpf can only load program with type BPF_PROG_TYPE_KPROBE program. To make libbpf useful in other scenarios, this patch introduced bpf_program__set_type() and bpf_object__set_type() which allows setting program type.
This changes doesn't break old API. The default program type is BPF_PROG_TYPE_KPROBE. If caller wants to load program with other type, one of these API should be called before bpf_object__load() or in callback function of loader. Signed-off-by: Wang Nan <wangn...@huawei.com> Cc: Arnaldo Carvalho de Melo <a...@redhat.com> --- tools/lib/bpf/libbpf.c | 43 ++++++++++++++++++++++++++++++++++++++----- tools/lib/bpf/libbpf.h | 16 ++++++++++++++++ 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 8334a5a..99be7f1 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -66,6 +66,7 @@ void libbpf_set_print(libbpf_print_fn_t warn, #define ERRNO_OFFSET(e) ((e) - __LIBBPF_ERRNO__START) #define ERRCODE_OFFSET(c) ERRNO_OFFSET(LIBBPF_ERRNO__##c) #define NR_ERRNO (__LIBBPF_ERRNO__END - __LIBBPF_ERRNO__START) +#define BPF_PROG_TYPE_MAX BPF_PROG_TYPE_SCHED_ACT static const char *libbpf_strerror_table[NR_ERRNO] = { [ERRCODE_OFFSET(LIBELF)] = "Something wrong in libelf", @@ -161,6 +162,7 @@ struct bpf_program { struct bpf_object *obj; void *priv; bpf_program_clear_priv_t clear_priv; + enum bpf_prog_type type; }; struct bpf_map { @@ -323,6 +325,7 @@ bpf_object__add_program(struct bpf_object *obj, void *data, size_t size, obj->programs = progs; obj->nr_programs = nr_progs + 1; prog.obj = obj; + prog.type = BPF_PROG_TYPE_KPROBE; progs[nr_progs] = prog; return 0; } @@ -871,7 +874,7 @@ static int bpf_object__collect_reloc(struct bpf_object *obj) } static int -load_program(struct bpf_insn *insns, int insns_cnt, +load_program(struct bpf_insn *insns, int insns_cnt, enum bpf_prog_type type, char *license, u32 kern_version, int *pfd) { int ret; @@ -884,9 +887,8 @@ load_program(struct bpf_insn *insns, int insns_cnt, if (!log_buf) pr_warning("Alloc log buffer for bpf loader error, continue without log\n"); - ret = bpf_load_program(BPF_PROG_TYPE_KPROBE, insns, - insns_cnt, license, kern_version, - log_buf, BPF_LOG_BUF_SIZE); + ret = bpf_load_program(type, insns, insns_cnt, license, + kern_version, log_buf, BPF_LOG_BUF_SIZE); if (ret >= 0) { *pfd = ret; @@ -945,7 +947,7 @@ bpf_program__load(struct bpf_program *prog, pr_warning("Program '%s' is inconsistent: nr(%d) != 1\n", prog->section_name, prog->instances.nr); } - err = load_program(prog->insns, prog->insns_cnt, + err = load_program(prog->insns, prog->insns_cnt, prog->type, license, kern_version, &fd); if (!err) prog->instances.fds[0] = fd; @@ -976,6 +978,7 @@ bpf_program__load(struct bpf_program *prog, err = load_program(result.new_insn_ptr, result.new_insn_cnt, + prog->type, license, kern_version, &fd); if (err) { @@ -1192,6 +1195,25 @@ bpf_object__get_kversion(struct bpf_object *obj) return obj->kern_version; } +int bpf_object__set_type(struct bpf_object *obj, + enum bpf_prog_type type) +{ + struct bpf_program *prog; + int err; + + if (!obj || type <= BPF_PROG_TYPE_UNSPEC || + type > BPF_PROG_TYPE_MAX) + return -EINVAL; + + bpf_object__for_each_program(prog, obj) { + err = bpf_program__set_type(prog, type); + if (err) + return err; + } + + return 0; +} + struct bpf_program * bpf_program__next(struct bpf_program *prev, struct bpf_object *obj) { @@ -1281,6 +1303,17 @@ int bpf_program__set_prep(struct bpf_program *prog, int nr_instances, return 0; } +int bpf_program__set_type(struct bpf_program *prog, + enum bpf_prog_type type) +{ + if (!prog || type <= BPF_PROG_TYPE_UNSPEC || + type > BPF_PROG_TYPE_MAX) + return -EINVAL; + + prog->type = type; + return 0; +} + int bpf_program__nth_fd(struct bpf_program *prog, int n) { int fd; diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index a51594c..c9d4130 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -11,6 +11,7 @@ #include <stdio.h> #include <stdbool.h> #include <linux/err.h> +#include <linux/bpf.h> enum libbpf_errno { __LIBBPF_ERRNO__START = 4000, @@ -58,6 +59,13 @@ int bpf_object__unload(struct bpf_object *obj); const char *bpf_object__get_name(struct bpf_object *obj); unsigned int bpf_object__get_kversion(struct bpf_object *obj); +/* + * Set type of all programs in an object. + * See bpf_program__set_type(). + */ +int bpf_object__set_type(struct bpf_object *obj, + enum bpf_prog_type type); + struct bpf_object *bpf_object__next(struct bpf_object *prev); #define bpf_object__for_each_safe(pos, tmp) \ for ((pos) = bpf_object__next(NULL), \ @@ -150,6 +158,14 @@ typedef int (*bpf_program_prep_t)(struct bpf_program *prog, int n, int bpf_program__set_prep(struct bpf_program *prog, int nr_instance, bpf_program_prep_t prep); +/* + * Set type of a program. Default is BPF_PROG_TYPE_KPROBE. + * This function should be called before bpf_object__load() + * or in bpf_program_prep callback. + */ +int bpf_program__set_type(struct bpf_program *prog, + enum bpf_prog_type type); + int bpf_program__nth_fd(struct bpf_program *prog, int n); /* -- 1.8.3.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/