netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc
@ 2018-07-10 21:05 Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 01/31] tc: use JSON in error handling Stephen Hemminger
                   ` (30 more replies)
  0 siblings, 31 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

This patch set adds some utility routines and then converts all
the remaining TC queue discipline managers to support JSON output.

v2
  - consolidate the utility patches
  - do all the remaining qdisc's

Stephen Hemminger (31):
  tc: use JSON in error handling
  tc: use const char in util
  tc: convert stats print to json
  tc/cbq: use sprint_rate
  tc/util: remove unused print functions
  tc/util: add print helpers for JSON
  tc/red: use new JSON helpers
  tc/sfq: add json support
  tc/fq: support JSON output
  tc/mqprio: implement JSON output
  tc/drr: implement JSON output
  tc/rr: implement JSON output
  tc/qfq: implement JSON
  tc/sfb: implement JSON output
  tc/multiq: implement JSON output
  tc/util: allow signed value for time
  tc/codel: implement JSON output
  tc/fifo: implement JSON output
  tc/tbf: implement JSON output format
  tc/choke: implement JSON output
  tc/hhf: implement JSON output
  tc/pie: implement JSON output
  tc/gred: implement JSON output
  tc/netem: implement JSON output
  tc/dsmark: implement JSON output
  tc/cbs: convert to JSON output
  tc/cbq: convert to JSON output
  tc/atm: convert to JSON output
  tc/hfsc: convert to JSON output
  tc/htb: implement JSON output
  tc/fq_codel: use JSON helpers

 tc/q_atm.c      |  38 +++++++------
 tc/q_cbq.c      |  80 ++++++++++++++-------------
 tc/q_cbs.c      |  10 ++--
 tc/q_choke.c    |  25 +++++----
 tc/q_codel.c    |  35 ++++++------
 tc/q_drr.c      |  10 ++--
 tc/q_dsmark.c   |  27 ++++++----
 tc/q_fifo.c     |   9 ++--
 tc/q_fq.c       | 103 ++++++++++++++++++++---------------
 tc/q_fq_codel.c |  38 ++++---------
 tc/q_gred.c     |  73 +++++++++++++------------
 tc/q_hfsc.c     |  26 ++++-----
 tc/q_hhf.c      |  24 ++++-----
 tc/q_htb.c      |  53 ++++++++++--------
 tc/q_mqprio.c   | 134 ++++++++++++++++++++++++---------------------
 tc/q_multiq.c   |   3 +-
 tc/q_netem.c    |  94 ++++++++++++++++----------------
 tc/q_pie.c      |  33 ++++++------
 tc/q_qfq.c      |   8 +--
 tc/q_red.c      |  13 ++---
 tc/q_rr.c       |  16 ++++--
 tc/q_sfb.c      |  56 +++++++++++--------
 tc/q_sfq.c      |  65 +++++++++++++---------
 tc/q_tbf.c      |  48 +++++++++--------
 tc/tc.c         |  19 ++++---
 tc/tc_util.c    | 140 ++++++++++++++++++++++++++++--------------------
 tc/tc_util.h    |  18 ++++---
 27 files changed, 648 insertions(+), 550 deletions(-)

-- 
2.18.0

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

* [PATCH v2 iproute2-next 01/31] tc: use JSON in error handling
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 02/31] tc: use const char in util Stephen Hemminger
                   ` (29 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

If option or qdisc is unknown, still output in JSON.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/tc.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/tc/tc.c b/tc/tc.c
index 0d223281ba25..b6d2a6151793 100644
--- a/tc/tc.c
+++ b/tc/tc.c
@@ -56,9 +56,11 @@ static struct filter_util *filter_list;
 static int print_noqopt(struct qdisc_util *qu, FILE *f,
 			struct rtattr *opt)
 {
-	if (opt && RTA_PAYLOAD(opt))
-		fprintf(f, "[Unknown qdisc, optlen=%u] ",
-			(unsigned int) RTA_PAYLOAD(opt));
+	if (opt && RTA_PAYLOAD(opt)) {
+		print_string(PRINT_JSON, "qdisc", NULL, "UNKNOWN");
+		print_uint(PRINT_ANY, "optlen", "[Unknown qdisc, optlen=%u] ",
+			   RTA_PAYLOAD(opt));
+	}
 	return 0;
 }
 
@@ -76,11 +78,12 @@ static int parse_noqopt(struct qdisc_util *qu, int argc, char **argv,
 
 static int print_nofopt(struct filter_util *qu, FILE *f, struct rtattr *opt, __u32 fhandle)
 {
-	if (opt && RTA_PAYLOAD(opt))
-		fprintf(f, "fh %08x [Unknown filter, optlen=%u] ",
-			fhandle, (unsigned int) RTA_PAYLOAD(opt));
-	else if (fhandle)
-		fprintf(f, "fh %08x ", fhandle);
+	if (opt && RTA_PAYLOAD(opt)) {
+		print_0xhex(PRINT_ANY, "handle", "fh %08x ", fhandle);
+		print_uint(PRINT_ANY, "optlen", "[Unknown filter, optlen=%u] ",
+			RTA_PAYLOAD(opt));
+	} else if (fhandle)
+		print_0xhex(PRINT_ANY, "handle", "fh %08x ", fhandle);
 	return 0;
 }
 
-- 
2.18.0

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

* [PATCH v2 iproute2-next 02/31] tc: use const char in util
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 01/31] tc: use JSON in error handling Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 03/31] tc: convert stats print to json Stephen Hemminger
                   ` (28 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

For prefix and path, can use const char.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/tc_util.c | 8 +++++---
 tc/tc_util.h | 6 +++---
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/tc/tc_util.c b/tc/tc_util.c
index e0c96291ade0..e8e1241d083d 100644
--- a/tc/tc_util.c
+++ b/tc/tc_util.c
@@ -35,7 +35,7 @@ static struct db_names *cls_names;
 
 #define NAMES_DB "/etc/iproute2/tc_cls"
 
-int cls_names_init(char *path)
+int cls_names_init(const char *path)
 {
 	int ret;
 
@@ -800,7 +800,8 @@ void print_tm(FILE *f, const struct tcf_t *tm)
 	}
 }
 
-void print_tcstats2_attr(FILE *fp, struct rtattr *rta, char *prefix, struct rtattr **xstats)
+void print_tcstats2_attr(FILE *fp, struct rtattr *rta,
+			 const char *prefix, struct rtattr **xstats)
 {
 	SPRINT_BUF(b1);
 	struct rtattr *tbs[TCA_STATS_MAX + 1];
@@ -868,7 +869,8 @@ void print_tcstats2_attr(FILE *fp, struct rtattr *rta, char *prefix, struct rtat
 		*xstats = tbs[TCA_STATS_APP] ? : NULL;
 }
 
-void print_tcstats_attr(FILE *fp, struct rtattr *tb[], char *prefix, struct rtattr **xstats)
+void print_tcstats_attr(FILE *fp, struct rtattr *tb[],
+			const char *prefix, struct rtattr **xstats)
 {
 	SPRINT_BUF(b1);
 
diff --git a/tc/tc_util.h b/tc/tc_util.h
index 6632c4f9c528..64b309903c69 100644
--- a/tc/tc_util.h
+++ b/tc/tc_util.h
@@ -100,9 +100,9 @@ char *sprint_ticks(__u32 ticks, char *buf);
 char *sprint_linklayer(unsigned int linklayer, char *buf);
 
 void print_tcstats_attr(FILE *fp, struct rtattr *tb[],
-			char *prefix, struct rtattr **xstats);
+			const char *prefix, struct rtattr **xstats);
 void print_tcstats2_attr(FILE *fp, struct rtattr *rta,
-			 char *prefix, struct rtattr **xstats);
+			 const char *prefix, struct rtattr **xstats);
 
 int get_tc_classid(__u32 *h, const char *str);
 int print_tc_classid(char *buf, int len, __u32 h);
@@ -130,7 +130,7 @@ int parse_action(int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n);
 void print_tm(FILE *f, const struct tcf_t *tm);
 int prio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt);
 
-int cls_names_init(char *path);
+int cls_names_init(const char *path);
 void cls_names_uninit(void);
 
 int action_a2n(char *arg, int *result, bool allow_num);
-- 
2.18.0

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

* [PATCH v2 iproute2-next 03/31] tc: convert stats print to json
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 01/31] tc: use JSON in error handling Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 02/31] tc: use const char in util Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 04/31] tc/cbq: use sprint_rate Stephen Hemminger
                   ` (27 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

Convert compatiablity statistics to print in JSON.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/tc_util.c | 32 ++++++++++++++++++++++----------
 1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/tc/tc_util.c b/tc/tc_util.c
index e8e1241d083d..05b6c97563b3 100644
--- a/tc/tc_util.c
+++ b/tc/tc_util.c
@@ -887,25 +887,37 @@ void print_tcstats_attr(FILE *fp, struct rtattr *tb[],
 		/* handle case where kernel returns more/less than we know about */
 		memcpy(&st, RTA_DATA(tb[TCA_STATS]), MIN(RTA_PAYLOAD(tb[TCA_STATS]), sizeof(st)));
 
-		fprintf(fp, "%sSent %llu bytes %u pkts (dropped %u, overlimits %u) ",
-			prefix, (unsigned long long)st.bytes, st.packets, st.drops,
-			st.overlimits);
+		print_string(PRINT_FP, NULL, "%sSent ", prefix);
+		print_u64(PRINT_ANY, "bytes", "%llu bytes ", (unsigned long long)st.bytes);
+		print_uint(PRINT_ANY, "packets", "%u pkts ", st.packets);
+		print_uint(PRINT_ANY, "dropped", "(dropped %u, ", st.drops);
+		print_uint(PRINT_ANY, "overlimits", "overlimits %u) ", st.overlimits);
 
 		if (st.bps || st.pps || st.qlen || st.backlog) {
-			fprintf(fp, "\n%s", prefix);
+			print_string(PRINT_FP, "%s%s", _SL_, prefix);
+
 			if (st.bps || st.pps) {
-				fprintf(fp, "rate ");
+				print_string(PRINT_FP, NULL, "%s", "rate ");
+				print_uint(PRINT_JSON, "rate", NULL, st.bps);
 				if (st.bps)
-					fprintf(fp, "%s ", sprint_rate(st.bps, b1));
+					print_string(PRINT_FP, NULL, "%s ",
+						     sprint_rate(st.bps, b1));
+
+				print_uint(PRINT_JSON, "pps", NULL, st.pps);
 				if (st.pps)
-					fprintf(fp, "%upps ", st.pps);
+					print_uint(PRINT_FP, NULL, "%upps ", st.pps);
 			}
 			if (st.qlen || st.backlog) {
-				fprintf(fp, "backlog ");
+				print_string(PRINT_FP, NULL, "%s", "backlog ");
+
+				print_uint(PRINT_JSON, "backlog", NULL, st.backlog);
+				print_uint(PRINT_JSON, "qlen", NULL, st.qlen);
 				if (st.backlog)
-					fprintf(fp, "%s ", sprint_size(st.backlog, b1));
+					print_string(PRINT_FP, NULL,
+						     "%s ", sprint_size(st.backlog, b1));
 				if (st.qlen)
-					fprintf(fp, "%up ", st.qlen);
+					print_uint(PRINT_FP, NULL,
+						     "%up ", st.qlen);
 			}
 		}
 	}
-- 
2.18.0

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

* [PATCH v2 iproute2-next 04/31] tc/cbq: use sprint_rate
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (2 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 03/31] tc: convert stats print to json Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 05/31] tc/util: remove unused print functions Stephen Hemminger
                   ` (26 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

All other places in tc use sprint_rate.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/q_cbq.c | 15 ++++++---------
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/tc/q_cbq.c b/tc/q_cbq.c
index e7f1a3bfaf5d..ad0170c41858 100644
--- a/tc/q_cbq.c
+++ b/tc/q_cbq.c
@@ -495,10 +495,9 @@ static int cbq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	}
 
 	if (r) {
-		char buf[64];
 
-		print_rate(buf, sizeof(buf), r->rate);
-		fprintf(f, "rate %s ", buf);
+		fprintf(f, "rate %s ",
+			sprint_rate(r->rate, b1));
 		linklayer = (r->linklayer & TC_LINKLAYER_MASK);
 		if (linklayer > TC_LINKLAYER_ETHERNET || show_details)
 			fprintf(f, "linklayer %s ", sprint_linklayer(linklayer, b2));
@@ -530,14 +529,12 @@ static int cbq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 			fprintf(f, "prio %u", wrr->priority);
 		else
 			fprintf(f, "prio no-transmit");
-		if (show_details) {
-			char buf[64];
 
+		if (show_details) {
 			fprintf(f, "/%u ", wrr->cpriority);
-			if (wrr->weight != 1) {
-				print_rate(buf, sizeof(buf), wrr->weight);
-				fprintf(f, "weight %s ", buf);
-			}
+			if (wrr->weight != 1)
+				fprintf(f, "weight %s ",
+					sprint_rate(wrr->weight, b1));
 			if (wrr->allot)
 				fprintf(f, "allot %ub ", wrr->allot);
 		}
-- 
2.18.0

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

* [PATCH v2 iproute2-next 05/31] tc/util: remove unused print functions
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (3 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 04/31] tc/cbq: use sprint_rate Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 06/31] tc/util: add print helpers for JSON Stephen Hemminger
                   ` (25 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

The functions for printing rate/time/size, etc are not
used by current code. Next patch will repurpose these for
JSON format output.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/tc_util.c | 49 ++++++++++++++++++-------------------------------
 tc/tc_util.h |  4 ----
 2 files changed, 18 insertions(+), 35 deletions(-)

diff --git a/tc/tc_util.c b/tc/tc_util.c
index 05b6c97563b3..29bdbbff4a6e 100644
--- a/tc/tc_util.c
+++ b/tc/tc_util.c
@@ -307,7 +307,7 @@ int get_rate64(__u64 *rate, const char *str)
 	return 0;
 }
 
-void print_rate(char *buf, int len, __u64 rate)
+char *sprint_rate(__u64 rate, char *buf)
 {
 	extern int use_iec;
 	unsigned long kilo = use_iec ? 1024 : 1000;
@@ -325,12 +325,8 @@ void print_rate(char *buf, int len, __u64 rate)
 		rate /= kilo;
 	}
 
-	snprintf(buf, len, "%.0f%s%sbit", (double)rate, units[i], str);
-}
-
-char *sprint_rate(__u64 rate, char *buf)
-{
-	print_rate(buf, SPRINT_BSIZE-1, rate);
+	snprintf(buf, SPRINT_BSIZE-1,
+		 "%.0f%s%sbit", (double)rate, units[i], str);
 	return buf;
 }
 
@@ -361,9 +357,9 @@ int get_time(unsigned int *time, const char *str)
 	return 0;
 }
 
-
-void print_time(char *buf, int len, __u32 time)
+char *sprint_time(__u32 time, char *buf)
 {
+	const size_t len = SPRINT_BSIZE - 1;
 	double tmp = time;
 
 	if (tmp >= TIME_UNITS_PER_SEC)
@@ -372,11 +368,7 @@ void print_time(char *buf, int len, __u32 time)
 		snprintf(buf, len, "%.1fms", tmp/(TIME_UNITS_PER_SEC/1000));
 	else
 		snprintf(buf, len, "%uus", time);
-}
 
-char *sprint_time(__u32 time, char *buf)
-{
-	print_time(buf, SPRINT_BSIZE-1, time);
 	return buf;
 }
 
@@ -455,8 +447,9 @@ void print_devname(enum output_type type, int ifindex)
 			   "dev", "%s ", ifname);
 }
 
-void print_size(char *buf, int len, __u32 sz)
+char *sprint_size(__u32 sz, char *buf)
 {
+	const size_t len = SPRINT_BSIZE - 1;
 	double tmp = sz;
 
 	if (sz >= 1024*1024 && fabs(1024*1024*rint(tmp/(1024*1024)) - sz) < 1024)
@@ -465,11 +458,7 @@ void print_size(char *buf, int len, __u32 sz)
 		snprintf(buf, len, "%gKb", rint(tmp/1024));
 	else
 		snprintf(buf, len, "%ub", sz);
-}
 
-char *sprint_size(__u32 size, char *buf)
-{
-	print_size(buf, SPRINT_BSIZE-1, size);
 	return buf;
 }
 
@@ -755,27 +744,25 @@ int get_linklayer(unsigned int *val, const char *arg)
 	return 0;
 }
 
-void print_linklayer(char *buf, int len, unsigned int linklayer)
+char *sprint_linklayer(unsigned int linklayer, char *buf)
 {
+	const size_t len = SPRINT_BSIZE - 1;
+
 	switch (linklayer) {
 	case LINKLAYER_UNSPEC:
-		snprintf(buf, len, "%s", "unspec");
-		return;
+		strlcpy(buf, "unspec", len);
+		break;
 	case LINKLAYER_ETHERNET:
-		snprintf(buf, len, "%s", "ethernet");
-		return;
+		strlcpy(buf, "ethernet", len);
+		break;
 	case LINKLAYER_ATM:
-		snprintf(buf, len, "%s", "atm");
-		return;
+		strlcpy(buf, "atm", len);
+		break;
 	default:
-		snprintf(buf, len, "%s", "unknown");
-		return;
+		strlcpy(buf, "unknown", len);
+		break;
 	}
-}
 
-char *sprint_linklayer(unsigned int linklayer, char *buf)
-{
-	print_linklayer(buf, SPRINT_BSIZE-1, linklayer);
 	return buf;
 }
 
diff --git a/tc/tc_util.h b/tc/tc_util.h
index 64b309903c69..1690ad262351 100644
--- a/tc/tc_util.h
+++ b/tc/tc_util.h
@@ -84,11 +84,7 @@ int get_size_and_cell(unsigned int *size, int *cell_log, char *str);
 int get_time(unsigned int *time, const char *str);
 int get_linklayer(unsigned int *val, const char *arg);
 
-void print_rate(char *buf, int len, __u64 rate);
-void print_size(char *buf, int len, __u32 size);
 void print_qdisc_handle(char *buf, int len, __u32 h);
-void print_time(char *buf, int len, __u32 time);
-void print_linklayer(char *buf, int len, unsigned int linklayer);
 void print_devname(enum output_type type, int ifindex);
 
 char *sprint_rate(__u64 rate, char *buf);
-- 
2.18.0

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

* [PATCH v2 iproute2-next 06/31] tc/util: add print helpers for JSON
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (4 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 05/31] tc/util: remove unused print functions Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-17  1:05   ` David Ahern
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 07/31] tc/red: use new JSON helpers Stephen Hemminger
                   ` (24 subsequent siblings)
  30 siblings, 1 reply; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

Add a helper to print rate, time and size in numeric or pretty format
based on JSON flag.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/tc_util.c | 83 +++++++++++++++++++++++++++++++++-------------------
 tc/tc_util.h |  6 ++++
 2 files changed, 59 insertions(+), 30 deletions(-)

diff --git a/tc/tc_util.c b/tc/tc_util.c
index 29bdbbff4a6e..43a67fd13f94 100644
--- a/tc/tc_util.c
+++ b/tc/tc_util.c
@@ -330,6 +330,19 @@ char *sprint_rate(__u64 rate, char *buf)
 	return buf;
 }
 
+/*
+ * print rate as numeric in JSON
+ * or in human format otherwise.
+ */
+void print_rate(const char *key, const char *fmt, __u64 rate)
+{
+	SPRINT_BUF(b1);
+
+	print_u64(PRINT_JSON, key, NULL, rate);
+	print_string(PRINT_FP, NULL, fmt,
+		     sprint_rate(rate, b1));
+}
+
 int get_time(unsigned int *time, const char *str)
 {
 	double t;
@@ -372,11 +385,27 @@ char *sprint_time(__u32 time, char *buf)
 	return buf;
 }
 
+void print_time(const char *key, const char *fmt, __u32 tm)
+{
+	double secs = (double)tm / TIME_UNITS_PER_SEC;
+	SPRINT_BUF(b1);
+
+	print_float(PRINT_JSON, key, NULL, secs);
+	print_string(PRINT_FP, NULL, fmt,
+		     sprint_time(tm, b1));
+}
+
+
 char *sprint_ticks(__u32 ticks, char *buf)
 {
 	return sprint_time(tc_core_tick2time(ticks), buf);
 }
 
+void print_ticks(const char *key, const char *fmt, __u32 ticks)
+{
+	print_time(key, fmt, tc_core_tick2time(ticks));
+}
+
 int get_size(unsigned int *size, const char *str)
 {
 	double sz;
@@ -462,6 +491,15 @@ char *sprint_size(__u32 sz, char *buf)
 	return buf;
 }
 
+void print_size(const char *key, const char *fmt, __u32 sz)
+{
+	SPRINT_BUF(b1);
+
+	print_uint(PRINT_JSON, key, NULL, sz);
+	print_string(PRINT_FP, NULL, fmt,
+		     sprint_size(sz, b1));
+}
+
 void print_qdisc_handle(char *buf, int len, __u32 h)
 {
 	snprintf(buf, len, "%x:", TC_H_MAJ(h)>>16);
@@ -766,6 +804,14 @@ char *sprint_linklayer(unsigned int linklayer, char *buf)
 	return buf;
 }
 
+void print_linklayer(const char *key, const char *fmt, unsigned int linklayer)
+{
+	SPRINT_BUF(b1);
+
+	sprint_linklayer(linklayer, b1);
+	print_string(PRINT_ANY, key, fmt, b1);
+}
+
 void print_tm(FILE *f, const struct tcf_t *tm)
 {
 	int hz = get_user_hz();
@@ -790,7 +836,6 @@ void print_tm(FILE *f, const struct tcf_t *tm)
 void print_tcstats2_attr(FILE *fp, struct rtattr *rta,
 			 const char *prefix, struct rtattr **xstats)
 {
-	SPRINT_BUF(b1);
 	struct rtattr *tbs[TCA_STATS_MAX + 1];
 
 	parse_rtattr_nested(tbs, TCA_STATS_MAX, rta);
@@ -821,21 +866,15 @@ void print_tcstats2_attr(FILE *fp, struct rtattr *rta,
 		       MIN(RTA_PAYLOAD(tbs[TCA_STATS_RATE_EST64]),
 			   sizeof(re)));
 		print_string(PRINT_FP, NULL, "\n%s", prefix);
-		print_lluint(PRINT_JSON, "rate", NULL, re.bps);
-		print_string(PRINT_FP, NULL, "rate %s",
-			     sprint_rate(re.bps, b1));
+		print_rate("rate", "rate %s", re.bps);
 		print_lluint(PRINT_ANY, "pps", " %llupps", re.pps);
 	} else if (tbs[TCA_STATS_RATE_EST]) {
 		struct gnet_stats_rate_est re = {0};
 
 		memcpy(&re, RTA_DATA(tbs[TCA_STATS_RATE_EST]),
 		       MIN(RTA_PAYLOAD(tbs[TCA_STATS_RATE_EST]), sizeof(re)));
-		fprintf(fp, "\n%srate %s %upps ",
-			prefix, sprint_rate(re.bps, b1), re.pps);
 		print_string(PRINT_FP, NULL, "\n%s", prefix);
-		print_uint(PRINT_JSON, "rate", NULL, re.bps);
-		print_string(PRINT_FP, NULL, "rate %s",
-			     sprint_rate(re.bps, b1));
+		print_rate("rate", "rate %s", re.bps);
 		print_uint(PRINT_ANY, "pps", " %upps", re.pps);
 	}
 
@@ -845,9 +884,7 @@ void print_tcstats2_attr(FILE *fp, struct rtattr *rta,
 		memcpy(&q, RTA_DATA(tbs[TCA_STATS_QUEUE]), MIN(RTA_PAYLOAD(tbs[TCA_STATS_QUEUE]), sizeof(q)));
 		if (!tbs[TCA_STATS_RATE_EST])
 			print_string(PRINT_FP, NULL, "\n%s", prefix);
-		print_uint(PRINT_JSON, "backlog", NULL, q.backlog);
-		print_string(PRINT_FP, NULL, "backlog %s",
-			     sprint_size(q.backlog, b1));
+		print_size("backlog",  "backlog %s", q.backlog);
 		print_uint(PRINT_ANY, "qlen", " %up", q.qlen);
 		print_uint(PRINT_FP, NULL, " requeues %u", q.requeues);
 	}
@@ -859,8 +896,6 @@ void print_tcstats2_attr(FILE *fp, struct rtattr *rta,
 void print_tcstats_attr(FILE *fp, struct rtattr *tb[],
 			const char *prefix, struct rtattr **xstats)
 {
-	SPRINT_BUF(b1);
-
 	if (tb[TCA_STATS2]) {
 		print_tcstats2_attr(fp, tb[TCA_STATS2], prefix, xstats);
 		if (xstats && NULL == *xstats)
@@ -885,26 +920,14 @@ void print_tcstats_attr(FILE *fp, struct rtattr *tb[],
 
 			if (st.bps || st.pps) {
 				print_string(PRINT_FP, NULL, "%s", "rate ");
-				print_uint(PRINT_JSON, "rate", NULL, st.bps);
-				if (st.bps)
-					print_string(PRINT_FP, NULL, "%s ",
-						     sprint_rate(st.bps, b1));
-
-				print_uint(PRINT_JSON, "pps", NULL, st.pps);
-				if (st.pps)
-					print_uint(PRINT_FP, NULL, "%upps ", st.pps);
+				print_rate("rate", "%s ", st.bps);
+				print_uint(PRINT_JSON, "pps", "%upps ", st.pps);
 			}
 			if (st.qlen || st.backlog) {
 				print_string(PRINT_FP, NULL, "%s", "backlog ");
 
-				print_uint(PRINT_JSON, "backlog", NULL, st.backlog);
-				print_uint(PRINT_JSON, "qlen", NULL, st.qlen);
-				if (st.backlog)
-					print_string(PRINT_FP, NULL,
-						     "%s ", sprint_size(st.backlog, b1));
-				if (st.qlen)
-					print_uint(PRINT_FP, NULL,
-						     "%up ", st.qlen);
+				print_size("backlog", "%s ", st.backlog);
+				print_uint(PRINT_ANY, "qlen", "%up ", st.qlen);
 			}
 		}
 	}
diff --git a/tc/tc_util.h b/tc/tc_util.h
index 1690ad262351..e83bb7dbcc76 100644
--- a/tc/tc_util.h
+++ b/tc/tc_util.h
@@ -87,6 +87,12 @@ int get_linklayer(unsigned int *val, const char *arg);
 void print_qdisc_handle(char *buf, int len, __u32 h);
 void print_devname(enum output_type type, int ifindex);
 
+void print_rate(const char *key, const char *fmt, __u64 rate);
+void print_size(const char *key, const char *fmt, __u32 sz);
+void print_time(const char *key, const char *fmt, __s32 tm);
+void print_ticks(const char *key, const char *fmt, __u32 ticks);
+void print_linklayer(const char *key, const char *fmt, unsigned int linklayer);
+
 char *sprint_rate(__u64 rate, char *buf);
 char *sprint_size(__u32 size, char *buf);
 char *sprint_qdisc_handle(__u32 h, char *buf);
-- 
2.18.0

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

* [PATCH v2 iproute2-next 07/31] tc/red: use new JSON helpers
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (5 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 06/31] tc/util: add print helpers for JSON Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 08/31] tc/sfq: add json support Stephen Hemminger
                   ` (23 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

Now have simplier way to print size.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/q_red.c | 13 +++----------
 1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/tc/q_red.c b/tc/q_red.c
index 49fd4ac80513..9e4124befdb7 100644
--- a/tc/q_red.c
+++ b/tc/q_red.c
@@ -163,10 +163,6 @@ static int red_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	struct tc_red_qopt *qopt;
 	__u32 max_P = 0;
 
-	SPRINT_BUF(b1);
-	SPRINT_BUF(b2);
-	SPRINT_BUF(b3);
-
 	if (opt == NULL)
 		return 0;
 
@@ -182,12 +178,9 @@ static int red_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	    RTA_PAYLOAD(tb[TCA_RED_MAX_P]) >= sizeof(__u32))
 		max_P = rta_getattr_u32(tb[TCA_RED_MAX_P]);
 
-	print_uint(PRINT_JSON, "limit", NULL, qopt->limit);
-	print_string(PRINT_FP, NULL, "limit %s ", sprint_size(qopt->limit, b1));
-	print_uint(PRINT_JSON, "min", NULL, qopt->qth_min);
-	print_string(PRINT_FP, NULL, "min %s ", sprint_size(qopt->qth_min, b2));
-	print_uint(PRINT_JSON, "max", NULL, qopt->qth_max);
-	print_string(PRINT_FP, NULL, "max %s ", sprint_size(qopt->qth_max, b3));
+	print_size("limit", "limit %s ", qopt->limit);
+	print_size("min", "min %s ", qopt->qth_min);
+	print_size("max", "max %s ", qopt->qth_max);
 
 	if (qopt->flags & TC_RED_ECN)
 		print_bool(PRINT_ANY, "ecn", "ecn ", true);
-- 
2.18.0

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

* [PATCH v2 iproute2-next 08/31] tc/sfq: add json support
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (6 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 07/31] tc/red: use new JSON helpers Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 09/31] tc/fq: support JSON output Stephen Hemminger
                   ` (22 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

Convert to use JSON

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/q_sfq.c | 65 ++++++++++++++++++++++++++++++++----------------------
 1 file changed, 39 insertions(+), 26 deletions(-)

diff --git a/tc/q_sfq.c b/tc/q_sfq.c
index 6a1d853b7c93..a813c055b92e 100644
--- a/tc/q_sfq.c
+++ b/tc/q_sfq.c
@@ -205,9 +205,6 @@ static int sfq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	struct tc_sfq_qopt *qopt;
 	struct tc_sfq_qopt_v1 *qopt_ext = NULL;
 
-	SPRINT_BUF(b1);
-	SPRINT_BUF(b2);
-	SPRINT_BUF(b3);
 	if (opt == NULL)
 		return 0;
 
@@ -216,36 +213,53 @@ static int sfq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	if (RTA_PAYLOAD(opt) >= sizeof(*qopt_ext))
 		qopt_ext = RTA_DATA(opt);
 	qopt = RTA_DATA(opt);
-	fprintf(f, "limit %up ", qopt->limit);
-	fprintf(f, "quantum %s ", sprint_size(qopt->quantum, b1));
+
+	print_uint(PRINT_ANY, "limit", "limit %up ", qopt->limit);
+	print_size("quantum", "quantum %s ", qopt->quantum);
+
 	if (qopt_ext && qopt_ext->depth)
-		fprintf(f, "depth %u ", qopt_ext->depth);
+		print_uint(PRINT_ANY, "depth",
+			   "depth %u ", qopt_ext->depth);
 	if (qopt_ext && qopt_ext->headdrop)
-		fprintf(f, "headdrop ");
+		print_null(PRINT_ANY, "headdrop", "headdrop ", NULL);
 
 	if (show_details) {
-		fprintf(f, "flows %u/%u ", qopt->flows, qopt->divisor);
+		print_uint(PRINT_ANY, "flows", "flows %u", qopt->flows);
+		print_uint(PRINT_ANY, "divisor", "/%u ", qopt->divisor);
+	} else {
+		print_uint(PRINT_ANY, "divisor", "divisor %u ", qopt->divisor);
 	}
-	fprintf(f, "divisor %u ", qopt->divisor);
+
 	if (qopt->perturb_period)
-		fprintf(f, "perturb %dsec ", qopt->perturb_period);
+		print_int(PRINT_ANY, "perturb",
+			  "perturb %dsec ", qopt->perturb_period);
+
 	if (qopt_ext && qopt_ext->qth_min) {
-		fprintf(f, "\n ewma %u ", qopt_ext->Wlog);
-		fprintf(f, "min %s max %s probability %g ",
-			sprint_size(qopt_ext->qth_min, b2),
-			sprint_size(qopt_ext->qth_max, b3),
-			qopt_ext->max_P / pow(2, 32));
+		print_string(PRINT_FP, NULL, "%s", _SL_);
+		print_uint(PRINT_ANY, "ewma", " ewma %u ", qopt_ext->Wlog);
+		print_size("qth_min", "min %s", qopt_ext->qth_min);
+		print_size("qth_max", "max %s ", qopt_ext->qth_max);
+		print_float(PRINT_ANY, "probability", "probability %g ",
+			    qopt_ext->max_P / pow(2, 32));
+
 		if (qopt_ext->flags & TC_RED_ECN)
-			fprintf(f, "ecn ");
+			print_null(PRINT_ANY, "ecn", "ecn ", NULL);
+
 		if (show_stats) {
-			fprintf(f, "\n prob_mark %u prob_mark_head %u prob_drop %u",
-				qopt_ext->stats.prob_mark,
-				qopt_ext->stats.prob_mark_head,
-				qopt_ext->stats.prob_drop);
-			fprintf(f, "\n forced_mark %u forced_mark_head %u forced_drop %u",
-				qopt_ext->stats.forced_mark,
-				qopt_ext->stats.forced_mark_head,
-				qopt_ext->stats.forced_drop);
+			print_string(PRINT_FP, NULL, "%s", _SL_);
+			print_uint(PRINT_ANY, "prob_mark", " prob_mark %u",
+				   qopt_ext->stats.prob_mark);
+			print_uint(PRINT_ANY, "prob_mark_head", " prob_mark_head %u",
+				   qopt_ext->stats.prob_mark_head);
+			print_uint(PRINT_ANY, "prob_drop", " prob_drop %u",
+				   qopt_ext->stats.prob_drop);
+			print_string(PRINT_FP, NULL, "%s", _SL_);
+			print_uint(PRINT_ANY, "forced_mark", " forced_mark %u",
+				   qopt_ext->stats.forced_mark);
+			print_uint(PRINT_ANY, "forced_mark_head", " forced_mark_head %u",
+				   qopt_ext->stats.forced_mark_head);
+			print_uint(PRINT_ANY, "forced_drop", " forced_drop %u",
+				   qopt_ext->stats.forced_drop);
 		}
 	}
 	return 0;
@@ -262,8 +276,7 @@ static int sfq_print_xstats(struct qdisc_util *qu, FILE *f,
 		return -1;
 	st = RTA_DATA(xstats);
 
-	fprintf(f, " allot %d ", st->allot);
-	fprintf(f, "\n");
+	print_int(PRINT_ANY, "allot", "allot %d\n", st->allot);
 	return 0;
 }
 
-- 
2.18.0

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

* [PATCH v2 iproute2-next 09/31] tc/fq: support JSON output
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (7 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 08/31] tc/sfq: add json support Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 10/31] tc/mqprio: implement " Stephen Hemminger
                   ` (21 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

Output parameters optionally in JSON.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/q_fq.c | 103 +++++++++++++++++++++++++++++++-----------------------
 1 file changed, 60 insertions(+), 43 deletions(-)

diff --git a/tc/q_fq.c b/tc/q_fq.c
index f3dbf2ba0c6f..fa546c6ae500 100644
--- a/tc/q_fq.c
+++ b/tc/q_fq.c
@@ -233,14 +233,6 @@ static int fq_parse_opt(struct qdisc_util *qu, int argc, char **argv,
 static int fq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 {
 	struct rtattr *tb[TCA_FQ_MAX + 1];
-	unsigned int plimit, flow_plimit;
-	unsigned int buckets_log;
-	int pacing;
-	unsigned int rate, quantum;
-	unsigned int refill_delay;
-	unsigned int orphan_mask;
-
-	SPRINT_BUF(b1);
 
 	if (opt == NULL)
 		return 0;
@@ -249,65 +241,80 @@ static int fq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 
 	if (tb[TCA_FQ_PLIMIT] &&
 	    RTA_PAYLOAD(tb[TCA_FQ_PLIMIT]) >= sizeof(__u32)) {
-		plimit = rta_getattr_u32(tb[TCA_FQ_PLIMIT]);
-		fprintf(f, "limit %up ", plimit);
+		unsigned int plimit = rta_getattr_u32(tb[TCA_FQ_PLIMIT]);
+
+		print_uint(PRINT_ANY, "limit", "limit %up ", plimit);
 	}
 	if (tb[TCA_FQ_FLOW_PLIMIT] &&
 	    RTA_PAYLOAD(tb[TCA_FQ_FLOW_PLIMIT]) >= sizeof(__u32)) {
-		flow_plimit = rta_getattr_u32(tb[TCA_FQ_FLOW_PLIMIT]);
-		fprintf(f, "flow_limit %up ", flow_plimit);
+		unsigned int flow_plimit = rta_getattr_u32(tb[TCA_FQ_FLOW_PLIMIT]);
+
+		print_uint(PRINT_ANY, "flow_limit",
+			   "flow_limit %up ", flow_plimit);
 	}
 	if (tb[TCA_FQ_BUCKETS_LOG] &&
 	    RTA_PAYLOAD(tb[TCA_FQ_BUCKETS_LOG]) >= sizeof(__u32)) {
-		buckets_log = rta_getattr_u32(tb[TCA_FQ_BUCKETS_LOG]);
-		fprintf(f, "buckets %u ", 1U << buckets_log);
+		unsigned int buckets_log = rta_getattr_u32(tb[TCA_FQ_BUCKETS_LOG]);
+
+		print_uint(PRINT_ANY, "buckets",
+			   "buckets %u ", 1U << buckets_log);
 	}
 	if (tb[TCA_FQ_ORPHAN_MASK] &&
 	    RTA_PAYLOAD(tb[TCA_FQ_ORPHAN_MASK]) >= sizeof(__u32)) {
-		orphan_mask = rta_getattr_u32(tb[TCA_FQ_ORPHAN_MASK]);
-		fprintf(f, "orphan_mask %u ", orphan_mask);
+		unsigned int orphan_mask = rta_getattr_u32(tb[TCA_FQ_ORPHAN_MASK]);
+
+		print_uint(PRINT_ANY, "orphan_mask",
+			   "orphan_mask %u ", orphan_mask);
 	}
 	if (tb[TCA_FQ_RATE_ENABLE] &&
 	    RTA_PAYLOAD(tb[TCA_FQ_RATE_ENABLE]) >= sizeof(int)) {
-		pacing = rta_getattr_u32(tb[TCA_FQ_RATE_ENABLE]);
+		unsigned int pacing = rta_getattr_u32(tb[TCA_FQ_RATE_ENABLE]);
 		if (pacing == 0)
-			fprintf(f, "nopacing ");
+			print_null(PRINT_ANY, "nopacing",
+				   " nopacing ", NULL);
 	}
 	if (tb[TCA_FQ_QUANTUM] &&
 	    RTA_PAYLOAD(tb[TCA_FQ_QUANTUM]) >= sizeof(__u32)) {
-		quantum = rta_getattr_u32(tb[TCA_FQ_QUANTUM]);
-		fprintf(f, "quantum %u ", quantum);
+		unsigned int quantum = rta_getattr_u32(tb[TCA_FQ_QUANTUM]);
+
+		print_uint(PRINT_ANY, "quantum",
+			   "quantum %u ", quantum);
 	}
 	if (tb[TCA_FQ_INITIAL_QUANTUM] &&
 	    RTA_PAYLOAD(tb[TCA_FQ_INITIAL_QUANTUM]) >= sizeof(__u32)) {
-		quantum = rta_getattr_u32(tb[TCA_FQ_INITIAL_QUANTUM]);
-		fprintf(f, "initial_quantum %u ", quantum);
+		unsigned int quantum = rta_getattr_u32(tb[TCA_FQ_INITIAL_QUANTUM]);
+
+		print_uint(PRINT_ANY, "initial_quantum",
+			   "initial_quantum %u ", quantum);
 	}
 	if (tb[TCA_FQ_FLOW_MAX_RATE] &&
 	    RTA_PAYLOAD(tb[TCA_FQ_FLOW_MAX_RATE]) >= sizeof(__u32)) {
-		rate = rta_getattr_u32(tb[TCA_FQ_FLOW_MAX_RATE]);
+		unsigned int rate = rta_getattr_u32(tb[TCA_FQ_FLOW_MAX_RATE]);
 
 		if (rate != ~0U)
-			fprintf(f, "maxrate %s ", sprint_rate(rate, b1));
+			print_rate("maxrate", "maxrate %s ", rate);
 	}
 	if (tb[TCA_FQ_FLOW_DEFAULT_RATE] &&
 	    RTA_PAYLOAD(tb[TCA_FQ_FLOW_DEFAULT_RATE]) >= sizeof(__u32)) {
-		rate = rta_getattr_u32(tb[TCA_FQ_FLOW_DEFAULT_RATE]);
+		unsigned int rate = rta_getattr_u32(tb[TCA_FQ_FLOW_DEFAULT_RATE]);
 
 		if (rate != 0)
-			fprintf(f, "defrate %s ", sprint_rate(rate, b1));
+			print_rate("defrate", "defrate %s ", rate);
 	}
 	if (tb[TCA_FQ_LOW_RATE_THRESHOLD] &&
 	    RTA_PAYLOAD(tb[TCA_FQ_LOW_RATE_THRESHOLD]) >= sizeof(__u32)) {
-		rate = rta_getattr_u32(tb[TCA_FQ_LOW_RATE_THRESHOLD]);
+		unsigned int rate = rta_getattr_u32(tb[TCA_FQ_LOW_RATE_THRESHOLD]);
 
 		if (rate != 0)
-			fprintf(f, "low_rate_threshold %s ", sprint_rate(rate, b1));
+			print_rate("low_rate_threshold",
+				   "low_rate_threshold %s ", rate);
 	}
 	if (tb[TCA_FQ_FLOW_REFILL_DELAY] &&
 	    RTA_PAYLOAD(tb[TCA_FQ_FLOW_REFILL_DELAY]) >= sizeof(__u32)) {
-		refill_delay = rta_getattr_u32(tb[TCA_FQ_FLOW_REFILL_DELAY]);
-		fprintf(f, "refill_delay %s ", sprint_time(refill_delay, b1));
+		unsigned int refill_delay = rta_getattr_u32(tb[TCA_FQ_FLOW_REFILL_DELAY]);
+
+		print_time("refill_delay",
+			   "refill_delay %s ", refill_delay);
 	}
 
 	return 0;
@@ -326,29 +333,39 @@ static int fq_print_xstats(struct qdisc_util *qu, FILE *f,
 
 	st = RTA_DATA(xstats);
 
-	fprintf(f, "  %u flows (%u inactive, %u throttled)",
-		st->flows, st->inactive_flows, st->throttled_flows);
+	print_uint(PRINT_ANY, "flows", "  %u flows", st->flows);
+	print_uint(PRINT_ANY, "inactive", " (%u inactive,", st->inactive_flows);
+	print_uint(PRINT_ANY, "throttled", " %u throttled)", st->throttled_flows);
 
 	if (st->time_next_delayed_flow > 0)
-		fprintf(f, ", next packet delay %llu ns", st->time_next_delayed_flow);
+		print_u64(PRINT_ANY, "next_delayed",
+			  ", next packet delay %llu ns", st->time_next_delayed_flow);
 
-	fprintf(f, "\n  %llu gc, %llu highprio",
-		st->gc_flows, st->highprio_packets);
+	print_string(PRINT_FP, NULL, "%s", _SL_);
+	print_u64(PRINT_ANY, "gc_flows", "  %llu gc,", st->gc_flows);
+	print_u64(PRINT_ANY, "highprio", " %llu highprio", st->highprio_packets);
 
 	if (st->tcp_retrans)
-		fprintf(f, ", %llu retrans", st->tcp_retrans);
+		print_u64(PRINT_ANY, "retrans",
+			   ", %llu retrans", st->tcp_retrans);
 
-	fprintf(f, ", %llu throttled", st->throttled);
+	print_uint(PRINT_ANY, "throttled", ", %llu throttled", st->throttled);
 
 	if (st->unthrottle_latency_ns)
-		fprintf(f, ", %u ns latency", st->unthrottle_latency_ns);
+		print_uint(PRINT_ANY, "latency",
+			   ", %u ns latency", st->unthrottle_latency_ns);
 
 	if (st->flows_plimit)
-		fprintf(f, ", %llu flows_plimit", st->flows_plimit);
-
-	if (st->pkts_too_long || st->allocation_errors)
-		fprintf(f, "\n  %llu too long pkts, %llu alloc errors\n",
-			st->pkts_too_long, st->allocation_errors);
+		print_u64(PRINT_ANY, "plimit",
+			  ", %llu flows_plimit", st->flows_plimit);
+
+	if (st->pkts_too_long || st->allocation_errors) {
+		print_string(PRINT_FP, NULL, "%s", _SL_);
+		print_u64(PRINT_ANY, "pkts_too_long",
+			  "  %llu too long pkts", st->pkts_too_long);
+		print_u64(PRINT_ANY, "alloc_errors",
+			  ", %llu alloc errors", st->allocation_errors);
+	}
 
 	return 0;
 }
-- 
2.18.0

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

* [PATCH v2 iproute2-next 10/31] tc/mqprio: implement JSON output
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (8 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 09/31] tc/fq: support JSON output Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 11/31] tc/drr: " Stephen Hemminger
                   ` (20 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

Output queue options in JSON if requested.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/q_mqprio.c | 134 +++++++++++++++++++++++++++-----------------------
 1 file changed, 72 insertions(+), 62 deletions(-)

diff --git a/tc/q_mqprio.c b/tc/q_mqprio.c
index 207d6441d8fa..3d78f9cec996 100644
--- a/tc/q_mqprio.c
+++ b/tc/q_mqprio.c
@@ -213,15 +213,37 @@ static int mqprio_parse_opt(struct qdisc_util *qu, int argc,
 	return 0;
 }
 
+static void print_rate_table(const struct tc_mqprio_qopt *qopt,
+			     const struct rtattr *tbl,
+			     const char *key, unsigned short type)
+{
+	__u64 rate64[TC_QOPT_MAX_QUEUE] = { 0 };
+	unsigned int rem = RTA_PAYLOAD(tbl);
+	const struct rtattr *r;
+	int i = 0;
+
+	for (r = RTA_DATA(tbl);  RTA_OK(r, rem); r = RTA_NEXT(r, rem)) {
+		if (r->rta_type != type) {
+			fprintf(stderr, "invalid rate table response\n");
+			return;
+		}
+		if (i == TC_QOPT_MAX_QUEUE)
+			break;
+		rate64[i++] = rta_getattr_u64(r);
+	}
+
+	print_string(PRINT_FP, NULL, "	%s:", key);
+	open_json_array(PRINT_JSON, key);
+	for (i = 0; i < qopt->num_tc; i++)
+		print_rate(NULL, "%s ", rate64[i]);
+	close_json_array(PRINT_JSON, "");
+}
+
 static int mqprio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 {
-	int i;
 	struct tc_mqprio_qopt *qopt;
-	__u64 min_rate64[TC_QOPT_MAX_QUEUE] = {0};
-	__u64 max_rate64[TC_QOPT_MAX_QUEUE] = {0};
-	int len;
-
-	SPRINT_BUF(b1);
+	struct rtattr *tb[TCA_MQPRIO_MAX + 1];
+	int i, len;
 
 	if (opt == NULL)
 		return 0;
@@ -234,71 +256,59 @@ static int mqprio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 
 	qopt = RTA_DATA(opt);
 
-	fprintf(f, " tc %u map ", qopt->num_tc);
-	for (i = 0; i <= TC_PRIO_MAX; i++)
-		fprintf(f, "%u ", qopt->prio_tc_map[i]);
-	fprintf(f, "\n             queues:");
-	for (i = 0; i < qopt->num_tc; i++)
-		fprintf(f, "(%u:%u) ", qopt->offset[i],
-			qopt->offset[i] + qopt->count[i] - 1);
+	print_uint(PRINT_ANY, "num_tc",
+		   " tc %u map ", qopt->num_tc);
 
-	if (len > 0) {
-		struct rtattr *tb[TCA_MQPRIO_MAX + 1];
-
-		parse_rtattr(tb, TCA_MQPRIO_MAX,
-			     RTA_DATA(opt) + RTA_ALIGN(sizeof(*qopt)),
-			     len);
+	open_json_array(PRINT_JSON, "priomap");
+	for (i = 0; i <= TC_PRIO_MAX; i++)
+		print_uint(PRINT_ANY, NULL, "%u ", qopt->prio_tc_map[i]);
+	close_json_array(PRINT_JSON, "");
+
+	print_string(PRINT_FP, NULL, "%s             queues:", _SL_);
+	open_json_array(PRINT_JSON, "queues");
+	for (i = 0; i < qopt->num_tc; i++) {
+		open_json_object(NULL);
+		print_uint(PRINT_ANY, "offset", "(%u", qopt->offset[i]);
+		print_uint(PRINT_ANY, "length", ":%u) ",
+			   qopt->offset[i] + qopt->count[i] - 1);
+		close_json_object();
+	}
+	close_json_array(PRINT_JSON, NULL);
 
-		if (tb[TCA_MQPRIO_MODE]) {
-			__u16 *mode = RTA_DATA(tb[TCA_MQPRIO_MODE]);
+	if (len == 0)
+		return 0;
 
-			if (*mode == TC_MQPRIO_MODE_CHANNEL)
-				fprintf(f, "\n             mode:channel");
-		} else {
-			fprintf(f, "\n             mode:dcb");
-		}
+	parse_rtattr(tb, TCA_MQPRIO_MAX,
+		     RTA_DATA(opt) + RTA_ALIGN(sizeof(*qopt)),
+		     len);
 
-		if (tb[TCA_MQPRIO_SHAPER]) {
-			__u16 *shaper = RTA_DATA(tb[TCA_MQPRIO_SHAPER]);
+	if (tb[TCA_MQPRIO_MODE]) {
+		__u16 mode = rta_getattr_u16(tb[TCA_MQPRIO_MODE]);
 
-			if (*shaper == TC_MQPRIO_SHAPER_BW_RATE)
-				fprintf(f, "\n             shaper:bw_rlimit");
-		} else {
-			fprintf(f, "\n             shaper:dcb");
-		}
+		print_string(PRINT_FP, NULL, "%s             ", _SL_);
+		print_string(PRINT_ANY, "mode", "mode:%s",
+			     mode == TC_MQPRIO_MODE_CHANNEL ? "channel" :
+			     mode == TC_MQPRIO_MODE_DCB ? "dcb" :
+			     "unknown");
+	}
 
-		if (tb[TCA_MQPRIO_MIN_RATE64]) {
-			struct rtattr *r;
-			int rem = RTA_PAYLOAD(tb[TCA_MQPRIO_MIN_RATE64]);
-			__u64 *min = min_rate64;
+	if (tb[TCA_MQPRIO_SHAPER]) {
+		__u16 shaper = rta_getattr_u16(tb[TCA_MQPRIO_SHAPER]);
 
-			for (r = RTA_DATA(tb[TCA_MQPRIO_MIN_RATE64]);
-			     RTA_OK(r, rem); r = RTA_NEXT(r, rem)) {
-				if (r->rta_type != TCA_MQPRIO_MIN_RATE64)
-					return -1;
-				*(min++) = rta_getattr_u64(r);
-			}
-			fprintf(f, "	min_rate:");
-			for (i = 0; i < qopt->num_tc; i++)
-				fprintf(f, "%s ", sprint_rate(min_rate64[i], b1));
-		}
+		print_string(PRINT_FP, NULL, "%s             ", _SL_);
+		print_string(PRINT_ANY, "shaper", "shaper:%s",
+			     shaper == TC_MQPRIO_SHAPER_BW_RATE ? "bw_rlimit" :
+			     shaper == TC_MQPRIO_SHAPER_DCB ? "dcb" :
+			     "unknown");
+	}
 
-		if (tb[TCA_MQPRIO_MAX_RATE64]) {
-			struct rtattr *r;
-			int rem = RTA_PAYLOAD(tb[TCA_MQPRIO_MAX_RATE64]);
-			__u64 *max = max_rate64;
+	if (tb[TCA_MQPRIO_MIN_RATE64])
+		print_rate_table(qopt, tb[TCA_MQPRIO_MIN_RATE64],
+				 "min_rate", TCA_MQPRIO_MIN_RATE64);
 
-			for (r = RTA_DATA(tb[TCA_MQPRIO_MAX_RATE64]);
-			     RTA_OK(r, rem); r = RTA_NEXT(r, rem)) {
-				if (r->rta_type != TCA_MQPRIO_MAX_RATE64)
-					return -1;
-				*(max++) = rta_getattr_u64(r);
-			}
-			fprintf(f, "	max_rate:");
-			for (i = 0; i < qopt->num_tc; i++)
-				fprintf(f, "%s ", sprint_rate(max_rate64[i], b1));
-		}
-	}
+	if (tb[TCA_MQPRIO_MAX_RATE64])
+		print_rate_table(qopt, tb[TCA_MQPRIO_MAX_RATE64],
+				 "max_rate", TCA_MQPRIO_MAX_RATE64);
 	return 0;
 }
 
-- 
2.18.0

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

* [PATCH v2 iproute2-next 11/31] tc/drr: implement JSON output
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (9 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 10/31] tc/mqprio: implement " Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 12/31] tc/rr: " Stephen Hemminger
                   ` (19 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/q_drr.c | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/tc/q_drr.c b/tc/q_drr.c
index f9c90f3035f3..882cd4a37ec7 100644
--- a/tc/q_drr.c
+++ b/tc/q_drr.c
@@ -84,16 +84,14 @@ static int drr_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 {
 	struct rtattr *tb[TCA_DRR_MAX + 1];
 
-	SPRINT_BUF(b1);
-
 	if (opt == NULL)
 		return 0;
 
 	parse_rtattr_nested(tb, TCA_DRR_MAX, opt);
 
 	if (tb[TCA_DRR_QUANTUM])
-		fprintf(f, "quantum %s ",
-			sprint_size(rta_getattr_u32(tb[TCA_DRR_QUANTUM]), b1));
+		print_size("quantum", "quantum %s ",
+			   rta_getattr_u32(tb[TCA_DRR_QUANTUM]));
 	return 0;
 }
 
@@ -101,15 +99,13 @@ static int drr_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstat
 {
 	struct tc_drr_stats *x;
 
-	SPRINT_BUF(b1);
-
 	if (xstats == NULL)
 		return 0;
 	if (RTA_PAYLOAD(xstats) < sizeof(*x))
 		return -1;
 	x = RTA_DATA(xstats);
 
-	fprintf(f, " deficit %s ", sprint_size(x->deficit, b1));
+	print_size("deficit", " deficit %s ", x->deficit);
 	return 0;
 }
 
-- 
2.18.0

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

* [PATCH v2 iproute2-next 12/31] tc/rr: implement JSON output
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (10 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 11/31] tc/drr: " Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 13/31] tc/qfq: implement JSON Stephen Hemminger
                   ` (18 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/q_rr.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/tc/q_rr.c b/tc/q_rr.c
index 843a4faeef41..dcc58ac98ba2 100644
--- a/tc/q_rr.c
+++ b/tc/q_rr.c
@@ -101,13 +101,19 @@ static int rr_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 						sizeof(*qopt)))
 		return -1;
 
-	fprintf(f, "bands %u priomap ", qopt->bands);
+	print_uint(PRINT_ANY, "bands", "bands %u priomap ", qopt->bands);
+	open_json_array(PRINT_JSON, "priomap");
 	for (i = 0; i <= TC_PRIO_MAX; i++)
-		fprintf(f, " %d", qopt->priomap[i]);
+		print_uint(PRINT_ANY, NULL, " %u", qopt->priomap[i]);
+	close_json_array(PRINT_JSON, NULL);
 
-	if (tb[TCA_PRIO_MQ])
-		fprintf(f, " multiqueue: %s ",
-			rta_getattr_u8(tb[TCA_PRIO_MQ]) ? "on" : "off");
+	if (tb[TCA_PRIO_MQ]) {
+		bool mq = rta_getattr_u8(tb[TCA_PRIO_MQ]);
+
+		print_string(PRINT_FP, NULL, " multiqueue: %s ",
+			     mq ? "on" : "off");
+		print_bool(PRINT_JSON, "multiqueue", NULL, mq);
+	}
 
 	return 0;
 }
-- 
2.18.0

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

* [PATCH v2 iproute2-next 13/31] tc/qfq: implement JSON
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (11 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 12/31] tc/rr: " Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 14/31] tc/sfb: implement JSON output Stephen Hemminger
                   ` (17 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/q_qfq.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/tc/q_qfq.c b/tc/q_qfq.c
index eb8fa4b84927..0bb52ad6340b 100644
--- a/tc/q_qfq.c
+++ b/tc/q_qfq.c
@@ -94,13 +94,13 @@ static int qfq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	parse_rtattr_nested(tb, TCA_QFQ_MAX, opt);
 
 	if (tb[TCA_QFQ_WEIGHT]) {
-		fprintf(f, "weight %u ",
-			rta_getattr_u32(tb[TCA_QFQ_WEIGHT]));
+		print_uint(PRINT_ANY, "weight", "weight %u ",
+			   rta_getattr_u32(tb[TCA_QFQ_WEIGHT]));
 	}
 
 	if (tb[TCA_QFQ_LMAX]) {
-		fprintf(f, "maxpkt %u ",
-			rta_getattr_u32(tb[TCA_QFQ_LMAX]));
+		print_uint(PRINT_ANY, "maxpkt", "maxpkt %u ",
+			   rta_getattr_u32(tb[TCA_QFQ_LMAX]));
 	}
 
 	return 0;
-- 
2.18.0

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

* [PATCH v2 iproute2-next 14/31] tc/sfb: implement JSON output
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (12 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 13/31] tc/qfq: implement JSON Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 15/31] tc/multiq: " Stephen Hemminger
                   ` (16 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/q_sfb.c | 56 +++++++++++++++++++++++++++++++++---------------------
 1 file changed, 34 insertions(+), 22 deletions(-)

diff --git a/tc/q_sfb.c b/tc/q_sfb.c
index 7f48c6e0ef39..d58ce71f83ce 100644
--- a/tc/q_sfb.c
+++ b/tc/q_sfb.c
@@ -153,14 +153,20 @@ static int sfb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	if (RTA_PAYLOAD(tb[TCA_SFB_PARMS]) < sizeof(*qopt))
 		return -1;
 
-	fprintf(f,
-		"limit %d max %d target %d\n"
-		"  increment %.5f decrement %.5f penalty rate %d burst %d (%ums %ums)",
-		qopt->limit, qopt->max, qopt->bin_size,
-		(double)qopt->increment / SFB_MAX_PROB,
-		(double)qopt->decrement / SFB_MAX_PROB,
-		qopt->penalty_rate, qopt->penalty_burst,
-		qopt->rehash_interval, qopt->warmup_time);
+	print_uint(PRINT_ANY, "limit", "limit %u", qopt->limit);
+	print_uint(PRINT_ANY, "max", " max %u", qopt->max);
+	print_uint(PRINT_ANY, "target", " target %u", qopt->bin_size);
+	print_string(PRINT_FP, NULL, "%s", _SL_);
+
+	print_float(PRINT_ANY, "increment", "  increment %.5f",
+		    (double)qopt->increment / SFB_MAX_PROB);
+	print_float(PRINT_ANY, "decrement", " decrement %.5f",
+		    (double)qopt->decrement / SFB_MAX_PROB);
+	print_uint(PRINT_ANY, "penalty_rate", " penalty rate %u",
+		   qopt->penalty_rate);
+	print_uint(PRINT_ANY, "penalty_burst", " burst %u", qopt->penalty_burst);
+	print_uint(PRINT_ANY, "rehash", " (%ums", qopt->rehash_interval);
+	print_uint(PRINT_ANY, "warmup", " %ums)", qopt->warmup_time);
 
 	return 0;
 }
@@ -168,24 +174,30 @@ static int sfb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 static int sfb_print_xstats(struct qdisc_util *qu, FILE *f,
 			    struct rtattr *xstats)
 {
-    struct tc_sfb_xstats *st;
+	struct tc_sfb_xstats *st;
 
-    if (xstats == NULL)
-	    return 0;
+	if (xstats == NULL)
+		return 0;
 
-    if (RTA_PAYLOAD(xstats) < sizeof(*st))
-	    return -1;
+	if (RTA_PAYLOAD(xstats) < sizeof(*st))
+		return -1;
 
-    st = RTA_DATA(xstats);
-    fprintf(f,
-	    "  earlydrop %u penaltydrop %u bucketdrop %u queuedrop %u childdrop %u marked %u\n"
-	    "  maxqlen %u maxprob %.5f avgprob %.5f ",
-	    st->earlydrop, st->penaltydrop, st->bucketdrop, st->queuedrop, st->childdrop,
-	    st->marked,
-	    st->maxqlen, (double)st->maxprob / SFB_MAX_PROB,
-		(double)st->avgprob / SFB_MAX_PROB);
+	st = RTA_DATA(xstats);
+	print_uint(PRINT_ANY, "earlydrop", "  earlydrop %u", st->earlydrop);
+	print_uint(PRINT_ANY, "penaltydrop", "penaltydrop %u", st->penaltydrop);
+	print_uint(PRINT_ANY, "bucketdrop", "bucketdrop %u", st->bucketdrop);
+	print_uint(PRINT_ANY, "queuedrop", "queuedrop %u", st->queuedrop);
+	print_uint(PRINT_ANY, "childdrop", "childdrop %u", st->childdrop);
+	print_uint(PRINT_ANY, "marked", "marked %u", st->marked);
+	print_uint(PRINT_ANY, "maxqlen", "  maxqlen %u", st->maxqlen);
+	print_string(PRINT_FP, NULL, "%s", _SL_);
+
+	print_float(PRINT_ANY, "maxprob", " maxprob %.5f",
+		    (double)st->maxprob / SFB_MAX_PROB);
+	print_float(PRINT_ANY, "avgprob", " avgprob %.5f",
+		    (double)st->avgprob / SFB_MAX_PROB);
 
-    return 0;
+	return 0;
 }
 
 struct qdisc_util sfb_qdisc_util = {
-- 
2.18.0

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

* [PATCH v2 iproute2-next 15/31] tc/multiq: implement JSON output
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (13 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 14/31] tc/sfb: implement JSON output Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 16/31] tc/util: allow signed value for time Stephen Hemminger
                   ` (15 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/q_multiq.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tc/q_multiq.c b/tc/q_multiq.c
index 8ad9e0b2fa3c..fd2d301bb0c6 100644
--- a/tc/q_multiq.c
+++ b/tc/q_multiq.c
@@ -70,7 +70,8 @@ static int multiq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 
 	qopt = RTA_DATA(opt);
 
-	fprintf(f, "bands %u/%u ", qopt->bands, qopt->max_bands);
+	print_uint(PRINT_ANY, "bands", "bands %u", qopt->bands);
+	print_uint(PRINT_ANY, "max_bands", "/%u ", qopt->max_bands);
 
 	return 0;
 }
-- 
2.18.0

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

* [PATCH v2 iproute2-next 16/31] tc/util: allow signed value for time
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (14 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 15/31] tc/multiq: " Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 17/31] tc/codel: implement JSON output Stephen Hemminger
                   ` (14 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

The codel algorithm wants a signed value for time when
outputting values.  Allow it for other uses as well.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/tc_util.c | 6 +++---
 tc/tc_util.h | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/tc/tc_util.c b/tc/tc_util.c
index 43a67fd13f94..3789b38773a7 100644
--- a/tc/tc_util.c
+++ b/tc/tc_util.c
@@ -370,7 +370,7 @@ int get_time(unsigned int *time, const char *str)
 	return 0;
 }
 
-char *sprint_time(__u32 time, char *buf)
+char *sprint_time(__s32 time, char *buf)
 {
 	const size_t len = SPRINT_BSIZE - 1;
 	double tmp = time;
@@ -380,12 +380,12 @@ char *sprint_time(__u32 time, char *buf)
 	else if (tmp >= TIME_UNITS_PER_SEC/1000)
 		snprintf(buf, len, "%.1fms", tmp/(TIME_UNITS_PER_SEC/1000));
 	else
-		snprintf(buf, len, "%uus", time);
+		snprintf(buf, len, "%dus", time);
 
 	return buf;
 }
 
-void print_time(const char *key, const char *fmt, __u32 tm)
+void print_time(const char *key, const char *fmt, __s32 tm)
 {
 	double secs = (double)tm / TIME_UNITS_PER_SEC;
 	SPRINT_BUF(b1);
diff --git a/tc/tc_util.h b/tc/tc_util.h
index e83bb7dbcc76..23d11520eb50 100644
--- a/tc/tc_util.h
+++ b/tc/tc_util.h
@@ -97,7 +97,7 @@ char *sprint_rate(__u64 rate, char *buf);
 char *sprint_size(__u32 size, char *buf);
 char *sprint_qdisc_handle(__u32 h, char *buf);
 char *sprint_tc_classid(__u32 h, char *buf);
-char *sprint_time(__u32 time, char *buf);
+char *sprint_time(__s32 time, char *buf);
 char *sprint_ticks(__u32 ticks, char *buf);
 char *sprint_linklayer(unsigned int linklayer, char *buf);
 
-- 
2.18.0

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

* [PATCH v2 iproute2-next 17/31] tc/codel: implement JSON output
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (15 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 16/31] tc/util: allow signed value for time Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 18/31] tc/fifo: " Stephen Hemminger
                   ` (13 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/q_codel.c | 35 +++++++++++++++++------------------
 1 file changed, 17 insertions(+), 18 deletions(-)

diff --git a/tc/q_codel.c b/tc/q_codel.c
index 8a2a871671cb..de5c514fc49c 100644
--- a/tc/q_codel.c
+++ b/tc/q_codel.c
@@ -133,7 +133,6 @@ static int codel_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	unsigned int ecn;
 	unsigned int ce_threshold;
 
-	SPRINT_BUF(b1);
 
 	if (opt == NULL)
 		return 0;
@@ -143,28 +142,28 @@ static int codel_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	if (tb[TCA_CODEL_LIMIT] &&
 	    RTA_PAYLOAD(tb[TCA_CODEL_LIMIT]) >= sizeof(__u32)) {
 		limit = rta_getattr_u32(tb[TCA_CODEL_LIMIT]);
-		fprintf(f, "limit %up ", limit);
+		print_uint(PRINT_ANY, "limit", "limit %up ", limit);
 	}
 	if (tb[TCA_CODEL_TARGET] &&
 	    RTA_PAYLOAD(tb[TCA_CODEL_TARGET]) >= sizeof(__u32)) {
 		target = rta_getattr_u32(tb[TCA_CODEL_TARGET]);
-		fprintf(f, "target %s ", sprint_time(target, b1));
+		print_time("target", "target %s ", target);
 	}
 	if (tb[TCA_CODEL_CE_THRESHOLD] &&
 	    RTA_PAYLOAD(tb[TCA_CODEL_CE_THRESHOLD]) >= sizeof(__u32)) {
 		ce_threshold = rta_getattr_u32(tb[TCA_CODEL_CE_THRESHOLD]);
-		fprintf(f, "ce_threshold %s ", sprint_time(ce_threshold, b1));
+		print_time("ce_threshold", "ce_threshold %s ", ce_threshold);
 	}
 	if (tb[TCA_CODEL_INTERVAL] &&
 	    RTA_PAYLOAD(tb[TCA_CODEL_INTERVAL]) >= sizeof(__u32)) {
 		interval = rta_getattr_u32(tb[TCA_CODEL_INTERVAL]);
-		fprintf(f, "interval %s ", sprint_time(interval, b1));
+		print_time("interval", "interval %s ", interval);
 	}
 	if (tb[TCA_CODEL_ECN] &&
 	    RTA_PAYLOAD(tb[TCA_CODEL_ECN]) >= sizeof(__u32)) {
 		ecn = rta_getattr_u32(tb[TCA_CODEL_ECN]);
 		if (ecn)
-			fprintf(f, "ecn ");
+			print_null(PRINT_ANY, "ecn", "ecn ", NULL);
 	}
 
 	return 0;
@@ -175,8 +174,6 @@ static int codel_print_xstats(struct qdisc_util *qu, FILE *f,
 {
 	struct tc_codel_xstats _st = {}, *st;
 
-	SPRINT_BUF(b1);
-
 	if (xstats == NULL)
 		return 0;
 
@@ -186,18 +183,20 @@ static int codel_print_xstats(struct qdisc_util *qu, FILE *f,
 		st = &_st;
 	}
 
-	fprintf(f, "  count %u lastcount %u ldelay %s",
-		st->count, st->lastcount, sprint_time(st->ldelay, b1));
+	print_uint(PRINT_ANY, "count", "  count %u", st->count);
+	print_uint(PRINT_ANY, "lastcount", " lastcount %u", st->lastcount);
+	print_time("ldelay", " ldelay %s", st->ldelay);
 	if (st->dropping)
-		fprintf(f, " dropping");
-	if (st->drop_next < 0)
-		fprintf(f, " drop_next -%s", sprint_time(-st->drop_next, b1));
-	else
-		fprintf(f, " drop_next %s", sprint_time(st->drop_next, b1));
-	fprintf(f, "\n  maxpacket %u ecn_mark %u drop_overlimit %u",
-		st->maxpacket, st->ecn_mark, st->drop_overlimit);
+		print_null(PRINT_ANY, "dropping", " dropping", NULL);
+	print_time("drop_next", " drop_next %s", st->drop_next);
+
+	print_string(PRINT_FP, NULL, "%s", _SL_);
+	print_uint(PRINT_ANY, "maxpacket", "  maxpacket %u", st->maxpacket);
+	print_uint(PRINT_ANY, "ecn_mark", "ecn_mark %u", st->ecn_mark);
+	print_uint(PRINT_ANY, "drop_overlimit", "drop_overlimit %u",
+		   st->drop_overlimit);
 	if (st->ce_mark)
-		fprintf(f, " ce_mark %u", st->ce_mark);
+		print_uint(PRINT_ANY, "ce_mark", " ce_mark %u", st->ce_mark);
 	return 0;
 
 }
-- 
2.18.0

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

* [PATCH v2 iproute2-next 18/31] tc/fifo: implement JSON output
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (16 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 17/31] tc/codel: implement JSON output Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 19/31] tc/tbf: implement JSON output format Stephen Hemminger
                   ` (12 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/q_fifo.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/tc/q_fifo.c b/tc/q_fifo.c
index 5fd6c1b1107d..65a7b0e218f2 100644
--- a/tc/q_fifo.c
+++ b/tc/q_fifo.c
@@ -67,11 +67,10 @@ static int fifo_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	if (RTA_PAYLOAD(opt)  < sizeof(*qopt))
 		return -1;
 	qopt = RTA_DATA(opt);
-	if (strcmp(qu->id, "bfifo") == 0) {
-		SPRINT_BUF(b1);
-		fprintf(f, "limit %s", sprint_size(qopt->limit, b1));
-	} else
-		fprintf(f, "limit %up", qopt->limit);
+	if (strcmp(qu->id, "bfifo") == 0)
+		print_size("limit", "limit %s", qopt->limit);
+	else
+		print_uint(PRINT_ANY, "limit", "limit %up", qopt->limit);
 	return 0;
 }
 
-- 
2.18.0

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

* [PATCH v2 iproute2-next 19/31] tc/tbf: implement JSON output format
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (17 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 18/31] tc/fifo: " Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 20/31] tc/choke: implement JSON output Stephen Hemminger
                   ` (11 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/q_tbf.c | 48 ++++++++++++++++++++++++++----------------------
 1 file changed, 26 insertions(+), 22 deletions(-)

diff --git a/tc/q_tbf.c b/tc/q_tbf.c
index b9465b20d2be..2695b4fb00e6 100644
--- a/tc/q_tbf.c
+++ b/tc/q_tbf.c
@@ -266,10 +266,6 @@ static int tbf_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	double latency;
 	__u64 rate64 = 0, prate64 = 0;
 
-	SPRINT_BUF(b1);
-	SPRINT_BUF(b2);
-	SPRINT_BUF(b3);
-
 	if (opt == NULL)
 		return 0;
 
@@ -285,53 +281,61 @@ static int tbf_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	if (tb[TCA_TBF_RATE64] &&
 	    RTA_PAYLOAD(tb[TCA_TBF_RATE64]) >= sizeof(rate64))
 		rate64 = rta_getattr_u64(tb[TCA_TBF_RATE64]);
-	fprintf(f, "rate %s ", sprint_rate(rate64, b1));
+
+	print_rate("rate", "rate %s ", rate64);
 	buffer = tc_calc_xmitsize(rate64, qopt->buffer);
+	print_size("burst", "burst %s", buffer);
 	if (show_details) {
-		fprintf(f, "burst %s/%u mpu %s ", sprint_size(buffer, b1),
-			1<<qopt->rate.cell_log, sprint_size(qopt->rate.mpu, b2));
-	} else {
-		fprintf(f, "burst %s ", sprint_size(buffer, b1));
+		print_uint(PRINT_ANY, "cell_log", "/%u",
+			   1 << qopt->rate.cell_log);
+		print_size("mpu", " mpu %s ", qopt->rate.mpu);
 	}
+
 	if (show_raw)
-		fprintf(f, "[%08x] ", qopt->buffer);
+		print_0xhex(PRINT_FP, NULL, "[%08x] ", qopt->buffer);
+
 	prate64 = qopt->peakrate.rate;
 	if (tb[TCA_TBF_PRATE64] &&
 	    RTA_PAYLOAD(tb[TCA_TBF_PRATE64]) >= sizeof(prate64))
 		prate64 = rta_getattr_u64(tb[TCA_TBF_PRATE64]);
+
 	if (prate64) {
-		fprintf(f, "peakrate %s ", sprint_rate(prate64, b1));
+		print_rate("peakrate", "peakrate %s ", prate64);
 		if (qopt->mtu || qopt->peakrate.mpu) {
 			mtu = tc_calc_xmitsize(prate64, qopt->mtu);
 			if (show_details) {
-				fprintf(f, "mtu %s/%u mpu %s ", sprint_size(mtu, b1),
-					1<<qopt->peakrate.cell_log, sprint_size(qopt->peakrate.mpu, b2));
+				print_size("mtu", "mtu %s", mtu);
+				print_uint(PRINT_FP, NULL, "/%u",
+					   1 << qopt->peakrate.cell_log);
+				print_size("peakrate", " mpu %s ", qopt->peakrate.mpu);
 			} else {
-				fprintf(f, "minburst %s ", sprint_size(mtu, b1));
+				print_size("minburst", "minburst %s ", mtu);
 			}
 			if (show_raw)
-				fprintf(f, "[%08x] ", qopt->mtu);
+				print_0xhex(PRINT_FP, NULL, "[%08x] ", qopt->mtu);
 		}
 	}
 
 	latency = TIME_UNITS_PER_SEC*(qopt->limit/(double)rate64) - tc_core_tick2time(qopt->buffer);
 	if (prate64) {
-		double lat2 = TIME_UNITS_PER_SEC*(qopt->limit/(double)prate64) - tc_core_tick2time(qopt->mtu);
+		double lat2 = TIME_UNITS_PER_SEC*(qopt->limit/(double)prate64)
+			- tc_core_tick2time(qopt->mtu);
 
 		if (lat2 > latency)
 			latency = lat2;
 	}
+
 	if (latency >= 0.0)
-		fprintf(f, "lat %s ", sprint_time(latency, b1));
+		print_time("latency", "lat %s ", latency);
 	if (show_raw || latency < 0.0)
-		fprintf(f, "limit %s ", sprint_size(qopt->limit, b1));
+		print_size("limit", "limit %s ", qopt->limit);
+
+	if (qopt->rate.overhead)
+		print_uint(PRINT_ANY, "overhead", "overhead %u", qopt->rate.overhead);
 
-	if (qopt->rate.overhead) {
-		fprintf(f, "overhead %d", qopt->rate.overhead);
-	}
 	linklayer = (qopt->rate.linklayer & TC_LINKLAYER_MASK);
 	if (linklayer > TC_LINKLAYER_ETHERNET || show_details)
-		fprintf(f, "linklayer %s ", sprint_linklayer(linklayer, b3));
+		print_linklayer("linklayer", "linklayer %s ", linklayer);
 
 	return 0;
 }
-- 
2.18.0

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

* [PATCH v2 iproute2-next 20/31] tc/choke: implement JSON output
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (18 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 19/31] tc/tbf: implement JSON output format Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 21/31] tc/hhf: " Stephen Hemminger
                   ` (10 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/q_choke.c | 25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/tc/q_choke.c b/tc/q_choke.c
index b269b1338b6d..718743f4a998 100644
--- a/tc/q_choke.c
+++ b/tc/q_choke.c
@@ -185,19 +185,23 @@ static int choke_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	    RTA_PAYLOAD(tb[TCA_CHOKE_MAX_P]) >= sizeof(__u32))
 		max_P = rta_getattr_u32(tb[TCA_CHOKE_MAX_P]);
 
-	fprintf(f, "limit %up min %up max %up ",
-		qopt->limit, qopt->qth_min, qopt->qth_max);
+	print_uint(PRINT_ANY, "limit", "limit %up", qopt->limit);
+	print_uint(PRINT_ANY, "min", " min %up", qopt->qth_min);
+	print_uint(PRINT_ANY, "max", " max %up ", qopt->qth_max);
 
 	if (qopt->flags & TC_RED_ECN)
-		fprintf(f, "ecn ");
+		print_null(PRINT_ANY, "ecn", "ecn ", NULL);
 
 	if (show_details) {
-		fprintf(f, "ewma %u ", qopt->Wlog);
+		print_uint(PRINT_ANY, "ewma", "ewma %u ", qopt->Wlog);
 		if (max_P)
-			fprintf(f, "probability %g ", max_P / pow(2, 32));
+			print_float(PRINT_ANY, "probability",
+				    "probability %g ", max_P / pow(2, 32));
 		else
-			fprintf(f, "Plog %u ", qopt->Plog);
-		fprintf(f, "Scell_log %u", qopt->Scell_log);
+			print_uint(PRINT_ANY, "plog",
+				   "Plog %u ", qopt->Plog);
+		print_uint(PRINT_ANY, "scell_log",
+			   "Scell_log %u", qopt->Scell_log);
 	}
 	return 0;
 }
@@ -214,8 +218,11 @@ static int choke_print_xstats(struct qdisc_util *qu, FILE *f,
 		return -1;
 
 	st = RTA_DATA(xstats);
-	fprintf(f, "  marked %u early %u pdrop %u other %u matched %u",
-		st->marked, st->early, st->pdrop, st->other, st->matched);
+	print_uint(PRINT_ANY, "marked", "  marked %u", st->marked);
+	print_uint(PRINT_ANY, "early", " early %u", st->early);
+	print_uint(PRINT_ANY, "pdrop", " pdrop %u", st->pdrop);
+	print_uint(PRINT_ANY, "other", " other %u", st->other);
+	print_uint(PRINT_ANY, "matched", " matched %u", st->matched);
 	return 0;
 
 }
-- 
2.18.0

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

* [PATCH v2 iproute2-next 21/31] tc/hhf: implement JSON output
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (19 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 20/31] tc/choke: implement JSON output Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 22/31] tc/pie: " Stephen Hemminger
                   ` (9 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/q_hhf.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/tc/q_hhf.c b/tc/q_hhf.c
index 21186a92c017..daea6bbcdd65 100644
--- a/tc/q_hhf.c
+++ b/tc/q_hhf.c
@@ -127,8 +127,6 @@ static int hhf_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	unsigned int evict_timeout;
 	unsigned int non_hh_weight;
 
-	SPRINT_BUF(b1);
-
 	if (opt == NULL)
 		return 0;
 
@@ -137,37 +135,38 @@ static int hhf_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	if (tb[TCA_HHF_BACKLOG_LIMIT] &&
 	    RTA_PAYLOAD(tb[TCA_HHF_BACKLOG_LIMIT]) >= sizeof(__u32)) {
 		limit = rta_getattr_u32(tb[TCA_HHF_BACKLOG_LIMIT]);
-		fprintf(f, "limit %up ", limit);
+		print_uint(PRINT_ANY, "limit", "limit %up ", limit);
 	}
 	if (tb[TCA_HHF_QUANTUM] &&
 	    RTA_PAYLOAD(tb[TCA_HHF_QUANTUM]) >= sizeof(__u32)) {
 		quantum = rta_getattr_u32(tb[TCA_HHF_QUANTUM]);
-		fprintf(f, "quantum %u ", quantum);
+		print_uint(PRINT_ANY, "quantum", "quantum %u ", quantum);
 	}
 	if (tb[TCA_HHF_HH_FLOWS_LIMIT] &&
 	    RTA_PAYLOAD(tb[TCA_HHF_HH_FLOWS_LIMIT]) >= sizeof(__u32)) {
 		hh_limit = rta_getattr_u32(tb[TCA_HHF_HH_FLOWS_LIMIT]);
-		fprintf(f, "hh_limit %u ", hh_limit);
+		print_uint(PRINT_ANY, "hh_limit", "hh_limit %u ", hh_limit);
 	}
 	if (tb[TCA_HHF_RESET_TIMEOUT] &&
 	    RTA_PAYLOAD(tb[TCA_HHF_RESET_TIMEOUT]) >= sizeof(__u32)) {
 		reset_timeout = rta_getattr_u32(tb[TCA_HHF_RESET_TIMEOUT]);
-		fprintf(f, "reset_timeout %s ", sprint_time(reset_timeout, b1));
+		print_time("reset_timeout", "reset_timeout %s ", reset_timeout);
 	}
 	if (tb[TCA_HHF_ADMIT_BYTES] &&
 	    RTA_PAYLOAD(tb[TCA_HHF_ADMIT_BYTES]) >= sizeof(__u32)) {
 		admit_bytes = rta_getattr_u32(tb[TCA_HHF_ADMIT_BYTES]);
-		fprintf(f, "admit_bytes %u ", admit_bytes);
+		print_uint(PRINT_ANY, "admit_bytes", "admit_bytes %u ", admit_bytes);
 	}
 	if (tb[TCA_HHF_EVICT_TIMEOUT] &&
 	    RTA_PAYLOAD(tb[TCA_HHF_EVICT_TIMEOUT]) >= sizeof(__u32)) {
 		evict_timeout = rta_getattr_u32(tb[TCA_HHF_EVICT_TIMEOUT]);
-		fprintf(f, "evict_timeout %s ", sprint_time(evict_timeout, b1));
+		print_time("evict_timeout", "evict_timeout %s ", evict_timeout);
 	}
 	if (tb[TCA_HHF_NON_HH_WEIGHT] &&
 	    RTA_PAYLOAD(tb[TCA_HHF_NON_HH_WEIGHT]) >= sizeof(__u32)) {
 		non_hh_weight = rta_getattr_u32(tb[TCA_HHF_NON_HH_WEIGHT]);
-		fprintf(f, "non_hh_weight %u ", non_hh_weight);
+		print_uint(PRINT_ANY, "non_hh_weight",
+			   "non_hh_weight %u ", non_hh_weight);
 	}
 	return 0;
 }
@@ -185,9 +184,10 @@ static int hhf_print_xstats(struct qdisc_util *qu, FILE *f,
 
 	st = RTA_DATA(xstats);
 
-	fprintf(f, "  drop_overlimit %u hh_overlimit %u tot_hh %u cur_hh %u",
-		st->drop_overlimit, st->hh_overlimit,
-		st->hh_tot_count, st->hh_cur_count);
+	print_uint(PRINT_ANY, "drop_overlimit", "drop_overlimit %u", st->drop_overlimit);
+	print_uint(PRINT_ANY, "hh_overlimit", "hh_overlimit %u", st->hh_overlimit);
+	print_uint(PRINT_ANY, "tot_count", "tot_hh %u", st->hh_tot_count);
+	print_uint(PRINT_ANY, "cur_count", "cur_hh %u", st->hh_cur_count);
 	return 0;
 }
 
-- 
2.18.0

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

* [PATCH v2 iproute2-next 22/31] tc/pie: implement JSON output
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (20 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 21/31] tc/hhf: " Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 23/31] tc/gred: " Stephen Hemminger
                   ` (8 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/q_pie.c | 33 ++++++++++++++++++---------------
 1 file changed, 18 insertions(+), 15 deletions(-)

diff --git a/tc/q_pie.c b/tc/q_pie.c
index f7924ef5e76c..086785588d64 100644
--- a/tc/q_pie.c
+++ b/tc/q_pie.c
@@ -135,8 +135,6 @@ static int pie_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	unsigned int ecn;
 	unsigned int bytemode;
 
-	SPRINT_BUF(b1);
-
 	if (opt == NULL)
 		return 0;
 
@@ -145,40 +143,40 @@ static int pie_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	if (tb[TCA_PIE_LIMIT] &&
 	    RTA_PAYLOAD(tb[TCA_PIE_LIMIT]) >= sizeof(__u32)) {
 		limit = rta_getattr_u32(tb[TCA_PIE_LIMIT]);
-		fprintf(f, "limit %up ", limit);
+		print_uint(PRINT_ANY, "limit", "limit %up ", limit);
 	}
 	if (tb[TCA_PIE_TARGET] &&
 	    RTA_PAYLOAD(tb[TCA_PIE_TARGET]) >= sizeof(__u32)) {
 		target = rta_getattr_u32(tb[TCA_PIE_TARGET]);
-		fprintf(f, "target %s ", sprint_time(target, b1));
+		print_time("target", "target %s ", target);
 	}
 	if (tb[TCA_PIE_TUPDATE] &&
 	    RTA_PAYLOAD(tb[TCA_PIE_TUPDATE]) >= sizeof(__u32)) {
 		tupdate = rta_getattr_u32(tb[TCA_PIE_TUPDATE]);
-		fprintf(f, "tupdate %s ", sprint_time(tupdate, b1));
+		print_time("tupdate", "tupdate %s ", tupdate);
 	}
 	if (tb[TCA_PIE_ALPHA] &&
 	    RTA_PAYLOAD(tb[TCA_PIE_ALPHA]) >= sizeof(__u32)) {
 		alpha = rta_getattr_u32(tb[TCA_PIE_ALPHA]);
-		fprintf(f, "alpha %u ", alpha);
+		print_uint(PRINT_ANY, "alpha", "alpha %u ", alpha);
 	}
 	if (tb[TCA_PIE_BETA] &&
 	    RTA_PAYLOAD(tb[TCA_PIE_BETA]) >= sizeof(__u32)) {
 		beta = rta_getattr_u32(tb[TCA_PIE_BETA]);
-		fprintf(f, "beta %u ", beta);
+		print_uint(PRINT_ANY, "beta", "beta %u ", beta);
 	}
 
 	if (tb[TCA_PIE_ECN] && RTA_PAYLOAD(tb[TCA_PIE_ECN]) >= sizeof(__u32)) {
 		ecn = rta_getattr_u32(tb[TCA_PIE_ECN]);
 		if (ecn)
-			fprintf(f, "ecn ");
+			print_null(PRINT_ANY, "ecn", "ecn ", NULL);
 	}
 
 	if (tb[TCA_PIE_BYTEMODE] &&
 	    RTA_PAYLOAD(tb[TCA_PIE_BYTEMODE]) >= sizeof(__u32)) {
 		bytemode = rta_getattr_u32(tb[TCA_PIE_BYTEMODE]);
 		if (bytemode)
-			fprintf(f, "bytemode ");
+			print_null(PRINT_ANY, "bytemode", "bytemode ", NULL);
 	}
 
 	return 0;
@@ -197,12 +195,17 @@ static int pie_print_xstats(struct qdisc_util *qu, FILE *f,
 
 	st = RTA_DATA(xstats);
 	/*prob is returned as a fracion of maximum integer value */
-	fprintf(f, "prob %f delay %uus avg_dq_rate %u\n",
-		(double)st->prob / (double)0xffffffff, st->delay,
-		st->avg_dq_rate);
-	fprintf(f, "pkts_in %u overlimit %u dropped %u maxq %u ecn_mark %u\n",
-		st->packets_in, st->overlimit, st->dropped, st->maxq,
-		st->ecn_mark);
+	print_float(PRINT_ANY, "prob", "prob %f",
+		    (double)st->prob / (double)0xffffffff);
+	print_uint(PRINT_ANY, "delay", " delay %uus", st->delay);
+	print_uint(PRINT_ANY, "avg_dq_rate", " avg_dq_rate %u", st->avg_dq_rate);
+	print_string(PRINT_FP, NULL, "%s", _SL_);
+
+	print_uint(PRINT_ANY, "packets_in", "pkts_in %u", st->packets_in);
+	print_uint(PRINT_ANY, "overlimit", " overlimit %u", st->overlimit);
+	print_uint(PRINT_ANY, "dropped", " dropped %u", st->dropped);
+	print_uint(PRINT_ANY, "maxq", " maxq %u", st->maxq);
+	print_uint(PRINT_ANY, "ecn_mark", " ecn_mark %u", st->ecn_mark);
 	return 0;
 
 }
-- 
2.18.0

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

* [PATCH v2 iproute2-next 23/31] tc/gred: implement JSON output
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (21 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 22/31] tc/pie: " Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 24/31] tc/netem: " Stephen Hemminger
                   ` (7 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/q_gred.c | 73 ++++++++++++++++++++++++++++-------------------------
 1 file changed, 38 insertions(+), 35 deletions(-)

diff --git a/tc/q_gred.c b/tc/q_gred.c
index e63fac72a883..957d3c0950f1 100644
--- a/tc/q_gred.c
+++ b/tc/q_gred.c
@@ -274,10 +274,6 @@ static int gred_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	__u32 *limit = NULL;
 	unsigned int i;
 
-	SPRINT_BUF(b1);
-	SPRINT_BUF(b2);
-	SPRINT_BUF(b3);
-
 	if (opt == NULL)
 		return 0;
 
@@ -298,49 +294,56 @@ static int gred_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	qopt = RTA_DATA(tb[TCA_GRED_PARMS]);
 	if (RTA_PAYLOAD(tb[TCA_GRED_DPS]) < sizeof(*sopt) ||
 	    RTA_PAYLOAD(tb[TCA_GRED_PARMS]) < sizeof(*qopt)*MAX_DPs) {
-		fprintf(f, "\n GRED received message smaller than expected\n");
+		fprintf(stderr, "\n GRED received message smaller than expected\n");
 		return -1;
 	}
 
-/* Bad hack! should really return a proper message as shown above*/
-
-	fprintf(f, "vqs %u default %u %s",
-		sopt->DPs,
-		sopt->def_DP,
-		sopt->grio ? "grio " : "");
+	/* Bad hack! should really return a proper message as shown above*/
+	print_uint(PRINT_ANY, "num_dp", "vqs %u", sopt->DPs);
+	print_uint(PRINT_ANY, "default", " default %u", sopt->def_DP);
+	if (sopt->grio)
+		print_null(PRINT_ANY, "grio", "grio ", NULL);
 
 	if (limit)
-		fprintf(f, "limit %s ",
-			sprint_size(*limit, b1));
+		print_size("limit", "limit %s ", *limit);
 
+	open_json_array(PRINT_JSON, "dp");
 	for (i = 0; i < MAX_DPs; i++, qopt++) {
-		if (qopt->DP >= MAX_DPs) continue;
-		fprintf(f, "\n vq %u prio %hhu limit %s min %s max %s ",
-			qopt->DP,
-			qopt->prio,
-			sprint_size(qopt->limit, b1),
-			sprint_size(qopt->qth_min, b2),
-			sprint_size(qopt->qth_max, b3));
+		if (qopt->DP >= MAX_DPs)
+			continue;
+		print_string(PRINT_FP, NULL, "%s", _SL_);
+		open_json_object(NULL);
+		print_uint(PRINT_ANY, "vq", "vq %u ", qopt->DP);
+		print_uint(PRINT_ANY, "prio", "prio %u ", qopt->prio);
+		print_size("limit", "limit %s ", qopt->limit);
+		print_size("min", "min %s ", qopt->qth_min);
+		print_size("max", "min %s ", qopt->qth_max);
+
 		if (show_details) {
-			fprintf(f, "ewma %u ", qopt->Wlog);
+			print_uint(PRINT_ANY, "ewma", "ewma %u ", qopt->Wlog);
 			if (max_p)
-				fprintf(f, "probability %lg ", max_p[i] / pow(2, 32));
+				print_float(PRINT_ANY, "probability",
+					    "probability %lg ", max_p[i] / pow(2, 32));
 			else
-				fprintf(f, "Plog %u ", qopt->Plog);
-			fprintf(f, "Scell_log %u ", qopt->Scell_log);
+				print_uint(PRINT_ANY, "plog",
+					   "Plog %u ", qopt->Plog);
+			print_uint(PRINT_ANY, "scell_log",
+				   "Scell_log %u ", qopt->Scell_log);
 		}
 		if (show_stats) {
-			fprintf(f, "\n  Queue size: average %s current %s ",
-				sprint_size(qopt->qave, b1),
-				sprint_size(qopt->backlog, b2));
-			fprintf(f, "\n  Dropped packets: forced %u early %u pdrop %u other %u ",
-				qopt->forced,
-				qopt->early,
-				qopt->pdrop,
-				qopt->other);
-			fprintf(f, "\n  Total packets: %u (%s) ",
-				qopt->packets,
-				sprint_size(qopt->bytesin, b1));
+			print_string(PRINT_FP, NULL, "%s", _SL_);
+			print_size("average", "  Queue size: average %s", qopt->qave);
+			print_size("backlog", " current %s ", qopt->backlog);
+
+			print_string(PRINT_FP, NULL, "%s  Dropped packets: ", _SL_);
+			print_uint(PRINT_ANY, "forced", " forced %u ", qopt->forced);
+			print_uint(PRINT_ANY, "early", "early %u ", qopt->early);
+			print_uint(PRINT_ANY, "pdrop", "pdrop %u ", qopt->pdrop);
+			print_uint(PRINT_ANY, "other", "other %u ", qopt->other);
+
+			print_string(PRINT_FP, NULL, "%s  Total ", _SL_);
+			print_uint(PRINT_ANY, "packets", "packets: %u ", qopt->packets);
+			print_size("bytes", "(%s) ", qopt->bytesin);
 		}
 	}
 	return 0;
-- 
2.18.0

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

* [PATCH v2 iproute2-next 24/31] tc/netem: implement JSON output
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (22 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 23/31] tc/gred: " Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 25/31] tc/dsmark: " Stephen Hemminger
                   ` (6 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

Also, fix a spelling error in usage message.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/q_netem.c | 94 +++++++++++++++++++++++++---------------------------
 1 file changed, 46 insertions(+), 48 deletions(-)

diff --git a/tc/q_netem.c b/tc/q_netem.c
index 623ec9038ad3..3844ec9adaae 100644
--- a/tc/q_netem.c
+++ b/tc/q_netem.c
@@ -39,7 +39,7 @@ static void explain(void)
 "                 [ loss state P13 [P31 [P32 [P23 P14]]]\n" \
 "                 [ loss gemodel PERCENT [R [1-H [1-K]]]\n" \
 "                 [ ecn ]\n" \
-"                 [ reorder PRECENT [CORRELATION] [ gap DISTANCE ]]\n" \
+"                 [ reorder PERCENT [CORRELATION] [ gap DISTANCE ]]\n" \
 "                 [ rate RATE [PACKETOVERHEAD] [CELLSIZE] [CELLOVERHEAD]]\n");
 }
 
@@ -70,15 +70,18 @@ static int get_percent(__u32 *percent, const char *str)
 	return 0;
 }
 
-static void print_percent(char *buf, int len, __u32 per)
+/*
+ * output percent in human readable format or
+ * in json as floating point (ie. .12 == 12%)
+ */
+static void print_percent(const char *key, const char *fmt, __u32 per)
 {
-	snprintf(buf, len, "%g%%", (100. * per) / UINT32_MAX);
-}
+	double percent = (double) per / UINT32_MAX;
+	SPRINT_BUF(b1);
 
-static char *sprint_percent(__u32 per, char *buf)
-{
-	print_percent(buf, SPRINT_BSIZE-1, per);
-	return buf;
+	print_float(PRINT_JSON, key, NULL, per);
+	snprintf(b1, sizeof(b1), "%g%%", 100. * percent);
+	print_string(PRINT_FP, NULL, fmt, b1);
 }
 
 /*
@@ -526,8 +529,6 @@ static int netem_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	int len;
 	__u64 rate64 = 0;
 
-	SPRINT_BUF(b1);
-
 	if (opt == NULL)
 		return 0;
 
@@ -585,83 +586,80 @@ static int netem_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 		}
 	}
 
-	fprintf(f, "limit %d", qopt.limit);
+	print_uint(PRINT_ANY, "limit", "limit %u", qopt.limit);
 
 	if (qopt.latency) {
-		fprintf(f, " delay %s", sprint_ticks(qopt.latency, b1));
+		print_ticks("delay", " delay %s", qopt.latency);
 
 		if (qopt.jitter) {
-			fprintf(f, "  %s", sprint_ticks(qopt.jitter, b1));
+			print_ticks("jitter", "  %s", qopt.jitter);
 			if (cor && cor->delay_corr)
-				fprintf(f, " %s", sprint_percent(cor->delay_corr, b1));
+				print_percent("delay_corr", " %s",
+					      cor->delay_corr);
 		}
 	}
 
 	if (qopt.loss) {
-		fprintf(f, " loss %s", sprint_percent(qopt.loss, b1));
+		print_percent("loss", " loss %s", qopt.loss);
 		if (cor && cor->loss_corr)
-			fprintf(f, " %s", sprint_percent(cor->loss_corr, b1));
+			print_percent("loss_corr", " %s", cor->loss_corr);
 	}
 
 	if (gimodel) {
-		fprintf(f, " loss state p13 %s", sprint_percent(gimodel->p13, b1));
-		fprintf(f, " p31 %s", sprint_percent(gimodel->p31, b1));
-		fprintf(f, " p32 %s", sprint_percent(gimodel->p32, b1));
-		fprintf(f, " p23 %s", sprint_percent(gimodel->p23, b1));
-		fprintf(f, " p14 %s", sprint_percent(gimodel->p14, b1));
+		print_string(PRINT_ANY, "loss", "loss %s", "state");
+		print_percent("p13", "p13 %s", gimodel->p13);
+		print_percent("p31", " p31 %s", gimodel->p31);
+		print_percent("p32", " p32 %s", gimodel->p32);
+		print_percent("p23", " p23 %s", gimodel->p23);
+		print_percent("p14", " p14 %s", gimodel->p14);
 	}
 
 	if (gemodel) {
-		fprintf(f, " loss gemodel p %s",
-			sprint_percent(gemodel->p, b1));
-		fprintf(f, " r %s", sprint_percent(gemodel->r, b1));
-		fprintf(f, " 1-h %s", sprint_percent(UINT32_MAX -
-						     gemodel->h, b1));
-		fprintf(f, " 1-k %s", sprint_percent(gemodel->k1, b1));
+		print_string(PRINT_ANY, "loss", "loss %s", "gemodel");
+		print_percent("p", "p %s", gemodel->p);
+		print_percent("r", " r %s", gemodel->r);
+		print_percent("1_h", " 1-h %s", UINT32_MAX - gemodel->h);
+		print_percent("1_k", " 1-k %s", gemodel->k1);
 	}
 
 	if (qopt.duplicate) {
-		fprintf(f, " duplicate %s",
-			sprint_percent(qopt.duplicate, b1));
+		print_percent("duplicate", " duplicate %s", qopt.duplicate);
 		if (cor && cor->dup_corr)
-			fprintf(f, " %s", sprint_percent(cor->dup_corr, b1));
+			print_percent("dup_corr", " %s", cor->dup_corr);
 	}
 
 	if (reorder && reorder->probability) {
-		fprintf(f, " reorder %s",
-			sprint_percent(reorder->probability, b1));
+		print_percent("reorder", " reorder %s", reorder->probability);
 		if (reorder->correlation)
-			fprintf(f, " %s",
-				sprint_percent(reorder->correlation, b1));
+			print_percent("reorder_corr", " %s",
+				      reorder->correlation);
 	}
 
 	if (corrupt && corrupt->probability) {
-		fprintf(f, " corrupt %s",
-			sprint_percent(corrupt->probability, b1));
+		print_percent("corrupt", " corrupt %s", corrupt->probability);
 		if (corrupt->correlation)
-			fprintf(f, " %s",
-				sprint_percent(corrupt->correlation, b1));
+			print_percent("corrupt_corr", " %s", corrupt->correlation);
 	}
 
 	if (rate && rate->rate) {
-		if (rate64)
-			fprintf(f, " rate %s", sprint_rate(rate64, b1));
-		else
-			fprintf(f, " rate %s", sprint_rate(rate->rate, b1));
+		print_rate("rate", "rate %s", rate64 ? : rate->rate);
+
 		if (rate->packet_overhead)
-			fprintf(f, " packetoverhead %d", rate->packet_overhead);
+			print_uint(PRINT_ANY, "packet_overhead",
+				   " packetoverhead %d", rate->packet_overhead);
 		if (rate->cell_size)
-			fprintf(f, " cellsize %u", rate->cell_size);
+			print_uint(PRINT_ANY, "cell_size",
+				   " cellsize %u", rate->cell_size);
 		if (rate->cell_overhead)
-			fprintf(f, " celloverhead %d", rate->cell_overhead);
+			print_uint(PRINT_ANY, "cell_overhead",
+				   " celloverhead %d", rate->cell_overhead);
 	}
 
 	if (ecn)
-		fprintf(f, " ecn ");
+		print_null(PRINT_ANY, "ecn", " ecn", NULL);
 
 	if (qopt.gap)
-		fprintf(f, " gap %lu", (unsigned long)qopt.gap);
-
+		print_uint(PRINT_ANY, "gap", " gap %u", qopt.gap);
 
 	return 0;
 }
-- 
2.18.0

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

* [PATCH v2 iproute2-next 25/31] tc/dsmark: implement JSON output
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (23 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 24/31] tc/netem: " Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 26/31] tc/cbs: convert to " Stephen Hemminger
                   ` (5 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/q_dsmark.c | 27 ++++++++++++++++++---------
 1 file changed, 18 insertions(+), 9 deletions(-)

diff --git a/tc/q_dsmark.c b/tc/q_dsmark.c
index d3e8292d777c..d2b9e3885377 100644
--- a/tc/q_dsmark.c
+++ b/tc/q_dsmark.c
@@ -131,28 +131,37 @@ static int dsmark_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	if (tb[TCA_DSMARK_MASK]) {
 		if (!RTA_PAYLOAD(tb[TCA_DSMARK_MASK]))
 			fprintf(stderr, "dsmark: empty mask\n");
-		else fprintf(f, "mask 0x%02x ",
-			    rta_getattr_u8(tb[TCA_DSMARK_MASK]));
+		else
+			print_0xhex(PRINT_ANY, "mask",
+				    "mask 0x%02x ",
+				    rta_getattr_u8(tb[TCA_DSMARK_MASK]));
 	}
 	if (tb[TCA_DSMARK_VALUE]) {
 		if (!RTA_PAYLOAD(tb[TCA_DSMARK_VALUE]))
 			fprintf(stderr, "dsmark: empty value\n");
-		else fprintf(f, "value 0x%02x ",
-			    rta_getattr_u8(tb[TCA_DSMARK_VALUE]));
+		else
+			print_0xhex(PRINT_ANY, "value",
+				    "value 0x%02x ",
+				    rta_getattr_u8(tb[TCA_DSMARK_VALUE]));
 	}
 	if (tb[TCA_DSMARK_INDICES]) {
 		if (RTA_PAYLOAD(tb[TCA_DSMARK_INDICES]) < sizeof(__u16))
 			fprintf(stderr, "dsmark: indices too short\n");
-		else fprintf(f, "indices 0x%04x ",
-			    rta_getattr_u16(tb[TCA_DSMARK_INDICES]));
+		else
+			print_0xhex(PRINT_ANY, "indcies",
+				    "indices 0x%04x ",
+				    rta_getattr_u16(tb[TCA_DSMARK_INDICES]));
 	}
 	if (tb[TCA_DSMARK_DEFAULT_INDEX]) {
 		if (RTA_PAYLOAD(tb[TCA_DSMARK_DEFAULT_INDEX]) < sizeof(__u16))
 			fprintf(stderr, "dsmark: default_index too short\n");
-		else fprintf(f, "default_index 0x%04x ",
-			    rta_getattr_u16(tb[TCA_DSMARK_DEFAULT_INDEX]));
+		else
+			print_0xhex(PRINT_ANY, "default_index",
+				    "default_index 0x%04x ",
+				    rta_getattr_u16(tb[TCA_DSMARK_DEFAULT_INDEX]));
 	}
-	if (tb[TCA_DSMARK_SET_TC_INDEX]) fprintf(f, "set_tc_index ");
+	if (tb[TCA_DSMARK_SET_TC_INDEX])
+		print_null(PRINT_ANY, "set_tc_index", "set_tc_index ", NULL);
 	return 0;
 }
 
-- 
2.18.0

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

* [PATCH v2 iproute2-next 26/31] tc/cbs: convert to JSON output
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (24 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 25/31] tc/dsmark: " Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 27/31] tc/cbq: " Stephen Hemminger
                   ` (4 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/q_cbs.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/tc/q_cbs.c b/tc/q_cbs.c
index a2ffb1db3852..1518a79cd733 100644
--- a/tc/q_cbs.c
+++ b/tc/q_cbs.c
@@ -125,11 +125,11 @@ static int cbs_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	if (RTA_PAYLOAD(tb[TCA_CBS_PARMS])  < sizeof(*qopt))
 		return -1;
 
-	fprintf(f, "hicredit %d ", qopt->hicredit);
-	fprintf(f, "locredit %d ", qopt->locredit);
-	fprintf(f, "sendslope %d ", qopt->sendslope);
-	fprintf(f, "idleslope %d ", qopt->idleslope);
-	fprintf(f, "offload %d ", qopt->offload);
+	print_uint(PRINT_ANY, "hicredit", "hicredit %u ", qopt->hicredit);
+	print_uint(PRINT_ANY, "locredit", "locredit %u", qopt->locredit);
+	print_uint(PRINT_ANY, "sendslope", "sendslope %u", qopt->sendslope);
+	print_uint(PRINT_ANY, "idleslope", "idleslope %u", qopt->idleslope);
+	print_uint(PRINT_ANY, "offload", "offload %u", qopt->offload);
 
 	return 0;
 }
-- 
2.18.0

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

* [PATCH v2 iproute2-next 27/31] tc/cbq: convert to JSON output
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (25 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 26/31] tc/cbs: convert to " Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 28/31] tc/atm: " Stephen Hemminger
                   ` (3 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/q_cbq.c | 73 ++++++++++++++++++++++++++++++------------------------
 1 file changed, 40 insertions(+), 33 deletions(-)

diff --git a/tc/q_cbq.c b/tc/q_cbq.c
index ad0170c41858..525a5823b808 100644
--- a/tc/q_cbq.c
+++ b/tc/q_cbq.c
@@ -453,9 +453,6 @@ static int cbq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	struct tc_cbq_ovl *ovl = NULL;
 	unsigned int linklayer;
 
-	SPRINT_BUF(b1);
-	SPRINT_BUF(b2);
-
 	if (opt == NULL)
 		return 0;
 
@@ -495,76 +492,84 @@ static int cbq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	}
 
 	if (r) {
+		print_rate("rate", "rate %s ", r->rate);
 
-		fprintf(f, "rate %s ",
-			sprint_rate(r->rate, b1));
 		linklayer = (r->linklayer & TC_LINKLAYER_MASK);
 		if (linklayer > TC_LINKLAYER_ETHERNET || show_details)
-			fprintf(f, "linklayer %s ", sprint_linklayer(linklayer, b2));
+			print_linklayer("linklayer", "linklayer %s ", linklayer);
+
 		if (show_details) {
-			fprintf(f, "cell %ub ", 1<<r->cell_log);
+			print_uint(PRINT_ANY, "cell", "cell %ub ", 1<<r->cell_log);
 			if (r->mpu)
-				fprintf(f, "mpu %ub ", r->mpu);
+				print_uint(PRINT_ANY, "mpu", "mpu %ub ", r->mpu);
 			if (r->overhead)
-				fprintf(f, "overhead %ub ", r->overhead);
+				print_uint(PRINT_ANY, "overhead",
+					   "overhead %ub ", r->overhead);
 		}
 	}
+
 	if (lss && lss->flags) {
 		int comma = 0;
 
-		fprintf(f, "(");
+		print_string(PRINT_FP, NULL, "(", NULL);
 		if (lss->flags&TCF_CBQ_LSS_BOUNDED) {
-			fprintf(f, "bounded");
+			print_null(PRINT_ANY, "bounded", "bounded", NULL);
 			comma = 1;
 		}
 		if (lss->flags&TCF_CBQ_LSS_ISOLATED) {
 			if (comma)
-				fprintf(f, ",");
-			fprintf(f, "isolated");
+				print_string(PRINT_FP, NULL, ",", NULL);
+			print_null(PRINT_ANY, "isolated", "isolated", NULL);
 		}
-		fprintf(f, ") ");
+		print_string(PRINT_FP, NULL, ") ", NULL);
 	}
+
 	if (wrr) {
 		if (wrr->priority != TC_CBQ_MAXPRIO)
-			fprintf(f, "prio %u", wrr->priority);
+			print_uint(PRINT_ANY, "prio", "prio %u", wrr->priority);
 		else
-			fprintf(f, "prio no-transmit");
+			print_null(PRINT_ANY, "no-transmit", "prio no-transmit", NULL);
 
 		if (show_details) {
-			fprintf(f, "/%u ", wrr->cpriority);
+			print_uint(PRINT_ANY, "cpriority", "/%u ", wrr->cpriority);
 			if (wrr->weight != 1)
-				fprintf(f, "weight %s ",
-					sprint_rate(wrr->weight, b1));
+				print_rate("weight", "weight %s ", wrr->weight);
 			if (wrr->allot)
-				fprintf(f, "allot %ub ", wrr->allot);
+				print_uint(PRINT_ANY, "allot", "allot %ub ", wrr->allot);
 		}
 	}
+
 	if (lss && show_details) {
-		fprintf(f, "\nlevel %u ewma %u avpkt %ub ", lss->level, lss->ewma_log, lss->avpkt);
+		print_string(PRINT_FP, NULL, "%s", _SL_);
+		print_uint(PRINT_ANY, "level", "level %u", lss->level);
+		print_uint(PRINT_ANY, "ewma", " ewma %u", lss->ewma_log);
+		print_uint(PRINT_ANY, "avpkt", " avpkt %ub ", lss->avpkt);
+
 		if (lss->maxidle) {
-			fprintf(f, "maxidle %s ", sprint_ticks(lss->maxidle>>lss->ewma_log, b1));
+			print_ticks("maxidle", "maxidle %s ", lss->maxidle >> lss->ewma_log);
 			if (show_raw)
-				fprintf(f, "[%08x] ", lss->maxidle);
+				print_0xhex(PRINT_FP, NULL, "[%08x] ", lss->maxidle);
 		}
 		if (lss->minidle != 0x7fffffff) {
-			fprintf(f, "minidle %s ", sprint_ticks(lss->minidle>>lss->ewma_log, b1));
+			print_ticks("minidle", "minidle %s ", lss->minidle >> lss->ewma_log);
 			if (show_raw)
-				fprintf(f, "[%08x] ", lss->minidle);
+				print_0xhex(PRINT_FP, NULL, "[%08x] ", lss->minidle);
 		}
 		if (lss->offtime) {
-			fprintf(f, "offtime %s ", sprint_ticks(lss->offtime, b1));
+			print_ticks("offtime", "offtime %s ", lss->offtime);
 			if (show_raw)
-				fprintf(f, "[%08x] ", lss->offtime);
+				print_0xhex(PRINT_FP, NULL, "[%08x] ", lss->offtime);
 		}
 	}
+
 	if (fopt && show_details) {
 		char buf[64];
 
 		print_tc_classid(buf, sizeof(buf), fopt->split);
-		fprintf(f, "\nsplit %s ", buf);
-		if (fopt->defmap) {
-			fprintf(f, "defmap %08x", fopt->defmap);
-		}
+		print_string(PRINT_FP, NULL, "%s", _SL_);
+		print_string(PRINT_ANY, "split", "split %s ", buf);
+		if (fopt->defmap)
+			print_0xhex(PRINT_ANY, "defmap", "defmap %08x", fopt->defmap);
 	}
 	return 0;
 }
@@ -580,8 +585,10 @@ static int cbq_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstat
 		return -1;
 
 	st = RTA_DATA(xstats);
-	fprintf(f, "  borrowed %u overactions %u avgidle %g undertime %g", st->borrows,
-		st->overactions, (double)st->avgidle, (double)st->undertime);
+	print_uint(PRINT_ANY, "borrowed", "  borrowed %u", st->borrows);
+	print_uint(PRINT_ANY, "overactions", " overactions %u", st->overactions);
+	print_float(PRINT_ANY, "avgidle", " avgidle %g", (double) st->avgidle);
+	print_float(PRINT_ANY, "undertime", " undertime %g", (double)st->undertime);
 	return 0;
 }
 
-- 
2.18.0

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

* [PATCH v2 iproute2-next 28/31] tc/atm: convert to JSON output
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (26 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 27/31] tc/cbq: " Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 29/31] tc/hfsc: " Stephen Hemminger
                   ` (2 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/q_atm.c | 38 +++++++++++++++++++++++---------------
 1 file changed, 23 insertions(+), 15 deletions(-)

diff --git a/tc/q_atm.c b/tc/q_atm.c
index f8215f06507a..d5ab7a06b28f 100644
--- a/tc/q_atm.c
+++ b/tc/q_atm.c
@@ -194,37 +194,45 @@ static int atm_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 			fprintf(stderr, "ATM: address too short\n");
 		else {
 			if (atm2text(buffer, MAX_ATM_ADDR_LEN,
-			    RTA_DATA(tb[TCA_ATM_ADDR]), A2T_PRETTY | A2T_NAME) <
-			    0) fprintf(stderr, "atm2text error\n");
-			fprintf(f, "pvc %s ", buffer);
+				     RTA_DATA(tb[TCA_ATM_ADDR]), A2T_PRETTY | A2T_NAME) < 0)
+				fprintf(stderr, "atm2text error\n");
+			else
+				print_string(PRINT_ANY, "pvc",
+					     "pvc %s ", buffer);
 		}
 	}
+
 	if (tb[TCA_ATM_HDR]) {
 		int i;
 		const __u8 *hdr = RTA_DATA(tb[TCA_ATM_HDR]);
 
-		fprintf(f, "hdr");
-		for (i = 0; i < RTA_PAYLOAD(tb[TCA_ATM_HDR]); i++)
-			fprintf(f, "%c%02x", i ? '.' : ' ', hdr[i]);
-		if (!i) fprintf(f, " .");
-		fprintf(f, " ");
+		open_json_array(PRINT_ANY, "hdr");
+		for (i = 0; i < RTA_PAYLOAD(tb[TCA_ATM_HDR]); i++) {
+			print_string(PRINT_FP, NULL, "%s",
+				     i ? "." : " ");
+			print_0xhex(PRINT_ANY, NULL, "%02x", hdr[i]);
+		}
+
+		print_string(PRINT_FP, NULL, "%s ", i ? "" : " .");
 	}
+
 	if (tb[TCA_ATM_EXCESS]) {
 		__u32 excess;
 
 		if (RTA_PAYLOAD(tb[TCA_ATM_EXCESS]) < sizeof(excess))
 			fprintf(stderr, "ATM: excess class ID too short\n");
 		else {
-			excess = rta_getattr_u32(tb[TCA_ATM_EXCESS]);
-			if (!excess) fprintf(f, "excess clp ");
-			else {
-				char buf[64];
+			char buf[64];
 
+			excess = rta_getattr_u32(tb[TCA_ATM_EXCESS]);
+			if (!excess)
+				strcpy(buf, "clp");
+			else
 				print_tc_classid(buf, sizeof(buf), excess);
-				fprintf(f, "excess %s ", buf);
-			}
+			print_string(PRINT_ANY, "excess", "excess %s ", buf);
 		}
 	}
+
 	if (tb[TCA_ATM_STATE]) {
 		static const char *map[] = { ATM_VS2TXT_MAP };
 		int state;
@@ -233,7 +241,7 @@ static int atm_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 			fprintf(stderr, "ATM: state field too short\n");
 		else {
 			state = rta_getattr_u32(tb[TCA_ATM_STATE]);
-			fprintf(f, "%s ", map[state]);
+			print_string(PRINT_ANY, "state", "%s ", map[state]);
 		}
 	}
 	return 0;
-- 
2.18.0

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

* [PATCH v2 iproute2-next 29/31] tc/hfsc: convert to JSON output
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (27 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 28/31] tc/atm: " Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 30/31] tc/htb: implement " Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 31/31] tc/fq_codel: use JSON helpers Stephen Hemminger
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/q_hfsc.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/tc/q_hfsc.c b/tc/q_hfsc.c
index f34b1b2fe2a9..e2f366b8a189 100644
--- a/tc/q_hfsc.c
+++ b/tc/q_hfsc.c
@@ -113,7 +113,8 @@ hfsc_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	qopt = RTA_DATA(opt);
 
 	if (qopt->defcls != 0)
-		fprintf(f, "default %x ", qopt->defcls);
+		print_0xhex(PRINT_ANY, "default",
+			    "default %x ", qopt->defcls);
 
 	return 0;
 }
@@ -129,13 +130,12 @@ hfsc_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstats)
 		return -1;
 	st = RTA_DATA(xstats);
 
-	fprintf(f, " period %u ", st->period);
+	print_uint(PRINT_ANY, "period", " period %u ", st->period);
 	if (st->work != 0)
-		fprintf(f, "work %llu bytes ", (unsigned long long) st->work);
+		print_u64(PRINT_ANY, "work", "work %llu bytes ", st->work);
 	if (st->rtwork != 0)
-		fprintf(f, "rtwork %llu bytes ", (unsigned long long) st->rtwork);
-	fprintf(f, "level %u ", st->level);
-	fprintf(f, "\n");
+		print_u64(PRINT_ANY, "rtwork", "rtwork %llu bytes ", st->rtwork);
+	print_uint(PRINT_ANY, "level", "level %u ", st->level);
 
 	return 0;
 }
@@ -214,14 +214,14 @@ hfsc_parse_class_opt(struct qdisc_util *qu, int argc, char **argv,
 }
 
 static void
-hfsc_print_sc(FILE *f, char *name, struct tc_service_curve *sc)
+hfsc_print_sc(FILE *f, const char *name, const struct tc_service_curve *sc)
 {
-	SPRINT_BUF(b1);
-
-	fprintf(f, "%s ", name);
-	fprintf(f, "m1 %s ", sprint_rate(sc->m1, b1));
-	fprintf(f, "d %s ", sprint_time(tc_core_ktime2time(sc->d), b1));
-	fprintf(f, "m2 %s ", sprint_rate(sc->m2, b1));
+	print_string(PRINT_FP, NULL, "%s ", name);
+	open_json_object(name);
+	print_rate("m1", "m1 %s ", sc->m1);
+	print_time("d", "d %s ", tc_core_ktime2time(sc->d));
+	print_rate("m2", "m2 %s ", sc->m2);
+	close_json_object();
 }
 
 static int
-- 
2.18.0

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

* [PATCH v2 iproute2-next 30/31] tc/htb: implement JSON output
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (28 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 29/31] tc/hfsc: " Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 31/31] tc/fq_codel: use JSON helpers Stephen Hemminger
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/q_htb.c | 53 ++++++++++++++++++++++++++++++-----------------------
 1 file changed, 30 insertions(+), 23 deletions(-)

diff --git a/tc/q_htb.c b/tc/q_htb.c
index 7d5f6ce44773..e7026ad017a4 100644
--- a/tc/q_htb.c
+++ b/tc/q_htb.c
@@ -278,8 +278,6 @@ static int htb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 	__u64 rate64, ceil64;
 
 	SPRINT_BUF(b1);
-	SPRINT_BUF(b2);
-	SPRINT_BUF(b3);
 
 	if (opt == NULL)
 		return 0;
@@ -308,34 +306,39 @@ static int htb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 		    RTA_PAYLOAD(tb[TCA_HTB_CEIL64]) >= sizeof(ceil64))
 			ceil64 = rta_getattr_u64(tb[TCA_HTB_CEIL64]);
 
-		fprintf(f, "rate %s ", sprint_rate(rate64, b1));
+		print_rate("rate", "rate %s ", rate64);
 		if (hopt->rate.overhead)
-			fprintf(f, "overhead %u ", hopt->rate.overhead);
+			print_uint(PRINT_ANY, "overhead", "overhead %u ", hopt->rate.overhead);
 		buffer = tc_calc_xmitsize(rate64, hopt->buffer);
 
-		fprintf(f, "ceil %s ", sprint_rate(ceil64, b1));
+		print_rate("ceil", "ceil %s ", ceil64);
 		cbuffer = tc_calc_xmitsize(ceil64, hopt->cbuffer);
 		linklayer = (hopt->rate.linklayer & TC_LINKLAYER_MASK);
 		if (linklayer > TC_LINKLAYER_ETHERNET || show_details)
-			fprintf(f, "linklayer %s ", sprint_linklayer(linklayer, b3));
+			print_linklayer("linklayer", "linklayer %s ", linklayer);
+
 		if (show_details) {
-			fprintf(f, "burst %s/%u mpu %s ",
-				sprint_size(buffer, b1),
-				1<<hopt->rate.cell_log,
-				sprint_size(hopt->rate.mpu, b2));
-			fprintf(f, "cburst %s/%u mpu %s ",
-				sprint_size(cbuffer, b1),
-				1<<hopt->ceil.cell_log,
-				sprint_size(hopt->ceil.mpu, b2));
-			fprintf(f, "level %d ", (int)hopt->level);
+			print_size("burst", "burst %s", buffer);
+			print_uint(PRINT_ANY, "rate_log", "/%u", 1u << hopt->rate.cell_log);
+			print_size("rate_mpu", " mpu %s ", hopt->rate.mpu);
+
+			print_size("cburst", "cburst %s", cbuffer);
+			print_uint(PRINT_ANY, "ceil_log", "/%u", 1u << hopt->ceil.cell_log);
+			print_size("ceil_mpu", " mpu %s ", hopt->ceil.mpu);
+			print_uint(PRINT_ANY, "level", "level %u ", hopt->level);
 		} else {
-			fprintf(f, "burst %s ", sprint_size(buffer, b1));
-			fprintf(f, "cburst %s ", sprint_size(cbuffer, b1));
+			print_size("burst", "burst %s ", buffer);
+			print_size("cburst", "cburst %s", cbuffer);
+		}
+
+		if (show_raw) {
+			print_0xhex(PRINT_ANY, "buffer",
+				    "buffer [%08x]", hopt->buffer);
+			print_0xhex(PRINT_ANY, "cbuffer",
+				    " cbuffer [%08x] ", hopt->cbuffer);
 		}
-		if (show_raw)
-			fprintf(f, "buffer [%08x] cbuffer [%08x] ",
-				hopt->buffer, hopt->cbuffer);
 	}
+
 	if (tb[TCA_HTB_INIT]) {
 		gopt = RTA_DATA(tb[TCA_HTB_INIT]);
 		if (RTA_PAYLOAD(tb[TCA_HTB_INIT])  < sizeof(*gopt)) return -1;
@@ -370,9 +373,13 @@ static int htb_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstat
 		return -1;
 
 	st = RTA_DATA(xstats);
-	fprintf(f, " lended: %u borrowed: %u giants: %u\n",
-		st->lends, st->borrows, st->giants);
-	fprintf(f, " tokens: %d ctokens: %d\n", st->tokens, st->ctokens);
+	print_uint(PRINT_ANY, "lended", " lended: %u", st->lends);
+	print_uint(PRINT_ANY, "borrowed", " borrowed: %u", st->borrows);
+	print_uint(PRINT_ANY, "giants", " giants: %u", st->giants);
+
+	print_string(PRINT_FP, NULL, "%s", _SL_);
+	print_int(PRINT_ANY, "tokens", " tokens: %d", st->tokens);
+	print_int(PRINT_ANY, "ctokens", " ctokens: %d", st->ctokens);
 	return 0;
 }
 
-- 
2.18.0

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

* [PATCH v2 iproute2-next 31/31] tc/fq_codel: use JSON helpers
  2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
                   ` (29 preceding siblings ...)
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 30/31] tc/htb: implement " Stephen Hemminger
@ 2018-07-10 21:05 ` Stephen Hemminger
  30 siblings, 0 replies; 33+ messages in thread
From: Stephen Hemminger @ 2018-07-10 21:05 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Stephen Hemminger

From: Stephen Hemminger <sthemmin@microsoft.com>

New routines make doing JSON output of time and size
easier and consistent.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 tc/q_fq_codel.c | 38 +++++++++-----------------------------
 1 file changed, 9 insertions(+), 29 deletions(-)

diff --git a/tc/q_fq_codel.c b/tc/q_fq_codel.c
index 02ad2214110b..4cdaec58bf0a 100644
--- a/tc/q_fq_codel.c
+++ b/tc/q_fq_codel.c
@@ -163,8 +163,6 @@ static int fq_codel_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt
 	unsigned int ce_threshold;
 	unsigned int memory_limit;
 
-	SPRINT_BUF(b1);
-
 	if (opt == NULL)
 		return 0;
 
@@ -188,30 +186,22 @@ static int fq_codel_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt
 	if (tb[TCA_FQ_CODEL_TARGET] &&
 	    RTA_PAYLOAD(tb[TCA_FQ_CODEL_TARGET]) >= sizeof(__u32)) {
 		target = rta_getattr_u32(tb[TCA_FQ_CODEL_TARGET]);
-		print_uint(PRINT_JSON, "target", NULL, target);
-		print_string(PRINT_FP, NULL, "target %s ",
-			     sprint_time(target, b1));
+		print_time("target", "target %s ", target);
 	}
 	if (tb[TCA_FQ_CODEL_CE_THRESHOLD] &&
 	    RTA_PAYLOAD(tb[TCA_FQ_CODEL_CE_THRESHOLD]) >= sizeof(__u32)) {
 		ce_threshold = rta_getattr_u32(tb[TCA_FQ_CODEL_CE_THRESHOLD]);
-		print_uint(PRINT_JSON, "ce_threshold", NULL, ce_threshold);
-		print_string(PRINT_FP, NULL, "ce_threshold %s ",
-			     sprint_time(ce_threshold, b1));
+		print_time("ce_threshold", "ce_threshold %s ", ce_threshold);
 	}
 	if (tb[TCA_FQ_CODEL_INTERVAL] &&
 	    RTA_PAYLOAD(tb[TCA_FQ_CODEL_INTERVAL]) >= sizeof(__u32)) {
 		interval = rta_getattr_u32(tb[TCA_FQ_CODEL_INTERVAL]);
-		print_uint(PRINT_JSON, "interval", NULL, interval);
-		print_string(PRINT_FP, NULL, "interval %s ",
-			     sprint_time(interval, b1));
+		print_time("interval", "interval %s ", interval);
 	}
 	if (tb[TCA_FQ_CODEL_MEMORY_LIMIT] &&
 	    RTA_PAYLOAD(tb[TCA_FQ_CODEL_MEMORY_LIMIT]) >= sizeof(__u32)) {
 		memory_limit = rta_getattr_u32(tb[TCA_FQ_CODEL_MEMORY_LIMIT]);
-		print_uint(PRINT_JSON, "memory_limit", NULL, memory_limit);
-		print_string(PRINT_FP, NULL, "memory_limit %s ",
-			     sprint_size(memory_limit, b1));
+		print_size("memory_limit", "memory_limit %s ", memory_limit);
 	}
 	if (tb[TCA_FQ_CODEL_ECN] &&
 	    RTA_PAYLOAD(tb[TCA_FQ_CODEL_ECN]) >= sizeof(__u32)) {
@@ -228,8 +218,6 @@ static int fq_codel_print_xstats(struct qdisc_util *qu, FILE *f,
 {
 	struct tc_fq_codel_xstats _st = {}, *st;
 
-	SPRINT_BUF(b1);
-
 	if (xstats == NULL)
 		return 0;
 
@@ -268,21 +256,13 @@ static int fq_codel_print_xstats(struct qdisc_util *qu, FILE *f,
 			st->class_stats.count);
 		print_uint(PRINT_ANY, "lastcount", " lastcount %u",
 			st->class_stats.lastcount);
-		print_uint(PRINT_JSON, "ldelay", NULL,
-			st->class_stats.ldelay);
-		print_string(PRINT_FP, NULL, " ldelay %s",
-			sprint_time(st->class_stats.ldelay, b1));
+		print_time("ldelay", " ldelay %s",
+			   st->class_stats.ldelay);
+
 		if (st->class_stats.dropping) {
 			print_bool(PRINT_ANY, "dropping", " dropping", true);
-			if (st->class_stats.drop_next < 0)
-				print_string(PRINT_FP, NULL, " drop_next -%s",
-					sprint_time(-st->class_stats.drop_next, b1));
-			else {
-				print_uint(PRINT_JSON, "drop_next", NULL,
-					st->class_stats.drop_next);
-				print_string(PRINT_FP, NULL, " drop_next %s",
-					sprint_time(st->class_stats.drop_next, b1));
-			}
+			print_time("drop_next", " drop_next %s",
+				   st->class_stats.drop_next);
 		}
 	}
 	return 0;
-- 
2.18.0

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

* Re: [PATCH v2 iproute2-next 06/31] tc/util: add print helpers for JSON
  2018-07-10 21:05 ` [PATCH v2 iproute2-next 06/31] tc/util: add print helpers for JSON Stephen Hemminger
@ 2018-07-17  1:05   ` David Ahern
  0 siblings, 0 replies; 33+ messages in thread
From: David Ahern @ 2018-07-17  1:05 UTC (permalink / raw)
  To: Stephen Hemminger, netdev; +Cc: Stephen Hemminger

On 7/10/18 3:05 PM, Stephen Hemminger wrote:
> From: Stephen Hemminger <sthemmin@microsoft.com>
> 
> Add a helper to print rate, time and size in numeric or pretty format
> based on JSON flag.
> 
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> ---
>  tc/tc_util.c | 83 +++++++++++++++++++++++++++++++++-------------------
>  tc/tc_util.h |  6 ++++
>  2 files changed, 59 insertions(+), 30 deletions(-)

This one fails to compile on Stretch:

tc
    CC       tc_util.o
tc_util.c:388:6: error: conflicting types for ‘print_time’
 void print_time(const char *key, const char *fmt, __u32 tm)
      ^~~~~~~~~~
In file included from tc_util.c:27:0:
tc_util.h:92:6: note: previous declaration of ‘print_time’ was here
 void print_time(const char *key, const char *fmt, __s32 tm);
      ^~~~~~~~~~
../config.mk:43: recipe for target 'tc_util.o' failed

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

end of thread, other threads:[~2018-07-17  1:35 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-07-10 21:05 [PATCH v2 iproute2-next 00/31] tc use JSON in all qdisc Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 01/31] tc: use JSON in error handling Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 02/31] tc: use const char in util Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 03/31] tc: convert stats print to json Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 04/31] tc/cbq: use sprint_rate Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 05/31] tc/util: remove unused print functions Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 06/31] tc/util: add print helpers for JSON Stephen Hemminger
2018-07-17  1:05   ` David Ahern
2018-07-10 21:05 ` [PATCH v2 iproute2-next 07/31] tc/red: use new JSON helpers Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 08/31] tc/sfq: add json support Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 09/31] tc/fq: support JSON output Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 10/31] tc/mqprio: implement " Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 11/31] tc/drr: " Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 12/31] tc/rr: " Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 13/31] tc/qfq: implement JSON Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 14/31] tc/sfb: implement JSON output Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 15/31] tc/multiq: " Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 16/31] tc/util: allow signed value for time Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 17/31] tc/codel: implement JSON output Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 18/31] tc/fifo: " Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 19/31] tc/tbf: implement JSON output format Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 20/31] tc/choke: implement JSON output Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 21/31] tc/hhf: " Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 22/31] tc/pie: " Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 23/31] tc/gred: " Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 24/31] tc/netem: " Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 25/31] tc/dsmark: " Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 26/31] tc/cbs: convert to " Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 27/31] tc/cbq: " Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 28/31] tc/atm: " Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 29/31] tc/hfsc: " Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 30/31] tc/htb: implement " Stephen Hemminger
2018-07-10 21:05 ` [PATCH v2 iproute2-next 31/31] tc/fq_codel: use JSON helpers Stephen Hemminger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).