Re: [PATCH iproute2-next 3/7] ip: add json support to ip rule

2018-03-06 Thread Stephen Hemminger
On Tue, 6 Mar 2018 09:51:29 -0700
David Ahern  wrote:

> NULL for detached value seems weird.
> [ {
> "priority": 998,
> "src": "all",
> "iif": "dummy2",
> "iif_detached": null,
> "table": "1"
> },
> 
> Is that normal for json for fields that only exist when a value is true?

null is the best way to indicate a value with presence having a meaning.



Re: [PATCH iproute2-next 3/7] ip: add json support to ip rule

2018-03-06 Thread David Ahern
On 3/5/18 8:04 PM, Stephen Hemminger wrote:
> @@ -202,50 +202,66 @@ int print_rule(const struct sockaddr_nl *who, struct 
> nlmsghdr *n, void *arg)
>   if (!filter_nlmsg(n, tb, host_len))
>   return 0;
>  
> + open_json_object(NULL);
>   if (n->nlmsg_type == RTM_DELRULE)
> - fprintf(fp, "Deleted ");
> + print_bool(PRINT_ANY, "deleted", "Deleted ", true);
>  
>   if (tb[FRA_PRIORITY])
> - fprintf(fp, "%u:\t",
> - rta_getattr_u32(tb[FRA_PRIORITY]));
> - else
> - fprintf(fp, "0:\t");
> + prio = rta_getattr_u32(tb[FRA_PRIORITY]);
> +
> + print_uint(PRINT_ANY, "priority",
> +"%u:\t", prio);

This one has a lot of instances where the print_* can be put on one line.


>  
>   if (frh->flags & FIB_RULE_INVERT)
> - fprintf(fp, "not ");
> + print_null(PRINT_ANY, "not", "not ", NULL);
> +
> + if (!is_json_context())
> + fprintf(fp, "from ");
>  
>   if (tb[FRA_SRC]) {
> - if (frh->src_len != host_len) {
> - fprintf(fp, "from %s/%u ",
> - rt_addr_n2a_rta(frh->family, tb[FRA_SRC]),
> - frh->src_len);
> - } else {
> - fprintf(fp, "from %s ",
> - format_host_rta(frh->family, tb[FRA_SRC]));
> - }
> + const char *src
> + = rt_addr_n2a_rta(frh->family, tb[FRA_SRC]);
> +
> + print_color_string(PRINT_ANY,
> +ifa_family_color(frh->family),
> +"src", "%s", src);
> + if (frh->src_len != host_len)
> + print_uint(PRINT_ANY, "srclen",
> +"/%u", frh->src_len);
>   } else if (frh->src_len) {
> - fprintf(fp, "from 0/%d ", frh->src_len);
> + print_string(PRINT_ANY,
> +  "src", "%s", "0");
> + print_uint(PRINT_ANY,
> +"srclen", "/%u", frh->src_len);
>   } else {
> - fprintf(fp, "from all ");
> + print_string(PRINT_ANY,
> +  "src", "%s", "all");
>   }
>  
> + if (!is_json_context())
> + fprintf(fp, " to ");
> +
>   if (tb[FRA_DST]) {
> - if (frh->dst_len != host_len) {
> - fprintf(fp, "to %s/%u ",
> - rt_addr_n2a_rta(frh->family, tb[FRA_DST]),
> - frh->dst_len);
> - } else {
> - fprintf(fp, "to %s ",
> - format_host_rta(frh->family, tb[FRA_DST]));
> - }
> + const char *dst
> + = rt_addr_n2a_rta(frh->family, tb[FRA_DST]);
> +
> + print_color_string(PRINT_ANY,
> +ifa_family_color(frh->family),
> +"dst", "%s", dst);
> + if (frh->dst_len != host_len)
> + print_uint(PRINT_ANY, "dstlen",
> +"/%u ", frh->dst_len);
>   } else if (frh->dst_len) {
> - fprintf(fp, "to 0/%d ", frh->dst_len);
> + print_string(PRINT_ANY,
> +  "dst", "%s", "0");
> + print_uint(PRINT_ANY,
> +"dstlen", "/%u ", frh->dst_len);
>   }
>  
>   if (frh->tos) {
> - SPRINT_BUF(b1);
> - fprintf(fp, "tos %s ",
> - rtnl_dsfield_n2a(frh->tos, b1, sizeof(b1)));
> + print_string(PRINT_ANY, "tos",
> +  "tos %s ",
> +  rtnl_dsfield_n2a(frh->tos, b1, sizeof(b1)));
>   }
>  
>   if (tb[FRA_FWMARK] || tb[FRA_FWMASK]) {
> @@ -255,53 +271,82 @@ int print_rule(const struct sockaddr_nl *who, struct 
> nlmsghdr *n, void *arg)
>   mark = rta_getattr_u32(tb[FRA_FWMARK]);
>  
>   if (tb[FRA_FWMASK] &&
> - (mask = rta_getattr_u32(tb[FRA_FWMASK])) != 0x)
> - fprintf(fp, "fwmark 0x%x/0x%x ", mark, mask);
> - else
> - fprintf(fp, "fwmark 0x%x ", mark);
> + (mask = rta_getattr_u32(tb[FRA_FWMASK])) != 0x) {
> + print_0xhex(PRINT_ANY, "fwmark",
> + "fwmark 0x%x", mark);
> + print_0xhex(PRINT_ANY, "fwmask",
> + "/0x%x ",  mask);
> + } else {
> + print_0xhex(PRINT_ANY, "fwmark",
> + "fwmark 0x%x ", mark);
> + }
>   }
>  
>   if (tb[FRA_IFNAME]) {
> - fprintf(fp, "iif %s ", rta_getattr_str(tb[FRA_IFNAME]));
> + if (!is_json_context())
> + fprintf(fp, "iif 

[PATCH iproute2-next 3/7] ip: add json support to ip rule

2018-03-05 Thread Stephen Hemminger
From: Stephen Hemminger 

More JSON and colorizing.

Signed-off-by: Stephen Hemminger 
---
 ip/iprule.c | 203 ++--
 1 file changed, 130 insertions(+), 73 deletions(-)

diff --git a/ip/iprule.c b/ip/iprule.c
index 6fdc9b5efa00..ab1e0c15f877 100644
--- a/ip/iprule.c
+++ b/ip/iprule.c
@@ -26,6 +26,7 @@
 #include "rt_names.h"
 #include "utils.h"
 #include "ip_common.h"
+#include "json_print.h"
 
 enum list_action {
IPRULE_LIST,
@@ -179,13 +180,12 @@ static bool filter_nlmsg(struct nlmsghdr *n, struct 
rtattr **tb, int host_len)
 
 int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 {
-   FILE *fp = (FILE *)arg;
+   FILE *fp = arg;
struct fib_rule_hdr *frh = NLMSG_DATA(n);
int len = n->nlmsg_len;
int host_len = -1;
-   __u32 table;
+   __u32 table, prio = 0;
struct rtattr *tb[FRA_MAX+1];
-
SPRINT_BUF(b1);
 
if (n->nlmsg_type != RTM_NEWRULE && n->nlmsg_type != RTM_DELRULE)
@@ -202,50 +202,66 @@ int print_rule(const struct sockaddr_nl *who, struct 
nlmsghdr *n, void *arg)
if (!filter_nlmsg(n, tb, host_len))
return 0;
 
+   open_json_object(NULL);
if (n->nlmsg_type == RTM_DELRULE)
-   fprintf(fp, "Deleted ");
+   print_bool(PRINT_ANY, "deleted", "Deleted ", true);
 
if (tb[FRA_PRIORITY])
-   fprintf(fp, "%u:\t",
-   rta_getattr_u32(tb[FRA_PRIORITY]));
-   else
-   fprintf(fp, "0:\t");
+   prio = rta_getattr_u32(tb[FRA_PRIORITY]);
+
+   print_uint(PRINT_ANY, "priority",
+  "%u:\t", prio);
 
if (frh->flags & FIB_RULE_INVERT)
-   fprintf(fp, "not ");
+   print_null(PRINT_ANY, "not", "not ", NULL);
+
+   if (!is_json_context())
+   fprintf(fp, "from ");
 
if (tb[FRA_SRC]) {
-   if (frh->src_len != host_len) {
-   fprintf(fp, "from %s/%u ",
-   rt_addr_n2a_rta(frh->family, tb[FRA_SRC]),
-   frh->src_len);
-   } else {
-   fprintf(fp, "from %s ",
-   format_host_rta(frh->family, tb[FRA_SRC]));
-   }
+   const char *src
+   = rt_addr_n2a_rta(frh->family, tb[FRA_SRC]);
+
+   print_color_string(PRINT_ANY,
+  ifa_family_color(frh->family),
+  "src", "%s", src);
+   if (frh->src_len != host_len)
+   print_uint(PRINT_ANY, "srclen",
+  "/%u", frh->src_len);
} else if (frh->src_len) {
-   fprintf(fp, "from 0/%d ", frh->src_len);
+   print_string(PRINT_ANY,
+"src", "%s", "0");
+   print_uint(PRINT_ANY,
+  "srclen", "/%u", frh->src_len);
} else {
-   fprintf(fp, "from all ");
+   print_string(PRINT_ANY,
+"src", "%s", "all");
}
 
+   if (!is_json_context())
+   fprintf(fp, " to ");
+
if (tb[FRA_DST]) {
-   if (frh->dst_len != host_len) {
-   fprintf(fp, "to %s/%u ",
-   rt_addr_n2a_rta(frh->family, tb[FRA_DST]),
-   frh->dst_len);
-   } else {
-   fprintf(fp, "to %s ",
-   format_host_rta(frh->family, tb[FRA_DST]));
-   }
+   const char *dst
+   = rt_addr_n2a_rta(frh->family, tb[FRA_DST]);
+
+   print_color_string(PRINT_ANY,
+  ifa_family_color(frh->family),
+  "dst", "%s", dst);
+   if (frh->dst_len != host_len)
+   print_uint(PRINT_ANY, "dstlen",
+  "/%u ", frh->dst_len);
} else if (frh->dst_len) {
-   fprintf(fp, "to 0/%d ", frh->dst_len);
+   print_string(PRINT_ANY,
+"dst", "%s", "0");
+   print_uint(PRINT_ANY,
+  "dstlen", "/%u ", frh->dst_len);
}
 
if (frh->tos) {
-   SPRINT_BUF(b1);
-   fprintf(fp, "tos %s ",
-   rtnl_dsfield_n2a(frh->tos, b1, sizeof(b1)));
+   print_string(PRINT_ANY, "tos",
+"tos %s ",
+rtnl_dsfield_n2a(frh->tos, b1, sizeof(b1)));
}
 
if (tb[FRA_FWMARK] || tb[FRA_FWMASK]) {
@@ -255,53 +271,82 @@ int print_rule(const struct sockaddr_nl *who, struct 
nlmsghdr *n, void *arg)
mark =