From 0f1475c268271164eba92989b8418e26af021dae Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 8 Mar 2018 18:02:18 -0800 Subject: [PATCH] ipmroute: convert to output JSON Should be no change for non-json case except putting color on address if desired. Signed-off-by: Stephen Hemminger Signed-off-by: David Ahern --- ip/ipmroute.c | 99 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 67 insertions(+), 32 deletions(-) diff --git a/ip/ipmroute.c b/ip/ipmroute.c index 5c232e8a..03087b6c 100644 --- a/ip/ipmroute.c +++ b/ip/ipmroute.c @@ -29,6 +29,7 @@ #include #include "utils.h" #include "ip_common.h" +#include "json_print.h" static void usage(void) __attribute__((noreturn)); @@ -53,13 +54,12 @@ struct rtfilter { int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { - FILE *fp = (FILE *)arg; struct rtmsg *r = NLMSG_DATA(n); int len = n->nlmsg_len; struct rtattr *tb[RTA_MAX+1]; - char obuf[256]; - + const char *src, *dst; SPRINT_BUF(b1); + SPRINT_BUF(b2); __u32 table; int iif = 0; int family; @@ -103,30 +103,44 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) family = get_real_family(r->rtm_type, r->rtm_family); + open_json_object(NULL); if (n->nlmsg_type == RTM_DELROUTE) - fprintf(fp, "Deleted "); + print_bool(PRINT_ANY, "deleted", "Deleted ", true); if (tb[RTA_SRC]) - len = snprintf(obuf, sizeof(obuf), - "(%s, ", rt_addr_n2a_rta(family, tb[RTA_SRC])); + src = rt_addr_n2a_r(family, RTA_PAYLOAD(tb[RTA_SRC]), + RTA_DATA(tb[RTA_SRC]), b1, sizeof(b1)); else - len = sprintf(obuf, "(unknown, "); + src = "unknown"; + if (tb[RTA_DST]) - snprintf(obuf + len, sizeof(obuf) - len, - "%s)", rt_addr_n2a_rta(family, tb[RTA_DST])); + dst = rt_addr_n2a_r(family, RTA_PAYLOAD(tb[RTA_DST]), + RTA_DATA(tb[RTA_DST]), b2, sizeof(b2)); else - snprintf(obuf + len, sizeof(obuf) - len, "unknown) "); + dst = "unknown"; + + if (is_json_context()) { + print_string(PRINT_JSON, "src", NULL, src); + print_string(PRINT_JSON, "dst", NULL, dst); + } else { + char obuf[256]; + + snprintf(obuf, sizeof(obuf), "(%s,%s)", src, dst); + print_string(PRINT_FP, NULL, + "%-32s Iif: ", obuf); + } - fprintf(fp, "%-32s Iif: ", obuf); if (iif) - fprintf(fp, "%-10s ", ll_index_to_name(iif)); + print_color_string(PRINT_ANY, COLOR_IFNAME, + "iif", "%-10s ", ll_index_to_name(iif)); else - fprintf(fp, "unresolved "); + print_string(PRINT_ANY,"iif", "%s ", "unresolved"); if (tb[RTA_MULTIPATH]) { struct rtnexthop *nh = RTA_DATA(tb[RTA_MULTIPATH]); int first = 1; + open_json_array(PRINT_JSON, "multipath"); len = RTA_PAYLOAD(tb[RTA_MULTIPATH]); for (;;) { @@ -135,47 +149,65 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) if (nh->rtnh_len > len) break; + open_json_object(NULL); if (first) { - fprintf(fp, "Oifs: "); + print_string(PRINT_FP, NULL, "Oifs: ", NULL); first = 0; } - fprintf(fp, "%s", ll_index_to_name(nh->rtnh_ifindex)); + + print_color_string(PRINT_ANY, COLOR_IFNAME, + "oif", "%s", ll_index_to_name(nh->rtnh_ifindex)); + if (nh->rtnh_hops > 1) - fprintf(fp, "(ttl %d) ", nh->rtnh_hops); + print_uint(PRINT_ANY, + "ttl", "(ttl %u) ", nh->rtnh_hops); else - fprintf(fp, " "); + print_string(PRINT_FP, NULL, " ", NULL); + + close_json_object(); len -= NLMSG_ALIGN(nh->rtnh_len); nh = RTNH_NEXT(nh); } + close_json_array(PRINT_JSON, NULL); } - fprintf(fp, " State: %s", - r->rtm_flags & RTNH_F_UNRESOLVED ? "unresolved" : "resolved"); + + print_string(PRINT_ANY, "state", " State: %s", + (r->rtm_flags & RTNH_F_UNRESOLVED) ? "unresolved" : "resolved"); + if (r->rtm_flags & RTNH_F_OFFLOAD) - fprintf(fp, " offload"); + print_null(PRINT_ANY, "offload", " offload", NULL); + if (show_stats && tb[RTA_MFC_STATS]) { struct rta_mfc_stats *mfcs = RTA_DATA(tb[RTA_MFC_STATS]); - fprintf(fp, "%s %"PRIu64" packets, %"PRIu64" bytes", _SL_, - (uint64_t)mfcs->mfcs_packets, - (uint64_t)mfcs->mfcs_bytes); + print_string(PRINT_FP, NULL, "%s", _SL_); + print_uint(PRINT_ANY, "packets", " %"PRIu64" packets,", + mfcs->mfcs_packets); + print_uint(PRINT_ANY, "bytes", " %"PRIu64" bytes", mfcs->mfcs_bytes); + if (mfcs->mfcs_wrong_if) - fprintf(fp, ", %"PRIu64" arrived on wrong iif.", - (uint64_t)mfcs->mfcs_wrong_if); + print_uint(PRINT_ANY, "wrong_if", + ", %"PRIu64" arrived on wrong iif.", + mfcs->mfcs_wrong_if); } + if (show_stats && tb[RTA_EXPIRES]) { struct timeval tv; + double age; __jiffies_to_tv(&tv, rta_getattr_u64(tb[RTA_EXPIRES])); - fprintf(fp, ", Age %4i.%.2i", (int)tv.tv_sec, - (int)tv.tv_usec/10000); + age = tv.tv_sec; + age += tv.tv_usec / 1000000.; + print_float(PRINT_ANY, "expires", + ", Age %.2f", age); } 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))); - fprintf(fp, "\n"); - fflush(fp); + print_string(PRINT_FP, NULL, "\n", NULL); + close_json_object(); return 0; } @@ -255,12 +287,15 @@ static int mroute_list(int argc, char **argv) return 1; } + new_json_obj(json); if (rtnl_dump_filter(&rth, print_mroute, stdout) < 0) { + delete_json_obj(); fprintf(stderr, "Dump terminated\n"); exit(1); } + delete_json_obj(); - exit(0); + return 0; } int do_multiroute(int argc, char **argv) -- 2.39.2