diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 30a558a52f..b94562f6a6 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -26,6 +26,7 @@ #include "spf_backoff.h" #include "srcdest_table.h" #include "vrf.h" +#include "lib/json.h" #include "isis_errors.h" #include "isis_constants.h" @@ -2347,7 +2348,7 @@ DEFUN(show_isis_topology, show_isis_topology_cmd, static void isis_print_route(struct ttable *tt, const struct prefix *prefix, struct isis_route_info *rinfo, bool prefix_sid, - bool no_adjacencies) + bool no_adjacencies, bool json) { struct isis_nexthop *nexthop; struct listnode *node; @@ -2399,7 +2400,7 @@ static void isis_print_route(struct ttable *tt, const struct prefix *prefix, continue; } - if (first) { + if (first || json) { ttable_add_row(tt, "%s|%u|%s|%s|%s|%s|%d", buf_prefix, rinfo->cost, @@ -2438,7 +2439,7 @@ static void isis_print_route(struct ttable *tt, const struct prefix *prefix, strlcpy(buf_labels, "-", sizeof(buf_labels)); - if (first) { + if (first || json) { ttable_add_row(tt, "%s|%u|%s|%s|%s", buf_prefix, rinfo->cost, buf_iface, buf_nhop, @@ -2480,7 +2481,7 @@ static void isis_print_route(struct ttable *tt, const struct prefix *prefix, } void isis_print_routes(struct vty *vty, struct isis_spftree *spftree, - bool prefix_sid, bool backup) + struct json_object **json, bool prefix_sid, bool backup) { struct route_table *route_table; struct ttable *tt; @@ -2506,8 +2507,9 @@ void isis_print_routes(struct vty *vty, struct isis_spftree *spftree, return; } - vty_out(vty, "IS-IS %s %s routing table:\n\n", - circuit_t2string(spftree->level), tree_id_text); + if (json == NULL) + vty_out(vty, "IS-IS %s %s routing table:\n\n", + circuit_t2string(spftree->level), tree_id_text); /* Prepare table. */ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]); @@ -2534,55 +2536,101 @@ void isis_print_routes(struct vty *vty, struct isis_spftree *spftree, if (!rinfo) continue; - isis_print_route(tt, &rn->p, rinfo, prefix_sid, no_adjacencies); + isis_print_route(tt, &rn->p, rinfo, prefix_sid, no_adjacencies, + json != NULL); } /* Dump the generated table. */ - if (tt->nrows > 1) { + if (json == NULL && tt->nrows > 1) { char *table; table = ttable_dump(tt, "\n"); vty_out(vty, "%s\n", table); XFREE(MTYPE_TMP, table); + } else if (json) { + *json = ttable_json(tt, prefix_sid ? "sdssdsdd" : "sdsss"); } ttable_del(tt); } static void show_isis_route_common(struct vty *vty, int levels, struct isis *isis, bool prefix_sid, - bool backup) + bool backup, json_object **json) { + json_object *json_level = NULL, *jstr = NULL, *json_val; struct listnode *node; struct isis_area *area; + char key[8]; if (!isis->area_list || isis->area_list->count == 0) return; + if (json) + *json = json_object_new_object(); + for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { - vty_out(vty, "Area %s:\n", - area->area_tag ? area->area_tag : "null"); + if (json) { + jstr = json_object_new_string( + area->area_tag ? area->area_tag : "null"); + json_object_object_add(*json, "area", jstr); + } else { + vty_out(vty, "Area %s:\n", + area->area_tag ? area->area_tag : "null"); + } for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) { if ((level & levels) == 0) continue; + if (json) { + json_level = json_object_new_object(); + jstr = json_object_new_string( + area->area_tag ? area->area_tag + : "null"); + json_object_object_add(json_level, "area", + jstr); + } + if (area->ip_circuits > 0) { + json_val = NULL; isis_print_routes( vty, area->spftree[SPFTREE_IPV4][level - 1], - prefix_sid, backup); + json ? &json_val : NULL, prefix_sid, + backup); + if (json && json_val) { + json_object_object_add( + json_level, "ipv4", json_val); + } } if (area->ipv6_circuits > 0) { + json_val = NULL; isis_print_routes( vty, area->spftree[SPFTREE_IPV6][level - 1], - prefix_sid, backup); + json ? &json_val : NULL, prefix_sid, + backup); + if (json && json_val) { + json_object_object_add( + json_level, "ipv6", json_val); + } } if (isis_area_ipv6_dstsrc_enabled(area)) { + json_val = NULL; isis_print_routes(vty, area->spftree[SPFTREE_DSTSRC] [level - 1], + json ? &json_val : NULL, prefix_sid, backup); + if (json && json_val) { + json_object_object_add(json_level, + "ipv6-dstsrc", + json_val); + } + } + if (json) { + snprintf(key, sizeof(key), "level-%d", level); + json_object_object_add(*json, key, json_level); } } } @@ -2594,7 +2642,8 @@ DEFUN(show_isis_route, show_isis_route_cmd, #ifndef FABRICD " []" #endif - " []", + " []" + " [json$uj]", SHOW_STR PROTO_HELP VRF_FULL_CMD_HELP_STR "IS-IS routing table\n" #ifndef FABRICD @@ -2602,7 +2651,7 @@ DEFUN(show_isis_route, show_isis_route_cmd, "level-2 routes\n" #endif "Show Prefix-SID information\n" - "Show backup routes\n") + "Show backup routes\n" JSON_STR) { int levels; struct isis *isis; @@ -2611,7 +2660,9 @@ DEFUN(show_isis_route, show_isis_route_cmd, bool all_vrf = false; bool prefix_sid = false; bool backup = false; + bool uj = use_json(argc, argv); int idx = 0; + json_object *json = NULL, *json_vrf = NULL; if (argv_find(argv, argc, "level-1", &idx)) levels = ISIS_LEVEL1; @@ -2631,17 +2682,44 @@ DEFUN(show_isis_route, show_isis_route_cmd, if (argv_find(argv, argc, "backup", &idx)) backup = true; + if (uj) + json = json_object_new_array(); + if (vrf_name) { if (all_vrf) { - for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) + for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) { show_isis_route_common(vty, levels, isis, - prefix_sid, backup); - return CMD_SUCCESS; + prefix_sid, backup, + uj ? &json_vrf : NULL); + if (uj) { + json_object_object_add( + json_vrf, "vrf_id", + json_object_new_int( + isis->vrf_id)); + json_object_array_add(json, json_vrf); + } + } + goto out; } isis = isis_lookup_by_vrfname(vrf_name); - if (isis != NULL) + if (isis != NULL) { show_isis_route_common(vty, levels, isis, prefix_sid, - backup); + backup, uj ? &json_vrf : NULL); + if (uj) { + json_object_object_add( + json_vrf, "vrf_id", + json_object_new_int(isis->vrf_id)); + json_object_array_add(json, json_vrf); + } + } + } + +out: + if (uj) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); } return CMD_SUCCESS; diff --git a/isisd/isis_spf.h b/isisd/isis_spf.h index 9af4d1bdcf..7e9754d9bf 100644 --- a/isisd/isis_spf.h +++ b/isisd/isis_spf.h @@ -12,6 +12,7 @@ #define _ZEBRA_ISIS_SPF_H #include "isisd/isis_lfa.h" +#include "lib/json.h" struct isis_spftree; @@ -62,7 +63,7 @@ int _isis_spf_schedule(struct isis_area *area, int level, const char *func, const char *file, int line); void isis_print_spftree(struct vty *vty, struct isis_spftree *spftree); void isis_print_routes(struct vty *vty, struct isis_spftree *spftree, - bool prefix_sid, bool backup); + json_object **json, bool prefix_sid, bool backup); void isis_spf_init(void); void isis_spf_print(struct isis_spftree *spftree, struct vty *vty); void isis_spf_print_json(struct isis_spftree *spftree, diff --git a/tests/isisd/test_isis_spf.c b/tests/isisd/test_isis_spf.c index 8319d7e813..6eb180b501 100644 --- a/tests/isisd/test_isis_spf.c +++ b/tests/isisd/test_isis_spf.c @@ -55,7 +55,7 @@ static void test_run_spf(struct vty *vty, const struct isis_topology *topology, /* Print the SPT and the corresponding routing table. */ isis_print_spftree(vty, spftree); - isis_print_routes(vty, spftree, false, false); + isis_print_routes(vty, spftree, NULL, false, false); /* Cleanup SPF tree. */ isis_spftree_del(spftree); @@ -86,9 +86,9 @@ static void test_run_lfa(struct vty *vty, const struct isis_topology *topology, /* Print the SPT and the corresponding main/backup routing tables. */ isis_print_spftree(vty, spftree_self); vty_out(vty, "Main:\n"); - isis_print_routes(vty, spftree_self, false, false); + isis_print_routes(vty, spftree_self, NULL, false, false); vty_out(vty, "Backup:\n"); - isis_print_routes(vty, spftree_self, false, true); + isis_print_routes(vty, spftree_self, NULL, false, true); /* Cleanup everything. */ isis_spftree_del(spftree_self); @@ -165,9 +165,9 @@ static void test_run_rlfa(struct vty *vty, const struct isis_topology *topology, /* Print the SPT and the corresponding main/backup routing tables. */ isis_print_spftree(vty, spftree_self); vty_out(vty, "Main:\n"); - isis_print_routes(vty, spftree_self, false, false); + isis_print_routes(vty, spftree_self, NULL, false, false); vty_out(vty, "Backup:\n"); - isis_print_routes(vty, spftree_self, false, true); + isis_print_routes(vty, spftree_self, NULL, false, true); /* Cleanup everything. */ isis_spftree_del(spftree_self); @@ -228,7 +228,7 @@ static void test_run_ti_lfa(struct vty *vty, * Print the post-convergence SPT and the corresponding routing table. */ isis_print_spftree(vty, spftree_pc); - isis_print_routes(vty, spftree_self, false, true); + isis_print_routes(vty, spftree_self, NULL, false, true); /* Cleanup everything. */ isis_spftree_del(spftree_self);