lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<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

Powered by Openwall GNU/*/Linux Powered by OpenVZ