Implemented "bpftool dumper" command. Two subcommands now: bpftool dumper pin <bpf_prog.o> <dumper_name> bpftool dumper show {target|dumper} The "pin" subcommand will create a dumper with <dumper_name> under the dump target (specified in <bpf_prog>.o). The "show" subcommand will show target func protos, which will be useful on how to write the bpf program, and the "dumper" subcommand will show the corresponding prog_id for each dumper. For example, with some of later selftest dumpers are pinned in the kernel, we can do inspection like below: $ bpftool dumper show target target prog_proto task bpfdump__task task/file bpfdump__task_file bpf_map bpfdump__bpf_map ipv6_route bpfdump__ipv6_route netlink bpfdump__netlink $ bpftool dumper show dumper dumper prog_id task/my1 8 task/file/my1 12 bpf_map/my1 4 ipv6_route/my2 16 netlink/my2 24 netlink/my3 20 Signed-off-by: Yonghong Song <yhs@xxxxxx> --- tools/bpf/bpftool/dumper.c | 131 +++++++++++++++++++++++++++++++++++++ tools/bpf/bpftool/main.c | 3 +- tools/bpf/bpftool/main.h | 1 + 3 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 tools/bpf/bpftool/dumper.c diff --git a/tools/bpf/bpftool/dumper.c b/tools/bpf/bpftool/dumper.c new file mode 100644 index 000000000000..81389083dec5 --- /dev/null +++ b/tools/bpf/bpftool/dumper.c @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +// Copyright (C) 2020 Facebook +// Author: Yonghong Song <yhs@xxxxxx> + +#define _GNU_SOURCE +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> +#include <ftw.h> + +#include <linux/err.h> +#include <bpf/bpf.h> +#include <bpf/libbpf.h> + +#include "main.h" + +static int do_pin(int argc, char **argv) +{ + struct bpf_program *prog; + struct bpf_object *obj; + const char *objfile, *dname; + int err; + + if (!REQ_ARGS(2)) { + usage(); + return -1; + } + + objfile = GET_ARG(); + dname = GET_ARG(); + + obj = bpf_object__open(objfile); + if (IS_ERR_OR_NULL(obj)) + return -1; + + err = bpf_object__load(obj); + if (err < 0) + return -1; + + prog = bpf_program__next(NULL, obj); + err = bpf_program__pin_dumper(prog, dname); + return err; +} + +static bool for_targets; +static const char *bpfdump_root = "/sys/kernel/bpfdump"; + +static int check_file(const char *fpath, const struct stat *sb, + int typeflag, struct FTW *ftwbuf) +{ + char proto_buf[64]; + unsigned prog_id; + const char *name; + int ret, fd; + + if ((for_targets && typeflag == FTW_F) || + (!for_targets && typeflag == FTW_D)) + return 0; + + if (for_targets && strcmp(fpath, bpfdump_root) == 0) + return 0; + + fd = open(fpath, O_RDONLY); + if (fd < 0) + return fd; + + ret = bpf_dump_query(fd, 0, proto_buf, sizeof(proto_buf), + &prog_id); + if (ret < 0) + goto done; + + name = fpath + strlen(bpfdump_root) + 1; + if (for_targets) + fprintf(stdout, "%-24s%-24s\n", name, proto_buf); + else + fprintf(stdout, "%-24s%-24d\n", name, prog_id); + +done: + close(fd); + return ret; +} + +static int do_show(int argc, char **argv) +{ + int flags = FTW_PHYS; + int nopenfd = 16; + const char *spec; + + if (!REQ_ARGS(1)) { + usage(); + return -1; + } + + spec = GET_ARG(); + if (strcmp(spec, "target") == 0) { + for_targets = true; + fprintf(stdout, "target prog_proto\n"); + } else if (strcmp(spec, "dumper") == 0) { + fprintf(stdout, "dumper prog_id\n"); + for_targets = false; + } else { + return -1; + } + + if (nftw(bpfdump_root, check_file, nopenfd, flags) == -1) + return -1; + + return 0; +} + +static int do_help(int argc, char **argv) +{ + return 0; +} + +static const struct cmd cmds[] = { + { "help", do_help }, + { "show", do_show }, + { "pin", do_pin }, + { 0 } +}; + +int do_dumper(int argc, char **argv) +{ + return cmd_select(cmds, argc, argv, do_help); +} diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c index 466c269eabdd..8489aba6543d 100644 --- a/tools/bpf/bpftool/main.c +++ b/tools/bpf/bpftool/main.c @@ -58,7 +58,7 @@ static int do_help(int argc, char **argv) " %s batch file FILE\n" " %s version\n" "\n" - " OBJECT := { prog | map | cgroup | perf | net | feature | btf | gen | struct_ops }\n" + " OBJECT := { prog | map | cgroup | perf | net | feature | btf | gen | struct_ops | dumper}\n" " " HELP_SPEC_OPTIONS "\n" "", bin_name, bin_name, bin_name); @@ -222,6 +222,7 @@ static const struct cmd cmds[] = { { "btf", do_btf }, { "gen", do_gen }, { "struct_ops", do_struct_ops }, + { "dumper", do_dumper }, { "version", do_version }, { 0 } }; diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h index 86f14ce26fd7..2c59f319bbe9 100644 --- a/tools/bpf/bpftool/main.h +++ b/tools/bpf/bpftool/main.h @@ -162,6 +162,7 @@ int do_feature(int argc, char **argv); int do_btf(int argc, char **argv); int do_gen(int argc, char **argv); int do_struct_ops(int argc, char **argv); +int do_dumper(int argc, char **arg); int parse_u32_arg(int *argc, char ***argv, __u32 *val, const char *what); int prog_parse_fd(int *argc, char ***argv); -- 2.24.1