From patchwork Tue Aug 13 13:09:19 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Quentin Monnet X-Patchwork-Id: 1146342 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: incoming-bpf@patchwork.ozlabs.org Delivered-To: patchwork-incoming-bpf@bilbo.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=bpf-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="eicD9E5j"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 467Cjc71tCz9sND for ; Tue, 13 Aug 2019 23:09:40 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728756AbfHMNJj (ORCPT ); Tue, 13 Aug 2019 09:09:39 -0400 Received: from mail-wm1-f66.google.com ([209.85.128.66]:55283 "EHLO mail-wm1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728548AbfHMNJi (ORCPT ); Tue, 13 Aug 2019 09:09:38 -0400 Received: by mail-wm1-f66.google.com with SMTP id p74so1457748wme.4 for ; Tue, 13 Aug 2019 06:09:38 -0700 (PDT) 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=jwSUSEZgz5QveQuauT2jx1+QbRo0U2C9co9dcGbvAiA=; b=eicD9E5jysBbCK9zfKC3ab5eWoNN/w4uDiEs4Xntnv5Pi8S3uFoq8JxCWX/PbHn11x SQVSaO8KFwWb8JoojYneeFmALd5rOozBIlnf5OX9paDnL3Ua9Qa/B5vdPEvsnbrmMoSu lQuB0hDLQjjpROtG+BC0vswWYzfJHW4P9xtRd93x5a2Pef2/qWzNxuTlvr47D6aBesjQ IbBz7xDQ4Q0N0XP+Kpm6PsIfE0LmJVL0Zt9i3AJRwJqNjT1O1WrCL0uSkgZ5AC/fMLnf NwSb13k+WRHxcWUWwi5CJQbmWiqlaCnH1OKqPqfvCFdciUG5fBEl5C8GkIu0J4dUK69o Ab8A== 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=jwSUSEZgz5QveQuauT2jx1+QbRo0U2C9co9dcGbvAiA=; b=Iro4kK0yFSxrzdM9gy6r1aHDef7j+kzm+wlmYopeeQq1E1VA8XTBvonk0968MUQkil Vh89pmGq3yJ6vi0noMmsQ7Z4hJKIRH02pzadnq1bEMVKDWf5huBoIyxT/0Au3QUeZ13h qscdCzlGqefqUBhK0Q0t7TA3b4jmWqJSBgtKcPI7hmpapXQouCUzI5QPdqdupTX/QK8k 0C8digLw/y5uWXqPqPffGC7Qr6UY36b6xZU0kfVgcWHPGCJE0XrRSopxydaWhUBEnLZ2 Qjcrzn8GI/mgcxTTRyaNX/wpahT3iLWhjVmJnC0NId40QGcSmEYvcS6ByOQxWP5kDGeT Jrdw== X-Gm-Message-State: APjAAAVjnXvTXbI21/jdUq9XnZryOuggELhiH8F3xdvc9FRyrVdLEdRF aCftpfgrlmhXdY2OaFV7qX7fCMBqE3Y= X-Google-Smtp-Source: APXvYqzQDPXOOf07TR4BQXYp3MxwPCeDBruQaLzxBoGWRWeHQqs/G821Aiuw12ZZ6Esz2SNPaix6ZQ== X-Received: by 2002:a1c:27c1:: with SMTP id n184mr2842664wmn.61.1565701777656; Tue, 13 Aug 2019 06:09:37 -0700 (PDT) Received: from cbtest32.netronome.com ([217.38.71.146]) by smtp.gmail.com with ESMTPSA id e3sm130534191wrs.37.2019.08.13.06.09.36 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 13 Aug 2019 06:09:36 -0700 (PDT) From: Quentin Monnet To: Alexei Starovoitov , Daniel Borkmann Cc: bpf@vger.kernel.org, netdev@vger.kernel.org, oss-drivers@netronome.com, Quentin Monnet Subject: [RFC bpf-next 1/3] tools: bpftool: clean up dump_map_elem() return value Date: Tue, 13 Aug 2019 14:09:19 +0100 Message-Id: <20190813130921.10704-2-quentin.monnet@netronome.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190813130921.10704-1-quentin.monnet@netronome.com> References: <20190813130921.10704-1-quentin.monnet@netronome.com> Sender: bpf-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org The code for dumping a map entry (as part of a full map dump) was moved to a specific function dump_map_elem() in commit 18a781daa93e ("tools/bpf: bpftool, split the function do_dump()"). The "num_elems" variable was moved in that function, incremented on success, and returned to be immediately added to the counter in do_dump(). Returning the count of elements dumped, which is either 0 or 1, is not really consistent with the rest of the function, especially because "dump_map_elem()" name is not explicit about returning a counter. Furthermore, the counter is not incremented when the entry is dumped in JSON. This has no visible effect, because the number of elements successfully dumped is not printed for JSON output. Still, let's remove "num_elems" from the function and make it return 0 or -1 in case of success or failure, respectively. This is more correct, and more consistent with the rest of the code. It is unclear if an error value should indeed be returned for maps of maps or maps of progs, but this has no effect on the output either, so we just leave the current behaviour unchanged. Signed-off-by: Quentin Monnet Reviewed-by: Jakub Kicinski --- tools/bpf/bpftool/map.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c index bfbbc6b4cb83..206ee46189d9 100644 --- a/tools/bpf/bpftool/map.c +++ b/tools/bpf/bpftool/map.c @@ -686,7 +686,6 @@ static int dump_map_elem(int fd, void *key, void *value, struct bpf_map_info *map_info, struct btf *btf, json_writer_t *btf_wtr) { - int num_elems = 0; int lookup_errno; if (!bpf_map_lookup_elem(fd, key, value)) { @@ -704,9 +703,8 @@ static int dump_map_elem(int fd, void *key, void *value, } else { print_entry_plain(map_info, key, value); } - num_elems++; } - return num_elems; + return 0; } /* lookup error handling */ @@ -714,7 +712,7 @@ static int dump_map_elem(int fd, void *key, void *value, if (map_is_map_of_maps(map_info->type) || map_is_map_of_progs(map_info->type)) - return 0; + return -1; if (json_output) { jsonw_start_object(json_wtr); @@ -738,7 +736,7 @@ static int dump_map_elem(int fd, void *key, void *value, msg ? : strerror(lookup_errno)); } - return 0; + return -1; } static int do_dump(int argc, char **argv) @@ -800,7 +798,8 @@ static int do_dump(int argc, char **argv) err = 0; break; } - num_elems += dump_map_elem(fd, key, value, &info, btf, btf_wtr); + if (!dump_map_elem(fd, key, value, &info, btf, btf_wtr)) + num_elems++; prev_key = key; } From patchwork Tue Aug 13 13:09:20 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Quentin Monnet X-Patchwork-Id: 1146343 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: incoming-bpf@patchwork.ozlabs.org Delivered-To: patchwork-incoming-bpf@bilbo.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=bpf-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="FA3IsM7W"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 467Cjd4HYyz9sDQ for ; Tue, 13 Aug 2019 23:09:41 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728796AbfHMNJl (ORCPT ); Tue, 13 Aug 2019 09:09:41 -0400 Received: from mail-wm1-f67.google.com ([209.85.128.67]:53973 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728749AbfHMNJk (ORCPT ); Tue, 13 Aug 2019 09:09:40 -0400 Received: by mail-wm1-f67.google.com with SMTP id 10so1458961wmp.3 for ; Tue, 13 Aug 2019 06:09:39 -0700 (PDT) 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=5t2Cjkq2qCeaG9kNbXuJM01Wwz49tMsT0IYIprvtUF8=; b=FA3IsM7WCftMDKM0KjEbh9ABTtcFnjKmj12/6SWB8PeXc4fR7K44ra8Iab2SO4Jp4e QTtTaobooTjCmkDrYD5zV9oRRHGwGiwUs/ASEtee0k4otrCtjM+4QMwUj0DEYLsgltQ5 +i3zSu29EgB1vmd5SX3Q6epR3pQoDAZPhV53t6ILZV9oDXPujLuvSI3fmfa8mshpdUq3 9K8m7sEkSHL4WceaASxVo6HTFdkbmssFWnLray1mqp3BdPBAZERNtQLPanSKjd2aOkOA ylK+I6iOb9OeSHse0mCeQg505nQxGFk1oZtYLqDb6fpoRFsppMbeh/aXkieG23D3WGe+ JiKg== 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=5t2Cjkq2qCeaG9kNbXuJM01Wwz49tMsT0IYIprvtUF8=; b=TY3+CKapsjhRW5kx2HE6ggmVkYUfsa9CcRZpwezb8kflybd6oOXyVcfUi1CY8u5byH ZwFtbpdkIykzt4T54vlK0lwQo4jjLdudkUl5qq4bMURSnbzvv0CBYgLL5ew+4Da3S9Pe y6JdZP2fMV2NR/p3yhWVQZlmvXEZLNt2styv2lKs51eNOpPzeUOPRFyGDBcBOQTN5A3s R0unNgEBgZ6d8u2z+BYmfWnkDU0Oyrcuu+8pB00KbnE2NjRQ9bsONF5aDdfpSh258iwg Fb70J+tidirwaN3BvuE3Jpq3sepKbn/fbkgASVtzaZx68aHcegdTkY6Zea7LTbeeEmCG KTVA== X-Gm-Message-State: APjAAAUZQuFo5oGtWAIldEBSO0wqmIbvrAcDScrar32YKq8+giWhSRtK hmXaonT3Y5XSUJEJnZ3bOnXANlp5ozw= X-Google-Smtp-Source: APXvYqxc+qQGpvM2IgwsH3+RygwGjsblkYoJEGg1sDVSn/qkgvJxBi2OIVQW+kU7lZtysghRtLpIlw== X-Received: by 2002:a05:600c:2411:: with SMTP id 17mr2853483wmp.171.1565701778589; Tue, 13 Aug 2019 06:09:38 -0700 (PDT) Received: from cbtest32.netronome.com ([217.38.71.146]) by smtp.gmail.com with ESMTPSA id e3sm130534191wrs.37.2019.08.13.06.09.37 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 13 Aug 2019 06:09:37 -0700 (PDT) From: Quentin Monnet To: Alexei Starovoitov , Daniel Borkmann Cc: bpf@vger.kernel.org, netdev@vger.kernel.org, oss-drivers@netronome.com, Quentin Monnet Subject: [RFC bpf-next 2/3] tools: bpftool: make comment more explicit for count of dumped entries Date: Tue, 13 Aug 2019 14:09:20 +0100 Message-Id: <20190813130921.10704-3-quentin.monnet@netronome.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190813130921.10704-1-quentin.monnet@netronome.com> References: <20190813130921.10704-1-quentin.monnet@netronome.com> Sender: bpf-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org The counter printed at the end of plain map dump does not reflect the exact number of entries in the map, but the number of entries bpftool managed to dump (some of them could not be read, or made no sense to dump (map-in-map...)). Edit slightly the message to make this more explicit. Signed-off-by: Quentin Monnet Reviewed-by: Jakub Kicinski --- tools/bpf/bpftool/map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c index 206ee46189d9..cead639b3ab1 100644 --- a/tools/bpf/bpftool/map.c +++ b/tools/bpf/bpftool/map.c @@ -809,7 +809,7 @@ static int do_dump(int argc, char **argv) jsonw_end_array(btf_wtr); jsonw_destroy(&btf_wtr); } else { - printf("Found %u element%s\n", num_elems, + printf("Found %u element%s to dump\n", num_elems, num_elems != 1 ? "s" : ""); } From patchwork Tue Aug 13 13:09:21 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Quentin Monnet X-Patchwork-Id: 1146346 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="lC9tcbie"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 467Cjm21KPz9sN6 for ; Tue, 13 Aug 2019 23:09:48 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728955AbfHMNJo (ORCPT ); Tue, 13 Aug 2019 09:09:44 -0400 Received: from mail-wm1-f66.google.com ([209.85.128.66]:35530 "EHLO mail-wm1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728548AbfHMNJn (ORCPT ); Tue, 13 Aug 2019 09:09:43 -0400 Received: by mail-wm1-f66.google.com with SMTP id l2so1406303wmg.0 for ; Tue, 13 Aug 2019 06:09:40 -0700 (PDT) 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=fBSwKRQRFtjc++Itb2fNjwWiILszK6eORmY1dPCJdUQ=; b=lC9tcbieOI+w9hLY9uHAqSQWU9hy2j8Mr5I1AOSNVb71zGwZvEQH/irk6FPNvV+7Wl rj4SZWbLesWpdT52pzkVgmbMlGgycA5X9rUx3QBfdbze2sLc0qFxcWlxOiCsOD3NX1CP N+9IyJJh3dI3zFQoMbdCFr/XquVps8LAWPzlS2w5DzPK6atPHGv2AQEaco10z9YZVspx 1+f74ZHvEykWc5dSlBU1qtQ5uZ7rHbUiIWKI57Hrnkjdl1u1GsJTZa/XFKyKwLcxk0f+ 8xWEHzm4DKB3Q/Ojgt+YDpoDbAvBSh1S2dT5rWmRHjwgNo3XleYfCUPZ/CLYBTDvKkFT hfew== 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=fBSwKRQRFtjc++Itb2fNjwWiILszK6eORmY1dPCJdUQ=; b=EyMz0J2JwVWsI+9j4F1li2r21NOuc/YO+HykDhGOCAjGMQ47rkvypSjTJY0KFbDu2J 8Rr1v4xlcc24XO4zLZkC7R4642bnEuATkYfMQBxGxmJgzBNmym2DahA0rRUQqxOAM87r X3VhO7wjUvLEWxBGOZpKSMzB/gDv3vFcG55FoAshvGECFeOzZcVOfnd3QA2yN6/w95Km NOkwIIlUBakJcNeRXtraZih7Qr8+JDg/MNbi1hC0PqtTFBrpVnyABN2h3cv+GGyYRSmz HRlyOkzK1IFyMBA5euT5+dIr5tCq0xIdWRPa7585CpJHEJt5NnISVq6Yz7Mocf2mIdRF gqnQ== X-Gm-Message-State: APjAAAVFlLHlRQBfRihenMDbPETYs/DbXhzRu2r/MNCOAA/YTce3rn50 aqy/CxWPR75L6bxvuWsmMh6DNQ== X-Google-Smtp-Source: APXvYqwfD4tzVtlkVpnEOpTAP+MB++U2UgrC+2KALOHSldAM+3AUh0DnCcNwO14L4gz2ww4FC9nqow== X-Received: by 2002:a7b:c155:: with SMTP id z21mr3112053wmi.137.1565701779904; Tue, 13 Aug 2019 06:09:39 -0700 (PDT) Received: from cbtest32.netronome.com ([217.38.71.146]) by smtp.gmail.com with ESMTPSA id e3sm130534191wrs.37.2019.08.13.06.09.38 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 13 Aug 2019 06:09:38 -0700 (PDT) From: Quentin Monnet To: Alexei Starovoitov , Daniel Borkmann Cc: bpf@vger.kernel.org, netdev@vger.kernel.org, oss-drivers@netronome.com, Quentin Monnet Subject: [RFC bpf-next 3/3] tools: bpftool: add "bpftool map count" to count entries in map Date: Tue, 13 Aug 2019 14:09:21 +0100 Message-Id: <20190813130921.10704-4-quentin.monnet@netronome.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190813130921.10704-1-quentin.monnet@netronome.com> References: <20190813130921.10704-1-quentin.monnet@netronome.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add a "map count" subcommand for counting the number of entries in a map. Because of the variety of BPF map types, it is not entirely clear what counts as an "entry" to dump. We could count all entries for which we have keys; but then for all array derivatives, it would simply come down to printing the maximum number of entries (already accessible through "bpftool map show"). Several map types set errno to ENOENT when they consider there is no value associated to a key, so we could maybe use that... But then there are also some map types that simply reject lookup attempts with EONOTSUPP (xskmap, sock_map, sock_hash): Not being able to lookup a value in such maps does not mean they have no values. Instead of trying to enforce a definition for a "map entry", the selected approach in this patch consists in dumping several counter, and letting the user decide how to interpret them. Values printed are: - Max number of entries - Number of key found - Number of successful lookups - Number of failed lookups, broken down into the most frequent values for errno (ENOENT, EOPNOTSUPP, EINVAL, EPERM). Not all possible values for errno are included (e.g. ENOMEM or EFAULT, for example), they can be added in the future if necessary. Below are some sample output with different types of maps. Array map: # bpftool map count id 11 max entries: 2 keys found: 2 successful lookups: 2 Empty prog_array map: # bpftool map count id 13 max entries: 5 keys found: 5 successful lookups: 0 failed lookups: 5, of which: - errno set to ENOENT: 5 Empty xskmap: # bpftool map count id 14 max entries: 5 keys found: 5 successful lookups: 0 failed lookups: 5, of which: - errno set to EOPNOTSUPP: 5 JSON for the array map: # bpftool map count id 11 { "max_entries": 2, "n_keys": 2, "n_lookup_success": 2, "lookup_failures": { "enoent": 0, "eopnotsupp": 0, "einval": 0, "eperm": 0, } } Queue map containing 3 items: # bpftool map count id 12 failed to get next key, interrupting count: Invalid argument max entries: 5 keys found: 0 successful lookups: 0 Note that counting entries for queue and stack maps is not supported (beyond max_entries), as these types do not support cycling over the keys. This commit also adds relevant documentation and bash completion. Signed-off-by: Quentin Monnet Reviewed-by: Jakub Kicinski --- .../bpf/bpftool/Documentation/bpftool-map.rst | 15 +++ tools/bpf/bpftool/bash-completion/bpftool | 4 +- tools/bpf/bpftool/map.c | 97 ++++++++++++++++++- 3 files changed, 113 insertions(+), 3 deletions(-) diff --git a/tools/bpf/bpftool/Documentation/bpftool-map.rst b/tools/bpf/bpftool/Documentation/bpftool-map.rst index 61d1d270eb5e..ccc19bdd2ca3 100644 --- a/tools/bpf/bpftool/Documentation/bpftool-map.rst +++ b/tools/bpf/bpftool/Documentation/bpftool-map.rst @@ -25,6 +25,7 @@ MAP COMMANDS | **bpftool** **map create** *FILE* **type** *TYPE* **key** *KEY_SIZE* **value** *VALUE_SIZE* \ | **entries** *MAX_ENTRIES* **name** *NAME* [**flags** *FLAGS*] [**dev** *NAME*] | **bpftool** **map dump** *MAP* +| **bpftool** **map count** *MAP* | **bpftool** **map update** *MAP* [**key** *DATA*] [**value** *VALUE*] [*UPDATE_FLAGS*] | **bpftool** **map lookup** *MAP* [**key** *DATA*] | **bpftool** **map getnext** *MAP* [**key** *DATA*] @@ -67,6 +68,20 @@ DESCRIPTION **bpftool map dump** *MAP* Dump all entries in a given *MAP*. + **bpftool map count** *MAP* + Count the number of entries in a given *MAP*. Several values + are printed: the maximum number of entries, the number of + keys found, the number of successful lookups with those keys. + The report for failed lookups is broken down to give values + for the most frequent **errno** values. + + Note that the counters may not be accurate if the map is + being modified (for example by a running BPF program). For + example, if an element gets removed while being dumped, and + then passed in as the "previous key" while cycling over map + keys, the dump will restart and bpftool will count the + entries multiple times. + **bpftool map update** *MAP* [**key** *DATA*] [**value** *VALUE*] [*UPDATE_FLAGS*] Update map entry for a given *KEY*. diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool index df16c5415444..764c88bfe9da 100644 --- a/tools/bpf/bpftool/bash-completion/bpftool +++ b/tools/bpf/bpftool/bash-completion/bpftool @@ -449,7 +449,7 @@ _bpftool() map) local MAP_TYPE='id pinned' case $command in - show|list|dump|peek|pop|dequeue) + show|list|dump|count|peek|pop|dequeue) case $prev in $command) COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) @@ -642,7 +642,7 @@ _bpftool() [[ $prev == $object ]] && \ COMPREPLY=( $( compgen -W 'delete dump getnext help \ lookup pin event_pipe show list update create \ - peek push enqueue pop dequeue' -- \ + peek push enqueue pop dequeue count' -- \ "$cur" ) ) ;; esac diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c index cead639b3ab1..918d08d1676e 100644 --- a/tools/bpf/bpftool/map.c +++ b/tools/bpf/bpftool/map.c @@ -822,6 +822,98 @@ static int do_dump(int argc, char **argv) return err; } +static int do_count(int argc, char **argv) +{ + unsigned int num_keys = 0, num_lookups = 0; + unsigned int err_cnts[1024] = {}; + struct bpf_map_info info = {}; + void *key, *value, *prev_key; + __u32 len = sizeof(info); + int err, fd; + + if (!REQ_ARGS(2)) + return -1; + + fd = map_parse_fd_and_info(&argc, &argv, &info, &len); + if (fd < 0) + return -1; + + key = malloc(info.key_size); + value = alloc_value(&info); + if (!key || !value) { + p_err("mem alloc failed"); + err = -1; + goto exit_free; + } + + prev_key = NULL; + while (true) { + int res; + + err = bpf_map_get_next_key(fd, prev_key, key); + if (err) { + if (errno == ENOENT) + err = 0; + else + p_info("failed to get next key, interrupting count: %s", + strerror(errno)); + break; + } + + num_keys++; + res = bpf_map_lookup_elem(fd, key, value); + if (res) { + if (errno < (int)ARRAY_SIZE(err_cnts)) + err_cnts[errno]++; + } else { + num_lookups++; + } + prev_key = key; + } + + if (json_output) { + jsonw_start_object(json_wtr); /* root */ + jsonw_uint_field(json_wtr, "max_entries", info.max_entries); + jsonw_uint_field(json_wtr, "n_keys", num_keys); + jsonw_uint_field(json_wtr, "n_lookup_success", num_lookups); + jsonw_name(json_wtr, "lookup_failures"); + jsonw_start_object(json_wtr); /* lookup_failures */ + jsonw_uint_field(json_wtr, "enoent", err_cnts[ENOENT]); + jsonw_uint_field(json_wtr, "eopnotsupp", err_cnts[EOPNOTSUPP]); + jsonw_uint_field(json_wtr, "einval", err_cnts[EINVAL]); + jsonw_uint_field(json_wtr, "eperm", err_cnts[EPERM]); + jsonw_end_object(json_wtr); /* lookup_failures */ + jsonw_end_object(json_wtr); /* root */ + } else { + printf("max entries:\t\t%u\n", info.max_entries); + printf("keys found:\t\t%u\n", num_keys); + printf("successful lookups:\t%u\n", num_lookups); + if (num_lookups != num_keys) { + printf("failed lookups:\t%u, of which:\n", + num_keys - num_lookups); + if (err_cnts[ENOENT]) + printf(" - errno set to ENOENT:\t%u\n", + err_cnts[ENOENT]); + if (err_cnts[EOPNOTSUPP]) + printf(" - errno set to EOPNOTSUPP:\t%u\n", + err_cnts[EOPNOTSUPP]); + if (err_cnts[EINVAL]) + printf(" - errno set to EINVAL:\t%u\n", + err_cnts[EINVAL]); + if (err_cnts[EPERM]) + printf(" - errno set to EPERM:\t\t%u\n", + err_cnts[EPERM]); + } + } + +exit_free: + free(key); + free(value); + close(fd); + + return err; +} + static int alloc_key_value(struct bpf_map_info *info, void **key, void **value) { *key = NULL; @@ -1250,6 +1342,7 @@ static int do_help(int argc, char **argv) " entries MAX_ENTRIES name NAME [flags FLAGS] \\\n" " [dev NAME]\n" " %s %s dump MAP\n" + " %s %s count MAP\n" " %s %s update MAP [key DATA] [value VALUE] [UPDATE_FLAGS]\n" " %s %s lookup MAP [key DATA]\n" " %s %s getnext MAP [key DATA]\n" @@ -1279,7 +1372,8 @@ static int do_help(int argc, char **argv) bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], - bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2]); + bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], + bin_name, argv[-2]); return 0; } @@ -1301,6 +1395,7 @@ static const struct cmd cmds[] = { { "enqueue", do_update }, { "pop", do_pop_dequeue }, { "dequeue", do_pop_dequeue }, + { "count", do_count }, { 0 } };