This patch introduces accessors for user of libbpf to retrive section name and fd of a opened/loaded eBPF program. 'struct bpf_prog_handler' is used for that purpose. Accessors of programs section name and file descriptor are provided. Set/get private data are also impelmented.
Signed-off-by: Wang Nan <wangn...@huawei.com> --- tools/lib/bpf/libbpf.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++ tools/lib/bpf/libbpf.h | 25 +++++++++ 2 files changed, 162 insertions(+) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index e8ef78e..d770adc 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -79,6 +79,20 @@ void libbpf_set_print(int (*warn)(const char *format, ...), # define LIBBPF_ELF_C_READ_MMAP ELF_C_READ #endif +#ifndef container_of +# define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) +#endif + +/* Accessing of project */ +struct bpf_prog_handler { + struct bpf_object *obj; + + void *priv; + bpf_prog_clear_priv_t clear_priv; +}; + /* * bpf_prog should be a better name but it has been used in * linux/filter.h. @@ -97,6 +111,7 @@ struct bpf_program { int nr_reloc; int fd; + struct bpf_prog_handler handler; }; struct bpf_object { @@ -146,6 +161,12 @@ static void bpf_clear_program(struct bpf_program *prog) if (!prog) return; + if (prog->handler.clear_priv) + prog->handler.clear_priv(&prog->handler, prog->handler.priv); + + prog->handler.priv = NULL; + prog->handler.clear_priv = NULL; + bpf_unload_program(prog); if (prog->section_name) { @@ -217,6 +238,7 @@ bpf_program_alloc(struct bpf_object *obj, void *data, size_t size, prog->insns_cnt * sizeof(struct bpf_insn)); prog->idx = idx; prog->fd = -1; + prog->handler.obj = obj; return prog; out: @@ -941,3 +963,118 @@ void bpf_close_object(struct bpf_object *obj) } free(obj); } + +static inline struct bpf_program * +handler_to_prog(struct bpf_prog_handler *handler) +{ + struct bpf_program *prog; + struct bpf_object *obj; + size_t idx; + + if (!handler) + goto out_warn; + + obj = handler->obj; + prog = container_of(handler, struct bpf_program, handler); + idx = prog - obj->programs; + if (idx >= obj->nr_programs) + goto out_warn; + return &obj->programs[idx]; + +out_warn: + pr_warning("invalid handler %p\n", handler); + return NULL; +} + +struct bpf_prog_handler * +bpf_next_prog(struct bpf_object *obj, struct bpf_prog_handler *handler) +{ + struct bpf_program *prog; + size_t idx; + + if (!obj->programs) + return NULL; + /* First handler */ + if (handler == NULL) + return (&obj->programs[0].handler); + + if (handler->obj != obj) { + pr_warning("error: program handler doesn't " + "match object\n"); + return NULL; + } + + prog = handler_to_prog(handler); + if (!prog) + return NULL; + + idx = (prog - obj->programs) + 1; + if (idx >= obj->nr_programs) + return NULL; + return &obj->programs[idx].handler; +} + +int bpf_prog_set_private(struct bpf_prog_handler *handler, void *priv, + bpf_prog_clear_priv_t clear_priv) +{ + struct bpf_program *prog; + + prog = handler_to_prog(handler); + if (!prog) + return -EINVAL; + + if (prog->handler.priv && prog->handler.clear_priv) + prog->handler.clear_priv(&prog->handler, prog->handler.priv); + + prog->handler.priv = priv; + prog->handler.clear_priv = clear_priv; + return 0; +} + +int bpf_prog_get_private(struct bpf_prog_handler *handler, void **ppriv) +{ + struct bpf_program *prog; + + prog = handler_to_prog(handler); + if (!prog || !ppriv) + return -EINVAL; + + *ppriv = prog->handler.priv; + return 0; +} + +int bpf_prog_get_title(struct bpf_prog_handler *handler, + const char **ptitle, bool dup) +{ + struct bpf_program *prog; + const char *title; + + prog = handler_to_prog(handler); + if (!prog || !ptitle) + return -EINVAL; + + title = prog->section_name; + if (dup) { + title = strdup(title); + if (!title) { + pr_warning("failed to strdup program title\n"); + *ptitle = NULL; + return -ENOMEM; + } + } + + *ptitle = title; + return 0; +} + +int bpf_prog_get_fd(struct bpf_prog_handler *handler, int *pfd) +{ + struct bpf_program *prog; + + prog = handler_to_prog(handler); + if (!prog || !pfd) + return -EINVAL; + + *pfd = prog->fd; + return 0; +} diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index c0b290d..b451d1a 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -10,6 +10,7 @@ #define __BPF_LIBBPF_H #include <stdio.h> +#include <stdbool.h> void libbpf_set_print(int (*warn)(const char *format, ...), int (*info)(const char *format, ...), @@ -25,6 +26,30 @@ void bpf_close_object(struct bpf_object *object); int bpf_load_object(struct bpf_object *obj); int bpf_unload_object(struct bpf_object *obj); +/* Accessors of bpf_program. */ +struct bpf_prog_handler; +struct bpf_prog_handler *bpf_next_prog(struct bpf_object *obj, + struct bpf_prog_handler *handler); + +#define bpf_obj_for_each_prog(obj, pos) \ + for ((pos) = bpf_next_prog((obj), NULL); \ + (pos) != NULL; \ + (pos) = bpf_next_prog((obj), (pos))) + +typedef void (*bpf_prog_clear_priv_t)(struct bpf_prog_handler *, + void *); + +int bpf_prog_set_private(struct bpf_prog_handler *handler, void *priv, + bpf_prog_clear_priv_t clear_priv); + +int bpf_prog_get_private(struct bpf_prog_handler *handler, + void **ppriv); + +int bpf_prog_get_title(struct bpf_prog_handler *handler, + const char **ptitle, bool dup); + +int bpf_prog_get_fd(struct bpf_prog_handler *handler, int *pfd); + /* * packed attribute is unnecessary for 'bpf_map_def'. */ -- 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/