On 3/5/18 8:04 PM, Stephen Hemminger wrote: > From: Stephen Hemminger <sthem...@microsoft.com> > > Use json_print to provide json (and color) support to > ip neigh command. > > Signed-off-by: Stephen Hemminger <step...@networkplumber.org> > --- > ip/ipneigh.c | 143 > ++++++++++++++++++++++++++++++++++++++++------------------- > 1 file changed, 97 insertions(+), 46 deletions(-) > > diff --git a/ip/ipneigh.c b/ip/ipneigh.c > index 0735424900f6..1f550e98e003 100644 > --- a/ip/ipneigh.c > +++ b/ip/ipneigh.c > @@ -23,6 +23,7 @@ > #include "rt_names.h" > #include "utils.h" > #include "ip_common.h" > +#include "json_print.h" > > #define NUD_VALID > (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE|NUD_PROBE|NUD_STALE|NUD_DELAY) > #define MAX_ROUNDS 10 > @@ -189,6 +190,48 @@ static int ipneigh_modify(int cmd, int flags, int argc, > char **argv) > return 0; > } > > +static void print_cacheinfo(const struct nda_cacheinfo *ci) > +{ > + static int hz; > + > + if (!hz) > + hz = get_user_hz(); > + > + if (ci->ndm_refcnt) > + print_uint(PRINT_ANY, "refcnt", > + " ref %u", ci->ndm_refcnt); > + > + print_uint(PRINT_ANY, > + "used", " used %u", ci->ndm_used / hz); > + print_uint(PRINT_ANY, > + "confirmed", "/%u", ci->ndm_confirmed / hz); > + print_uint(PRINT_ANY, > + "updated", "/u", ci->ndm_updated / hz);
alignment is off in the above and it looks like all of them can be on 1 line and not exceed 80 col. > +} > + > +static void print_neigh_state(unsigned int nud) > +{ > + > + open_json_array(PRINT_JSON, > + is_json_context() ? "state" : ""); > + > +#define PRINT_FLAG(f) \ > + if (nud & NUD_##f) { \ > + nud &= ~NUD_##f; \ > + print_string(PRINT_ANY, NULL, " %s", #f); \ > + } > + > + PRINT_FLAG(INCOMPLETE); > + PRINT_FLAG(REACHABLE); > + PRINT_FLAG(STALE); > + PRINT_FLAG(DELAY); > + PRINT_FLAG(PROBE); > + PRINT_FLAG(FAILED); > + PRINT_FLAG(NOARP); > + PRINT_FLAG(PERMANENT); > +#undef PRINT_FLAG > + close_json_array(PRINT_JSON, NULL); > +} > > int print_neigh(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) > { > @@ -262,65 +305,71 @@ int print_neigh(const struct sockaddr_nl *who, struct > nlmsghdr *n, void *arg) > return 0; > } > > + open_json_object(NULL); > if (n->nlmsg_type == RTM_DELNEIGH) > - fprintf(fp, "Deleted "); > + print_bool(PRINT_ANY, "deleted", "Deleted ", true); > else if (n->nlmsg_type == RTM_GETNEIGH) > - fprintf(fp, "miss "); > + print_null(PRINT_ANY, "miss", "%s ", "miss"); > + > if (tb[NDA_DST]) { > - fprintf(fp, "%s ", > - format_host_rta(r->ndm_family, tb[NDA_DST])); > + const char *dst; > + > + dst = format_host_rta(r->ndm_family, tb[NDA_DST]); > + print_color_string(PRINT_ANY, > + ifa_family_color(r->ndm_family), > + "dst", "%s ", dst); > } > - if (!filter.index && r->ndm_ifindex) > - fprintf(fp, "dev %s ", ll_index_to_name(r->ndm_ifindex)); > + > + if (!filter.index && r->ndm_ifindex) { > + if (!is_json_context()) > + fprintf(fp, "dev "); > + > + print_color_string(PRINT_ANY, COLOR_IFNAME, > + "dev", "%s ", > + ll_index_to_name(r->ndm_ifindex)); > + } > + > if (tb[NDA_LLADDR]) { > + const char *lladdr; > SPRINT_BUF(b1); > - fprintf(fp, "lladdr %s", ll_addr_n2a(RTA_DATA(tb[NDA_LLADDR]), > - RTA_PAYLOAD(tb[NDA_LLADDR]), > - ll_index_to_type(r->ndm_ifindex), > - b1, sizeof(b1))); > - } > - if (r->ndm_flags & NTF_ROUTER) { > - fprintf(fp, " router"); > - } > - if (r->ndm_flags & NTF_PROXY) { > - fprintf(fp, " proxy"); > - } > - if (tb[NDA_CACHEINFO] && show_stats) { > - struct nda_cacheinfo *ci = RTA_DATA(tb[NDA_CACHEINFO]); > - int hz = get_user_hz(); > > - if (ci->ndm_refcnt) > - printf(" ref %d", ci->ndm_refcnt); > - fprintf(fp, " used %d/%d/%d", ci->ndm_used/hz, > - ci->ndm_confirmed/hz, ci->ndm_updated/hz); > - } > + lladdr = ll_addr_n2a(RTA_DATA(tb[NDA_LLADDR]), > + RTA_PAYLOAD(tb[NDA_LLADDR]), > + ll_index_to_type(r->ndm_ifindex), > + b1, sizeof(b1)); > > - if (tb[NDA_PROBES] && show_stats) { > - __u32 p = rta_getattr_u32(tb[NDA_PROBES]); > + if (!is_json_context()) > + fprintf(fp, "lladdr "); > > - fprintf(fp, " probes %u", p); > + print_color_string(PRINT_ANY, COLOR_MAC, > + "lladdr", "%s", lladdr); > } > > - if (r->ndm_state) { > - int nud = r->ndm_state; > - > - fprintf(fp, " "); > - > -#define PRINT_FLAG(f) if (nud & NUD_##f) { \ > - nud &= ~NUD_##f; fprintf(fp, #f "%s", nud ? "," : ""); } > - PRINT_FLAG(INCOMPLETE); > - PRINT_FLAG(REACHABLE); > - PRINT_FLAG(STALE); > - PRINT_FLAG(DELAY); > - PRINT_FLAG(PROBE); > - PRINT_FLAG(FAILED); > - PRINT_FLAG(NOARP); > - PRINT_FLAG(PERMANENT); > -#undef PRINT_FLAG > + if (r->ndm_flags & NTF_ROUTER) > + print_null(PRINT_ANY, "router", " %s", "router"); > + > + if (r->ndm_flags & NTF_PROXY) > + print_null(PRINT_ANY, "proxy", " %s", "proxy"); > + > + if (show_stats) { > + if (tb[NDA_CACHEINFO]) > + print_cacheinfo(RTA_DATA(tb[NDA_CACHEINFO])); > + > + if (tb[NDA_PROBES]) { > + __u32 p = rta_getattr_u32(tb[NDA_PROBES]); > + > + print_uint(PRINT_ANY, "probes", > + " probes %u", p); alignment on the above as well.