All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH bpf-next v4 0/9] tools: bpftool: add probes for system and device
@ 2019-01-16 14:21 Quentin Monnet
  2019-01-16 14:21 ` [PATCH bpf-next v4 1/9] tools: bpftool: add basic probe capability, probe syscall availability Quentin Monnet
                   ` (10 more replies)
  0 siblings, 11 replies; 25+ messages in thread
From: Quentin Monnet @ 2019-01-16 14:21 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann
  Cc: netdev, oss-drivers, Quentin Monnet, Arnaldo Carvalho de Melo,
	Jesper Dangaard Brouer, Stanislav Fomichev

Hi,
This set adds a new command to bpftool in order to dump a list of
eBPF-related parameters for the system (or for a specific network
device) to the console. Once again, this is based on a suggestion from
Daniel.

At this time, output includes:

    - Availability of bpf() system call
    - Availability of bpf() system call for unprivileged users
    - JIT status (enabled or not, with or without debugging traces)
    - JIT hardening status
    - JIT kallsyms exports status
    - Global memory limit for JIT compiler for unprivileged users
    - Status of kernel compilation options related to BPF features
    - Availability of known eBPF program types
    - Availability of known eBPF map types
    - Availability of known eBPF helper functions

There are three different ways to dump this information at this time:

    - Plain output dumps probe results in plain text. It is the most
      flexible options for providing descriptive output to the user, but
      should not be relied upon for parsing the output.
    - JSON output is supported.
    - A third mode, available through the "macros" keyword appended to the
      command line, dumps some of those parameters (not all) as a series of
      "#define" directives, that can be included into a C header file for
      example.

Probes for supported program and map types, and supported helpers, are
directly added to libbpf, so that other applications (or selftests) can
reuse them as necessary.

If the user does not have root privileges (or more precisely, the
CAP_SYS_ADMIN capability) detection will be erroneous for most
parameters. Therefore, forbid non-root users to run the command.

v4:
- Probe bpf_jit_limit parameter (patch 2).
- Probe some additional kernel config options (patch 3).
- Minor fixes on patch 6.

v3:
- Do not probe kernel version in bpftool (just retrieve it to probe support
  for kprobes in libbpf).
- Change the way results for helper support is displayed: now one list of
  compatible helpers for each program type (and C-style output gets a
  HAVE_PROG_TYPE_HELPER(prog_type, helper) macro to help with tests. See
  patches 6, 7.
- Address other comments from feedback from v2 (please refer to individual
  patches' history).

v2 (please also refer to individual patches' history):
- Move probes for prog/map types, helpers, from bpftool to libbpf.
- Move C-style output as a separate patch, and restrict it to a subset of
  collected information (bpf() availability, prog/map types, helpers).
- Now probe helpers with all supported program types, and display a list of
  compatible program types (as supported on the system) for each helper.
- NOT addressed: grouping compilation options for kernel into subsections
  (patch 3) (I don't see an easy way of grouping them at the moment, please
  see also the discussion on v1 thread).

Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Jesper Dangaard Brouer <brouer@redhat.com>
Cc: Stanislav Fomichev <sdf@google.com>

Quentin Monnet (9):
  tools: bpftool: add basic probe capability, probe syscall availability
  tools: bpftool: add probes for /proc/ eBPF parameters
  tools: bpftool: add probes for kernel configuration options
  tools: bpftool: add probes for eBPF program types
  tools: bpftool: add probes for eBPF map types
  tools: bpftool: add probes for eBPF helper functions
  tools: bpftool: add C-style "#define" output for probes
  tools: bpftool: add probes for a network device
  tools: bpftool: add bash completion for bpftool probes

 .../bpftool/Documentation/bpftool-cgroup.rst  |   1 +
 .../bpftool/Documentation/bpftool-feature.rst |  85 ++
 .../bpf/bpftool/Documentation/bpftool-map.rst |   1 +
 .../bpf/bpftool/Documentation/bpftool-net.rst |   1 +
 .../bpftool/Documentation/bpftool-perf.rst    |   1 +
 .../bpftool/Documentation/bpftool-prog.rst    |   1 +
 tools/bpf/bpftool/Documentation/bpftool.rst   |   1 +
 tools/bpf/bpftool/bash-completion/bpftool     |  19 +
 tools/bpf/bpftool/feature.c                   | 764 ++++++++++++++++++
 tools/bpf/bpftool/main.c                      |   3 +-
 tools/bpf/bpftool/main.h                      |   4 +
 tools/bpf/bpftool/map.c                       |   4 +-
 tools/lib/bpf/Build                           |   2 +-
 tools/lib/bpf/libbpf.h                        |  14 +
 tools/lib/bpf/libbpf.map                      |   3 +
 tools/lib/bpf/libbpf_probes.c                 | 242 ++++++
 16 files changed, 1143 insertions(+), 3 deletions(-)
 create mode 100644 tools/bpf/bpftool/Documentation/bpftool-feature.rst
 create mode 100644 tools/bpf/bpftool/feature.c
 create mode 100644 tools/lib/bpf/libbpf_probes.c

-- 
2.17.1


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH bpf-next v4 1/9] tools: bpftool: add basic probe capability, probe syscall availability
  2019-01-16 14:21 [PATCH bpf-next v4 0/9] tools: bpftool: add probes for system and device Quentin Monnet
@ 2019-01-16 14:21 ` Quentin Monnet
  2019-01-17  0:28   ` Jakub Kicinski
  2019-01-16 14:21 ` [PATCH bpf-next v4 2/9] tools: bpftool: add probes for /proc/ eBPF parameters Quentin Monnet
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 25+ messages in thread
From: Quentin Monnet @ 2019-01-16 14:21 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann
  Cc: netdev, oss-drivers, Quentin Monnet, Arnaldo Carvalho de Melo,
	Jesper Dangaard Brouer, Stanislav Fomichev

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>
---
 .../bpftool/Documentation/bpftool-cgroup.rst  |   1 +
 .../bpftool/Documentation/bpftool-feature.rst |  60 ++++++++
 .../bpf/bpftool/Documentation/bpftool-map.rst |   1 +
 .../bpf/bpftool/Documentation/bpftool-net.rst |   1 +
 .../bpftool/Documentation/bpftool-perf.rst    |   1 +
 .../bpftool/Documentation/bpftool-prog.rst    |   1 +
 tools/bpf/bpftool/Documentation/bpftool.rst   |   1 +
 tools/bpf/bpftool/feature.c                   | 131 ++++++++++++++++++
 tools/bpf/bpftool/main.c                      |   3 +-
 tools/bpf/bpftool/main.h                      |   1 +
 10 files changed, 200 insertions(+), 1 deletion(-)
 create mode 100644 tools/bpf/bpftool/Documentation/bpftool-feature.rst
 create mode 100644 tools/bpf/bpftool/feature.c

diff --git a/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst b/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
index d07ccf8a23f7..d43fce568ef7 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
@@ -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
index 000000000000..40ac13c0b782
--- /dev/null
+++ b/tools/bpf/bpftool/Documentation/bpftool-feature.rst
@@ -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)
diff --git a/tools/bpf/bpftool/Documentation/bpftool-map.rst b/tools/bpf/bpftool/Documentation/bpftool-map.rst
index 64b001b4f777..eafdc9f76694 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-map.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-map.rst
@@ -236,5 +236,6 @@ SEE ALSO
 	**bpftool**\ (8),
 	**bpftool-prog**\ (8),
 	**bpftool-cgroup**\ (8),
+	**bpftool-feature**\ (8),
 	**bpftool-net**\ (8),
 	**bpftool-perf**\ (8)
diff --git a/tools/bpf/bpftool/Documentation/bpftool-net.rst b/tools/bpf/bpftool/Documentation/bpftool-net.rst
index ed87c9b619ad..779dab3650ee 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-net.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-net.rst
@@ -142,4 +142,5 @@ SEE ALSO
 	**bpftool-prog**\ (8),
 	**bpftool-map**\ (8),
 	**bpftool-cgroup**\ (8),
+	**bpftool-feature**\ (8),
 	**bpftool-perf**\ (8)
diff --git a/tools/bpf/bpftool/Documentation/bpftool-perf.rst b/tools/bpf/bpftool/Documentation/bpftool-perf.rst
index f4c5e5538bb8..bca5590a80d0 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-perf.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-perf.rst
@@ -84,4 +84,5 @@ SEE ALSO
 	**bpftool-prog**\ (8),
 	**bpftool-map**\ (8),
 	**bpftool-cgroup**\ (8),
+	**bpftool-feature**\ (8),
 	**bpftool-net**\ (8)
diff --git a/tools/bpf/bpftool/Documentation/bpftool-prog.rst b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
index 58c8369b77dd..13b56102f528 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-prog.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
@@ -258,5 +258,6 @@ SEE ALSO
 	**bpftool**\ (8),
 	**bpftool-map**\ (8),
 	**bpftool-cgroup**\ (8),
+	**bpftool-feature**\ (8),
 	**bpftool-net**\ (8),
 	**bpftool-perf**\ (8)
diff --git a/tools/bpf/bpftool/Documentation/bpftool.rst b/tools/bpf/bpftool/Documentation/bpftool.rst
index e1677e81ed59..27153bb816ac 100644
--- a/tools/bpf/bpftool/Documentation/bpftool.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool.rst
@@ -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
index 000000000000..954fb12a5228
--- /dev/null
+++ b/tools/bpf/bpftool/feature.c
@@ -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);
+}
diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c
index f44a1c2c4ea0..a9d5e9e6a732 100644
--- a/tools/bpf/bpftool/main.c
+++ b/tools/bpf/bpftool/main.c
@@ -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 }
 };
diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
index 052c91d4dc55..5cfc6601de9b 100644
--- a/tools/bpf/bpftool/main.h
+++ b/tools/bpf/bpftool/main.h
@@ -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);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH bpf-next v4 2/9] tools: bpftool: add probes for /proc/ eBPF parameters
  2019-01-16 14:21 [PATCH bpf-next v4 0/9] tools: bpftool: add probes for system and device Quentin Monnet
  2019-01-16 14:21 ` [PATCH bpf-next v4 1/9] tools: bpftool: add basic probe capability, probe syscall availability Quentin Monnet
@ 2019-01-16 14:21 ` Quentin Monnet
  2019-01-16 14:21 ` [PATCH bpf-next v4 3/9] tools: bpftool: add probes for kernel configuration options Quentin Monnet
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 25+ messages in thread
From: Quentin Monnet @ 2019-01-16 14:21 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann
  Cc: netdev, oss-drivers, Quentin Monnet, Arnaldo Carvalho de Melo,
	Jesper Dangaard Brouer, Stanislav Fomichev

Add a set of probes to dump the eBPF-related parameters available from
/proc/: availability of bpf() syscall for unprivileged users,
JIT compiler status and hardening status, kallsyms exports status.

Sample output:

    # bpftool feature probe kernel
    Scanning system configuration...
    bpf() syscall for unprivileged users is enabled
    JIT compiler is disabled
    JIT compiler hardening is disabled
    JIT compiler kallsyms exports are disabled
    Global memory limit for JIT compiler for unprivileged users \
            is 264241152 bytes
    ...

    # bpftool --json --pretty feature probe kernel
    {
        "system_config": {
            "unprivileged_bpf_disabled": 0,
            "bpf_jit_enable": 0,
            "bpf_jit_harden": 0,
            "bpf_jit_kallsyms": 0,
            "bpf_jit_limit": 264241152
        },
        ...
    }

These probes are skipped if procfs is not mounted.

v4:
- Add bpf_jit_limit parameter.

v2:
- Remove C-style macros output from this patch.

Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
 tools/bpf/bpftool/feature.c | 187 ++++++++++++++++++++++++++++++++++++
 1 file changed, 187 insertions(+)

diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c
index 954fb12a5228..cedc44a61c6e 100644
--- a/tools/bpf/bpftool/feature.c
+++ b/tools/bpf/bpftool/feature.c
@@ -5,6 +5,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <sys/utsname.h>
+#include <sys/vfs.h>
 
 #include <linux/filter.h>
 #include <linux/limits.h>
@@ -13,11 +14,29 @@
 
 #include "main.h"
 
+#ifndef PROC_SUPER_MAGIC
+# define PROC_SUPER_MAGIC	0x9fa0
+#endif
+
 enum probe_component {
 	COMPONENT_UNSPEC,
 	COMPONENT_KERNEL,
 };
 
+/* Miscellaneous utility functions */
+
+static bool check_procfs(void)
+{
+	struct statfs st_fs;
+
+	if (statfs("/proc", &st_fs) < 0)
+		return false;
+	if ((unsigned long)st_fs.f_type != PROC_SUPER_MAGIC)
+		return false;
+
+	return true;
+}
+
 /* Printing utility functions */
 
 static void
@@ -42,6 +61,153 @@ print_start_section(const char *json_title, const char *plain_title)
 
 /* Probing functions */
 
+static int read_procfs(const char *path)
+{
+	char *endptr, *line = NULL;
+	size_t len = 0;
+	FILE *fd;
+	int res;
+
+	fd = fopen(path, "r");
+	if (!fd)
+		return -1;
+
+	res = getline(&line, &len, fd);
+	fclose(fd);
+	if (res < 0)
+		return -1;
+
+	errno = 0;
+	res = strtol(line, &endptr, 10);
+	if (errno || *line == '\0' || *endptr != '\n')
+		res = -1;
+	free(line);
+
+	return res;
+}
+
+static void probe_unprivileged_disabled(void)
+{
+	int res;
+
+	res = read_procfs("/proc/sys/kernel/unprivileged_bpf_disabled");
+	if (json_output) {
+		jsonw_int_field(json_wtr, "unprivileged_bpf_disabled", res);
+	} else {
+		switch (res) {
+		case 0:
+			printf("bpf() syscall for unprivileged users is enabled\n");
+			break;
+		case 1:
+			printf("bpf() syscall restricted to privileged users\n");
+			break;
+		case -1:
+			printf("Unable to retrieve required privileges for bpf() syscall\n");
+			break;
+		default:
+			printf("bpf() syscall restriction has unknown value %d\n", res);
+		}
+	}
+}
+
+static void probe_jit_enable(void)
+{
+	int res;
+
+	res = read_procfs("/proc/sys/net/core/bpf_jit_enable");
+	if (json_output) {
+		jsonw_int_field(json_wtr, "bpf_jit_enable", res);
+	} else {
+		switch (res) {
+		case 0:
+			printf("JIT compiler is disabled\n");
+			break;
+		case 1:
+			printf("JIT compiler is enabled\n");
+			break;
+		case 2:
+			printf("JIT compiler is enabled with debugging traces in kernel logs\n");
+			break;
+		case -1:
+			printf("Unable to retrieve JIT-compiler status\n");
+			break;
+		default:
+			printf("JIT-compiler status has unknown value %d\n",
+			       res);
+		}
+	}
+}
+
+static void probe_jit_harden(void)
+{
+	int res;
+
+	res = read_procfs("/proc/sys/net/core/bpf_jit_harden");
+	if (json_output) {
+		jsonw_int_field(json_wtr, "bpf_jit_harden", res);
+	} else {
+		switch (res) {
+		case 0:
+			printf("JIT compiler hardening is disabled\n");
+			break;
+		case 1:
+			printf("JIT compiler hardening is enabled for unprivileged users\n");
+			break;
+		case 2:
+			printf("JIT compiler hardening is enabled for all users\n");
+			break;
+		case -1:
+			printf("Unable to retrieve JIT hardening status\n");
+			break;
+		default:
+			printf("JIT hardening status has unknown value %d\n",
+			       res);
+		}
+	}
+}
+
+static void probe_jit_kallsyms(void)
+{
+	int res;
+
+	res = read_procfs("/proc/sys/net/core/bpf_jit_kallsyms");
+	if (json_output) {
+		jsonw_int_field(json_wtr, "bpf_jit_kallsyms", res);
+	} else {
+		switch (res) {
+		case 0:
+			printf("JIT compiler kallsyms exports are disabled\n");
+			break;
+		case 1:
+			printf("JIT compiler kallsyms exports are enabled for root\n");
+			break;
+		case -1:
+			printf("Unable to retrieve JIT kallsyms export status\n");
+			break;
+		default:
+			printf("JIT kallsyms exports status has unknown value %d\n", res);
+		}
+	}
+}
+
+static void probe_jit_limit(void)
+{
+	int res;
+
+	res = read_procfs("/proc/sys/net/core/bpf_jit_limit");
+	if (json_output) {
+		jsonw_int_field(json_wtr, "bpf_jit_limit", res);
+	} else {
+		switch (res) {
+		case -1:
+			printf("Unable to retrieve global memory limit for JIT compiler for unprivileged users\n");
+			break;
+		default:
+			printf("Global memory limit for JIT compiler for unprivileged users is %d bytes\n", res);
+		}
+	}
+}
+
 static bool probe_bpf_syscall(void)
 {
 	bool res;
@@ -88,6 +254,27 @@ static int do_probe(int argc, char **argv)
 	if (json_output)
 		jsonw_start_object(json_wtr);
 
+	switch (target) {
+	case COMPONENT_KERNEL:
+	case COMPONENT_UNSPEC:
+		print_start_section("system_config",
+				    "Scanning system configuration...");
+		if (check_procfs()) {
+			probe_unprivileged_disabled();
+			probe_jit_enable();
+			probe_jit_harden();
+			probe_jit_kallsyms();
+			probe_jit_limit();
+		} else {
+			p_info("/* procfs not mounted, skipping related probes */");
+		}
+		if (json_output)
+			jsonw_end_object(json_wtr);
+		else
+			printf("\n");
+		break;
+	}
+
 	print_start_section("syscall_config",
 			    "Scanning system call availability...");
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH bpf-next v4 3/9] tools: bpftool: add probes for kernel configuration options
  2019-01-16 14:21 [PATCH bpf-next v4 0/9] tools: bpftool: add probes for system and device Quentin Monnet
  2019-01-16 14:21 ` [PATCH bpf-next v4 1/9] tools: bpftool: add basic probe capability, probe syscall availability Quentin Monnet
  2019-01-16 14:21 ` [PATCH bpf-next v4 2/9] tools: bpftool: add probes for /proc/ eBPF parameters Quentin Monnet
@ 2019-01-16 14:21 ` Quentin Monnet
  2019-01-17  0:34   ` Jakub Kicinski
  2019-01-16 14:21 ` [PATCH bpf-next v4 4/9] tools: bpftool: add probes for eBPF program types Quentin Monnet
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 25+ messages in thread
From: Quentin Monnet @ 2019-01-16 14:21 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann
  Cc: netdev, oss-drivers, Quentin Monnet, Arnaldo Carvalho de Melo,
	Jesper Dangaard Brouer, Stanislav Fomichev

Add probes to dump a number of options set (or not set) for compiling
the kernel image. These parameters provide information about what BPF
components should be available on the system. A number of them are not
directly related to eBPF, but are in fact used in the kernel as
conditions on which to compile, or not to compile, some of the eBPF
helper functions.

Sample output:

    # bpftool feature probe kernel
    Scanning system configuration...
    ...
    CONFIG_BPF is set to y
    CONFIG_BPF_SYSCALL is set to y
    CONFIG_HAVE_EBPF_JIT is set to y
    ...

    # bpftool --pretty --json feature probe kernel
    {
        "system_config": {
            ...
            "CONFIG_BPF": "y",
            "CONFIG_BPF_SYSCALL": "y",
            "CONFIG_HAVE_EBPF_JIT": "y",
            ...
        }
    }

v4:
- Add some options to the list:
    - CONFIG_TRACING
    - CONFIG_KPROBE_EVENTS
    - CONFIG_UPROBE_EVENTS
    - CONFIG_FTRACE_SYSCALLS
- Add comments about those options in the source code.

v3:
- Add a comment about /proc/config.gz not being supported as a path for
  the config file at this time.
- Use p_info() instead of p_err() on failure to get options from config
  file, as bpftool keeps probing other parameters and that would
  possibly create duplicate "error" entries for JSON.

v2:
- Remove C-style macros output from this patch.
- NOT addressed: grouping of those config options into subsections
  (I don't see an easy way of grouping them at the moment, please see
  also the discussion on v1 thread).

Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
---
 tools/bpf/bpftool/feature.c | 182 ++++++++++++++++++++++++++++++++++++
 1 file changed, 182 insertions(+)

diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c
index cedc44a61c6e..f502da9fc628 100644
--- a/tools/bpf/bpftool/feature.c
+++ b/tools/bpf/bpftool/feature.c
@@ -48,6 +48,30 @@ print_bool_feature(const char *feat_name, const char *plain_name, bool res)
 		printf("%s is %savailable\n", plain_name, res ? "" : "NOT ");
 }
 
+static void print_kernel_option(const char *name, const char *value)
+{
+	char *endptr;
+	int res;
+
+	if (json_output) {
+		if (!value) {
+			jsonw_null_field(json_wtr, name);
+			return;
+		}
+		errno = 0;
+		res = strtol(value, &endptr, 0);
+		if (!errno && *endptr == '\n')
+			jsonw_int_field(json_wtr, name, res);
+		else
+			jsonw_string_field(json_wtr, name, value);
+	} else {
+		if (value)
+			printf("%s is set to %s\n", name, value);
+		else
+			printf("%s is not set\n", name);
+	}
+}
+
 static void
 print_start_section(const char *json_title, const char *plain_title)
 {
@@ -208,6 +232,163 @@ static void probe_jit_limit(void)
 	}
 }
 
+static char *get_kernel_config_option(FILE *fd, const char *option)
+{
+	size_t line_n = 0, optlen = strlen(option);
+	char *res, *strval, *line = NULL;
+	ssize_t n;
+
+	rewind(fd);
+	while ((n = getline(&line, &line_n, fd)) > 0) {
+		if (strncmp(line, option, optlen))
+			continue;
+		/* Check we have at least '=', value, and '\n' */
+		if (strlen(line) < optlen + 3)
+			continue;
+		if (*(line + optlen) != '=')
+			continue;
+
+		/* Trim ending '\n' */
+		line[strlen(line) - 1] = '\0';
+
+		/* Copy and return config option value */
+		strval = line + optlen + 1;
+		res = strdup(strval);
+		free(line);
+		return res;
+	}
+	free(line);
+
+	return NULL;
+}
+
+static void probe_kernel_image_config(void)
+{
+	const char * const options[] = {
+		/* Enable BPF */
+		"CONFIG_BPF",
+		/* Enable bpf() syscall */
+		"CONFIG_BPF_SYSCALL",
+		/* Does selected architecture support eBPF JIT compiler */
+		"CONFIG_HAVE_EBPF_JIT",
+		/* Compile eBPF JIT compiler */
+		"CONFIG_BPF_JIT",
+		/* Avoid compiling eBPF interpreter (use JIT only) */
+		"CONFIG_BPF_JIT_ALWAYS_ON",
+
+		/* cgroups */
+		"CONFIG_CGROUPS",
+		/* BPF programs attached to cgroups */
+		"CONFIG_CGROUP_BPF",
+		/* bpf_get_cgroup_classid() helper */
+		"CONFIG_CGROUP_NET_CLASSID",
+		/* bpf_skb_{,ancestor_}cgroup_id() helpers */
+		"CONFIG_SOCK_CGROUP_DATA",
+
+		/* Tracing: attach BPF to kprobes, tracepoints, etc. */
+		"CONFIG_BPF_EVENTS",
+		/* Kprobes */
+		"CONFIG_KPROBE_EVENTS",
+		/* Uprobes */
+		"CONFIG_UPROBE_EVENTS",
+		/* Tracepoints */
+		"CONFIG_TRACING",
+		/* Syscall tracepoints */
+		"CONFIG_FTRACE_SYSCALLS",
+		/* bpf_override_return() helper support for selected arch */
+		"CONFIG_FUNCTION_ERROR_INJECTION",
+		/* bpf_override_return() helper */
+		"CONFIG_BPF_KPROBE_OVERRIDE",
+
+		/* Network */
+		"CONFIG_NET",
+		/* AF_XDP sockets */
+		"CONFIG_XDP_SOCKETS",
+		/* BPF_PROG_TYPE_LWT_* and related helpers */
+		"CONFIG_LWTUNNEL_BPF",
+		/* BPF_PROG_TYPE_SCHED_ACT, TC (traffic control) actions */
+		"CONFIG_NET_ACT_BPF",
+		/* BPF_PROG_TYPE_SCHED_CLS, TC filters */
+		"CONFIG_NET_CLS_BPF",
+		/* TC clsact qdisc */
+		"CONFIG_NET_CLS_ACT",
+		/* Ingress filtering with TC */
+		"CONFIG_NET_SCH_INGRESS",
+		/* bpf_skb_get_xfrm_state() helper */
+		"CONFIG_XFRM",
+		/* bpf_get_route_realm() helper */
+		"CONFIG_IP_ROUTE_CLASSID",
+		/* BPF_PROG_TYPE_LWT_SEG6_LOCAL and related helpers */
+		"CONFIG_IPV6_SEG6_BPF",
+		/* BPF_PROG_TYPE_LIRC_MODE2 and related helpers */
+		"CONFIG_BPF_LIRC_MODE2",
+		/* BPF stream parser and BPF socket maps */
+		"CONFIG_BPF_STREAM_PARSER",
+		/* xt_bpf module for passing BPF programs to netfilter  */
+		"CONFIG_NETFILTER_XT_MATCH_BPF",
+		/* bpfilter back-end for iptables */
+		"CONFIG_BPFILTER",
+		/* bpftilter module with "user mode helper" */
+		"CONFIG_BPFILTER_UMH",
+
+		/* test_bpf module for BPF tests */
+		"CONFIG_TEST_BPF",
+	};
+	char *value, *buf = NULL;
+	struct utsname utsn;
+	char path[PATH_MAX];
+	size_t i, n;
+	ssize_t ret;
+	FILE *fd;
+
+	if (uname(&utsn))
+		goto no_config;
+
+	snprintf(path, sizeof(path), "/boot/config-%s", utsn.release);
+
+	fd = fopen(path, "r");
+	if (!fd && errno == ENOENT) {
+		/* Some distributions put the config file at /proc/config, give
+		 * it a try.
+		 * Sometimes it is also at /proc/config.gz but we do not try
+		 * this one for now, it would require linking against libz.
+		 */
+		fd = fopen("/proc/config", "r");
+	}
+	if (!fd) {
+		p_info("skipping kernel config, can't open file: %s",
+		       strerror(errno));
+		goto no_config;
+	}
+	/* Sanity checks */
+	ret = getline(&buf, &n, fd);
+	ret = getline(&buf, &n, fd);
+	if (!buf || !ret) {
+		p_info("skipping kernel config, can't read from file: %s",
+		       strerror(errno));
+		free(buf);
+		goto no_config;
+	}
+	if (strcmp(buf, "# Automatically generated file; DO NOT EDIT.\n")) {
+		p_info("skipping kernel config, can't find correct file");
+		free(buf);
+		goto no_config;
+	}
+	free(buf);
+
+	for (i = 0; i < ARRAY_SIZE(options); i++) {
+		value = get_kernel_config_option(fd, options[i]);
+		print_kernel_option(options[i], value);
+		free(value);
+	}
+	fclose(fd);
+	return;
+
+no_config:
+	for (i = 0; i < ARRAY_SIZE(options); i++)
+		print_kernel_option(options[i], NULL);
+}
+
 static bool probe_bpf_syscall(void)
 {
 	bool res;
@@ -268,6 +449,7 @@ static int do_probe(int argc, char **argv)
 		} else {
 			p_info("/* procfs not mounted, skipping related probes */");
 		}
+		probe_kernel_image_config();
 		if (json_output)
 			jsonw_end_object(json_wtr);
 		else
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH bpf-next v4 4/9] tools: bpftool: add probes for eBPF program types
  2019-01-16 14:21 [PATCH bpf-next v4 0/9] tools: bpftool: add probes for system and device Quentin Monnet
                   ` (2 preceding siblings ...)
  2019-01-16 14:21 ` [PATCH bpf-next v4 3/9] tools: bpftool: add probes for kernel configuration options Quentin Monnet
@ 2019-01-16 14:21 ` Quentin Monnet
  2019-01-17  0:42   ` Jakub Kicinski
  2019-01-16 14:21 ` [PATCH bpf-next v4 5/9] tools: bpftool: add probes for eBPF map types Quentin Monnet
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 25+ messages in thread
From: Quentin Monnet @ 2019-01-16 14:21 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann
  Cc: netdev, oss-drivers, Quentin Monnet, Arnaldo Carvalho de Melo,
	Jesper Dangaard Brouer, Stanislav Fomichev

Introduce probes for supported BPF program types in libbpf, and call it
from bpftool to test what types are available on the system. The probe
simply consists in loading a very basic program of that type and see if
the verifier complains or not.

Sample output:

    # bpftool feature probe kernel
    ...
    Scanning eBPF program types...
    eBPF program_type socket_filter is available
    eBPF program_type kprobe is available
    eBPF program_type sched_cls is available
    ...

    # bpftool --json --pretty feature probe kernel
    {
        ...
        "program_types": {
            "have_socket_filter_prog_type": true,
            "have_kprobe_prog_type": true,
            "have_sched_cls_prog_type": true,
            ...
        }
    }

v3:
- Get kernel version for checking kprobes availability from libbpf
  instead of from bpftool. Do not pass kernel_version as an argument
  when calling libbpf probes.
- Use a switch with all enum values for setting specific program
  parameters just before probing, so that gcc complains at compile time
  (-Wswitch-enum) if new prog types were added to the kernel but libbpf
  was not updated.
- Add a comment in libbpf.h about setrlimit() usage to allow many
  consecutive probe attempts.

v2:
- Move probes from bpftool to libbpf.
- Remove C-style macros output from this patch.

Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
---
 tools/bpf/bpftool/feature.c   | 48 +++++++++++++++++-
 tools/lib/bpf/Build           |  2 +-
 tools/lib/bpf/libbpf.h        | 11 ++++
 tools/lib/bpf/libbpf.map      |  1 +
 tools/lib/bpf/libbpf_probes.c | 95 +++++++++++++++++++++++++++++++++++
 5 files changed, 155 insertions(+), 2 deletions(-)
 create mode 100644 tools/lib/bpf/libbpf_probes.c

diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c
index f502da9fc628..037252486033 100644
--- a/tools/bpf/bpftool/feature.c
+++ b/tools/bpf/bpftool/feature.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
 /* Copyright (c) 2019 Netronome Systems, Inc. */
 
+#include <ctype.h>
 #include <errno.h>
 #include <string.h>
 #include <unistd.h>
@@ -11,6 +12,7 @@
 #include <linux/limits.h>
 
 #include <bpf.h>
+#include <libbpf.h>
 
 #include "main.h"
 
@@ -83,6 +85,17 @@ print_start_section(const char *json_title, const char *plain_title)
 	}
 }
 
+static void
+print_end_then_start_section(const char *json_title, const char *plain_title)
+{
+	if (json_output)
+		jsonw_end_object(json_wtr);
+	else
+		printf("\n");
+
+	print_start_section(json_title, plain_title);
+}
+
 /* Probing functions */
 
 static int read_procfs(const char *path)
@@ -403,9 +416,33 @@ static bool probe_bpf_syscall(void)
 	return res;
 }
 
+static void probe_prog_type(enum bpf_prog_type prog_type, bool *supported_types)
+{
+	const char *plain_comment = "eBPF program_type ";
+	char feat_name[128], plain_desc[128];
+	size_t maxlen;
+	bool res;
+
+	res = bpf_probe_prog_type(prog_type, 0);
+
+	supported_types[prog_type] |= res;
+
+	maxlen = sizeof(plain_desc) - strlen(plain_comment) - 1;
+	if (strlen(prog_type_name[prog_type]) > maxlen) {
+		p_info("program type name too long");
+		return;
+	}
+
+	sprintf(feat_name, "have_%s_prog_type", prog_type_name[prog_type]);
+	sprintf(plain_desc, "%s%s", plain_comment, prog_type_name[prog_type]);
+	print_bool_feature(feat_name, plain_desc, res);
+}
+
 static int do_probe(int argc, char **argv)
 {
 	enum probe_component target = COMPONENT_UNSPEC;
+	bool supported_types[128] = {};
+	unsigned int i;
 
 	/* Detection assumes user has sufficient privileges (CAP_SYS_ADMIN).
 	 * Let's approximate, and restrict usage to root user only.
@@ -460,8 +497,17 @@ static int do_probe(int argc, char **argv)
 	print_start_section("syscall_config",
 			    "Scanning system call availability...");
 
-	probe_bpf_syscall();
+	if (!probe_bpf_syscall())
+		/* bpf() syscall unavailable, don't probe other BPF features */
+		goto exit_close_json;
+
+	print_end_then_start_section("program_types",
+				     "Scanning eBPF program types...");
+
+	for (i = BPF_PROG_TYPE_UNSPEC + 1; i < ARRAY_SIZE(prog_type_name); i++)
+		probe_prog_type(i, supported_types);
 
+exit_close_json:
 	if (json_output) {
 		/* End current "section" of probes */
 		jsonw_end_object(json_wtr);
diff --git a/tools/lib/bpf/Build b/tools/lib/bpf/Build
index 197b40f5b5c6..bfd9bfc82c3b 100644
--- a/tools/lib/bpf/Build
+++ b/tools/lib/bpf/Build
@@ -1 +1 @@
-libbpf-y := libbpf.o bpf.o nlattr.o btf.o libbpf_errno.o str_error.o netlink.o bpf_prog_linfo.o
+libbpf-y := libbpf.o bpf.o nlattr.o btf.o libbpf_errno.o str_error.o netlink.o bpf_prog_linfo.o libbpf_probes.o
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 5f68d7b75215..8e63821109ab 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -355,6 +355,17 @@ LIBBPF_API const struct bpf_line_info *
 bpf_prog_linfo__lfind(const struct bpf_prog_linfo *prog_linfo,
 		      __u32 insn_off, __u32 nr_skip);
 
+/*
+ * Probe for supported system features
+ *
+ * Note that running many of these probes in a short amount of time can cause
+ * the kernel to reach the maximal size of lockable memory allowed for the
+ * user, causing subsequent probes to fail. In this case, the caller may want
+ * to adjust that limit with setrlimit().
+ */
+LIBBPF_API bool bpf_probe_prog_type(enum bpf_prog_type prog_type,
+				    __u32 ifindex);
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
index cd02cd4e2cc3..6355e4c80a86 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -56,6 +56,7 @@ LIBBPF_0.0.1 {
 		bpf_object__unpin_maps;
 		bpf_object__unpin_programs;
 		bpf_perf_event_read_simple;
+		bpf_probe_prog_type;
 		bpf_prog_attach;
 		bpf_prog_detach;
 		bpf_prog_detach2;
diff --git a/tools/lib/bpf/libbpf_probes.c b/tools/lib/bpf/libbpf_probes.c
new file mode 100644
index 000000000000..f08c33fa8dc9
--- /dev/null
+++ b/tools/lib/bpf/libbpf_probes.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
+/* Copyright (c) 2019 Netronome Systems, Inc. */
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/utsname.h>
+
+#include <linux/filter.h>
+#include <linux/kernel.h>
+
+#include "bpf.h"
+#include "libbpf.h"
+
+static int get_kernel_version(void)
+{
+	int version, subversion, patchlevel;
+	struct utsname utsn;
+
+	/* Return 0 on failure, and attempt to probe with empty kversion */
+	if (uname(&utsn))
+		return 0;
+
+	if (sscanf(utsn.release, "%d.%d.%d",
+		   &version, &subversion, &patchlevel) != 3)
+		return 0;
+
+	return (version << 16) + (subversion << 8) + patchlevel;
+}
+
+static void
+prog_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns,
+	  size_t insns_cnt, char *buf, size_t buf_len, __u32 ifindex)
+{
+	struct bpf_load_program_attr xattr = {};
+	int fd;
+
+	switch (prog_type) {
+	case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
+		xattr.expected_attach_type = BPF_CGROUP_INET4_CONNECT;
+		break;
+	case BPF_PROG_TYPE_KPROBE:
+		xattr.kern_version = get_kernel_version();
+		break;
+	case BPF_PROG_TYPE_UNSPEC:
+	case BPF_PROG_TYPE_SOCKET_FILTER:
+	case BPF_PROG_TYPE_SCHED_CLS:
+	case BPF_PROG_TYPE_SCHED_ACT:
+	case BPF_PROG_TYPE_TRACEPOINT:
+	case BPF_PROG_TYPE_XDP:
+	case BPF_PROG_TYPE_PERF_EVENT:
+	case BPF_PROG_TYPE_CGROUP_SKB:
+	case BPF_PROG_TYPE_CGROUP_SOCK:
+	case BPF_PROG_TYPE_LWT_IN:
+	case BPF_PROG_TYPE_LWT_OUT:
+	case BPF_PROG_TYPE_LWT_XMIT:
+	case BPF_PROG_TYPE_SOCK_OPS:
+	case BPF_PROG_TYPE_SK_SKB:
+	case BPF_PROG_TYPE_CGROUP_DEVICE:
+	case BPF_PROG_TYPE_SK_MSG:
+	case BPF_PROG_TYPE_RAW_TRACEPOINT:
+	case BPF_PROG_TYPE_LWT_SEG6LOCAL:
+	case BPF_PROG_TYPE_LIRC_MODE2:
+	case BPF_PROG_TYPE_SK_REUSEPORT:
+	case BPF_PROG_TYPE_FLOW_DISSECTOR:
+	default:
+		break;
+	}
+
+	xattr.prog_type = prog_type;
+	xattr.insns = insns;
+	xattr.insns_cnt = insns_cnt;
+	xattr.license = "GPL";
+	xattr.prog_ifindex = ifindex;
+
+	fd = bpf_load_program_xattr(&xattr, buf, buf_len);
+	if (fd >= 0)
+		close(fd);
+}
+
+bool bpf_probe_prog_type(enum bpf_prog_type prog_type, __u32 ifindex)
+{
+	struct bpf_insn insns[2] = {
+		BPF_MOV64_IMM(BPF_REG_0, 0),
+		BPF_EXIT_INSN()
+	};
+
+	if (ifindex && prog_type == BPF_PROG_TYPE_SCHED_CLS)
+		/* nfp returns -EINVAL on exit(0) with TC offload */
+		insns[0].imm = 2;
+
+	errno = 0;
+	prog_load(prog_type, insns, ARRAY_SIZE(insns), NULL, 0, ifindex);
+
+	return errno != EINVAL && errno != EOPNOTSUPP;
+}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH bpf-next v4 5/9] tools: bpftool: add probes for eBPF map types
  2019-01-16 14:21 [PATCH bpf-next v4 0/9] tools: bpftool: add probes for system and device Quentin Monnet
                   ` (3 preceding siblings ...)
  2019-01-16 14:21 ` [PATCH bpf-next v4 4/9] tools: bpftool: add probes for eBPF program types Quentin Monnet
@ 2019-01-16 14:21 ` Quentin Monnet
  2019-01-16 14:21 ` [PATCH bpf-next v4 6/9] tools: bpftool: add probes for eBPF helper functions Quentin Monnet
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 25+ messages in thread
From: Quentin Monnet @ 2019-01-16 14:21 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann
  Cc: netdev, oss-drivers, Quentin Monnet, Arnaldo Carvalho de Melo,
	Jesper Dangaard Brouer, Stanislav Fomichev

Add new probes for eBPF map types, to detect what are the ones available
on the system. Try creating one map of each type, and see if the kernel
complains.

Sample output:

    # bpftool feature probe kernel
    ...
    Scanning eBPF map types...
    eBPF map_type hash is available
    eBPF map_type array is available
    eBPF map_type prog_array is available
    ...

    # bpftool --json --pretty feature probe kernel
    {
        ...
        "map_types": {
            "have_hash_map_type": true,
            "have_array_map_type": true,
            "have_prog_array_map_type": true,
            ...
        }
    }

v3:
- Use a switch with all enum values for setting specific map parameters,
  so that gcc complains at compile time (-Wswitch-enum) if new map types
  were added to the kernel but libbpf was not updated.

v2:
- Move probes from bpftool to libbpf.
- Remove C-style macros output from this patch.

Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
---
 tools/bpf/bpftool/feature.c   | 26 +++++++++++
 tools/bpf/bpftool/main.h      |  3 ++
 tools/bpf/bpftool/map.c       |  4 +-
 tools/lib/bpf/libbpf.h        |  1 +
 tools/lib/bpf/libbpf.map      |  1 +
 tools/lib/bpf/libbpf_probes.c | 84 +++++++++++++++++++++++++++++++++++
 6 files changed, 118 insertions(+), 1 deletion(-)

diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c
index 037252486033..3d53306bb66d 100644
--- a/tools/bpf/bpftool/feature.c
+++ b/tools/bpf/bpftool/feature.c
@@ -438,6 +438,26 @@ static void probe_prog_type(enum bpf_prog_type prog_type, bool *supported_types)
 	print_bool_feature(feat_name, plain_desc, res);
 }
 
+static void probe_map_type(enum bpf_map_type map_type)
+{
+	const char *plain_comment = "eBPF map_type ";
+	char feat_name[128], plain_desc[128];
+	size_t maxlen;
+	bool res;
+
+	res = bpf_probe_map_type(map_type, 0);
+
+	maxlen = sizeof(plain_desc) - strlen(plain_comment) - 1;
+	if (strlen(map_type_name[map_type]) > maxlen) {
+		p_info("map type name too long");
+		return;
+	}
+
+	sprintf(feat_name, "have_%s_map_type", map_type_name[map_type]);
+	sprintf(plain_desc, "%s%s", plain_comment, map_type_name[map_type]);
+	print_bool_feature(feat_name, plain_desc, res);
+}
+
 static int do_probe(int argc, char **argv)
 {
 	enum probe_component target = COMPONENT_UNSPEC;
@@ -507,6 +527,12 @@ static int do_probe(int argc, char **argv)
 	for (i = BPF_PROG_TYPE_UNSPEC + 1; i < ARRAY_SIZE(prog_type_name); i++)
 		probe_prog_type(i, supported_types);
 
+	print_end_then_start_section("map_types",
+				     "Scanning eBPF map types...");
+
+	for (i = BPF_MAP_TYPE_UNSPEC + 1; i < map_type_name_size; i++)
+		probe_map_type(i);
+
 exit_close_json:
 	if (json_output) {
 		/* End current "section" of probes */
diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
index 5cfc6601de9b..d7dd84d3c660 100644
--- a/tools/bpf/bpftool/main.h
+++ b/tools/bpf/bpftool/main.h
@@ -75,6 +75,9 @@ static const char * const prog_type_name[] = {
 	[BPF_PROG_TYPE_FLOW_DISSECTOR]		= "flow_dissector",
 };
 
+extern const char * const map_type_name[];
+extern const size_t map_type_name_size;
+
 enum bpf_obj_type {
 	BPF_OBJ_UNKNOWN,
 	BPF_OBJ_PROG,
diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c
index 2037e3dc864b..b73985589929 100644
--- a/tools/bpf/bpftool/map.c
+++ b/tools/bpf/bpftool/map.c
@@ -21,7 +21,7 @@
 #include "json_writer.h"
 #include "main.h"
 
-static const char * const map_type_name[] = {
+const char * const map_type_name[] = {
 	[BPF_MAP_TYPE_UNSPEC]			= "unspec",
 	[BPF_MAP_TYPE_HASH]			= "hash",
 	[BPF_MAP_TYPE_ARRAY]			= "array",
@@ -48,6 +48,8 @@ static const char * const map_type_name[] = {
 	[BPF_MAP_TYPE_STACK]			= "stack",
 };
 
+const size_t map_type_name_size = ARRAY_SIZE(map_type_name);
+
 static bool map_is_per_cpu(__u32 type)
 {
 	return type == BPF_MAP_TYPE_PERCPU_HASH ||
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 8e63821109ab..72385f6f9415 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -365,6 +365,7 @@ bpf_prog_linfo__lfind(const struct bpf_prog_linfo *prog_linfo,
  */
 LIBBPF_API bool bpf_probe_prog_type(enum bpf_prog_type prog_type,
 				    __u32 ifindex);
+LIBBPF_API bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex);
 
 #ifdef __cplusplus
 } /* extern "C" */
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
index 6355e4c80a86..c08f4c726e8e 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -56,6 +56,7 @@ LIBBPF_0.0.1 {
 		bpf_object__unpin_maps;
 		bpf_object__unpin_programs;
 		bpf_perf_event_read_simple;
+		bpf_probe_map_type;
 		bpf_probe_prog_type;
 		bpf_prog_attach;
 		bpf_prog_detach;
diff --git a/tools/lib/bpf/libbpf_probes.c b/tools/lib/bpf/libbpf_probes.c
index f08c33fa8dc9..e3d57632a975 100644
--- a/tools/lib/bpf/libbpf_probes.c
+++ b/tools/lib/bpf/libbpf_probes.c
@@ -93,3 +93,87 @@ bool bpf_probe_prog_type(enum bpf_prog_type prog_type, __u32 ifindex)
 
 	return errno != EINVAL && errno != EOPNOTSUPP;
 }
+
+bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex)
+{
+	int key_size, value_size, max_entries, map_flags;
+	struct bpf_create_map_attr attr = {};
+	int fd = -1, fd_inner;
+
+	key_size	= sizeof(__u32);
+	value_size	= sizeof(__u32);
+	max_entries	= 1;
+	map_flags	= 0;
+
+	switch (map_type) {
+	case BPF_MAP_TYPE_STACK_TRACE:
+		value_size	= sizeof(__u64);
+		break;
+	case BPF_MAP_TYPE_LPM_TRIE:
+		key_size	= sizeof(__u64);
+		value_size	= sizeof(__u64);
+		map_flags	= BPF_F_NO_PREALLOC;
+		break;
+	case BPF_MAP_TYPE_CGROUP_STORAGE:
+	case BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE:
+		key_size	= sizeof(struct bpf_cgroup_storage_key);
+		value_size	= sizeof(__u64);
+		max_entries	= 0;
+		break;
+	case BPF_MAP_TYPE_QUEUE:
+	case BPF_MAP_TYPE_STACK:
+		key_size	= 0;
+		break;
+	case BPF_MAP_TYPE_UNSPEC:
+	case BPF_MAP_TYPE_HASH:
+	case BPF_MAP_TYPE_ARRAY:
+	case BPF_MAP_TYPE_PROG_ARRAY:
+	case BPF_MAP_TYPE_PERF_EVENT_ARRAY:
+	case BPF_MAP_TYPE_PERCPU_HASH:
+	case BPF_MAP_TYPE_PERCPU_ARRAY:
+	case BPF_MAP_TYPE_CGROUP_ARRAY:
+	case BPF_MAP_TYPE_LRU_HASH:
+	case BPF_MAP_TYPE_LRU_PERCPU_HASH:
+	case BPF_MAP_TYPE_ARRAY_OF_MAPS:
+	case BPF_MAP_TYPE_HASH_OF_MAPS:
+	case BPF_MAP_TYPE_DEVMAP:
+	case BPF_MAP_TYPE_SOCKMAP:
+	case BPF_MAP_TYPE_CPUMAP:
+	case BPF_MAP_TYPE_XSKMAP:
+	case BPF_MAP_TYPE_SOCKHASH:
+	case BPF_MAP_TYPE_REUSEPORT_SOCKARRAY:
+	default:
+		break;
+	}
+
+	if (map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS ||
+	    map_type == BPF_MAP_TYPE_HASH_OF_MAPS) {
+		/* TODO: probe for device, once libbpf has a function to create
+		 * map-in-map for offload
+		 */
+		if (ifindex)
+			return false;
+
+		fd_inner = bpf_create_map(BPF_MAP_TYPE_HASH,
+					  sizeof(__u32), sizeof(__u32), 1, 0);
+		if (fd_inner < 0)
+			return false;
+		fd = bpf_create_map_in_map(map_type, NULL, sizeof(__u32),
+					   fd_inner, 1, 0);
+		close(fd_inner);
+	} else {
+		/* Note: No other restriction on map type probes for offload */
+		attr.map_type = map_type;
+		attr.key_size = key_size;
+		attr.value_size = value_size;
+		attr.max_entries = max_entries;
+		attr.map_flags = map_flags;
+		attr.map_ifindex = ifindex;
+
+		fd = bpf_create_map_xattr(&attr);
+	}
+	if (fd >= 0)
+		close(fd);
+
+	return fd >= 0;
+}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH bpf-next v4 6/9] tools: bpftool: add probes for eBPF helper functions
  2019-01-16 14:21 [PATCH bpf-next v4 0/9] tools: bpftool: add probes for system and device Quentin Monnet
                   ` (4 preceding siblings ...)
  2019-01-16 14:21 ` [PATCH bpf-next v4 5/9] tools: bpftool: add probes for eBPF map types Quentin Monnet
@ 2019-01-16 14:21 ` Quentin Monnet
  2019-01-16 14:21 ` [PATCH bpf-next v4 7/9] tools: bpftool: add C-style "#define" output for probes Quentin Monnet
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 25+ messages in thread
From: Quentin Monnet @ 2019-01-16 14:21 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann
  Cc: netdev, oss-drivers, Quentin Monnet, Arnaldo Carvalho de Melo,
	Jesper Dangaard Brouer, Stanislav Fomichev

Similarly to what was done for program types and map types, add a set of
probes to test the availability of the different eBPF helper functions
on the current system.

For each known program type, all known helpers are tested, in order to
establish a compatibility matrix. Output is provided as a set of lists
of available helpers, one per program type.

Sample output:

    # bpftool feature probe kernel
    ...
    Scanning eBPF helper functions...
    eBPF helpers supported for program type socket_filter:
            - bpf_map_lookup_elem
            - bpf_map_update_elem
            - bpf_map_delete_elem
    ...
    eBPF helpers supported for program type kprobe:
            - bpf_map_lookup_elem
            - bpf_map_update_elem
            - bpf_map_delete_elem
    ...

    # bpftool --json --pretty feature probe kernel
    {
        ...
        "helpers": {
            "socket_filter_available_helpers": ["bpf_map_lookup_elem", \
                    "bpf_map_update_elem","bpf_map_delete_elem", ...
            ],
            "kprobe_available_helpers": ["bpf_map_lookup_elem", \
                    "bpf_map_update_elem","bpf_map_delete_elem", ...
            ],
            ...
        }
    }

v4:
- Use "enum bpf_func_id" instead of "__u32" in bpf_probe_helper()
  declaration for the type of the argument used to pass the id of
  the helper to probe.
- Undef BPF_HELPER_MAKE_ENTRY after using it.

v3:
- Do not pass kernel version from bpftool to libbpf probes (kernel
  version for testing program with kprobes is retrieved directly from
  libbpf).
- Dump one list of available helpers per program type (instead of one
  list of compatible program types per helper).

v2:
- Move probes from bpftool to libbpf.
- Test all program types for each helper, print a list of working prog
  types for each helper.
- Fall back on include/uapi/linux/bpf.h for names and ids of helpers.
- Remove C-style macros output from this patch.

Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
---
 .../bpftool/Documentation/bpftool-feature.rst |  4 ++
 tools/bpf/bpftool/feature.c                   | 51 +++++++++++++++
 tools/lib/bpf/libbpf.h                        |  2 +
 tools/lib/bpf/libbpf.map                      |  1 +
 tools/lib/bpf/libbpf_probes.c                 | 63 +++++++++++++++++++
 5 files changed, 121 insertions(+)

diff --git a/tools/bpf/bpftool/Documentation/bpftool-feature.rst b/tools/bpf/bpftool/Documentation/bpftool-feature.rst
index 40ac13c0b782..255e3b3629a0 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-feature.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-feature.rst
@@ -30,6 +30,10 @@ DESCRIPTION
 
 		  Keyword **kernel** can be omitted.
 
+		  Note that when probed, some eBPF helpers (e.g.
+		  **bpf_trace_printk**\ () or **bpf_probe_write_user**\ ()) may
+		  print warnings to kernel logs.
+
 	**bpftool feature help**
 		  Print short help message.
 
diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c
index 3d53306bb66d..eb4d0500520d 100644
--- a/tools/bpf/bpftool/feature.c
+++ b/tools/bpf/bpftool/feature.c
@@ -25,6 +25,13 @@ enum probe_component {
 	COMPONENT_KERNEL,
 };
 
+#define BPF_HELPER_MAKE_ENTRY(name)	[BPF_FUNC_ ## name] = "bpf_" # name
+static const char * const helper_name[] = {
+	__BPF_FUNC_MAPPER(BPF_HELPER_MAKE_ENTRY)
+};
+
+#undef BPF_HELPER_MAKE_ENTRY
+
 /* Miscellaneous utility functions */
 
 static bool check_procfs(void)
@@ -458,6 +465,44 @@ static void probe_map_type(enum bpf_map_type map_type)
 	print_bool_feature(feat_name, plain_desc, res);
 }
 
+static void
+probe_helpers_for_progtype(enum bpf_prog_type prog_type, bool supported_type)
+{
+	const char *ptype_name = prog_type_name[prog_type];
+	char feat_name[128];
+	unsigned int id;
+	bool res;
+
+	if (json_output) {
+		sprintf(feat_name, "%s_available_helpers", ptype_name);
+		jsonw_name(json_wtr, feat_name);
+		jsonw_start_array(json_wtr);
+	} else {
+		printf("eBPF helpers supported for program type %s:",
+		       ptype_name);
+	}
+
+	for (id = 1; id < ARRAY_SIZE(helper_name); id++) {
+		if (!supported_type)
+			res = false;
+		else
+			res = bpf_probe_helper(id, prog_type, 0);
+
+		if (json_output) {
+			if (res)
+				jsonw_string(json_wtr, helper_name[id]);
+		} else {
+			if (res)
+				printf("\n\t- %s", helper_name[id]);
+		}
+	}
+
+	if (json_output)
+		jsonw_end_array(json_wtr);
+	else
+		printf("\n");
+}
+
 static int do_probe(int argc, char **argv)
 {
 	enum probe_component target = COMPONENT_UNSPEC;
@@ -533,6 +578,12 @@ static int do_probe(int argc, char **argv)
 	for (i = BPF_MAP_TYPE_UNSPEC + 1; i < map_type_name_size; i++)
 		probe_map_type(i);
 
+	print_end_then_start_section("helpers",
+				     "Scanning eBPF helper functions...");
+
+	for (i = BPF_PROG_TYPE_UNSPEC + 1; i < ARRAY_SIZE(prog_type_name); i++)
+		probe_helpers_for_progtype(i, supported_types[i]);
+
 exit_close_json:
 	if (json_output) {
 		/* End current "section" of probes */
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 72385f6f9415..62ae6cb93da1 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -366,6 +366,8 @@ bpf_prog_linfo__lfind(const struct bpf_prog_linfo *prog_linfo,
 LIBBPF_API bool bpf_probe_prog_type(enum bpf_prog_type prog_type,
 				    __u32 ifindex);
 LIBBPF_API bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex);
+LIBBPF_API bool bpf_probe_helper(enum bpf_func_id id,
+				 enum bpf_prog_type prog_type, __u32 ifindex);
 
 #ifdef __cplusplus
 } /* extern "C" */
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
index c08f4c726e8e..67e51b2becec 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -56,6 +56,7 @@ LIBBPF_0.0.1 {
 		bpf_object__unpin_maps;
 		bpf_object__unpin_programs;
 		bpf_perf_event_read_simple;
+		bpf_probe_helper;
 		bpf_probe_map_type;
 		bpf_probe_prog_type;
 		bpf_prog_attach;
diff --git a/tools/lib/bpf/libbpf_probes.c b/tools/lib/bpf/libbpf_probes.c
index e3d57632a975..890ab9370c8d 100644
--- a/tools/lib/bpf/libbpf_probes.c
+++ b/tools/lib/bpf/libbpf_probes.c
@@ -2,7 +2,11 @@
 /* Copyright (c) 2019 Netronome Systems, Inc. */
 
 #include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
 #include <unistd.h>
+#include <net/if.h>
 #include <sys/utsname.h>
 
 #include <linux/filter.h>
@@ -11,6 +15,37 @@
 #include "bpf.h"
 #include "libbpf.h"
 
+static bool grep(const char *buffer, const char *pattern)
+{
+	return !!strstr(buffer, pattern);
+}
+
+static int get_vendor_id(int ifindex)
+{
+	char ifname[IF_NAMESIZE], path[64], buf[8];
+	ssize_t len;
+	int fd;
+
+	if (!if_indextoname(ifindex, ifname))
+		return -1;
+
+	snprintf(path, sizeof(path), "/sys/class/net/%s/device/vendor", ifname);
+
+	fd = open(path, O_RDONLY);
+	if (fd < 0)
+		return -1;
+
+	len = read(fd, buf, sizeof(buf));
+	close(fd);
+	if (len < 0)
+		return -1;
+	if (len >= (ssize_t)sizeof(buf))
+		return -1;
+	buf[len] = '\0';
+
+	return strtol(buf, NULL, 0);
+}
+
 static int get_kernel_version(void)
 {
 	int version, subversion, patchlevel;
@@ -177,3 +212,31 @@ bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex)
 
 	return fd >= 0;
 }
+
+bool bpf_probe_helper(enum bpf_func_id id, enum bpf_prog_type prog_type,
+		      __u32 ifindex)
+{
+	struct bpf_insn insns[2] = {
+		BPF_EMIT_CALL(id),
+		BPF_EXIT_INSN()
+	};
+	char buf[4096] = {};
+	bool res;
+
+	prog_load(prog_type, insns, ARRAY_SIZE(insns), buf, sizeof(buf),
+		  ifindex);
+	res = !grep(buf, "invalid func ") && !grep(buf, "unknown func ");
+
+	if (ifindex) {
+		switch (get_vendor_id(ifindex)) {
+		case 0x19ee: /* Netronome specific */
+			res = res && !grep(buf, "not supported by FW") &&
+				!grep(buf, "unsupported function id");
+			break;
+		default:
+			break;
+		}
+	}
+
+	return res;
+}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH bpf-next v4 7/9] tools: bpftool: add C-style "#define" output for probes
  2019-01-16 14:21 [PATCH bpf-next v4 0/9] tools: bpftool: add probes for system and device Quentin Monnet
                   ` (5 preceding siblings ...)
  2019-01-16 14:21 ` [PATCH bpf-next v4 6/9] tools: bpftool: add probes for eBPF helper functions Quentin Monnet
@ 2019-01-16 14:21 ` Quentin Monnet
  2019-01-16 14:21 ` [PATCH bpf-next v4 8/9] tools: bpftool: add probes for a network device Quentin Monnet
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 25+ messages in thread
From: Quentin Monnet @ 2019-01-16 14:21 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann
  Cc: netdev, oss-drivers, Quentin Monnet, Arnaldo Carvalho de Melo,
	Jesper Dangaard Brouer, Stanislav Fomichev

Make bpftool able to dump a subset of the parameters collected by
probing the system as a listing of C-style #define macros, so that
external projects can reuse the result of this probing and build
BPF-based project in accordance with the features available on the
system.

The new "macros" keyword is used to select this output. An additional
"prefix" keyword is added so that users can select a custom prefix for
macro names, in order to avoid any namespace conflict.

Sample output:

    # bpftool feature probe kernel macros prefix FOO_
    /*** System call availability ***/
    #define FOO_HAVE_BPF_SYSCALL

    /*** eBPF program types ***/
    #define FOO_HAVE_SOCKET_FILTER_PROG_TYPE
    #define FOO_HAVE_KPROBE_PROG_TYPE
    #define FOO_HAVE_SCHED_CLS_PROG_TYPE
    ...

    /*** eBPF map types ***/
    #define FOO_HAVE_HASH_MAP_TYPE
    #define FOO_HAVE_ARRAY_MAP_TYPE
    #define FOO_HAVE_PROG_ARRAY_MAP_TYPE
    ...

    /*** eBPF helper functions ***/
    /*
     * Use FOO_HAVE_PROG_TYPE_HELPER(prog_type_name, helper_name)
     * to determine if <helper_name> is available for <prog_type_name>,
     * e.g.
     *      #if FOO_HAVE_PROG_TYPE_HELPER(xdp, bpf_redirect)
     *              // do stuff with this helper
     *      #elif
     *              // use a workaround
     *      #endif
     */
    #define FOO_HAVE_PROG_TYPE_HELPER(prog_type, helper)        \
            FOO_BPF__PROG_TYPE_ ## prog_type ## __HELPER_ ## helper
    ...
    #define FOO_BPF__PROG_TYPE_socket_filter__HELPER_bpf_probe_read 0
    #define FOO_BPF__PROG_TYPE_socket_filter__HELPER_bpf_ktime_get_ns 1
    #define FOO_BPF__PROG_TYPE_socket_filter__HELPER_bpf_trace_printk 1
    ...

v3:
- Change output for helpers again: add a
  HAVE_PROG_TYPE_HELPER(type, helper) macro that can be used to tell
  if <helper> is available for program <type>.

v2:
- #define-based output added as a distinct patch.
- "HAVE_" prefix appended to macro names.
- Output limited to bpf() syscall availability, BPF prog and map types,
  helper functions. In this version kernel config options, procfs
  parameter or kernel version are intentionally left aside.
- Following the change on helper probes, format for helper probes in
  this output style has changed (now a list of compatible program
  types).

Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
---
 .../bpftool/Documentation/bpftool-feature.rst |  13 +-
 tools/bpf/bpftool/feature.c                   | 150 ++++++++++++++----
 2 files changed, 133 insertions(+), 30 deletions(-)

diff --git a/tools/bpf/bpftool/Documentation/bpftool-feature.rst b/tools/bpf/bpftool/Documentation/bpftool-feature.rst
index 255e3b3629a0..53092995f46b 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-feature.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-feature.rst
@@ -19,15 +19,24 @@ SYNOPSIS
 MAP COMMANDS
 =============
 
-|	**bpftool** **feature probe** [**kernel**]
+|	**bpftool** **feature probe** [**kernel**] [**macros** [**prefix** *PREFIX*]]
 |	**bpftool** **feature help**
 
 DESCRIPTION
 ===========
-	**bpftool feature probe** [**kernel**]
+	**bpftool feature probe** [**kernel**] [**macros** [**prefix** *PREFIX*]]
 		  Probe the running kernel and dump a number of eBPF-related
 		  parameters, such as availability of the **bpf()** system call.
 
+		  If the **macros** keyword (but not the **-j** option) is
+		  passed, a subset of the output is dumped as a list of
+		  **#define** macros that are ready to be included in a C
+		  header file, for example. If, additionally, **prefix** is
+		  used to define a *PREFIX*, the provided string will be used
+		  as a prefix to the names of the macros: this can be used to
+		  avoid conflicts on macro names when including the output of
+		  this command as a header file.
+
 		  Keyword **kernel** can be omitted.
 
 		  Note that when probed, some eBPF helpers (e.g.
diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c
index eb4d0500520d..ba3a449d1869 100644
--- a/tools/bpf/bpftool/feature.c
+++ b/tools/bpf/bpftool/feature.c
@@ -46,13 +46,25 @@ static bool check_procfs(void)
 	return true;
 }
 
+static void uppercase(char *str, size_t len)
+{
+	size_t i;
+
+	for (i = 0; i < len && str[i] != '\0'; i++)
+		str[i] = toupper(str[i]);
+}
+
 /* Printing utility functions */
 
 static void
-print_bool_feature(const char *feat_name, const char *plain_name, bool res)
+print_bool_feature(const char *feat_name, const char *plain_name,
+		   const char *define_name, bool res, const char *define_prefix)
 {
 	if (json_output)
 		jsonw_bool_field(json_wtr, feat_name, res);
+	else if (define_prefix)
+		printf("#define %s%sHAVE_%s\n", define_prefix,
+		       res ? "" : "NO_", define_name);
 	else
 		printf("%s is %savailable\n", plain_name, res ? "" : "NOT ");
 }
@@ -62,6 +74,8 @@ static void print_kernel_option(const char *name, const char *value)
 	char *endptr;
 	int res;
 
+	/* No support for C-style ouptut */
+
 	if (json_output) {
 		if (!value) {
 			jsonw_null_field(json_wtr, name);
@@ -82,25 +96,31 @@ static void print_kernel_option(const char *name, const char *value)
 }
 
 static void
-print_start_section(const char *json_title, const char *plain_title)
+print_start_section(const char *json_title, const char *plain_title,
+		    const char *define_comment, const char *define_prefix)
 {
 	if (json_output) {
 		jsonw_name(json_wtr, json_title);
 		jsonw_start_object(json_wtr);
+	} else if (define_prefix) {
+		printf("%s\n", define_comment);
 	} else {
 		printf("%s\n", plain_title);
 	}
 }
 
 static void
-print_end_then_start_section(const char *json_title, const char *plain_title)
+print_end_then_start_section(const char *json_title, const char *plain_title,
+			     const char *define_comment,
+			     const char *define_prefix)
 {
 	if (json_output)
 		jsonw_end_object(json_wtr);
 	else
 		printf("\n");
 
-	print_start_section(json_title, plain_title);
+	print_start_section(json_title, plain_title, define_comment,
+			    define_prefix);
 }
 
 /* Probing functions */
@@ -134,6 +154,8 @@ static void probe_unprivileged_disabled(void)
 {
 	int res;
 
+	/* No support for C-style ouptut */
+
 	res = read_procfs("/proc/sys/kernel/unprivileged_bpf_disabled");
 	if (json_output) {
 		jsonw_int_field(json_wtr, "unprivileged_bpf_disabled", res);
@@ -158,6 +180,8 @@ static void probe_jit_enable(void)
 {
 	int res;
 
+	/* No support for C-style ouptut */
+
 	res = read_procfs("/proc/sys/net/core/bpf_jit_enable");
 	if (json_output) {
 		jsonw_int_field(json_wtr, "bpf_jit_enable", res);
@@ -186,6 +210,8 @@ static void probe_jit_harden(void)
 {
 	int res;
 
+	/* No support for C-style ouptut */
+
 	res = read_procfs("/proc/sys/net/core/bpf_jit_harden");
 	if (json_output) {
 		jsonw_int_field(json_wtr, "bpf_jit_harden", res);
@@ -214,6 +240,8 @@ static void probe_jit_kallsyms(void)
 {
 	int res;
 
+	/* No support for C-style ouptut */
+
 	res = read_procfs("/proc/sys/net/core/bpf_jit_kallsyms");
 	if (json_output) {
 		jsonw_int_field(json_wtr, "bpf_jit_kallsyms", res);
@@ -238,6 +266,8 @@ static void probe_jit_limit(void)
 {
 	int res;
 
+	/* No support for C-style ouptut */
+
 	res = read_procfs("/proc/sys/net/core/bpf_jit_limit");
 	if (json_output) {
 		jsonw_int_field(json_wtr, "bpf_jit_limit", res);
@@ -409,7 +439,7 @@ static void probe_kernel_image_config(void)
 		print_kernel_option(options[i], NULL);
 }
 
-static bool probe_bpf_syscall(void)
+static bool probe_bpf_syscall(const char *define_prefix)
 {
 	bool res;
 
@@ -418,15 +448,18 @@ static bool probe_bpf_syscall(void)
 
 	print_bool_feature("have_bpf_syscall",
 			   "bpf() syscall",
-			   res);
+			   "BPF_SYSCALL",
+			   res, define_prefix);
 
 	return res;
 }
 
-static void probe_prog_type(enum bpf_prog_type prog_type, bool *supported_types)
+static void
+probe_prog_type(enum bpf_prog_type prog_type, bool *supported_types,
+		const char *define_prefix)
 {
+	char feat_name[128], plain_desc[128], define_name[128];
 	const char *plain_comment = "eBPF program_type ";
-	char feat_name[128], plain_desc[128];
 	size_t maxlen;
 	bool res;
 
@@ -441,14 +474,18 @@ static void probe_prog_type(enum bpf_prog_type prog_type, bool *supported_types)
 	}
 
 	sprintf(feat_name, "have_%s_prog_type", prog_type_name[prog_type]);
+	sprintf(define_name, "%s_prog_type", prog_type_name[prog_type]);
+	uppercase(define_name, sizeof(define_name));
 	sprintf(plain_desc, "%s%s", plain_comment, prog_type_name[prog_type]);
-	print_bool_feature(feat_name, plain_desc, res);
+	print_bool_feature(feat_name, plain_desc, define_name, res,
+			   define_prefix);
 }
 
-static void probe_map_type(enum bpf_map_type map_type)
+static void
+probe_map_type(enum bpf_map_type map_type, const char *define_prefix)
 {
+	char feat_name[128], plain_desc[128], define_name[128];
 	const char *plain_comment = "eBPF map_type ";
-	char feat_name[128], plain_desc[128];
 	size_t maxlen;
 	bool res;
 
@@ -461,12 +498,16 @@ static void probe_map_type(enum bpf_map_type map_type)
 	}
 
 	sprintf(feat_name, "have_%s_map_type", map_type_name[map_type]);
+	sprintf(define_name, "%s_map_type", map_type_name[map_type]);
+	uppercase(define_name, sizeof(define_name));
 	sprintf(plain_desc, "%s%s", plain_comment, map_type_name[map_type]);
-	print_bool_feature(feat_name, plain_desc, res);
+	print_bool_feature(feat_name, plain_desc, define_name, res,
+			   define_prefix);
 }
 
 static void
-probe_helpers_for_progtype(enum bpf_prog_type prog_type, bool supported_type)
+probe_helpers_for_progtype(enum bpf_prog_type prog_type, bool supported_type,
+			   const char *define_prefix)
 {
 	const char *ptype_name = prog_type_name[prog_type];
 	char feat_name[128];
@@ -477,7 +518,7 @@ probe_helpers_for_progtype(enum bpf_prog_type prog_type, bool supported_type)
 		sprintf(feat_name, "%s_available_helpers", ptype_name);
 		jsonw_name(json_wtr, feat_name);
 		jsonw_start_array(json_wtr);
-	} else {
+	} else if (!define_prefix) {
 		printf("eBPF helpers supported for program type %s:",
 		       ptype_name);
 	}
@@ -491,6 +532,10 @@ probe_helpers_for_progtype(enum bpf_prog_type prog_type, bool supported_type)
 		if (json_output) {
 			if (res)
 				jsonw_string(json_wtr, helper_name[id]);
+		} else if (define_prefix) {
+			printf("#define %sBPF__PROG_TYPE_%s__HELPER_%s %s\n",
+			       define_prefix, ptype_name, helper_name[id],
+			       res ? "1" : "0");
 		} else {
 			if (res)
 				printf("\n\t- %s", helper_name[id]);
@@ -499,13 +544,14 @@ probe_helpers_for_progtype(enum bpf_prog_type prog_type, bool supported_type)
 
 	if (json_output)
 		jsonw_end_array(json_wtr);
-	else
+	else if (!define_prefix)
 		printf("\n");
 }
 
 static int do_probe(int argc, char **argv)
 {
 	enum probe_component target = COMPONENT_UNSPEC;
+	const char *define_prefix = NULL;
 	bool supported_types[128] = {};
 	unsigned int i;
 
@@ -527,21 +573,45 @@ static int do_probe(int argc, char **argv)
 			}
 			target = COMPONENT_KERNEL;
 			NEXT_ARG();
+		} else if (is_prefix(*argv, "macros") && !define_prefix) {
+			define_prefix = "";
+			NEXT_ARG();
+		} else if (is_prefix(*argv, "prefix")) {
+			if (!define_prefix) {
+				p_err("'prefix' argument can only be use after 'macros'");
+				return -1;
+			}
+			if (strcmp(define_prefix, "")) {
+				p_err("'prefix' already defined");
+				return -1;
+			}
+			NEXT_ARG();
+
+			if (!REQ_ARGS(1))
+				return -1;
+			define_prefix = GET_ARG();
 		} else {
-			p_err("expected no more arguments, 'kernel', got: '%s'?",
+			p_err("expected no more arguments, 'kernel', 'macros' or 'prefix', got: '%s'?",
 			      *argv);
 			return -1;
 		}
 	}
 
-	if (json_output)
+	if (json_output) {
+		define_prefix = NULL;
 		jsonw_start_object(json_wtr);
+	}
 
 	switch (target) {
 	case COMPONENT_KERNEL:
 	case COMPONENT_UNSPEC:
+		if (define_prefix)
+			break;
+
 		print_start_section("system_config",
-				    "Scanning system configuration...");
+				    "Scanning system configuration...",
+				    NULL, /* define_comment never used here */
+				    NULL); /* define_prefix always NULL here */
 		if (check_procfs()) {
 			probe_unprivileged_disabled();
 			probe_jit_enable();
@@ -560,29 +630,53 @@ static int do_probe(int argc, char **argv)
 	}
 
 	print_start_section("syscall_config",
-			    "Scanning system call availability...");
+			    "Scanning system call availability...",
+			    "/*** System call availability ***/",
+			    define_prefix);
 
-	if (!probe_bpf_syscall())
+	if (!probe_bpf_syscall(define_prefix))
 		/* bpf() syscall unavailable, don't probe other BPF features */
 		goto exit_close_json;
 
 	print_end_then_start_section("program_types",
-				     "Scanning eBPF program types...");
+				     "Scanning eBPF program types...",
+				     "/*** eBPF program types ***/",
+				     define_prefix);
 
 	for (i = BPF_PROG_TYPE_UNSPEC + 1; i < ARRAY_SIZE(prog_type_name); i++)
-		probe_prog_type(i, supported_types);
+		probe_prog_type(i, supported_types, define_prefix);
 
 	print_end_then_start_section("map_types",
-				     "Scanning eBPF map types...");
+				     "Scanning eBPF map types...",
+				     "/*** eBPF map types ***/",
+				     define_prefix);
 
 	for (i = BPF_MAP_TYPE_UNSPEC + 1; i < map_type_name_size; i++)
-		probe_map_type(i);
+		probe_map_type(i, define_prefix);
 
 	print_end_then_start_section("helpers",
-				     "Scanning eBPF helper functions...");
-
+				     "Scanning eBPF helper functions...",
+				     "/*** eBPF helper functions ***/",
+				     define_prefix);
+
+	if (define_prefix)
+		printf("/*\n"
+		       " * Use %sHAVE_PROG_TYPE_HELPER(prog_type_name, helper_name)\n"
+		       " * to determine if <helper_name> is available for <prog_type_name>,\n"
+		       " * e.g.\n"
+		       " *	#if %sHAVE_PROG_TYPE_HELPER(xdp, bpf_redirect)\n"
+		       " *		// do stuff with this helper\n"
+		       " *	#elif\n"
+		       " *		// use a workaround\n"
+		       " *	#endif\n"
+		       " */\n"
+		       "#define %sHAVE_PROG_TYPE_HELPER(prog_type, helper)	\\\n"
+		       "	%sBPF__PROG_TYPE_ ## prog_type ## __HELPER_ ## helper\n",
+		       define_prefix, define_prefix, define_prefix,
+		       define_prefix);
 	for (i = BPF_PROG_TYPE_UNSPEC + 1; i < ARRAY_SIZE(prog_type_name); i++)
-		probe_helpers_for_progtype(i, supported_types[i]);
+		probe_helpers_for_progtype(i, supported_types[i],
+					   define_prefix);
 
 exit_close_json:
 	if (json_output) {
@@ -603,7 +697,7 @@ static int do_help(int argc, char **argv)
 	}
 
 	fprintf(stderr,
-		"Usage: %s %s probe [kernel]\n"
+		"Usage: %s %s probe [kernel] [macros [prefix PREFIX]]\n"
 		"       %s %s help\n"
 		"",
 		bin_name, argv[-2], bin_name, argv[-2]);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH bpf-next v4 8/9] tools: bpftool: add probes for a network device
  2019-01-16 14:21 [PATCH bpf-next v4 0/9] tools: bpftool: add probes for system and device Quentin Monnet
                   ` (6 preceding siblings ...)
  2019-01-16 14:21 ` [PATCH bpf-next v4 7/9] tools: bpftool: add C-style "#define" output for probes Quentin Monnet
@ 2019-01-16 14:21 ` Quentin Monnet
  2019-01-16 14:42   ` Jesper Dangaard Brouer
  2019-01-16 14:21 ` [PATCH bpf-next v4 9/9] tools: bpftool: add bash completion for bpftool probes Quentin Monnet
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 25+ messages in thread
From: Quentin Monnet @ 2019-01-16 14:21 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann
  Cc: netdev, oss-drivers, Quentin Monnet, Arnaldo Carvalho de Melo,
	Jesper Dangaard Brouer, Stanislav Fomichev

bpftool gained support for probing the current system in order to see
what program and map types, and what helpers are available on that
system. This patch adds the possibility to pass an interface index to
libbpf (and hence to the kernel) when trying to load the programs or to
create the maps, in order to see what items a given network device can
support.

A new keyword "dev <ifname>" can be used as an alternative to "kernel"
to indicate that the given device should be tested. If no target ("dev"
or "kernel") is specified bpftool defaults to probing the kernel.

Sample output:

    # bpftool -p feature probe dev lo
    {
        "syscall_config": {
            "have_bpf_syscall": true
        },
        "program_types": {
            "have_sched_cls_prog_type": false,
            "have_xdp_prog_type": false
        },
        ...
    }

As the target is a network device, /proc/ parameters and kernel
configuration are NOT dumped. Availability of the bpf() syscall is
still probed, so we can return early if that syscall is not usable
(since there is no point in attempting the remaining probes in this
case).

Among the program types, only the ones that can be offloaded are probed.
All map types are probed, as there is no specific rule telling which one
could or could not be supported by a device in the future. All helpers
are probed (but only for offload-able program types).

Caveat: as bpftool does not attempt to attach programs to the device at
the moment, probes do not entirely reflect what the device accepts:
typically, for Netronome's nfp, results will announce that TC cls
offload is available even if support has been deactivated (with e.g.
ethtool -K eth1 hw-tc-offload off).

v2:
- All helpers are probed, whereas previous version would only probe the
  ones compatible with an offload-able program type. This is because we
  do not keep a default compatible program type for each helper anymore.

Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
 .../bpftool/Documentation/bpftool-feature.rst | 18 ++++-
 tools/bpf/bpftool/feature.c                   | 69 ++++++++++++++++---
 2 files changed, 73 insertions(+), 14 deletions(-)

diff --git a/tools/bpf/bpftool/Documentation/bpftool-feature.rst b/tools/bpf/bpftool/Documentation/bpftool-feature.rst
index 53092995f46b..8d489a26e3c9 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-feature.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-feature.rst
@@ -19,14 +19,18 @@ SYNOPSIS
 MAP COMMANDS
 =============
 
-|	**bpftool** **feature probe** [**kernel**] [**macros** [**prefix** *PREFIX*]]
+|	**bpftool** **feature probe** [*COMPONENT*] [**macros** [**prefix** *PREFIX*]]
 |	**bpftool** **feature help**
+|
+|	*COMPONENT* := { **kernel** | **dev** *NAME* }
 
 DESCRIPTION
 ===========
 	**bpftool feature probe** [**kernel**] [**macros** [**prefix** *PREFIX*]]
 		  Probe the running kernel and dump a number of eBPF-related
-		  parameters, such as availability of the **bpf()** system call.
+		  parameters, such as availability of the **bpf()** system call,
+		  JIT status, eBPF program types availability, eBPF helper
+		  functions availability, and more.
 
 		  If the **macros** keyword (but not the **-j** option) is
 		  passed, a subset of the output is dumped as a list of
@@ -37,12 +41,20 @@ DESCRIPTION
 		  avoid conflicts on macro names when including the output of
 		  this command as a header file.
 
-		  Keyword **kernel** can be omitted.
+		  Keyword **kernel** can be omitted. If no probe target is
+		  specified, probing the kernel is the default behaviour.
 
 		  Note that when probed, some eBPF helpers (e.g.
 		  **bpf_trace_printk**\ () or **bpf_probe_write_user**\ ()) may
 		  print warnings to kernel logs.
 
+	**bpftool feature probe dev** *NAME* [**macros** [**prefix** *PREFIX*]]
+		  Probe network device for supported eBPF features and dump
+		  results to the console.
+
+		  The two keywords **macros** and **prefix** have the same
+		  role as when probing the kernel.
+
 	**bpftool feature help**
 		  Print short help message.
 
diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c
index ba3a449d1869..0c195101dd72 100644
--- a/tools/bpf/bpftool/feature.c
+++ b/tools/bpf/bpftool/feature.c
@@ -5,6 +5,7 @@
 #include <errno.h>
 #include <string.h>
 #include <unistd.h>
+#include <net/if.h>
 #include <sys/utsname.h>
 #include <sys/vfs.h>
 
@@ -23,6 +24,7 @@
 enum probe_component {
 	COMPONENT_UNSPEC,
 	COMPONENT_KERNEL,
+	COMPONENT_DEVICE,
 };
 
 #define BPF_HELPER_MAKE_ENTRY(name)	[BPF_FUNC_ ## name] = "bpf_" # name
@@ -456,14 +458,24 @@ static bool probe_bpf_syscall(const char *define_prefix)
 
 static void
 probe_prog_type(enum bpf_prog_type prog_type, bool *supported_types,
-		const char *define_prefix)
+		const char *define_prefix, __u32 ifindex)
 {
 	char feat_name[128], plain_desc[128], define_name[128];
 	const char *plain_comment = "eBPF program_type ";
 	size_t maxlen;
 	bool res;
 
-	res = bpf_probe_prog_type(prog_type, 0);
+	if (ifindex)
+		/* Only test offload-able program types */
+		switch (prog_type) {
+		case BPF_PROG_TYPE_SCHED_CLS:
+		case BPF_PROG_TYPE_XDP:
+			break;
+		default:
+			return;
+		}
+
+	res = bpf_probe_prog_type(prog_type, ifindex);
 
 	supported_types[prog_type] |= res;
 
@@ -482,14 +494,15 @@ probe_prog_type(enum bpf_prog_type prog_type, bool *supported_types,
 }
 
 static void
-probe_map_type(enum bpf_map_type map_type, const char *define_prefix)
+probe_map_type(enum bpf_map_type map_type, const char *define_prefix,
+	       __u32 ifindex)
 {
 	char feat_name[128], plain_desc[128], define_name[128];
 	const char *plain_comment = "eBPF map_type ";
 	size_t maxlen;
 	bool res;
 
-	res = bpf_probe_map_type(map_type, 0);
+	res = bpf_probe_map_type(map_type, ifindex);
 
 	maxlen = sizeof(plain_desc) - strlen(plain_comment) - 1;
 	if (strlen(map_type_name[map_type]) > maxlen) {
@@ -507,13 +520,23 @@ probe_map_type(enum bpf_map_type map_type, const char *define_prefix)
 
 static void
 probe_helpers_for_progtype(enum bpf_prog_type prog_type, bool supported_type,
-			   const char *define_prefix)
+			   const char *define_prefix, __u32 ifindex)
 {
 	const char *ptype_name = prog_type_name[prog_type];
 	char feat_name[128];
 	unsigned int id;
 	bool res;
 
+	if (ifindex)
+		/* Only test helpers for offload-able program types */
+		switch (prog_type) {
+		case BPF_PROG_TYPE_SCHED_CLS:
+		case BPF_PROG_TYPE_XDP:
+			break;
+		default:
+			return;
+		}
+
 	if (json_output) {
 		sprintf(feat_name, "%s_available_helpers", ptype_name);
 		jsonw_name(json_wtr, feat_name);
@@ -527,7 +550,7 @@ probe_helpers_for_progtype(enum bpf_prog_type prog_type, bool supported_type,
 		if (!supported_type)
 			res = false;
 		else
-			res = bpf_probe_helper(id, prog_type, 0);
+			res = bpf_probe_helper(id, prog_type, ifindex);
 
 		if (json_output) {
 			if (res)
@@ -553,7 +576,9 @@ static int do_probe(int argc, char **argv)
 	enum probe_component target = COMPONENT_UNSPEC;
 	const char *define_prefix = NULL;
 	bool supported_types[128] = {};
+	__u32 ifindex = 0;
 	unsigned int i;
+	char *ifname;
 
 	/* Detection assumes user has sufficient privileges (CAP_SYS_ADMIN).
 	 * Let's approximate, and restrict usage to root user only.
@@ -573,6 +598,24 @@ static int do_probe(int argc, char **argv)
 			}
 			target = COMPONENT_KERNEL;
 			NEXT_ARG();
+		} else if (is_prefix(*argv, "dev")) {
+			NEXT_ARG();
+
+			if (target != COMPONENT_UNSPEC || ifindex) {
+				p_err("component to probe already specified");
+				return -1;
+			}
+			if (!REQ_ARGS(1))
+				return -1;
+
+			target = COMPONENT_DEVICE;
+			ifname = GET_ARG();
+			ifindex = if_nametoindex(ifname);
+			if (!ifindex) {
+				p_err("unrecognized netdevice '%s': %s", ifname,
+				      strerror(errno));
+				return -1;
+			}
 		} else if (is_prefix(*argv, "macros") && !define_prefix) {
 			define_prefix = "";
 			NEXT_ARG();
@@ -591,7 +634,7 @@ static int do_probe(int argc, char **argv)
 				return -1;
 			define_prefix = GET_ARG();
 		} else {
-			p_err("expected no more arguments, 'kernel', 'macros' or 'prefix', got: '%s'?",
+			p_err("expected no more arguments, 'kernel', 'dev', 'macros' or 'prefix', got: '%s'?",
 			      *argv);
 			return -1;
 		}
@@ -627,6 +670,8 @@ static int do_probe(int argc, char **argv)
 		else
 			printf("\n");
 		break;
+	default:
+		break;
 	}
 
 	print_start_section("syscall_config",
@@ -644,7 +689,7 @@ static int do_probe(int argc, char **argv)
 				     define_prefix);
 
 	for (i = BPF_PROG_TYPE_UNSPEC + 1; i < ARRAY_SIZE(prog_type_name); i++)
-		probe_prog_type(i, supported_types, define_prefix);
+		probe_prog_type(i, supported_types, define_prefix, ifindex);
 
 	print_end_then_start_section("map_types",
 				     "Scanning eBPF map types...",
@@ -652,7 +697,7 @@ static int do_probe(int argc, char **argv)
 				     define_prefix);
 
 	for (i = BPF_MAP_TYPE_UNSPEC + 1; i < map_type_name_size; i++)
-		probe_map_type(i, define_prefix);
+		probe_map_type(i, define_prefix, ifindex);
 
 	print_end_then_start_section("helpers",
 				     "Scanning eBPF helper functions...",
@@ -676,7 +721,7 @@ static int do_probe(int argc, char **argv)
 		       define_prefix);
 	for (i = BPF_PROG_TYPE_UNSPEC + 1; i < ARRAY_SIZE(prog_type_name); i++)
 		probe_helpers_for_progtype(i, supported_types[i],
-					   define_prefix);
+					   define_prefix, ifindex);
 
 exit_close_json:
 	if (json_output) {
@@ -697,8 +742,10 @@ static int do_help(int argc, char **argv)
 	}
 
 	fprintf(stderr,
-		"Usage: %s %s probe [kernel] [macros [prefix PREFIX]]\n"
+		"Usage: %s %s probe [COMPONENT] [macros [prefix PREFIX]]\n"
 		"       %s %s help\n"
+		"\n"
+		"       COMPONENT := { kernel | dev NAME }\n"
 		"",
 		bin_name, argv[-2], bin_name, argv[-2]);
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH bpf-next v4 9/9] tools: bpftool: add bash completion for bpftool probes
  2019-01-16 14:21 [PATCH bpf-next v4 0/9] tools: bpftool: add probes for system and device Quentin Monnet
                   ` (7 preceding siblings ...)
  2019-01-16 14:21 ` [PATCH bpf-next v4 8/9] tools: bpftool: add probes for a network device Quentin Monnet
@ 2019-01-16 14:21 ` Quentin Monnet
  2019-01-16 17:15 ` [PATCH bpf-next v4 0/9] tools: bpftool: add probes for system and device Stanislav Fomichev
  2019-01-17  0:55 ` Jakub Kicinski
  10 siblings, 0 replies; 25+ messages in thread
From: Quentin Monnet @ 2019-01-16 14:21 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann
  Cc: netdev, oss-drivers, Quentin Monnet, Arnaldo Carvalho de Melo,
	Jesper Dangaard Brouer, Stanislav Fomichev

Add the bash completion related to the newly introduced "bpftool feature
probe" command.

Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
 tools/bpf/bpftool/bash-completion/bpftool | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool
index e4e4fab1b8c7..21d5295936ed 100644
--- a/tools/bpf/bpftool/bash-completion/bpftool
+++ b/tools/bpf/bpftool/bash-completion/bpftool
@@ -624,6 +624,25 @@ _bpftool()
                     ;;
             esac
             ;;
+        feature)
+            case $command in
+                probe)
+                    [[ $prev == "dev" ]] && _sysfs_get_netdevs && return 0
+                    [[ $prev == "prefix" ]] && return 0
+                    if _bpftool_search_list 'macros'; then
+                        COMPREPLY+=( $( compgen -W 'prefix' -- "$cur" ) )
+                    else
+                        COMPREPLY+=( $( compgen -W 'macros' -- "$cur" ) )
+                    fi
+                    _bpftool_one_of_list 'kernel dev'
+                    return 0
+                    ;;
+                *)
+                    [[ $prev == $object ]] && \
+                        COMPREPLY=( $( compgen -W 'help probe' -- "$cur" ) )
+                    ;;
+            esac
+            ;;
     esac
 } &&
 complete -F _bpftool bpftool
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v4 8/9] tools: bpftool: add probes for a network device
  2019-01-16 14:21 ` [PATCH bpf-next v4 8/9] tools: bpftool: add probes for a network device Quentin Monnet
@ 2019-01-16 14:42   ` Jesper Dangaard Brouer
  2019-01-16 14:59     ` Quentin Monnet
  0 siblings, 1 reply; 25+ messages in thread
From: Jesper Dangaard Brouer @ 2019-01-16 14:42 UTC (permalink / raw)
  To: Quentin Monnet
  Cc: Alexei Starovoitov, Daniel Borkmann, netdev, oss-drivers,
	Arnaldo Carvalho de Melo, Stanislav Fomichev, brouer,
	Eric Leblond, Toke Høiland-Jørgensen

On Wed, 16 Jan 2019 14:21:18 +0000
Quentin Monnet <quentin.monnet@netronome.com> wrote:

> bpftool gained support for probing the current system in order to see
> what program and map types, and what helpers are available on that
> system. This patch adds the possibility to pass an interface index to
> libbpf (and hence to the kernel) when trying to load the programs or to
> create the maps, in order to see what items a given network device can
> support.
> 
> A new keyword "dev <ifname>" can be used as an alternative to "kernel"
> to indicate that the given device should be tested. If no target ("dev"
> or "kernel") is specified bpftool defaults to probing the kernel.
> 
> Sample output:
> 
>     # bpftool -p feature probe dev lo
>     {
>         "syscall_config": {
>             "have_bpf_syscall": true
>         },
>         "program_types": {
>             "have_sched_cls_prog_type": false,
>             "have_xdp_prog_type": false
>         },
>         ...
>     }
> 
> As the target is a network device, /proc/ parameters and kernel
> configuration are NOT dumped. Availability of the bpf() syscall is
> still probed, so we can return early if that syscall is not usable
> (since there is no point in attempting the remaining probes in this
> case).
> 
> Among the program types, only the ones that can be offloaded are probed.

Do you imagine we (later) can use this probe dev interface for probing
e.g. what XDP actions a given driver supports?  and e.g. if driver have
data_meta support.

Use-case: I've very interested in finding a solution for probing for
XDP_REDIRECT support, as Suricata need this information, so it can
choose to fallback to offloading elefant flows via TC-cls_bpf (if
XDP_REDIRECT is not avail).


> All map types are probed, as there is no specific rule telling which one
> could or could not be supported by a device in the future. All helpers
> are probed (but only for offload-able program types).
> 
> Caveat: as bpftool does not attempt to attach programs to the device at
> the moment, probes do not entirely reflect what the device accepts:
> typically, for Netronome's nfp, results will announce that TC cls
> offload is available even if support has been deactivated (with e.g.
> ethtool -K eth1 hw-tc-offload off).
> 
> v2:
> - All helpers are probed, whereas previous version would only probe the
>   ones compatible with an offload-able program type. This is because we
>   do not keep a default compatible program type for each helper anymore.



-- 
Best regards,
  Jesper Dangaard Brouer
  MSc.CS, Principal Kernel Engineer at Red Hat
  LinkedIn: http://www.linkedin.com/in/brouer

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v4 8/9] tools: bpftool: add probes for a network device
  2019-01-16 14:42   ` Jesper Dangaard Brouer
@ 2019-01-16 14:59     ` Quentin Monnet
  0 siblings, 0 replies; 25+ messages in thread
From: Quentin Monnet @ 2019-01-16 14:59 UTC (permalink / raw)
  To: Jesper Dangaard Brouer
  Cc: Alexei Starovoitov, Daniel Borkmann, netdev, oss-drivers,
	Arnaldo Carvalho de Melo, Stanislav Fomichev, Eric Leblond,
	Toke Høiland-Jørgensen

2019-01-16 15:42 UTC+0100 ~ Jesper Dangaard Brouer <brouer@redhat.com>
> On Wed, 16 Jan 2019 14:21:18 +0000
> Quentin Monnet <quentin.monnet@netronome.com> wrote:
> 
>> bpftool gained support for probing the current system in order to see
>> what program and map types, and what helpers are available on that
>> system. This patch adds the possibility to pass an interface index to
>> libbpf (and hence to the kernel) when trying to load the programs or to
>> create the maps, in order to see what items a given network device can
>> support.
>>
>> A new keyword "dev <ifname>" can be used as an alternative to "kernel"
>> to indicate that the given device should be tested. If no target ("dev"
>> or "kernel") is specified bpftool defaults to probing the kernel.
>>
>> Sample output:
>>
>>     # bpftool -p feature probe dev lo
>>     {
>>         "syscall_config": {
>>             "have_bpf_syscall": true
>>         },
>>         "program_types": {
>>             "have_sched_cls_prog_type": false,
>>             "have_xdp_prog_type": false
>>         },
>>         ...
>>     }
>>
>> As the target is a network device, /proc/ parameters and kernel
>> configuration are NOT dumped. Availability of the bpf() syscall is
>> still probed, so we can return early if that syscall is not usable
>> (since there is no point in attempting the remaining probes in this
>> case).
>>
>> Among the program types, only the ones that can be offloaded are probed.
> 
> Do you imagine we (later) can use this probe dev interface for probing
> e.g. what XDP actions a given driver supports?  and e.g. if driver have
> data_meta support.
> 
> Use-case: I've very interested in finding a solution for probing for
> XDP_REDIRECT support, as Suricata need this information, so it can
> choose to fallback to offloading elefant flows via TC-cls_bpf (if
> XDP_REDIRECT is not avail).

Hi Jesper!

For me, the question is rather a matter of how to extract the info from
the kernel (or driver in that case). If the information can be made
available somehow, sure, bpftool seems to be one of the best candidates
to use it and dump the value.

Quentin

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v4 0/9] tools: bpftool: add probes for system and device
  2019-01-16 14:21 [PATCH bpf-next v4 0/9] tools: bpftool: add probes for system and device Quentin Monnet
                   ` (8 preceding siblings ...)
  2019-01-16 14:21 ` [PATCH bpf-next v4 9/9] tools: bpftool: add bash completion for bpftool probes Quentin Monnet
@ 2019-01-16 17:15 ` Stanislav Fomichev
  2019-01-17 10:06   ` Quentin Monnet
  2019-01-17  0:55 ` Jakub Kicinski
  10 siblings, 1 reply; 25+ messages in thread
From: Stanislav Fomichev @ 2019-01-16 17:15 UTC (permalink / raw)
  To: Quentin Monnet
  Cc: Alexei Starovoitov, Daniel Borkmann, netdev, oss-drivers,
	Arnaldo Carvalho de Melo, Jesper Dangaard Brouer,
	Stanislav Fomichev

On 01/16, Quentin Monnet wrote:
> Hi,
> This set adds a new command to bpftool in order to dump a list of
> eBPF-related parameters for the system (or for a specific network
> device) to the console. Once again, this is based on a suggestion from
> Daniel.
> 
> At this time, output includes:
> 
>     - Availability of bpf() system call
>     - Availability of bpf() system call for unprivileged users
>     - JIT status (enabled or not, with or without debugging traces)
>     - JIT hardening status
>     - JIT kallsyms exports status
>     - Global memory limit for JIT compiler for unprivileged users
>     - Status of kernel compilation options related to BPF features
>     - Availability of known eBPF program types
>     - Availability of known eBPF map types
>     - Availability of known eBPF helper functions
> 
> There are three different ways to dump this information at this time:
> 
>     - Plain output dumps probe results in plain text. It is the most
>       flexible options for providing descriptive output to the user, but
>       should not be relied upon for parsing the output.
>     - JSON output is supported.
>     - A third mode, available through the "macros" keyword appended to the
>       command line, dumps some of those parameters (not all) as a series of
>       "#define" directives, that can be included into a C header file for
>       example.
> 
> Probes for supported program and map types, and supported helpers, are
> directly added to libbpf, so that other applications (or selftests) can
> reuse them as necessary.
> 
> If the user does not have root privileges (or more precisely, the
> CAP_SYS_ADMIN capability) detection will be erroneous for most
> parameters. Therefore, forbid non-root users to run the command.
> 
> v4:
> - Probe bpf_jit_limit parameter (patch 2).
> - Probe some additional kernel config options (patch 3).
> - Minor fixes on patch 6.
Looks great! For the whole series:

Reviewed-by: Stanislav Fomichev <sdf@google.com>
> 
> v3:
> - Do not probe kernel version in bpftool (just retrieve it to probe support
>   for kprobes in libbpf).
> - Change the way results for helper support is displayed: now one list of
>   compatible helpers for each program type (and C-style output gets a
>   HAVE_PROG_TYPE_HELPER(prog_type, helper) macro to help with tests. See
>   patches 6, 7.
> - Address other comments from feedback from v2 (please refer to individual
>   patches' history).
> 
> v2 (please also refer to individual patches' history):
> - Move probes for prog/map types, helpers, from bpftool to libbpf.
> - Move C-style output as a separate patch, and restrict it to a subset of
>   collected information (bpf() availability, prog/map types, helpers).
> - Now probe helpers with all supported program types, and display a list of
>   compatible program types (as supported on the system) for each helper.
> - NOT addressed: grouping compilation options for kernel into subsections
>   (patch 3) (I don't see an easy way of grouping them at the moment, please
>   see also the discussion on v1 thread).
> 
> Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
> Cc: Jesper Dangaard Brouer <brouer@redhat.com>
> Cc: Stanislav Fomichev <sdf@google.com>
> 
> Quentin Monnet (9):
>   tools: bpftool: add basic probe capability, probe syscall availability
>   tools: bpftool: add probes for /proc/ eBPF parameters
>   tools: bpftool: add probes for kernel configuration options
>   tools: bpftool: add probes for eBPF program types
>   tools: bpftool: add probes for eBPF map types
>   tools: bpftool: add probes for eBPF helper functions
>   tools: bpftool: add C-style "#define" output for probes
>   tools: bpftool: add probes for a network device
>   tools: bpftool: add bash completion for bpftool probes
> 
>  .../bpftool/Documentation/bpftool-cgroup.rst  |   1 +
>  .../bpftool/Documentation/bpftool-feature.rst |  85 ++
>  .../bpf/bpftool/Documentation/bpftool-map.rst |   1 +
>  .../bpf/bpftool/Documentation/bpftool-net.rst |   1 +
>  .../bpftool/Documentation/bpftool-perf.rst    |   1 +
>  .../bpftool/Documentation/bpftool-prog.rst    |   1 +
>  tools/bpf/bpftool/Documentation/bpftool.rst   |   1 +
>  tools/bpf/bpftool/bash-completion/bpftool     |  19 +
>  tools/bpf/bpftool/feature.c                   | 764 ++++++++++++++++++
>  tools/bpf/bpftool/main.c                      |   3 +-
>  tools/bpf/bpftool/main.h                      |   4 +
>  tools/bpf/bpftool/map.c                       |   4 +-
>  tools/lib/bpf/Build                           |   2 +-
>  tools/lib/bpf/libbpf.h                        |  14 +
>  tools/lib/bpf/libbpf.map                      |   3 +
>  tools/lib/bpf/libbpf_probes.c                 | 242 ++++++
>  16 files changed, 1143 insertions(+), 3 deletions(-)
>  create mode 100644 tools/bpf/bpftool/Documentation/bpftool-feature.rst
>  create mode 100644 tools/bpf/bpftool/feature.c
>  create mode 100644 tools/lib/bpf/libbpf_probes.c
> 
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v4 1/9] tools: bpftool: add basic probe capability, probe syscall availability
  2019-01-16 14:21 ` [PATCH bpf-next v4 1/9] tools: bpftool: add basic probe capability, probe syscall availability Quentin Monnet
@ 2019-01-17  0:28   ` Jakub Kicinski
  2019-01-17 10:02     ` Quentin Monnet
  0 siblings, 1 reply; 25+ messages in thread
From: Jakub Kicinski @ 2019-01-17  0:28 UTC (permalink / raw)
  To: Quentin Monnet
  Cc: Alexei Starovoitov, Daniel Borkmann, netdev, oss-drivers,
	Arnaldo Carvalho de Melo, Jesper Dangaard Brouer,
	Stanislav Fomichev

On Wed, 16 Jan 2019 14:21:11 +0000, Quentin Monnet wrote:
> +-------------------------------------------------------------------------------
> +tool for inspection of eBPF-related parameters for Linux kernel or net device
> +-------------------------------------------------------------------------------

Slight preference for s/eBPF/BPF/, the system call and /proc/ stuff is
all called bpf, not ebpf.

Also a question/nit here:

Does the rst2man tool care about the marking vs text length, here
dashes are longer than the actual text, people are fixing such
occurrences for Sphinx, I wonder if we should care?

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v4 3/9] tools: bpftool: add probes for kernel configuration options
  2019-01-16 14:21 ` [PATCH bpf-next v4 3/9] tools: bpftool: add probes for kernel configuration options Quentin Monnet
@ 2019-01-17  0:34   ` Jakub Kicinski
  2019-01-17 10:03     ` Quentin Monnet
  0 siblings, 1 reply; 25+ messages in thread
From: Jakub Kicinski @ 2019-01-17  0:34 UTC (permalink / raw)
  To: Quentin Monnet
  Cc: Alexei Starovoitov, Daniel Borkmann, netdev, oss-drivers,
	Arnaldo Carvalho de Melo, Jesper Dangaard Brouer,
	Stanislav Fomichev

On Wed, 16 Jan 2019 14:21:13 +0000, Quentin Monnet wrote:
> +static void probe_kernel_image_config(void)
> +{
> +	const char * const options[] = {

nit: static

> +		/* Enable BPF */
> +		"CONFIG_BPF",
> +		/* Enable bpf() syscall */
> +		"CONFIG_BPF_SYSCALL",
> +		/* Does selected architecture support eBPF JIT compiler */
> +		"CONFIG_HAVE_EBPF_JIT",
> +		/* Compile eBPF JIT compiler */
> +		"CONFIG_BPF_JIT",
> +		/* Avoid compiling eBPF interpreter (use JIT only) */
> +		"CONFIG_BPF_JIT_ALWAYS_ON",

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v4 4/9] tools: bpftool: add probes for eBPF program types
  2019-01-16 14:21 ` [PATCH bpf-next v4 4/9] tools: bpftool: add probes for eBPF program types Quentin Monnet
@ 2019-01-17  0:42   ` Jakub Kicinski
  2019-01-17  9:27     ` Daniel Borkmann
  2019-01-17 14:11     ` Quentin Monnet
  0 siblings, 2 replies; 25+ messages in thread
From: Jakub Kicinski @ 2019-01-17  0:42 UTC (permalink / raw)
  To: Quentin Monnet
  Cc: Alexei Starovoitov, Daniel Borkmann, netdev, oss-drivers,
	Arnaldo Carvalho de Melo, Jesper Dangaard Brouer,
	Stanislav Fomichev

On Wed, 16 Jan 2019 14:21:14 +0000, Quentin Monnet wrote:
> diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
> index cd02cd4e2cc3..6355e4c80a86 100644
> --- a/tools/lib/bpf/libbpf.map
> +++ b/tools/lib/bpf/libbpf.map
> @@ -56,6 +56,7 @@ LIBBPF_0.0.1 {
>  		bpf_object__unpin_maps;
>  		bpf_object__unpin_programs;
>  		bpf_perf_event_read_simple;
> +		bpf_probe_prog_type;

I think you have to start a new 0.0.2 section now, no?

>  		bpf_prog_attach;
>  		bpf_prog_detach;
>  		bpf_prog_detach2;

> +bool bpf_probe_prog_type(enum bpf_prog_type prog_type, __u32 ifindex)
> +{
> +	struct bpf_insn insns[2] = {
> +		BPF_MOV64_IMM(BPF_REG_0, 0),
> +		BPF_EXIT_INSN()
> +	};
> +
> +	if (ifindex && prog_type == BPF_PROG_TYPE_SCHED_CLS)
> +		/* nfp returns -EINVAL on exit(0) with TC offload */
> +		insns[0].imm = 2;
> +
> +	errno = 0;
> +	prog_load(prog_type, insns, ARRAY_SIZE(insns), NULL, 0, ifindex);
> +
> +	return errno != EINVAL && errno != EOPNOTSUPP;

nit: could you check that errno in the function doing the load? :|
     also perhaps name that function probe_load()?

> +}

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v4 0/9] tools: bpftool: add probes for system and device
  2019-01-16 14:21 [PATCH bpf-next v4 0/9] tools: bpftool: add probes for system and device Quentin Monnet
                   ` (9 preceding siblings ...)
  2019-01-16 17:15 ` [PATCH bpf-next v4 0/9] tools: bpftool: add probes for system and device Stanislav Fomichev
@ 2019-01-17  0:55 ` Jakub Kicinski
  2019-01-17  0:56   ` Jakub Kicinski
  10 siblings, 1 reply; 25+ messages in thread
From: Jakub Kicinski @ 2019-01-17  0:55 UTC (permalink / raw)
  To: Quentin Monnet
  Cc: Alexei Starovoitov, Daniel Borkmann, netdev, oss-drivers,
	Arnaldo Carvalho de Melo, Jesper Dangaard Brouer,
	Stanislav Fomichev

On Wed, 16 Jan 2019 14:21:10 +0000, Quentin Monnet wrote:
>  tools/bpf/bpftool/feature.c                   | 764 ++++++++++++++++++

should we perhaps git mv feature.c probe.c ?  (if you create a commit
with just a move right after the first commit which adds the file git
will figure out its a rename, and the squash this rename into first
commit).

Minor nits but otherwise feel free to re-add:

Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>

:)

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v4 0/9] tools: bpftool: add probes for system and device
  2019-01-17  0:55 ` Jakub Kicinski
@ 2019-01-17  0:56   ` Jakub Kicinski
  0 siblings, 0 replies; 25+ messages in thread
From: Jakub Kicinski @ 2019-01-17  0:56 UTC (permalink / raw)
  To: Quentin Monnet
  Cc: Alexei Starovoitov, Daniel Borkmann, netdev, oss-drivers,
	Arnaldo Carvalho de Melo, Jesper Dangaard Brouer,
	Stanislav Fomichev

On Wed, 16 Jan 2019 16:55:13 -0800, Jakub Kicinski wrote:
> On Wed, 16 Jan 2019 14:21:10 +0000, Quentin Monnet wrote:
> >  tools/bpf/bpftool/feature.c                   | 764 ++++++++++++++++++  
> 
> should we perhaps git mv feature.c probe.c ?  (if you create a commit
> with just a move right after the first commit which adds the file git
> will figure out its a rename, and the squash this rename into first
> commit).

Ah, scratch that, we got "feature probe".

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v4 4/9] tools: bpftool: add probes for eBPF program types
  2019-01-17  0:42   ` Jakub Kicinski
@ 2019-01-17  9:27     ` Daniel Borkmann
  2019-01-17 10:04       ` Quentin Monnet
  2019-01-17 14:11     ` Quentin Monnet
  1 sibling, 1 reply; 25+ messages in thread
From: Daniel Borkmann @ 2019-01-17  9:27 UTC (permalink / raw)
  To: Jakub Kicinski, Quentin Monnet
  Cc: Alexei Starovoitov, netdev, oss-drivers,
	Arnaldo Carvalho de Melo, Jesper Dangaard Brouer,
	Stanislav Fomichev

On 01/17/2019 01:42 AM, Jakub Kicinski wrote:
> On Wed, 16 Jan 2019 14:21:14 +0000, Quentin Monnet wrote:
>> diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
>> index cd02cd4e2cc3..6355e4c80a86 100644
>> --- a/tools/lib/bpf/libbpf.map
>> +++ b/tools/lib/bpf/libbpf.map
>> @@ -56,6 +56,7 @@ LIBBPF_0.0.1 {
>>  		bpf_object__unpin_maps;
>>  		bpf_object__unpin_programs;
>>  		bpf_perf_event_read_simple;
>> +		bpf_probe_prog_type;
> 
> I think you have to start a new 0.0.2 section now, no?

Yeah agree, 0.0.2 since this will go into a different kernel release
than the current functions.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v4 1/9] tools: bpftool: add basic probe capability, probe syscall availability
  2019-01-17  0:28   ` Jakub Kicinski
@ 2019-01-17 10:02     ` Quentin Monnet
  2019-01-17 10:11       ` Daniel Borkmann
  0 siblings, 1 reply; 25+ messages in thread
From: Quentin Monnet @ 2019-01-17 10:02 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Alexei Starovoitov, Daniel Borkmann, netdev, oss-drivers,
	Arnaldo Carvalho de Melo, Jesper Dangaard Brouer,
	Stanislav Fomichev

2019-01-16 16:28 UTC-0800 ~ Jakub Kicinski <jakub.kicinski@netronome.com>
> On Wed, 16 Jan 2019 14:21:11 +0000, Quentin Monnet wrote:
>> +-------------------------------------------------------------------------------
>> +tool for inspection of eBPF-related parameters for Linux kernel or net device
>> +-------------------------------------------------------------------------------
> 
> Slight preference for s/eBPF/BPF/, the system call and /proc/ stuff is
> all called bpf, not ebpf.
> 
> Also a question/nit here:
> 
> Does the rst2man tool care about the marking vs text length, here
> dashes are longer than the actual text, people are fixing such
> occurrences for Sphinx, I wonder if we should care?
> 

I'd rather keep it unchanged in this patch, as it is aligned with what 
other bpftool man pages do: bpftool, bpftool-cgroup, bpftool-map and 
bpftool-prog all have “eBPF” (bpftool-perf and bpftool-net have “bpf”, 
lower case) in their description. And all pages have longer dash rules, 
which rst2man does not seem to mind about.

I can fix all this for all bpftool pages in a follow-up patch, though, 
if it's alright for you?

Quentin

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v4 3/9] tools: bpftool: add probes for kernel configuration options
  2019-01-17  0:34   ` Jakub Kicinski
@ 2019-01-17 10:03     ` Quentin Monnet
  0 siblings, 0 replies; 25+ messages in thread
From: Quentin Monnet @ 2019-01-17 10:03 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Alexei Starovoitov, Daniel Borkmann, netdev, oss-drivers,
	Arnaldo Carvalho de Melo, Jesper Dangaard Brouer,
	Stanislav Fomichev

2019-01-16 16:34 UTC-0800 ~ Jakub Kicinski <jakub.kicinski@netronome.com>
> On Wed, 16 Jan 2019 14:21:13 +0000, Quentin Monnet wrote:
>> +static void probe_kernel_image_config(void)
>> +{
>> +	const char * const options[] = {
> 
> nit: static

Thanks, will fix.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v4 4/9] tools: bpftool: add probes for eBPF program types
  2019-01-17  9:27     ` Daniel Borkmann
@ 2019-01-17 10:04       ` Quentin Monnet
  0 siblings, 0 replies; 25+ messages in thread
From: Quentin Monnet @ 2019-01-17 10:04 UTC (permalink / raw)
  To: Daniel Borkmann, Jakub Kicinski
  Cc: Alexei Starovoitov, netdev, oss-drivers,
	Arnaldo Carvalho de Melo, Jesper Dangaard Brouer,
	Stanislav Fomichev

2019-01-17 10:27 UTC+0100 ~ Daniel Borkmann <daniel@iogearbox.net>
> On 01/17/2019 01:42 AM, Jakub Kicinski wrote:
>> On Wed, 16 Jan 2019 14:21:14 +0000, Quentin Monnet wrote:
>>> diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
>>> index cd02cd4e2cc3..6355e4c80a86 100644
>>> --- a/tools/lib/bpf/libbpf.map
>>> +++ b/tools/lib/bpf/libbpf.map
>>> @@ -56,6 +56,7 @@ LIBBPF_0.0.1 {
>>>   		bpf_object__unpin_maps;
>>>   		bpf_object__unpin_programs;
>>>   		bpf_perf_event_read_simple;
>>> +		bpf_probe_prog_type;
>>
>> I think you have to start a new 0.0.2 section now, no?
> 
> Yeah agree, 0.0.2 since this will go into a different kernel release
> than the current functions.

Oh I had not realised that, thanks. I'll fix and send v5.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v4 0/9] tools: bpftool: add probes for system and device
  2019-01-16 17:15 ` [PATCH bpf-next v4 0/9] tools: bpftool: add probes for system and device Stanislav Fomichev
@ 2019-01-17 10:06   ` Quentin Monnet
  0 siblings, 0 replies; 25+ messages in thread
From: Quentin Monnet @ 2019-01-17 10:06 UTC (permalink / raw)
  To: Stanislav Fomichev
  Cc: Alexei Starovoitov, Daniel Borkmann, netdev, oss-drivers,
	Arnaldo Carvalho de Melo, Jesper Dangaard Brouer,
	Stanislav Fomichev

2019-01-16 09:15 UTC-0800 ~ Stanislav Fomichev <sdf@fomichev.me>
> On 01/16, Quentin Monnet wrote:
>> Hi,
>> This set adds a new command to bpftool in order to dump a list of
>> eBPF-related parameters for the system (or for a specific network
>> device) to the console. Once again, this is based on a suggestion from
>> Daniel.
>>
>> At this time, output includes:
>>
>>      - Availability of bpf() system call
>>      - Availability of bpf() system call for unprivileged users
>>      - JIT status (enabled or not, with or without debugging traces)
>>      - JIT hardening status
>>      - JIT kallsyms exports status
>>      - Global memory limit for JIT compiler for unprivileged users
>>      - Status of kernel compilation options related to BPF features
>>      - Availability of known eBPF program types
>>      - Availability of known eBPF map types
>>      - Availability of known eBPF helper functions
>>
>> There are three different ways to dump this information at this time:
>>
>>      - Plain output dumps probe results in plain text. It is the most
>>        flexible options for providing descriptive output to the user, but
>>        should not be relied upon for parsing the output.
>>      - JSON output is supported.
>>      - A third mode, available through the "macros" keyword appended to the
>>        command line, dumps some of those parameters (not all) as a series of
>>        "#define" directives, that can be included into a C header file for
>>        example.
>>
>> Probes for supported program and map types, and supported helpers, are
>> directly added to libbpf, so that other applications (or selftests) can
>> reuse them as necessary.
>>
>> If the user does not have root privileges (or more precisely, the
>> CAP_SYS_ADMIN capability) detection will be erroneous for most
>> parameters. Therefore, forbid non-root users to run the command.
>>
>> v4:
>> - Probe bpf_jit_limit parameter (patch 2).
>> - Probe some additional kernel config options (patch 3).
>> - Minor fixes on patch 6.
> Looks great! For the whole series:
> 
> Reviewed-by: Stanislav Fomichev <sdf@google.com>

Thanks for the reviews! :)

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v4 1/9] tools: bpftool: add basic probe capability, probe syscall availability
  2019-01-17 10:02     ` Quentin Monnet
@ 2019-01-17 10:11       ` Daniel Borkmann
  0 siblings, 0 replies; 25+ messages in thread
From: Daniel Borkmann @ 2019-01-17 10:11 UTC (permalink / raw)
  To: Quentin Monnet, Jakub Kicinski
  Cc: Alexei Starovoitov, netdev, oss-drivers,
	Arnaldo Carvalho de Melo, Jesper Dangaard Brouer,
	Stanislav Fomichev

On 01/17/2019 11:02 AM, Quentin Monnet wrote:
> 2019-01-16 16:28 UTC-0800 ~ Jakub Kicinski <jakub.kicinski@netronome.com>
>> On Wed, 16 Jan 2019 14:21:11 +0000, Quentin Monnet wrote:
>>> +-------------------------------------------------------------------------------
>>> +tool for inspection of eBPF-related parameters for Linux kernel or net device
>>> +-------------------------------------------------------------------------------
>>
>> Slight preference for s/eBPF/BPF/, the system call and /proc/ stuff is
>> all called bpf, not ebpf.
>>
>> Also a question/nit here:
>>
>> Does the rst2man tool care about the marking vs text length, here
>> dashes are longer than the actual text, people are fixing such
>> occurrences for Sphinx, I wonder if we should care?
> 
> I'd rather keep it unchanged in this patch, as it is aligned with what other bpftool man pages do: bpftool, bpftool-cgroup, bpftool-map and bpftool-prog all have “eBPF” (bpftool-perf and bpftool-net have “bpf”, lower case) in their description. And all pages have longer dash rules, which rst2man does not seem to mind about.
> 
> I can fix all this for all bpftool pages in a follow-up patch, though, if it's alright for you?

My preference is on for s/eBPF/BPF/ as well, so lets fix everything up;
follow-up is okay with me.

Thanks,
Daniel

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v4 4/9] tools: bpftool: add probes for eBPF program types
  2019-01-17  0:42   ` Jakub Kicinski
  2019-01-17  9:27     ` Daniel Borkmann
@ 2019-01-17 14:11     ` Quentin Monnet
  1 sibling, 0 replies; 25+ messages in thread
From: Quentin Monnet @ 2019-01-17 14:11 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Alexei Starovoitov, Daniel Borkmann, netdev, oss-drivers,
	Arnaldo Carvalho de Melo, Jesper Dangaard Brouer,
	Stanislav Fomichev

2019-01-16 16:42 UTC-0800 ~ Jakub Kicinski <jakub.kicinski@netronome.com>
> On Wed, 16 Jan 2019 14:21:14 +0000, Quentin Monnet wrote:

>> +bool bpf_probe_prog_type(enum bpf_prog_type prog_type, __u32 ifindex)
>> +{
>> +	struct bpf_insn insns[2] = {
>> +		BPF_MOV64_IMM(BPF_REG_0, 0),
>> +		BPF_EXIT_INSN()
>> +	};
>> +
>> +	if (ifindex && prog_type == BPF_PROG_TYPE_SCHED_CLS)
>> +		/* nfp returns -EINVAL on exit(0) with TC offload */
>> +		insns[0].imm = 2;
>> +
>> +	errno = 0;
>> +	prog_load(prog_type, insns, ARRAY_SIZE(insns), NULL, 0, ifindex);
>> +
>> +	return errno != EINVAL && errno != EOPNOTSUPP;
> 
> nit: could you check that errno in the function doing the load? :|

No, the prog_load() function is also used in patch 6 in
bpf_probe_helper() to load the probes, but the check to assess the
success or failure of the probes is not the same for helpers and program
types. So checking the result does not belong to prog_load(), in my opinion.

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2019-01-17 14:11 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-16 14:21 [PATCH bpf-next v4 0/9] tools: bpftool: add probes for system and device Quentin Monnet
2019-01-16 14:21 ` [PATCH bpf-next v4 1/9] tools: bpftool: add basic probe capability, probe syscall availability Quentin Monnet
2019-01-17  0:28   ` Jakub Kicinski
2019-01-17 10:02     ` Quentin Monnet
2019-01-17 10:11       ` Daniel Borkmann
2019-01-16 14:21 ` [PATCH bpf-next v4 2/9] tools: bpftool: add probes for /proc/ eBPF parameters Quentin Monnet
2019-01-16 14:21 ` [PATCH bpf-next v4 3/9] tools: bpftool: add probes for kernel configuration options Quentin Monnet
2019-01-17  0:34   ` Jakub Kicinski
2019-01-17 10:03     ` Quentin Monnet
2019-01-16 14:21 ` [PATCH bpf-next v4 4/9] tools: bpftool: add probes for eBPF program types Quentin Monnet
2019-01-17  0:42   ` Jakub Kicinski
2019-01-17  9:27     ` Daniel Borkmann
2019-01-17 10:04       ` Quentin Monnet
2019-01-17 14:11     ` Quentin Monnet
2019-01-16 14:21 ` [PATCH bpf-next v4 5/9] tools: bpftool: add probes for eBPF map types Quentin Monnet
2019-01-16 14:21 ` [PATCH bpf-next v4 6/9] tools: bpftool: add probes for eBPF helper functions Quentin Monnet
2019-01-16 14:21 ` [PATCH bpf-next v4 7/9] tools: bpftool: add C-style "#define" output for probes Quentin Monnet
2019-01-16 14:21 ` [PATCH bpf-next v4 8/9] tools: bpftool: add probes for a network device Quentin Monnet
2019-01-16 14:42   ` Jesper Dangaard Brouer
2019-01-16 14:59     ` Quentin Monnet
2019-01-16 14:21 ` [PATCH bpf-next v4 9/9] tools: bpftool: add bash completion for bpftool probes Quentin Monnet
2019-01-16 17:15 ` [PATCH bpf-next v4 0/9] tools: bpftool: add probes for system and device Stanislav Fomichev
2019-01-17 10:06   ` Quentin Monnet
2019-01-17  0:55 ` Jakub Kicinski
2019-01-17  0:56   ` Jakub Kicinski

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.