From mboxrd@z Thu Jan 1 00:00:00 1970 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.0 required=3.0 tests=DKIMWL_WL_MED,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham 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 876D3C43387 for ; Wed, 16 Jan 2019 14:21:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 4C1F0205C9 for ; Wed, 16 Jan 2019 14:21:54 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=netronome-com.20150623.gappssmtp.com header.i=@netronome-com.20150623.gappssmtp.com header.b="pqXSkZyR" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2404669AbfAPOVv (ORCPT ); Wed, 16 Jan 2019 09:21:51 -0500 Received: from mail-wm1-f65.google.com ([209.85.128.65]:53283 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2404656AbfAPOVt (ORCPT ); Wed, 16 Jan 2019 09:21:49 -0500 Received: by mail-wm1-f65.google.com with SMTP id d15so2170185wmb.3 for ; Wed, 16 Jan 2019 06:21:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=netronome-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=QjvvIzQcTGSW0w2XIItM7T9XhJkSNcQGOlJvPQyRpnk=; b=pqXSkZyR4orFnt0kWSVN93mwPg8wY729MWDAaV7a5hreWo1Rm1442K/VQFFKw34NXR m+x4PyCXN7wNnX2pgcxTb87fP7oolEwqIQHyvf5f5RmhGejw2U3hWLoJZG33EF4SLAwk ofDX9C496EQVlhtTJpprbdgEd9ig5t0K+T1C8shoNl+CUGOS4NiBOgf5wZPv+Xn0Cefx hsMlXDz3rwTOCc/WWMSiirym9acnWBcMtmP9zxv0Uhe6hREI5g5cXnqIEYWBStG2ddRc NmAKSMTvdJDmG4EOujTwB0lDw3gPHiJYeEE2qNAESKeqvr6sOyMvhrtXytGwRhhC3hIs 2oSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=QjvvIzQcTGSW0w2XIItM7T9XhJkSNcQGOlJvPQyRpnk=; b=t2f6I6yVAYzmTQLpjeJJh50IrUWfNpjOhSiXrNLOPb4GleH63MyqSoLaRF6GYxBbj5 XlTz/KovREnbItohzCp0WCSOBnofCSGcNPOwiEJuAm563do8oyTXigQrxxSB/d2waaAZ pK1JpRGAA+vZrM41/r5DjaQkjCoOpJJNVV4vo2heA4uU7ODjPlQV2dKbJRjuxsG8oKUj Rn9+3ykE+4xNAoEUoPEp5qZeCYfPXF92b1vc2DFVubo1mFpnEHhEezJKo+G9sF8RRdlF plkBKJVyzE6estjjVX8Decn7A0IqSBsFYSCLOCcnM0+Hc0UOauH2I75UDr5QXNrPEnWt eGSw== X-Gm-Message-State: AJcUukcJzpN89uzJ/YWFbD0qdzpu3cPuwj0W/NCeq9gvJIQf3uF3+KR6 fJGI4HRaXNLOfVw4PLppILDtEbtd7c8= X-Google-Smtp-Source: ALg8bN6wmkdYbJ6G4OBg0GJ2/MEl0bAze1FMpDX4pqlyiavjImMb9sa10lDrfXo2Io6wWsbf4tx+HA== X-Received: by 2002:a7b:c5cc:: with SMTP id n12mr7824066wmk.149.1547648506832; Wed, 16 Jan 2019 06:21:46 -0800 (PST) Received: from cbtest32.netronome.com ([217.38.71.146]) by smtp.gmail.com with ESMTPSA id p6sm97412602wrx.50.2019.01.16.06.21.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 16 Jan 2019 06:21:46 -0800 (PST) From: Quentin Monnet To: Alexei Starovoitov , Daniel Borkmann Cc: netdev@vger.kernel.org, oss-drivers@netronome.com, Quentin Monnet , Arnaldo Carvalho de Melo , Jesper Dangaard Brouer , Stanislav Fomichev Subject: [PATCH bpf-next v4 8/9] tools: bpftool: add probes for a network device Date: Wed, 16 Jan 2019 14:21:18 +0000 Message-Id: <20190116142119.8358-9-quentin.monnet@netronome.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190116142119.8358-1-quentin.monnet@netronome.com> References: <20190116142119.8358-1-quentin.monnet@netronome.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org 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 " 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 Reviewed-by: Jakub Kicinski --- .../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 #include #include +#include #include #include @@ -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