aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorToke Høiland-Jørgensen <toke@redhat.com>2019-08-19 21:18:05 +0200
committerToke Høiland-Jørgensen <toke@redhat.com>2019-08-19 22:18:25 +0200
commit6f535f29b14ace3185d8c5ef6a9e772b47384822 (patch)
treea7d7cffeb04e657180de8153754ea665be0267d7
parent6a48fb76d3d23f19f9532f0f122f13f8ce5cdf16 (diff)
downloadiproute2-libbpf.tar.gz
iproute2: Support loading XDP programs with libbpflibbpf
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@redhat.com>
-rw-r--r--lib/bpf.c115
1 files changed, 102 insertions, 13 deletions
diff --git a/lib/bpf.c b/lib/bpf.c
index c6e3bd0de..de1a655af 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