]> git.proxmox.com Git - mirror_iproute2.git/commitdiff
ip: bond: add xstats support
authorNikolay Aleksandrov <nikolay@cumulusnetworks.com>
Tue, 12 Mar 2019 16:41:28 +0000 (18:41 +0200)
committerDavid Ahern <dsahern@gmail.com>
Fri, 15 Mar 2019 20:58:16 +0000 (13:58 -0700)
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 <nikolay@cumulusnetworks.com>
Signed-off-by: David Ahern <dsahern@gmail.com>
ip/ip_common.h
ip/iplink_bond.c
ip/iplink_bond_slave.c

index d67575c63c24b93d268dea47c99fd467e3d7dd08..b4aa34a70c92b9a53e82734105701a444e3a5576 100644 (file)
@@ -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);
index f906e7f1b323239f63162748dbc34b77ef44fbfd..c60f0e8ad0a0d953d3d94e7d9c85e0b44c278e1a 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <linux/if_link.h>
-#include <linux/if_ether.h>
-#include <net/if.h>
+#include <linux/if_bonding.h>
 
 #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,
 };
index 67219c67241be32b718cdfda55b87ef39331a8fc..4eaf72b86f5991581ec858229dddbc0f7c5879ea 100644 (file)
@@ -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,
 };