From patchwork Tue Feb 18 19:02:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Rostecki X-Patchwork-Id: 208774 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2B8DDC34049 for ; Tue, 18 Feb 2020 19:03:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0ED8A24670 for ; Tue, 18 Feb 2020 19:03:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726496AbgBRTCg (ORCPT ); Tue, 18 Feb 2020 14:02:36 -0500 Received: from mx2.suse.de ([195.135.220.15]:35592 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726464AbgBRTCg (ORCPT ); Tue, 18 Feb 2020 14:02:36 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 3EA46ABEA; Tue, 18 Feb 2020 19:02:33 +0000 (UTC) From: Michal Rostecki To: bpf@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , Martin KaFai Lau , Song Liu , Yonghong Song , Andrii Nakryiko , Quentin Monnet , Jakub Kicinski , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Shuah Khan , "David S. Miller" , Jesper Dangaard Brouer , John Fastabend , linux-kselftest@vger.kernel.org Subject: [PATCH bpf-next 1/6] bpftool: Move out sections to separate functions Date: Tue, 18 Feb 2020 20:02:18 +0100 Message-Id: <20200218190224.22508-2-mrostecki@opensuse.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200218190224.22508-1-mrostecki@opensuse.org> References: <20200218190224.22508-1-mrostecki@opensuse.org> MIME-Version: 1.0 Sender: linux-kselftest-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org 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. Next changes are going to allow probing chosen subsets of features. This change will make them more readable. Signed-off-by: Michal Rostecki --- tools/bpf/bpftool/feature.c | 219 +++++++++++++++++++++--------------- 1 file changed, 126 insertions(+), 93 deletions(-) diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c index 941873d778d8..345e4a2b4f53 100644 --- a/tools/bpf/bpftool/feature.c +++ b/tools/bpf/bpftool/feature.c @@ -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 is available for ,\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 is available for ,\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; } From patchwork Tue Feb 18 19:02:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Rostecki X-Patchwork-Id: 208775 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EB175C34026 for ; Tue, 18 Feb 2020 19:03:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C642F24672 for ; Tue, 18 Feb 2020 19:03:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726650AbgBRTCl (ORCPT ); Tue, 18 Feb 2020 14:02:41 -0500 Received: from mx2.suse.de ([195.135.220.15]:35646 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726464AbgBRTCl (ORCPT ); Tue, 18 Feb 2020 14:02:41 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id AD6E7ADBE; Tue, 18 Feb 2020 19:02:36 +0000 (UTC) From: Michal Rostecki To: bpf@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , Martin KaFai Lau , Song Liu , Yonghong Song , Andrii Nakryiko , Quentin Monnet , Jakub Kicinski , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Shuah Khan , linux-kselftest@vger.kernel.org Subject: [PATCH bpf-next 3/6] bpftool: Add arguments for filtering in and filtering out probes Date: Tue, 18 Feb 2020 20:02:20 +0100 Message-Id: <20200218190224.22508-4-mrostecki@opensuse.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200218190224.22508-1-mrostecki@opensuse.org> References: <20200218190224.22508-1-mrostecki@opensuse.org> MIME-Version: 1.0 Sender: linux-kselftest-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org Add positional arguments "filter_in" and "filter_out" to the feature command of bpftool. If "filter_in" is defined, bpftool is going to perform and print only checks which match the given pattern. If "filter_out" is defined, bpftool will not perform and print checks which match the given pattern. Signed-off-by: Michal Rostecki --- tools/bpf/bpftool/feature.c | 324 ++++++++++++++++++++++++++++-------- 1 file changed, 256 insertions(+), 68 deletions(-) diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c index cfba0faf148f..f10e928d18c8 100644 --- a/tools/bpf/bpftool/feature.c +++ b/tools/bpf/bpftool/feature.c @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -64,6 +65,55 @@ static void uppercase(char *str, size_t len) str[i] = toupper(str[i]); } +/* Filtering utility functions */ + +static bool +check_filters(const char *name, regex_t *filter_in, regex_t *filter_out) +{ + char err_buf[100]; + int ret; + + /* Do not probe if filter_in was defined and string does not match + * against the pattern. + */ + if (filter_in) { + ret = regexec(filter_in, name, 0, NULL, 0); + switch (ret) { + case 0: + break; + case REG_NOMATCH: + return false; + default: + regerror(ret, filter_in, err_buf, ARRAY_SIZE(err_buf)); + p_err("could not match regex: %s", err_buf); + free(filter_in); + free(filter_out); + exit(1); + } + } + + /* Do not probe if filter_out was defined and string matches against the + * pattern. + */ + if (filter_out) { + ret = regexec(filter_out, name, 0, NULL, 0); + switch (ret) { + case 0: + return false; + case REG_NOMATCH: + break; + default: + regerror(ret, filter_out, err_buf, ARRAY_SIZE(err_buf)); + p_err("could not match regex: %s", err_buf); + free(filter_in); + free(filter_out); + exit(1); + } + } + + return true; +} + /* Printing utility functions */ static void @@ -79,11 +129,16 @@ print_bool_feature(const char *feat_name, const char *plain_name, printf("%s is %savailable\n", plain_name, res ? "" : "NOT "); } -static void print_kernel_option(const char *name, const char *value) +static void +print_kernel_option(const char *name, const char *value, regex_t *filter_in, + regex_t *filter_out) { char *endptr; int res; + if (!check_filters(name, filter_in, filter_out)) + return; + /* No support for C-style ouptut */ if (json_output) { @@ -154,15 +209,19 @@ static int read_procfs(const char *path) return res; } -static void probe_unprivileged_disabled(void) +static void probe_unprivileged_disabled(regex_t *filter_in, regex_t *filter_out) { + const char *feat_name = "unprivileged_bpf_disabled"; int res; /* No support for C-style ouptut */ + if (!check_filters(feat_name, filter_in, filter_out)) + return; + res = read_procfs("/proc/sys/kernel/unprivileged_bpf_disabled"); if (json_output) { - jsonw_int_field(json_wtr, "unprivileged_bpf_disabled", res); + jsonw_int_field(json_wtr, feat_name, res); } else { switch (res) { case 0: @@ -180,15 +239,19 @@ static void probe_unprivileged_disabled(void) } } -static void probe_jit_enable(void) +static void probe_jit_enable(regex_t *filter_in, regex_t *filter_out) { + const char *feat_name = "bpf_jit_enable"; int res; /* No support for C-style ouptut */ + if (!check_filters(feat_name, filter_in, filter_out)) + return; + res = read_procfs("/proc/sys/net/core/bpf_jit_enable"); if (json_output) { - jsonw_int_field(json_wtr, "bpf_jit_enable", res); + jsonw_int_field(json_wtr, feat_name, res); } else { switch (res) { case 0: @@ -210,15 +273,19 @@ static void probe_jit_enable(void) } } -static void probe_jit_harden(void) +static void probe_jit_harden(regex_t *filter_in, regex_t *filter_out) { + const char *feat_name = "bpf_jit_harden"; int res; /* No support for C-style ouptut */ + if (!check_filters(feat_name, filter_in, filter_out)) + return; + res = read_procfs("/proc/sys/net/core/bpf_jit_harden"); if (json_output) { - jsonw_int_field(json_wtr, "bpf_jit_harden", res); + jsonw_int_field(json_wtr, feat_name, res); } else { switch (res) { case 0: @@ -240,15 +307,19 @@ static void probe_jit_harden(void) } } -static void probe_jit_kallsyms(void) +static void probe_jit_kallsyms(regex_t *filter_in, regex_t *filter_out) { + const char *feat_name = "bpf_jit_kallsyms"; int res; /* No support for C-style ouptut */ + if (!check_filters(feat_name, filter_in, filter_out)) + return; + res = read_procfs("/proc/sys/net/core/bpf_jit_kallsyms"); if (json_output) { - jsonw_int_field(json_wtr, "bpf_jit_kallsyms", res); + jsonw_int_field(json_wtr, feat_name, res); } else { switch (res) { case 0: @@ -266,15 +337,19 @@ static void probe_jit_kallsyms(void) } } -static void probe_jit_limit(void) +static void probe_jit_limit(regex_t *filter_in, regex_t *filter_out) { + const char *feat_name = "bpf_jit_limit"; int res; /* No support for C-style ouptut */ + if (!check_filters(feat_name, filter_in, filter_out)) + return; + res = read_procfs("/proc/sys/net/core/bpf_jit_limit"); if (json_output) { - jsonw_int_field(json_wtr, "bpf_jit_limit", res); + jsonw_int_field(json_wtr, feat_name, res); } else { switch (res) { case -1: @@ -314,7 +389,8 @@ static bool read_next_kernel_config_option(gzFile file, char *buf, size_t n, return false; } -static void probe_kernel_image_config(void) +static void +probe_kernel_image_config(regex_t *filter_in, regex_t *filter_out) { static const char * const options[] = { /* Enable BPF */ @@ -438,23 +514,31 @@ static void probe_kernel_image_config(void) gzclose(file); for (i = 0; i < ARRAY_SIZE(options); i++) { - print_kernel_option(options[i], values[i]); + print_kernel_option(options[i], values[i], filter_in, + filter_out); free(values[i]); } } static bool -probe_bpf_syscall(bool print_syscall_config, const char *define_prefix) +probe_bpf_syscall(bool print_syscall_config, const char *define_prefix, + regex_t *filter_in, regex_t *filter_out) { + const char *feat_name = "have_bpf_syscall"; + const char *plain_desc = "bpf() syscall"; + const char *define_name = "BPF_SYSCALL"; bool res; bpf_load_program(BPF_PROG_TYPE_UNSPEC, NULL, 0, NULL, 0, NULL, 0); res = (errno != ENOSYS); + if (!check_filters(feat_name, filter_in, filter_out)) + print_syscall_config = false; + if (print_syscall_config) - print_bool_feature("have_bpf_syscall", - "bpf() syscall", - "BPF_SYSCALL", + print_bool_feature(feat_name, + plain_desc, + define_name, res, define_prefix); return res; @@ -462,13 +546,19 @@ probe_bpf_syscall(bool print_syscall_config, const char *define_prefix) static void probe_prog_type(bool print_program_types, enum bpf_prog_type prog_type, - bool *supported_types, const char *define_prefix, __u32 ifindex) + bool *supported_types, const char *define_prefix, + regex_t *filter_in, regex_t *filter_out, __u32 ifindex) { char feat_name[128], plain_desc[128], define_name[128]; const char *plain_comment = "eBPF program_type "; size_t maxlen; bool res; + 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]); + if (ifindex) /* Only test offload-able program types */ switch (prog_type) { @@ -489,10 +579,8 @@ probe_prog_type(bool print_program_types, enum bpf_prog_type prog_type, return; } - 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]); + if (!check_filters(feat_name, filter_in, filter_out)) + return; if (print_program_types) print_bool_feature(feat_name, plain_desc, define_name, res, @@ -501,13 +589,21 @@ probe_prog_type(bool print_program_types, enum bpf_prog_type prog_type, static void probe_map_type(enum bpf_map_type map_type, const char *define_prefix, - __u32 ifindex) + regex_t *filter_in, regex_t *filter_out, __u32 ifindex) { char feat_name[128], plain_desc[128], define_name[128]; const char *plain_comment = "eBPF map_type "; size_t maxlen; bool res; + 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]); + + if (!check_filters(feat_name, filter_in, filter_out)) + return; + res = bpf_probe_map_type(map_type, ifindex); maxlen = sizeof(plain_desc) - strlen(plain_comment) - 1; @@ -516,23 +612,23 @@ probe_map_type(enum bpf_map_type map_type, const char *define_prefix, return; } - 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, define_name, res, define_prefix); } static void probe_helpers_for_progtype(enum bpf_prog_type prog_type, bool supported_type, - const char *define_prefix, __u32 ifindex) + const char *define_prefix, regex_t *filter_in, + regex_t *filter_out, __u32 ifindex) { const char *ptype_name = prog_type_name[prog_type]; char feat_name[128]; unsigned int id; bool res; + if (!check_filters(ptype_name, filter_in, filter_out)) + return; + if (ifindex) /* Only test helpers for offload-able program types */ switch (prog_type) { @@ -553,6 +649,9 @@ probe_helpers_for_progtype(enum bpf_prog_type prog_type, bool supported_type, } for (id = 1; id < ARRAY_SIZE(helper_name); id++) { + if (!check_filters(helper_name[id], filter_in, filter_out)) + continue; + if (!supported_type) res = false; else @@ -578,19 +677,27 @@ probe_helpers_for_progtype(enum bpf_prog_type prog_type, bool supported_type, } static void -probe_large_insn_limit(const char *define_prefix, __u32 ifindex) +probe_large_insn_limit(const char *define_prefix, regex_t *filter_in, + regex_t *filter_out, __u32 ifindex) { + const char *plain_desc = "Large program size limit"; + const char *feat_name = "have_large_insn_limit"; + const char *define_name = "LARGE_INSN_LIMIT"; bool res; + if (!check_filters(feat_name, filter_in, filter_out)) + return; + res = bpf_probe_large_insn_limit(ifindex); - print_bool_feature("have_large_insn_limit", - "Large program size limit", - "LARGE_INSN_LIMIT", + print_bool_feature(feat_name, + plain_desc, + define_name, res, define_prefix); } static void -section_system_config(enum probe_component target, const char *define_prefix) +section_system_config(enum probe_component target, const char *define_prefix, + regex_t *filter_in, regex_t *filter_out) { switch (target) { case COMPONENT_KERNEL: @@ -603,15 +710,15 @@ section_system_config(enum probe_component target, const char *define_prefix) 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(); + probe_unprivileged_disabled(filter_in, filter_out); + probe_jit_enable(filter_in, filter_out); + probe_jit_harden(filter_in, filter_out); + probe_jit_kallsyms(filter_in, filter_out); + probe_jit_limit(filter_in, filter_out); } else { p_info("/* procfs not mounted, skipping related probes */"); } - probe_kernel_image_config(); + probe_kernel_image_config(filter_in, filter_out); print_end_section(); break; default: @@ -620,7 +727,8 @@ section_system_config(enum probe_component target, const char *define_prefix) } static bool -section_syscall_config(bool print_syscall_config, const char *define_prefix) +section_syscall_config(bool print_syscall_config, const char *define_prefix, + regex_t *filter_in, regex_t *filter_out) { bool res; @@ -629,7 +737,8 @@ section_syscall_config(bool print_syscall_config, const char *define_prefix) "Scanning system call availability...", "/*** System call availability ***/", define_prefix); - res = probe_bpf_syscall(print_syscall_config, define_prefix); + res = probe_bpf_syscall(print_syscall_config, define_prefix, + filter_in, filter_out); if (print_syscall_config) print_end_section(); @@ -638,7 +747,8 @@ section_syscall_config(bool print_syscall_config, const char *define_prefix) static void section_program_types(bool print_program_types, bool *supported_types, - const char *define_prefix, __u32 ifindex) + const char *define_prefix, regex_t *filter_in, + regex_t *filter_out, __u32 ifindex) { unsigned int i; @@ -650,13 +760,14 @@ section_program_types(bool print_program_types, bool *supported_types, for (i = BPF_PROG_TYPE_UNSPEC + 1; i < ARRAY_SIZE(prog_type_name); i++) probe_prog_type(print_program_types, i, supported_types, - define_prefix, ifindex); + define_prefix, filter_in, filter_out, ifindex); if (print_program_types) print_end_section(); } -static void section_map_types(const char *define_prefix, __u32 ifindex) +static void section_map_types(const char *define_prefix, regex_t *filter_in, + regex_t *filter_out, __u32 ifindex) { unsigned int i; @@ -666,13 +777,15 @@ static void section_map_types(const char *define_prefix, __u32 ifindex) define_prefix); for (i = BPF_MAP_TYPE_UNSPEC + 1; i < map_type_name_size; i++) - probe_map_type(i, define_prefix, ifindex); + probe_map_type(i, define_prefix, filter_in, filter_out, + ifindex); print_end_section(); } static void -section_helpers(bool *supported_types, const char *define_prefix, __u32 ifindex) +section_helpers(bool *supported_types, const char *define_prefix, + regex_t *filter_in, regex_t *filter_out, __u32 ifindex) { unsigned int i; @@ -698,18 +811,20 @@ section_helpers(bool *supported_types, const char *define_prefix, __u32 ifindex) 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); + define_prefix, filter_in, filter_out, + ifindex); print_end_section(); } -static void section_misc(const char *define_prefix, __u32 ifindex) +static void section_misc(const char *define_prefix, regex_t *filter_in, + regex_t *filter_out, __u32 ifindex) { print_start_section(SECTION_MISC, "Scanning miscellaneous eBPF features...", "/*** eBPF misc features ***/", define_prefix); - probe_large_insn_limit(define_prefix, ifindex); + probe_large_insn_limit(define_prefix, filter_in, filter_out, ifindex); print_end_section(); } @@ -721,6 +836,8 @@ static int do_probe(int argc, char **argv) * should exit. */ bool print_syscall_config = false; + const char *filter_out_raw = NULL; + const char *filter_in_raw = NULL; const char *define_prefix = NULL; bool check_system_config = false; /* Program types probes are needed if helper probes are going to be @@ -734,9 +851,14 @@ static int do_probe(int argc, char **argv) bool check_map_types = false; bool check_helpers = false; bool check_section = false; + regex_t *filter_out = NULL; + regex_t *filter_in = NULL; bool check_misc = false; + char regerror_buf[100]; __u32 ifindex = 0; char *ifname; + int reg_ret; + int ret = 0; /* Detection assumes user has sufficient privileges (CAP_SYS_ADMIN). * Let's approximate, and restrict usage to root user only. @@ -752,7 +874,8 @@ static int do_probe(int argc, char **argv) if (is_prefix(*argv, "kernel")) { if (target != COMPONENT_UNSPEC) { p_err("component to probe already specified"); - return -1; + ret = -1; + goto cleanup; } target = COMPONENT_KERNEL; NEXT_ARG(); @@ -761,10 +884,13 @@ static int do_probe(int argc, char **argv) if (target != COMPONENT_UNSPEC || ifindex) { p_err("component to probe already specified"); - return -1; + ret = -1; + goto cleanup; + } + if (!REQ_ARGS(1)) { + ret = -1; + goto cleanup; } - if (!REQ_ARGS(1)) - return -1; target = COMPONENT_DEVICE; ifname = GET_ARG(); @@ -772,7 +898,8 @@ static int do_probe(int argc, char **argv) if (!ifindex) { p_err("unrecognized netdevice '%s': %s", ifname, strerror(errno)); - return -1; + ret = -1; + goto cleanup; } } else if (is_prefix(*argv, "section")) { check_section = true; @@ -804,30 +931,82 @@ static int do_probe(int argc, char **argv) SECTION_MAP_TYPES, SECTION_HELPERS, SECTION_MISC); - return -1; + ret = -1; + goto cleanup; + } + NEXT_ARG(); + } else if (is_prefix(*argv, "filter_in")) { + if (filter_in_raw) { + p_err("filter_in can be used only once"); + ret = -1; + goto cleanup; } NEXT_ARG(); + if (!REQ_ARGS(1)) { + ret = -1; + goto cleanup; + } + filter_in_raw = GET_ARG(); + + filter_in = malloc(sizeof(regex_t)); + reg_ret = regcomp(filter_in, filter_in_raw, 0); + if (reg_ret) { + regerror(reg_ret, filter_in, regerror_buf, + ARRAY_SIZE(regerror_buf)); + p_err("could not compile regex: %s", + regerror_buf); + ret = -1; + goto cleanup; + } + } else if (is_prefix(*argv, "filter_out")) { + if (filter_out_raw) { + p_err("filter_out can be used only once"); + ret = -1; + goto cleanup; + } + NEXT_ARG(); + if (!REQ_ARGS(1)) { + ret = -1; + goto cleanup; + } + filter_out_raw = GET_ARG(); + + filter_out = malloc(sizeof(regex_t)); + reg_ret = regcomp(filter_out, filter_out_raw, 0); + if (reg_ret) { + regerror(reg_ret, filter_out, regerror_buf, + ARRAY_SIZE(regerror_buf)); + p_err("could not compile regex: %s", + regerror_buf); + ret = -1; + goto cleanup; + } } 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; + ret = -1; + goto cleanup; } if (strcmp(define_prefix, "")) { p_err("'prefix' already defined"); - return -1; + ret = -1; + goto cleanup; } NEXT_ARG(); - if (!REQ_ARGS(1)) - return -1; + if (!REQ_ARGS(1)) { + ret = -1; + goto cleanup; + } define_prefix = GET_ARG(); } else { p_err("expected no more arguments, 'kernel', 'dev', 'macros' or 'prefix', got: '%s'?", *argv); - return -1; + ret = -1; + goto cleanup; } } @@ -848,26 +1027,35 @@ static int do_probe(int argc, char **argv) } if (check_system_config) - section_system_config(target, define_prefix); - if (!section_syscall_config(print_syscall_config, define_prefix)) + section_system_config(target, define_prefix, filter_in, + filter_out); + if (!section_syscall_config(print_syscall_config, define_prefix, + filter_in, filter_out)) /* bpf() syscall unavailable, don't probe other BPF features */ goto exit_close_json; if (check_program_types) section_program_types(print_program_types, supported_types, - define_prefix, ifindex); + define_prefix, filter_in, filter_out, + ifindex); if (check_map_types) - section_map_types(define_prefix, ifindex); + section_map_types(define_prefix, filter_in, filter_out, + ifindex); if (check_helpers) - section_helpers(supported_types, define_prefix, ifindex); + section_helpers(supported_types, define_prefix, filter_in, + filter_out, ifindex); if (check_misc) - section_misc(define_prefix, ifindex); + section_misc(define_prefix, filter_in, filter_out, ifindex); exit_close_json: if (json_output) /* End root object */ jsonw_end_object(json_wtr); - return 0; +cleanup: + free(filter_in); + free(filter_out); + + return ret; } static int do_help(int argc, char **argv) @@ -878,7 +1066,7 @@ static int do_help(int argc, char **argv) } fprintf(stderr, - "Usage: %s %s probe [COMPONENT] [section SECTION] [macros [prefix PREFIX]]\n" + "Usage: %s %s probe [COMPONENT] [section SECTION] [filter_in PATTERN] [filter_out PATTERN] [macros [prefix PREFIX]]\n" " %s %s help\n" "\n" " COMPONENT := { kernel | dev NAME }\n" From patchwork Tue Feb 18 19:02:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Rostecki X-Patchwork-Id: 208776 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A9841C34026 for ; Tue, 18 Feb 2020 19:02:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8DAEA24683 for ; Tue, 18 Feb 2020 19:02:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726736AbgBRTCo (ORCPT ); Tue, 18 Feb 2020 14:02:44 -0500 Received: from mx2.suse.de ([195.135.220.15]:35758 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726691AbgBRTCo (ORCPT ); Tue, 18 Feb 2020 14:02:44 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 43D69ADE4; Tue, 18 Feb 2020 19:02:40 +0000 (UTC) From: Michal Rostecki To: bpf@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , Martin KaFai Lau , Song Liu , Yonghong Song , Andrii Nakryiko , Quentin Monnet , Jakub Kicinski , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Shuah Khan , linux-kselftest@vger.kernel.org Subject: [PATCH bpf-next 5/6] bpftool: Update bash completion for "bpftool feature" command Date: Tue, 18 Feb 2020 20:02:22 +0100 Message-Id: <20200218190224.22508-6-mrostecki@opensuse.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200218190224.22508-1-mrostecki@opensuse.org> References: <20200218190224.22508-1-mrostecki@opensuse.org> MIME-Version: 1.0 Sender: linux-kselftest-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org Update bash completion for "bpftool feature" command with information about new arguments: "section", "filter_id" and "filter_out". Signed-off-by: Michal Rostecki --- tools/bpf/bpftool/bash-completion/bpftool | 32 +++++++++++++++++------ 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool index 754d8395e451..ff8ac9bebdda 100644 --- a/tools/bpf/bpftool/bash-completion/bpftool +++ b/tools/bpf/bpftool/bash-completion/bpftool @@ -981,14 +981,30 @@ _bpftool() feature) case $command in probe) - [[ $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 + case $prev in + $command) + COMPREPLY+=( $( compgen -W 'kernel dev section filter_in filter_out macros' -- \ + "$cur" ) ) + return 0 + ;; + section) + COMPREPLY+=( $( compgen -W 'system_config syscall_config program_types map_types helpers misc' -- \ + "$cur" ) ) + return 0 + ;; + filter_in|filter_out|prefix) + return 0 + ;; + macros) + COMPREPLY+=( $( compgen -W 'prefix' -- "$cur" ) ) + return 0 + ;; + *) + _bpftool_one_of_list 'kernel dev' + _bpftool_once_attr 'section filter_in filter_out macros' + return 0 + ;; + esac ;; *) [[ $prev == $object ]] && \