isisd: add option to display isis routes as json

Append an optional parameter to "show isis route [prefix-sid]" that
formats the output as a JSON array.

Signed-off-by: Eric Kinzie <ekinzie@labn.net>
Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
This commit is contained in:
Eric Kinzie 2022-09-02 16:33:52 +02:00 committed by Louis Scalbert
parent e39af3727e
commit 42ac448538
3 changed files with 106 additions and 27 deletions

View File

@ -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,6 +2507,7 @@ void isis_print_routes(struct vty *vty, struct isis_spftree *spftree,
return;
}
if (json == NULL)
vty_out(vty, "IS-IS %s %s routing table:\n\n",
circuit_t2string(spftree->level), tree_id_text);
@ -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)) {
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
" [<level-1|level-2>]"
#endif
" [<prefix-sid|backup>]",
" [<prefix-sid|backup>]"
" [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;

View File

@ -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,

View File

@ -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);