From: Stephen Hemminger <sthem...@microsoft.com> Add JSON (and limited color) to ip neighbor table parameter output.
Signed-off-by: Stephen Hemminger <step...@networkplumber.org> --- ip/ipntable.c | 415 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 226 insertions(+), 189 deletions(-) diff --git a/ip/ipntable.c b/ip/ipntable.c index 2f72c989f35d..f6dff28ecbb2 100644 --- a/ip/ipntable.c +++ b/ip/ipntable.c @@ -31,6 +31,7 @@ #include "utils.h" #include "ip_common.h" +#include "json_print.h" static struct { @@ -338,274 +339,308 @@ static const char *ntable_strtime_delta(__u32 msec) return str; } -static int print_ntable(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) +static void print_ndtconfig(const struct ndt_config *ndtc) { - FILE *fp = (FILE *)arg; - struct ndtmsg *ndtm = NLMSG_DATA(n); - int len = n->nlmsg_len; - struct rtattr *tb[NDTA_MAX+1]; - struct rtattr *tpb[NDTPA_MAX+1]; - int ret; - if (n->nlmsg_type != RTM_NEWNEIGHTBL) { - fprintf(stderr, "Not NEIGHTBL: %08x %08x %08x\n", - n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); - return 0; - } - len -= NLMSG_LENGTH(sizeof(*ndtm)); - if (len < 0) { - fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); - return -1; - } + print_uint(PRINT_ANY, "key_length", + " config key_len %u ", ndtc->ndtc_key_len); + print_uint(PRINT_ANY, "entry_size", + "entry_size %u ", ndtc->ndtc_entry_size); + print_uint(PRINT_ANY, "entries", + "entries %u ", ndtc->ndtc_entries); - if (preferred_family && preferred_family != ndtm->ndtm_family) - return 0; + print_string(PRINT_FP, NULL, "%s", _SL_); - parse_rtattr(tb, NDTA_MAX, NDTA_RTA(ndtm), - n->nlmsg_len - NLMSG_LENGTH(sizeof(*ndtm))); + print_string(PRINT_ANY, "last_flush", + " last_flush %s ", + ntable_strtime_delta(ndtc->ndtc_last_flush)); + print_string(PRINT_ANY, "last_rand", + "last_rand %s ", + ntable_strtime_delta(ndtc->ndtc_last_rand)); - if (tb[NDTA_NAME]) { - const char *name = rta_getattr_str(tb[NDTA_NAME]); + print_string(PRINT_FP, NULL, "%s", _SL_); - if (filter.name && strcmp(filter.name, name)) - return 0; - } - if (tb[NDTA_PARMS]) { - parse_rtattr(tpb, NDTPA_MAX, RTA_DATA(tb[NDTA_PARMS]), - RTA_PAYLOAD(tb[NDTA_PARMS])); + print_uint(PRINT_ANY, "hash_rnd", + " hash_rnd %u ", ndtc->ndtc_hash_rnd); + print_0xhex(PRINT_ANY, "hash_mask", + "hash_mask %08x ", ndtc->ndtc_hash_mask); - if (tpb[NDTPA_IFINDEX]) { - __u32 ifindex = rta_getattr_u32(tpb[NDTPA_IFINDEX]); + print_uint(PRINT_ANY, "hash_chain_gc", + "hash_chain_gc %u ", ndtc->ndtc_hash_chain_gc); + print_uint(PRINT_ANY, "proxy_qlen", + "proxy_qlen %u ", ndtc->ndtc_proxy_qlen); - if (filter.index && filter.index != ifindex) - return 0; - } else { - if (filter.index && filter.index != NONE_DEV) - return 0; - } + print_string(PRINT_FP, NULL, "%s", _SL_); +} + +static void print_ndtparams(struct rtattr *tpb[]) +{ + + if (tpb[NDTPA_IFINDEX]) { + __u32 ifindex = rta_getattr_u32(tpb[NDTPA_IFINDEX]); + + print_string(PRINT_FP, NULL, " dev ", NULL); + print_color_string(PRINT_ANY, COLOR_IFNAME, + "dev", "%s ", ll_index_to_name(ifindex)); + print_string(PRINT_FP, NULL, "%s", _SL_); } - if (ndtm->ndtm_family == AF_INET) - fprintf(fp, "inet "); - else if (ndtm->ndtm_family == AF_INET6) - fprintf(fp, "inet6 "); - else if (ndtm->ndtm_family == AF_DECnet) - fprintf(fp, "dnet "); - else - fprintf(fp, "(%d) ", ndtm->ndtm_family); + print_string(PRINT_FP, NULL, " ", NULL); + if (tpb[NDTPA_REFCNT]) { + __u32 refcnt = rta_getattr_u32(tpb[NDTPA_REFCNT]); - if (tb[NDTA_NAME]) { - const char *name = rta_getattr_str(tb[NDTA_NAME]); + print_uint(PRINT_ANY, "refcnt", "refcnt %u ", refcnt); + } - fprintf(fp, "%s ", name); + if (tpb[NDTPA_REACHABLE_TIME]) { + __u64 reachable = rta_getattr_u64(tpb[NDTPA_REACHABLE_TIME]); + + print_uint(PRINT_ANY, "reachable", + "reachable %llu ", reachable); } - fprintf(fp, "%s", _SL_); + if (tpb[NDTPA_BASE_REACHABLE_TIME]) { + __u64 breachable + = rta_getattr_u64(tpb[NDTPA_BASE_REACHABLE_TIME]); - ret = (tb[NDTA_THRESH1] || tb[NDTA_THRESH2] || tb[NDTA_THRESH3] || - tb[NDTA_GC_INTERVAL]); - if (ret) - fprintf(fp, " "); - if (tb[NDTA_THRESH1]) { - __u32 thresh1 = rta_getattr_u32(tb[NDTA_THRESH1]); + print_uint(PRINT_ANY, "base_reachable", + "base_reachable %llu ", breachable); + } - fprintf(fp, "thresh1 %u ", thresh1); + if (tpb[NDTPA_RETRANS_TIME]) { + __u64 retrans = rta_getattr_u64(tpb[NDTPA_RETRANS_TIME]); + + print_uint(PRINT_ANY, "retrans", "retrans %llu ", retrans); } - if (tb[NDTA_THRESH2]) { - __u32 thresh2 = rta_getattr_u32(tb[NDTA_THRESH2]); - fprintf(fp, "thresh2 %u ", thresh2); + print_string(PRINT_FP, NULL, "%s ", _SL_); + + if (tpb[NDTPA_GC_STALETIME]) { + __u64 gc_stale + = rta_getattr_u64(tpb[NDTPA_GC_STALETIME]); + + print_uint(PRINT_ANY, "gc_stale", "gc_stale %llu ", gc_stale); } - if (tb[NDTA_THRESH3]) { - __u32 thresh3 = rta_getattr_u32(tb[NDTA_THRESH3]); - fprintf(fp, "thresh3 %u ", thresh3); + if (tpb[NDTPA_DELAY_PROBE_TIME]) { + __u64 delay_probe + = rta_getattr_u64(tpb[NDTPA_DELAY_PROBE_TIME]); + + print_uint(PRINT_ANY, "delay_probe", + "delay_probe %llu ", delay_probe); } - if (tb[NDTA_GC_INTERVAL]) { - unsigned long long gc_int = rta_getattr_u64(tb[NDTA_GC_INTERVAL]); - fprintf(fp, "gc_int %llu ", gc_int); + if (tpb[NDTPA_QUEUE_LEN]) { + __u32 queue = rta_getattr_u32(tpb[NDTPA_QUEUE_LEN]); + + print_uint(PRINT_ANY, "queue", "queue %u ", queue); } - if (ret) - fprintf(fp, "%s", _SL_); + print_string(PRINT_FP, NULL, "%s ", _SL_); - if (tb[NDTA_CONFIG] && show_stats) { - struct ndt_config *ndtc = RTA_DATA(tb[NDTA_CONFIG]); + if (tpb[NDTPA_APP_PROBES]) { + __u32 aprobe = rta_getattr_u32(tpb[NDTPA_APP_PROBES]); - fprintf(fp, " "); - fprintf(fp, "config "); + print_uint(PRINT_ANY, "app_probes", + "app_probes %u ", aprobe); + } - fprintf(fp, "key_len %u ", ndtc->ndtc_key_len); - fprintf(fp, "entry_size %u ", ndtc->ndtc_entry_size); - fprintf(fp, "entries %u ", ndtc->ndtc_entries); + if (tpb[NDTPA_UCAST_PROBES]) { + __u32 uprobe = rta_getattr_u32(tpb[NDTPA_UCAST_PROBES]); - fprintf(fp, "%s", _SL_); - fprintf(fp, " "); + print_uint(PRINT_ANY, "ucast_probes", + "ucast_probes %u ", uprobe); + } - fprintf(fp, "last_flush %s ", - ntable_strtime_delta(ndtc->ndtc_last_flush)); - fprintf(fp, "last_rand %s ", - ntable_strtime_delta(ndtc->ndtc_last_rand)); + if (tpb[NDTPA_MCAST_PROBES]) { + __u32 mprobe = rta_getattr_u32(tpb[NDTPA_MCAST_PROBES]); - fprintf(fp, "%s", _SL_); - fprintf(fp, " "); + print_uint(PRINT_ANY, "mcast_probes", + "mcast_probes %u ", mprobe); + } - fprintf(fp, "hash_rnd %u ", ndtc->ndtc_hash_rnd); - fprintf(fp, "hash_mask %08x ", ndtc->ndtc_hash_mask); + print_string(PRINT_FP, NULL, "%s ", _SL_); - fprintf(fp, "hash_chain_gc %u ", ndtc->ndtc_hash_chain_gc); - fprintf(fp, "proxy_qlen %u ", ndtc->ndtc_proxy_qlen); + if (tpb[NDTPA_ANYCAST_DELAY]) { + __u64 anycast_delay = rta_getattr_u64(tpb[NDTPA_ANYCAST_DELAY]); - fprintf(fp, "%s", _SL_); + print_uint(PRINT_ANY, "anycast_delay", + "anycast_delay %llu ", anycast_delay); } - if (tb[NDTA_PARMS]) { - if (tpb[NDTPA_IFINDEX]) { - __u32 ifindex = rta_getattr_u32(tpb[NDTPA_IFINDEX]); + if (tpb[NDTPA_PROXY_DELAY]) { + __u64 proxy_delay = rta_getattr_u64(tpb[NDTPA_PROXY_DELAY]); - fprintf(fp, " "); - fprintf(fp, "dev %s ", ll_index_to_name(ifindex)); - fprintf(fp, "%s", _SL_); - } + print_uint(PRINT_ANY, "proxy_delay", + "proxy_delay %llu ", proxy_delay); + } - fprintf(fp, " "); + if (tpb[NDTPA_PROXY_QLEN]) { + __u32 pqueue = rta_getattr_u32(tpb[NDTPA_PROXY_QLEN]); - if (tpb[NDTPA_REFCNT]) { - __u32 refcnt = rta_getattr_u32(tpb[NDTPA_REFCNT]); + print_uint(PRINT_ANY, "proxy_queue", "proxy_queue %u ", pqueue); + } - fprintf(fp, "refcnt %u ", refcnt); - } - if (tpb[NDTPA_REACHABLE_TIME]) { - unsigned long long reachable = rta_getattr_u64(tpb[NDTPA_REACHABLE_TIME]); + if (tpb[NDTPA_LOCKTIME]) { + __u64 locktime = rta_getattr_u64(tpb[NDTPA_LOCKTIME]); - fprintf(fp, "reachable %llu ", reachable); - } - if (tpb[NDTPA_BASE_REACHABLE_TIME]) { - unsigned long long breachable = rta_getattr_u64(tpb[NDTPA_BASE_REACHABLE_TIME]); + print_uint(PRINT_ANY, "locktime", + "locktime %llu ", locktime); + } - fprintf(fp, "base_reachable %llu ", breachable); - } - if (tpb[NDTPA_RETRANS_TIME]) { - unsigned long long retrans = rta_getattr_u64(tpb[NDTPA_RETRANS_TIME]); + print_string(PRINT_FP, NULL, "%s", _SL_); +} - fprintf(fp, "retrans %llu ", retrans); - } +static void print_ndtstats(const struct ndt_stats *ndts) +{ - fprintf(fp, "%s", _SL_); + print_string(PRINT_FP, NULL, " stats ", NULL); - fprintf(fp, " "); + print_uint(PRINT_ANY, "allocs", "allocs %llu ", + ndts->ndts_allocs); + print_uint(PRINT_ANY, "destroys", "destroys %llu ", + ndts->ndts_destroys); + print_uint(PRINT_ANY, "hash_grows", "hash_grows %llu ", + ndts->ndts_hash_grows); - if (tpb[NDTPA_GC_STALETIME]) { - unsigned long long gc_stale = rta_getattr_u64(tpb[NDTPA_GC_STALETIME]); + print_string(PRINT_FP, NULL, "%s ", _SL_); - fprintf(fp, "gc_stale %llu ", gc_stale); - } - if (tpb[NDTPA_DELAY_PROBE_TIME]) { - unsigned long long delay_probe = rta_getattr_u64(tpb[NDTPA_DELAY_PROBE_TIME]); + print_uint(PRINT_ANY, "res_failed", "res_failed %llu ", + ndts->ndts_res_failed); + print_uint(PRINT_ANY, "lookups", "lookups %llu ", + ndts->ndts_lookups); + print_uint(PRINT_ANY, "hits", "hits %llu ", + ndts->ndts_hits); - fprintf(fp, "delay_probe %llu ", delay_probe); - } - if (tpb[NDTPA_QUEUE_LEN]) { - __u32 queue = rta_getattr_u32(tpb[NDTPA_QUEUE_LEN]); + print_string(PRINT_FP, NULL, "%s ", _SL_); - fprintf(fp, "queue %u ", queue); - } + print_uint(PRINT_ANY, "rcv_probes_mcast", "rcv_probes_mcast %llu ", + ndts->ndts_rcv_probes_mcast); + print_uint(PRINT_ANY, "rcv_probes_ucast", "rcv_probes_ucast %llu ", + ndts->ndts_rcv_probes_ucast); - fprintf(fp, "%s", _SL_); + print_string(PRINT_FP, NULL, "%s ", _SL_); - fprintf(fp, " "); + print_uint(PRINT_ANY, "periodic_gc_runs", "periodic_gc_runs %llu ", + ndts->ndts_periodic_gc_runs); + print_uint(PRINT_ANY, "forced_gc_runs", "forced_gc_runs %llu ", + ndts->ndts_forced_gc_runs); - if (tpb[NDTPA_APP_PROBES]) { - __u32 aprobe = rta_getattr_u32(tpb[NDTPA_APP_PROBES]); + print_string(PRINT_FP, NULL, "%s", _SL_); +} - fprintf(fp, "app_probes %u ", aprobe); - } - if (tpb[NDTPA_UCAST_PROBES]) { - __u32 uprobe = rta_getattr_u32(tpb[NDTPA_UCAST_PROBES]); +static int print_ntable(const struct sockaddr_nl *who, + struct nlmsghdr *n, void *arg) +{ + FILE *fp = (FILE *)arg; + struct ndtmsg *ndtm = NLMSG_DATA(n); + int len = n->nlmsg_len; + struct rtattr *tb[NDTA_MAX+1]; + struct rtattr *tpb[NDTPA_MAX+1]; + int ret; - fprintf(fp, "ucast_probes %u ", uprobe); - } - if (tpb[NDTPA_MCAST_PROBES]) { - __u32 mprobe = rta_getattr_u32(tpb[NDTPA_MCAST_PROBES]); + if (n->nlmsg_type != RTM_NEWNEIGHTBL) { + fprintf(stderr, "Not NEIGHTBL: %08x %08x %08x\n", + n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); + return 0; + } + len -= NLMSG_LENGTH(sizeof(*ndtm)); + if (len < 0) { + fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); + return -1; + } - fprintf(fp, "mcast_probes %u ", mprobe); - } + if (preferred_family && preferred_family != ndtm->ndtm_family) + return 0; - fprintf(fp, "%s", _SL_); + parse_rtattr(tb, NDTA_MAX, NDTA_RTA(ndtm), + n->nlmsg_len - NLMSG_LENGTH(sizeof(*ndtm))); - fprintf(fp, " "); + if (tb[NDTA_NAME]) { + const char *name = rta_getattr_str(tb[NDTA_NAME]); - if (tpb[NDTPA_ANYCAST_DELAY]) { - unsigned long long anycast_delay = rta_getattr_u64(tpb[NDTPA_ANYCAST_DELAY]); + if (filter.name && strcmp(filter.name, name)) + return 0; + } - fprintf(fp, "anycast_delay %llu ", anycast_delay); - } - if (tpb[NDTPA_PROXY_DELAY]) { - unsigned long long proxy_delay = rta_getattr_u64(tpb[NDTPA_PROXY_DELAY]); + if (tb[NDTA_PARMS]) { + parse_rtattr(tpb, NDTPA_MAX, RTA_DATA(tb[NDTA_PARMS]), + RTA_PAYLOAD(tb[NDTA_PARMS])); - fprintf(fp, "proxy_delay %llu ", proxy_delay); - } - if (tpb[NDTPA_PROXY_QLEN]) { - __u32 pqueue = rta_getattr_u32(tpb[NDTPA_PROXY_QLEN]); + if (tpb[NDTPA_IFINDEX]) { + __u32 ifindex = rta_getattr_u32(tpb[NDTPA_IFINDEX]); - fprintf(fp, "proxy_queue %u ", pqueue); + if (filter.index && filter.index != ifindex) + return 0; + } else { + if (filter.index && filter.index != NONE_DEV) + return 0; } - if (tpb[NDTPA_LOCKTIME]) { - unsigned long long locktime = rta_getattr_u64(tpb[NDTPA_LOCKTIME]); + } - fprintf(fp, "locktime %llu ", locktime); - } + open_json_object(NULL); + print_string(PRINT_ANY, "family", + "%s ", family_name(ndtm->ndtm_family)); + + if (tb[NDTA_NAME]) { + const char *name = rta_getattr_str(tb[NDTA_NAME]); - fprintf(fp, "%s", _SL_); + print_string(PRINT_ANY, "name", + "%s ", name); } - if (tb[NDTA_STATS] && show_stats) { - struct ndt_stats *ndts = RTA_DATA(tb[NDTA_STATS]); + print_string(PRINT_FP, NULL, "%s", _SL_); - fprintf(fp, " "); - fprintf(fp, "stats "); + ret = (tb[NDTA_THRESH1] || tb[NDTA_THRESH2] || tb[NDTA_THRESH3] || + tb[NDTA_GC_INTERVAL]); + if (ret) + print_string(PRINT_FP, NULL, " ", NULL); - fprintf(fp, "allocs %llu ", - (unsigned long long) ndts->ndts_allocs); - fprintf(fp, "destroys %llu ", - (unsigned long long) ndts->ndts_destroys); - fprintf(fp, "hash_grows %llu ", - (unsigned long long) ndts->ndts_hash_grows); + if (tb[NDTA_THRESH1]) { + __u32 thresh1 = rta_getattr_u32(tb[NDTA_THRESH1]); - fprintf(fp, "%s", _SL_); - fprintf(fp, " "); + print_uint(PRINT_ANY, "thresh1", + "thresh1 %u ", thresh1); + } - fprintf(fp, "res_failed %llu ", - (unsigned long long) ndts->ndts_res_failed); - fprintf(fp, "lookups %llu ", - (unsigned long long) ndts->ndts_lookups); - fprintf(fp, "hits %llu ", - (unsigned long long) ndts->ndts_hits); + if (tb[NDTA_THRESH2]) { + __u32 thresh2 = rta_getattr_u32(tb[NDTA_THRESH2]); - fprintf(fp, "%s", _SL_); - fprintf(fp, " "); + print_uint(PRINT_ANY, "thresh2", + "thresh2 %u ", thresh2); + } - fprintf(fp, "rcv_probes_mcast %llu ", - (unsigned long long) ndts->ndts_rcv_probes_mcast); - fprintf(fp, "rcv_probes_ucast %llu ", - (unsigned long long) ndts->ndts_rcv_probes_ucast); + if (tb[NDTA_THRESH3]) { + __u32 thresh3 = rta_getattr_u32(tb[NDTA_THRESH3]); - fprintf(fp, "%s", _SL_); - fprintf(fp, " "); + print_uint(PRINT_ANY, "thresh3", + "thresh3 %u ", thresh3); + } - fprintf(fp, "periodic_gc_runs %llu ", - (unsigned long long) ndts->ndts_periodic_gc_runs); - fprintf(fp, "forced_gc_runs %llu ", - (unsigned long long) ndts->ndts_forced_gc_runs); + if (tb[NDTA_GC_INTERVAL]) { + __u64 gc_int = rta_getattr_u64(tb[NDTA_GC_INTERVAL]); - fprintf(fp, "%s", _SL_); + print_uint(PRINT_ANY, "gc_interval", + "gc_int %llu ", gc_int); } - fprintf(fp, "\n"); + if (ret) + print_string(PRINT_FP, NULL, "%s", _SL_); + if (tb[NDTA_CONFIG] && show_stats) + print_ndtconfig(RTA_DATA(tb[NDTA_CONFIG])); + + if (tb[NDTA_PARMS]) + print_ndtparams(tpb); + + if (tb[NDTA_STATS] && show_stats) + print_ndtstats(RTA_DATA(tb[NDTA_STATS])); + + print_string(PRINT_FP, NULL, "\n", ""); + close_json_object(); fflush(fp); + return 0; } @@ -643,10 +678,12 @@ static int ipntable_show(int argc, char **argv) exit(1); } + new_json_obj(json); if (rtnl_dump_filter(&rth, print_ntable, stdout) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } + delete_json_obj(); return 0; } -- 2.16.1