bpftool: Add support for dumping streams

Add support for printing the BPF stream contents of a program in
bpftool. The new bpftool prog tracelog command is extended to take
stdout and stderr arguments, and then the prog specification.

The bpf_prog_stream_read() API added in previous patch is simply reused
to grab data and then it is dumped to the respective file. The stdout
data is sent to stdout, and stderr is printed to stderr.

Cc: Quentin Monnet <qmo@kernel.org>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20250703204818.925464-12-memxor@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Kumar Kartikeya Dwivedi
2025-07-03 13:48:17 -07:00
committed by Alexei Starovoitov
parent 3bbc1ba9cc
commit 876f5ebd58
3 changed files with 70 additions and 2 deletions

View File

@@ -35,6 +35,7 @@ PROG COMMANDS
| **bpftool** **prog attach** *PROG* *ATTACH_TYPE* [*MAP*]
| **bpftool** **prog detach** *PROG* *ATTACH_TYPE* [*MAP*]
| **bpftool** **prog tracelog**
| **bpftool** **prog tracelog** [ { **stdout** | **stderr** } *PROG* ]
| **bpftool** **prog run** *PROG* **data_in** *FILE* [**data_out** *FILE* [**data_size_out** *L*]] [**ctx_in** *FILE* [**ctx_out** *FILE* [**ctx_size_out** *M*]]] [**repeat** *N*]
| **bpftool** **prog profile** *PROG* [**duration** *DURATION*] *METRICs*
| **bpftool** **prog help**
@@ -179,6 +180,12 @@ bpftool prog tracelog
purposes. For streaming data from BPF programs to user space, one can use
perf events (see also **bpftool-map**\ (8)).
bpftool prog tracelog { stdout | stderr } *PROG*
Dump the BPF stream of the program. BPF programs can write to these streams
at runtime with the **bpf_stream_vprintk**\ () kfunc. The kernel may write
error messages to the standard error stream. This facility should be used
only for debugging purposes.
bpftool prog run *PROG* data_in *FILE* [data_out *FILE* [data_size_out *L*]] [ctx_in *FILE* [ctx_out *FILE* [ctx_size_out *M*]]] [repeat *N*]
Run BPF program *PROG* in the kernel testing infrastructure for BPF,
meaning that the program works on the data and context provided by the

View File

@@ -518,7 +518,21 @@ _bpftool()
esac
;;
tracelog)
return 0
case $prev in
$command)
COMPREPLY+=( $( compgen -W "stdout stderr" -- \
"$cur" ) )
return 0
;;
stdout|stderr)
COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \
"$cur" ) )
return 0
;;
*)
return 0
;;
esac
;;
profile)
case $cword in

View File

@@ -1113,6 +1113,52 @@ static int do_detach(int argc, char **argv)
return 0;
}
enum prog_tracelog_mode {
TRACE_STDOUT,
TRACE_STDERR,
};
static int
prog_tracelog_stream(int prog_fd, enum prog_tracelog_mode mode)
{
FILE *file = mode == TRACE_STDOUT ? stdout : stderr;
int stream_id = mode == TRACE_STDOUT ? 1 : 2;
char buf[512];
int ret;
ret = 0;
do {
ret = bpf_prog_stream_read(prog_fd, stream_id, buf, sizeof(buf), NULL);
if (ret > 0)
fwrite(buf, sizeof(buf[0]), ret, file);
} while (ret > 0);
fflush(file);
return ret ? -1 : 0;
}
static int do_tracelog_any(int argc, char **argv)
{
enum prog_tracelog_mode mode;
int fd;
if (argc == 0)
return do_tracelog(argc, argv);
if (!is_prefix(*argv, "stdout") && !is_prefix(*argv, "stderr"))
usage();
mode = is_prefix(*argv, "stdout") ? TRACE_STDOUT : TRACE_STDERR;
NEXT_ARG();
if (!REQ_ARGS(2))
return -1;
fd = prog_parse_fd(&argc, &argv);
if (fd < 0)
return -1;
return prog_tracelog_stream(fd, mode);
}
static int check_single_stdin(char *file_data_in, char *file_ctx_in)
{
if (file_data_in && file_ctx_in &&
@@ -2493,6 +2539,7 @@ static int do_help(int argc, char **argv)
" [repeat N]\n"
" %1$s %2$s profile PROG [duration DURATION] METRICs\n"
" %1$s %2$s tracelog\n"
" %1$s %2$s tracelog { stdout | stderr } PROG\n"
" %1$s %2$s help\n"
"\n"
" " HELP_SPEC_MAP "\n"
@@ -2532,7 +2579,7 @@ static const struct cmd cmds[] = {
{ "loadall", do_loadall },
{ "attach", do_attach },
{ "detach", do_detach },
{ "tracelog", do_tracelog },
{ "tracelog", do_tracelog_any },
{ "run", do_run },
{ "profile", do_profile },
{ 0 }