* [PATCH iproute2-next 0/4] JSON (and color) support for iproute
@ 2018-02-08 16:26 Stephen Hemminger
2018-02-08 16:26 ` [PATCH iproute2-next 1/4] json: make pretty printing optional Stephen Hemminger
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Stephen Hemminger @ 2018-02-08 16:26 UTC (permalink / raw)
To: dsahern; +Cc: netdev, Stephen Hemminger
From: Stephen Hemminger <stephen@networkplumber.org>
This set of patches adds JSON output to route printing.
Tested for the simple cases, but there are many variations and there
such as lw tunnels which have not be tested.
The color formatting may need some additional tweaks. It looks
like for some tags the tag is also showing up in color.
This should be fixed in print_color_string rather than having
to do special case handling in so many places.
This patchset also changes the default JSON output to be compressed
(since the purpose of JSON is to make output machine readable);
but do optional pretty print formatting with -p flag.
Stephen Hemminger (4):
json: make pretty printing optional
man: add documentation for json and pretty flags
json: fix newline at end of array
iproute: implement JSON and color output
include/json_print.h | 2 +
include/utils.h | 5 +
ip/ip.c | 7 +-
ip/iproute.c | 376 +++++++++++++++++++++++++++++++++++---------------
ip/iproute_lwtunnel.c | 129 ++++++++++-------
lib/json_print.c | 5 +-
lib/json_writer.c | 5 +
man/man8/ip.8 | 18 ++-
man/man8/tc.8 | 3 +-
tc/tc.c | 3 +
10 files changed, 381 insertions(+), 172 deletions(-)
--
2.15.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH iproute2-next 1/4] json: make pretty printing optional
2018-02-08 16:26 [PATCH iproute2-next 0/4] JSON (and color) support for iproute Stephen Hemminger
@ 2018-02-08 16:26 ` Stephen Hemminger
2018-02-08 16:26 ` [PATCH iproute2-next 2/4] man: add documentation for json and pretty flags Stephen Hemminger
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Stephen Hemminger @ 2018-02-08 16:26 UTC (permalink / raw)
To: dsahern; +Cc: netdev, Stephen Hemminger
From: Stephen Hemminger <stephen@networkplumber.org>
Since JSON is intended for programmatic consumption, it makes
sense for the default output format to be concise as possible.
For programmer and other uses, it is helpful to keep the pretty
whitespace format; therefore enable it with -p flag.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
include/json_print.h | 2 ++
ip/ip.c | 3 +++
lib/json_print.c | 3 ++-
tc/tc.c | 3 +++
4 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/include/json_print.h b/include/json_print.h
index 2ca7830adbd6..45a817ce6b9a 100644
--- a/include/json_print.h
+++ b/include/json_print.h
@@ -15,6 +15,8 @@
#include "json_writer.h"
#include "color.h"
+extern int show_pretty;
+
json_writer_t *get_json_writer(void);
/*
diff --git a/ip/ip.c b/ip/ip.c
index b15e6b66b3f6..a6611292808d 100644
--- a/ip/ip.c
+++ b/ip/ip.c
@@ -31,6 +31,7 @@ int show_stats;
int show_details;
int oneline;
int brief;
+int show_pretty;
int json;
int timestamp;
const char *_SL_;
@@ -259,6 +260,8 @@ int main(int argc, char **argv)
++brief;
} else if (matches(opt, "-json") == 0) {
++json;
+ } else if (matches(opt, "-pretty") == 0) {
+ ++show_pretty;
} else if (matches(opt, "-rcvbuf") == 0) {
unsigned int size;
diff --git a/lib/json_print.c b/lib/json_print.c
index 6518ba98f5bf..e3da1bdfd5b0 100644
--- a/lib/json_print.c
+++ b/lib/json_print.c
@@ -28,7 +28,8 @@ void new_json_obj(int json)
perror("json object");
exit(1);
}
- jsonw_pretty(_jw, true);
+ if (show_pretty)
+ jsonw_pretty(_jw, true);
jsonw_start_array(_jw);
}
}
diff --git a/tc/tc.c b/tc/tc.c
index 63e64fece87d..aba5c101739c 100644
--- a/tc/tc.c
+++ b/tc/tc.c
@@ -42,6 +42,7 @@ int use_iec;
int force;
bool use_names;
int json;
+int pretty;
static char *conf_file;
@@ -484,6 +485,8 @@ int main(int argc, char **argv)
++timestamp_short;
} else if (matches(argv[1], "-json") == 0) {
++json;
+ } else if (matches(argv[1], "-pretty") == 0) {
+ ++pretty;
} else {
fprintf(stderr, "Option \"%s\" is unknown, try \"tc -help\".\n", argv[1]);
return -1;
--
2.15.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH iproute2-next 2/4] man: add documentation for json and pretty flags
2018-02-08 16:26 [PATCH iproute2-next 0/4] JSON (and color) support for iproute Stephen Hemminger
2018-02-08 16:26 ` [PATCH iproute2-next 1/4] json: make pretty printing optional Stephen Hemminger
@ 2018-02-08 16:26 ` Stephen Hemminger
2018-02-08 16:26 ` [PATCH iproute2-next 3/4] json: fix newline at end of array Stephen Hemminger
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Stephen Hemminger @ 2018-02-08 16:26 UTC (permalink / raw)
To: dsahern; +Cc: netdev, Stephen Hemminger
From: Stephen Hemminger <stephen@networkplumber.org>
Add description for -json and -pretty options.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
ip/ip.c | 4 ++--
man/man8/ip.8 | 18 ++++++++++++++----
man/man8/tc.8 | 3 ++-
3 files changed, 18 insertions(+), 7 deletions(-)
diff --git a/ip/ip.c b/ip/ip.c
index a6611292808d..233a9d772492 100644
--- a/ip/ip.c
+++ b/ip/ip.c
@@ -54,12 +54,12 @@ static void usage(void)
" netns | l2tp | fou | macsec | tcp_metrics | token | netconf | ila |\n"
" vrf | sr }\n"
" OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n"
-" -h[uman-readable] | -iec |\n"
+" -h[uman-readable] | -iec | -j[son] | -p[retty] |\n"
" -f[amily] { inet | inet6 | ipx | dnet | mpls | bridge | link } |\n"
" -4 | -6 | -I | -D | -B | -0 |\n"
" -l[oops] { maximum-addr-flush-attempts } | -br[ief] |\n"
" -o[neline] | -t[imestamp] | -ts[hort] | -b[atch] [filename] |\n"
-" -rc[vbuf] [size] | -n[etns] name | -a[ll] | -c[olor]}\n");
+" -rc[vbuf] [size] | -n[etns] name | -a[ll] | -c[olor]}\n");
exit(-1);
}
diff --git a/man/man8/ip.8 b/man/man8/ip.8
index 7f26582db795..0087d18b7470 100644
--- a/man/man8/ip.8
+++ b/man/man8/ip.8
@@ -48,9 +48,10 @@ ip \- show / manipulate routing, network devices, interfaces and tunnels
\fB\-ts\fR[\fIhort\fR] |
\fB\-n\fR[\fIetns\fR] name |
\fB\-a\fR[\fIll\fR] |
-\fB\-c\fR[\fIolor\fR]
-\fB\-br\fR[\fIief\fR] }
-
+\fB\-c\fR[\fIolor\fR] |
+\fB\-br\fR[\fIief\fR] |
+\fB\-j\fR[son\fR] |
+\fB\-p\fR[retty\fR] }
.SH OPTIONS
@@ -208,10 +209,19 @@ Set the netlink socket receive buffer size, defaults to 1MB.
print human readable rates in IEC units (e.g. 1Ki = 1024).
.TP
-.BR "\-br" , "\-brief"
+.BR "\-br" , " \-brief"
Print only basic information in a tabular format for better readability. This option is currently only supported by
.BR "ip addr show " and " ip link show " commands.
+.TP
+.BR "\-j", " \-json"
+Output results in JavaScript Object Notation (JSON).
+
+.TP
+.BR "\-p", " \-pretty"
+The default JSON format is compact and more efficient to parse but hard for most users to read.
+This flag adds indentation for readability.
+
.SH IP - COMMAND SYNTAX
.SS
diff --git a/man/man8/tc.8 b/man/man8/tc.8
index 5ffea373d18b..a58f46542340 100644
--- a/man/man8/tc.8
+++ b/man/man8/tc.8
@@ -670,7 +670,8 @@ output raw hex values for handles.
.TP
.BR "\-p", " \-pretty"
-decode filter offset and mask values to equivalent filter commands based on TCP/IP.
+for u32 filter, decode offset and mask values to equivalent filter commands based on TCP/IP.
+In JSON output, add whitespace to improve readability.
.TP
.BR "\-iec"
--
2.15.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH iproute2-next 3/4] json: fix newline at end of array
2018-02-08 16:26 [PATCH iproute2-next 0/4] JSON (and color) support for iproute Stephen Hemminger
2018-02-08 16:26 ` [PATCH iproute2-next 1/4] json: make pretty printing optional Stephen Hemminger
2018-02-08 16:26 ` [PATCH iproute2-next 2/4] man: add documentation for json and pretty flags Stephen Hemminger
@ 2018-02-08 16:26 ` Stephen Hemminger
2018-02-08 16:26 ` [PATCH iproute2-next 4/4] iproute: implement JSON and color output Stephen Hemminger
2018-02-10 16:25 ` [PATCH iproute2-next 0/4] JSON (and color) support for iproute David Ahern
4 siblings, 0 replies; 6+ messages in thread
From: Stephen Hemminger @ 2018-02-08 16:26 UTC (permalink / raw)
To: dsahern; +Cc: netdev, Stephen Hemminger
From: Stephen Hemminger <stephen@networkplumber.org>
The json print library was toggling pretty print at the end of
an array to workaround a bug in underlying json_writer.
Instead, just fix json_writer to pretty print array correctly.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
lib/json_print.c | 2 --
lib/json_writer.c | 5 +++++
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/lib/json_print.c b/lib/json_print.c
index e3da1bdfd5b0..b507b14ba27f 100644
--- a/lib/json_print.c
+++ b/lib/json_print.c
@@ -89,9 +89,7 @@ void open_json_array(enum output_type type, const char *str)
void close_json_array(enum output_type type, const char *str)
{
if (_IS_JSON_CONTEXT(type)) {
- jsonw_pretty(_jw, false);
jsonw_end_array(_jw);
- jsonw_pretty(_jw, true);
} else if (_IS_FP_CONTEXT(type)) {
printf("%s", str);
}
diff --git a/lib/json_writer.c b/lib/json_writer.c
index f3eeaf7bc479..0d910dc068b5 100644
--- a/lib/json_writer.c
+++ b/lib/json_writer.c
@@ -180,10 +180,15 @@ void jsonw_end_object(json_writer_t *self)
void jsonw_start_array(json_writer_t *self)
{
jsonw_begin(self, '[');
+ if (self->pretty)
+ putc(' ', self->out);
}
void jsonw_end_array(json_writer_t *self)
{
+ if (self->pretty && self->sep)
+ putc(' ', self->out);
+ self->sep = '\0';
jsonw_end(self, ']');
}
--
2.15.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH iproute2-next 4/4] iproute: implement JSON and color output
2018-02-08 16:26 [PATCH iproute2-next 0/4] JSON (and color) support for iproute Stephen Hemminger
` (2 preceding siblings ...)
2018-02-08 16:26 ` [PATCH iproute2-next 3/4] json: fix newline at end of array Stephen Hemminger
@ 2018-02-08 16:26 ` Stephen Hemminger
2018-02-10 16:25 ` [PATCH iproute2-next 0/4] JSON (and color) support for iproute David Ahern
4 siblings, 0 replies; 6+ messages in thread
From: Stephen Hemminger @ 2018-02-08 16:26 UTC (permalink / raw)
To: dsahern; +Cc: netdev, Stephen Hemminger
From: Stephen Hemminger <stephen@networkplumber.org>
Add JSON and color output formatting to ip route command.
Similar to existing address and link output.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
include/utils.h | 5 +
ip/iproute.c | 376 +++++++++++++++++++++++++++++++++++---------------
ip/iproute_lwtunnel.c | 129 ++++++++++-------
3 files changed, 348 insertions(+), 162 deletions(-)
diff --git a/include/utils.h b/include/utils.h
index 8b8ee2e55ab8..4dc514d66ad1 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -23,6 +23,7 @@ extern int resolve_hosts;
extern int oneline;
extern int brief;
extern int json;
+extern int pretty;
extern int timestamp;
extern int timestamp_short;
extern const char * _SL_;
@@ -155,6 +156,10 @@ int af_byte_len(int af);
const char *format_host_r(int af, int len, const void *addr,
char *buf, int buflen);
+#define format_host_rta_r(af, rta, buf, buflen) \
+ format_host_r(af, RTA_PAYLOAD(rta), RTA_DATA(rta), \
+ buf, buflen)
+
const char *format_host(int af, int lne, const void *addr);
#define format_host_rta(af, rta) \
format_host(af, RTA_PAYLOAD(rta), RTA_DATA(rta))
diff --git a/ip/iproute.c b/ip/iproute.c
index 3c56240f1291..e4809a4383d9 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -339,72 +339,95 @@ static void print_rtax_features(FILE *fp, unsigned int features)
unsigned int of = features;
if (features & RTAX_FEATURE_ECN) {
- fprintf(fp, "ecn ");
+ print_null(PRINT_ANY, "ecn", "ecn ", NULL);
features &= ~RTAX_FEATURE_ECN;
}
if (features)
- fprintf(fp, "0x%x ", of);
+ print_0xhex(PRINT_ANY,
+ "features", "0x%x ", of);
}
static void print_rt_flags(FILE *fp, unsigned int flags)
{
+ open_json_array(PRINT_JSON,
+ is_json_context() ? "flags" : "");
+
if (flags & RTNH_F_DEAD)
- fprintf(fp, "dead ");
+ print_string(PRINT_ANY, NULL, "%s ", "dead");
if (flags & RTNH_F_ONLINK)
- fprintf(fp, "onlink ");
+ print_string(PRINT_ANY, NULL, "%s ", "onlink");
if (flags & RTNH_F_PERVASIVE)
- fprintf(fp, "pervasive ");
+ print_string(PRINT_ANY, NULL, "%s ", "pervasive");
if (flags & RTNH_F_OFFLOAD)
- fprintf(fp, "offload ");
+ print_string(PRINT_ANY, NULL, "%s ", "offload");
+ if (flags & RTM_F_NOTIFY)
+ print_string(PRINT_ANY, NULL, "%s ", "notify");
if (flags & RTNH_F_LINKDOWN)
- fprintf(fp, "linkdown ");
+ print_string(PRINT_ANY, NULL, "%s ", "linkdown");
if (flags & RTNH_F_UNRESOLVED)
- fprintf(fp, "unresolved ");
+ print_string(PRINT_ANY, NULL, "%s ", "unresolved");
+
+ close_json_array(PRINT_JSON, NULL);
}
static void print_rt_pref(FILE *fp, unsigned int pref)
{
- fprintf(fp, "pref ");
switch (pref) {
case ICMPV6_ROUTER_PREF_LOW:
- fprintf(fp, "low");
+ print_string(PRINT_ANY,
+ "pref", "pref %s", "low");
break;
case ICMPV6_ROUTER_PREF_MEDIUM:
- fprintf(fp, "medium");
+ print_string(PRINT_ANY,
+ "pref", "pref %s", "medium");
break;
case ICMPV6_ROUTER_PREF_HIGH:
- fprintf(fp, "high");
+ print_string(PRINT_ANY,
+ "pref", "pref %s", "high");
break;
default:
- fprintf(fp, "%u", pref);
+ print_uint(PRINT_ANY,
+ "pref", "%u", pref);
}
}
static void print_rta_if(FILE *fp, const struct rtattr *rta,
- const char *prefix)
+ const char *prefix)
{
const char *ifname = ll_index_to_name(rta_getattr_u32(rta));
- fprintf(fp, "%s %s ", prefix, ifname);
+ if (is_json_context())
+ print_string(PRINT_JSON, prefix, NULL, ifname);
+ else {
+ fprintf(fp, "%s ", prefix);
+ color_fprintf(fp, COLOR_IFNAME, "%s ", ifname);
+ }
}
static void print_cache_flags(FILE *fp, __u32 flags)
{
+ json_writer_t *jw = get_json_writer();
flags &= ~0xFFFF;
- fprintf(fp, "%s cache ", _SL_);
-
- if (flags == 0)
- return;
-
- putc('<', fp);
+ if (jw) {
+ jsonw_name(jw, "cache");
+ jsonw_start_array(jw);
+ } else {
+ fprintf(fp, "%s cache ", _SL_);
+ if (flags == 0)
+ return;
+ putc('<', fp);
+ }
#define PRTFL(fl, flname) \
if (flags & RTCF_##fl) { \
flags &= ~RTCF_##fl; \
- fprintf(fp, "%s%s", flname, flags ? "," : "> "); \
+ if (jw) \
+ jsonw_string(jw, flname); \
+ else \
+ fprintf(fp, "%s%s", flname, flags ? "," : "> "); \
}
PRTFL(LOCAL, "local");
@@ -424,7 +447,12 @@ static void print_cache_flags(FILE *fp, __u32 flags)
#undef PRTFL
if (flags)
- fprintf(fp, "%#x> ", flags);
+ print_hex(PRINT_ANY, "flags", "%x>", flags);
+
+ if (jw) {
+ jsonw_end_array(jw);
+ jsonw_destroy(&jw);
+ }
}
static void print_rta_cacheinfo(FILE *fp, const struct rta_cacheinfo *ci)
@@ -433,23 +461,34 @@ static void print_rta_cacheinfo(FILE *fp, const struct rta_cacheinfo *ci)
if (!hz)
hz = get_user_hz();
+
if (ci->rta_expires != 0)
- fprintf(fp, "expires %dsec ", ci->rta_expires/hz);
+ print_uint(PRINT_ANY, "expires",
+ "expires %usec ", ci->rta_expires/hz);
if (ci->rta_error != 0)
- fprintf(fp, "error %d ", ci->rta_error);
+ print_uint(PRINT_ANY, "error",
+ "error %u ", ci->rta_error);
+
if (show_stats) {
if (ci->rta_clntref)
- fprintf(fp, "users %d ", ci->rta_clntref);
+ print_uint(PRINT_ANY, "users",
+ "users %u ", ci->rta_clntref);
if (ci->rta_used != 0)
- fprintf(fp, "used %d ", ci->rta_used);
+ print_uint(PRINT_ANY, "used",
+ "used %u ", ci->rta_used);
if (ci->rta_lastuse != 0)
- fprintf(fp, "age %dsec ", ci->rta_lastuse/hz);
+ print_uint(PRINT_ANY, "age",
+ "age %usec ", ci->rta_lastuse/hz);
}
if (ci->rta_id)
- fprintf(fp, "ipid 0x%04x ", ci->rta_id);
- if (ci->rta_ts || ci->rta_tsage)
- fprintf(fp, "ts 0x%x tsage %dsec ",
- ci->rta_ts, ci->rta_tsage);
+ print_0xhex(PRINT_ANY, "ipid",
+ "ipid 0x%04x ", ci->rta_id);
+ if (ci->rta_ts || ci->rta_tsage) {
+ print_0xhex(PRINT_ANY, "ts",
+ "ts 0x%x", ci->rta_ts);
+ print_uint(PRINT_ANY, "tsage",
+ "tsage %usec ", ci->rta_tsage);
+ }
}
static void print_rta_flow(FILE *fp, const struct rtattr *rta)
@@ -459,13 +498,24 @@ static void print_rta_flow(FILE *fp, const struct rtattr *rta)
SPRINT_BUF(b1);
to &= 0xFFFF;
- fprintf(fp, "realm%s ", from ? "s" : "");
- if (from) {
- fprintf(fp, "%s/",
- rtnl_rtrealm_n2a(from, b1, sizeof(b1)));
+ if (is_json_context()) {
+ open_json_object("flow");
+
+ if (from)
+ print_string(PRINT_JSON, "from", NULL,
+ rtnl_rtrealm_n2a(from, b1, sizeof(b1)));
+ print_string(PRINT_JSON, "to", NULL,
+ rtnl_rtrealm_n2a(to, b1, sizeof(b1)));
+ close_json_object();
+ } else {
+ fprintf(fp, "realm%s ", from ? "s" : "");
+
+ if (from)
+ print_string(PRINT_FP, NULL, "%s/",
+ rtnl_rtrealm_n2a(from, b1, sizeof(b1)));
+ print_string(PRINT_FP, NULL, "%s ",
+ rtnl_rtrealm_n2a(to, b1, sizeof(b1)));
}
- fprintf(fp, "%s ",
- rtnl_rtrealm_n2a(to, b1, sizeof(b1)));
}
static void print_rta_newdst(FILE *fp, const struct rtmsg *r,
@@ -473,7 +523,14 @@ static void print_rta_newdst(FILE *fp, const struct rtmsg *r,
{
const char *newdst = format_host_rta(r->rtm_family, rta);
- fprintf(fp, "as to %s ", newdst);
+ if (is_json_context())
+ print_string(PRINT_JSON, "to", NULL, newdst);
+ else {
+ fprintf(fp, "as to ");
+ print_color_string(PRINT_FP,
+ ifa_family_color(r->rtm_family),
+ NULL, "%s ", newdst);
+ }
}
static void print_rta_gateway(FILE *fp, const struct rtmsg *r,
@@ -481,17 +538,38 @@ static void print_rta_gateway(FILE *fp, const struct rtmsg *r,
{
const char *gateway = format_host_rta(r->rtm_family, rta);
- fprintf(fp, "via %s ", gateway);
+ if (is_json_context())
+ print_string(PRINT_JSON, "gateway", NULL, gateway);
+ else {
+ fprintf(fp, "via ");
+ print_color_string(PRINT_FP,
+ ifa_family_color(r->rtm_family),
+ NULL, "%s ", gateway);
+ }
}
static void print_rta_via(FILE *fp, const struct rtattr *rta)
{
+ size_t len = RTA_PAYLOAD(rta) - 2;
const struct rtvia *via = RTA_DATA(rta);
- size_t len = RTA_PAYLOAD(rta);
- fprintf(fp, "via %s %s ",
- family_name(via->rtvia_family),
- format_host(via->rtvia_family, len, via->rtvia_addr));
+ if (is_json_context()) {
+ open_json_object("via");
+ print_string(PRINT_JSON, "family", NULL,
+ family_name(via->rtvia_family));
+ print_string(PRINT_JSON, "host", NULL,
+ format_host(via->rtvia_family, len,
+ via->rtvia_addr));
+ close_json_object();
+ } else {
+ print_string(PRINT_FP, NULL, "via %s ",
+ family_name(via->rtvia_family));
+ print_color_string(PRINT_FP,
+ ifa_family_color(via->rtvia_family),
+ NULL, "%s ",
+ format_host(via->rtvia_family,
+ len, via->rtvia_addr));
+ }
}
static void print_rta_metrics(FILE *fp, const struct rtattr *rta)
@@ -500,6 +578,8 @@ static void print_rta_metrics(FILE *fp, const struct rtattr *rta)
unsigned int mxlock = 0;
int i;
+ open_json_array(PRINT_JSON, "metrics");
+
parse_rtattr(mxrta, RTAX_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta));
if (mxrta[RTAX_LOCK])
@@ -517,13 +597,15 @@ static void print_rta_metrics(FILE *fp, const struct rtattr *rta)
if (i == RTAX_HOPLIMIT && (int)val == -1)
continue;
- if (i < sizeof(mx_names)/sizeof(char *) && mx_names[i])
- fprintf(fp, "%s ", mx_names[i]);
- else
- fprintf(fp, "metric %d ", i);
+ if (!is_json_context()) {
+ if (i < sizeof(mx_names)/sizeof(char *) && mx_names[i])
+ fprintf(fp, "%s ", mx_names[i]);
+ else
+ fprintf(fp, "metric %d ", i);
- if (mxlock & (1<<i))
- fprintf(fp, "lock ");
+ if (mxlock & (1<<i))
+ fprintf(fp, "lock ");
+ }
switch (i) {
case RTAX_FEATURES:
@@ -541,16 +623,24 @@ static void print_rta_metrics(FILE *fp, const struct rtattr *rta)
else if (i == RTAX_RTTVAR)
val /= 4;
- if (val >= 1000)
- fprintf(fp, "%gs ", val/1e3);
- else
- fprintf(fp, "%ums ", val);
+ if (is_json_context())
+ print_uint(PRINT_JSON, mx_names[i],
+ NULL, val);
+ else {
+ if (val >= 1000)
+ fprintf(fp, "%gs ", val/1e3);
+ else
+ fprintf(fp, "%ums ", val);
+ }
break;
case RTAX_CC_ALGO:
- fprintf(fp, "%s ", rta_getattr_str(mxrta[i]));
+ print_string(PRINT_ANY, "congestion",
+ "%s ", rta_getattr_str(mxrta[i]));
break;
}
}
+
+ close_json_array(PRINT_JSON, NULL);
}
static void print_rta_multipath(FILE *fp, const struct rtmsg *r,
@@ -566,16 +656,18 @@ static void print_rta_multipath(FILE *fp, const struct rtmsg *r,
if (nh->rtnh_len > len)
break;
- if ((r->rtm_flags & RTM_F_CLONED) &&
- r->rtm_type == RTN_MULTICAST) {
- if (first) {
- fprintf(fp, "Oifs: ");
- first = 0;
- } else {
- fprintf(fp, " ");
- }
- } else
- fprintf(fp, "%s\tnexthop ", _SL_);
+ if (!is_json_context()) {
+ if ((r->rtm_flags & RTM_F_CLONED) &&
+ r->rtm_type == RTN_MULTICAST) {
+ if (first) {
+ fprintf(fp, "Oifs: ");
+ first = 0;
+ } else {
+ fprintf(fp, " ");
+ }
+ } else
+ fprintf(fp, "%s\tnexthop ", _SL_);
+ }
if (nh->rtnh_len > sizeof(*nh)) {
parse_rtattr(tb, RTA_MAX, RTNH_DATA(nh),
@@ -602,8 +694,7 @@ static void print_rta_multipath(FILE *fp, const struct rtmsg *r,
fprintf(fp, "(ttl>%d)", nh->rtnh_hops);
fprintf(fp, " ");
} else {
- fprintf(fp, "dev %s ",
- ll_index_to_name(nh->rtnh_ifindex));
+ fprintf(fp, "dev %s ", ll_index_to_name(nh->rtnh_ifindex));
if (r->rtm_family != AF_MPLS)
fprintf(fp, "weight %d ",
nh->rtnh_hops+1);
@@ -622,7 +713,7 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
struct rtmsg *r = NLMSG_DATA(n);
int len = n->nlmsg_len;
struct rtattr *tb[RTA_MAX+1];
- int host_len, family;
+ int family, color, host_len;
__u32 table;
int ret;
@@ -668,39 +759,56 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
return 0;
}
+ open_json_object(NULL);
if (n->nlmsg_type == RTM_DELROUTE)
- fprintf(fp, "Deleted ");
+ print_bool(PRINT_ANY, "deleted", "Deleted ", true);
+
if ((r->rtm_type != RTN_UNICAST || show_details > 0) &&
(!filter.typemask || (filter.typemask & (1 << r->rtm_type))))
- fprintf(fp, "%s ", rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1)));
+ print_string(PRINT_ANY, NULL, "%s ",
+ rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1)));
+ color = COLOR_NONE;
if (tb[RTA_DST]) {
family = get_real_family(r->rtm_type, r->rtm_family);
+ color = ifa_family_color(family);
+
if (r->rtm_dst_len != host_len) {
- fprintf(fp, "%s/%u ",
- rt_addr_n2a_rta(family, tb[RTA_DST]),
- r->rtm_dst_len);
+ snprintf(b1, sizeof(b1),
+ "%s/%u", rt_addr_n2a_rta(family, tb[RTA_DST]),
+ r->rtm_dst_len);
} else {
- fprintf(fp, "%s ",
- format_host_rta(family, tb[RTA_DST]));
+ format_host_rta_r(family, tb[RTA_DST],
+ b1, sizeof(b1));
+
}
} else if (r->rtm_dst_len) {
- fprintf(fp, "0/%d ", r->rtm_dst_len);
+ snprintf(b1, sizeof(b1), "0/%d ", r->rtm_dst_len);
} else {
- fprintf(fp, "default ");
+ strncpy(b1, "default", sizeof(b1));
}
+ print_color_string(PRINT_ANY, color,
+ "dst", "%s ", b1);
+
if (tb[RTA_SRC]) {
family = get_real_family(r->rtm_type, r->rtm_family);
+ color = ifa_family_color(family);
+
if (r->rtm_src_len != host_len) {
- fprintf(fp, "from %s/%u ",
- rt_addr_n2a_rta(family, tb[RTA_SRC]),
- r->rtm_src_len);
+ snprintf(b1, sizeof(b1),
+ "%s/%u",
+ rt_addr_n2a_rta(family, tb[RTA_SRC]),
+ r->rtm_src_len);
} else {
- fprintf(fp, "from %s ",
- format_host_rta(family, tb[RTA_SRC]));
+ format_host_rta_r(family, tb[RTA_SRC],
+ b1, sizeof(b1));
}
+ print_color_string(PRINT_ANY, color,
+ "from", "from %s ", b1);
} else if (r->rtm_src_len) {
- fprintf(fp, "from 0/%u ", r->rtm_src_len);
+ snprintf(b1, sizeof(b1), "0/%u", r->rtm_src_len);
+
+ print_string(PRINT_ANY, "src", "from %s ", b1);
}
if (tb[RTA_NEWDST])
@@ -710,8 +818,8 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
lwt_print_encap(fp, tb[RTA_ENCAP_TYPE], tb[RTA_ENCAP]);
if (r->rtm_tos && filter.tosmask != -1) {
- SPRINT_BUF(b1);
- fprintf(fp, "tos %s ", rtnl_dsfield_n2a(r->rtm_tos, b1, sizeof(b1)));
+ print_string(PRINT_ANY, "tos", "tos %s ",
+ rtnl_dsfield_n2a(r->rtm_tos, b1, sizeof(b1)));
}
if (tb[RTA_GATEWAY] && filter.rvia.bitlen != host_len)
@@ -721,25 +829,50 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
print_rta_via(fp, tb[RTA_VIA]);
if (tb[RTA_OIF] && filter.oifmask != -1)
- print_rta_if(fp, tb[RTA_OIF], "dev");
+ print_rta_if(fp, tb[RTA_OIF], "dev");
if (table && (table != RT_TABLE_MAIN || show_details > 0) && !filter.tb)
- fprintf(fp, "table %s ", rtnl_rttable_n2a(table, b1, sizeof(b1)));
+ print_string(PRINT_ANY,
+ "table", "table %s ",
+ rtnl_rttable_n2a(table, b1, sizeof(b1)));
+
if (!(r->rtm_flags & RTM_F_CLONED)) {
- if ((r->rtm_protocol != RTPROT_BOOT || show_details > 0) && filter.protocolmask != -1)
- fprintf(fp, "proto %s ", rtnl_rtprot_n2a(r->rtm_protocol, b1, sizeof(b1)));
- if ((r->rtm_scope != RT_SCOPE_UNIVERSE || show_details > 0) && filter.scopemask != -1)
- fprintf(fp, "scope %s ", rtnl_rtscope_n2a(r->rtm_scope, b1, sizeof(b1)));
+ if ((r->rtm_protocol != RTPROT_BOOT || show_details > 0) &&
+ filter.protocolmask != -1)
+ print_string(PRINT_ANY,
+ "protocol", "proto %s ",
+ rtnl_rtprot_n2a(r->rtm_protocol,
+ b1, sizeof(b1)));
+
+ if ((r->rtm_scope != RT_SCOPE_UNIVERSE || show_details > 0) &&
+ filter.scopemask != -1)
+ print_string(PRINT_ANY,
+ "scope", "scope %s ",
+ rtnl_rtscope_n2a(r->rtm_scope,
+ b1, sizeof(b1)));
}
+
if (tb[RTA_PREFSRC] && filter.rprefsrc.bitlen != host_len) {
+ const char *psrc
+ = rt_addr_n2a_rta(r->rtm_family, tb[RTA_PREFSRC]);
+
/* Do not use format_host(). It is our local addr
and symbolic name will not be useful.
- */
- fprintf(fp, "src %s ",
- rt_addr_n2a_rta(r->rtm_family, tb[RTA_PREFSRC]));
+ */
+ if (is_json_context())
+ print_string(PRINT_JSON, "prefsrc", NULL, psrc);
+ else {
+ fprintf(fp, "src ");
+ print_color_string(PRINT_FP,
+ ifa_family_color(r->rtm_family),
+ NULL, "%s ", psrc);
+ }
+
}
+
if (tb[RTA_PRIORITY] && filter.metricmask != -1)
- fprintf(fp, "metric %u ", rta_getattr_u32(tb[RTA_PRIORITY]));
+ print_uint(PRINT_ANY, "metric", "metric %u ",
+ rta_getattr_u32(tb[RTA_PRIORITY]));
print_rt_flags(fp, r->rtm_flags);
@@ -747,10 +880,14 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
unsigned int mark = rta_getattr_u32(tb[RTA_MARK]);
if (mark) {
- if (mark >= 16)
- fprintf(fp, "mark 0x%x ", mark);
+ if (is_json_context())
+ print_uint(PRINT_JSON, "mark", NULL, mark);
+ else if (mark >= 16)
+ print_0xhex(PRINT_FP, NULL,
+ "mark 0x%x ", mark);
else
- fprintf(fp, "mark %u ", mark);
+ print_uint(PRINT_FP, NULL,
+ "mark %u ", mark);
}
}
@@ -758,20 +895,21 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
print_rta_flow(fp, tb[RTA_FLOW]);
if (tb[RTA_UID])
- fprintf(fp, "uid %u ", rta_getattr_u32(tb[RTA_UID]));
-
- if ((r->rtm_flags & RTM_F_CLONED) && r->rtm_family == AF_INET) {
- print_cache_flags(fp, r->rtm_flags);
+ print_uint(PRINT_ANY, "uid", "uid %u ",
+ rta_getattr_u32(tb[RTA_UID]));
- if (tb[RTA_CACHEINFO])
- print_rta_cacheinfo(fp, RTA_DATA(tb[RTA_CACHEINFO]));
+ if (r->rtm_family == AF_INET) {
+ if (r->rtm_flags & RTM_F_CLONED) {
+ print_cache_flags(fp, r->rtm_flags);
+ if (tb[RTA_CACHEINFO])
+ print_rta_cacheinfo(fp, RTA_DATA(tb[RTA_CACHEINFO]));
+ }
} else if (r->rtm_family == AF_INET6) {
- if (r->rtm_flags & RTM_F_CLONED)
- fprintf(fp, "%s cache ", _SL_);
-
- if (tb[RTA_CACHEINFO])
- print_rta_cacheinfo(fp, RTA_DATA(tb[RTA_CACHEINFO]));
+ if (r->rtm_flags & RTM_F_CLONED) {
+ if (tb[RTA_CACHEINFO])
+ print_rta_cacheinfo(fp, RTA_DATA(tb[RTA_CACHEINFO]));
+ }
}
if (tb[RTA_METRICS])
@@ -787,13 +925,19 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
print_rt_pref(fp, rta_getattr_u8(tb[RTA_PREF]));
if (tb[RTA_TTL_PROPAGATE]) {
- fprintf(fp, "ttl-propagate ");
- if (rta_getattr_u8(tb[RTA_TTL_PROPAGATE]))
- fprintf(fp, "enabled");
+ bool propogate = rta_getattr_u8(tb[RTA_TTL_PROPAGATE]);
+
+ if (is_json_context())
+ print_bool(PRINT_JSON, "ttl-propogate", NULL,
+ propogate);
else
- fprintf(fp, "disabled");
+ print_string(PRINT_FP, NULL,
+ "ttl-propogate %s",
+ propogate ? "enabled" : "disabled");
}
- fprintf(fp, "\n");
+
+ print_string(PRINT_FP, NULL, "\n", NULL);
+ close_json_object();
fflush(fp);
return 0;
}
@@ -1756,11 +1900,15 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
}
}
+ new_json_obj(json);
+
if (rtnl_dump_filter(&rth, filter_fn, stdout) < 0) {
fprintf(stderr, "Dump terminated\n");
return -2;
}
+ delete_json_obj();
+ fflush(stdout);
return 0;
}
diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c
index f7fbc6287932..fa3feaea7436 100644
--- a/ip/iproute_lwtunnel.c
+++ b/ip/iproute_lwtunnel.c
@@ -94,20 +94,28 @@ static void print_srh(FILE *fp, struct ipv6_sr_hdr *srh)
{
int i;
- fprintf(fp, "segs %d [ ", srh->first_segment + 1);
+ if (is_json_context())
+ open_json_array(PRINT_JSON, "segs");
+ else
+ fprintf(fp, "segs %d [ ", srh->first_segment + 1);
for (i = srh->first_segment; i >= 0; i--)
- fprintf(fp, "%s ",
- rt_addr_n2a(AF_INET6, 16, &srh->segments[i]));
+ print_color_string(PRINT_ANY, COLOR_INET6,
+ NULL, "%s ",
+ rt_addr_n2a(AF_INET6, 16, &srh->segments[i]));
- fprintf(fp, "] ");
+ if (is_json_context())
+ close_json_array(PRINT_JSON, NULL);
+ else
+ fprintf(fp, "] ");
if (sr_has_hmac(srh)) {
unsigned int offset = ((srh->hdrlen + 1) << 3) - 40;
struct sr6_tlv_hmac *tlv;
tlv = (struct sr6_tlv_hmac *)((char *)srh + offset);
- fprintf(fp, "hmac 0x%X ", ntohl(tlv->hmackeyid));
+ print_0xhex(PRINT_ANY, "hmac",
+ "hmac 0x%X ", ntohl(tlv->hmackeyid));
}
}
@@ -148,7 +156,8 @@ static void print_encap_seg6(FILE *fp, struct rtattr *encap)
return;
tuninfo = RTA_DATA(tb[SEG6_IPTUNNEL_SRH]);
- fprintf(fp, "mode %s ", format_seg6mode_type(tuninfo->mode));
+ print_string(PRINT_ANY, "mode",
+ "mode %s ", format_seg6mode_type(tuninfo->mode));
print_srh(fp, tuninfo->srh);
}
@@ -205,36 +214,41 @@ static void print_encap_seg6local(FILE *fp, struct rtattr *encap)
action = rta_getattr_u32(tb[SEG6_LOCAL_ACTION]);
- fprintf(fp, "action %s ", format_action_type(action));
+ print_string(PRINT_ANY, "action",
+ "action %s ", format_action_type(action));
if (tb[SEG6_LOCAL_SRH]) {
- fprintf(fp, "srh ");
+ open_json_object("srh");
print_srh(fp, RTA_DATA(tb[SEG6_LOCAL_SRH]));
+ close_json_object();
}
if (tb[SEG6_LOCAL_TABLE])
- fprintf(fp, "table %u ", rta_getattr_u32(tb[SEG6_LOCAL_TABLE]));
+ print_uint(PRINT_ANY, "table",
+ "table %u ", rta_getattr_u32(tb[SEG6_LOCAL_TABLE]));
if (tb[SEG6_LOCAL_NH4]) {
- fprintf(fp, "nh4 %s ",
- rt_addr_n2a_rta(AF_INET, tb[SEG6_LOCAL_NH4]));
+ print_string(PRINT_ANY, "nh4",
+ "nh4 %s ", rt_addr_n2a_rta(AF_INET, tb[SEG6_LOCAL_NH4]));
}
if (tb[SEG6_LOCAL_NH6]) {
- fprintf(fp, "nh6 %s ",
- rt_addr_n2a_rta(AF_INET6, tb[SEG6_LOCAL_NH6]));
+ print_string(PRINT_ANY, "nh6",
+ "nh6 %s ", rt_addr_n2a_rta(AF_INET6, tb[SEG6_LOCAL_NH6]));
}
if (tb[SEG6_LOCAL_IIF]) {
int iif = rta_getattr_u32(tb[SEG6_LOCAL_IIF]);
- fprintf(fp, "iif %s ", ll_index_to_name(iif));
+ print_string(PRINT_ANY, "iif",
+ "iif %s ", ll_index_to_name(iif));
}
if (tb[SEG6_LOCAL_OIF]) {
int oif = rta_getattr_u32(tb[SEG6_LOCAL_OIF]);
- fprintf(fp, "oif %s ", ll_index_to_name(oif));
+ print_string(PRINT_ANY, "oif",
+ "oif %s ", ll_index_to_name(oif));
}
}
@@ -245,10 +259,10 @@ static void print_encap_mpls(FILE *fp, struct rtattr *encap)
parse_rtattr_nested(tb, MPLS_IPTUNNEL_MAX, encap);
if (tb[MPLS_IPTUNNEL_DST])
- fprintf(fp, " %s ",
+ print_string(PRINT_ANY, "dst", " %s ",
format_host_rta(AF_MPLS, tb[MPLS_IPTUNNEL_DST]));
if (tb[MPLS_IPTUNNEL_TTL])
- fprintf(fp, "ttl %u ",
+ print_uint(PRINT_ANY, "ttl", "ttl %u ",
rta_getattr_u8(tb[MPLS_IPTUNNEL_TTL]));
}
@@ -259,22 +273,26 @@ static void print_encap_ip(FILE *fp, struct rtattr *encap)
parse_rtattr_nested(tb, LWTUNNEL_IP_MAX, encap);
if (tb[LWTUNNEL_IP_ID])
- fprintf(fp, "id %llu ",
- ntohll(rta_getattr_u64(tb[LWTUNNEL_IP_ID])));
+ print_uint(PRINT_ANY, "id", "id %llu ",
+ ntohll(rta_getattr_u64(tb[LWTUNNEL_IP_ID])));
if (tb[LWTUNNEL_IP_SRC])
- fprintf(fp, "src %s ",
- rt_addr_n2a_rta(AF_INET, tb[LWTUNNEL_IP_SRC]));
+ print_color_string(PRINT_ANY, COLOR_INET,
+ "src", "src %s ",
+ rt_addr_n2a_rta(AF_INET, tb[LWTUNNEL_IP_SRC]));
if (tb[LWTUNNEL_IP_DST])
- fprintf(fp, "dst %s ",
- rt_addr_n2a_rta(AF_INET, tb[LWTUNNEL_IP_DST]));
+ print_color_string(PRINT_ANY, COLOR_INET,
+ "dst", "dst %s ",
+ rt_addr_n2a_rta(AF_INET, tb[LWTUNNEL_IP_DST]));
if (tb[LWTUNNEL_IP_TTL])
- fprintf(fp, "ttl %u ", rta_getattr_u8(tb[LWTUNNEL_IP_TTL]));
+ print_uint(PRINT_ANY, "ttl",
+ "ttl %u ", rta_getattr_u8(tb[LWTUNNEL_IP_TTL]));
if (tb[LWTUNNEL_IP_TOS])
- fprintf(fp, "tos %d ", rta_getattr_u8(tb[LWTUNNEL_IP_TOS]));
+ print_uint(PRINT_ANY, "tos",
+ "tos %d ", rta_getattr_u8(tb[LWTUNNEL_IP_TOS]));
}
static void print_encap_ila(FILE *fp, struct rtattr *encap)
@@ -288,23 +306,24 @@ static void print_encap_ila(FILE *fp, struct rtattr *encap)
addr64_n2a(rta_getattr_u64(tb[ILA_ATTR_LOCATOR]),
abuf, sizeof(abuf));
- fprintf(fp, " %s ", abuf);
+ print_string(PRINT_ANY, "locator",
+ " %s ", abuf);
}
if (tb[ILA_ATTR_CSUM_MODE])
- fprintf(fp, " csum-mode %s ",
- ila_csum_mode2name(rta_getattr_u8(
- tb[ILA_ATTR_CSUM_MODE])));
+ print_string(PRINT_ANY, "csum_mode",
+ " csum-mode %s ",
+ ila_csum_mode2name(rta_getattr_u8(tb[ILA_ATTR_CSUM_MODE])));
if (tb[ILA_ATTR_IDENT_TYPE])
- fprintf(fp, " ident-type %s ",
- ila_ident_type2name(rta_getattr_u8(
- tb[ILA_ATTR_IDENT_TYPE])));
+ print_string(PRINT_ANY, "ident_type",
+ " ident-type %s ",
+ ila_ident_type2name(rta_getattr_u8(tb[ILA_ATTR_IDENT_TYPE])));
if (tb[ILA_ATTR_HOOK_TYPE])
- fprintf(fp, " hook-type %s ",
- ila_hook_type2name(rta_getattr_u8(
- tb[ILA_ATTR_HOOK_TYPE])));
+ print_string(PRINT_ANY, "hook_type",
+ " hook-type %s ",
+ ila_hook_type2name(rta_getattr_u8(tb[ILA_ATTR_HOOK_TYPE])));
}
static void print_encap_ip6(FILE *fp, struct rtattr *encap)
@@ -314,35 +333,48 @@ static void print_encap_ip6(FILE *fp, struct rtattr *encap)
parse_rtattr_nested(tb, LWTUNNEL_IP6_MAX, encap);
if (tb[LWTUNNEL_IP6_ID])
- fprintf(fp, "id %llu ",
- ntohll(rta_getattr_u64(tb[LWTUNNEL_IP6_ID])));
+ print_uint(PRINT_ANY, "id", "id %llu ",
+ ntohll(rta_getattr_u64(tb[LWTUNNEL_IP6_ID])));
if (tb[LWTUNNEL_IP6_SRC])
- fprintf(fp, "src %s ",
- rt_addr_n2a_rta(AF_INET6, tb[LWTUNNEL_IP6_SRC]));
+ print_color_string(PRINT_ANY, COLOR_INET6,
+ "src", "src %s ",
+ rt_addr_n2a_rta(AF_INET6, tb[LWTUNNEL_IP6_SRC]));
if (tb[LWTUNNEL_IP6_DST])
- fprintf(fp, "dst %s ",
- rt_addr_n2a_rta(AF_INET6, tb[LWTUNNEL_IP6_DST]));
+ print_color_string(PRINT_ANY, COLOR_INET6,
+ "dst", "dst %s ",
+ rt_addr_n2a_rta(AF_INET6, tb[LWTUNNEL_IP6_DST]));
if (tb[LWTUNNEL_IP6_HOPLIMIT])
- fprintf(fp, "hoplimit %u ",
- rta_getattr_u8(tb[LWTUNNEL_IP6_HOPLIMIT]));
+ print_uint(PRINT_ANY, "hoplimit",
+ "hoplimit %u ",
+ rta_getattr_u8(tb[LWTUNNEL_IP6_HOPLIMIT]));
if (tb[LWTUNNEL_IP6_TC])
- fprintf(fp, "tc %d ", rta_getattr_u8(tb[LWTUNNEL_IP6_TC]));
+ print_uint(PRINT_ANY, "tc",
+ "tc %u ", rta_getattr_u8(tb[LWTUNNEL_IP6_TC]));
}
static void print_encap_bpf_prog(FILE *fp, struct rtattr *encap,
const char *str)
{
struct rtattr *tb[LWT_BPF_PROG_MAX+1];
+ const char *progname = NULL;
parse_rtattr_nested(tb, LWT_BPF_PROG_MAX, encap);
- fprintf(fp, "%s ", str);
if (tb[LWT_BPF_PROG_NAME])
- fprintf(fp, "%s ", rta_getattr_str(tb[LWT_BPF_PROG_NAME]));
+ progname = rta_getattr_str(tb[LWT_BPF_PROG_NAME]);
+
+ if (is_json_context())
+ print_string(PRINT_JSON, str, NULL,
+ progname ? : "<unknown>");
+ else {
+ fprintf(fp, "%s ", str);
+ if (progname)
+ fprintf(fp, "%s ", progname);
+ }
}
static void print_encap_bpf(FILE *fp, struct rtattr *encap)
@@ -358,7 +390,8 @@ static void print_encap_bpf(FILE *fp, struct rtattr *encap)
if (tb[LWT_BPF_XMIT])
print_encap_bpf_prog(fp, tb[LWT_BPF_XMIT], "xmit");
if (tb[LWT_BPF_XMIT_HEADROOM])
- fprintf(fp, "%d ", rta_getattr_u32(tb[LWT_BPF_XMIT_HEADROOM]));
+ print_uint(PRINT_ANY, "headroom",
+ " %u ", rta_getattr_u32(tb[LWT_BPF_XMIT_HEADROOM]));
}
void lwt_print_encap(FILE *fp, struct rtattr *encap_type,
@@ -371,7 +404,7 @@ void lwt_print_encap(FILE *fp, struct rtattr *encap_type,
et = rta_getattr_u16(encap_type);
- fprintf(fp, " encap %s ", format_encap_type(et));
+ print_string(PRINT_ANY, "encap", " encap %s ", format_encap_type(et));
switch (et) {
case LWTUNNEL_ENCAP_MPLS:
--
2.15.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH iproute2-next 0/4] JSON (and color) support for iproute
2018-02-08 16:26 [PATCH iproute2-next 0/4] JSON (and color) support for iproute Stephen Hemminger
` (3 preceding siblings ...)
2018-02-08 16:26 ` [PATCH iproute2-next 4/4] iproute: implement JSON and color output Stephen Hemminger
@ 2018-02-10 16:25 ` David Ahern
4 siblings, 0 replies; 6+ messages in thread
From: David Ahern @ 2018-02-10 16:25 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev
On 2/8/18 9:26 AM, Stephen Hemminger wrote:
> From: Stephen Hemminger <stephen@networkplumber.org>
>
> This set of patches adds JSON output to route printing.
> Tested for the simple cases, but there are many variations and there
> such as lw tunnels which have not be tested.
>
> The color formatting may need some additional tweaks. It looks
> like for some tags the tag is also showing up in color.
> This should be fixed in print_color_string rather than having
> to do special case handling in so many places.
>
> This patchset also changes the default JSON output to be compressed
> (since the purpose of JSON is to make output machine readable);
> but do optional pretty print formatting with -p flag.
Looks good. Series applied to iproute2-next.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2018-02-10 16:25 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-02-08 16:26 [PATCH iproute2-next 0/4] JSON (and color) support for iproute Stephen Hemminger
2018-02-08 16:26 ` [PATCH iproute2-next 1/4] json: make pretty printing optional Stephen Hemminger
2018-02-08 16:26 ` [PATCH iproute2-next 2/4] man: add documentation for json and pretty flags Stephen Hemminger
2018-02-08 16:26 ` [PATCH iproute2-next 3/4] json: fix newline at end of array Stephen Hemminger
2018-02-08 16:26 ` [PATCH iproute2-next 4/4] iproute: implement JSON and color output Stephen Hemminger
2018-02-10 16:25 ` [PATCH iproute2-next 0/4] JSON (and color) support for iproute David Ahern
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).