From patchwork Thu Jan 3 14:02:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Quentin Monnet X-Patchwork-Id: 1020320 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=netronome.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=netronome-com.20150623.gappssmtp.com header.i=@netronome-com.20150623.gappssmtp.com header.b="ZoljGVBJ"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 43VqPv6g1sz9s9h for ; Fri, 4 Jan 2019 01:03:15 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731829AbfACODB (ORCPT ); Thu, 3 Jan 2019 09:03:01 -0500 Received: from mail-wr1-f67.google.com ([209.85.221.67]:41094 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731762AbfACOC7 (ORCPT ); Thu, 3 Jan 2019 09:02:59 -0500 Received: by mail-wr1-f67.google.com with SMTP id x10so33639465wrs.8 for ; Thu, 03 Jan 2019 06:02:58 -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=202PP8Dy4PW6VGwSHicEq9RzeblpF1cBAogkBo9KcvI=; b=ZoljGVBJ6glzO0AdqhxLIQaykOJg4vg9x9nsoMkyfuNVn90ouj3brFWbhjUCmBUb6s Lsitj+hMYGndkA/hl+Eniq1U4hvJNPWAVZgg4Nt06k7fNuP/qynDTtvBU+XY/HvWEOrJ yGlG7Lf1Zy+i3DNUuQ81h3ouOMn2cfJyvNUjsNwPtbqwN8/vdoPr1U97Yjm5g5SPamxb tKX5T1ypXJvhYybld8l+ddLV33L1MYszm0bebuElLenJLwxMuaMl7hiF5bndYXumWhz2 GOBuPuC7yOI+OJIb1PK63Q8xqQlxAFQ1iydvDzd+2FG9wqjxzaxN5j2YeIGEGQFkiO6F c3GQ== 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=202PP8Dy4PW6VGwSHicEq9RzeblpF1cBAogkBo9KcvI=; b=UfYo3y14U0Q9q9dHoIw/ybd0Dx3IhypxMHBLvXQK7lZOzKj9rlRR+adqOfZk4y3VDz ttbzndi0HsILruFC7GeXgxk2rQYhCO/qdBsYaZXbUul/4Cp37mn7D6evXejGtnHTQSwD 8OSaMOI3yP3wk4On4/jt2czdxwwup0o3FCtBzZ9ZeA/zVC0yO7b8tGbZ+17dWZoAPqMt iNU6LfYlHfkQWutiO/Oh6HO92rnyRIkccN0Lz7KRdsZ1cWWhTb8XXbddyV8Xq90Kqy5T NGBv4d21J5EUQP0dfb7nfHLQOgPYXVfQ8IKf6Mhcb0IETGvcSqAR96njdB3jwkYV1GDz NTnw== X-Gm-Message-State: AJcUukfE5EYsoLp9d6qPmgF6MzLKkJRHWRBw0aA//iQL0JwX9AOK5wB6 n0Qlb4kikZg6NktzA1TH8DOVQjhNXoXmnw== X-Google-Smtp-Source: ALg8bN6R8oq1JZMZCF0PhY0/ehqzGEUMW/4LMrRjYlHUhSFs7OUqMyLokK37IlwD1Zadiu+6HRpCcw== X-Received: by 2002:adf:84e4:: with SMTP id 91mr40667833wrg.237.1546524177270; Thu, 03 Jan 2019 06:02:57 -0800 (PST) Received: from cbtest32.netronome.com ([217.38.71.146]) by smtp.gmail.com with ESMTPSA id 10sm44854771wmy.40.2019.01.03.06.02.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 03 Jan 2019 06:02:56 -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: [RFC bpf-next v3 3/9] tools: bpftool: add probes for kernel configuration options Date: Thu, 3 Jan 2019 14:02:33 +0000 Message-Id: <20190103140239.23548-4-quentin.monnet@netronome.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190103140239.23548-1-quentin.monnet@netronome.com> References: <20190103140239.23548-1-quentin.monnet@netronome.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org 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", ... } } 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 Reviewed-by: Jakub Kicinski --- tools/bpf/bpftool/feature.c | 142 ++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c index 37fe79f59015..05c16fe67005 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) { @@ -190,6 +214,123 @@ static void probe_jit_kallsyms(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[] = { + "CONFIG_BPF", + "CONFIG_BPF_SYSCALL", + "CONFIG_HAVE_EBPF_JIT", + "CONFIG_BPF_JIT", + "CONFIG_BPF_JIT_ALWAYS_ON", + "CONFIG_NET", + "CONFIG_XDP_SOCKETS", + "CONFIG_CGROUPS", + "CONFIG_CGROUP_BPF", + "CONFIG_CGROUP_NET_CLASSID", + "CONFIG_BPF_EVENTS", + "CONFIG_LWTUNNEL_BPF", + "CONFIG_NET_ACT_BPF", + "CONFIG_NET_CLS_ACT", + "CONFIG_NET_CLS_BPF", + "CONFIG_NET_SCH_INGRESS", + "CONFIG_XFRM", + "CONFIG_SOCK_CGROUP_DATA", + "CONFIG_IP_ROUTE_CLASSID", + "CONFIG_IPV6_SEG6_BPF", + "CONFIG_FUNCTION_ERROR_INJECTION", + "CONFIG_BPF_KPROBE_OVERRIDE", + "CONFIG_BPF_LIRC_MODE2", + "CONFIG_NETFILTER_XT_MATCH_BPF", + "CONFIG_TEST_BPF", + "CONFIG_BPFILTER", + "CONFIG_BPFILTER_UMH", + "CONFIG_BPF_STREAM_PARSER", + }; + 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; @@ -249,6 +390,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