static void copy_state(struct rnh *rnh, const struct route_entry *re,
struct route_node *rn);
static bool compare_state(struct route_entry *r1, struct route_entry *r2);
-static void print_rnh(struct route_node *rn, struct vty *vty);
+static void print_rnh(struct route_node *rn, struct vty *vty,
+ json_object *json);
static int zebra_client_cleanup_rnh(struct zserv *client);
void zebra_rnh_init(void)
}
void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, safi_t safi,
- struct vty *vty, const struct prefix *p)
+ struct vty *vty, const struct prefix *p,
+ json_object *json)
{
struct route_table *table;
struct route_node *rn;
continue;
if (rn->info)
- print_rnh(rn, vty);
+ print_rnh(rn, vty, json);
}
}
return -1;
}
-static void print_nh(struct nexthop *nexthop, struct vty *vty)
+static void print_nh(struct nexthop *nexthop, struct vty *vty,
+ json_object *json)
{
- char buf[BUFSIZ];
struct zebra_ns *zns = zebra_ns_lookup(nexthop->vrf_id);
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_per_ns(zns, nexthop->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));
+ }
break;
case NEXTHOP_TYPE_IPV6:
case NEXTHOP_TYPE_IPV6_IFINDEX:
- vty_out(vty, " %s",
- inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ));
- if (nexthop->ifindex)
- vty_out(vty, ", via %s",
- ifindex2ifname_per_ns(zns, nexthop->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));
+ }
break;
case NEXTHOP_TYPE_IFINDEX:
- vty_out(vty, " is directly connected, %s",
- ifindex2ifname_per_ns(zns, nexthop->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));
+ }
break;
case NEXTHOP_TYPE_BLACKHOLE:
- vty_out(vty, " is directly connected, Null0");
+ if (json) {
+ json_object_string_add(json, "interface", "Null0");
+ json_object_boolean_true_add(json, "directlyConnected");
+ } else {
+ vty_out(vty, " is directly connected, Null0");
+ }
break;
default:
break;
}
- vty_out(vty, "\n");
+
+ if (!json)
+ vty_out(vty, "\n");
}
-static void print_rnh(struct route_node *rn, struct vty *vty)
+static void print_rnh(struct route_node *rn, struct vty *vty, json_object *json)
{
struct rnh *rnh;
struct nexthop *nexthop;
struct listnode *node;
struct zserv *client;
char buf[BUFSIZ];
+ json_object *json_nht = NULL;
+ json_object *json_client_array = NULL;
+ json_object *json_client = NULL;
+ json_object *json_nexthop_array = NULL;
+ json_object *json_nexthop = NULL;
rnh = rn->info;
- vty_out(vty, "%s%s\n",
- inet_ntop(rn->p.family, &rn->p.u.prefix, buf, BUFSIZ),
- CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED) ? "(Connected)"
- : "");
- if (rnh->state) {
- vty_out(vty, " resolved via %s\n",
- zebra_route_string(rnh->state->type));
- for (nexthop = rnh->state->nhe->nhg.nexthop; nexthop;
- nexthop = nexthop->next)
- print_nh(nexthop, vty);
- } else
- vty_out(vty, " unresolved%s\n",
+
+ if (json) {
+ json_nht = json_object_new_object();
+ json_nexthop_array = json_object_new_array();
+ json_client_array = json_object_new_array();
+
+ json_object_object_add(
+ json,
+ inet_ntop(rn->p.family, &rn->p.u.prefix, buf, BUFSIZ),
+ json_nht);
+ json_object_boolean_add(
+ json_nht, "nhtConnected",
+ 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);
+ } else {
+ vty_out(vty, "%s%s\n",
+ inet_ntop(rn->p.family, &rn->p.u.prefix, buf, BUFSIZ),
CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)
? "(Connected)"
: "");
+ }
+
+ if (rnh->state) {
+ if (json)
+ json_object_string_add(
+ json_nht, "resolvedProtocol",
+ zebra_route_string(rnh->state->type));
+ else
+ vty_out(vty, " resolved via %s\n",
+ zebra_route_string(rnh->state->type));
+
+ for (nexthop = rnh->state->nhe->nhg.nexthop; nexthop;
+ nexthop = nexthop->next) {
+ if (json) {
+ json_nexthop = json_object_new_object();
+ json_object_array_add(json_nexthop_array,
+ json_nexthop);
+ }
+ print_nh(nexthop, vty, json_nexthop);
+ }
+ } else {
+ if (json)
+ json_object_boolean_add(
+ json_nht, "unresolved",
+ CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED));
+ else
+ vty_out(vty, " unresolved%s\n",
+ CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)
+ ? "(Connected)"
+ : "");
+ }
+
+ if (!json)
+ vty_out(vty, " Client list:");
+
+ for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) {
+ if (json) {
+ json_client = json_object_new_object();
+ json_object_array_add(json_client_array, json_client);
+
+ json_object_string_add(
+ json_client, "protocol",
+ zebra_route_string(client->proto));
+ json_object_int_add(json_client, "socket",
+ client->sock);
+ json_object_string_add(json_client, "protocolFiltered",
+ (rnh->filtered[client->proto]
+ ? "(filtered)"
+ : "none"));
+ } else {
+ vty_out(vty, " %s(fd %d)%s",
+ zebra_route_string(client->proto), client->sock,
+ rnh->filtered[client->proto] ? "(filtered)"
+ : "");
+ }
+ }
+
+ if (!list_isempty(rnh->zebra_pseudowire_list)) {
+ if (json)
+ json_object_boolean_true_add(json_nht,
+ "zebraPseudowires");
+ else
+ vty_out(vty, " zebra[pseudowires]");
+ }
- vty_out(vty, " Client list:");
- for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client))
- vty_out(vty, " %s(fd %d)%s", zebra_route_string(client->proto),
- client->sock,
- rnh->filtered[client->proto] ? "(filtered)" : "");
- if (!list_isempty(rnh->zebra_pseudowire_list))
- vty_out(vty, " zebra[pseudowires]");
- vty_out(vty, "\n");
+ if (!json)
+ vty_out(vty, "\n");
}
static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, afi_t afi, safi_t safi,
DEFPY (show_ip_nht,
show_ip_nht_cmd,
- "show <ip$ipv4|ipv6$ipv6> <nht|import-check>$type [<A.B.C.D|X:X::X:X>$addr|vrf NAME$vrf_name [<A.B.C.D|X:X::X:X>$addr]|vrf all$vrf_all] [mrib$mrib]",
+ "show <ip$ipv4|ipv6$ipv6> <nht|import-check>$type [<A.B.C.D|X:X::X:X>$addr|vrf NAME$vrf_name [<A.B.C.D|X:X::X:X>$addr]|vrf all$vrf_all] [mrib$mrib] [json]",
SHOW_STR
IP_STR
IP6_STR
"IPv4 Address\n"
"IPv6 Address\n"
VRF_ALL_CMD_HELP_STR
- "Show Multicast (MRIB) NHT state\n")
+ "Show Multicast (MRIB) NHT state\n"
+ JSON_STR)
{
afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
vrf_id_t vrf_id = VRF_DEFAULT;
struct prefix prefix, *p = NULL;
safi_t safi = mrib ? SAFI_MULTICAST : SAFI_UNICAST;
+ bool uj = use_json(argc, argv);
+ json_object *json = NULL;
+ json_object *json_vrf = NULL;
+ json_object *json_nexthop = NULL;
+
+ if (uj)
+ json = json_object_new_object();
if (vrf_all) {
struct vrf *vrf;
struct zebra_vrf *zvrf;
- RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
if ((zvrf = vrf->info) != NULL) {
- vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf));
+ if (uj) {
+ json_vrf = json_object_new_object();
+ json_nexthop = json_object_new_object();
+ json_object_object_add(json,
+ zvrf_name(zvrf),
+ json_vrf);
+ json_object_object_add(json_vrf,
+ "nexthops",
+ json_nexthop);
+ } else {
+ vty_out(vty, "\nVRF %s:\n",
+ zvrf_name(zvrf));
+ }
zebra_print_rnh_table(zvrf_id(zvrf), afi, safi,
- vty, NULL);
+ vty, NULL, json_nexthop);
}
+ }
+
+ if (uj)
+ vty_json(vty, json);
+
return CMD_SUCCESS;
}
if (vrf_name)
memset(&prefix, 0, sizeof(prefix));
if (addr) {
p = sockunion2hostprefix(addr, &prefix);
- if (!p)
+ if (!p) {
+ if (uj)
+ json_object_free(json);
return CMD_WARNING;
+ }
}
- zebra_print_rnh_table(vrf_id, afi, safi, vty, p);
+ if (uj) {
+ json_vrf = json_object_new_object();
+ json_nexthop = json_object_new_object();
+ if (vrf_name)
+ json_object_object_add(json, vrf_name, json_vrf);
+ else
+ json_object_object_add(json, "default", json_vrf);
+
+ json_object_object_add(json_vrf, "nexthops", json_nexthop);
+ }
+
+ zebra_print_rnh_table(vrf_id, afi, safi, vty, p, json_nexthop);
+
+ if (uj)
+ vty_json(vty, json);
+
return CMD_SUCCESS;
}