From 553c8048460a3c01bf984163a3b5f4ac7122b5a2 Mon Sep 17 00:00:00 2001 From: Pooja Jagadeesh Doijode Date: Tue, 24 Jan 2023 18:15:36 -0800 Subject: [PATCH] zebra: fix JSON fields for "show ip/ipv6 nht" 1. Renamed "gates" to "nexthops" 2. Displaying afi of the nexthops being dispalyed in place of "nexthops" JSON object in the old JSON output 3. Calling show_route_nexthop_helper() and show_nexthop_json_helper() instead of print_nh() inorder to keeps the fields in "nexthops" JSON object in sync with "nexthops" JSON object of "show nexthop-group rib json". Updated vtysh: r1# show ip nht 192.168.0.2 resolved via connected is directly connected, r1-eth0 (vrf default) Client list: static(fd 28) 192.168.0.4 resolved via connected is directly connected, r1-eth0 (vrf default) Client list: static(fd 28) Updated JSON: r1# show ip nht json { "default":{ "ipv4":{ "192.168.0.2":{ "nhtConnected":false, "clientList":[ { "protocol":"static", "socket":28, "protocolFiltered":"none" } ], "nexthops":[ { "flags":3, "fib":true, "directlyConnected":true, "interfaceIndex":2, "interfaceName":"r1-eth0", "vrf":"default", "active":true } ], "resolvedProtocol":"connected" } } } } Signed-off-by: Pooja Jagadeesh Doijode --- .../all_protocol_startup/r1/ip_nht.ref | 24 +- .../all_protocol_startup/r1/ipv6_nht.ref | 8 +- zebra/zebra_rnh.c | 319 +++++++++++++--- zebra/zebra_rnh.h | 6 + zebra/zebra_vty.c | 342 +----------------- 5 files changed, 299 insertions(+), 400 deletions(-) diff --git a/tests/topotests/all_protocol_startup/r1/ip_nht.ref b/tests/topotests/all_protocol_startup/r1/ip_nht.ref index 1da4da4df5..0ef3f4b675 100644 --- a/tests/topotests/all_protocol_startup/r1/ip_nht.ref +++ b/tests/topotests/all_protocol_startup/r1/ip_nht.ref @@ -1,34 +1,34 @@ 1.1.1.1 resolved via static - is directly connected, r1-eth1 + is directly connected, r1-eth1 (vrf default), weight 1 Client list: pbr(fd XX) 1.1.1.2 resolved via static - is directly connected, r1-eth2 + is directly connected, r1-eth2 (vrf default), weight 1 Client list: pbr(fd XX) 1.1.1.3 resolved via static - is directly connected, r1-eth3 + is directly connected, r1-eth3 (vrf default), weight 1 Client list: pbr(fd XX) 1.1.1.4 resolved via static - is directly connected, r1-eth4 + is directly connected, r1-eth4 (vrf default), weight 1 Client list: pbr(fd XX) 1.1.1.5 resolved via static - is directly connected, r1-eth5 + is directly connected, r1-eth5 (vrf default), weight 1 Client list: pbr(fd XX) 1.1.1.6 resolved via static - is directly connected, r1-eth6 + is directly connected, r1-eth6 (vrf default), weight 1 Client list: pbr(fd XX) 1.1.1.7 resolved via static - is directly connected, r1-eth7 + is directly connected, r1-eth7 (vrf default), weight 1 Client list: pbr(fd XX) 1.1.1.8 resolved via static - is directly connected, r1-eth8 + is directly connected, r1-eth8 (vrf default), weight 1 Client list: pbr(fd XX) 2.2.2.1 unresolved @@ -53,19 +53,19 @@ Client list: pbr(fd XX) 192.168.0.2 resolved via connected - is directly connected, r1-eth0 + is directly connected, r1-eth0 (vrf default) Client list: static(fd XX) 192.168.0.4 resolved via connected - is directly connected, r1-eth0 + is directly connected, r1-eth0 (vrf default) Client list: static(fd XX) 192.168.7.10 resolved via connected - is directly connected, r1-eth7 + is directly connected, r1-eth7 (vrf default) Client list: bgp(fd XX) 192.168.7.20(Connected) resolved via connected - is directly connected, r1-eth7 + is directly connected, r1-eth7 (vrf default) Client list: bgp(fd XX) 192.168.161.4 unresolved diff --git a/tests/topotests/all_protocol_startup/r1/ipv6_nht.ref b/tests/topotests/all_protocol_startup/r1/ipv6_nht.ref index 0255ecdee8..8c93728007 100644 --- a/tests/topotests/all_protocol_startup/r1/ipv6_nht.ref +++ b/tests/topotests/all_protocol_startup/r1/ipv6_nht.ref @@ -1,13 +1,13 @@ fc00::2 resolved via connected - is directly connected, r1-eth0 + is directly connected, r1-eth0 (vrf default) Client list: static(fd XX) fc00:0:0:8::1000 resolved via connected - is directly connected, r1-eth8 + is directly connected, r1-eth8 (vrf default) Client list: bgp(fd XX) fc00:0:0:8::2000(Connected) resolved via connected - is directly connected, r1-eth8 + is directly connected, r1-eth8 (vrf default) Client list: bgp(fd XX) - \ No newline at end of file + diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 599c679864..e24556122b 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -1270,73 +1270,291 @@ failure: return -1; } -static void print_nh(struct nexthop *nexthop, struct vty *vty, - json_object *json) + +/* + * Render a nexthop into a json object; the caller allocates and owns + * the json object memory. + */ +void show_nexthop_json_helper(json_object *json_nexthop, + const struct nexthop *nexthop, + const struct route_entry *re) { - struct zebra_ns *zns = zebra_ns_lookup(nexthop->vrf_id); + json_object *json_labels = NULL; + json_object *json_backups = NULL; + json_object *json_seg6local = NULL; + json_object *json_seg6 = NULL; + int i; + + json_object_int_add(json_nexthop, "flags", nexthop->flags); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE)) + json_object_boolean_true_add(json_nexthop, "duplicate"); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) + json_object_boolean_true_add(json_nexthop, "fib"); switch (nexthop->type) { case NEXTHOP_TYPE_IPV4: case NEXTHOP_TYPE_IPV4_IFINDEX: - if (json) { - json_object_string_addf(json, "ip", "%pI4", - &nexthop->gate.ipv4); - if (nexthop->ifindex) - json_object_string_add( - json, "interface", - ifindex2ifname_per_ns( - zns, nexthop->ifindex)); - } else { - vty_out(vty, " via %pI4", &nexthop->gate.ipv4); - if (nexthop->ifindex) - vty_out(vty, ", %s", - ifindex2ifname_per_ns( - zns, nexthop->ifindex)); + json_object_string_addf(json_nexthop, "ip", "%pI4", + &nexthop->gate.ipv4); + json_object_string_add(json_nexthop, "afi", "ipv4"); + + if (nexthop->ifindex) { + json_object_int_add(json_nexthop, "interfaceIndex", + nexthop->ifindex); + json_object_string_add(json_nexthop, "interfaceName", + ifindex2ifname(nexthop->ifindex, + nexthop->vrf_id)); } break; case NEXTHOP_TYPE_IPV6: case NEXTHOP_TYPE_IPV6_IFINDEX: - if (json) { - json_object_string_addf(json, "ip", "%pI6", - &nexthop->gate.ipv6); - if (nexthop->ifindex) - json_object_string_add( - json, "interface", - ifindex2ifname_per_ns( - zns, nexthop->ifindex)); - } else { - vty_out(vty, " %pI6", &nexthop->gate.ipv6); - if (nexthop->ifindex) - vty_out(vty, ", via %s", - ifindex2ifname_per_ns( - zns, nexthop->ifindex)); + json_object_string_addf(json_nexthop, "ip", "%pI6", + &nexthop->gate.ipv6); + json_object_string_add(json_nexthop, "afi", "ipv6"); + + if (nexthop->ifindex) { + json_object_int_add(json_nexthop, "interfaceIndex", + nexthop->ifindex); + json_object_string_add(json_nexthop, "interfaceName", + ifindex2ifname(nexthop->ifindex, + nexthop->vrf_id)); } break; + case NEXTHOP_TYPE_IFINDEX: - if (json) { - json_object_string_add( - json, "interface", - ifindex2ifname_per_ns(zns, nexthop->ifindex)); - json_object_boolean_true_add(json, "directlyConnected"); - } else { - vty_out(vty, " is directly connected, %s", - ifindex2ifname_per_ns(zns, nexthop->ifindex)); + json_object_boolean_true_add(json_nexthop, "directlyConnected"); + json_object_int_add(json_nexthop, "interfaceIndex", + nexthop->ifindex); + json_object_string_add( + json_nexthop, "interfaceName", + ifindex2ifname(nexthop->ifindex, nexthop->vrf_id)); + break; + case NEXTHOP_TYPE_BLACKHOLE: + json_object_boolean_true_add(json_nexthop, "unreachable"); + switch (nexthop->bh_type) { + case BLACKHOLE_REJECT: + json_object_boolean_true_add(json_nexthop, "reject"); + break; + case BLACKHOLE_ADMINPROHIB: + json_object_boolean_true_add(json_nexthop, + "adminProhibited"); + break; + case BLACKHOLE_NULL: + json_object_boolean_true_add(json_nexthop, "blackhole"); + break; + case BLACKHOLE_UNSPEC: + break; + } + break; + } + + /* This nexthop is a resolver for the parent nexthop. + * Set resolver flag for better clarity and delimiter + * in flat list of nexthops in json. + */ + if (nexthop->rparent) + json_object_boolean_true_add(json_nexthop, "resolver"); + + if ((re == NULL || (nexthop->vrf_id != re->vrf_id))) + json_object_string_add(json_nexthop, "vrf", + vrf_id_to_name(nexthop->vrf_id)); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE)) + json_object_boolean_true_add(json_nexthop, "duplicate"); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + json_object_boolean_true_add(json_nexthop, "active"); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) + json_object_boolean_true_add(json_nexthop, "onLink"); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_LINKDOWN)) + json_object_boolean_true_add(json_nexthop, "linkDown"); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + json_object_boolean_true_add(json_nexthop, "recursive"); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) { + json_backups = json_object_new_array(); + for (i = 0; i < nexthop->backup_num; i++) { + json_object_array_add( + json_backups, + json_object_new_int(nexthop->backup_idx[i])); } + + json_object_object_add(json_nexthop, "backupIndex", + json_backups); + } + + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + if (nexthop->src.ipv4.s_addr) + json_object_string_addf(json_nexthop, "source", "%pI4", + &nexthop->src.ipv4); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) + json_object_string_addf(json_nexthop, "source", "%pI6", + &nexthop->src.ipv6); + break; + default: + break; + } + + if (nexthop->nh_label && nexthop->nh_label->num_labels) { + json_labels = json_object_new_array(); + + for (int label_index = 0; + label_index < nexthop->nh_label->num_labels; label_index++) + json_object_array_add( + json_labels, + json_object_new_int( + nexthop->nh_label->label[label_index])); + + json_object_object_add(json_nexthop, "labels", json_labels); + } + + if (nexthop->weight) + json_object_int_add(json_nexthop, "weight", nexthop->weight); + + if (nexthop->srte_color) + json_object_int_add(json_nexthop, "srteColor", + nexthop->srte_color); + + if (nexthop->nh_srv6) { + json_seg6local = json_object_new_object(); + json_object_string_add( + json_seg6local, "action", + seg6local_action2str( + nexthop->nh_srv6->seg6local_action)); + json_object_object_add(json_nexthop, "seg6local", + json_seg6local); + + json_seg6 = json_object_new_object(); + json_object_string_addf(json_seg6, "segs", "%pI6", + &nexthop->nh_srv6->seg6_segs); + json_object_object_add(json_nexthop, "seg6", json_seg6); + } +} + +/* + * Helper for nexthop output, used in the 'show ip route' path + */ +void show_route_nexthop_helper(struct vty *vty, const struct route_entry *re, + const struct nexthop *nexthop) +{ + char buf[MPLS_LABEL_STRLEN]; + int i; + + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + vty_out(vty, " via %pI4", &nexthop->gate.ipv4); + if (nexthop->ifindex) + vty_out(vty, ", %s", + ifindex2ifname(nexthop->ifindex, + nexthop->vrf_id)); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + vty_out(vty, " via %s", + inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, + sizeof(buf))); + if (nexthop->ifindex) + vty_out(vty, ", %s", + ifindex2ifname(nexthop->ifindex, + nexthop->vrf_id)); + break; + + case NEXTHOP_TYPE_IFINDEX: + vty_out(vty, " is directly connected, %s", + ifindex2ifname(nexthop->ifindex, nexthop->vrf_id)); break; case NEXTHOP_TYPE_BLACKHOLE: - if (json) { - json_object_string_add(json, "interface", "Null0"); - json_object_boolean_true_add(json, "directlyConnected"); - } else { - vty_out(vty, " is directly connected, Null0"); + vty_out(vty, " unreachable"); + switch (nexthop->bh_type) { + case BLACKHOLE_REJECT: + vty_out(vty, " (ICMP unreachable)"); + break; + case BLACKHOLE_ADMINPROHIB: + vty_out(vty, " (ICMP admin-prohibited)"); + break; + case BLACKHOLE_NULL: + vty_out(vty, " (blackhole)"); + break; + case BLACKHOLE_UNSPEC: + break; } break; + } + + if ((re == NULL || (nexthop->vrf_id != re->vrf_id))) + vty_out(vty, " (vrf %s)", vrf_id_to_name(nexthop->vrf_id)); + + if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + vty_out(vty, " inactive"); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) + vty_out(vty, " onlink"); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_LINKDOWN)) + vty_out(vty, " linkdown"); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + vty_out(vty, " (recursive)"); + + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + if (nexthop->src.ipv4.s_addr) { + vty_out(vty, ", src %pI4", &nexthop->src.ipv4); + /* SR-TE information */ + if (nexthop->srte_color) + vty_out(vty, ", SR-TE color %u", + nexthop->srte_color); + } + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) + vty_out(vty, ", src %pI6", &nexthop->src.ipv6); + break; default: break; } - if (!json) - vty_out(vty, "\n"); + /* Label information */ + if (nexthop->nh_label && nexthop->nh_label->num_labels) { + vty_out(vty, ", label %s", + mpls_label2str(nexthop->nh_label->num_labels, + nexthop->nh_label->label, buf, + sizeof(buf), 1)); + } + + if (nexthop->nh_srv6) { + seg6local_context2str(buf, sizeof(buf), + &nexthop->nh_srv6->seg6local_ctx, + nexthop->nh_srv6->seg6local_action); + vty_out(vty, ", seg6local %s %s", + seg6local_action2str( + nexthop->nh_srv6->seg6local_action), + buf); + vty_out(vty, ", seg6 %pI6", &nexthop->nh_srv6->seg6_segs); + } + + if (nexthop->weight) + vty_out(vty, ", weight %u", nexthop->weight); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) { + vty_out(vty, ", backup %d", nexthop->backup_idx[0]); + + for (i = 1; i < nexthop->backup_num; i++) + vty_out(vty, ",%d", nexthop->backup_idx[i]); + } } static void print_rnh(struct route_node *rn, struct vty *vty, json_object *json) @@ -1368,7 +1586,8 @@ static void print_rnh(struct route_node *rn, struct vty *vty, json_object *json) CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)); json_object_object_add(json_nht, "clientList", json_client_array); - json_object_object_add(json_nht, "gates", json_nexthop_array); + json_object_object_add(json_nht, "nexthops", + json_nexthop_array); } else { vty_out(vty, "%s%s\n", inet_ntop(rn->p.family, &rn->p.u.prefix, buf, BUFSIZ), @@ -1392,8 +1611,12 @@ static void print_rnh(struct route_node *rn, struct vty *vty, json_object *json) json_nexthop = json_object_new_object(); json_object_array_add(json_nexthop_array, json_nexthop); + show_nexthop_json_helper(json_nexthop, nexthop, + NULL); + } else { + show_route_nexthop_helper(vty, NULL, nexthop); + vty_out(vty, "\n"); } - print_nh(nexthop, vty, json_nexthop); } } else { if (json) diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h index 44ce65b4b6..88be69a81d 100644 --- a/zebra/zebra_rnh.h +++ b/zebra/zebra_rnh.h @@ -58,6 +58,12 @@ extern bool rnh_nexthop_valid(const struct route_entry *re, void rnh_set_hide_backups(bool hide_p); bool rnh_get_hide_backups(void); +void show_nexthop_json_helper(json_object *json_nexthop, + const struct nexthop *nexthop, + const struct route_entry *re); +void show_route_nexthop_helper(struct vty *vty, const struct route_entry *re, + const struct nexthop *nexthop); + #ifdef __cplusplus } #endif diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index ccd6eb2631..8a73ae3d28 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -598,340 +598,6 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn, } } -/* - * Helper for nexthop output, used in the 'show ip route' path - */ -static void show_route_nexthop_helper(struct vty *vty, - const struct route_entry *re, - const struct nexthop *nexthop) -{ - char buf[MPLS_LABEL_STRLEN]; - int i; - - switch (nexthop->type) { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - vty_out(vty, " via %pI4", &nexthop->gate.ipv4); - if (nexthop->ifindex) - vty_out(vty, ", %s", - ifindex2ifname(nexthop->ifindex, - nexthop->vrf_id)); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - vty_out(vty, " via %s", - inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, - sizeof(buf))); - if (nexthop->ifindex) - vty_out(vty, ", %s", - ifindex2ifname(nexthop->ifindex, - nexthop->vrf_id)); - break; - - case NEXTHOP_TYPE_IFINDEX: - vty_out(vty, " is directly connected, %s", - ifindex2ifname(nexthop->ifindex, nexthop->vrf_id)); - break; - case NEXTHOP_TYPE_BLACKHOLE: - vty_out(vty, " unreachable"); - switch (nexthop->bh_type) { - case BLACKHOLE_REJECT: - vty_out(vty, " (ICMP unreachable)"); - break; - case BLACKHOLE_ADMINPROHIB: - vty_out(vty, " (ICMP admin-prohibited)"); - break; - case BLACKHOLE_NULL: - vty_out(vty, " (blackhole)"); - break; - case BLACKHOLE_UNSPEC: - break; - } - break; - } - - if ((re == NULL || (nexthop->vrf_id != re->vrf_id))) - vty_out(vty, " (vrf %s)", vrf_id_to_name(nexthop->vrf_id)); - - if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - vty_out(vty, " inactive"); - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) - vty_out(vty, " onlink"); - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_LINKDOWN)) - vty_out(vty, " linkdown"); - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - vty_out(vty, " (recursive)"); - - switch (nexthop->type) { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - if (nexthop->src.ipv4.s_addr) { - if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf, - sizeof(buf))) - vty_out(vty, ", src %s", buf); - /* SR-TE information */ - if (nexthop->srte_color) - vty_out(vty, ", SR-TE color %u", - nexthop->srte_color); - } - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) { - if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf, - sizeof(buf))) - vty_out(vty, ", src %s", buf); - } - break; - default: - break; - } - - /* Label information */ - if (nexthop->nh_label && nexthop->nh_label->num_labels) { - vty_out(vty, ", label %s", - mpls_label2str(nexthop->nh_label->num_labels, - nexthop->nh_label->label, buf, - sizeof(buf), 1)); - } - - if (nexthop->nh_srv6) { - seg6local_context2str(buf, sizeof(buf), - &nexthop->nh_srv6->seg6local_ctx, - nexthop->nh_srv6->seg6local_action); - vty_out(vty, ", seg6local %s %s", - seg6local_action2str( - nexthop->nh_srv6->seg6local_action), - buf); - - inet_ntop(AF_INET6, &nexthop->nh_srv6->seg6_segs, buf, - sizeof(buf)); - vty_out(vty, ", seg6 %s", buf); - } - - if (nexthop->weight) - vty_out(vty, ", weight %u", nexthop->weight); - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) { - vty_out(vty, ", backup %d", nexthop->backup_idx[0]); - - for (i = 1; i < nexthop->backup_num; i++) - vty_out(vty, ",%d", nexthop->backup_idx[i]); - } -} - - -/* - * Render a nexthop into a json object; the caller allocates and owns - * the json object memory. - */ -static void show_nexthop_json_helper(json_object *json_nexthop, - const struct nexthop *nexthop, - const struct route_entry *re) -{ - char buf[SRCDEST2STR_BUFFER]; - json_object *json_labels = NULL; - json_object *json_backups = NULL; - json_object *json_seg6local = NULL; - json_object *json_seg6 = NULL; - int i; - - json_object_int_add(json_nexthop, "flags", - nexthop->flags); - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE)) - json_object_boolean_true_add(json_nexthop, - "duplicate"); - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) - json_object_boolean_true_add(json_nexthop, - "fib"); - - switch (nexthop->type) { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - json_object_string_addf(json_nexthop, "ip", "%pI4", - &nexthop->gate.ipv4); - json_object_string_add(json_nexthop, "afi", - "ipv4"); - - if (nexthop->ifindex) { - json_object_int_add(json_nexthop, - "interfaceIndex", - nexthop->ifindex); - json_object_string_add( - json_nexthop, "interfaceName", - ifindex2ifname( - nexthop->ifindex, - nexthop->vrf_id)); - } - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - json_object_string_addf(json_nexthop, "ip", "%pI6", - &nexthop->gate.ipv6); - json_object_string_add(json_nexthop, "afi", - "ipv6"); - - if (nexthop->ifindex) { - json_object_int_add(json_nexthop, - "interfaceIndex", - nexthop->ifindex); - json_object_string_add( - json_nexthop, "interfaceName", - ifindex2ifname( - nexthop->ifindex, - nexthop->vrf_id)); - } - break; - - case NEXTHOP_TYPE_IFINDEX: - json_object_boolean_true_add( - json_nexthop, "directlyConnected"); - json_object_int_add(json_nexthop, - "interfaceIndex", - nexthop->ifindex); - json_object_string_add( - json_nexthop, "interfaceName", - ifindex2ifname(nexthop->ifindex, - nexthop->vrf_id)); - break; - case NEXTHOP_TYPE_BLACKHOLE: - json_object_boolean_true_add(json_nexthop, - "unreachable"); - switch (nexthop->bh_type) { - case BLACKHOLE_REJECT: - json_object_boolean_true_add( - json_nexthop, "reject"); - break; - case BLACKHOLE_ADMINPROHIB: - json_object_boolean_true_add(json_nexthop, - "adminProhibited"); - break; - case BLACKHOLE_NULL: - json_object_boolean_true_add( - json_nexthop, "blackhole"); - break; - case BLACKHOLE_UNSPEC: - break; - } - break; - } - - /* This nexthop is a resolver for the parent nexthop. - * Set resolver flag for better clarity and delimiter - * in flat list of nexthops in json. - */ - if (nexthop->rparent) - json_object_boolean_true_add(json_nexthop, "resolver"); - - if ((re == NULL || (nexthop->vrf_id != re->vrf_id))) - json_object_string_add(json_nexthop, "vrf", - vrf_id_to_name(nexthop->vrf_id)); - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE)) - json_object_boolean_true_add(json_nexthop, - "duplicate"); - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - json_object_boolean_true_add(json_nexthop, - "active"); - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) - json_object_boolean_true_add(json_nexthop, "onLink"); - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_LINKDOWN)) - json_object_boolean_true_add(json_nexthop, "linkDown"); - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - json_object_boolean_true_add(json_nexthop, - "recursive"); - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) { - json_backups = json_object_new_array(); - for (i = 0; i < nexthop->backup_num; i++) { - json_object_array_add( - json_backups, - json_object_new_int(nexthop->backup_idx[i])); - } - - json_object_object_add(json_nexthop, "backupIndex", - json_backups); - } - - switch (nexthop->type) { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - if (nexthop->src.ipv4.s_addr) { - if (inet_ntop(AF_INET, - &nexthop->src.ipv4, buf, - sizeof(buf))) - json_object_string_add( - json_nexthop, "source", - buf); - } - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, - &in6addr_any)) { - if (inet_ntop(AF_INET6, - &nexthop->src.ipv6, buf, - sizeof(buf))) - json_object_string_add( - json_nexthop, "source", - buf); - } - break; - default: - break; - } - - if (nexthop->nh_label - && nexthop->nh_label->num_labels) { - json_labels = json_object_new_array(); - - for (int label_index = 0; - label_index - < nexthop->nh_label->num_labels; - label_index++) - json_object_array_add( - json_labels, - json_object_new_int( - nexthop->nh_label->label - [label_index])); - - json_object_object_add(json_nexthop, "labels", - json_labels); - } - - if (nexthop->weight) - json_object_int_add(json_nexthop, "weight", - nexthop->weight); - - if (nexthop->srte_color) - json_object_int_add(json_nexthop, "srteColor", - nexthop->srte_color); - - if (nexthop->nh_srv6) { - json_seg6local = json_object_new_object(); - json_object_string_add( - json_seg6local, "action", seg6local_action2str( - nexthop->nh_srv6->seg6local_action)); - json_object_object_add(json_nexthop, "seg6local", - json_seg6local); - - json_seg6 = json_object_new_object(); - inet_ntop(AF_INET6, &nexthop->nh_srv6->seg6_segs, buf, - sizeof(buf)); - json_object_string_add(json_seg6, "segs", buf); - json_object_object_add(json_nexthop, "seg6", json_seg6); - } -} - static void vty_show_ip_route(struct vty *vty, struct route_node *rn, struct route_entry *re, json_object *json, bool is_fib, bool show_ng) @@ -1410,7 +1076,9 @@ DEFPY (show_ip_nht, zvrf_name(zvrf), json_vrf); json_object_object_add(json_vrf, - "nexthops", + (afi == AFI_IP) + ? "ipv4" + : "ipv6", json_nexthop); } else { vty_out(vty, "\nVRF %s:\n", @@ -1447,7 +1115,9 @@ DEFPY (show_ip_nht, else json_object_object_add(json, "default", json_vrf); - json_object_object_add(json_vrf, "nexthops", json_nexthop); + json_object_object_add(json_vrf, + (afi == AFI_IP) ? "ipv4" : "ipv6", + json_nexthop); } zebra_print_rnh_table(vrf_id, afi, safi, vty, p, json_nexthop); -- 2.39.5