From 65d5e933e5162c3464857ee233a2f20e778ee1b6 Mon Sep 17 00:00:00 2001 From: Andrea Claudi Date: Thu, 30 Apr 2020 12:35:47 +0200 Subject: [PATCH] ip: fix ip route show json output for multipath nexthops Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1738633 Upstream Status: iproute2.git commit 4ecefff3cf250 commit 4ecefff3cf250c1e4499dff14c80ed38bec6d7de Author: Julien Fortin Date: Thu Sep 26 17:29:34 2019 +0200 ip: fix ip route show json output for multipath nexthops print_rta_multipath doesn't support JSON output: { "dst":"27.0.0.13", "protocol":"bgp", "metric":20, "flags":[], "gateway":"169.254.0.1"dev uplink-1 weight 1 , "flags":["onlink"], "gateway":"169.254.0.1"dev uplink-2 weight 1 , "flags":["onlink"] }, since RTA_MULTIPATH has nested objects we should print them in a json array. With the path we have the following output: { "flags": [], "dst": "36.0.0.13", "protocol": "bgp", "metric": 20, "nexthops": [ { "weight": 1, "flags": [ "onlink" ], "gateway": "169.254.0.1", "dev": "uplink-1" }, { "weight": 1, "flags": [ "onlink" ], "gateway": "169.254.0.1", "dev": "uplink-2" } ] } Fixes: 663c3cb23103f4 ("iproute: implement JSON and color output") Signed-off-by: Julien Fortin Signed-off-by: David Ahern --- ip/iproute.c | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/ip/iproute.c b/ip/iproute.c index a453385113cb9..32bb52df250c2 100644 --- a/ip/iproute.c +++ b/ip/iproute.c @@ -649,24 +649,26 @@ static void print_rta_multipath(FILE *fp, const struct rtmsg *r, int len = RTA_PAYLOAD(rta); int first = 1; + open_json_array(PRINT_JSON, "nexthops"); + while (len >= sizeof(*nh)) { struct rtattr *tb[RTA_MAX + 1]; if (nh->rtnh_len > len) break; - 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_); - } + open_json_object(NULL); + + if ((r->rtm_flags & RTM_F_CLONED) && + r->rtm_type == RTN_MULTICAST) { + if (first) { + print_string(PRINT_FP, NULL, "Oifs: ", NULL); + first = 0; + } else { + print_string(PRINT_FP, NULL, " ", NULL); + } + } else + print_string(PRINT_FP, NULL, "%s\tnexthop ", _SL_); if (nh->rtnh_len > sizeof(*nh)) { parse_rtattr(tb, RTA_MAX, RTNH_DATA(nh), @@ -689,22 +691,30 @@ static void print_rta_multipath(FILE *fp, const struct rtmsg *r, if ((r->rtm_flags & RTM_F_CLONED) && r->rtm_type == RTN_MULTICAST) { - fprintf(fp, "%s", ll_index_to_name(nh->rtnh_ifindex)); + print_string(PRINT_ANY, "dev", + "%s", ll_index_to_name(nh->rtnh_ifindex)); + if (nh->rtnh_hops != 1) - fprintf(fp, "(ttl>%d)", nh->rtnh_hops); - fprintf(fp, " "); + print_int(PRINT_ANY, "ttl", "(ttl>%d)", nh->rtnh_hops); + + print_string(PRINT_FP, NULL, " ", NULL); } else { - fprintf(fp, "dev %s ", ll_index_to_name(nh->rtnh_ifindex)); + print_string(PRINT_ANY, "dev", + "dev %s ", ll_index_to_name(nh->rtnh_ifindex)); + if (r->rtm_family != AF_MPLS) - fprintf(fp, "weight %d ", - nh->rtnh_hops+1); + print_int(PRINT_ANY, "weight", + "weight %d ", nh->rtnh_hops + 1); } print_rt_flags(fp, nh->rtnh_flags); len -= NLMSG_ALIGN(nh->rtnh_len); nh = RTNH_NEXT(nh); + + close_json_object(); } + close_json_array(PRINT_JSON, NULL); } int print_route(struct nlmsghdr *n, void *arg) -- 2.25.4