bpf: pass program type in struct bpf_cfg_in

Program type is needed both for parsing and loading of
the program.  Parsing may also induce the type based on
signatures from __bpf_prog_meta.  Instead of passing
the type around keep it in struct bpf_cfg_in.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
This commit is contained in:
Jakub Kicinski 2017-11-23 18:11:58 -08:00 committed by Stephen Hemminger
parent 6054c1ebf7
commit 658cfebc27
6 changed files with 30 additions and 25 deletions

View File

@ -60,6 +60,7 @@ struct bpf_cfg_in {
const char *object; const char *object;
const char *section; const char *section;
const char *uds; const char *uds;
enum bpf_prog_type type;
int argc; int argc;
char **argv; char **argv;
struct sock_filter *ops; struct sock_filter *ops;
@ -244,8 +245,8 @@ struct bpf_cfg_in {
.off = 0, \ .off = 0, \
.imm = 0 }) .imm = 0 })
int bpf_parse_common(enum bpf_prog_type type, struct bpf_cfg_in *cfg, int bpf_parse_common(struct bpf_cfg_in *cfg, const struct bpf_cfg_ops *ops,
const struct bpf_cfg_ops *ops, void *nl); void *nl);
const char *bpf_prog_to_default_section(enum bpf_prog_type type); const char *bpf_prog_to_default_section(enum bpf_prog_type type);

View File

@ -52,6 +52,7 @@ int xdp_parse(int *argc, char ***argv, struct iplink_req *req, bool generic,
bool drv, bool offload) bool drv, bool offload)
{ {
struct bpf_cfg_in cfg = { struct bpf_cfg_in cfg = {
.type = BPF_PROG_TYPE_XDP,
.argc = *argc, .argc = *argc,
.argv = *argv, .argv = *argv,
}; };
@ -74,7 +75,7 @@ int xdp_parse(int *argc, char ***argv, struct iplink_req *req, bool generic,
return xdp_delete(&xdp); return xdp_delete(&xdp);
} }
if (bpf_parse_common(BPF_PROG_TYPE_XDP, &cfg, &bpf_cb_ops, &xdp)) if (bpf_parse_common(&cfg, &bpf_cb_ops, &xdp))
return -1; return -1;
*argc = cfg.argc; *argc = cfg.argc;

View File

@ -886,6 +886,7 @@ static int lwt_parse_bpf(struct rtattr *rta, size_t len,
int attr, const enum bpf_prog_type bpf_type) int attr, const enum bpf_prog_type bpf_type)
{ {
struct bpf_cfg_in cfg = { struct bpf_cfg_in cfg = {
.type = bpf_type,
.argc = *argcp, .argc = *argcp,
.argv = *argvp, .argv = *argvp,
}; };
@ -897,7 +898,7 @@ static int lwt_parse_bpf(struct rtattr *rta, size_t len,
int err; int err;
nest = rta_nest(rta, len, attr); nest = rta_nest(rta, len, attr);
err = bpf_parse_common(bpf_type, &cfg, &bpf_cb_ops, &x); err = bpf_parse_common(&cfg, &bpf_cb_ops, &x);
if (err < 0) { if (err < 0) {
fprintf(stderr, "Failed to parse eBPF program: %s\n", fprintf(stderr, "Failed to parse eBPF program: %s\n",
strerror(-err)); strerror(-err));

View File

@ -813,8 +813,8 @@ enum bpf_mode {
BPF_MODE_MAX, BPF_MODE_MAX,
}; };
static int bpf_parse(enum bpf_prog_type *type, enum bpf_mode *mode, static int bpf_parse(enum bpf_mode *mode, struct bpf_cfg_in *cfg,
struct bpf_cfg_in *cfg, const bool *opt_tbl) const bool *opt_tbl)
{ {
const char *file, *section, *uds_name; const char *file, *section, *uds_name;
bool verbose = false; bool verbose = false;
@ -852,7 +852,7 @@ static int bpf_parse(enum bpf_prog_type *type, enum bpf_mode *mode,
file = *argv; file = *argv;
NEXT_ARG_FWD(); NEXT_ARG_FWD();
if (*type == BPF_PROG_TYPE_UNSPEC) { if (cfg->type == BPF_PROG_TYPE_UNSPEC) {
if (argc > 0 && matches(*argv, "type") == 0) { if (argc > 0 && matches(*argv, "type") == 0) {
NEXT_ARG(); NEXT_ARG();
for (i = 0; i < ARRAY_SIZE(__bpf_prog_meta); for (i = 0; i < ARRAY_SIZE(__bpf_prog_meta);
@ -861,30 +861,30 @@ static int bpf_parse(enum bpf_prog_type *type, enum bpf_mode *mode,
continue; continue;
if (!matches(*argv, if (!matches(*argv,
__bpf_prog_meta[i].type)) { __bpf_prog_meta[i].type)) {
*type = i; cfg->type = i;
break; break;
} }
} }
if (*type == BPF_PROG_TYPE_UNSPEC) { if (cfg->type == BPF_PROG_TYPE_UNSPEC) {
fprintf(stderr, "What type is \"%s\"?\n", fprintf(stderr, "What type is \"%s\"?\n",
*argv); *argv);
return -1; return -1;
} }
NEXT_ARG_FWD(); NEXT_ARG_FWD();
} else { } else {
*type = BPF_PROG_TYPE_SCHED_CLS; cfg->type = BPF_PROG_TYPE_SCHED_CLS;
} }
} }
section = bpf_prog_to_default_section(*type); section = bpf_prog_to_default_section(cfg->type);
if (argc > 0 && matches(*argv, "section") == 0) { if (argc > 0 && matches(*argv, "section") == 0) {
NEXT_ARG(); NEXT_ARG();
section = *argv; section = *argv;
NEXT_ARG_FWD(); NEXT_ARG_FWD();
} }
if (__bpf_prog_meta[*type].may_uds_export) { if (__bpf_prog_meta[cfg->type].may_uds_export) {
uds_name = getenv(BPF_ENV_UDS); uds_name = getenv(BPF_ENV_UDS);
if (argc > 0 && !uds_name && if (argc > 0 && !uds_name &&
matches(*argv, "export") == 0) { matches(*argv, "export") == 0) {
@ -905,9 +905,9 @@ static int bpf_parse(enum bpf_prog_type *type, enum bpf_mode *mode,
if (*mode == CBPF_BYTECODE || *mode == CBPF_FILE) if (*mode == CBPF_BYTECODE || *mode == CBPF_FILE)
ret = bpf_ops_parse(argc, argv, cfg->ops, *mode == CBPF_FILE); ret = bpf_ops_parse(argc, argv, cfg->ops, *mode == CBPF_FILE);
else if (*mode == EBPF_OBJECT) else if (*mode == EBPF_OBJECT)
ret = bpf_obj_open(file, *type, section, verbose); ret = bpf_obj_open(file, cfg->type, section, verbose);
else if (*mode == EBPF_PINNED) else if (*mode == EBPF_PINNED)
ret = bpf_obj_pinned(file, *type); ret = bpf_obj_pinned(file, cfg->type);
else else
return -1; return -1;
@ -920,7 +920,7 @@ static int bpf_parse(enum bpf_prog_type *type, enum bpf_mode *mode,
return ret; return ret;
} }
static int bpf_parse_opt_tbl(enum bpf_prog_type type, struct bpf_cfg_in *cfg, static int bpf_parse_opt_tbl(struct bpf_cfg_in *cfg,
const struct bpf_cfg_ops *ops, void *nl, const struct bpf_cfg_ops *ops, void *nl,
const bool *opt_tbl) const bool *opt_tbl)
{ {
@ -930,7 +930,7 @@ static int bpf_parse_opt_tbl(enum bpf_prog_type type, struct bpf_cfg_in *cfg,
int ret; int ret;
cfg->ops = opcodes; cfg->ops = opcodes;
ret = bpf_parse(&type, &mode, cfg, opt_tbl); ret = bpf_parse(&mode, cfg, opt_tbl);
cfg->ops = NULL; cfg->ops = NULL;
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -947,8 +947,8 @@ static int bpf_parse_opt_tbl(enum bpf_prog_type type, struct bpf_cfg_in *cfg,
return 0; return 0;
} }
int bpf_parse_common(enum bpf_prog_type type, struct bpf_cfg_in *cfg, int bpf_parse_common(struct bpf_cfg_in *cfg, const struct bpf_cfg_ops *ops,
const struct bpf_cfg_ops *ops, void *nl) void *nl)
{ {
bool opt_tbl[BPF_MODE_MAX] = {}; bool opt_tbl[BPF_MODE_MAX] = {};
@ -962,12 +962,11 @@ int bpf_parse_common(enum bpf_prog_type type, struct bpf_cfg_in *cfg,
opt_tbl[EBPF_PINNED] = true; opt_tbl[EBPF_PINNED] = true;
} }
return bpf_parse_opt_tbl(type, cfg, ops, nl, opt_tbl); return bpf_parse_opt_tbl(cfg, ops, nl, opt_tbl);
} }
int bpf_graft_map(const char *map_path, uint32_t *key, int argc, char **argv) int bpf_graft_map(const char *map_path, uint32_t *key, int argc, char **argv)
{ {
enum bpf_prog_type type = BPF_PROG_TYPE_UNSPEC;
const bool opt_tbl[BPF_MODE_MAX] = { const bool opt_tbl[BPF_MODE_MAX] = {
[EBPF_OBJECT] = true, [EBPF_OBJECT] = true,
[EBPF_PINNED] = true, [EBPF_PINNED] = true,
@ -978,6 +977,7 @@ int bpf_graft_map(const char *map_path, uint32_t *key, int argc, char **argv)
.size_value = sizeof(int), .size_value = sizeof(int),
}; };
struct bpf_cfg_in cfg = { struct bpf_cfg_in cfg = {
.type = BPF_PROG_TYPE_UNSPEC,
.argc = argc, .argc = argc,
.argv = argv, .argv = argv,
}; };
@ -986,7 +986,7 @@ int bpf_graft_map(const char *map_path, uint32_t *key, int argc, char **argv)
enum bpf_mode mode; enum bpf_mode mode;
uint32_t map_key; uint32_t map_key;
prog_fd = bpf_parse(&type, &mode, &cfg, opt_tbl); prog_fd = bpf_parse(&mode, &cfg, opt_tbl);
if (prog_fd < 0) if (prog_fd < 0)
return prog_fd; return prog_fd;
if (key) { if (key) {
@ -1000,7 +1000,7 @@ int bpf_graft_map(const char *map_path, uint32_t *key, int argc, char **argv)
} }
} }
map_fd = bpf_obj_get(map_path, type); map_fd = bpf_obj_get(map_path, cfg.type);
if (map_fd < 0) { if (map_fd < 0) {
fprintf(stderr, "Couldn\'t retrieve pinned map \'%s\': %s\n", fprintf(stderr, "Couldn\'t retrieve pinned map \'%s\': %s\n",
map_path, strerror(errno)); map_path, strerror(errno));
@ -1010,7 +1010,7 @@ int bpf_graft_map(const char *map_path, uint32_t *key, int argc, char **argv)
ret = bpf_map_selfcheck_pinned(map_fd, &test, &ext, ret = bpf_map_selfcheck_pinned(map_fd, &test, &ext,
offsetof(struct bpf_elf_map, max_elem), offsetof(struct bpf_elf_map, max_elem),
type); cfg.type);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "Map \'%s\' self-check failed!\n", map_path); fprintf(stderr, "Map \'%s\' self-check failed!\n", map_path);
goto out_map; goto out_map;

View File

@ -103,10 +103,11 @@ static int bpf_parse_opt(struct filter_util *qu, char *handle,
NEXT_ARG(); NEXT_ARG();
opt_bpf: opt_bpf:
seen_run = true; seen_run = true;
cfg.type = bpf_type;
cfg.argc = argc; cfg.argc = argc;
cfg.argv = argv; cfg.argv = argv;
if (bpf_parse_common(bpf_type, &cfg, &bpf_cb_ops, n)) if (bpf_parse_common(&cfg, &bpf_cb_ops, n))
return -1; return -1;
argc = cfg.argc; argc = cfg.argc;

View File

@ -98,10 +98,11 @@ static int bpf_parse_opt(struct action_util *a, int *ptr_argc, char ***ptr_argv,
NEXT_ARG(); NEXT_ARG();
opt_bpf: opt_bpf:
seen_run = true; seen_run = true;
cfg.type = bpf_type;
cfg.argc = argc; cfg.argc = argc;
cfg.argv = argv; cfg.argv = argv;
if (bpf_parse_common(bpf_type, &cfg, &bpf_cb_ops, n)) if (bpf_parse_common(&cfg, &bpf_cb_ops, n))
return -1; return -1;
argc = cfg.argc; argc = cfg.argc;