@@ -22,6 +22,13 @@
# define PROC_SUPER_MAGIC 0x9fa0
#endif
+#define SECTION_SYSCALL_CONFIG "syscall_config"
+#define SECTION_SYSTEM_CONFIG "system_config"
+#define SECTION_PROGRAM_TYPES "program_types"
+#define SECTION_MAP_TYPES "map_types"
+#define SECTION_HELPERS "helpers"
+#define SECTION_MISC "misc"
+
enum probe_component {
COMPONENT_UNSPEC,
COMPONENT_KERNEL,
@@ -436,24 +443,26 @@ static void probe_kernel_image_config(void)
}
}
-static bool probe_bpf_syscall(const char *define_prefix)
+static bool
+probe_bpf_syscall(bool print_syscall_config, const char *define_prefix)
{
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",
- "BPF_SYSCALL",
- res, define_prefix);
+ if (print_syscall_config)
+ print_bool_feature("have_bpf_syscall",
+ "bpf() syscall",
+ "BPF_SYSCALL",
+ res, define_prefix);
return res;
}
static void
-probe_prog_type(enum bpf_prog_type prog_type, bool *supported_types,
- const char *define_prefix, __u32 ifindex)
+probe_prog_type(bool print_program_types, enum bpf_prog_type prog_type,
+ bool *supported_types, const char *define_prefix, __u32 ifindex)
{
char feat_name[128], plain_desc[128], define_name[128];
const char *plain_comment = "eBPF program_type ";
@@ -484,8 +493,10 @@ probe_prog_type(enum bpf_prog_type prog_type, bool *supported_types,
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, define_name, res,
- define_prefix);
+
+ if (print_program_types)
+ print_bool_feature(feat_name, plain_desc, define_name, res,
+ define_prefix);
}
static void
@@ -587,7 +598,7 @@ section_system_config(enum probe_component target, const char *define_prefix)
if (define_prefix)
break;
- print_start_section("system_config",
+ print_start_section(SECTION_SYSTEM_CONFIG,
"Scanning system configuration...",
NULL, /* define_comment never used here */
NULL); /* define_prefix always NULL here */
@@ -608,42 +619,48 @@ section_system_config(enum probe_component target, const char *define_prefix)
}
}
-static bool section_syscall_config(const char *define_prefix)
+static bool
+section_syscall_config(bool print_syscall_config, const char *define_prefix)
{
bool res;
- print_start_section("syscall_config",
- "Scanning system call availability...",
- "/*** System call availability ***/",
- define_prefix);
- res = probe_bpf_syscall(define_prefix);
- print_end_section();
+ if (print_syscall_config)
+ print_start_section(SECTION_SYSCALL_CONFIG,
+ "Scanning system call availability...",
+ "/*** System call availability ***/",
+ define_prefix);
+ res = probe_bpf_syscall(print_syscall_config, define_prefix);
+ if (print_syscall_config)
+ print_end_section();
return res;
}
static void
-section_program_types(bool *supported_types, const char *define_prefix,
- __u32 ifindex)
+section_program_types(bool print_program_types, bool *supported_types,
+ const char *define_prefix, __u32 ifindex)
{
unsigned int i;
- print_start_section("program_types",
- "Scanning eBPF program types...",
- "/*** eBPF program types ***/",
- define_prefix);
+ if (print_program_types)
+ print_start_section(SECTION_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, define_prefix, ifindex);
+ probe_prog_type(print_program_types, i, supported_types,
+ define_prefix, ifindex);
- print_end_section();
+ if (print_program_types)
+ print_end_section();
}
static void section_map_types(const char *define_prefix, __u32 ifindex)
{
unsigned int i;
- print_start_section("map_types",
+ print_start_section(SECTION_MAP_TYPES,
"Scanning eBPF map types...",
"/*** eBPF map types ***/",
define_prefix);
@@ -659,7 +676,7 @@ section_helpers(bool *supported_types, const char *define_prefix, __u32 ifindex)
{
unsigned int i;
- print_start_section("helpers",
+ print_start_section(SECTION_HELPERS,
"Scanning eBPF helper functions...",
"/*** eBPF helper functions ***/",
define_prefix);
@@ -688,7 +705,7 @@ section_helpers(bool *supported_types, const char *define_prefix, __u32 ifindex)
static void section_misc(const char *define_prefix, __u32 ifindex)
{
- print_start_section("misc",
+ print_start_section(SECTION_MISC,
"Scanning miscellaneous eBPF features...",
"/*** eBPF misc features ***/",
define_prefix);
@@ -699,8 +716,25 @@ static void section_misc(const char *define_prefix, __u32 ifindex)
static int do_probe(int argc, char **argv)
{
enum probe_component target = COMPONENT_UNSPEC;
+ /* Syscall probe is always performed, because performing any other
+ * checks without bpf() syscall does not make sense and the program
+ * should exit.
+ */
+ bool print_syscall_config = false;
const char *define_prefix = NULL;
+ bool check_system_config = false;
+ /* Program types probes are needed if helper probes are going to be
+ * performed. Therefore we should differentiate between checking and
+ * printing supported program types. If only helper checks were
+ * requested, program types probes will be performed, but not printed.
+ */
+ bool check_program_types = false;
+ bool print_program_types = false;
bool supported_types[128] = {};
+ bool check_map_types = false;
+ bool check_helpers = false;
+ bool check_section = false;
+ bool check_misc = false;
__u32 ifindex = 0;
char *ifname;
@@ -740,6 +774,39 @@ static int do_probe(int argc, char **argv)
strerror(errno));
return -1;
}
+ } else if (is_prefix(*argv, "section")) {
+ check_section = true;
+ NEXT_ARG();
+ if (is_prefix(*argv, SECTION_SYSTEM_CONFIG)) {
+ check_system_config = true;
+ } else if (is_prefix(*argv, SECTION_SYSCALL_CONFIG)) {
+ print_syscall_config = true;
+ } else if (is_prefix(*argv, SECTION_PROGRAM_TYPES)) {
+ check_program_types = true;
+ print_program_types = true;
+ } else if (is_prefix(*argv, SECTION_MAP_TYPES)) {
+ check_map_types = true;
+ } else if (is_prefix(*argv, SECTION_HELPERS)) {
+ /* When helpers probes are requested, program
+ * types probes have to be performed, but they
+ * may not be printed.
+ */
+ check_program_types = true;
+ check_helpers = true;
+ } else if (is_prefix(*argv, SECTION_MISC)) {
+ check_misc = true;
+ } else {
+ p_err("unrecognized section '%s', available sections: %s, %s, %s, %s, %s, %s",
+ *argv,
+ SECTION_SYSTEM_CONFIG,
+ SECTION_SYSCALL_CONFIG,
+ SECTION_PROGRAM_TYPES,
+ SECTION_MAP_TYPES,
+ SECTION_HELPERS,
+ SECTION_MISC);
+ return -1;
+ }
+ NEXT_ARG();
} else if (is_prefix(*argv, "macros") && !define_prefix) {
define_prefix = "";
NEXT_ARG();
@@ -764,19 +831,36 @@ static int do_probe(int argc, char **argv)
}
}
+ /* Perform all checks if specific section check was not requested. */
+ if (!check_section) {
+ print_syscall_config = true;
+ check_system_config = true;
+ check_program_types = true;
+ print_program_types = true;
+ check_map_types = true;
+ check_helpers = true;
+ check_misc = true;
+ }
+
if (json_output) {
define_prefix = NULL;
jsonw_start_object(json_wtr);
}
- section_system_config(target, define_prefix);
- if (!section_syscall_config(define_prefix))
+ if (check_system_config)
+ section_system_config(target, define_prefix);
+ if (!section_syscall_config(print_syscall_config, define_prefix))
/* bpf() syscall unavailable, don't probe other BPF features */
goto exit_close_json;
- section_program_types(supported_types, define_prefix, ifindex);
- section_map_types(define_prefix, ifindex);
- section_helpers(supported_types, define_prefix, ifindex);
- section_misc(define_prefix, ifindex);
+ if (check_program_types)
+ section_program_types(print_program_types, supported_types,
+ define_prefix, ifindex);
+ if (check_map_types)
+ section_map_types(define_prefix, ifindex);
+ if (check_helpers)
+ section_helpers(supported_types, define_prefix, ifindex);
+ if (check_misc)
+ section_misc(define_prefix, ifindex);
exit_close_json:
if (json_output)
@@ -794,12 +878,15 @@ static int do_help(int argc, char **argv)
}
fprintf(stderr,
- "Usage: %s %s probe [COMPONENT] [macros [prefix PREFIX]]\n"
+ "Usage: %s %s probe [COMPONENT] [section SECTION] [macros [prefix PREFIX]]\n"
" %s %s help\n"
"\n"
" COMPONENT := { kernel | dev NAME }\n"
+ " SECTION := { %s | %s | %s | %s | %s | %s }\n"
"",
- bin_name, argv[-2], bin_name, argv[-2]);
+ bin_name, argv[-2], bin_name, argv[-2], SECTION_SYSTEM_CONFIG,
+ SECTION_SYSCALL_CONFIG, SECTION_PROGRAM_TYPES,
+ SECTION_MAP_TYPES, SECTION_HELPERS, SECTION_MISC);
return 0;
}
This change introduces a new positional argument "section" which takes the following arguments: - system_config - syscall_config - program_types - map_types - helpers - misc If "section" argument is defined, only that particular section is going to be probed and printed. The only section which is always going to be probed is "syscall_config", but if the other section was provided as an argument, "syscall_config" check will perform silently without printing and exit bpftool if the bpf() syscall is not available (because in that case running any probe has no sense). Signed-off-by: Michal Rostecki <mrostecki@opensuse.org> --- tools/bpf/bpftool/feature.c | 159 ++++++++++++++++++++++++++++-------- 1 file changed, 123 insertions(+), 36 deletions(-)