mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-05-02 20:59:42 +00:00
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:
parent
e39af3727e
commit
42ac448538
110
isisd/isis_spf.c
110
isisd/isis_spf.c
@ -26,6 +26,7 @@
|
|||||||
#include "spf_backoff.h"
|
#include "spf_backoff.h"
|
||||||
#include "srcdest_table.h"
|
#include "srcdest_table.h"
|
||||||
#include "vrf.h"
|
#include "vrf.h"
|
||||||
|
#include "lib/json.h"
|
||||||
|
|
||||||
#include "isis_errors.h"
|
#include "isis_errors.h"
|
||||||
#include "isis_constants.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,
|
static void isis_print_route(struct ttable *tt, const struct prefix *prefix,
|
||||||
struct isis_route_info *rinfo, bool prefix_sid,
|
struct isis_route_info *rinfo, bool prefix_sid,
|
||||||
bool no_adjacencies)
|
bool no_adjacencies, bool json)
|
||||||
{
|
{
|
||||||
struct isis_nexthop *nexthop;
|
struct isis_nexthop *nexthop;
|
||||||
struct listnode *node;
|
struct listnode *node;
|
||||||
@ -2399,7 +2400,7 @@ static void isis_print_route(struct ttable *tt, const struct prefix *prefix,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (first) {
|
if (first || json) {
|
||||||
ttable_add_row(tt,
|
ttable_add_row(tt,
|
||||||
"%s|%u|%s|%s|%s|%s|%d",
|
"%s|%u|%s|%s|%s|%s|%d",
|
||||||
buf_prefix, rinfo->cost,
|
buf_prefix, rinfo->cost,
|
||||||
@ -2438,7 +2439,7 @@ static void isis_print_route(struct ttable *tt, const struct prefix *prefix,
|
|||||||
strlcpy(buf_labels, "-",
|
strlcpy(buf_labels, "-",
|
||||||
sizeof(buf_labels));
|
sizeof(buf_labels));
|
||||||
|
|
||||||
if (first) {
|
if (first || json) {
|
||||||
ttable_add_row(tt, "%s|%u|%s|%s|%s",
|
ttable_add_row(tt, "%s|%u|%s|%s|%s",
|
||||||
buf_prefix, rinfo->cost,
|
buf_prefix, rinfo->cost,
|
||||||
buf_iface, buf_nhop,
|
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,
|
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 route_table *route_table;
|
||||||
struct ttable *tt;
|
struct ttable *tt;
|
||||||
@ -2506,6 +2507,7 @@ void isis_print_routes(struct vty *vty, struct isis_spftree *spftree,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (json == NULL)
|
||||||
vty_out(vty, "IS-IS %s %s routing table:\n\n",
|
vty_out(vty, "IS-IS %s %s routing table:\n\n",
|
||||||
circuit_t2string(spftree->level), tree_id_text);
|
circuit_t2string(spftree->level), tree_id_text);
|
||||||
|
|
||||||
@ -2534,55 +2536,101 @@ void isis_print_routes(struct vty *vty, struct isis_spftree *spftree,
|
|||||||
if (!rinfo)
|
if (!rinfo)
|
||||||
continue;
|
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. */
|
/* Dump the generated table. */
|
||||||
if (tt->nrows > 1) {
|
if (json == NULL && tt->nrows > 1) {
|
||||||
char *table;
|
char *table;
|
||||||
|
|
||||||
table = ttable_dump(tt, "\n");
|
table = ttable_dump(tt, "\n");
|
||||||
vty_out(vty, "%s\n", table);
|
vty_out(vty, "%s\n", table);
|
||||||
XFREE(MTYPE_TMP, table);
|
XFREE(MTYPE_TMP, table);
|
||||||
|
} else if (json) {
|
||||||
|
*json = ttable_json(tt, prefix_sid ? "sdssdsdd" : "sdsss");
|
||||||
}
|
}
|
||||||
ttable_del(tt);
|
ttable_del(tt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_isis_route_common(struct vty *vty, int levels,
|
static void show_isis_route_common(struct vty *vty, int levels,
|
||||||
struct isis *isis, bool prefix_sid,
|
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 listnode *node;
|
||||||
struct isis_area *area;
|
struct isis_area *area;
|
||||||
|
char key[8];
|
||||||
|
|
||||||
if (!isis->area_list || isis->area_list->count == 0)
|
if (!isis->area_list || isis->area_list->count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (json)
|
||||||
|
*json = json_object_new_object();
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) {
|
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",
|
vty_out(vty, "Area %s:\n",
|
||||||
area->area_tag ? area->area_tag : "null");
|
area->area_tag ? area->area_tag : "null");
|
||||||
|
}
|
||||||
|
|
||||||
for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) {
|
for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) {
|
||||||
if ((level & levels) == 0)
|
if ((level & levels) == 0)
|
||||||
continue;
|
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) {
|
if (area->ip_circuits > 0) {
|
||||||
|
json_val = NULL;
|
||||||
isis_print_routes(
|
isis_print_routes(
|
||||||
vty,
|
vty,
|
||||||
area->spftree[SPFTREE_IPV4][level - 1],
|
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) {
|
if (area->ipv6_circuits > 0) {
|
||||||
|
json_val = NULL;
|
||||||
isis_print_routes(
|
isis_print_routes(
|
||||||
vty,
|
vty,
|
||||||
area->spftree[SPFTREE_IPV6][level - 1],
|
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)) {
|
if (isis_area_ipv6_dstsrc_enabled(area)) {
|
||||||
|
json_val = NULL;
|
||||||
isis_print_routes(vty,
|
isis_print_routes(vty,
|
||||||
area->spftree[SPFTREE_DSTSRC]
|
area->spftree[SPFTREE_DSTSRC]
|
||||||
[level - 1],
|
[level - 1],
|
||||||
|
json ? &json_val : NULL,
|
||||||
prefix_sid, backup);
|
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
|
#ifndef FABRICD
|
||||||
" [<level-1|level-2>]"
|
" [<level-1|level-2>]"
|
||||||
#endif
|
#endif
|
||||||
" [<prefix-sid|backup>]",
|
" [<prefix-sid|backup>]"
|
||||||
|
" [json$uj]",
|
||||||
SHOW_STR PROTO_HELP VRF_FULL_CMD_HELP_STR
|
SHOW_STR PROTO_HELP VRF_FULL_CMD_HELP_STR
|
||||||
"IS-IS routing table\n"
|
"IS-IS routing table\n"
|
||||||
#ifndef FABRICD
|
#ifndef FABRICD
|
||||||
@ -2602,7 +2651,7 @@ DEFUN(show_isis_route, show_isis_route_cmd,
|
|||||||
"level-2 routes\n"
|
"level-2 routes\n"
|
||||||
#endif
|
#endif
|
||||||
"Show Prefix-SID information\n"
|
"Show Prefix-SID information\n"
|
||||||
"Show backup routes\n")
|
"Show backup routes\n" JSON_STR)
|
||||||
{
|
{
|
||||||
int levels;
|
int levels;
|
||||||
struct isis *isis;
|
struct isis *isis;
|
||||||
@ -2611,7 +2660,9 @@ DEFUN(show_isis_route, show_isis_route_cmd,
|
|||||||
bool all_vrf = false;
|
bool all_vrf = false;
|
||||||
bool prefix_sid = false;
|
bool prefix_sid = false;
|
||||||
bool backup = false;
|
bool backup = false;
|
||||||
|
bool uj = use_json(argc, argv);
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
|
json_object *json = NULL, *json_vrf = NULL;
|
||||||
|
|
||||||
if (argv_find(argv, argc, "level-1", &idx))
|
if (argv_find(argv, argc, "level-1", &idx))
|
||||||
levels = ISIS_LEVEL1;
|
levels = ISIS_LEVEL1;
|
||||||
@ -2631,17 +2682,44 @@ DEFUN(show_isis_route, show_isis_route_cmd,
|
|||||||
if (argv_find(argv, argc, "backup", &idx))
|
if (argv_find(argv, argc, "backup", &idx))
|
||||||
backup = true;
|
backup = true;
|
||||||
|
|
||||||
|
if (uj)
|
||||||
|
json = json_object_new_array();
|
||||||
|
|
||||||
if (vrf_name) {
|
if (vrf_name) {
|
||||||
if (all_vrf) {
|
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,
|
show_isis_route_common(vty, levels, isis,
|
||||||
prefix_sid, backup);
|
prefix_sid, backup,
|
||||||
return CMD_SUCCESS;
|
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);
|
isis = isis_lookup_by_vrfname(vrf_name);
|
||||||
if (isis != NULL)
|
if (isis != NULL) {
|
||||||
show_isis_route_common(vty, levels, isis, prefix_sid,
|
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;
|
return CMD_SUCCESS;
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#define _ZEBRA_ISIS_SPF_H
|
#define _ZEBRA_ISIS_SPF_H
|
||||||
|
|
||||||
#include "isisd/isis_lfa.h"
|
#include "isisd/isis_lfa.h"
|
||||||
|
#include "lib/json.h"
|
||||||
|
|
||||||
struct isis_spftree;
|
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);
|
const char *func, const char *file, int line);
|
||||||
void isis_print_spftree(struct vty *vty, struct isis_spftree *spftree);
|
void isis_print_spftree(struct vty *vty, struct isis_spftree *spftree);
|
||||||
void isis_print_routes(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_init(void);
|
||||||
void isis_spf_print(struct isis_spftree *spftree, struct vty *vty);
|
void isis_spf_print(struct isis_spftree *spftree, struct vty *vty);
|
||||||
void isis_spf_print_json(struct isis_spftree *spftree,
|
void isis_spf_print_json(struct isis_spftree *spftree,
|
||||||
|
@ -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. */
|
/* Print the SPT and the corresponding routing table. */
|
||||||
isis_print_spftree(vty, spftree);
|
isis_print_spftree(vty, spftree);
|
||||||
isis_print_routes(vty, spftree, false, false);
|
isis_print_routes(vty, spftree, NULL, false, false);
|
||||||
|
|
||||||
/* Cleanup SPF tree. */
|
/* Cleanup SPF tree. */
|
||||||
isis_spftree_del(spftree);
|
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. */
|
/* Print the SPT and the corresponding main/backup routing tables. */
|
||||||
isis_print_spftree(vty, spftree_self);
|
isis_print_spftree(vty, spftree_self);
|
||||||
vty_out(vty, "Main:\n");
|
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");
|
vty_out(vty, "Backup:\n");
|
||||||
isis_print_routes(vty, spftree_self, false, true);
|
isis_print_routes(vty, spftree_self, NULL, false, true);
|
||||||
|
|
||||||
/* Cleanup everything. */
|
/* Cleanup everything. */
|
||||||
isis_spftree_del(spftree_self);
|
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. */
|
/* Print the SPT and the corresponding main/backup routing tables. */
|
||||||
isis_print_spftree(vty, spftree_self);
|
isis_print_spftree(vty, spftree_self);
|
||||||
vty_out(vty, "Main:\n");
|
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");
|
vty_out(vty, "Backup:\n");
|
||||||
isis_print_routes(vty, spftree_self, false, true);
|
isis_print_routes(vty, spftree_self, NULL, false, true);
|
||||||
|
|
||||||
/* Cleanup everything. */
|
/* Cleanup everything. */
|
||||||
isis_spftree_del(spftree_self);
|
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.
|
* Print the post-convergence SPT and the corresponding routing table.
|
||||||
*/
|
*/
|
||||||
isis_print_spftree(vty, spftree_pc);
|
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. */
|
/* Cleanup everything. */
|
||||||
isis_spftree_del(spftree_self);
|
isis_spftree_del(spftree_self);
|
||||||
|
Loading…
Reference in New Issue
Block a user