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: Stanislav Fomichev <sdf@google.com> Acked-by: Jakub Kicinski <jakub.kicinski@netronome.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
33a2c75c55
commit
77380998d9
@ -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
|
|||||||
| **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
|
|||||||
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
|
|||||||
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()
|
|||||||
# 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()
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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);
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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 @@ err_free_reuse_maps:
|
|||||||
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)
|
|||||||
" %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[] = {
|
|||||||
{ "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 }
|
||||||
|
Loading…
Reference in New Issue
Block a user