Merge branch 'bpf-bpftool-dbg-output'
Quentin Monnet says: ==================== This series adds an option to bpftool to make it print additional information via libbpf and the kernel verifier when attempting to load programs. A new API function is added to libbpf in order to pass the log_level from bpftool with the bpf_object__* part of the API. Options for a finer control over the log levels to use for libbpf and the verifier could be added in the future, if desired. v3: - Fix and clarify commit logs. v2: - Do not add distinct options for libbpf and verifier logs, just keep the one that sets all log levels to their maximum. Rename the option. - Do not offer a way to pick desired log levels. The choice is "use the option to print all logs" or "stick with the defaults". - Do not export BPF_LOG_* flags to user header. - Update all man pages (most bpftool operations use libbpf and may print libbpf logs). Verifier logs are only used when attempting to load programs for now, so bpftool-prog.rst and bpftool.rst remain the only pages updated in that regard. Previous discussion available at: https://lore.kernel.org/bpf/20190523105426.3938-1-quentin.monnet@netronome.com/ https://lore.kernel.org/bpf/20190429095227.9745-1-quentin.monnet@netronome.com/ ==================== Acked-by: Yonghong Song <yhs@fb.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
This commit is contained in:
commit
463910a5dd
@ -72,6 +72,10 @@ OPTIONS
|
||||
-p, --pretty
|
||||
Generate human-readable JSON output. Implies **-j**.
|
||||
|
||||
-d, --debug
|
||||
Print all logs available from libbpf, including debug-level
|
||||
information.
|
||||
|
||||
EXAMPLES
|
||||
========
|
||||
**# bpftool btf dump id 1226**
|
||||
|
@ -113,6 +113,10 @@ OPTIONS
|
||||
-f, --bpffs
|
||||
Show file names of pinned programs.
|
||||
|
||||
-d, --debug
|
||||
Print all logs available from libbpf, including debug-level
|
||||
information.
|
||||
|
||||
EXAMPLES
|
||||
========
|
||||
|
|
||||
|
@ -73,6 +73,10 @@ OPTIONS
|
||||
-p, --pretty
|
||||
Generate human-readable JSON output. Implies **-j**.
|
||||
|
||||
-d, --debug
|
||||
Print all logs available from libbpf, including debug-level
|
||||
information.
|
||||
|
||||
SEE ALSO
|
||||
========
|
||||
**bpf**\ (2),
|
||||
|
@ -152,6 +152,10 @@ OPTIONS
|
||||
Do not automatically attempt to mount any virtual file system
|
||||
(such as tracefs or BPF virtual file system) when necessary.
|
||||
|
||||
-d, --debug
|
||||
Print all logs available from libbpf, including debug-level
|
||||
information.
|
||||
|
||||
EXAMPLES
|
||||
========
|
||||
**# bpftool map show**
|
||||
|
@ -65,6 +65,10 @@ OPTIONS
|
||||
-p, --pretty
|
||||
Generate human-readable JSON output. Implies **-j**.
|
||||
|
||||
-d, --debug
|
||||
Print all logs available from libbpf, including debug-level
|
||||
information.
|
||||
|
||||
EXAMPLES
|
||||
========
|
||||
|
||||
|
@ -53,6 +53,10 @@ OPTIONS
|
||||
-p, --pretty
|
||||
Generate human-readable JSON output. Implies **-j**.
|
||||
|
||||
-d, --debug
|
||||
Print all logs available from libbpf, including debug-level
|
||||
information.
|
||||
|
||||
EXAMPLES
|
||||
========
|
||||
|
||||
|
@ -174,6 +174,11 @@ OPTIONS
|
||||
Do not automatically attempt to mount any virtual file system
|
||||
(such as tracefs or BPF virtual file system) when necessary.
|
||||
|
||||
-d, --debug
|
||||
Print all logs available, even debug-level information. This
|
||||
includes logs from libbpf as well as from the verifier, when
|
||||
attempting to load programs.
|
||||
|
||||
EXAMPLES
|
||||
========
|
||||
**# bpftool prog show**
|
||||
|
@ -66,6 +66,10 @@ OPTIONS
|
||||
Do not automatically attempt to mount any virtual file system
|
||||
(such as tracefs or BPF virtual file system) when necessary.
|
||||
|
||||
-d, --debug
|
||||
Print all logs available, even debug-level information. This
|
||||
includes logs from libbpf as well as from the verifier, when
|
||||
attempting to load programs.
|
||||
|
||||
SEE ALSO
|
||||
========
|
||||
|
@ -187,7 +187,7 @@ _bpftool()
|
||||
|
||||
# Deal with options
|
||||
if [[ ${words[cword]} == -* ]]; then
|
||||
local c='--version --json --pretty --bpffs --mapcompat'
|
||||
local c='--version --json --pretty --bpffs --mapcompat --debug'
|
||||
COMPREPLY=( $( compgen -W "$c" -- "$cur" ) )
|
||||
return 0
|
||||
fi
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <bpf.h>
|
||||
#include <libbpf.h>
|
||||
|
||||
#include "main.h"
|
||||
|
||||
@ -25,6 +26,7 @@ bool pretty_output;
|
||||
bool json_output;
|
||||
bool show_pinned;
|
||||
bool block_mount;
|
||||
bool verifier_logs;
|
||||
int bpf_flags;
|
||||
struct pinned_obj_table prog_table;
|
||||
struct pinned_obj_table map_table;
|
||||
@ -77,6 +79,13 @@ static int do_version(int argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __printf(2, 0)
|
||||
print_all_levels(__maybe_unused enum libbpf_print_level level,
|
||||
const char *format, va_list args)
|
||||
{
|
||||
return vfprintf(stderr, format, args);
|
||||
}
|
||||
|
||||
int cmd_select(const struct cmd *cmds, int argc, char **argv,
|
||||
int (*help)(int argc, char **argv))
|
||||
{
|
||||
@ -317,6 +326,7 @@ int main(int argc, char **argv)
|
||||
{ "bpffs", no_argument, NULL, 'f' },
|
||||
{ "mapcompat", no_argument, NULL, 'm' },
|
||||
{ "nomount", no_argument, NULL, 'n' },
|
||||
{ "debug", no_argument, NULL, 'd' },
|
||||
{ 0 }
|
||||
};
|
||||
int opt, ret;
|
||||
@ -332,7 +342,7 @@ int main(int argc, char **argv)
|
||||
hash_init(map_table.table);
|
||||
|
||||
opterr = 0;
|
||||
while ((opt = getopt_long(argc, argv, "Vhpjfmn",
|
||||
while ((opt = getopt_long(argc, argv, "Vhpjfmnd",
|
||||
options, NULL)) >= 0) {
|
||||
switch (opt) {
|
||||
case 'V':
|
||||
@ -362,6 +372,10 @@ int main(int argc, char **argv)
|
||||
case 'n':
|
||||
block_mount = true;
|
||||
break;
|
||||
case 'd':
|
||||
libbpf_set_print(print_all_levels);
|
||||
verifier_logs = true;
|
||||
break;
|
||||
default:
|
||||
p_err("unrecognized option '%s'", argv[optind - 1]);
|
||||
if (json_output)
|
||||
|
@ -91,6 +91,7 @@ extern json_writer_t *json_wtr;
|
||||
extern bool json_output;
|
||||
extern bool show_pinned;
|
||||
extern bool block_mount;
|
||||
extern bool verifier_logs;
|
||||
extern int bpf_flags;
|
||||
extern struct pinned_obj_table prog_table;
|
||||
extern struct pinned_obj_table map_table;
|
||||
|
@ -750,10 +750,11 @@ static int do_detach(int argc, char **argv)
|
||||
|
||||
static int load_with_options(int argc, char **argv, bool first_prog_only)
|
||||
{
|
||||
enum bpf_attach_type expected_attach_type;
|
||||
struct bpf_object_open_attr attr = {
|
||||
.prog_type = BPF_PROG_TYPE_UNSPEC,
|
||||
struct bpf_object_load_attr load_attr = { 0 };
|
||||
struct bpf_object_open_attr open_attr = {
|
||||
.prog_type = BPF_PROG_TYPE_UNSPEC,
|
||||
};
|
||||
enum bpf_attach_type expected_attach_type;
|
||||
struct map_replace *map_replace = NULL;
|
||||
struct bpf_program *prog = NULL, *pos;
|
||||
unsigned int old_map_fds = 0;
|
||||
@ -767,7 +768,7 @@ static int load_with_options(int argc, char **argv, bool first_prog_only)
|
||||
|
||||
if (!REQ_ARGS(2))
|
||||
return -1;
|
||||
attr.file = GET_ARG();
|
||||
open_attr.file = GET_ARG();
|
||||
pinfile = GET_ARG();
|
||||
|
||||
while (argc) {
|
||||
@ -776,7 +777,7 @@ static int load_with_options(int argc, char **argv, bool first_prog_only)
|
||||
|
||||
NEXT_ARG();
|
||||
|
||||
if (attr.prog_type != BPF_PROG_TYPE_UNSPEC) {
|
||||
if (open_attr.prog_type != BPF_PROG_TYPE_UNSPEC) {
|
||||
p_err("program type already specified");
|
||||
goto err_free_reuse_maps;
|
||||
}
|
||||
@ -793,7 +794,8 @@ static int load_with_options(int argc, char **argv, bool first_prog_only)
|
||||
strcat(type, *argv);
|
||||
strcat(type, "/");
|
||||
|
||||
err = libbpf_prog_type_by_name(type, &attr.prog_type,
|
||||
err = libbpf_prog_type_by_name(type,
|
||||
&open_attr.prog_type,
|
||||
&expected_attach_type);
|
||||
free(type);
|
||||
if (err < 0)
|
||||
@ -881,16 +883,16 @@ static int load_with_options(int argc, char **argv, bool first_prog_only)
|
||||
|
||||
set_max_rlimit();
|
||||
|
||||
obj = __bpf_object__open_xattr(&attr, bpf_flags);
|
||||
obj = __bpf_object__open_xattr(&open_attr, bpf_flags);
|
||||
if (IS_ERR_OR_NULL(obj)) {
|
||||
p_err("failed to open object file");
|
||||
goto err_free_reuse_maps;
|
||||
}
|
||||
|
||||
bpf_object__for_each_program(pos, obj) {
|
||||
enum bpf_prog_type prog_type = attr.prog_type;
|
||||
enum bpf_prog_type prog_type = open_attr.prog_type;
|
||||
|
||||
if (attr.prog_type == BPF_PROG_TYPE_UNSPEC) {
|
||||
if (open_attr.prog_type == BPF_PROG_TYPE_UNSPEC) {
|
||||
const char *sec_name = bpf_program__title(pos, false);
|
||||
|
||||
err = libbpf_prog_type_by_name(sec_name, &prog_type,
|
||||
@ -960,7 +962,12 @@ static int load_with_options(int argc, char **argv, bool first_prog_only)
|
||||
goto err_close_obj;
|
||||
}
|
||||
|
||||
err = bpf_object__load(obj);
|
||||
load_attr.obj = obj;
|
||||
if (verifier_logs)
|
||||
/* log_level1 + log_level2 + stats, but not stable UAPI */
|
||||
load_attr.log_level = 1 + 2 + 4;
|
||||
|
||||
err = bpf_object__load_xattr(&load_attr);
|
||||
if (err) {
|
||||
p_err("failed to load object file");
|
||||
goto err_close_obj;
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
BPF_VERSION = 0
|
||||
BPF_PATCHLEVEL = 0
|
||||
BPF_EXTRAVERSION = 3
|
||||
BPF_EXTRAVERSION = 4
|
||||
|
||||
MAKEFLAGS += --no-print-directory
|
||||
|
||||
|
@ -2224,7 +2224,7 @@ static bool bpf_program__is_function_storage(struct bpf_program *prog,
|
||||
}
|
||||
|
||||
static int
|
||||
bpf_object__load_progs(struct bpf_object *obj)
|
||||
bpf_object__load_progs(struct bpf_object *obj, int log_level)
|
||||
{
|
||||
size_t i;
|
||||
int err;
|
||||
@ -2232,6 +2232,7 @@ bpf_object__load_progs(struct bpf_object *obj)
|
||||
for (i = 0; i < obj->nr_programs; i++) {
|
||||
if (bpf_program__is_function_storage(&obj->programs[i], obj))
|
||||
continue;
|
||||
obj->programs[i].log_level = log_level;
|
||||
err = bpf_program__load(&obj->programs[i],
|
||||
obj->license,
|
||||
obj->kern_version);
|
||||
@ -2383,10 +2384,14 @@ int bpf_object__unload(struct bpf_object *obj)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bpf_object__load(struct bpf_object *obj)
|
||||
int bpf_object__load_xattr(struct bpf_object_load_attr *attr)
|
||||
{
|
||||
struct bpf_object *obj;
|
||||
int err;
|
||||
|
||||
if (!attr)
|
||||
return -EINVAL;
|
||||
obj = attr->obj;
|
||||
if (!obj)
|
||||
return -EINVAL;
|
||||
|
||||
@ -2399,7 +2404,7 @@ int bpf_object__load(struct bpf_object *obj)
|
||||
|
||||
CHECK_ERR(bpf_object__create_maps(obj), err, out);
|
||||
CHECK_ERR(bpf_object__relocate(obj), err, out);
|
||||
CHECK_ERR(bpf_object__load_progs(obj), err, out);
|
||||
CHECK_ERR(bpf_object__load_progs(obj, attr->log_level), err, out);
|
||||
|
||||
return 0;
|
||||
out:
|
||||
@ -2408,6 +2413,15 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
int bpf_object__load(struct bpf_object *obj)
|
||||
{
|
||||
struct bpf_object_load_attr attr = {
|
||||
.obj = obj,
|
||||
};
|
||||
|
||||
return bpf_object__load_xattr(&attr);
|
||||
}
|
||||
|
||||
static int check_path(const char *path)
|
||||
{
|
||||
char *cp, errmsg[STRERR_BUFSIZE];
|
||||
|
@ -89,8 +89,14 @@ LIBBPF_API int bpf_object__unpin_programs(struct bpf_object *obj,
|
||||
LIBBPF_API int bpf_object__pin(struct bpf_object *object, const char *path);
|
||||
LIBBPF_API void bpf_object__close(struct bpf_object *object);
|
||||
|
||||
struct bpf_object_load_attr {
|
||||
struct bpf_object *obj;
|
||||
int log_level;
|
||||
};
|
||||
|
||||
/* Load/unload object into/from kernel */
|
||||
LIBBPF_API int bpf_object__load(struct bpf_object *obj);
|
||||
LIBBPF_API int bpf_object__load_xattr(struct bpf_object_load_attr *attr);
|
||||
LIBBPF_API int bpf_object__unload(struct bpf_object *obj);
|
||||
LIBBPF_API const char *bpf_object__name(struct bpf_object *obj);
|
||||
LIBBPF_API unsigned int bpf_object__kversion(struct bpf_object *obj);
|
||||
|
@ -171,4 +171,5 @@ LIBBPF_0.0.4 {
|
||||
btf_dump__free;
|
||||
btf_dump__new;
|
||||
btf__parse_elf;
|
||||
bpf_object__load_xattr;
|
||||
} LIBBPF_0.0.3;
|
||||
|
Loading…
Reference in New Issue
Block a user