Commit 77380998 authored by Stanislav Fomichev's avatar Stanislav Fomichev Committed by Alexei Starovoitov

bpftool: add loadall command

This patch adds new *loadall* command which slightly differs from the
existing *load*. *load* command loads all programs from the obj file,
but pins only the first programs. *loadall* pins all programs from the
obj file under specified directory.

The intended usecase is flow_dissector, where we want to load a bunch
of progs, pin them all and after that construct a jump table.
Signed-off-by: default avatarStanislav Fomichev <sdf@google.com>
Acked-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 33a2c75c
...@@ -15,7 +15,8 @@ SYNOPSIS ...@@ -15,7 +15,8 @@ SYNOPSIS
*OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-f** | **--bpffs** } } *OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-f** | **--bpffs** } }
*COMMANDS* := *COMMANDS* :=
{ **show** | **list** | **dump xlated** | **dump jited** | **pin** | **load** | **help** } { **show** | **list** | **dump xlated** | **dump jited** | **pin** | **load**
| **loadall** | **help** }
MAP COMMANDS MAP COMMANDS
============= =============
...@@ -24,7 +25,7 @@ MAP COMMANDS ...@@ -24,7 +25,7 @@ MAP COMMANDS
| **bpftool** **prog dump xlated** *PROG* [{**file** *FILE* | **opcodes** | **visual**}] | **bpftool** **prog dump xlated** *PROG* [{**file** *FILE* | **opcodes** | **visual**}]
| **bpftool** **prog dump jited** *PROG* [{**file** *FILE* | **opcodes**}] | **bpftool** **prog dump jited** *PROG* [{**file** *FILE* | **opcodes**}]
| **bpftool** **prog pin** *PROG* *FILE* | **bpftool** **prog pin** *PROG* *FILE*
| **bpftool** **prog load** *OBJ* *FILE* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*] | **bpftool** **prog { load | loadall }** *OBJ* *PATH* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*]
| **bpftool** **prog attach** *PROG* *ATTACH_TYPE* *MAP* | **bpftool** **prog attach** *PROG* *ATTACH_TYPE* *MAP*
| **bpftool** **prog detach** *PROG* *ATTACH_TYPE* *MAP* | **bpftool** **prog detach** *PROG* *ATTACH_TYPE* *MAP*
| **bpftool** **prog help** | **bpftool** **prog help**
...@@ -79,8 +80,11 @@ DESCRIPTION ...@@ -79,8 +80,11 @@ DESCRIPTION
contain a dot character ('.'), which is reserved for future contain a dot character ('.'), which is reserved for future
extensions of *bpffs*. extensions of *bpffs*.
**bpftool prog load** *OBJ* *FILE* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*] **bpftool prog { load | loadall }** *OBJ* *PATH* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*]
Load bpf program from binary *OBJ* and pin as *FILE*. Load bpf program(s) from binary *OBJ* and pin as *PATH*.
**bpftool prog load** pins only the first program from the
*OBJ* as *PATH*. **bpftool prog loadall** pins all programs
from the *OBJ* under *PATH* directory.
**type** is optional, if not specified program type will be **type** is optional, if not specified program type will be
inferred from section names. inferred from section names.
By default bpftool will create new maps as declared in the ELF By default bpftool will create new maps as declared in the ELF
...@@ -93,7 +97,7 @@ DESCRIPTION ...@@ -93,7 +97,7 @@ DESCRIPTION
If **dev** *NAME* is specified program will be loaded onto If **dev** *NAME* is specified program will be loaded onto
given networking device (offload). given networking device (offload).
Note: *FILE* must be located in *bpffs* mount. It must not Note: *PATH* must be located in *bpffs* mount. It must not
contain a dot character ('.'), which is reserved for future contain a dot character ('.'), which is reserved for future
extensions of *bpffs*. extensions of *bpffs*.
......
...@@ -243,7 +243,7 @@ _bpftool() ...@@ -243,7 +243,7 @@ _bpftool()
# Completion depends on object and command in use # Completion depends on object and command in use
case $object in case $object in
prog) prog)
if [[ $command != "load" ]]; then if [[ $command != "load" && $command != "loadall" ]]; then
case $prev in case $prev in
id) id)
_bpftool_get_prog_ids _bpftool_get_prog_ids
...@@ -309,7 +309,7 @@ _bpftool() ...@@ -309,7 +309,7 @@ _bpftool()
fi fi
return 0 return 0
;; ;;
load) load|loadall)
local obj local obj
if [[ ${#words[@]} -lt 6 ]]; then if [[ ${#words[@]} -lt 6 ]]; then
......
...@@ -177,34 +177,23 @@ int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type) ...@@ -177,34 +177,23 @@ int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type)
return fd; return fd;
} }
int do_pin_fd(int fd, const char *name) int mount_bpffs_for_pin(const char *name)
{ {
char err_str[ERR_MAX_LEN]; char err_str[ERR_MAX_LEN];
char *file; char *file;
char *dir; char *dir;
int err = 0; int err = 0;
err = bpf_obj_pin(fd, name);
if (!err)
goto out;
file = malloc(strlen(name) + 1); file = malloc(strlen(name) + 1);
strcpy(file, name); strcpy(file, name);
dir = dirname(file); dir = dirname(file);
if (errno != EPERM || is_bpffs(dir)) { if (is_bpffs(dir))
p_err("can't pin the object (%s): %s", name, strerror(errno)); /* nothing to do if already mounted */
goto out_free; goto out_free;
}
/* Attempt to mount bpffs, then retry pinning. */
err = mnt_bpffs(dir, err_str, ERR_MAX_LEN); err = mnt_bpffs(dir, err_str, ERR_MAX_LEN);
if (!err) { if (err) {
err = bpf_obj_pin(fd, name);
if (err)
p_err("can't pin the object (%s): %s", name,
strerror(errno));
} else {
err_str[ERR_MAX_LEN - 1] = '\0'; err_str[ERR_MAX_LEN - 1] = '\0';
p_err("can't mount BPF file system to pin the object (%s): %s", p_err("can't mount BPF file system to pin the object (%s): %s",
name, err_str); name, err_str);
...@@ -212,10 +201,20 @@ int do_pin_fd(int fd, const char *name) ...@@ -212,10 +201,20 @@ int do_pin_fd(int fd, const char *name)
out_free: out_free:
free(file); free(file);
out:
return err; return err;
} }
int do_pin_fd(int fd, const char *name)
{
int err;
err = mount_bpffs_for_pin(name);
if (err)
return err;
return bpf_obj_pin(fd, name);
}
int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32)) int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32))
{ {
unsigned int id; unsigned int id;
......
...@@ -131,6 +131,7 @@ const char *get_fd_type_name(enum bpf_obj_type type); ...@@ -131,6 +131,7 @@ const char *get_fd_type_name(enum bpf_obj_type type);
char *get_fdinfo(int fd, const char *key); char *get_fdinfo(int fd, const char *key);
int open_obj_pinned(char *path); int open_obj_pinned(char *path);
int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type); int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type);
int mount_bpffs_for_pin(const char *name);
int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32)); int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32));
int do_pin_fd(int fd, const char *name); int do_pin_fd(int fd, const char *name);
......
...@@ -792,15 +792,16 @@ static int do_detach(int argc, char **argv) ...@@ -792,15 +792,16 @@ static int do_detach(int argc, char **argv)
jsonw_null(json_wtr); jsonw_null(json_wtr);
return 0; return 0;
} }
static int do_load(int argc, char **argv)
static int load_with_options(int argc, char **argv, bool first_prog_only)
{ {
enum bpf_attach_type expected_attach_type; enum bpf_attach_type expected_attach_type;
struct bpf_object_open_attr attr = { struct bpf_object_open_attr attr = {
.prog_type = BPF_PROG_TYPE_UNSPEC, .prog_type = BPF_PROG_TYPE_UNSPEC,
}; };
struct map_replace *map_replace = NULL; struct map_replace *map_replace = NULL;
struct bpf_program *prog = NULL, *pos;
unsigned int old_map_fds = 0; unsigned int old_map_fds = 0;
struct bpf_program *prog;
struct bpf_object *obj; struct bpf_object *obj;
struct bpf_map *map; struct bpf_map *map;
const char *pinfile; const char *pinfile;
...@@ -918,26 +919,25 @@ static int do_load(int argc, char **argv) ...@@ -918,26 +919,25 @@ static int do_load(int argc, char **argv)
goto err_free_reuse_maps; goto err_free_reuse_maps;
} }
prog = bpf_program__next(NULL, obj); bpf_object__for_each_program(pos, obj) {
if (!prog) { enum bpf_prog_type prog_type = attr.prog_type;
p_err("object file doesn't contain any bpf program");
goto err_close_obj;
}
bpf_program__set_ifindex(prog, ifindex); if (attr.prog_type == BPF_PROG_TYPE_UNSPEC) {
if (attr.prog_type == BPF_PROG_TYPE_UNSPEC) { const char *sec_name = bpf_program__title(pos, false);
const char *sec_name = bpf_program__title(prog, false);
err = libbpf_prog_type_by_name(sec_name, &attr.prog_type, err = libbpf_prog_type_by_name(sec_name, &prog_type,
&expected_attach_type); &expected_attach_type);
if (err < 0) { if (err < 0) {
p_err("failed to guess program type based on section name %s\n", p_err("failed to guess program type based on section name %s\n",
sec_name); sec_name);
goto err_close_obj; goto err_close_obj;
}
} }
bpf_program__set_ifindex(pos, ifindex);
bpf_program__set_type(pos, prog_type);
bpf_program__set_expected_attach_type(pos, expected_attach_type);
} }
bpf_program__set_type(prog, attr.prog_type);
bpf_program__set_expected_attach_type(prog, expected_attach_type);
qsort(map_replace, old_map_fds, sizeof(*map_replace), qsort(map_replace, old_map_fds, sizeof(*map_replace),
map_replace_compar); map_replace_compar);
...@@ -1003,9 +1003,31 @@ static int do_load(int argc, char **argv) ...@@ -1003,9 +1003,31 @@ static int do_load(int argc, char **argv)
goto err_close_obj; goto err_close_obj;
} }
if (do_pin_fd(bpf_program__fd(prog), pinfile)) err = mount_bpffs_for_pin(pinfile);
if (err)
goto err_close_obj; goto err_close_obj;
if (first_prog_only) {
prog = bpf_program__next(NULL, obj);
if (!prog) {
p_err("object file doesn't contain any bpf program");
goto err_close_obj;
}
err = bpf_obj_pin(bpf_program__fd(prog), pinfile);
if (err) {
p_err("failed to pin program %s",
bpf_program__title(prog, false));
goto err_close_obj;
}
} else {
err = bpf_object__pin_programs(obj, pinfile);
if (err) {
p_err("failed to pin all programs");
goto err_close_obj;
}
}
if (json_output) if (json_output)
jsonw_null(json_wtr); jsonw_null(json_wtr);
...@@ -1025,6 +1047,16 @@ static int do_load(int argc, char **argv) ...@@ -1025,6 +1047,16 @@ static int do_load(int argc, char **argv)
return -1; return -1;
} }
static int do_load(int argc, char **argv)
{
return load_with_options(argc, argv, true);
}
static int do_loadall(int argc, char **argv)
{
return load_with_options(argc, argv, false);
}
static int do_help(int argc, char **argv) static int do_help(int argc, char **argv)
{ {
if (json_output) { if (json_output) {
...@@ -1037,7 +1069,8 @@ static int do_help(int argc, char **argv) ...@@ -1037,7 +1069,8 @@ static int do_help(int argc, char **argv)
" %s %s dump xlated PROG [{ file FILE | opcodes | visual }]\n" " %s %s dump xlated PROG [{ file FILE | opcodes | visual }]\n"
" %s %s dump jited PROG [{ file FILE | opcodes }]\n" " %s %s dump jited PROG [{ file FILE | opcodes }]\n"
" %s %s pin PROG FILE\n" " %s %s pin PROG FILE\n"
" %s %s load OBJ FILE [type TYPE] [dev NAME] \\\n" " %s %s { load | loadall } OBJ PATH \\\n"
" [type TYPE] [dev NAME] \\\n"
" [map { idx IDX | name NAME } MAP]\n" " [map { idx IDX | name NAME } MAP]\n"
" %s %s attach PROG ATTACH_TYPE MAP\n" " %s %s attach PROG ATTACH_TYPE MAP\n"
" %s %s detach PROG ATTACH_TYPE MAP\n" " %s %s detach PROG ATTACH_TYPE MAP\n"
...@@ -1069,6 +1102,7 @@ static const struct cmd cmds[] = { ...@@ -1069,6 +1102,7 @@ static const struct cmd cmds[] = {
{ "dump", do_dump }, { "dump", do_dump },
{ "pin", do_pin }, { "pin", do_pin },
{ "load", do_load }, { "load", do_load },
{ "loadall", do_loadall },
{ "attach", do_attach }, { "attach", do_attach },
{ "detach", do_detach }, { "detach", do_detach },
{ 0 } { 0 }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment