From patchwork Tue Mar 12 16:41:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1055543 X-Patchwork-Delegate: dsahern@gmail.com 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=pass (p=none dis=none) header.from=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.b="ZFUiSoES"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44Jgmx5w9Yz9s6w for ; Wed, 13 Mar 2019 03:44:49 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726781AbfCLQop (ORCPT ); Tue, 12 Mar 2019 12:44:45 -0400 Received: from mail-wm1-f68.google.com ([209.85.128.68]:33806 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726329AbfCLQop (ORCPT ); Tue, 12 Mar 2019 12:44:45 -0400 Received: by mail-wm1-f68.google.com with SMTP id o10so2558319wmc.1 for ; Tue, 12 Mar 2019 09:44:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=GX73gBYQgRNCq9VajW4eN1R/JmQRCAC+k64paQtIlj8=; b=ZFUiSoESYsC0unyM6JhKYdmqPGGRFhVM03AC7IoKvmseqmssLOHjGRcvLE3uk2bXK4 xBMxg6uFlvNFr6ZeuRLV+CqurOiKJpOL1LHWIyT6TzyKIljuP0xe1kep4crB37yzKyZQ gbtmZjxSwWh+AIRBZZS7PLRvj5JMRL57OlXig= 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=GX73gBYQgRNCq9VajW4eN1R/JmQRCAC+k64paQtIlj8=; b=tbYPTV9Dcf1E9V0HCO8NeT60BtJu/idDNCHaEgUHAavdlZrVxXia+g4w19yz6MB5q0 6PqP1ITl7zUv50wuBJcDog+WWN4N+j4NFx6ijRofkIpvPyJrvd6Az3YTM84yiHaRpISe jMjrWUQdM7oPdXs8MBhowcWbKB4DxCEe2asWlPuPQXfKYFYj1ErcsFtYhFjk4Xfx8P2e /KYKqrF27/WvB8SyqkQ7K2vYgV2Pom+e71ya0BkJ0I4tWxUj6a5+7CawbdnLzRGxFo8f NiC/hzcNzz6mQw7ip0h3M2MfrwdLbXyf3lznzVTsRcLLsCWGvNhJ/NyJgVhQRY2ThTVq wIaA== X-Gm-Message-State: APjAAAVNksOjZv7ULv8I2yfmNswvginQ9CxS7xEciiVA98RrXSAMOCNT 3kyqEhcrbMb7D9Qb9gsLT+QMWzHN2kI= X-Google-Smtp-Source: APXvYqyRKWJ/3lZVyJ4uqLA/fTELE2AH80SUKr6IQ3usDmO6e6HD2eduSup1XCc2WWrWgg5DQTEybg== X-Received: by 2002:a7b:c752:: with SMTP id w18mr3196803wmk.97.1552409083128; Tue, 12 Mar 2019 09:44:43 -0700 (PDT) Received: from localhost.localdomain ([93.152.141.58]) by smtp.gmail.com with ESMTPSA id b195sm5634864wmg.36.2019.03.12.09.44.42 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 12 Mar 2019 09:44:42 -0700 (PDT) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@cumulusnetworks.com, dsa@cumulusnetworks.com, stephen@networkplumber.org, Nikolay Aleksandrov Subject: [PATCH iproute2-next 1/3] ip: xstats: add json output support Date: Tue, 12 Mar 2019 18:41:26 +0200 Message-Id: <20190312164128.22536-2-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.17.2 In-Reply-To: <20190312164128.22536-1-nikolay@cumulusnetworks.com> References: <20190312164128.22536-1-nikolay@cumulusnetworks.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This adds only initial object support if json argument is specified. Later patches convert the current xstats users to json. Signed-off-by: Nikolay Aleksandrov --- ip/iplink_xstats.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ip/iplink_xstats.c b/ip/iplink_xstats.c index 908d9228369f..c64e6885678c 100644 --- a/ip/iplink_xstats.c +++ b/ip/iplink_xstats.c @@ -70,10 +70,13 @@ int iplink_ifla_xstats(int argc, char **argv) return -1; } + new_json_obj(json); if (rtnl_dump_filter(&rth, lu->print_ifla_xstats, stdout) < 0) { + delete_json_obj(); fprintf(stderr, "Dump terminated\n"); return -1; } + delete_json_obj(); return 0; } From patchwork Tue Mar 12 16:41:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1055544 X-Patchwork-Delegate: dsahern@gmail.com 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=pass (p=none dis=none) header.from=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.b="ZzzRhaSS"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44Jgmy4nPCz9s5c for ; Wed, 13 Mar 2019 03:44:50 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726813AbfCLQos (ORCPT ); Tue, 12 Mar 2019 12:44:48 -0400 Received: from mail-wr1-f67.google.com ([209.85.221.67]:44023 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726329AbfCLQor (ORCPT ); Tue, 12 Mar 2019 12:44:47 -0400 Received: by mail-wr1-f67.google.com with SMTP id d17so3443401wre.10 for ; Tue, 12 Mar 2019 09:44:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=9hiXh6N+0bVJ6vwaJrBSIyLFAX5MSuXdYQLQtfuNYSU=; b=ZzzRhaSSMkaMEX+aU1eJYdmfNqdmo6LCzDpPDV/NkKXFCD1jRCfpy2nw/WS9Ec8JKx Sa5nDbMcjrTBADigDq4wHrkX5Qfn+vzFJtZHVO+r1UPJ3KfZs+0SFJeuSfGrT7bh1w5/ iRk+A8X90aJtQMbceM0D6q6IF7FwpLPVZ5tKw= 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=9hiXh6N+0bVJ6vwaJrBSIyLFAX5MSuXdYQLQtfuNYSU=; b=VV2NJydQ1PamShkYykBuA1cC1zVatSuQ1SIzM1BG+xIQX5Qv8yVG3CfKYwHvoaTjzP 0EuKNNEMx1f0VCJRP3W5k2LRrJ4U6xkSOWVp/bp34q8cB/I3NHYQ3fdVuxTkCJPHMoFE ZAlIdkUfPGTn1Fb5hj5Pcg0gfyB01pIQLcMbXMpEaXzFLLET3GGHlk4Shn0lwntkw298 HkuJTRTAlgtCozFhSBNBDfqSyF90SBMGbe+YHHycL+u7IzinqUq6Q8VFfmjszxawFImZ ggw/5LNfJq43y8m2hohWW9GOurXOpJ7dwkjBt7VtssKawjJ0E9/V18WQNrOH6lEDq4XC 5BXw== X-Gm-Message-State: APjAAAVsnugsQs71/omNbCWHG+Q/vF2AeHUVVD8TA2q6XuXP9jnshUfA ml8dbJ5FvAIQ+cYFISApUBhUbjAVPTk= X-Google-Smtp-Source: APXvYqxShag2X5hUi6GpluHH/I2/DrsAbwafOLC2yjU5oKQwXdXrlaDgj5XdbW0VJ54Hr3MRvHO2PQ== X-Received: by 2002:a5d:6b46:: with SMTP id x6mr15361472wrw.94.1552409085029; Tue, 12 Mar 2019 09:44:45 -0700 (PDT) Received: from localhost.localdomain ([93.152.141.58]) by smtp.gmail.com with ESMTPSA id b195sm5634864wmg.36.2019.03.12.09.44.43 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 12 Mar 2019 09:44:43 -0700 (PDT) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@cumulusnetworks.com, dsa@cumulusnetworks.com, stephen@networkplumber.org, Nikolay Aleksandrov Subject: [PATCH iproute2-next 2/3] ip: bridge: add xstats json support Date: Tue, 12 Mar 2019 18:41:27 +0200 Message-Id: <20190312164128.22536-3-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.17.2 In-Reply-To: <20190312164128.22536-1-nikolay@cumulusnetworks.com> References: <20190312164128.22536-1-nikolay@cumulusnetworks.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add json support for bridge's xstats output. The plain text output format should remain the same. Note that this patch pulls the interface out of the attribute loop, this was an oversight when the set was upstreamed. This does not change the output format, but fixes it when new xstats attributes show up. Example: $ ip -p -j link xstats type bridge [ { "ifname": "br0", "multicast": { "igmp_queries": { "rx_v1": 0, "rx_v2": 32, "rx_v3": 0, "tx_v1": 0, "tx_v2": 0, "tx_v3": 0 }, "igmp_reports": { "rx_v1": 0, "rx_v2": 32, "rx_v3": 0, "tx_v1": 0, "tx_v2": 0, "tx_v3": 0 }, "igmp_leaves": { "rx": 0, "tx": 0 }, "igmp_parse_errors": 0, "mld_queries": { "rx_v1": 33, "rx_v2": 0, "tx_v1": 0, "tx_v2": 0 }, "mld_reports": { "rx_v1": 66, "rx_v2": 2, "tx_v1": 0, "tx_v2": 0 }, "mld_leaves": { "rx": 0, "tx": 0 }, "mld_parse_errors": 0 } } ] Signed-off-by: Nikolay Aleksandrov --- ip/iplink_bridge.c | 169 ++++++++++++++++++++++++++++----------------- 1 file changed, 104 insertions(+), 65 deletions(-) diff --git a/ip/iplink_bridge.c b/ip/iplink_bridge.c index fbf8a79bfbbb..e9b77fdfe377 100644 --- a/ip/iplink_bridge.c +++ b/ip/iplink_bridge.c @@ -670,7 +670,7 @@ static void bridge_print_xstats_help(struct link_util *lu, FILE *f) fprintf(f, "Usage: ... %s [ igmp ] [ dev DEVICE ]\n", lu->id); } -static void bridge_print_stats_attr(FILE *f, struct rtattr *attr, int ifindex) +static void bridge_print_stats_attr(struct rtattr *attr, int ifindex) { struct rtattr *brtb[LINK_XSTATS_TYPE_MAX+1]; struct br_mcast_stats *mstats; @@ -685,76 +685,116 @@ static void bridge_print_stats_attr(FILE *f, struct rtattr *attr, int ifindex) list = brtb[LINK_XSTATS_TYPE_BRIDGE]; rem = RTA_PAYLOAD(list); + open_json_object(NULL); + ifname = ll_index_to_name(ifindex); + print_string(PRINT_ANY, "ifname", "%-16s\n", ifname); for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) { if (xstats_print_attr && i->rta_type != xstats_print_attr) continue; switch (i->rta_type) { case BRIDGE_XSTATS_MCAST: mstats = RTA_DATA(i); - ifname = ll_index_to_name(ifindex); - fprintf(f, "%-16s\n", ifname); - fprintf(f, "%-16s IGMP queries:\n", ""); - fprintf(f, "%-16s RX: v1 %llu v2 %llu v3 %llu\n", - "", - mstats->igmp_v1queries[BR_MCAST_DIR_RX], - mstats->igmp_v2queries[BR_MCAST_DIR_RX], - mstats->igmp_v3queries[BR_MCAST_DIR_RX]); - fprintf(f, "%-16s TX: v1 %llu v2 %llu v3 %llu\n", - "", - mstats->igmp_v1queries[BR_MCAST_DIR_TX], - mstats->igmp_v2queries[BR_MCAST_DIR_TX], - mstats->igmp_v3queries[BR_MCAST_DIR_TX]); - - fprintf(f, "%-16s IGMP reports:\n", ""); - fprintf(f, "%-16s RX: v1 %llu v2 %llu v3 %llu\n", - "", - mstats->igmp_v1reports[BR_MCAST_DIR_RX], - mstats->igmp_v2reports[BR_MCAST_DIR_RX], - mstats->igmp_v3reports[BR_MCAST_DIR_RX]); - fprintf(f, "%-16s TX: v1 %llu v2 %llu v3 %llu\n", - "", - mstats->igmp_v1reports[BR_MCAST_DIR_TX], - mstats->igmp_v2reports[BR_MCAST_DIR_TX], - mstats->igmp_v3reports[BR_MCAST_DIR_TX]); - - fprintf(f, "%-16s IGMP leaves: RX: %llu TX: %llu\n", - "", - mstats->igmp_leaves[BR_MCAST_DIR_RX], - mstats->igmp_leaves[BR_MCAST_DIR_TX]); - - fprintf(f, "%-16s IGMP parse errors: %llu\n", - "", mstats->igmp_parse_errors); - - fprintf(f, "%-16s MLD queries:\n", ""); - fprintf(f, "%-16s RX: v1 %llu v2 %llu\n", - "", - mstats->mld_v1queries[BR_MCAST_DIR_RX], - mstats->mld_v2queries[BR_MCAST_DIR_RX]); - fprintf(f, "%-16s TX: v1 %llu v2 %llu\n", - "", - mstats->mld_v1queries[BR_MCAST_DIR_TX], - mstats->mld_v2queries[BR_MCAST_DIR_TX]); - - fprintf(f, "%-16s MLD reports:\n", ""); - fprintf(f, "%-16s RX: v1 %llu v2 %llu\n", - "", - mstats->mld_v1reports[BR_MCAST_DIR_RX], - mstats->mld_v2reports[BR_MCAST_DIR_RX]); - fprintf(f, "%-16s TX: v1 %llu v2 %llu\n", - "", - mstats->mld_v1reports[BR_MCAST_DIR_TX], - mstats->mld_v2reports[BR_MCAST_DIR_TX]); - - fprintf(f, "%-16s MLD leaves: RX: %llu TX: %llu\n", - "", - mstats->mld_leaves[BR_MCAST_DIR_RX], - mstats->mld_leaves[BR_MCAST_DIR_TX]); - - fprintf(f, "%-16s MLD parse errors: %llu\n", - "", mstats->mld_parse_errors); + open_json_object("multicast"); + open_json_object("igmp_queries"); + print_string(PRINT_FP, NULL, + "%-16s IGMP queries:\n", ""); + print_string(PRINT_FP, NULL, "%-16s ", ""); + print_u64(PRINT_ANY, "rx_v1", "RX: v1 %llu ", + mstats->igmp_v1queries[BR_MCAST_DIR_RX]); + print_u64(PRINT_ANY, "rx_v2", "v2 %llu ", + mstats->igmp_v2queries[BR_MCAST_DIR_RX]); + print_u64(PRINT_ANY, "rx_v3", "v3 %llu\n", + mstats->igmp_v3queries[BR_MCAST_DIR_RX]); + print_string(PRINT_FP, NULL, "%-16s ", ""); + print_u64(PRINT_ANY, "tx_v1", "TX: v1 %llu ", + mstats->igmp_v1queries[BR_MCAST_DIR_TX]); + print_u64(PRINT_ANY, "tx_v2", "v2 %llu ", + mstats->igmp_v2queries[BR_MCAST_DIR_TX]); + print_u64(PRINT_ANY, "tx_v3", "v3 %llu\n", + mstats->igmp_v3queries[BR_MCAST_DIR_TX]); + close_json_object(); + + open_json_object("igmp_reports"); + print_string(PRINT_FP, NULL, + "%-16s IGMP reports:\n", ""); + print_string(PRINT_FP, NULL, "%-16s ", ""); + print_u64(PRINT_ANY, "rx_v1", "RX: v1 %llu ", + mstats->igmp_v1reports[BR_MCAST_DIR_RX]); + print_u64(PRINT_ANY, "rx_v2", "v2 %llu ", + mstats->igmp_v2reports[BR_MCAST_DIR_RX]); + print_u64(PRINT_ANY, "rx_v3", "v3 %llu\n", + mstats->igmp_v3reports[BR_MCAST_DIR_RX]); + print_string(PRINT_FP, NULL, "%-16s ", ""); + print_u64(PRINT_ANY, "tx_v1", "TX: v1 %llu ", + mstats->igmp_v1reports[BR_MCAST_DIR_TX]); + print_u64(PRINT_ANY, "tx_v2", "v2 %llu", + mstats->igmp_v2reports[BR_MCAST_DIR_TX]); + print_u64(PRINT_ANY, "tx_v3", "v3 %llu\n", + mstats->igmp_v3reports[BR_MCAST_DIR_TX]); + close_json_object(); + + open_json_object("igmp_leaves"); + print_string(PRINT_FP, NULL, + "%-16s IGMP leaves: ", ""); + print_u64(PRINT_ANY, "rx", "RX: %llu ", + mstats->igmp_leaves[BR_MCAST_DIR_RX]); + print_u64(PRINT_ANY, "tx", "TX: %llu\n", + mstats->igmp_leaves[BR_MCAST_DIR_TX]); + close_json_object(); + + print_string(PRINT_FP, NULL, + "%-16s IGMP parse errors: ", ""); + print_u64(PRINT_ANY, "igmp_parse_errors", "%llu\n", + mstats->igmp_parse_errors); + + open_json_object("mld_queries"); + print_string(PRINT_FP, NULL, + "%-16s MLD queries:\n", ""); + print_string(PRINT_FP, NULL, "%-16s ", ""); + print_u64(PRINT_ANY, "rx_v1", "RX: v1 %llu ", + mstats->mld_v1queries[BR_MCAST_DIR_RX]); + print_u64(PRINT_ANY, "rx_v2", "v2 %llu\n", + mstats->mld_v2queries[BR_MCAST_DIR_RX]); + print_string(PRINT_FP, NULL, "%-16s ", ""); + print_u64(PRINT_ANY, "tx_v1", "TX: v1 %llu ", + mstats->mld_v1queries[BR_MCAST_DIR_TX]); + print_u64(PRINT_ANY, "tx_v2", "v2 %llu\n", + mstats->mld_v2queries[BR_MCAST_DIR_TX]); + close_json_object(); + + open_json_object("mld_reports"); + print_string(PRINT_FP, NULL, + "%-16s MLD reports:\n", ""); + print_string(PRINT_FP, NULL, "%-16s ", ""); + print_u64(PRINT_ANY, "rx_v1", "RX: v1 %llu ", + mstats->mld_v1reports[BR_MCAST_DIR_RX]); + print_u64(PRINT_ANY, "rx_v2", "v2 %llu\n", + mstats->mld_v2reports[BR_MCAST_DIR_RX]); + print_string(PRINT_FP, NULL, "%-16s ", ""); + print_u64(PRINT_ANY, "tx_v1", "TX: v1 %llu ", + mstats->mld_v1reports[BR_MCAST_DIR_TX]); + print_u64(PRINT_ANY, "tx_v2", "v2 %llu\n", + mstats->mld_v2reports[BR_MCAST_DIR_TX]); + close_json_object(); + + open_json_object("mld_leaves"); + print_string(PRINT_FP, NULL, + "%-16s MLD leaves: ", ""); + print_u64(PRINT_ANY, "rx", "RX: %llu ", + mstats->mld_leaves[BR_MCAST_DIR_RX]); + print_u64(PRINT_ANY, "tx", "TX: %llu\n", + mstats->mld_leaves[BR_MCAST_DIR_TX]); + close_json_object(); + + print_string(PRINT_FP, NULL, + "%-16s MLD parse errors: ", ""); + print_u64(PRINT_ANY, "mld_parse_errors", "%llu\n", + mstats->mld_parse_errors); + close_json_object(); break; } } + close_json_object(); } int bridge_print_xstats(struct nlmsghdr *n, void *arg) @@ -762,7 +802,6 @@ int bridge_print_xstats(struct nlmsghdr *n, void *arg) struct if_stats_msg *ifsm = NLMSG_DATA(n); struct rtattr *tb[IFLA_STATS_MAX+1]; int len = n->nlmsg_len; - FILE *fp = arg; len -= NLMSG_LENGTH(sizeof(*ifsm)); if (len < 0) { @@ -774,11 +813,11 @@ int bridge_print_xstats(struct nlmsghdr *n, void *arg) parse_rtattr(tb, IFLA_STATS_MAX, IFLA_STATS_RTA(ifsm), len); if (tb[IFLA_STATS_LINK_XSTATS]) - bridge_print_stats_attr(fp, tb[IFLA_STATS_LINK_XSTATS], + bridge_print_stats_attr(tb[IFLA_STATS_LINK_XSTATS], ifsm->ifindex); if (tb[IFLA_STATS_LINK_XSTATS_SLAVE]) - bridge_print_stats_attr(fp, tb[IFLA_STATS_LINK_XSTATS_SLAVE], + bridge_print_stats_attr(tb[IFLA_STATS_LINK_XSTATS_SLAVE], ifsm->ifindex); return 0; From patchwork Tue Mar 12 16:41:28 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1055545 X-Patchwork-Delegate: dsahern@gmail.com 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=pass (p=none dis=none) header.from=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.b="RjYNr4fu"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44Jgn02Bp2z9s5c for ; Wed, 13 Mar 2019 03:44:52 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726832AbfCLQov (ORCPT ); Tue, 12 Mar 2019 12:44:51 -0400 Received: from mail-wr1-f68.google.com ([209.85.221.68]:46128 "EHLO mail-wr1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726512AbfCLQot (ORCPT ); Tue, 12 Mar 2019 12:44:49 -0400 Received: by mail-wr1-f68.google.com with SMTP id 33so957376wrb.13 for ; Tue, 12 Mar 2019 09:44:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=4b08YIs5Xng5lqaGlS7OJKfvE3bnZL3WoMo4VtBH+JA=; b=RjYNr4fu/vuTbfeT2tsDxNQtSj0aWBd9eoh3ERdgyWLk4Fwg4Y9qiMhJHtezMp8K3y JXkyLCwSrswQXfTe0+gR1Q1voUdvvwPJNmxju6HR5t4eccnp4zRHsCww3A+GaL+OfMKa Qo5+lxNFEOixkqF1cL+P2DCepkqUoVEM5tIIM= 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=4b08YIs5Xng5lqaGlS7OJKfvE3bnZL3WoMo4VtBH+JA=; b=sIIWlQk9waxn6zGvfxzvkV/c5YoiO+jf3o1ex5dsOJq0w+VucNzfzTXVCUk5zpIQL6 9pGPTdv29xCHmDmLkTYojBOPnoApEm5/7fHxVvxXFjGcVlOYRHJ3WLk2jN+gv3HBj8RZ KseBtJfx9Y3iV/kPxTXTa2/dcoNwEw39/70VBJD298b51ysJIhV/ML/pyn2ihZPiV45f hHHKdUQNFWkEBfacSHS7CJKx35zcd86PH2U8tSWGvqqonEmxRReJ+dIcGC18PtCu8BbX 65viCU7OC/RPzHdn23zCvfCYOs5MIp9R8y7yg9EQfLI63GyKT0i+4h7QkRF43NnXtcmA cwyA== X-Gm-Message-State: APjAAAWeM32x1qpfngsZQI5wm0YaDwFFMHNgVvCqlNxQ/9SWDEINp6W6 PvnhIfc7USAreac5rDqSb0VMKNj6p9Q= X-Google-Smtp-Source: APXvYqzWy4fjpjwlMWyz7eu6QtgjayyEAHc24Bn0CkZ3kOMONJ1rLnqXVMKtDWNnn5Ivy5X1nkxq2w== X-Received: by 2002:adf:a749:: with SMTP id e9mr23369801wrd.210.1552409086438; Tue, 12 Mar 2019 09:44:46 -0700 (PDT) Received: from localhost.localdomain ([93.152.141.58]) by smtp.gmail.com with ESMTPSA id b195sm5634864wmg.36.2019.03.12.09.44.45 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 12 Mar 2019 09:44:45 -0700 (PDT) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@cumulusnetworks.com, dsa@cumulusnetworks.com, stephen@networkplumber.org, Nikolay Aleksandrov Subject: [PATCH iproute2-next 3/3] ip: bond: add xstats support Date: Tue, 12 Mar 2019 18:41:28 +0200 Message-Id: <20190312164128.22536-4-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.17.2 In-Reply-To: <20190312164128.22536-1-nikolay@cumulusnetworks.com> References: <20190312164128.22536-1-nikolay@cumulusnetworks.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add bond and bond_slave xstats support with optional json output. Example: - Plain text: $ ip link xstats type bond 802.3ad bond0 LACPDU Rx 2017 LACPDU Tx 2038 LACPDU Unknown type Rx 0 LACPDU Illegal Rx 0 Marker Rx 0 Marker Tx 0 Marker response Rx 0 Marker response Tx 0 Marker unknown type Rx 0 - JSON: $ ip -j -p link xstats type bond 802.3ad [ { "ifname": "bond0", "802.3ad": { "lacpdu_rx": 219, "lacpdu_tx": 241, "lacpdu_unknown_rx": 0, "lacpdu_illegal_rx": 0, "marker_rx": 0, "marker_tx": 0, "marker_response_rx": 0, "marker_response_tx": 0, "marker_unknown_rx": 0 } } ] Signed-off-by: Nikolay Aleksandrov --- ip/ip_common.h | 3 + ip/iplink_bond.c | 167 ++++++++++++++++++++++++++++++++++++++++- ip/iplink_bond_slave.c | 2 + 3 files changed, 169 insertions(+), 3 deletions(-) diff --git a/ip/ip_common.h b/ip/ip_common.h index d67575c63c24..b4aa34a70c92 100644 --- a/ip/ip_common.h +++ b/ip/ip_common.h @@ -130,6 +130,9 @@ void br_dump_bridge_id(const struct ifla_bridge_id *id, char *buf, size_t len); int bridge_parse_xstats(struct link_util *lu, int argc, char **argv); int bridge_print_xstats(struct nlmsghdr *n, void *arg); +int bond_parse_xstats(struct link_util *lu, int argc, char **argv); +int bond_print_xstats(struct nlmsghdr *n, void *arg); + /* iproute_lwtunnel.c */ int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp); void lwt_print_encap(FILE *fp, struct rtattr *encap_type, struct rtattr *encap); diff --git a/ip/iplink_bond.c b/ip/iplink_bond.c index f906e7f1b323..c60f0e8ad0a0 100644 --- a/ip/iplink_bond.c +++ b/ip/iplink_bond.c @@ -13,16 +13,18 @@ #include #include #include -#include -#include -#include +#include #include "rt_names.h" #include "utils.h" #include "ip_common.h" +#include "json_print.h" #define BOND_MAX_ARP_TARGETS 16 +static unsigned int xstats_print_attr; +static int filter_index; + static const char *mode_tbl[] = { "balance-rr", "active-backup", @@ -649,10 +651,169 @@ static void bond_print_help(struct link_util *lu, int argc, char **argv, print_explain(f); } +static void bond_print_xstats_help(struct link_util *lu, FILE *f) +{ + fprintf(f, "Usage: ... %s [ 802.3ad ] [ dev DEVICE ]\n", lu->id); +} + +static void bond_print_3ad_stats(struct rtattr *lacpattr) +{ + struct rtattr *lacptb[BOND_3AD_STAT_MAX+1]; + __u64 val; + + parse_rtattr(lacptb, BOND_3AD_STAT_MAX, RTA_DATA(lacpattr), + RTA_PAYLOAD(lacpattr)); + open_json_object("802.3ad"); + if (lacptb[BOND_3AD_STAT_LACPDU_RX]) { + print_string(PRINT_FP, NULL, "%-16s ", ""); + print_u64(PRINT_ANY, "lacpdu_rx", "LACPDU Rx %llu\n", + rta_getattr_u64(lacptb[BOND_3AD_STAT_LACPDU_RX])); + } + if (lacptb[BOND_3AD_STAT_LACPDU_TX]) { + print_string(PRINT_FP, NULL, "%-16s ", ""); + print_u64(PRINT_ANY, "lacpdu_tx", "LACPDU Tx %llu\n", + rta_getattr_u64(lacptb[BOND_3AD_STAT_LACPDU_TX])); + } + if (lacptb[BOND_3AD_STAT_LACPDU_UNKNOWN_RX]) { + print_string(PRINT_FP, NULL, "%-16s ", ""); + val = rta_getattr_u64(lacptb[BOND_3AD_STAT_LACPDU_UNKNOWN_RX]); + print_u64(PRINT_ANY, + "lacpdu_unknown_rx", + "LACPDU Unknown type Rx %llu\n", + val); + } + if (lacptb[BOND_3AD_STAT_LACPDU_ILLEGAL_RX]) { + print_string(PRINT_FP, NULL, "%-16s ", ""); + val = rta_getattr_u64(lacptb[BOND_3AD_STAT_LACPDU_ILLEGAL_RX]); + print_u64(PRINT_ANY, + "lacpdu_illegal_rx", + "LACPDU Illegal Rx %llu\n", + val); + } + if (lacptb[BOND_3AD_STAT_MARKER_RX]) { + print_string(PRINT_FP, NULL, "%-16s ", ""); + print_u64(PRINT_ANY, "marker_rx", "Marker Rx %llu\n", + rta_getattr_u64(lacptb[BOND_3AD_STAT_MARKER_RX])); + } + if (lacptb[BOND_3AD_STAT_MARKER_TX]) { + print_string(PRINT_FP, NULL, "%-16s ", ""); + print_u64(PRINT_ANY, "marker_tx", "Marker Tx %llu\n", + rta_getattr_u64(lacptb[BOND_3AD_STAT_MARKER_TX])); + } + if (lacptb[BOND_3AD_STAT_MARKER_RESP_RX]) { + print_string(PRINT_FP, NULL, "%-16s ", ""); + val = rta_getattr_u64(lacptb[BOND_3AD_STAT_MARKER_RESP_RX]); + print_u64(PRINT_ANY, + "marker_response_rx", + "Marker response Rx %llu\n", + val); + } + if (lacptb[BOND_3AD_STAT_MARKER_RESP_TX]) { + print_string(PRINT_FP, NULL, "%-16s ", ""); + val = rta_getattr_u64(lacptb[BOND_3AD_STAT_MARKER_RESP_TX]); + print_u64(PRINT_ANY, + "marker_response_tx", + "Marker response Tx %llu\n", + val); + } + if (lacptb[BOND_3AD_STAT_MARKER_UNKNOWN_RX]) { + print_string(PRINT_FP, NULL, "%-16s ", ""); + val = rta_getattr_u64(lacptb[BOND_3AD_STAT_MARKER_UNKNOWN_RX]); + print_u64(PRINT_ANY, + "marker_unknown_rx", + "Marker unknown type Rx %llu\n", + val); + } + close_json_object(); +} + +static void bond_print_stats_attr(struct rtattr *attr, int ifindex) +{ + struct rtattr *bondtb[LINK_XSTATS_TYPE_MAX+1]; + struct rtattr *i, *list; + const char *ifname = ""; + int rem; + + parse_rtattr(bondtb, LINK_XSTATS_TYPE_MAX+1, RTA_DATA(attr), + RTA_PAYLOAD(attr)); + if (!bondtb[LINK_XSTATS_TYPE_BOND]) + return; + + list = bondtb[LINK_XSTATS_TYPE_BOND]; + rem = RTA_PAYLOAD(list); + open_json_object(NULL); + ifname = ll_index_to_name(ifindex); + print_string(PRINT_ANY, "ifname", "%-16s\n", ifname); + for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) { + if (xstats_print_attr && i->rta_type != xstats_print_attr) + continue; + + switch (i->rta_type) { + case BOND_XSTATS_3AD: + bond_print_3ad_stats(i); + break; + } + break; + } + close_json_object(); +} + +int bond_print_xstats(struct nlmsghdr *n, void *arg) +{ + struct if_stats_msg *ifsm = NLMSG_DATA(n); + struct rtattr *tb[IFLA_STATS_MAX+1]; + int len = n->nlmsg_len; + + len -= NLMSG_LENGTH(sizeof(*ifsm)); + if (len < 0) { + fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); + return -1; + } + if (filter_index && filter_index != ifsm->ifindex) + return 0; + + parse_rtattr(tb, IFLA_STATS_MAX, IFLA_STATS_RTA(ifsm), len); + if (tb[IFLA_STATS_LINK_XSTATS]) + bond_print_stats_attr(tb[IFLA_STATS_LINK_XSTATS], + ifsm->ifindex); + + if (tb[IFLA_STATS_LINK_XSTATS_SLAVE]) + bond_print_stats_attr(tb[IFLA_STATS_LINK_XSTATS_SLAVE], + ifsm->ifindex); + + return 0; +} + +int bond_parse_xstats(struct link_util *lu, int argc, char **argv) +{ + while (argc > 0) { + if (strcmp(*argv, "lacp") == 0 || + strcmp(*argv, "802.3ad") == 0) { + xstats_print_attr = BOND_XSTATS_3AD; + } else if (strcmp(*argv, "dev") == 0) { + NEXT_ARG(); + filter_index = ll_name_to_index(*argv); + if (!filter_index) + return nodev(*argv); + } else if (strcmp(*argv, "help") == 0) { + bond_print_xstats_help(lu, stdout); + exit(0); + } else { + invarg("unknown attribute", *argv); + } + argc--; argv++; + } + + return 0; +} + + struct link_util bond_link_util = { .id = "bond", .maxattr = IFLA_BOND_MAX, .parse_opt = bond_parse_opt, .print_opt = bond_print_opt, .print_help = bond_print_help, + .parse_ifla_xstats = bond_parse_xstats, + .print_ifla_xstats = bond_print_xstats, }; diff --git a/ip/iplink_bond_slave.c b/ip/iplink_bond_slave.c index 67219c67241b..4eaf72b86f59 100644 --- a/ip/iplink_bond_slave.c +++ b/ip/iplink_bond_slave.c @@ -156,4 +156,6 @@ struct link_util bond_slave_link_util = { .print_opt = bond_slave_print_opt, .parse_opt = bond_slave_parse_opt, .print_help = bond_slave_print_help, + .parse_ifla_xstats = bond_parse_xstats, + .print_ifla_xstats = bond_print_xstats, };