This switches over loading of XDP programs to the using libbpf, if it is available. It uses the automatic pinning features added to libbpf to construct the same pinning paths as the libelf-based loader. Since map-in-map support has not yet been added to libbpf, this means that map-in-map definitions will not work with this patch. Signed-off-by: Toke Høiland-Jørgensen <toke@xxxxxxxxxx> --- lib/bpf.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 102 insertions(+), 13 deletions(-) diff --git a/lib/bpf.c b/lib/bpf.c index c6e3bd0d..de1a655a 100644 --- a/lib/bpf.c +++ b/lib/bpf.c @@ -938,9 +938,17 @@ static int bpf_do_parse(struct bpf_cfg_in *cfg, const bool *opt_tbl) return ret; } +#ifdef HAVE_LIBBPF +static int bpf_do_load_libbpf(struct bpf_cfg_in *cfg); +#endif + static int bpf_do_load(struct bpf_cfg_in *cfg) { if (cfg->mode == EBPF_OBJECT) { +#ifdef HAVE_LIBBPF + if(cfg->type == BPF_PROG_TYPE_XDP) + return bpf_do_load_libbpf(cfg); +#endif cfg->prog_fd = bpf_obj_open(cfg->object, cfg->type, cfg->section, cfg->ifindex, cfg->verbose); @@ -1407,25 +1415,22 @@ static bool bpf_no_pinning(const struct bpf_elf_ctx *ctx, } } -static void bpf_make_pathname(char *pathname, size_t len, const char *name, +static int bpf_make_pathname(char *pathname, size_t len, const char *name, const struct bpf_elf_ctx *ctx, uint32_t pinning) { switch (pinning) { case PIN_OBJECT_NS: - snprintf(pathname, len, "%s/%s/%s", - bpf_get_work_dir(ctx->type), - ctx->obj_uid, name); - break; + return snprintf(pathname, len, "%s/%s/%s", + bpf_get_work_dir(ctx->type), + ctx->obj_uid, name); case PIN_GLOBAL_NS: - snprintf(pathname, len, "%s/%s/%s", - bpf_get_work_dir(ctx->type), - BPF_DIR_GLOBALS, name); - break; + return snprintf(pathname, len, "%s/%s/%s", + bpf_get_work_dir(ctx->type), + BPF_DIR_GLOBALS, name); default: - snprintf(pathname, len, "%s/../%s/%s", - bpf_get_work_dir(ctx->type), - bpf_custom_pinning(ctx, pinning), name); - break; + return snprintf(pathname, len, "%s/../%s/%s", + bpf_get_work_dir(ctx->type), + bpf_custom_pinning(ctx, pinning), name); } } @@ -3160,3 +3165,87 @@ int bpf_recv_map_fds(const char *path, int *fds, struct bpf_map_aux *aux, return ret; } #endif /* HAVE_ELF */ + +#ifdef HAVE_LIBBPF +static int bpf_gen_pin_name(void *priv, char *buf, int buf_len, + const char *name, unsigned int pinning) +{ + struct bpf_elf_ctx *ctx = priv; + const char *tmp; + int ret = 0; + + if (bpf_no_pinning(ctx, pinning) || !bpf_get_work_dir(ctx->type)) + return 0; + + if (pinning == PIN_OBJECT_NS) + ret = bpf_make_obj_path(ctx); + else if ((tmp = bpf_custom_pinning(ctx, pinning))) + ret = bpf_make_custom_path(ctx, tmp); + if (ret < 0) + return ret; + + return bpf_make_pathname(buf, buf_len, name, ctx, pinning); +} + +static int bpf_elf_ctx_init_stub(struct bpf_elf_ctx *ctx, const char *pathname, + enum bpf_prog_type type, int verbose) +{ + uint8_t tmp[20]; + int ret; + + memset(ctx, 0, sizeof(*ctx)); + ret = bpf_obj_hash(pathname, tmp, sizeof(tmp)); + if (ret) + ctx->noafalg = true; + else + hexstring_n2a(tmp, sizeof(tmp), ctx->obj_uid, + sizeof(ctx->obj_uid)); + + ctx->verbose = verbose; + ctx->type = type; + bpf_hash_init(ctx, CONFDIR "/bpf_pinning"); + + return 0; +} + +static int verbose_print(enum libbpf_print_level level, const char *format, + va_list args) +{ + return vfprintf(stderr, format, args); +} + +static int bpf_do_load_libbpf(struct bpf_cfg_in *cfg) +{ + struct bpf_elf_ctx *ctx = &__ctx; + struct bpf_program *prog; + struct bpf_object *obj; + int err, prog_fd = -1; + + struct bpf_prog_load_attr attr = { + .file = cfg->object, + .prog_type = cfg->type, + .ifindex = cfg->ifindex, + .log_level = cfg->verbose, + .auto_pin_cb = bpf_gen_pin_name, + .auto_pin_ctx = ctx, + }; + + if (cfg->verbose) + libbpf_set_print(verbose_print); + + bpf_elf_ctx_init_stub(ctx, cfg->object, cfg->type, cfg->verbose); + + err = bpf_prog_load_xattr(&attr, &obj, &prog_fd); + if (err) + return err; + + if (cfg->section) { + prog = bpf_object__find_program_by_title(obj, + cfg->section); + prog_fd = bpf_program__fd(prog); + } + + cfg->prog_fd = prog_fd; + return cfg->prog_fd; +} +#endif -- 2.22.1