tools: bpftool: add basic probe capability, probe syscall availability
authorQuentin Monnet <quentin.monnet@netronome.com>
Thu, 17 Jan 2019 15:27:50 +0000 (15:27 +0000)
committerAlexei Starovoitov <ast@kernel.org>
Wed, 23 Jan 2019 06:15:40 +0000 (22:15 -0800)
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: Quentin Monnet <quentin.monnet@netronome.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Stanislav Fomichev <sdf@google.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
tools/bpf/bpftool/Documentation/bpftool-feature.rst [new file with mode: 0644]
tools/bpf/bpftool/Documentation/bpftool-map.rst
tools/bpf/bpftool/Documentation/bpftool-net.rst
tools/bpf/bpftool/Documentation/bpftool-perf.rst
tools/bpf/bpftool/Documentation/bpftool-prog.rst
tools/bpf/bpftool/Documentation/bpftool.rst
tools/bpf/bpftool/feature.c [new file with mode: 0644]
tools/bpf/bpftool/main.c
tools/bpf/bpftool/main.h

index d07ccf8a23f7170be674d12a08957d673a560f77..d43fce568ef7cf6fd6bb1d74abbd4e4347de0255 100644 (file)
@@ -142,5 +142,6 @@ SEE ALSO
        **bpftool**\ (8),
        **bpftool-prog**\ (8),
        **bpftool-map**\ (8),
+       **bpftool-feature**\ (8),
        **bpftool-net**\ (8),
        **bpftool-perf**\ (8)
diff --git a/tools/bpf/bpftool/Documentation/bpftool-feature.rst b/tools/bpf/bpftool/Documentation/bpftool-feature.rst
new file mode 100644 (file)
index 0000000..40ac13c
--- /dev/null
@@ -0,0 +1,60 @@
+===============
+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)
index 0584c31d3fe2582b5165ab477c1f15e0136edbac..5c984ffc9f01e8bcece0499dde198eb51c321197 100644 (file)
@@ -256,5 +256,6 @@ SEE ALSO
        **bpftool**\ (8),
        **bpftool-prog**\ (8),
        **bpftool-cgroup**\ (8),
+       **bpftool-feature**\ (8),
        **bpftool-net**\ (8),
        **bpftool-perf**\ (8)
index ed87c9b619adc889310e7795bcfcc4b790251827..779dab3650eeb20047d4a9114d2c8da8bf796dca 100644 (file)
@@ -142,4 +142,5 @@ SEE ALSO
        **bpftool-prog**\ (8),
        **bpftool-map**\ (8),
        **bpftool-cgroup**\ (8),
+       **bpftool-feature**\ (8),
        **bpftool-perf**\ (8)
index f4c5e5538bb8e516624b0f28f749bf613c5a477e..bca5590a80d057dfb7b1c1c1b5d581536f88de27 100644 (file)
@@ -84,4 +84,5 @@ SEE ALSO
        **bpftool-prog**\ (8),
        **bpftool-map**\ (8),
        **bpftool-cgroup**\ (8),
+       **bpftool-feature**\ (8),
        **bpftool-net**\ (8)
index 58c8369b77dd556f59c10f8f3266b97cbb671c57..13b56102f5288cdef6f75879bd0a2ac9946a6fd3 100644 (file)
@@ -258,5 +258,6 @@ SEE ALSO
        **bpftool**\ (8),
        **bpftool-map**\ (8),
        **bpftool-cgroup**\ (8),
+       **bpftool-feature**\ (8),
        **bpftool-net**\ (8),
        **bpftool-perf**\ (8)
index e1677e81ed594a81d9bf8330e46b1d860038f663..27153bb816ac40b58c512ec593e5193adef148e0 100644 (file)
@@ -72,5 +72,6 @@ SEE ALSO
        **bpftool-prog**\ (8),
        **bpftool-map**\ (8),
        **bpftool-cgroup**\ (8),
+       **bpftool-feature**\ (8),
        **bpftool-net**\ (8),
        **bpftool-perf**\ (8)
diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c
new file mode 100644 (file)
index 0000000..954fb12
--- /dev/null
@@ -0,0 +1,131 @@
+// 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);
+}
index f44a1c2c4ea06f5ff4793e93bdcff344092c8871..a9d5e9e6a7327d9a8af33825e8daa93f4c06fc4e 100644 (file)
@@ -56,7 +56,7 @@ static int do_help(int argc, char **argv)
                "       %s batch file FILE\n"
                "       %s version\n"
                "\n"
-               "       OBJECT := { prog | map | cgroup | perf | net }\n"
+               "       OBJECT := { prog | map | cgroup | perf | net | feature }\n"
                "       " HELP_SPEC_OPTIONS "\n"
                "",
                bin_name, bin_name, bin_name);
@@ -187,6 +187,7 @@ static const struct cmd cmds[] = {
        { "cgroup",     do_cgroup },
        { "perf",       do_perf },
        { "net",        do_net },
+       { "feature",    do_feature },
        { "version",    do_version },
        { 0 }
 };
index 052c91d4dc5585b46f420da26498e6808695401f..5cfc6601de9b51004bc3bdd2788c248a1fbb82f9 100644 (file)
@@ -145,6 +145,7 @@ int do_cgroup(int argc, char **arg);
 int do_perf(int argc, char **arg);
 int do_net(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 prog_parse_fd(int *argc, char ***argv);