[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAEf4BzZwFsVPjR+cwvvuuhfAMy0AW=+=oe4bF-1fH8rxsOmeBw@mail.gmail.com>
Date: Tue, 8 Sep 2020 16:20:41 -0700
From: Andrii Nakryiko <andrii.nakryiko@...il.com>
To: Quentin Monnet <quentin@...valent.com>
Cc: Alexei Starovoitov <ast@...nel.org>,
Daniel Borkmann <daniel@...earbox.net>,
bpf <bpf@...r.kernel.org>, Networking <netdev@...r.kernel.org>
Subject: Re: [PATCH bpf-next 1/3] tools: bpftool: print optional built-in
features along with version
On Mon, Sep 7, 2020 at 7:50 AM Quentin Monnet <quentin@...valent.com> wrote:
>
> On 04/09/2020 22:45, Andrii Nakryiko wrote:
> > On Fri, Sep 4, 2020 at 1:57 PM Quentin Monnet <quentin@...valent.com> wrote:
> >>
> >> Bpftool has a number of features that can be included or left aside
> >> during compilation. This includes:
> >>
> >> - Support for libbfd, providing the disassembler for JIT-compiled
> >> programs.
> >> - Support for BPF skeletons, used for profiling programs or iterating on
> >> the PIDs of processes associated with BPF objects.
> >>
> >> In order to make it easy for users to understand what features were
> >> compiled for a given bpftool binary, print the status of the two
> >> features above when showing the version number for bpftool ("bpftool -V"
> >> or "bpftool version"). Document this in the main manual page. Example
> >> invocation:
> >>
> >> $ bpftool -p version
> >> {
> >> "version": "5.9.0-rc1",
> >> "features": [
> >> "libbfd": true,
> >> "skeletons": true
> >> ]
> >
> > Is this a valid JSON? array of key/value pairs?
>
> No it's not, silly me :'(. I'll fix that, thanks for spotting it.
>
> >> }
> >>
> >> Some other parameters are optional at compilation
> >> ("DISASM_FOUR_ARGS_SIGNATURE", LIBCAP support) but they do not impact
> >> significantly bpftool's behaviour from a user's point of view, so their
> >> status is not reported.
> >>
> >> Available commands and supported program types depend on the version
> >> number, and are therefore not reported either. Note that they are
> >> already available, albeit without JSON, via bpftool's help messages.
> >>
> >> Signed-off-by: Quentin Monnet <quentin@...valent.com>
> >> ---
> >> tools/bpf/bpftool/Documentation/bpftool.rst | 8 +++++++-
> >> tools/bpf/bpftool/main.c | 22 +++++++++++++++++++++
> >> 2 files changed, 29 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/tools/bpf/bpftool/Documentation/bpftool.rst b/tools/bpf/bpftool/Documentation/bpftool.rst
> >> index 420d4d5df8b6..a3629a3f1175 100644
> >> --- a/tools/bpf/bpftool/Documentation/bpftool.rst
> >> +++ b/tools/bpf/bpftool/Documentation/bpftool.rst
> >> @@ -50,7 +50,13 @@ OPTIONS
> >> Print short help message (similar to **bpftool help**).
> >>
> >> -V, --version
> >> - Print version number (similar to **bpftool version**).
> >> + Print version number (similar to **bpftool version**), and
> >> + optional features that were included when bpftool was
> >> + compiled. Optional features include linking against libbfd to
> >> + provide the disassembler for JIT-ted programs (**bpftool prog
> >> + dump jited**) and usage of BPF skeletons (some features like
> >> + **bpftool prog profile** or showing pids associated to BPF
> >> + objects may rely on it).
> >
> > nit: I'd emit it as a list, easier to see list of features visually
> >
> >>
> >> -j, --json
> >> Generate JSON output. For commands that cannot produce JSON, this
> >> diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c
> >> index 4a191fcbeb82..2ae8c0d82030 100644
> >> --- a/tools/bpf/bpftool/main.c
> >> +++ b/tools/bpf/bpftool/main.c
> >> @@ -70,13 +70,35 @@ static int do_help(int argc, char **argv)
> >>
> >> static int do_version(int argc, char **argv)
> >> {
> >> +#ifdef HAVE_LIBBFD_SUPPORT
> >> + const bool has_libbfd = true;
> >> +#else
> >> + const bool has_libbfd = false;
> >> +#endif
> >> +#ifdef BPFTOOL_WITHOUT_SKELETONS
> >> + const bool has_skeletons = false;
> >> +#else
> >> + const bool has_skeletons = true;
> >> +#endif
> >> +
> >> if (json_output) {
> >> jsonw_start_object(json_wtr);
> >> +
> >> jsonw_name(json_wtr, "version");
> >> jsonw_printf(json_wtr, "\"%s\"", BPFTOOL_VERSION);
> >> +
> >> + jsonw_name(json_wtr, "features");
> >> + jsonw_start_array(json_wtr);
> >> + jsonw_bool_field(json_wtr, "libbfd", has_libbfd);
> >> + jsonw_bool_field(json_wtr, "skeletons", has_skeletons);
> >> + jsonw_end_array(json_wtr);
> >> +
> >> jsonw_end_object(json_wtr);
> >> } else {
> >> printf("%s v%s\n", bin_name, BPFTOOL_VERSION);
> >> + printf("features: libbfd=%s, skeletons=%s\n",
> >> + has_libbfd ? "true" : "false",
> >> + has_skeletons ? "true" : "false");
> >
> > now imagine parsing this with CLI text tools, you'll have to find
> > "skeletons=(false|true)" and then parse "true" to know skeletons are
> > supported. Why not just print out features that are supported?
>
> You could just grep for "skeletons=true" (not too hard) (And generally
> speaking I'd recommend against parsing bpftool's plain output, JSON is
> more stable - Once you're parsing the JSON, checking the feature is
> present or checking whether it's at "true" does not make a great
> difference).
>
> Anyway, the reason I have those booleans is that if you just list the
> features and run "bpftool version | grep libbpfd" and get no result, you
> cannot tell if the binary has been compiled without the disassembler or
> if you are running an older version of bpftool that does not list
> built-in features. You could then parse the version number and double
> check, but you need to find in what version the change has been added.
> Besides libbfd and skeletons, this could happen again for future
> optional features if we add them to bpftool but forget to immediately
> add the related check for "bpftool version".
Now you are making this into a list of potential features that could
be supported if only they were built with proper dependencies, don't
you think?
I thought the idea is to detect if a given bpftool that you have
supports, say, skeleton feature. Whether it's too old to support it or
it doesn't support because it wasn't built with necessary dependencies
is immaterial -- it doesn't support the feature, if there is no
"skeleton" in a list of features.
Continuing your logic -- parse JSON if you want to know this. In JSON
having {"skeleton": false, "libbfd": true"} feels natural. In
human-oriented plain text output seeing "features: libbpf=false,
skeleton=true" looks weird, instead of just "features: skeleton", IMO.
>
> So I would be inclined to keep the booleans. Or do you still believe a
> list is preferable?
>
I still believe plain text should be minimal and simple, but won't
argue further :)
> Quentin
Powered by blists - more mailing lists