[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date: Wed, 9 Sep 2020 09:35:45 +0100
From: Quentin Monnet <quentin@...valent.com>
To: Andrii Nakryiko <andrii.nakryiko@...il.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 09/09/2020 00:20, Andrii Nakryiko wrote:
> 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?
(That will be the case for new versions of bpftool that will be able to
dump their features, won't it? Anyway.)
>
> 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.
I agree the reason does not matter, if the feature is not available then
we cannot use it, period. The concern I have is false negatives. If a
script does "bpftool version | grep libbfd" and gets no output, then it
may skip dumping the JITed instructions, although bpftool might simply
be too old to dump the feature.
>
> 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.
Ok, so we agree we can have the booleans in JSON to have a way to avoid
the "false negative" issue. In that case I'm fine with having a simpler
list for plain output, this will make a small difference in the info
provided between plain output and JSON but it seems acceptable. I'll
send a new version with that change soon.
Thanks,
Quentin
Powered by blists - more mailing lists