]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
ip: Introduce get_rtnl_link_stats_rta() to get link statistics
authorSerhey Popovych <serhe.popovych@gmail.com>
Wed, 7 Feb 2018 06:30:52 +0000 (08:30 +0200)
committerDavid Ahern <dsahern@gmail.com>
Thu, 8 Feb 2018 00:15:28 +0000 (16:15 -0800)
Assume all statistics in ip(8) represented either by IFLA_STATS64 or
IFLA_STATS is 64 bit. It is clean that we can store __u32 counters of
@struct rtnl_link_stats in __u64 counters in @struct rtnl_link_stats64.

New get_rtnl_link_stats_rta() follows __print_link_stats() behaviour on
handling of stats attribute: copy no more than size of data structure
and no less than attribute length zeroing rest.

Drop print_link_stats32() as it's functionality can be handled by 64bit
variant. Move code from __print_link_stats() to print_link_stats64() and
finally rename print_link_stats64() to __print_link_stats().

More users of introduced function will come in future.

Signed-off-by: Serhey Popovych <serhe.popovych@gmail.com>
Signed-off-by: David Ahern <dsahern@gmail.com>
include/utils.h
ip/ipaddress.c
lib/utils.c

index f81928abe78ce45e8da0c9f7a4ddb1ca8c59c279..8b8ee2e55ab8657bbd898064f8fda6b1070aef54 100644 (file)
@@ -284,6 +284,9 @@ int make_path(const char *path, mode_t mode);
 char *find_cgroup2_mount(void);
 int get_command_name(const char *pid, char *comm, size_t len);
 
+int get_rtnl_link_stats_rta(struct rtnl_link_stats64 *stats64,
+                           struct rtattr *tb[]);
+
 #ifdef NEED_STRLCPY
 size_t strlcpy(char *dst, const char *src, size_t size);
 size_t strlcat(char *dst, const char *src, size_t size);
index a80a385c1f7cae7768a961205f26e706f3b154eb..6990b81560f270514f220179419f9a811892430f 100644 (file)
@@ -593,152 +593,18 @@ static void print_vf_stats64(FILE *fp, struct rtattr *vfstats)
        }
 }
 
-static void print_link_stats64(FILE *fp, const struct rtnl_link_stats64 *s,
-                              const struct rtattr *carrier_changes)
+static void __print_link_stats(FILE *fp, struct rtattr *tb[])
 {
-       if (is_json_context()) {
-               open_json_object("stats64");
-
-               /* RX stats */
-               open_json_object("rx");
-               print_uint(PRINT_JSON, "bytes", NULL, s->rx_bytes);
-               print_uint(PRINT_JSON, "packets", NULL, s->rx_packets);
-               print_uint(PRINT_JSON, "errors", NULL, s->rx_errors);
-               print_uint(PRINT_JSON, "dropped", NULL, s->rx_dropped);
-               print_uint(PRINT_JSON, "over_errors", NULL, s->rx_over_errors);
-               print_uint(PRINT_JSON, "multicast", NULL, s->multicast);
-               if (s->rx_compressed)
-                       print_uint(PRINT_JSON,
-                                  "compressed", NULL, s->rx_compressed);
-
-               /* RX error stats */
-               if (show_stats > 1) {
-                       print_uint(PRINT_JSON,
-                                  "length_errors",
-                                  NULL, s->rx_length_errors);
-                       print_uint(PRINT_JSON,
-                                  "crc_errors",
-                                  NULL, s->rx_crc_errors);
-                       print_uint(PRINT_JSON,
-                                  "frame_errors",
-                                  NULL, s->rx_frame_errors);
-                       print_uint(PRINT_JSON,
-                                  "fifo_errors",
-                                  NULL, s->rx_fifo_errors);
-                       print_uint(PRINT_JSON,
-                                  "missed_errors",
-                                  NULL, s->rx_missed_errors);
-                       if (s->rx_nohandler)
-                               print_uint(PRINT_JSON,
-                                          "nohandler", NULL, s->rx_nohandler);
-               }
-               close_json_object();
-
-               /* TX stats */
-               open_json_object("tx");
-               print_uint(PRINT_JSON, "bytes", NULL, s->tx_bytes);
-               print_uint(PRINT_JSON, "packets", NULL, s->tx_packets);
-               print_uint(PRINT_JSON, "errors", NULL, s->tx_errors);
-               print_uint(PRINT_JSON, "dropped", NULL, s->tx_dropped);
-               print_uint(PRINT_JSON,
-                          "carrier_errors",
-                          NULL, s->tx_carrier_errors);
-               print_uint(PRINT_JSON, "collisions", NULL, s->collisions);
-               if (s->tx_compressed)
-                       print_uint(PRINT_JSON,
-                                  "compressed", NULL, s->tx_compressed);
-
-               /* TX error stats */
-               if (show_stats > 1) {
-                       print_uint(PRINT_JSON,
-                                  "aborted_errors",
-                                  NULL, s->tx_aborted_errors);
-                       print_uint(PRINT_JSON,
-                                  "fifo_errors",
-                                  NULL, s->tx_fifo_errors);
-                       print_uint(PRINT_JSON,
-                                  "window_errors",
-                                  NULL, s->tx_window_errors);
-                       print_uint(PRINT_JSON,
-                                  "heartbeat_errors",
-                                  NULL, s->tx_heartbeat_errors);
-                       if (carrier_changes)
-                               print_uint(PRINT_JSON, "carrier_changes", NULL,
-                                          rta_getattr_u32(carrier_changes));
-               }
-
-               close_json_object();
-               close_json_object();
-       } else {
-               /* RX stats */
-               fprintf(fp, "    RX: bytes  packets  errors  dropped overrun mcast   %s%s",
-                       s->rx_compressed ? "compressed" : "", _SL_);
-
-               fprintf(fp, "    ");
-               print_num(fp, 10, s->rx_bytes);
-               print_num(fp, 8, s->rx_packets);
-               print_num(fp, 7, s->rx_errors);
-               print_num(fp, 7, s->rx_dropped);
-               print_num(fp, 7, s->rx_over_errors);
-               print_num(fp, 7, s->multicast);
-               if (s->rx_compressed)
-                       print_num(fp, 7, s->rx_compressed);
-
-               /* RX error stats */
-               if (show_stats > 1) {
-                       fprintf(fp, "%s", _SL_);
-                       fprintf(fp, "    RX errors: length   crc     frame   fifo    missed%s%s",
-                               s->rx_nohandler ? "   nohandler" : "", _SL_);
-                       fprintf(fp, "               ");
-                       print_num(fp, 8, s->rx_length_errors);
-                       print_num(fp, 7, s->rx_crc_errors);
-                       print_num(fp, 7, s->rx_frame_errors);
-                       print_num(fp, 7, s->rx_fifo_errors);
-                       print_num(fp, 7, s->rx_missed_errors);
-                       if (s->rx_nohandler)
-                               print_num(fp, 7, s->rx_nohandler);
-               }
-               fprintf(fp, "%s", _SL_);
-
-               /* TX stats */
-               fprintf(fp, "    TX: bytes  packets  errors  dropped carrier collsns %s%s",
-                       s->tx_compressed ? "compressed" : "", _SL_);
-
-               fprintf(fp, "    ");
-               print_num(fp, 10, s->tx_bytes);
-               print_num(fp, 8, s->tx_packets);
-               print_num(fp, 7, s->tx_errors);
-               print_num(fp, 7, s->tx_dropped);
-               print_num(fp, 7, s->tx_carrier_errors);
-               print_num(fp, 7, s->collisions);
-               if (s->tx_compressed)
-                       print_num(fp, 7, s->tx_compressed);
-
-               /* TX error stats */
-               if (show_stats > 1) {
-                       fprintf(fp, "%s", _SL_);
-                       fprintf(fp, "    TX errors: aborted  fifo   window heartbeat");
-                       if (carrier_changes)
-                               fprintf(fp, " transns");
-                       fprintf(fp, "%s", _SL_);
+       const struct rtattr *carrier_changes = tb[IFLA_CARRIER_CHANGES];
+       struct rtnl_link_stats64 _s, *s = &_s;
+       int ret;
 
-                       fprintf(fp, "               ");
-                       print_num(fp, 8, s->tx_aborted_errors);
-                       print_num(fp, 7, s->tx_fifo_errors);
-                       print_num(fp, 7, s->tx_window_errors);
-                       print_num(fp, 7, s->tx_heartbeat_errors);
-                       if (carrier_changes)
-                               print_num(fp, 7,
-                                         rta_getattr_u32(carrier_changes));
-               }
-       }
-}
+       ret = get_rtnl_link_stats_rta(s, tb);
+       if (ret < 0)
+               return;
 
-static void print_link_stats32(FILE *fp, const struct rtnl_link_stats *s,
-                              const struct rtattr *carrier_changes)
-{
        if (is_json_context()) {
-               open_json_object("stats");
+               open_json_object((ret == sizeof(*s)) ? "stats64" : "stats");
 
                /* RX stats */
                open_json_object("rx");
@@ -875,27 +741,6 @@ static void print_link_stats32(FILE *fp, const struct rtnl_link_stats *s,
        }
 }
 
-static void __print_link_stats(FILE *fp, struct rtattr **tb)
-{
-       const struct rtattr *carrier_changes = tb[IFLA_CARRIER_CHANGES];
-
-       if (tb[IFLA_STATS64]) {
-               struct rtnl_link_stats64 stats = { 0 };
-
-               memcpy(&stats, RTA_DATA(tb[IFLA_STATS64]),
-                      MIN(RTA_PAYLOAD(tb[IFLA_STATS64]), sizeof(stats)));
-
-               print_link_stats64(fp, &stats, carrier_changes);
-       } else if (tb[IFLA_STATS]) {
-               struct rtnl_link_stats stats = { 0 };
-
-               memcpy(&stats, RTA_DATA(tb[IFLA_STATS]),
-                      MIN(RTA_PAYLOAD(tb[IFLA_STATS]), sizeof(stats)));
-
-               print_link_stats32(fp, &stats, carrier_changes);
-       }
-}
-
 static void print_link_stats(FILE *fp, struct nlmsghdr *n)
 {
        struct ifinfomsg *ifi = NLMSG_DATA(n);
index 8e15625e0c1ec1af66afb1da391aad9e0c46ce66..d86c2eec3d582bcd8b07f99d4e2cff9f7d90d97c 100644 (file)
@@ -1431,6 +1431,51 @@ int get_real_family(int rtm_type, int rtm_family)
        return rtm_family;
 }
 
+/* Based on copy_rtnl_link_stats() from kernel at net/core/rtnetlink.c */
+static void copy_rtnl_link_stats64(struct rtnl_link_stats64 *stats64,
+                                  const struct rtnl_link_stats *stats)
+{
+       __u64 *a = (__u64 *)stats64;
+       const __u32 *b = (const __u32 *)stats;
+       const __u32 *e = b + sizeof(*stats) / sizeof(*b);
+
+       while (b < e)
+               *a++ = *b++;
+}
+
+int get_rtnl_link_stats_rta(struct rtnl_link_stats64 *stats64,
+                           struct rtattr *tb[])
+{
+       struct rtnl_link_stats stats;
+       void *s;
+       struct rtattr *rta;
+       int size, len;
+
+       if (tb[IFLA_STATS64]) {
+               rta = tb[IFLA_STATS64];
+               size = sizeof(struct rtnl_link_stats64);
+               s = stats64;
+       } else if (tb[IFLA_STATS]) {
+               rta = tb[IFLA_STATS];
+               size = sizeof(struct rtnl_link_stats);
+               s = &stats;
+       } else {
+               return -1;
+       }
+
+       len = RTA_PAYLOAD(rta);
+       if (len < size)
+               memset(s + len, 0, size - len);
+       else
+               len = size;
+
+       memcpy(s, RTA_DATA(rta), len);
+
+       if (s != stats64)
+               copy_rtnl_link_stats64(stats64, s);
+       return size;
+}
+
 #ifdef NEED_STRLCPY
 size_t strlcpy(char *dst, const char *src, size_t size)
 {