This patch adds support for a new xstats link subcommand which uses the specified link type's new parse/print_ifla_xstats callbacks to display extended statistics.
Signed-off-by: Nikolay Aleksandrov <niko...@cumulusnetworks.com> --- ip/Makefile | 2 +- ip/ip_common.h | 9 ++++-- ip/iplink.c | 5 ++++ ip/iplink_xstats.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++ man/man8/ip-link.8.in | 12 ++++++++ 5 files changed, 106 insertions(+), 3 deletions(-) create mode 100644 ip/iplink_xstats.c diff --git a/ip/Makefile b/ip/Makefile index 1928489e7f90..4276a34b529e 100644 --- a/ip/Makefile +++ b/ip/Makefile @@ -8,7 +8,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \ link_iptnl.o link_gre6.o iplink_bond.o iplink_bond_slave.o iplink_hsr.o \ iplink_bridge.o iplink_bridge_slave.o ipfou.o iplink_ipvlan.o \ iplink_geneve.o iplink_vrf.o iproute_lwtunnel.o ipmacsec.o ipila.o \ - ipvrf.o + ipvrf.o iplink_xstats.o RTMONOBJ=rtmon.o diff --git a/ip/ip_common.h b/ip/ip_common.h index ab6a83431fd6..071c3db280f2 100644 --- a/ip/ip_common.h +++ b/ip/ip_common.h @@ -61,6 +61,7 @@ int do_ipvrf(int argc, char **argv); void vrf_reset(void); int iplink_get(unsigned int flags, char *name, __u32 filt_mask); +int iplink_ifla_xstats(int argc, char **argv); static inline int rtm_get_table(struct rtmsg *r, struct rtattr **tb) { @@ -84,9 +85,13 @@ struct link_util { void (*print_opt)(struct link_util *, FILE *, struct rtattr *[]); void (*print_xstats)(struct link_util *, FILE *, - struct rtattr *); + struct rtattr *); void (*print_help)(struct link_util *, int, char **, - FILE *); + FILE *); + int (*parse_ifla_xstats)(struct link_util *, + int, char **); + int (*print_ifla_xstats)(const struct sockaddr_nl *, + struct nlmsghdr *, void *); }; struct link_util *get_link_kind(const char *kind); diff --git a/ip/iplink.c b/ip/iplink.c index 2638408c23b8..00fed9006ea6 100644 --- a/ip/iplink.c +++ b/ip/iplink.c @@ -98,6 +98,8 @@ void iplink_usage(void) "\n" " ip link show [ DEVICE | group GROUP ] [up] [master DEV] [vrf NAME] [type TYPE]\n"); + fprintf(stderr, "\n ip link xstats type TYPE [ ARGS ]\n"); + if (iplink_have_newlink()) { fprintf(stderr, "\n" @@ -1411,6 +1413,9 @@ int do_iplink(int argc, char **argv) matches(*argv, "list") == 0) return ipaddr_list_link(argc-1, argv+1); + if (matches(*argv, "xstats") == 0) + return iplink_ifla_xstats(argc-1, argv+1); + if (matches(*argv, "help") == 0) { do_help(argc-1, argv+1); return 0; diff --git a/ip/iplink_xstats.c b/ip/iplink_xstats.c new file mode 100644 index 000000000000..10f953bc4584 --- /dev/null +++ b/ip/iplink_xstats.c @@ -0,0 +1,81 @@ +/* + * iplink_stats.c Extended statistics commands + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Authors: Nikolay Aleksandrov <niko...@cumulusnetworks.com> + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <linux/if_link.h> +#include <netinet/ether.h> + +#include "utils.h" +#include "ip_common.h" + +static void print_explain(FILE *f) +{ + fprintf(f, "Usage: ... xstats type TYPE [ ARGS ]\n"); +} + +int iplink_ifla_xstats(int argc, char **argv) +{ + struct link_util *lu = NULL; + __u32 filt_mask; + + if (!argc) { + fprintf(stderr, "xstats: missing argument\n"); + return -1; + } + + if (matches(*argv, "type") == 0) { + NEXT_ARG(); + lu = get_link_kind(*argv); + if (!lu) + invarg("invalid type", *argv); + } else if (matches(*argv, "help") == 0) { + print_explain(stdout); + return 0; + } else { + invarg("unknown argument", *argv); + } + + if (!lu) { + print_explain(stderr); + return -1; + } + + if (!lu->print_ifla_xstats) { + fprintf(stderr, "xstats: link type %s doesn't support xstats\n", + lu->id); + return -1; + } + + if (lu->parse_ifla_xstats && + lu->parse_ifla_xstats(lu, argc-1, argv+1)) + return -1; + + if (strstr(lu->id, "_slave")) + filt_mask = IFLA_STATS_FILTER_BIT(IFLA_STATS_LINK_XSTATS_SLAVE); + else + filt_mask = IFLA_STATS_FILTER_BIT(IFLA_STATS_LINK_XSTATS); + + if (rtnl_wilddump_stats_req_filter(&rth, AF_UNSPEC, + RTM_GETSTATS, + filt_mask) < 0) { + perror("Cannont send dump request"); + return -1; + } + + if (rtnl_dump_filter(&rth, lu->print_ifla_xstats, stdout) < 0) { + fprintf(stderr, "Dump terminated\n"); + return -1; + } + + return 0; +} diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in index 116034dc620a..2cbdefeb749a 100644 --- a/man/man8/ip-link.8.in +++ b/man/man8/ip-link.8.in @@ -169,6 +169,11 @@ ip-link \- network device configuration .IR NAME " ]" .ti -8 +.B ip link xstats +.BI type " TYPE" +.RI "[ " ARGS " ]" + +.ti -8 .B ip link help .RI "[ " TYPE " ]" @@ -1616,6 +1621,13 @@ interface list by comparing it with the relevant attribute in case the kernel didn't filter already. Therefore any string is accepted, but may lead to empty output. +.SS ip link xstats - display extended statistics + +.TP +.BI type " TYPE " +.I TYPE +specifies the type of devices to display extended statistics for. + .SS ip link help - display help .PP -- 2.1.4