diff options
author | Petr Machata <petrm@nvidia.com> | 2022-04-22 10:30:53 +0200 |
---|---|---|
committer | David Ahern <dsahern@kernel.org> | 2022-04-27 20:12:42 -0600 |
commit | 82f6444f83c76e01870ca9f7779a43cfd81d38d9 (patch) | |
tree | 9bdc90650ca3a56d46a8623ec7372a6a3ff274a9 | |
parent | 54d82b0699a07b1af32a46e229ed37331e38d3a2 (diff) | |
download | iproute2-82f6444f83c76e01870ca9f7779a43cfd81d38d9.tar.gz |
ipstats: Add a "set" command
Add a command to allow toggling HW stats. An example usage:
# ip stats set dev swp1 l3_stats on
Signed-off-by: Petr Machata <petrm@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
-rw-r--r-- | ip/ipstats.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/ip/ipstats.c b/ip/ipstats.c index 099e18a21..1f5b3f774 100644 --- a/ip/ipstats.c +++ b/ip/ipstats.c @@ -1,4 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ +#include <errno.h> + #include "utils.h" #include "ip_common.h" @@ -6,11 +8,85 @@ static int do_help(void) { fprintf(stderr, "Usage: ip stats help\n" + " ip stats set dev DEV l3_stats { on | off }\n" ); return 0; } +static int ipstats_set_do(int ifindex, int at, bool enable) +{ + struct ipstats_req req = { + .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct if_stats_msg)), + .nlh.nlmsg_flags = NLM_F_REQUEST, + .nlh.nlmsg_type = RTM_SETSTATS, + .ifsm.family = PF_UNSPEC, + .ifsm.ifindex = ifindex, + }; + + addattr8(&req.nlh, sizeof(req), at, enable); + + if (rtnl_talk(&rth, &req.nlh, NULL) < 0) + return -2; + return 0; +} + +static int ipstats_set(int argc, char **argv) +{ + const char *dev = NULL; + bool enable = false; + int ifindex; + int at = 0; + + while (argc > 0) { + if (strcmp(*argv, "dev") == 0) { + NEXT_ARG(); + if (dev) + duparg2("dev", *argv); + if (check_ifname(*argv)) + invarg("\"dev\" not a valid ifname", *argv); + dev = *argv; + } else if (strcmp(*argv, "l3_stats") == 0) { + int err; + + NEXT_ARG(); + if (at) { + fprintf(stderr, "A statistics suite to toggle was already given.\n"); + return -EINVAL; + } + at = IFLA_STATS_SET_OFFLOAD_XSTATS_L3_STATS; + enable = parse_on_off("l3_stats", *argv, &err); + if (err) + return err; + } else if (strcmp(*argv, "help") == 0) { + do_help(); + return 0; + } else { + fprintf(stderr, "What is \"%s\"?\n", *argv); + do_help(); + return -EINVAL; + } + + NEXT_ARG_FWD(); + } + + if (!dev) { + fprintf(stderr, "Not enough information: \"dev\" argument is required.\n"); + exit(-1); + } + + if (!at) { + fprintf(stderr, "Not enough information: stat type to toggle is required.\n"); + exit(-1); + } + + ifindex = ll_name_to_index(dev); + if (!ifindex) + return nodev(dev); + + return ipstats_set_do(ifindex, at, enable); +} + int do_ipstats(int argc, char **argv) { int rc; @@ -21,6 +97,8 @@ int do_ipstats(int argc, char **argv) } else if (strcmp(*argv, "help") == 0) { do_help(); rc = 0; + } else if (strcmp(*argv, "set") == 0) { + rc = ipstats_set(argc-1, argv+1); } else { fprintf(stderr, "Command \"%s\" is unknown, try \"ip stats help\".\n", *argv); |