All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv2 1/1] ip-link: add switch to show human readable output
@ 2014-10-10 22:27 Christian Hesse
  2014-10-30  5:47 ` Stephen Hemminger
  0 siblings, 1 reply; 8+ messages in thread
From: Christian Hesse @ 2014-10-10 22:27 UTC (permalink / raw)
  To: netdev; +Cc: Christian Hesse

Byte and packet count can increase to really big numbers. This adds a
switch to show human readable output.

% ip -s link ls wl
4: wl: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DORMANT group default qlen 1000
    link/ether 00:de:ad:be:ee:ef brd ff:ff:ff:ff:ff:ff
    RX: bytes  packets  errors  dropped overrun mcast
    113570876  156975   0       0       0       0
    TX: bytes  packets  errors  dropped carrier collsns
    27290790   94313    0       0       0       0
% ip -s -h link ls wl
4: wl: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DORMANT group default qlen 1000
    link/ether 00:de:ad:be:ee:ef brd ff:ff:ff:ff:ff:ff
    RX: bytes  packets  errors  dropped overrun mcast
    122368888  169840   0       0       0       0
    116.7Mi    165.8Ki  0       0       0       0
    TX: bytes  packets  errors  dropped carrier collsns
    29087507   102309   0       0       0       0
    27.7Mi     99.9Ki   0       0       0       0
---
 include/utils.h       |   1 +
 ip/ip.c               |   5 ++
 ip/ipaddress.c        | 143 ++++++++++++++++++++++++++++++++++++++++++++++++--
 man/man8/ip-link.8.in |   1 +
 4 files changed, 146 insertions(+), 4 deletions(-)

diff --git a/include/utils.h b/include/utils.h
index 704dc51..7bb19e9 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -11,6 +11,7 @@
 #include "rtm_map.h"
 
 extern int preferred_family;
+extern int human_readable;
 extern int show_stats;
 extern int show_details;
 extern int show_raw;
diff --git a/ip/ip.c b/ip/ip.c
index 739b88d..6b352c8 100644
--- a/ip/ip.c
+++ b/ip/ip.c
@@ -24,6 +24,7 @@
 #include "ip_common.h"
 
 int preferred_family = AF_UNSPEC;
+int human_readable = 0;
 int show_stats = 0;
 int show_details = 0;
 int resolve_hosts = 0;
@@ -47,6 +48,7 @@ static void usage(void)
 "                   tunnel | tuntap | maddr | mroute | mrule | monitor | xfrm |\n"
 "                   netns | l2tp | tcp_metrics | token | netconf }\n"
 "       OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n"
+"                    -h[uman-readable] |\n"
 "                    -f[amily] { inet | inet6 | ipx | dnet | bridge | link } |\n"
 "                    -4 | -6 | -I | -D | -B | -0 |\n"
 "                    -l[oops] { maximum-addr-flush-attempts } |\n"
@@ -212,6 +214,9 @@ int main(int argc, char **argv)
 			preferred_family = AF_DECnet;
 		} else if (strcmp(opt, "-B") == 0) {
 			preferred_family = AF_BRIDGE;
+		} else if (matches(opt, "-human") == 0 ||
+			   matches(opt, "-human-readable") == 0) {
+			++human_readable;
 		} else if (matches(opt, "-stats") == 0 ||
 			   matches(opt, "-statistics") == 0) {
 			++show_stats;
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 45729d8..d625434 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -319,6 +319,54 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
 	}
 }
 
+static void print_human64(FILE *fp, int length, uint64_t count)
+{
+	int written;
+
+	if (count > 1125899906842624) /* 2**50 */
+		written = fprintf(fp, "%"PRIu64".%"PRIu64"Pi",
+				count / 1125899906842624,
+				count * 10 / 1125899906842624 % 10);
+	else if (count > 1099511627776) /* 2**40 */
+		written = fprintf(fp, "%"PRIu64".%"PRIu64"Ti",
+				count / 1099511627776,
+				count * 10 / 1099511627776 % 10);
+	else if (count > 1073741824) /* 2**30 */
+		written = fprintf(fp, "%"PRIu64".%"PRIu64"Gi",
+				count / 1073741824, count * 10 / 1073741824 % 10);
+	else if (count > 1048576) /* 2**20 */
+		written = fprintf(fp, "%"PRIu64".%"PRIu64"Mi",
+				count / 1048576, count * 10 / 1048576 % 10);
+	else if (count > 1024) /* 2**10 */
+		written = fprintf(fp, "%"PRIu64".%"PRIu64"Ki",
+				count / 1024, count * 10 / 1024 % 10);
+	else
+		written = fprintf(fp, "%"PRIu64, count);
+
+	while(written++ <= length)
+		fputc(' ', fp);
+}
+
+static void print_human32(FILE *fp, int length, uint32_t count)
+{
+	int written;
+
+	if (count > 1073741824) /* 2**30 */
+		written = fprintf(fp, "%u.%uGi",
+				count / 1073741824, count * 10 / 1073741824 % 10);
+	else if (count > 1048576) /* 2**20 */
+		written = fprintf(fp, "%u.%uMi",
+				count / 1048576, count * 10 / 1048576 % 10);
+	else if (count > 1024) /* 2**10 */
+		written = fprintf(fp, "%u.%uKi",
+				count / 1024, count * 10 / 1024 % 10);
+	else
+		written = fprintf(fp, "%u", count);
+
+	while(written++ <= length)
+		fputc(' ', fp);
+}
+
 static void print_link_stats64(FILE *fp, const struct rtnl_link_stats64 *s,
                                const struct rtattr *carrier_changes)
 {
@@ -334,15 +382,36 @@ static void print_link_stats64(FILE *fp, const struct rtnl_link_stats64 *s,
 	if (s->rx_compressed)
 		fprintf(fp, " %-7"PRIu64"",
 			(uint64_t)s->rx_compressed);
+	if (human_readable) {
+		fprintf(fp, "%s", _SL_);
+		fprintf(fp, "    ");
+		print_human64(fp, 10, (uint64_t)s->rx_bytes);
+		print_human64(fp, 8, (uint64_t)s->rx_packets);
+		print_human64(fp, 7, (uint64_t)s->rx_errors);
+		print_human64(fp, 7, (uint64_t)s->rx_dropped);
+		print_human64(fp, 7, (uint64_t)s->rx_over_errors);
+		print_human64(fp, 7, (uint64_t)s->multicast);
+		if (s->rx_compressed)
+			print_human64(fp, 7, (uint64_t)s->rx_compressed);
+	}
 	if (show_stats > 1) {
 		fprintf(fp, "%s", _SL_);
 		fprintf(fp, "    RX errors: length  crc     frame   fifo    missed%s", _SL_);
-		fprintf(fp, "               %-7"PRIu64"  %-7"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64"",
+		fprintf(fp, "               %-8"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64"",
 			(uint64_t)s->rx_length_errors,
 			(uint64_t)s->rx_crc_errors,
 			(uint64_t)s->rx_frame_errors,
 			(uint64_t)s->rx_fifo_errors,
 			(uint64_t)s->rx_missed_errors);
+		if (human_readable) {
+			fprintf(fp, "%s", _SL_);
+			fprintf(fp, "               ");
+			print_human64(fp, 8, (uint64_t)s->rx_length_errors);
+			print_human64(fp, 7, (uint64_t)s->rx_crc_errors);
+			print_human64(fp, 7, (uint64_t)s->rx_frame_errors);
+			print_human64(fp, 7, (uint64_t)s->rx_fifo_errors);
+			print_human64(fp, 7, (uint64_t)s->rx_missed_errors);
+		}
 	}
 	fprintf(fp, "%s", _SL_);
 	fprintf(fp, "    TX: bytes  packets  errors  dropped carrier collsns %s%s",
@@ -357,13 +426,25 @@ static void print_link_stats64(FILE *fp, const struct rtnl_link_stats64 *s,
 	if (s->tx_compressed)
 		fprintf(fp, " %-7"PRIu64"",
 			(uint64_t)s->tx_compressed);
+	if (human_readable) {
+		fprintf(fp, "%s", _SL_);
+		fprintf(fp, "    ");
+		print_human64(fp, 10, (uint64_t)s->tx_bytes);
+		print_human64(fp, 8, (uint64_t)s->tx_packets);
+		print_human64(fp, 7, (uint64_t)s->tx_errors);
+		print_human64(fp, 7, (uint64_t)s->tx_dropped);
+		print_human64(fp, 7, (uint64_t)s->tx_carrier_errors);
+		print_human64(fp, 7, (uint64_t)s->collisions);
+		if (s->tx_compressed)
+			print_human64(fp, 7, (uint64_t)s->tx_compressed);
+	}
 	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_);
-		fprintf(fp, "               %-7"PRIu64"  %-7"PRIu64" %-7"PRIu64" %-8"PRIu64"",
+		fprintf(fp, "               %-8"PRIu64" %-7"PRIu64" %-7"PRIu64" %-8"PRIu64"",
 			(uint64_t)s->tx_aborted_errors,
 			(uint64_t)s->tx_fifo_errors,
 			(uint64_t)s->tx_window_errors,
@@ -371,6 +452,17 @@ static void print_link_stats64(FILE *fp, const struct rtnl_link_stats64 *s,
 		if (carrier_changes)
 			fprintf(fp, " %-7u",
 				*(uint32_t*)RTA_DATA(carrier_changes));
+		if (human_readable) {
+			fprintf(fp, "%s", _SL_);
+			fprintf(fp, "               ");
+			print_human64(fp, 8, (uint64_t)s->tx_aborted_errors);
+			print_human64(fp, 7, (uint64_t)s->tx_fifo_errors);
+			print_human64(fp, 7, (uint64_t)s->tx_window_errors);
+			print_human64(fp, 7, (uint64_t)s->tx_heartbeat_errors);
+			if (carrier_changes)
+				print_human64(fp, 7, (uint64_t)*(uint32_t*)RTA_DATA(carrier_changes));
+		}
+
 	}
 }
 
@@ -386,16 +478,37 @@ static void print_link_stats32(FILE *fp, const struct rtnl_link_stats *s,
 		);
 	if (s->rx_compressed)
 		fprintf(fp, " %-7u", s->rx_compressed);
+	if (human_readable) {
+		fprintf(fp, "%s", _SL_);
+		fprintf(fp, "    ");
+		print_human32(fp, 10, s->rx_bytes);
+		print_human32(fp, 8, s->rx_packets);
+		print_human32(fp, 7, s->rx_errors);
+		print_human32(fp, 7, s->rx_dropped);
+		print_human32(fp, 7, s->rx_over_errors);
+		print_human32(fp, 7, s->multicast);
+		if (s->rx_compressed)
+			print_human32(fp, 7, s->rx_compressed);
+	}
 	if (show_stats > 1) {
 		fprintf(fp, "%s", _SL_);
 		fprintf(fp, "    RX errors: length  crc     frame   fifo    missed%s", _SL_);
-		fprintf(fp, "               %-7u  %-7u %-7u %-7u %-7u",
+		fprintf(fp, "               %-8u %-7u %-7u %-7u %-7u",
 			s->rx_length_errors,
 			s->rx_crc_errors,
 			s->rx_frame_errors,
 			s->rx_fifo_errors,
 			s->rx_missed_errors
 			);
+		if (human_readable) {
+			fprintf(fp, "%s", _SL_);
+			fprintf(fp, "               ");
+			print_human32(fp, 8, s->rx_length_errors);
+			print_human32(fp, 7, s->rx_crc_errors);
+			print_human32(fp, 7, s->rx_frame_errors);
+			print_human32(fp, 7, s->rx_fifo_errors);
+			print_human32(fp, 7, s->rx_missed_errors);
+		}
 	}
 	fprintf(fp, "%s", _SL_);
 	fprintf(fp, "    TX: bytes  packets  errors  dropped carrier collsns %s%s",
@@ -405,13 +518,25 @@ static void print_link_stats32(FILE *fp, const struct rtnl_link_stats *s,
 		s->tx_dropped, s->tx_carrier_errors, s->collisions);
 	if (s->tx_compressed)
 		fprintf(fp, " %-7u", s->tx_compressed);
+	if (human_readable) {
+		fprintf(fp, "%s", _SL_);
+		fprintf(fp, "    ");
+		print_human32(fp, 10, s->tx_bytes);
+		print_human32(fp, 8, s->tx_packets);
+		print_human32(fp, 7, s->tx_errors);
+		print_human32(fp, 7, s->tx_dropped);
+		print_human32(fp, 7, s->tx_carrier_errors);
+		print_human32(fp, 7, s->collisions);
+		if (s->tx_compressed)
+			print_human32(fp, 7, s->tx_compressed);
+	}
 	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_);
-		fprintf(fp, "               %-7u  %-7u %-7u %-8u",
+		fprintf(fp, "               %-8u %-7u %-7u %-8u",
 			s->tx_aborted_errors,
 			s->tx_fifo_errors,
 			s->tx_window_errors,
@@ -420,6 +545,16 @@ static void print_link_stats32(FILE *fp, const struct rtnl_link_stats *s,
 		if (carrier_changes)
 			fprintf(fp, " %-7u",
 				*(uint32_t*)RTA_DATA(carrier_changes));
+		if (human_readable) {
+			fprintf(fp, "%s", _SL_);
+			fprintf(fp, "               ");
+			print_human32(fp, 8, s->tx_aborted_errors);
+			print_human32(fp, 7, s->tx_fifo_errors);
+			print_human32(fp, 7, s->tx_window_errors);
+			print_human32(fp, 7, s->tx_heartbeat_errors);
+			if (carrier_changes)
+				print_human32(fp, 7, *(uint32_t*)RTA_DATA(carrier_changes));
+		}
 	}
 }
 
diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in
index 383917a..9c20dd0 100644
--- a/man/man8/ip-link.8.in
+++ b/man/man8/ip-link.8.in
@@ -16,6 +16,7 @@ ip-link \- network device configuration
 .ti -8
 .IR OPTIONS " := { "
 \fB\-V\fR[\fIersion\fR] |
+\fB\-h\fR[\fIuman-readable\fR] |
 \fB\-s\fR[\fItatistics\fR] |
 \fB\-r\fR[\fIesolve\fR] |
 \fB\-f\fR[\fIamily\fR] {
-- 
2.1.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCHv2 1/1] ip-link: add switch to show human readable output
  2014-10-10 22:27 [PATCHv2 1/1] ip-link: add switch to show human readable output Christian Hesse
@ 2014-10-30  5:47 ` Stephen Hemminger
  2014-10-30  9:16   ` [PATCH v3 " Christian Hesse
  0 siblings, 1 reply; 8+ messages in thread
From: Stephen Hemminger @ 2014-10-30  5:47 UTC (permalink / raw)
  To: Christian Hesse; +Cc: netdev

On Sat, 11 Oct 2014 00:27:36 +0200
Christian Hesse <mail@eworm.de> wrote:

> Byte and packet count can increase to really big numbers. This adds a
> switch to show human readable output.
> 
> % ip -s link ls wl
> 4: wl: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DORMANT group default qlen 1000
>     link/ether 00:de:ad:be:ee:ef brd ff:ff:ff:ff:ff:ff
>     RX: bytes  packets  errors  dropped overrun mcast
>     113570876  156975   0       0       0       0
>     TX: bytes  packets  errors  dropped carrier collsns
>     27290790   94313    0       0       0       0
> % ip -s -h link ls wl
> 4: wl: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DORMANT group default qlen 1000
>     link/ether 00:de:ad:be:ee:ef brd ff:ff:ff:ff:ff:ff
>     RX: bytes  packets  errors  dropped overrun mcast
>     122368888  169840   0       0       0       0
>     116.7Mi    165.8Ki  0       0       0       0
>     TX: bytes  packets  errors  dropped carrier collsns
>     29087507   102309   0       0       0       0
>     27.7Mi     99.9Ki   0       0       0       0
> ---

I like the idea as a concept but there are two issues:
  1. The IEC suffix is a rarely used thing and is non-standard
     for communications where K = 1000 M = 1000000 etc.
     Please just use standard suffices

  2. Don't double print the data, if the user asks for human
     format, only show the human format.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v3 1/1] ip-link: add switch to show human readable output
  2014-10-30  5:47 ` Stephen Hemminger
@ 2014-10-30  9:16   ` Christian Hesse
  2014-10-31 10:17     ` Christian Hesse
  0 siblings, 1 reply; 8+ messages in thread
From: Christian Hesse @ 2014-10-30  9:16 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev, Christian Hesse

Byte and packet count can increase to really big numbers. This adds a
switch to show human readable output.

% ip -s link ls en
3: en: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 00:de:ad:be:ee:ef brd ff:ff:ff:ff:ff:ff
    RX: bytes  packets  errors  dropped overrun mcast
    48494310   141370   0       196     0       0
    TX: bytes  packets  errors  dropped carrier collsns
    153830639  180773   0       0       0       0
% ip -s -h link ls en
3: en: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 00:de:ad:be:ee:ef brd ff:ff:ff:ff:ff:ff
    RX: bytes  packets  errors  dropped overrun mcast
    46.3M      138.8K   0       198     0       0
    TX: bytes  packets  errors  dropped carrier collsns
    148.1M     177.7K   0       0       0       0
---
 include/utils.h       |   1 +
 ip/ip.c               |   5 +
 ip/ipaddress.c        | 279 ++++++++++++++++++++++++++++++++++++++------------
 man/man8/ip-link.8.in |   1 +
 4 files changed, 220 insertions(+), 66 deletions(-)

diff --git a/include/utils.h b/include/utils.h
index 704dc51..7bb19e9 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -11,6 +11,7 @@
 #include "rtm_map.h"
 
 extern int preferred_family;
+extern int human_readable;
 extern int show_stats;
 extern int show_details;
 extern int show_raw;
diff --git a/ip/ip.c b/ip/ip.c
index 739b88d..6b352c8 100644
--- a/ip/ip.c
+++ b/ip/ip.c
@@ -24,6 +24,7 @@
 #include "ip_common.h"
 
 int preferred_family = AF_UNSPEC;
+int human_readable = 0;
 int show_stats = 0;
 int show_details = 0;
 int resolve_hosts = 0;
@@ -47,6 +48,7 @@ static void usage(void)
 "                   tunnel | tuntap | maddr | mroute | mrule | monitor | xfrm |\n"
 "                   netns | l2tp | tcp_metrics | token | netconf }\n"
 "       OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n"
+"                    -h[uman-readable] |\n"
 "                    -f[amily] { inet | inet6 | ipx | dnet | bridge | link } |\n"
 "                    -4 | -6 | -I | -D | -B | -0 |\n"
 "                    -l[oops] { maximum-addr-flush-attempts } |\n"
@@ -212,6 +214,9 @@ int main(int argc, char **argv)
 			preferred_family = AF_DECnet;
 		} else if (strcmp(opt, "-B") == 0) {
 			preferred_family = AF_BRIDGE;
+		} else if (matches(opt, "-human") == 0 ||
+			   matches(opt, "-human-readable") == 0) {
+			++human_readable;
 		} else if (matches(opt, "-stats") == 0 ||
 			   matches(opt, "-statistics") == 0) {
 			++show_stats;
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 45729d8..dcf31c0 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -319,107 +319,254 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
 	}
 }
 
+static void print_human64(FILE *fp, int length, uint64_t count)
+{
+	int written;
+
+	if (count > 1125899906842624) /* 2**50 */
+		written = fprintf(fp, "%"PRIu64".%"PRIu64"P",
+				count / 1125899906842624,
+				count * 10 / 1125899906842624 % 10);
+	else if (count > 1099511627776) /* 2**40 */
+		written = fprintf(fp, "%"PRIu64".%"PRIu64"T",
+				count / 1099511627776,
+				count * 10 / 1099511627776 % 10);
+	else if (count > 1073741824) /* 2**30 */
+		written = fprintf(fp, "%"PRIu64".%"PRIu64"G",
+				count / 1073741824, count * 10 / 1073741824 % 10);
+	else if (count > 1048576) /* 2**20 */
+		written = fprintf(fp, "%"PRIu64".%"PRIu64"M",
+				count / 1048576, count * 10 / 1048576 % 10);
+	else if (count > 1024) /* 2**10 */
+		written = fprintf(fp, "%"PRIu64".%"PRIu64"K",
+				count / 1024, count * 10 / 1024 % 10);
+	else
+		written = fprintf(fp, "%"PRIu64, count);
+
+	do {
+		fputc(' ', fp);
+	} while (written++ < length);
+}
+
+static void print_human32(FILE *fp, int length, uint32_t count)
+{
+	int written;
+
+	if (count > 1073741824) /* 2**30 */
+		written = fprintf(fp, "%u.%uG",
+				count / 1073741824, count * 10 / 1073741824 % 10);
+	else if (count > 1048576) /* 2**20 */
+		written = fprintf(fp, "%u.%uM",
+				count / 1048576, count * 10 / 1048576 % 10);
+	else if (count > 1024) /* 2**10 */
+		written = fprintf(fp, "%u.%uK",
+				count / 1024, count * 10 / 1024 % 10);
+	else
+		written = fprintf(fp, "%u", count);
+
+	do {
+		fputc(' ', fp);
+	} while (written++ < length);
+}
+
 static void print_link_stats64(FILE *fp, const struct rtnl_link_stats64 *s,
                                const struct rtattr *carrier_changes)
 {
+	/* RX stats */
 	fprintf(fp, "    RX: bytes  packets  errors  dropped overrun mcast   %s%s",
 		s->rx_compressed ? "compressed" : "", _SL_);
-	fprintf(fp, "    %-10"PRIu64" %-8"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64"",
-		(uint64_t)s->rx_bytes,
-		(uint64_t)s->rx_packets,
-		(uint64_t)s->rx_errors,
-		(uint64_t)s->rx_dropped,
-		(uint64_t)s->rx_over_errors,
-		(uint64_t)s->multicast);
-	if (s->rx_compressed)
-		fprintf(fp, " %-7"PRIu64"",
-			(uint64_t)s->rx_compressed);
+	if (human_readable) {
+		fprintf(fp, "    ");
+		print_human64(fp, 10, (uint64_t)s->rx_bytes);
+		print_human64(fp, 8, (uint64_t)s->rx_packets);
+		print_human64(fp, 7, (uint64_t)s->rx_errors);
+		print_human64(fp, 7, (uint64_t)s->rx_dropped);
+		print_human64(fp, 7, (uint64_t)s->rx_over_errors);
+		print_human64(fp, 7, (uint64_t)s->multicast);
+		if (s->rx_compressed)
+			print_human64(fp, 7, (uint64_t)s->rx_compressed);
+	} else {
+		fprintf(fp, "    %-10"PRIu64" %-8"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64"",
+			(uint64_t)s->rx_bytes,
+			(uint64_t)s->rx_packets,
+			(uint64_t)s->rx_errors,
+			(uint64_t)s->rx_dropped,
+			(uint64_t)s->rx_over_errors,
+			(uint64_t)s->multicast);
+		if (s->rx_compressed)
+			fprintf(fp, " %-7"PRIu64"",
+				(uint64_t)s->rx_compressed);
+	}
+
+	/* RX error stats */
 	if (show_stats > 1) {
 		fprintf(fp, "%s", _SL_);
-		fprintf(fp, "    RX errors: length  crc     frame   fifo    missed%s", _SL_);
-		fprintf(fp, "               %-7"PRIu64"  %-7"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64"",
-			(uint64_t)s->rx_length_errors,
-			(uint64_t)s->rx_crc_errors,
-			(uint64_t)s->rx_frame_errors,
-			(uint64_t)s->rx_fifo_errors,
-			(uint64_t)s->rx_missed_errors);
+		fprintf(fp, "    RX errors: length   crc     frame   fifo    missed%s", _SL_);
+		if (human_readable) {
+			fprintf(fp, "               ");
+			print_human64(fp, 8, (uint64_t)s->rx_length_errors);
+			print_human64(fp, 7, (uint64_t)s->rx_crc_errors);
+			print_human64(fp, 7, (uint64_t)s->rx_frame_errors);
+			print_human64(fp, 7, (uint64_t)s->rx_fifo_errors);
+			print_human64(fp, 7, (uint64_t)s->rx_missed_errors);
+		} else {
+			fprintf(fp, "               %-8"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64"",
+				(uint64_t)s->rx_length_errors,
+				(uint64_t)s->rx_crc_errors,
+				(uint64_t)s->rx_frame_errors,
+				(uint64_t)s->rx_fifo_errors,
+				(uint64_t)s->rx_missed_errors);
+		}
 	}
 	fprintf(fp, "%s", _SL_);
+
+	/* TX stats */
 	fprintf(fp, "    TX: bytes  packets  errors  dropped carrier collsns %s%s",
 		(uint64_t)s->tx_compressed ? "compressed" : "", _SL_);
-	fprintf(fp, "    %-10"PRIu64" %-8"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64"",
-		(uint64_t)s->tx_bytes,
-		(uint64_t)s->tx_packets,
-		(uint64_t)s->tx_errors,
-		(uint64_t)s->tx_dropped,
-		(uint64_t)s->tx_carrier_errors,
-		(uint64_t)s->collisions);
-	if (s->tx_compressed)
-		fprintf(fp, " %-7"PRIu64"",
-			(uint64_t)s->tx_compressed);
+	if (human_readable) {
+		fprintf(fp, "    ");
+		print_human64(fp, 10, (uint64_t)s->tx_bytes);
+		print_human64(fp, 8, (uint64_t)s->tx_packets);
+		print_human64(fp, 7, (uint64_t)s->tx_errors);
+		print_human64(fp, 7, (uint64_t)s->tx_dropped);
+		print_human64(fp, 7, (uint64_t)s->tx_carrier_errors);
+		print_human64(fp, 7, (uint64_t)s->collisions);
+		if (s->tx_compressed)
+			print_human64(fp, 7, (uint64_t)s->tx_compressed);
+	} else {
+		fprintf(fp, "    %-10"PRIu64" %-8"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64"",
+			(uint64_t)s->tx_bytes,
+			(uint64_t)s->tx_packets,
+			(uint64_t)s->tx_errors,
+			(uint64_t)s->tx_dropped,
+			(uint64_t)s->tx_carrier_errors,
+			(uint64_t)s->collisions);
+		if (s->tx_compressed)
+			fprintf(fp, " %-7"PRIu64"",
+				(uint64_t)s->tx_compressed);
+	}
+
+	/* TX error stats */
 	if (show_stats > 1) {
 		fprintf(fp, "%s", _SL_);
-		fprintf(fp, "    TX errors: aborted fifo    window  heartbeat");
+		fprintf(fp, "    TX errors: aborted  fifo   window heartbeat");
                 if (carrier_changes)
 			fprintf(fp, " transns");
 		fprintf(fp, "%s", _SL_);
-		fprintf(fp, "               %-7"PRIu64"  %-7"PRIu64" %-7"PRIu64" %-8"PRIu64"",
-			(uint64_t)s->tx_aborted_errors,
-			(uint64_t)s->tx_fifo_errors,
-			(uint64_t)s->tx_window_errors,
-			(uint64_t)s->tx_heartbeat_errors);
-		if (carrier_changes)
-			fprintf(fp, " %-7u",
-				*(uint32_t*)RTA_DATA(carrier_changes));
+		if (human_readable) {
+			fprintf(fp, "               ");
+			print_human64(fp, 8, (uint64_t)s->tx_aborted_errors);
+			print_human64(fp, 7, (uint64_t)s->tx_fifo_errors);
+			print_human64(fp, 7, (uint64_t)s->tx_window_errors);
+			print_human64(fp, 7, (uint64_t)s->tx_heartbeat_errors);
+			if (carrier_changes)
+				print_human64(fp, 7, (uint64_t)*(uint32_t*)RTA_DATA(carrier_changes));
+		} else {
+			fprintf(fp, "               %-8"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64"",
+				(uint64_t)s->tx_aborted_errors,
+				(uint64_t)s->tx_fifo_errors,
+				(uint64_t)s->tx_window_errors,
+				(uint64_t)s->tx_heartbeat_errors);
+			if (carrier_changes)
+				fprintf(fp, " %-7u",
+					*(uint32_t*)RTA_DATA(carrier_changes));
+		}
 	}
 }
 
 static void print_link_stats32(FILE *fp, const struct rtnl_link_stats *s,
 			       const struct rtattr *carrier_changes)
 {
+	/* RX stats */
 	fprintf(fp, "    RX: bytes  packets  errors  dropped overrun mcast   %s%s",
 		s->rx_compressed ? "compressed" : "", _SL_);
-	fprintf(fp, "    %-10u %-8u %-7u %-7u %-7u %-7u",
-		s->rx_bytes, s->rx_packets, s->rx_errors,
-		s->rx_dropped, s->rx_over_errors,
-		s->multicast
-		);
-	if (s->rx_compressed)
-		fprintf(fp, " %-7u", s->rx_compressed);
+	if (human_readable) {
+		fprintf(fp, "    ");
+		print_human32(fp, 10, s->rx_bytes);
+		print_human32(fp, 8, s->rx_packets);
+		print_human32(fp, 7, s->rx_errors);
+		print_human32(fp, 7, s->rx_dropped);
+		print_human32(fp, 7, s->rx_over_errors);
+		print_human32(fp, 7, s->multicast);
+		if (s->rx_compressed)
+			print_human32(fp, 7, s->rx_compressed);
+	} else {
+		fprintf(fp, "    %-10u %-8u %-7u %-7u %-7u %-7u",
+			s->rx_bytes, s->rx_packets, s->rx_errors,
+			s->rx_dropped, s->rx_over_errors,
+			s->multicast);
+		if (s->rx_compressed)
+			fprintf(fp, " %-7u", s->rx_compressed);
+	}
+
+	/* RX error stats */
 	if (show_stats > 1) {
 		fprintf(fp, "%s", _SL_);
-		fprintf(fp, "    RX errors: length  crc     frame   fifo    missed%s", _SL_);
-		fprintf(fp, "               %-7u  %-7u %-7u %-7u %-7u",
-			s->rx_length_errors,
-			s->rx_crc_errors,
-			s->rx_frame_errors,
-			s->rx_fifo_errors,
-			s->rx_missed_errors
-			);
+		fprintf(fp, "    RX errors: length   crc     frame   fifo    missed%s", _SL_);
+		if (human_readable) {
+			fprintf(fp, "               ");
+			print_human32(fp, 8, s->rx_length_errors);
+			print_human32(fp, 7, s->rx_crc_errors);
+			print_human32(fp, 7, s->rx_frame_errors);
+			print_human32(fp, 7, s->rx_fifo_errors);
+			print_human32(fp, 7, s->rx_missed_errors);
+		} else {
+			fprintf(fp, "               %-8u %-7u %-7u %-7u %-7u",
+				s->rx_length_errors,
+				s->rx_crc_errors,
+				s->rx_frame_errors,
+				s->rx_fifo_errors,
+				s->rx_missed_errors);
+		}
 	}
 	fprintf(fp, "%s", _SL_);
+
+	/* TX stats */
 	fprintf(fp, "    TX: bytes  packets  errors  dropped carrier collsns %s%s",
 		s->tx_compressed ? "compressed" : "", _SL_);
-	fprintf(fp, "    %-10u %-8u %-7u %-7u %-7u %-7u",
-		s->tx_bytes, s->tx_packets, s->tx_errors,
-		s->tx_dropped, s->tx_carrier_errors, s->collisions);
-	if (s->tx_compressed)
-		fprintf(fp, " %-7u", s->tx_compressed);
+	if (human_readable) {
+		fprintf(fp, "    ");
+		print_human32(fp, 10, s->tx_bytes);
+		print_human32(fp, 8, s->tx_packets);
+		print_human32(fp, 7, s->tx_errors);
+		print_human32(fp, 7, s->tx_dropped);
+		print_human32(fp, 7, s->tx_carrier_errors);
+		print_human32(fp, 7, s->collisions);
+		if (s->tx_compressed)
+			print_human32(fp, 7, s->tx_compressed);
+	} else {
+		fprintf(fp, "    %-10u %-8u %-7u %-7u %-7u %-7u",
+			s->tx_bytes, s->tx_packets, s->tx_errors,
+			s->tx_dropped, s->tx_carrier_errors, s->collisions);
+		if (s->tx_compressed)
+			fprintf(fp, " %-7u", s->tx_compressed);
+	}
+
+	/* TX error stats */
 	if (show_stats > 1) {
 		fprintf(fp, "%s", _SL_);
-		fprintf(fp, "    TX errors: aborted fifo    window  heartbeat");
+		fprintf(fp, "    TX errors: aborted  fifo   window heartbeat");
                 if (carrier_changes)
 			fprintf(fp, " transns");
 		fprintf(fp, "%s", _SL_);
-		fprintf(fp, "               %-7u  %-7u %-7u %-8u",
-			s->tx_aborted_errors,
-			s->tx_fifo_errors,
-			s->tx_window_errors,
-			s->tx_heartbeat_errors
-			);
-		if (carrier_changes)
-			fprintf(fp, " %-7u",
-				*(uint32_t*)RTA_DATA(carrier_changes));
+		if (human_readable) {
+			fprintf(fp, "               ");
+			print_human32(fp, 8, s->tx_aborted_errors);
+			print_human32(fp, 7, s->tx_fifo_errors);
+			print_human32(fp, 7, s->tx_window_errors);
+			print_human32(fp, 7, s->tx_heartbeat_errors);
+			if (carrier_changes)
+				print_human32(fp, 7, *(uint32_t*)RTA_DATA(carrier_changes));
+		} else {
+			fprintf(fp, "               %-8u %-7u %-7u %-7u",
+				s->tx_aborted_errors,
+				s->tx_fifo_errors,
+				s->tx_window_errors,
+				s->tx_heartbeat_errors);
+			if (carrier_changes)
+				fprintf(fp, " %-7u",
+					*(uint32_t*)RTA_DATA(carrier_changes));
+		}
 	}
 }
 
diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in
index 464009d..b05c6d0 100644
--- a/man/man8/ip-link.8.in
+++ b/man/man8/ip-link.8.in
@@ -16,6 +16,7 @@ ip-link \- network device configuration
 .ti -8
 .IR OPTIONS " := { "
 \fB\-V\fR[\fIersion\fR] |
+\fB\-h\fR[\fIuman-readable\fR] |
 \fB\-s\fR[\fItatistics\fR] |
 \fB\-r\fR[\fIesolve\fR] |
 \fB\-f\fR[\fIamily\fR] {
-- 
2.1.3

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v3 1/1] ip-link: add switch to show human readable output
  2014-10-30  9:16   ` [PATCH v3 " Christian Hesse
@ 2014-10-31 10:17     ` Christian Hesse
  2014-10-31 19:31       ` Stephen Hemminger
  0 siblings, 1 reply; 8+ messages in thread
From: Christian Hesse @ 2014-10-31 10:17 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev

[-- Attachment #1: Type: text/plain, Size: 3127 bytes --]

Stephen Hemminger <stephen@networkplumber.org> on Wed, 2014/10/29 22:47:
> I like the idea as a concept

Great! ;)

> but there are two issues:
>   1. The IEC suffix is a rarely used thing and is non-standard
>      for communications where K = 1000 M = 1000000 etc.
>      Please just use standard suffices

Removed the suffix in patch v3. Not sure if it is correct, though. I do use a
base of 2, so K = 1024, M = 1048576, ...

This is what ifconfig behaves as well. Output should give the exact same
numbers (except the suffix):

# ip -s -h link list en
3: en: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
mode DEFAULT group default qlen 1000
    link/ether 00:de:ad:be:ee:ef brd ff:ff:ff:ff:ff:ff
    RX: bytes  packets  errors  dropped overrun mcast
    26.3M      59.2K    0       68      0       0
    TX: bytes  packets  errors  dropped carrier collsns
    37.0M      67.6K    0       0       0       0
# ifconfig en 
en: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet XX.XX.XX.XX  netmask 255.255.255.0  broadcast XX.XX.XX.255
        ether 00:de:ad:be:ee:ef  txqueuelen 1000  (Ethernet)
        RX packets 60677  bytes 27671339 (26.3 MiB)
        RX errors 0  dropped 68  overruns 0  frame 0
        TX packets 69350  bytes 38874609 (37.0 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

>   2. Don't double print the data, if the user asks for human
>      format, only show the human format.

Fixed.

Hopefully I got the line breaks right. How to check print_link_stats32()?
Even von i686 ip calls print_link_stats64() on my systems.

I did some minor changes to the error stats column alignment. Is that ok? See
the difference of before and after:

# ip -s -s link list en    # before
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP
mode DEFAULT group default qlen 1000
    link/ether 00:de:ad:be:ee:ef brd ff:ff:ff:ff:ff:ff 
    RX: bytes  packets  errors  dropped overrun mcast   
    144544239  100441   0       0       0       1      
    RX errors: length  crc     frame   fifo    missed
               0        0       0       0       0      
    TX: bytes  packets  errors  dropped carrier collsns 
    808343     9630     0       0       0       0      
    TX errors: aborted fifo    window  heartbeat transns
               0        0       0       0        2      
# ip -s -s link list en    # after
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP
mode DEFAULT group default qlen 1000
    link/ether 00:de:ad:be:ee:ef brd ff:ff:ff:ff:ff:ff
    RX: bytes  packets  errors  dropped overrun mcast
    87432187   60642    0       0       0       1
    RX errors: length   crc     frame   fifo    missed
               0        0       0       0       0
    TX: bytes  packets  errors  dropped carrier collsns 
    450437     5793     0       0       0       0      
    TX errors: aborted  fifo   window heartbeat transns
               0        0       0       0       2      
-- 
Best regards,
Christian Hesse

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v3 1/1] ip-link: add switch to show human readable output
  2014-10-31 10:17     ` Christian Hesse
@ 2014-10-31 19:31       ` Stephen Hemminger
  2014-10-31 21:33         ` [PATCH v4 " Christian Hesse
  0 siblings, 1 reply; 8+ messages in thread
From: Stephen Hemminger @ 2014-10-31 19:31 UTC (permalink / raw)
  To: Christian Hesse; +Cc: netdev

On Fri, 31 Oct 2014 11:17:53 +0100
Christian Hesse <mail@eworm.de> wrote:

> Stephen Hemminger <stephen@networkplumber.org> on Wed, 2014/10/29 22:47:
> > I like the idea as a concept  
> 
> Great! ;)
> 
> > but there are two issues:
> >   1. The IEC suffix is a rarely used thing and is non-standard
> >      for communications where K = 1000 M = 1000000 etc.
> >      Please just use standard suffices  
> 
> Removed the suffix in patch v3. Not sure if it is correct, though. I do use a
> base of 2, so K = 1024, M = 1048576, ...

No must be 1000 for communications (SI)


  http://en.wikipedia.org/wiki/Binary_prefix

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v4 1/1] ip-link: add switch to show human readable output
  2014-10-31 19:31       ` Stephen Hemminger
@ 2014-10-31 21:33         ` Christian Hesse
  2014-11-02 20:51           ` Stephen Hemminger
  0 siblings, 1 reply; 8+ messages in thread
From: Christian Hesse @ 2014-10-31 21:33 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev, Christian Hesse

Byte and packet count can increase to really big numbers. This adds a
switch to show human readable output.

4: wl: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DORMANT group default qlen 1000
    link/ether 00:de:ad:be:ee:ef brd ff:ff:ff:ff:ff:ff
    RX: bytes  packets  errors  dropped overrun mcast
    1523846973 3969051  0       0       0       0
    TX: bytes  packets  errors  dropped carrier collsns
    8710088361 6077735  0       0       0       0
4: wl: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DORMANT group default qlen 1000
    link/ether 00:de:ad:be:ee:ef brd ff:ff:ff:ff:ff:ff
    RX: bytes  packets  errors  dropped overrun mcast
    1.5G       3.9M     0       0       0       0
    TX: bytes  packets  errors  dropped carrier collsns
    8.7G       6.0M     0       0       0       0
---
 include/utils.h       |   1 +
 ip/ip.c               |   5 +
 ip/ipaddress.c        | 286 ++++++++++++++++++++++++++++++++++++++------------
 man/man8/ip-link.8.in |   7 ++
 4 files changed, 233 insertions(+), 66 deletions(-)

diff --git a/include/utils.h b/include/utils.h
index 704dc51..7bb19e9 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -11,6 +11,7 @@
 #include "rtm_map.h"
 
 extern int preferred_family;
+extern int human_readable;
 extern int show_stats;
 extern int show_details;
 extern int show_raw;
diff --git a/ip/ip.c b/ip/ip.c
index 739b88d..6b352c8 100644
--- a/ip/ip.c
+++ b/ip/ip.c
@@ -24,6 +24,7 @@
 #include "ip_common.h"
 
 int preferred_family = AF_UNSPEC;
+int human_readable = 0;
 int show_stats = 0;
 int show_details = 0;
 int resolve_hosts = 0;
@@ -47,6 +48,7 @@ static void usage(void)
 "                   tunnel | tuntap | maddr | mroute | mrule | monitor | xfrm |\n"
 "                   netns | l2tp | tcp_metrics | token | netconf }\n"
 "       OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n"
+"                    -h[uman-readable] |\n"
 "                    -f[amily] { inet | inet6 | ipx | dnet | bridge | link } |\n"
 "                    -4 | -6 | -I | -D | -B | -0 |\n"
 "                    -l[oops] { maximum-addr-flush-attempts } |\n"
@@ -212,6 +214,9 @@ int main(int argc, char **argv)
 			preferred_family = AF_DECnet;
 		} else if (strcmp(opt, "-B") == 0) {
 			preferred_family = AF_BRIDGE;
+		} else if (matches(opt, "-human") == 0 ||
+			   matches(opt, "-human-readable") == 0) {
+			++human_readable;
 		} else if (matches(opt, "-stats") == 0 ||
 			   matches(opt, "-statistics") == 0) {
 			++show_stats;
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 45729d8..4b8ddca 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -319,107 +319,261 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
 	}
 }
 
+
+static void print_human64(FILE *fp, int length, uint64_t count)
+{
+	char * prefix = "kMGTPE";
+	int written = 0, i;
+	uint64_t powi = 1;
+
+	if (count < 1000) {
+		/* we are below 1000, so no precision and no prefix */
+		written = fprintf(fp, "%"PRIu64, count);
+	} else {
+		/* increase value by a factor of 1000 and print
+		 * if result is something a human can read */
+		for (i = 0; i < 6; i++) {
+			powi *= 1000;
+			if (count / 1000 < powi) {
+				 written = fprintf(fp, "%"PRIu64".%"PRIu64"%c",
+					 count / powi, count * 10 / powi % 10, *prefix);
+				 break;
+			}
+			prefix++;
+		}
+	}
+
+	do {
+		fputc(' ', fp);
+	} while (written++ < length);
+}
+
+static void print_human32(FILE *fp, int length, uint32_t count)
+{
+	char * prefix = "KMG";
+	int written = 0, i;
+	uint32_t powi = 1;
+
+	if (count < 1000) {
+		/* we are below 1000, so no precision and no prefix */
+		written = fprintf(fp, "%u", count);
+	} else {
+		/* increase value by a factor of 1000 and print
+		 * if result is something a human can read */
+		for (i = 0; i < 3; i++) {
+			powi *= 1000;
+			if (count / 1000 < powi) {
+				 written = fprintf(fp, "%u.%u%c",
+					 count / powi, count * 10 / powi % 10, *prefix);
+				 break;
+			}
+			prefix++;
+		}
+	}
+
+	do {
+		fputc(' ', fp);
+	} while (written++ < length);
+}
+
 static void print_link_stats64(FILE *fp, const struct rtnl_link_stats64 *s,
                                const struct rtattr *carrier_changes)
 {
+	/* RX stats */
 	fprintf(fp, "    RX: bytes  packets  errors  dropped overrun mcast   %s%s",
 		s->rx_compressed ? "compressed" : "", _SL_);
-	fprintf(fp, "    %-10"PRIu64" %-8"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64"",
-		(uint64_t)s->rx_bytes,
-		(uint64_t)s->rx_packets,
-		(uint64_t)s->rx_errors,
-		(uint64_t)s->rx_dropped,
-		(uint64_t)s->rx_over_errors,
-		(uint64_t)s->multicast);
-	if (s->rx_compressed)
-		fprintf(fp, " %-7"PRIu64"",
-			(uint64_t)s->rx_compressed);
+	if (human_readable) {
+		fprintf(fp, "    ");
+		print_human64(fp, 10, (uint64_t)s->rx_bytes);
+		print_human64(fp, 8, (uint64_t)s->rx_packets);
+		print_human64(fp, 7, (uint64_t)s->rx_errors);
+		print_human64(fp, 7, (uint64_t)s->rx_dropped);
+		print_human64(fp, 7, (uint64_t)s->rx_over_errors);
+		print_human64(fp, 7, (uint64_t)s->multicast);
+		if (s->rx_compressed)
+			print_human64(fp, 7, (uint64_t)s->rx_compressed);
+	} else {
+		fprintf(fp, "    %-10"PRIu64" %-8"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64"",
+			(uint64_t)s->rx_bytes,
+			(uint64_t)s->rx_packets,
+			(uint64_t)s->rx_errors,
+			(uint64_t)s->rx_dropped,
+			(uint64_t)s->rx_over_errors,
+			(uint64_t)s->multicast);
+		if (s->rx_compressed)
+			fprintf(fp, " %-7"PRIu64"",
+				(uint64_t)s->rx_compressed);
+	}
+
+	/* RX error stats */
 	if (show_stats > 1) {
 		fprintf(fp, "%s", _SL_);
-		fprintf(fp, "    RX errors: length  crc     frame   fifo    missed%s", _SL_);
-		fprintf(fp, "               %-7"PRIu64"  %-7"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64"",
-			(uint64_t)s->rx_length_errors,
-			(uint64_t)s->rx_crc_errors,
-			(uint64_t)s->rx_frame_errors,
-			(uint64_t)s->rx_fifo_errors,
-			(uint64_t)s->rx_missed_errors);
+		fprintf(fp, "    RX errors: length   crc     frame   fifo    missed%s", _SL_);
+		if (human_readable) {
+			fprintf(fp, "               ");
+			print_human64(fp, 8, (uint64_t)s->rx_length_errors);
+			print_human64(fp, 7, (uint64_t)s->rx_crc_errors);
+			print_human64(fp, 7, (uint64_t)s->rx_frame_errors);
+			print_human64(fp, 7, (uint64_t)s->rx_fifo_errors);
+			print_human64(fp, 7, (uint64_t)s->rx_missed_errors);
+		} else {
+			fprintf(fp, "               %-8"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64"",
+				(uint64_t)s->rx_length_errors,
+				(uint64_t)s->rx_crc_errors,
+				(uint64_t)s->rx_frame_errors,
+				(uint64_t)s->rx_fifo_errors,
+				(uint64_t)s->rx_missed_errors);
+		}
 	}
 	fprintf(fp, "%s", _SL_);
+
+	/* TX stats */
 	fprintf(fp, "    TX: bytes  packets  errors  dropped carrier collsns %s%s",
 		(uint64_t)s->tx_compressed ? "compressed" : "", _SL_);
-	fprintf(fp, "    %-10"PRIu64" %-8"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64"",
-		(uint64_t)s->tx_bytes,
-		(uint64_t)s->tx_packets,
-		(uint64_t)s->tx_errors,
-		(uint64_t)s->tx_dropped,
-		(uint64_t)s->tx_carrier_errors,
-		(uint64_t)s->collisions);
-	if (s->tx_compressed)
-		fprintf(fp, " %-7"PRIu64"",
-			(uint64_t)s->tx_compressed);
+	if (human_readable) {
+		fprintf(fp, "    ");
+		print_human64(fp, 10, (uint64_t)s->tx_bytes);
+		print_human64(fp, 8, (uint64_t)s->tx_packets);
+		print_human64(fp, 7, (uint64_t)s->tx_errors);
+		print_human64(fp, 7, (uint64_t)s->tx_dropped);
+		print_human64(fp, 7, (uint64_t)s->tx_carrier_errors);
+		print_human64(fp, 7, (uint64_t)s->collisions);
+		if (s->tx_compressed)
+			print_human64(fp, 7, (uint64_t)s->tx_compressed);
+	} else {
+		fprintf(fp, "    %-10"PRIu64" %-8"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64"",
+			(uint64_t)s->tx_bytes,
+			(uint64_t)s->tx_packets,
+			(uint64_t)s->tx_errors,
+			(uint64_t)s->tx_dropped,
+			(uint64_t)s->tx_carrier_errors,
+			(uint64_t)s->collisions);
+		if (s->tx_compressed)
+			fprintf(fp, " %-7"PRIu64"",
+				(uint64_t)s->tx_compressed);
+	}
+
+	/* TX error stats */
 	if (show_stats > 1) {
 		fprintf(fp, "%s", _SL_);
-		fprintf(fp, "    TX errors: aborted fifo    window  heartbeat");
+		fprintf(fp, "    TX errors: aborted  fifo   window heartbeat");
                 if (carrier_changes)
 			fprintf(fp, " transns");
 		fprintf(fp, "%s", _SL_);
-		fprintf(fp, "               %-7"PRIu64"  %-7"PRIu64" %-7"PRIu64" %-8"PRIu64"",
-			(uint64_t)s->tx_aborted_errors,
-			(uint64_t)s->tx_fifo_errors,
-			(uint64_t)s->tx_window_errors,
-			(uint64_t)s->tx_heartbeat_errors);
-		if (carrier_changes)
-			fprintf(fp, " %-7u",
-				*(uint32_t*)RTA_DATA(carrier_changes));
+		if (human_readable) {
+			fprintf(fp, "               ");
+			print_human64(fp, 8, (uint64_t)s->tx_aborted_errors);
+			print_human64(fp, 7, (uint64_t)s->tx_fifo_errors);
+			print_human64(fp, 7, (uint64_t)s->tx_window_errors);
+			print_human64(fp, 7, (uint64_t)s->tx_heartbeat_errors);
+			if (carrier_changes)
+				print_human64(fp, 7, (uint64_t)*(uint32_t*)RTA_DATA(carrier_changes));
+		} else {
+			fprintf(fp, "               %-8"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64"",
+				(uint64_t)s->tx_aborted_errors,
+				(uint64_t)s->tx_fifo_errors,
+				(uint64_t)s->tx_window_errors,
+				(uint64_t)s->tx_heartbeat_errors);
+			if (carrier_changes)
+				fprintf(fp, " %-7u",
+					*(uint32_t*)RTA_DATA(carrier_changes));
+		}
 	}
 }
 
 static void print_link_stats32(FILE *fp, const struct rtnl_link_stats *s,
 			       const struct rtattr *carrier_changes)
 {
+	/* RX stats */
 	fprintf(fp, "    RX: bytes  packets  errors  dropped overrun mcast   %s%s",
 		s->rx_compressed ? "compressed" : "", _SL_);
-	fprintf(fp, "    %-10u %-8u %-7u %-7u %-7u %-7u",
-		s->rx_bytes, s->rx_packets, s->rx_errors,
-		s->rx_dropped, s->rx_over_errors,
-		s->multicast
-		);
-	if (s->rx_compressed)
-		fprintf(fp, " %-7u", s->rx_compressed);
+	if (human_readable) {
+		fprintf(fp, "    ");
+		print_human32(fp, 10, s->rx_bytes);
+		print_human32(fp, 8, s->rx_packets);
+		print_human32(fp, 7, s->rx_errors);
+		print_human32(fp, 7, s->rx_dropped);
+		print_human32(fp, 7, s->rx_over_errors);
+		print_human32(fp, 7, s->multicast);
+		if (s->rx_compressed)
+			print_human32(fp, 7, s->rx_compressed);
+	} else {
+		fprintf(fp, "    %-10u %-8u %-7u %-7u %-7u %-7u",
+			s->rx_bytes, s->rx_packets, s->rx_errors,
+			s->rx_dropped, s->rx_over_errors,
+			s->multicast);
+		if (s->rx_compressed)
+			fprintf(fp, " %-7u", s->rx_compressed);
+	}
+
+	/* RX error stats */
 	if (show_stats > 1) {
 		fprintf(fp, "%s", _SL_);
-		fprintf(fp, "    RX errors: length  crc     frame   fifo    missed%s", _SL_);
-		fprintf(fp, "               %-7u  %-7u %-7u %-7u %-7u",
-			s->rx_length_errors,
-			s->rx_crc_errors,
-			s->rx_frame_errors,
-			s->rx_fifo_errors,
-			s->rx_missed_errors
-			);
+		fprintf(fp, "    RX errors: length   crc     frame   fifo    missed%s", _SL_);
+		if (human_readable) {
+			fprintf(fp, "               ");
+			print_human32(fp, 8, s->rx_length_errors);
+			print_human32(fp, 7, s->rx_crc_errors);
+			print_human32(fp, 7, s->rx_frame_errors);
+			print_human32(fp, 7, s->rx_fifo_errors);
+			print_human32(fp, 7, s->rx_missed_errors);
+		} else {
+			fprintf(fp, "               %-8u %-7u %-7u %-7u %-7u",
+				s->rx_length_errors,
+				s->rx_crc_errors,
+				s->rx_frame_errors,
+				s->rx_fifo_errors,
+				s->rx_missed_errors);
+		}
 	}
 	fprintf(fp, "%s", _SL_);
+
+	/* TX stats */
 	fprintf(fp, "    TX: bytes  packets  errors  dropped carrier collsns %s%s",
 		s->tx_compressed ? "compressed" : "", _SL_);
-	fprintf(fp, "    %-10u %-8u %-7u %-7u %-7u %-7u",
-		s->tx_bytes, s->tx_packets, s->tx_errors,
-		s->tx_dropped, s->tx_carrier_errors, s->collisions);
-	if (s->tx_compressed)
-		fprintf(fp, " %-7u", s->tx_compressed);
+	if (human_readable) {
+		fprintf(fp, "    ");
+		print_human32(fp, 10, s->tx_bytes);
+		print_human32(fp, 8, s->tx_packets);
+		print_human32(fp, 7, s->tx_errors);
+		print_human32(fp, 7, s->tx_dropped);
+		print_human32(fp, 7, s->tx_carrier_errors);
+		print_human32(fp, 7, s->collisions);
+		if (s->tx_compressed)
+			print_human32(fp, 7, s->tx_compressed);
+	} else {
+		fprintf(fp, "    %-10u %-8u %-7u %-7u %-7u %-7u",
+			s->tx_bytes, s->tx_packets, s->tx_errors,
+			s->tx_dropped, s->tx_carrier_errors, s->collisions);
+		if (s->tx_compressed)
+			fprintf(fp, " %-7u", s->tx_compressed);
+	}
+
+	/* TX error stats */
 	if (show_stats > 1) {
 		fprintf(fp, "%s", _SL_);
-		fprintf(fp, "    TX errors: aborted fifo    window  heartbeat");
+		fprintf(fp, "    TX errors: aborted  fifo   window heartbeat");
                 if (carrier_changes)
 			fprintf(fp, " transns");
 		fprintf(fp, "%s", _SL_);
-		fprintf(fp, "               %-7u  %-7u %-7u %-8u",
-			s->tx_aborted_errors,
-			s->tx_fifo_errors,
-			s->tx_window_errors,
-			s->tx_heartbeat_errors
-			);
-		if (carrier_changes)
-			fprintf(fp, " %-7u",
-				*(uint32_t*)RTA_DATA(carrier_changes));
+		if (human_readable) {
+			fprintf(fp, "               ");
+			print_human32(fp, 8, s->tx_aborted_errors);
+			print_human32(fp, 7, s->tx_fifo_errors);
+			print_human32(fp, 7, s->tx_window_errors);
+			print_human32(fp, 7, s->tx_heartbeat_errors);
+			if (carrier_changes)
+				print_human32(fp, 7, *(uint32_t*)RTA_DATA(carrier_changes));
+		} else {
+			fprintf(fp, "               %-8u %-7u %-7u %-7u",
+				s->tx_aborted_errors,
+				s->tx_fifo_errors,
+				s->tx_window_errors,
+				s->tx_heartbeat_errors);
+			if (carrier_changes)
+				fprintf(fp, " %-7u",
+					*(uint32_t*)RTA_DATA(carrier_changes));
+		}
 	}
 }
 
diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in
index 464009d..9747c4c 100644
--- a/man/man8/ip-link.8.in
+++ b/man/man8/ip-link.8.in
@@ -16,6 +16,7 @@ ip-link \- network device configuration
 .ti -8
 .IR OPTIONS " := { "
 \fB\-V\fR[\fIersion\fR] |
+\fB\-h\fR[\fIuman-readable\fR] |
 \fB\-s\fR[\fItatistics\fR] |
 \fB\-r\fR[\fIesolve\fR] |
 \fB\-f\fR[\fIamily\fR] {
@@ -660,6 +661,12 @@ specifies what group of devices to show.
 .B up
 only display running interfaces.
 
+.SH "NOTES"
+Human readable values are calculated with SI prefixes, so with a decimal
+base, not binary. (This is unlike
+.BR ifconfig (8)
+, with uses binary prefix.) 1,000 bytes are 1 kB, 1,000 kB are 1 MB, ...
+
 .SH "EXAMPLES"
 .PP
 ip link show
-- 
2.1.3

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v4 1/1] ip-link: add switch to show human readable output
  2014-10-31 21:33         ` [PATCH v4 " Christian Hesse
@ 2014-11-02 20:51           ` Stephen Hemminger
  2014-11-03  6:53             ` Christian Hesse
  0 siblings, 1 reply; 8+ messages in thread
From: Stephen Hemminger @ 2014-11-02 20:51 UTC (permalink / raw)
  To: Christian Hesse; +Cc: netdev

On Fri, 31 Oct 2014 22:33:13 +0100
Christian Hesse <mail@eworm.de> wrote:

> Byte and packet count can increase to really big numbers. This adds a
> switch to show human readable output.
> 
> 4: wl: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DORMANT group default qlen 1000
>     link/ether 00:de:ad:be:ee:ef brd ff:ff:ff:ff:ff:ff
>     RX: bytes  packets  errors  dropped overrun mcast
>     1523846973 3969051  0       0       0       0
>     TX: bytes  packets  errors  dropped carrier collsns
>     8710088361 6077735  0       0       0       0
> 4: wl: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DORMANT group default qlen 1000
>     link/ether 00:de:ad:be:ee:ef brd ff:ff:ff:ff:ff:ff
>     RX: bytes  packets  errors  dropped overrun mcast
>     1.5G       3.9M     0       0       0       0
>     TX: bytes  packets  errors  dropped carrier collsns
>     8.7G       6.0M     0       0       0       0

Applied, then I did a code cleanup and added -iec as a option (similar to tc).

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v4 1/1] ip-link: add switch to show human readable output
  2014-11-02 20:51           ` Stephen Hemminger
@ 2014-11-03  6:53             ` Christian Hesse
  0 siblings, 0 replies; 8+ messages in thread
From: Christian Hesse @ 2014-11-03  6:53 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev

[-- Attachment #1: Type: text/plain, Size: 1334 bytes --]

Stephen Hemminger <stephen@networkplumber.org> on Sun, 2014/11/02 12:51:
> On Fri, 31 Oct 2014 22:33:13 +0100
> Christian Hesse <mail@eworm.de> wrote:
> 
> > Byte and packet count can increase to really big numbers. This adds a
> > switch to show human readable output.
> > 
> > 4: wl: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode
> > DORMANT group default qlen 1000 link/ether 00:de:ad:be:ee:ef brd
> > ff:ff:ff:ff:ff:ff RX: bytes  packets  errors  dropped overrun mcast
> >     1523846973 3969051  0       0       0       0
> >     TX: bytes  packets  errors  dropped carrier collsns
> >     8710088361 6077735  0       0       0       0
> > 4: wl: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode
> > DORMANT group default qlen 1000 link/ether 00:de:ad:be:ee:ef brd
> > ff:ff:ff:ff:ff:ff RX: bytes  packets  errors  dropped overrun mcast
> >     1.5G       3.9M     0       0       0       0
> >     TX: bytes  packets  errors  dropped carrier collsns
> >     8.7G       6.0M     0       0       0       0
> 
> Applied, then I did a code cleanup and added -iec as a option (similar to
> tc).

I would have come up with something similar later. ;) Thanks a lot!
I am perfectly happy now and can live without ifconfig in the future.
-- 
Best regards,
Christian Hesse

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2014-11-03  6:53 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-10-10 22:27 [PATCHv2 1/1] ip-link: add switch to show human readable output Christian Hesse
2014-10-30  5:47 ` Stephen Hemminger
2014-10-30  9:16   ` [PATCH v3 " Christian Hesse
2014-10-31 10:17     ` Christian Hesse
2014-10-31 19:31       ` Stephen Hemminger
2014-10-31 21:33         ` [PATCH v4 " Christian Hesse
2014-11-02 20:51           ` Stephen Hemminger
2014-11-03  6:53             ` Christian Hesse

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.