Commit 49eb7ab3 authored by Quentin Monnet's avatar Quentin Monnet Committed by Alexei Starovoitov

tools: bpftool: add basic probe capability, probe syscall availability

Add a new component and command for bpftool, in order to probe the
system to dump a set of eBPF-related parameters so that users can know
what features are available on the system.

Parameters are dumped in plain or JSON output (with -j/-p options).

The current patch introduces probing of one simple parameter:
availability of the bpf() system call. Later commits
will add other probes.

Sample output:

    # bpftool feature probe kernel
    Scanning system call availability...
    bpf() syscall is available

    # bpftool --json --pretty feature probe kernel
    {
        "syscall_config": {
            "have_bpf_syscall": true
        }
    }

The optional "kernel" keyword enforces probing of the current system,
which is the only possible behaviour at this stage. It can be safely
omitted.

The feature comes with the relevant man page, but bash completion will
come in a dedicated commit.

v3:
- Do not probe kernel version. Contrarily to what is written below for
  v2, we can have the kernel version retrieved in libbpf instead of
  bpftool (in the patch adding probing for program types).

v2:
- Remove C-style macros output from this patch.
- Even though kernel version is no longer needed for testing kprobes
  availability, note that we still collect it in this patch so that
  bpftool gets able to probe (in next patches) older kernels as well.
Signed-off-by: default avatarQuentin Monnet <quentin.monnet@netronome.com>
Reviewed-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: default avatarStanislav Fomichev <sdf@google.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent d0b2818e
...@@ -142,5 +142,6 @@ SEE ALSO ...@@ -142,5 +142,6 @@ SEE ALSO
**bpftool**\ (8), **bpftool**\ (8),
**bpftool-prog**\ (8), **bpftool-prog**\ (8),
**bpftool-map**\ (8), **bpftool-map**\ (8),
**bpftool-feature**\ (8),
**bpftool-net**\ (8), **bpftool-net**\ (8),
**bpftool-perf**\ (8) **bpftool-perf**\ (8)
===============
bpftool-feature
===============
-------------------------------------------------------------------------------
tool for inspection of eBPF-related parameters for Linux kernel or net device
-------------------------------------------------------------------------------
:Manual section: 8
SYNOPSIS
========
**bpftool** [*OPTIONS*] **feature** *COMMAND*
*OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] }
*COMMANDS* := { **probe** | **help** }
MAP COMMANDS
=============
| **bpftool** **feature probe** [**kernel**]
| **bpftool** **feature help**
DESCRIPTION
===========
**bpftool feature probe** [**kernel**]
Probe the running kernel and dump a number of eBPF-related
parameters, such as availability of the **bpf()** system call.
Keyword **kernel** can be omitted.
**bpftool feature help**
Print short help message.
OPTIONS
=======
-h, --help
Print short generic help message (similar to **bpftool help**).
-v, --version
Print version number (similar to **bpftool version**).
-j, --json
Generate JSON output. For commands that cannot produce JSON, this
option has no effect.
-p, --pretty
Generate human-readable JSON output. Implies **-j**.
SEE ALSO
========
**bpf**\ (2),
**bpf-helpers**\ (7),
**bpftool**\ (8),
**bpftool-prog**\ (8),
**bpftool-map**\ (8),
**bpftool-cgroup**\ (8),
**bpftool-net**\ (8),
**bpftool-perf**\ (8)
...@@ -256,5 +256,6 @@ SEE ALSO ...@@ -256,5 +256,6 @@ SEE ALSO
**bpftool**\ (8), **bpftool**\ (8),
**bpftool-prog**\ (8), **bpftool-prog**\ (8),
**bpftool-cgroup**\ (8), **bpftool-cgroup**\ (8),
**bpftool-feature**\ (8),
**bpftool-net**\ (8), **bpftool-net**\ (8),
**bpftool-perf**\ (8) **bpftool-perf**\ (8)
...@@ -142,4 +142,5 @@ SEE ALSO ...@@ -142,4 +142,5 @@ SEE ALSO
**bpftool-prog**\ (8), **bpftool-prog**\ (8),
**bpftool-map**\ (8), **bpftool-map**\ (8),
**bpftool-cgroup**\ (8), **bpftool-cgroup**\ (8),
**bpftool-feature**\ (8),
**bpftool-perf**\ (8) **bpftool-perf**\ (8)
...@@ -84,4 +84,5 @@ SEE ALSO ...@@ -84,4 +84,5 @@ SEE ALSO
**bpftool-prog**\ (8), **bpftool-prog**\ (8),
**bpftool-map**\ (8), **bpftool-map**\ (8),
**bpftool-cgroup**\ (8), **bpftool-cgroup**\ (8),
**bpftool-feature**\ (8),
**bpftool-net**\ (8) **bpftool-net**\ (8)
...@@ -258,5 +258,6 @@ SEE ALSO ...@@ -258,5 +258,6 @@ SEE ALSO
**bpftool**\ (8), **bpftool**\ (8),
**bpftool-map**\ (8), **bpftool-map**\ (8),
**bpftool-cgroup**\ (8), **bpftool-cgroup**\ (8),
**bpftool-feature**\ (8),
**bpftool-net**\ (8), **bpftool-net**\ (8),
**bpftool-perf**\ (8) **bpftool-perf**\ (8)
...@@ -72,5 +72,6 @@ SEE ALSO ...@@ -72,5 +72,6 @@ SEE ALSO
**bpftool-prog**\ (8), **bpftool-prog**\ (8),
**bpftool-map**\ (8), **bpftool-map**\ (8),
**bpftool-cgroup**\ (8), **bpftool-cgroup**\ (8),
**bpftool-feature**\ (8),
**bpftool-net**\ (8), **bpftool-net**\ (8),
**bpftool-perf**\ (8) **bpftool-perf**\ (8)
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
/* Copyright (c) 2019 Netronome Systems, Inc. */
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/utsname.h>
#include <linux/filter.h>
#include <linux/limits.h>
#include <bpf.h>
#include "main.h"
enum probe_component {
COMPONENT_UNSPEC,
COMPONENT_KERNEL,
};
/* Printing utility functions */
static void
print_bool_feature(const char *feat_name, const char *plain_name, bool res)
{
if (json_output)
jsonw_bool_field(json_wtr, feat_name, res);
else
printf("%s is %savailable\n", plain_name, res ? "" : "NOT ");
}
static void
print_start_section(const char *json_title, const char *plain_title)
{
if (json_output) {
jsonw_name(json_wtr, json_title);
jsonw_start_object(json_wtr);
} else {
printf("%s\n", plain_title);
}
}
/* Probing functions */
static bool probe_bpf_syscall(void)
{
bool res;
bpf_load_program(BPF_PROG_TYPE_UNSPEC, NULL, 0, NULL, 0, NULL, 0);
res = (errno != ENOSYS);
print_bool_feature("have_bpf_syscall",
"bpf() syscall",
res);
return res;
}
static int do_probe(int argc, char **argv)
{
enum probe_component target = COMPONENT_UNSPEC;
/* Detection assumes user has sufficient privileges (CAP_SYS_ADMIN).
* Let's approximate, and restrict usage to root user only.
*/
if (geteuid()) {
p_err("please run this command as root user");
return -1;
}
set_max_rlimit();
while (argc) {
if (is_prefix(*argv, "kernel")) {
if (target != COMPONENT_UNSPEC) {
p_err("component to probe already specified");
return -1;
}
target = COMPONENT_KERNEL;
NEXT_ARG();
} else {
p_err("expected no more arguments, 'kernel', got: '%s'?",
*argv);
return -1;
}
}
if (json_output)
jsonw_start_object(json_wtr);
print_start_section("syscall_config",
"Scanning system call availability...");
probe_bpf_syscall();
if (json_output) {
/* End current "section" of probes */
jsonw_end_object(json_wtr);
/* End root object */
jsonw_end_object(json_wtr);
}
return 0;
}
static int do_help(int argc, char **argv)
{
if (json_output) {
jsonw_null(json_wtr);
return 0;
}
fprintf(stderr,
"Usage: %s %s probe [kernel]\n"
" %s %s help\n"
"",
bin_name, argv[-2], bin_name, argv[-2]);
return 0;
}
static const struct cmd cmds[] = {
{ "help", do_help },
{ "probe", do_probe },
{ 0 }
};
int do_feature(int argc, char **argv)
{
return cmd_select(cmds, argc, argv, do_help);
}
...@@ -56,7 +56,7 @@ static int do_help(int argc, char **argv) ...@@ -56,7 +56,7 @@ static int do_help(int argc, char **argv)
" %s batch file FILE\n" " %s batch file FILE\n"
" %s version\n" " %s version\n"
"\n" "\n"
" OBJECT := { prog | map | cgroup | perf | net }\n" " OBJECT := { prog | map | cgroup | perf | net | feature }\n"
" " HELP_SPEC_OPTIONS "\n" " " HELP_SPEC_OPTIONS "\n"
"", "",
bin_name, bin_name, bin_name); bin_name, bin_name, bin_name);
...@@ -187,6 +187,7 @@ static const struct cmd cmds[] = { ...@@ -187,6 +187,7 @@ static const struct cmd cmds[] = {
{ "cgroup", do_cgroup }, { "cgroup", do_cgroup },
{ "perf", do_perf }, { "perf", do_perf },
{ "net", do_net }, { "net", do_net },
{ "feature", do_feature },
{ "version", do_version }, { "version", do_version },
{ 0 } { 0 }
}; };
......
...@@ -145,6 +145,7 @@ int do_cgroup(int argc, char **arg); ...@@ -145,6 +145,7 @@ int do_cgroup(int argc, char **arg);
int do_perf(int argc, char **arg); int do_perf(int argc, char **arg);
int do_net(int argc, char **arg); int do_net(int argc, char **arg);
int do_tracelog(int argc, char **arg); int do_tracelog(int argc, char **arg);
int do_feature(int argc, char **argv);
int parse_u32_arg(int *argc, char ***argv, __u32 *val, const char *what); int parse_u32_arg(int *argc, char ***argv, __u32 *val, const char *what);
int prog_parse_fd(int *argc, char ***argv); int prog_parse_fd(int *argc, char ***argv);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment