Commit 6b52ca44 authored by Michal Rostecki's avatar Michal Rostecki Committed by Daniel Borkmann
Browse files

bpftool: Move out sections to separate functions



Remove all calls of print_end_then_start_section function and for loops
out from the do_probe function. Instead, provide separate functions for
each section (like i.e. section_helpers) which are called in do_probe.
This change is motivated by better readability.

Signed-off-by: default avatarMichal Rostecki <mrostecki@opensuse.org>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Reviewed-by: default avatarQuentin Monnet <quentin@isovalent.com>
Link: https://lore.kernel.org/bpf/20200226165941.6379-2-mrostecki@opensuse.org
parent 3494bec0
Loading
Loading
Loading
Loading
+126 −93
Original line number Diff line number Diff line
@@ -112,18 +112,12 @@ 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,
			     const char *define_comment,
			     const char *define_prefix)
static void print_end_section(void)
{
	if (json_output)
		jsonw_end_object(json_wtr);
	else
		printf("\n");

	print_start_section(json_title, plain_title, define_comment,
			    define_prefix);
}

/* Probing functions */
@@ -584,13 +578,130 @@ probe_large_insn_limit(const char *define_prefix, __u32 ifindex)
			   res, define_prefix);
}

static void
section_system_config(enum probe_component target, const char *define_prefix)
{
	switch (target) {
	case COMPONENT_KERNEL:
	case COMPONENT_UNSPEC:
		if (define_prefix)
			break;

		print_start_section("system_config",
				    "Scanning system configuration...",
				    NULL, /* define_comment never used here */
				    NULL); /* define_prefix always NULL here */
		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 */");
		}
		probe_kernel_image_config();
		print_end_section();
		break;
	default:
		break;
	}
}

static bool section_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();

	return res;
}

static void
section_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);

	for (i = BPF_PROG_TYPE_UNSPEC + 1; i < ARRAY_SIZE(prog_type_name); i++)
		probe_prog_type(i, supported_types, define_prefix, ifindex);

	print_end_section();
}

static void section_map_types(const char *define_prefix, __u32 ifindex)
{
	unsigned int i;

	print_start_section("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, define_prefix, ifindex);

	print_end_section();
}

static void
section_helpers(bool *supported_types, const char *define_prefix, __u32 ifindex)
{
	unsigned int i;

	print_start_section("helpers",
			    "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],
					   define_prefix, ifindex);

	print_end_section();
}

static void section_misc(const char *define_prefix, __u32 ifindex)
{
	print_start_section("misc",
			    "Scanning miscellaneous eBPF features...",
			    "/*** eBPF misc features ***/",
			    define_prefix);
	probe_large_insn_limit(define_prefix, ifindex);
	print_end_section();
}

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).
@@ -658,97 +769,19 @@ static int do_probe(int argc, char **argv)
		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...",
				    NULL, /* define_comment never used here */
				    NULL); /* define_prefix always NULL here */
		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 */");
		}
		probe_kernel_image_config();
		if (json_output)
			jsonw_end_object(json_wtr);
		else
			printf("\n");
		break;
	default:
		break;
	}

	print_start_section("syscall_config",
			    "Scanning system call availability...",
			    "/*** System call availability ***/",
			    define_prefix);

	if (!probe_bpf_syscall(define_prefix))
	section_system_config(target, define_prefix);
	if (!section_syscall_config(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...",
				     "/*** 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);

	print_end_then_start_section("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, define_prefix, ifindex);

	print_end_then_start_section("helpers",
				     "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],
					   define_prefix, ifindex);

	print_end_then_start_section("misc",
				     "Scanning miscellaneous eBPF features...",
				     "/*** eBPF misc features ***/",
				     define_prefix);
	probe_large_insn_limit(define_prefix, ifindex);
	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);

exit_close_json:
	if (json_output) {
		/* End current "section" of probes */
		jsonw_end_object(json_wtr);
	if (json_output)
		/* End root object */
		jsonw_end_object(json_wtr);
	}

	return 0;
}