[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1517514058-23596-3-git-send-email-serhe.popovych@gmail.com>
Date: Thu, 1 Feb 2018 21:40:54 +0200
From: Serhey Popovych <serhe.popovych@...il.com>
To: netdev@...r.kernel.org
Subject: [RFC][PATCH iproute2-next 2/6] ip: Introduce get_rtnl_link_stats_rta() to get link statistics
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@...il.com>
---
include/utils.h | 3 +
ip/ipaddress.c | 171 +++----------------------------------------------------
lib/utils.c | 68 ++++++++++++++++++++++
3 files changed, 79 insertions(+), 163 deletions(-)
diff --git a/include/utils.h b/include/utils.h
index 0394268..ffb2a2c 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -294,6 +294,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);
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index ae419f0..078c6cf 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -594,152 +594,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");
@@ -876,27 +742,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);
diff --git a/lib/utils.c b/lib/utils.c
index 8e15625..9e2de2b 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -1431,6 +1431,74 @@ 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 *a,
+ const struct rtnl_link_stats *b)
+{
+ a->rx_packets = b->rx_packets;
+ a->tx_packets = b->tx_packets;
+ a->rx_bytes = b->rx_bytes;
+ a->tx_bytes = b->tx_bytes;
+ a->rx_errors = b->rx_errors;
+ a->tx_errors = b->tx_errors;
+ a->rx_dropped = b->rx_dropped;
+ a->tx_dropped = b->tx_dropped;
+
+ a->multicast = b->multicast;
+ a->collisions = b->collisions;
+
+ a->rx_length_errors = b->rx_length_errors;
+ a->rx_over_errors = b->rx_over_errors;
+ a->rx_crc_errors = b->rx_crc_errors;
+ a->rx_frame_errors = b->rx_frame_errors;
+ a->rx_fifo_errors = b->rx_fifo_errors;
+ a->rx_missed_errors = b->rx_missed_errors;
+
+ a->tx_aborted_errors = b->tx_aborted_errors;
+ a->tx_carrier_errors = b->tx_carrier_errors;
+ a->tx_fifo_errors = b->tx_fifo_errors;
+ a->tx_heartbeat_errors = b->tx_heartbeat_errors;
+ a->tx_window_errors = b->tx_window_errors;
+
+ a->rx_compressed = b->rx_compressed;
+ a->tx_compressed = b->tx_compressed;
+
+ a->rx_nohandler = b->rx_nohandler;
+}
+
+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)
{
--
1.7.10.4
Powered by blists - more mailing lists