summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRuss White <russ@riw.us>2022-03-08 17:15:25 +0100
committerGitHub <noreply@github.com>2022-03-08 17:15:25 +0100
commit82934a6a326977b40dd2d31772e6e4c7f2953d0b (patch)
tree7b258b5eab8bd02690ddbe22b35bdb468a489784
parentMerge pull request #10722 from chiragshah6/evpn_dev3 (diff)
parenttopotest: Add test for isis json cmds. (diff)
downloadfrr-82934a6a326977b40dd2d31772e6e4c7f2953d0b.tar.xz
frr-82934a6a326977b40dd2d31772e6e4c7f2953d0b.zip
Merge pull request #10701 from rampxxxx/feat_isis_json_show_cmds
Feat isis json show cmds
-rw-r--r--doc/user/isisd.rst8
-rw-r--r--isisd/isis_adjacency.c214
-rw-r--r--isisd/isis_adjacency.h2
-rw-r--r--isisd/isis_circuit.c145
-rw-r--r--isisd/isis_circuit.h2
-rw-r--r--isisd/isis_lsp.c76
-rw-r--r--isisd/isis_lsp.h17
-rw-r--r--isisd/isis_pdu.c4
-rw-r--r--isisd/isis_spf.c12
-rw-r--r--isisd/isis_spf.h2
-rw-r--r--isisd/isis_tlvs.c1288
-rw-r--r--isisd/isis_tlvs.h2
-rw-r--r--isisd/isisd.c633
-rw-r--r--isisd/isisd.h12
-rw-r--r--tests/isisd/test_fuzz_isis_tlv.c8
-rw-r--r--tests/isisd/test_isis_spf.c2
-rw-r--r--tests/topotests/isis_topo1/test_isis_topo1.py88
17 files changed, 2094 insertions, 421 deletions
diff --git a/doc/user/isisd.rst b/doc/user/isisd.rst
index f7d42d820..d2859670d 100644
--- a/doc/user/isisd.rst
+++ b/doc/user/isisd.rst
@@ -272,7 +272,7 @@ ISIS interface
Showing ISIS information
========================
-.. clicmd:: show isis summary
+.. clicmd:: show isis [vrf <NAME|all>] summary [json]
Show summary information about ISIS.
@@ -280,17 +280,17 @@ Showing ISIS information
Show information about ISIS node.
-.. clicmd:: show isis interface [detail] [IFNAME]
+.. clicmd:: show isis [vrf <NAME|all>] interface [detail] [IFNAME] [json]
Show state and configuration of ISIS specified interface, or all interfaces
if no interface is given with or without details.
-.. clicmd:: show isis neighbor [detail] [SYSTEMID]
+.. clicmd:: show isis [vrf <NAME|all>] neighbor [detail] [SYSTEMID] [json]
Show state and information of ISIS specified neighbor, or all neighbors if
no system id is given with or without details.
-.. clicmd:: show isis database [detail] [LSPID]
+.. clicmd:: show isis [vrf <NAME|all>] database [detail] [LSPID] [json]
Show the ISIS database globally, for a specific LSP id without or with
details.
diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c
index 06909c430..2729dce38 100644
--- a/isisd/isis_adjacency.c
+++ b/isisd/isis_adjacency.c
@@ -464,6 +464,220 @@ void isis_adj_expire(struct thread *thread)
}
/*
+ * show isis neighbor [detail] json
+ */
+void isis_adj_print_json(struct isis_adjacency *adj, struct json_object *json,
+ char detail)
+{
+ json_object *iface_json, *ipv4_addr_json, *ipv6_link_json,
+ *ipv6_non_link_json, *topo_json, *dis_flaps_json,
+ *area_addr_json, *adj_sid_json;
+ time_t now;
+ struct isis_dynhn *dyn;
+ int level;
+ char buf[256];
+
+ json_object_string_add(json, "adj", isis_adj_name(adj));
+
+ if (detail == ISIS_UI_LEVEL_BRIEF) {
+ if (adj->circuit)
+ json_object_string_add(json, "interface",
+ adj->circuit->interface->name);
+ else
+ json_object_string_add(json, "interface",
+ "NULL circuit!");
+ json_object_int_add(json, "level", adj->level);
+ json_object_string_add(json, "state",
+ adj_state2string(adj->adj_state));
+ now = time(NULL);
+ if (adj->last_upd) {
+ if (adj->last_upd + adj->hold_time < now)
+ json_object_string_add(json, "last-upd",
+ "expiring");
+ else
+ json_object_string_add(
+ json, "expires-in",
+ time2string(adj->last_upd +
+ adj->hold_time - now));
+ }
+ json_object_string_add(json, "snpa", snpa_print(adj->snpa));
+ }
+
+ if (detail == ISIS_UI_LEVEL_DETAIL) {
+ struct sr_adjacency *sra;
+ struct listnode *anode;
+
+ level = adj->level;
+ iface_json = json_object_new_object();
+ json_object_object_add(json, "interface", iface_json);
+ if (adj->circuit)
+ json_object_string_add(iface_json, "name",
+ adj->circuit->interface->name);
+ else
+ json_object_string_add(iface_json, "name",
+ "null-circuit");
+ json_object_int_add(json, "level", adj->level);
+ json_object_string_add(iface_json, "state",
+ adj_state2string(adj->adj_state));
+ now = time(NULL);
+ if (adj->last_upd) {
+ if (adj->last_upd + adj->hold_time < now)
+ json_object_string_add(iface_json, "last-upd",
+ "expiring");
+ else
+ json_object_string_add(
+ json, "expires-in",
+ time2string(adj->last_upd +
+ adj->hold_time - now));
+ } else
+ json_object_string_add(json, "expires-in",
+ time2string(adj->hold_time));
+ json_object_int_add(iface_json, "adj-flaps", adj->flaps);
+ json_object_string_add(iface_json, "last-ago",
+ time2string(now - adj->last_flap));
+ json_object_string_add(iface_json, "circuit-type",
+ circuit_t2string(adj->circuit_t));
+ json_object_string_add(iface_json, "speaks",
+ nlpid2string(&adj->nlpids));
+ if (adj->mt_count != 1 ||
+ adj->mt_set[0] != ISIS_MT_IPV4_UNICAST) {
+ topo_json = json_object_new_object();
+ json_object_object_add(iface_json, "topologies",
+ topo_json);
+ for (unsigned int i = 0; i < adj->mt_count; i++) {
+ snprintfrr(buf, sizeof(buf), "topo-%d", i);
+ json_object_string_add(
+ topo_json, buf,
+ isis_mtid2str(adj->mt_set[i]));
+ }
+ }
+ json_object_string_add(iface_json, "snpa",
+ snpa_print(adj->snpa));
+ if (adj->circuit &&
+ (adj->circuit->circ_type == CIRCUIT_T_BROADCAST)) {
+ dyn = dynhn_find_by_id(adj->circuit->isis, adj->lanid);
+ if (dyn) {
+ snprintfrr(buf, sizeof(buf), "%s-%02x",
+ dyn->hostname,
+ adj->lanid[ISIS_SYS_ID_LEN]);
+ json_object_string_add(iface_json, "lan-id",
+ buf);
+ } else {
+ snprintfrr(buf, sizeof(buf), "%s-%02x",
+ sysid_print(adj->lanid),
+ adj->lanid[ISIS_SYS_ID_LEN]);
+ json_object_string_add(iface_json, "lan-id",
+ buf);
+ }
+
+ json_object_int_add(iface_json, "lan-prio",
+ adj->prio[adj->level - 1]);
+
+ dis_flaps_json = json_object_new_object();
+ json_object_object_add(iface_json, "dis-flaps",
+ dis_flaps_json);
+ json_object_string_add(
+ dis_flaps_json, "dis-record",
+ isis_disflag2string(
+ adj->dis_record[ISIS_LEVELS + level - 1]
+ .dis));
+ json_object_int_add(dis_flaps_json, "last",
+ adj->dischanges[level - 1]);
+ json_object_string_add(
+ dis_flaps_json, "ago",
+ time2string(now - (adj->dis_record[ISIS_LEVELS +
+ level - 1]
+ .last_dis_change)));
+ }
+
+ if (adj->area_address_count) {
+ area_addr_json = json_object_new_object();
+ json_object_object_add(iface_json, "area-address",
+ area_addr_json);
+ for (unsigned int i = 0; i < adj->area_address_count;
+ i++) {
+ json_object_string_add(
+ area_addr_json, "isonet",
+ isonet_print(adj->area_addresses[i]
+ .area_addr,
+ adj->area_addresses[i]
+ .addr_len));
+ }
+ }
+ if (adj->ipv4_address_count) {
+ ipv4_addr_json = json_object_new_object();
+ json_object_object_add(iface_json, "ipv4-address",
+ ipv4_addr_json);
+ for (unsigned int i = 0; i < adj->ipv4_address_count;
+ i++){
+ inet_ntop(AF_INET, &adj->ipv4_addresses[i], buf,
+ sizeof(buf));
+ json_object_string_add(ipv4_addr_json, "ipv4", buf);
+ }
+ }
+ if (adj->ll_ipv6_count) {
+ ipv6_link_json = json_object_new_object();
+ json_object_object_add(iface_json, "ipv6-link-local",
+ ipv6_link_json);
+ for (unsigned int i = 0; i < adj->ll_ipv6_count; i++) {
+ char buf[INET6_ADDRSTRLEN];
+ inet_ntop(AF_INET6, &adj->ll_ipv6_addrs[i], buf,
+ sizeof(buf));
+ json_object_string_add(ipv6_link_json, "ipv6",
+ buf);
+ }
+ }
+ if (adj->global_ipv6_count) {
+ ipv6_non_link_json = json_object_new_object();
+ json_object_object_add(iface_json, "ipv6-global",
+ ipv6_non_link_json);
+ for (unsigned int i = 0; i < adj->global_ipv6_count;
+ i++) {
+ char buf[INET6_ADDRSTRLEN];
+ inet_ntop(AF_INET6, &adj->global_ipv6_addrs[i],
+ buf, sizeof(buf));
+ json_object_string_add(ipv6_non_link_json,
+ "ipv6", buf);
+ }
+ }
+
+ adj_sid_json = json_object_new_object();
+ json_object_object_add(iface_json, "adj-sid", adj_sid_json);
+ for (ALL_LIST_ELEMENTS_RO(adj->adj_sids, anode, sra)) {
+ const char *adj_type;
+ const char *backup;
+ uint32_t sid;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ adj_type = "LAN Adjacency-SID";
+ sid = sra->u.ladj_sid->sid;
+ break;
+ case CIRCUIT_T_P2P:
+ adj_type = "Adjacency-SID";
+ sid = sra->u.adj_sid->sid;
+ break;
+ default:
+ continue;
+ }
+ backup = (sra->type == ISIS_SR_LAN_BACKUP) ? " (backup)"
+ : "";
+
+ json_object_string_add(adj_sid_json, "nexthop",
+ (sra->nexthop.family == AF_INET)
+ ? "IPv4"
+ : "IPv6");
+ json_object_string_add(adj_sid_json, "adj-type",
+ adj_type);
+ json_object_string_add(adj_sid_json, "is-backup",
+ backup);
+ json_object_int_add(adj_sid_json, "sid", sid);
+ }
+ }
+ return;
+}
+
+/*
* show isis neighbor [detail]
*/
void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty,
diff --git a/isisd/isis_adjacency.h b/isisd/isis_adjacency.h
index 4d84c5ca4..7467a619c 100644
--- a/isisd/isis_adjacency.h
+++ b/isisd/isis_adjacency.h
@@ -144,6 +144,8 @@ const char *isis_adj_yang_state(enum isis_adj_state state);
void isis_adj_expire(struct thread *thread);
void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty,
char detail);
+void isis_adj_print_json(struct isis_adjacency *adj, struct json_object *json,
+ char detail);
void isis_adj_build_neigh_list(struct list *adjdb, struct list *list);
void isis_adj_build_up_list(struct list *adjdb, struct list *list);
int isis_adj_usage2levels(enum isis_adj_usage usage);
diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c
index 1b0447226..da75f196b 100644
--- a/isisd/isis_circuit.c
+++ b/isisd/isis_circuit.c
@@ -933,6 +933,151 @@ void circuit_update_nlpids(struct isis_circuit *circuit)
return;
}
+void isis_circuit_print_json(struct isis_circuit *circuit,
+ struct json_object *json, char detail)
+{
+ int level;
+ json_object *iface_json, *ipv4_addr_json, *ipv6_link_json,
+ *ipv6_non_link_json, *hold_json, *lan_prio_json, *levels_json,
+ *level_json;
+ char buf_prx[INET6_BUFSIZ];
+ char buf[255];
+
+ snprintfrr(buf, sizeof(buf), "0x%x", circuit->circuit_id);
+ if (detail == ISIS_UI_LEVEL_BRIEF) {
+ iface_json = json_object_new_object();
+ json_object_object_add(json, "interface", iface_json);
+ json_object_string_add(iface_json, "name",
+ circuit->interface->name);
+ json_object_string_add(iface_json, "circuit-id", buf);
+ json_object_string_add(iface_json, "state",
+ circuit_state2string(circuit->state));
+ json_object_string_add(iface_json, "type",
+ circuit_type2string(circuit->circ_type));
+ json_object_string_add(iface_json, "level",
+ circuit_t2string(circuit->is_type));
+ }
+
+ if (detail == ISIS_UI_LEVEL_DETAIL) {
+ struct listnode *node;
+ struct prefix *ip_addr;
+
+ iface_json = json_object_new_object();
+ json_object_object_add(json, "interface", iface_json);
+ json_object_string_add(iface_json, "name",
+ circuit->interface->name);
+ json_object_string_add(iface_json, "state",
+ circuit_state2string(circuit->state));
+ if (circuit->is_passive)
+ json_object_string_add(iface_json, "is-passive",
+ "passive");
+ else
+ json_object_string_add(iface_json, "is-passive",
+ "active");
+ json_object_string_add(iface_json, "circuit-id", buf);
+ json_object_string_add(iface_json, "type",
+ circuit_type2string(circuit->circ_type));
+ json_object_string_add(iface_json, "level",
+ circuit_t2string(circuit->is_type));
+ if (circuit->circ_type == CIRCUIT_T_BROADCAST)
+ json_object_string_add(iface_json, "snpa",
+ snpa_print(circuit->u.bc.snpa));
+
+
+ levels_json = json_object_new_array();
+ json_object_object_add(iface_json, "levels", levels_json);
+ for (level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) {
+ if ((circuit->is_type & level) == 0)
+ continue;
+ level_json = json_object_new_object();
+ json_object_string_add(level_json, "level",
+ circuit_t2string(level));
+ if (circuit->area->newmetric)
+ json_object_int_add(level_json, "metric",
+ circuit->te_metric[0]);
+ else
+ json_object_int_add(level_json, "metric",
+ circuit->metric[0]);
+ if (!circuit->is_passive) {
+ json_object_int_add(level_json,
+ "active-neighbors",
+ circuit->upadjcount[0]);
+ json_object_int_add(level_json,
+ "hello-interval",
+ circuit->hello_interval[0]);
+ hold_json = json_object_new_object();
+ json_object_object_add(level_json, "holddown",
+ hold_json);
+ json_object_int_add(
+ hold_json, "count",
+ circuit->hello_multiplier[0]);
+ json_object_string_add(
+ hold_json, "pad",
+ (circuit->pad_hellos ? "yes" : "no"));
+ json_object_int_add(level_json, "cnsp-interval",
+ circuit->csnp_interval[0]);
+ json_object_int_add(level_json, "psnp-interval",
+ circuit->psnp_interval[0]);
+ if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
+ lan_prio_json =
+ json_object_new_object();
+ json_object_object_add(level_json,
+ "lan",
+ lan_prio_json);
+ json_object_int_add(
+ lan_prio_json, "priority",
+ circuit->priority[0]);
+ json_object_string_add(
+ lan_prio_json, "is-dis",
+ (circuit->u.bc.is_dr[0]
+ ? "yes"
+ : "no"));
+ }
+ }
+ json_object_array_add(levels_json, level_json);
+ }
+
+ if (circuit->ip_addrs && listcount(circuit->ip_addrs) > 0) {
+ ipv4_addr_json = json_object_new_object();
+ json_object_object_add(iface_json, "ip-prefix",
+ ipv4_addr_json);
+ for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs, node,
+ ip_addr)) {
+ snprintfrr(buf_prx, INET6_BUFSIZ, "%pFX",
+ ip_addr);
+ json_object_string_add(ipv4_addr_json, "ip",
+ buf_prx);
+ }
+ }
+ if (circuit->ipv6_link && listcount(circuit->ipv6_link) > 0) {
+ ipv6_link_json = json_object_new_object();
+ json_object_object_add(iface_json, "ipv6-link-locals",
+ ipv6_link_json);
+ for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_link, node,
+ ip_addr)) {
+ snprintfrr(buf_prx, INET6_BUFSIZ, "%pFX",
+ ip_addr);
+ json_object_string_add(ipv6_link_json, "ipv6",
+ buf_prx);
+ }
+ }
+ if (circuit->ipv6_non_link &&
+ listcount(circuit->ipv6_non_link) > 0) {
+ ipv6_non_link_json = json_object_new_object();
+ json_object_object_add(iface_json, "ipv6-prefixes",
+ ipv6_non_link_json);
+ for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link, node,
+ ip_addr)) {
+ snprintfrr(buf_prx, INET6_BUFSIZ, "%pFX",
+ ip_addr);
+ json_object_string_add(ipv6_non_link_json,
+ "ipv6", buf_prx);
+ }
+ }
+ }
+ return;
+}
+
void isis_circuit_print_vty(struct isis_circuit *circuit, struct vty *vty,
char detail)
{
diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h
index 746578084..5ff0390c2 100644
--- a/isisd/isis_circuit.h
+++ b/isisd/isis_circuit.h
@@ -206,6 +206,8 @@ void isis_circuit_down(struct isis_circuit *);
void circuit_update_nlpids(struct isis_circuit *circuit);
void isis_circuit_print_vty(struct isis_circuit *circuit, struct vty *vty,
char detail);
+void isis_circuit_print_json(struct isis_circuit *circuit,
+ struct json_object *json, char detail);
size_t isis_circuit_pdu_size(struct isis_circuit *circuit);
void isis_circuit_stream(struct isis_circuit *circuit, struct stream **stream);
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index 463d26f6c..eb7e9e725 100644
--- a/isisd/isis_lsp.c
+++ b/isisd/isis_lsp.c
@@ -733,8 +733,48 @@ static const char *lsp_bits2string(uint8_t lsp_bits, char *buf, size_t buf_size)
}
/* this function prints the lsp on show isis database */
-void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost,
- struct isis *isis)
+void lsp_print_common(struct isis_lsp *lsp, struct vty *vty, struct json_object *json,
+ char dynhost, struct isis *isis)
+{
+ if (json) {
+ return lsp_print_json(lsp, json, dynhost, isis);
+ } else {
+ return lsp_print_vty(lsp, vty, dynhost, isis);
+ }
+}
+
+void lsp_print_json(struct isis_lsp *lsp, struct json_object *json,
+ char dynhost, struct isis *isis)
+{
+ char LSPid[255];
+ char age_out[8];
+ char b[200];
+ json_object *own_json;
+ char buf[256];
+
+ lspid_print(lsp->hdr.lsp_id, LSPid, sizeof(LSPid), dynhost, 1, isis);
+ own_json = json_object_new_object();
+ json_object_object_add(json, "lsp", own_json);
+ json_object_string_add(own_json, "id", LSPid);
+ json_object_string_add(own_json, "own", lsp->own_lsp ? "*" : " ");
+ json_object_int_add(json, "pdu-len", lsp->hdr.pdu_len);
+ snprintfrr(buf, sizeof(buf), "0x%08x", lsp->hdr.seqno);
+ json_object_string_add(json, "seq-number", buf);
+ snprintfrr(buf, sizeof(buf), "0x%04hx", lsp->hdr.checksum);
+ json_object_string_add(json, "chksum", buf);
+ if (lsp->hdr.rem_lifetime == 0) {
+ snprintf(age_out, sizeof(age_out), "(%d)", lsp->age_out);
+ age_out[7] = '\0';
+ json_object_string_add(json, "holdtime", age_out);
+ } else {
+ json_object_int_add(json, "holdtime", lsp->hdr.rem_lifetime);
+ }
+ json_object_string_add(
+ json, "att-p-ol", lsp_bits2string(lsp->hdr.lsp_bits, b, sizeof(b)));
+}
+
+void lsp_print_vty(struct isis_lsp *lsp, struct vty *vty,
+ char dynhost, struct isis *isis)
{
char LSPid[255];
char age_out[8];
@@ -754,30 +794,40 @@ void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost,
vty_out(vty, "%s\n", lsp_bits2string(lsp->hdr.lsp_bits, b, sizeof(b)));
}
-void lsp_print_detail(struct isis_lsp *lsp, struct vty *vty, char dynhost,
- struct isis *isis)
+void lsp_print_detail(struct isis_lsp *lsp, struct vty *vty,
+ struct json_object *json, char dynhost,
+ struct isis *isis)
{
- lsp_print(lsp, vty, dynhost, isis);
- if (lsp->tlvs)
- vty_multiline(vty, " ", "%s", isis_format_tlvs(lsp->tlvs));
- vty_out(vty, "\n");
+ if (json) {
+ lsp_print_json(lsp, json, dynhost, isis);
+ if (lsp->tlvs) {
+ isis_format_tlvs(lsp->tlvs, json);
+ }
+ } else {
+ lsp_print_vty(lsp, vty, dynhost, isis);
+ if (lsp->tlvs)
+ vty_multiline(vty, " ", "%s",
+ isis_format_tlvs(lsp->tlvs, NULL));
+ vty_out(vty, "\n");
+ }
}
/* print all the lsps info in the local lspdb */
-int lsp_print_all(struct vty *vty, struct lspdb_head *head, char detail,
- char dynhost, struct isis *isis)
+int lsp_print_all(struct vty *vty, struct json_object *json,
+ struct lspdb_head *head, char detail, char dynhost,
+ struct isis *isis)
{
struct isis_lsp *lsp;
int lsp_count = 0;
if (detail == ISIS_UI_LEVEL_BRIEF) {
frr_each (lspdb, head, lsp) {
- lsp_print(lsp, vty, dynhost, isis);
+ lsp_print_common(lsp, vty, json, dynhost, isis);
lsp_count++;
}
} else if (detail == ISIS_UI_LEVEL_DETAIL) {
frr_each (lspdb, head, lsp) {
- lsp_print_detail(lsp, vty, dynhost, isis);
+ lsp_print_detail(lsp, vty, json, dynhost, isis);
lsp_count++;
}
}
@@ -1264,7 +1314,7 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
if (!fragments) {
zlog_warn("BUG: could not fragment own LSP:");
log_multiline(LOG_WARNING, " ", "%s",
- isis_format_tlvs(tlvs));
+ isis_format_tlvs(tlvs, NULL));
isis_free_tlvs(tlvs);
return;
}
diff --git a/isisd/isis_lsp.h b/isisd/isis_lsp.h
index f42d702b3..b13b2a35e 100644
--- a/isisd/isis_lsp.h
+++ b/isisd/isis_lsp.h
@@ -120,12 +120,19 @@ void lsp_update(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr,
void lsp_inc_seqno(struct isis_lsp *lsp, uint32_t seqno);
void lspid_print(uint8_t *lsp_id, char *dest, size_t dest_len, char dynhost,
char frag, struct isis *isis);
-void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost,
- struct isis *isis);
-void lsp_print_detail(struct isis_lsp *lsp, struct vty *vty, char dynhost,
+void lsp_print_common(struct isis_lsp *lsp, struct vty *vty,
+ struct json_object *json, char dynhost,
struct isis *isis);
-int lsp_print_all(struct vty *vty, struct lspdb_head *head, char detail,
- char dynhost, struct isis *isis);
+void lsp_print_vty(struct isis_lsp *lsp, struct vty *vty, char dynhost,
+ struct isis *isis);
+void lsp_print_json(struct isis_lsp *lsp, struct json_object *json,
+ char dynhost, struct isis *isis);
+void lsp_print_detail(struct isis_lsp *lsp, struct vty *vty,
+ struct json_object *json, char dynhost,
+ struct isis *isis);
+int lsp_print_all(struct vty *vty, struct json_object *json,
+ struct lspdb_head *head, char detail, char dynhost,
+ struct isis *isis);
/* sets SRMflags for all active circuits of an lsp */
void lsp_set_all_srmflags(struct isis_lsp *lsp, bool set);
diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c
index 517c9ec5a..1a54d47f3 100644
--- a/isisd/isis_pdu.c
+++ b/isisd/isis_pdu.c
@@ -2209,7 +2209,7 @@ int send_csnp(struct isis_circuit *circuit, int level)
circuit->interface->name,
stream_get_endp(circuit->snd_stream));
log_multiline(LOG_DEBUG, " ", "%s",
- isis_format_tlvs(tlvs));
+ isis_format_tlvs(tlvs, NULL));
if (IS_DEBUG_PACKET_DUMP)
zlog_dump_data(
STREAM_DATA(circuit->snd_stream),
@@ -2368,7 +2368,7 @@ static int send_psnp(int level, struct isis_circuit *circuit)
circuit->interface->name,
stream_get_endp(circuit->snd_stream));
log_multiline(LOG_DEBUG, " ", "%s",
- isis_format_tlvs(tlvs));
+ isis_format_tlvs(tlvs, NULL));
if (IS_DEBUG_PACKET_DUMP)
zlog_dump_data(
STREAM_DATA(circuit->snd_stream),
diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c
index 04b5cf1a6..d5b02f388 100644
--- a/isisd/isis_spf.c
+++ b/isisd/isis_spf.c
@@ -2683,3 +2683,15 @@ void isis_spf_print(struct isis_spftree *spftree, struct vty *vty)
vty_out(vty, " run count : %u\n", spftree->runcount);
}
+void isis_spf_print_json(struct isis_spftree *spftree, struct json_object *json)
+{
+ char uptime[MONOTIME_STRLEN];
+ time_t cur;
+ cur = time(NULL);
+ cur -= spftree->last_run_timestamp;
+ frrtime_to_interval(cur, uptime, sizeof(uptime));
+ json_object_string_add(json, "last-run-elapsed", uptime);
+ json_object_int_add(json, "last-run-duration-usec",
+ spftree->last_run_duration);
+ json_object_int_add(json, "last-run-count", spftree->runcount);
+}
diff --git a/isisd/isis_spf.h b/isisd/isis_spf.h
index 5b3aa5937..815db7b22 100644
--- a/isisd/isis_spf.h
+++ b/isisd/isis_spf.h
@@ -75,6 +75,8 @@ void isis_print_routes(struct vty *vty, struct isis_spftree *spftree,
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,
+ struct json_object *json);
void isis_run_spf(struct isis_spftree *spftree);
struct isis_spftree *isis_run_hopcount_spf(struct isis_area *area,
uint8_t *sysid,
diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c
index f1aae7caf..d3d59fb43 100644
--- a/isisd/isis_tlvs.c
+++ b/isisd/isis_tlvs.c
@@ -22,6 +22,7 @@
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
+#include <json-c/json_object.h>
#include <zebra.h>
#ifdef CRYPTO_INTERNAL
@@ -57,7 +58,8 @@ typedef void (*free_item_func)(struct isis_item *i);
typedef int (*unpack_item_func)(uint16_t mtid, uint8_t len, struct stream *s,
struct sbuf *log, void *dest, int indent);
typedef void (*format_item_func)(uint16_t mtid, struct isis_item *i,
- struct sbuf *buf, int indent);
+ struct sbuf *buf, struct json_object *json,
+ int indent);
typedef struct isis_item *(*copy_item_func)(struct isis_item *i);
struct tlv_ops {
@@ -208,152 +210,430 @@ copy_item_ext_subtlvs(struct isis_ext_subtlvs *exts, uint16_t mtid)
/* mtid parameter is used to manage multi-topology i.e. IPv4 / IPv6 */
static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
- struct sbuf *buf, int indent,
- uint16_t mtid)
+ struct sbuf *buf, struct json_object *json,
+ int indent, uint16_t mtid)
{
+ char aux_buf[255];
+ char cnt_buf[255];
/* Standard metrics */
- if (IS_SUBTLV(exts, EXT_ADM_GRP))
- sbuf_push(buf, indent, "Administrative Group: 0x%x\n",
- exts->adm_group);
+ if (IS_SUBTLV(exts, EXT_ADM_GRP)) {
+ if (json) {
+ snprintfrr(aux_buf, sizeof(aux_buf), "0x%x",
+ exts->adm_group);
+ json_object_string_add(json, "adm-group", aux_buf);
+ } else
+ sbuf_push(buf, indent, "Administrative Group: 0x%x\n",
+ exts->adm_group);
+ }
if (IS_SUBTLV(exts, EXT_LLRI)) {
- sbuf_push(buf, indent, "Link Local ID: %u\n",
- exts->local_llri);
- sbuf_push(buf, indent, "Link Remote ID: %u\n",
- exts->remote_llri);
- }
- if (IS_SUBTLV(exts, EXT_LOCAL_ADDR))
- sbuf_push(buf, indent, "Local Interface IP Address(es): %pI4\n",
- &exts->local_addr);
- if (IS_SUBTLV(exts, EXT_NEIGH_ADDR))
- sbuf_push(buf, indent,
- "Remote Interface IP Address(es): %pI4\n",
- &exts->neigh_addr);
- if (IS_SUBTLV(exts, EXT_LOCAL_ADDR6))
- sbuf_push(buf, indent,
- "Local Interface IPv6 Address(es): %pI6\n",
- &exts->local_addr6);
- if (IS_SUBTLV(exts, EXT_NEIGH_ADDR6))
- sbuf_push(buf, indent,
- "Remote Interface IPv6 Address(es): %pI6\n",
- &exts->neigh_addr6);
- if (IS_SUBTLV(exts, EXT_MAX_BW))
- sbuf_push(buf, indent, "Maximum Bandwidth: %g (Bytes/sec)\n",
- exts->max_bw);
- if (IS_SUBTLV(exts, EXT_MAX_RSV_BW))
- sbuf_push(buf, indent,
- "Maximum Reservable Bandwidth: %g (Bytes/sec)\n",
- exts->max_rsv_bw);
+ if (json) {
+ json_object_int_add(json, "link-local-id",
+ exts->local_llri);
+ json_object_int_add(json, "link-remote-id",
+ exts->remote_llri);
+ } else {
+ sbuf_push(buf, indent, "Link Local ID: %u\n",
+ exts->local_llri);
+ sbuf_push(buf, indent, "Link Remote ID: %u\n",
+ exts->remote_llri);
+ }
+ }
+ if (IS_SUBTLV(exts, EXT_LOCAL_ADDR)) {
+ if (json) {
+ inet_ntop(AF_INET, &exts->local_addr, aux_buf,
+ sizeof(aux_buf));
+ json_object_string_add(json, "local-iface-ip", aux_buf);
+ } else
+ sbuf_push(buf, indent,
+ "Local Interface IP Address(es): %pI4\n",
+ &exts->local_addr);
+ }
+ if (IS_SUBTLV(exts, EXT_NEIGH_ADDR)) {
+ if (json) {
+ inet_ntop(AF_INET, &exts->neigh_addr, aux_buf,
+ sizeof(aux_buf));
+ json_object_string_add(json, "remote-iface-ip",
+ aux_buf);
+ } else
+ sbuf_push(buf, indent,
+ "Remote Interface IP Address(es): %pI4\n",
+ &exts->neigh_addr);
+ }
+ if (IS_SUBTLV(exts, EXT_LOCAL_ADDR6)) {
+ if (json) {
+ inet_ntop(AF_INET6, &exts->local_addr6, aux_buf,
+ sizeof(aux_buf));
+ json_object_string_add(json, "local-iface-ipv6",
+ aux_buf);
+ } else
+ sbuf_push(buf, indent,
+ "Local Interface IPv6 Address(es): %pI6\n",
+ &exts->local_addr6);
+ }
+ if (IS_SUBTLV(exts, EXT_NEIGH_ADDR6)) {
+ if (json) {
+ inet_ntop(AF_INET6, &exts->neigh_addr6, aux_buf,
+ sizeof(aux_buf));
+ json_object_string_add(json, "remote-iface-ipv6",
+ aux_buf);
+ } else
+ sbuf_push(buf, indent,
+ "Remote Interface IPv6 Address(es): %pI6\n",
+ &exts->neigh_addr6);
+ }
+ if (IS_SUBTLV(exts, EXT_MAX_BW)) {
+ if (json) {
+ snprintfrr(aux_buf, sizeof(aux_buf), "%g",
+ exts->max_bw);
+ json_object_string_add(json, "max-bandwith-bytes-sec",
+ aux_buf);
+ } else
+ sbuf_push(buf, indent,
+ "Maximum Bandwidth: %g (Bytes/sec)\n",
+ exts->max_bw);
+ }
+ if (IS_SUBTLV(exts, EXT_MAX_RSV_BW)) {
+ if (json) {
+ snprintfrr(aux_buf, sizeof(aux_buf), "%g",
+ exts->max_rsv_bw);
+ json_object_string_add(
+ json, "max-res-bandwith-bytes-sec", aux_buf);
+ } else
+ sbuf_push(
+ buf, indent,
+ "Maximum Reservable Bandwidth: %g (Bytes/sec)\n",
+ exts->max_rsv_bw);
+ }
if (IS_SUBTLV(exts, EXT_UNRSV_BW)) {
- sbuf_push(buf, indent, "Unreserved Bandwidth:\n");
- for (int j = 0; j < MAX_CLASS_TYPE; j += 2) {
- sbuf_push(buf, indent + 2,
- "[%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n",
- j, exts->unrsv_bw[j],
- j + 1, exts->unrsv_bw[j + 1]);
+ if (json) {
+ struct json_object *unrsv_json;
+ unrsv_json = json_object_new_object();
+ json_object_object_add(json, "unrsv-bandwith-bytes-sec",
+ unrsv_json);
+ for (int j = 0; j < MAX_CLASS_TYPE; j += 1) {
+ snprintfrr(cnt_buf, sizeof(cnt_buf), "%d", j);
+ snprintfrr(aux_buf, sizeof(aux_buf), "%g",
+ exts->unrsv_bw[j]);
+ json_object_string_add(unrsv_json, cnt_buf,
+ aux_buf);
+ }
+ } else {
+ sbuf_push(buf, indent, "Unreserved Bandwidth:\n");
+ for (int j = 0; j < MAX_CLASS_TYPE; j += 2) {
+ sbuf_push(
+ buf, indent + 2,
+ "[%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n",
+ j, exts->unrsv_bw[j], j + 1,
+ exts->unrsv_bw[j + 1]);
+ }
}
}
- if (IS_SUBTLV(exts, EXT_TE_METRIC))
- sbuf_push(buf, indent, "Traffic Engineering Metric: %u\n",
- exts->te_metric);
- if (IS_SUBTLV(exts, EXT_RMT_AS))
- sbuf_push(buf, indent,
- "Inter-AS TE Remote AS number: %u\n",
- exts->remote_as);
- if (IS_SUBTLV(exts, EXT_RMT_IP))
- sbuf_push(buf, indent,
- "Inter-AS TE Remote ASBR IP address: %pI4\n",
- &exts->remote_ip);
+ if (IS_SUBTLV(exts, EXT_TE_METRIC)) {
+ if (json) {
+ json_object_int_add(json, "te-metric", exts->te_metric);
+ } else
+ sbuf_push(buf, indent,
+ "Traffic Engineering Metric: %u\n",
+ exts->te_metric);
+ }
+ if (IS_SUBTLV(exts, EXT_RMT_AS)) {
+ if (json) {
+ json_object_int_add(json, "inter-as-te-remote-as",
+ exts->remote_as);
+ } else
+ sbuf_push(buf, indent,
+ "Inter-AS TE Remote AS number: %u\n",
+ exts->remote_as);
+ }
+ if (IS_SUBTLV(exts, EXT_RMT_IP)) {
+ if (json) {
+ inet_ntop(AF_INET6, &exts->remote_ip, aux_buf,
+ sizeof(aux_buf));
+ json_object_string_add(
+ json, "inter-as-te-remote-asbr-ip", aux_buf);
+ } else
+ sbuf_push(buf, indent,
+ "Inter-AS TE Remote ASBR IP address: %pI4\n",
+ &exts->remote_ip);
+ }
/* Extended metrics */
- if (IS_SUBTLV(exts, EXT_DELAY))
- sbuf_push(buf, indent,
- "%s Average Link Delay: %u (micro-sec)\n",
- IS_ANORMAL(exts->delay) ? "Anomalous" : "Normal",
- exts->delay);
+ if (IS_SUBTLV(exts, EXT_DELAY)) {
+ if (json) {
+ struct json_object *avg_json;
+ avg_json = json_object_new_object();
+ json_object_object_add(json, "avg-delay", avg_json);
+ json_object_string_add(avg_json, "delay",
+ IS_ANORMAL(exts->delay)
+ ? "Anomalous"
+ : "Normal");
+ json_object_int_add(avg_json, "micro-sec", exts->delay);
+ } else
+ sbuf_push(buf, indent,
+ "%s Average Link Delay: %u (micro-sec)\n",
+ IS_ANORMAL(exts->delay) ? "Anomalous"
+ : "Normal",
+ exts->delay);
+ }
if (IS_SUBTLV(exts, EXT_MM_DELAY)) {
- sbuf_push(buf, indent, "%s Min/Max Link Delay: %u / %u (micro-sec)\n",
- IS_ANORMAL(exts->min_delay) ? "Anomalous" : "Normal",
- exts->min_delay & TE_EXT_MASK,
- exts->max_delay & TE_EXT_MASK);
+ if (json) {
+ struct json_object *avg_json;
+ avg_json = json_object_new_object();
+ json_object_object_add(json, "max-min-delay", avg_json);
+ json_object_string_add(avg_json, "delay",
+ IS_ANORMAL(exts->min_delay)
+ ? "Anomalous"
+ : "Normal");
+ snprintfrr(aux_buf, sizeof(aux_buf), "%u / %u",
+ exts->min_delay & TE_EXT_MASK,
+ exts->max_delay & TE_EXT_MASK);
+ json_object_string_add(avg_json, "micro-sec", aux_buf);
+
+ } else
+ sbuf_push(
+ buf, indent,
+ "%s Min/Max Link Delay: %u / %u (micro-sec)\n",
+ IS_ANORMAL(exts->min_delay) ? "Anomalous"
+ : "Normal",
+ exts->min_delay & TE_EXT_MASK,
+ exts->max_delay & TE_EXT_MASK);
}
if (IS_SUBTLV(exts, EXT_DELAY_VAR)) {
- sbuf_push(buf, indent,
- "Delay Variation: %u (micro-sec)\n",
- exts->delay_var & TE_EXT_MASK);
- }
- if (IS_SUBTLV(exts, EXT_PKT_LOSS))
- sbuf_push(buf, indent, "%s Link Packet Loss: %g (%%)\n",
- IS_ANORMAL(exts->pkt_loss) ? "Anomalous" : "Normal",
- (float)((exts->pkt_loss & TE_EXT_MASK)
- * LOSS_PRECISION));
- if (IS_SUBTLV(exts, EXT_RES_BW))
- sbuf_push(buf, indent,
- "Unidir. Residual Bandwidth: %g (Bytes/sec)\n",
- exts->res_bw);
- if (IS_SUBTLV(exts, EXT_AVA_BW))
- sbuf_push(buf, indent,
- "Unidir. Available Bandwidth: %g (Bytes/sec)\n",
- exts->ava_bw);
- if (IS_SUBTLV(exts, EXT_USE_BW))
- sbuf_push(buf, indent,
- "Unidir. Utilized Bandwidth: %g (Bytes/sec)\n",
- exts->use_bw);
+ if (json) {
+ json_object_int_add(json, "delay-variation-micro-sec",
+ exts->delay_var & TE_EXT_MASK);
+ } else
+ sbuf_push(buf, indent,
+ "Delay Variation: %u (micro-sec)\n",
+ exts->delay_var & TE_EXT_MASK);
+ }
+ if (IS_SUBTLV(exts, EXT_PKT_LOSS)) {
+ if (json) {
+ snprintfrr(aux_buf, sizeof(aux_buf), "%g",
+ (float)((exts->pkt_loss & TE_EXT_MASK) *
+ LOSS_PRECISION));
+ struct json_object *link_json;
+ link_json = json_object_new_object();
+ json_object_object_add(json, "link-packet-loss",
+ link_json);
+ json_object_string_add(link_json, "loss",
+ IS_ANORMAL(exts->pkt_loss)
+ ? "Anomalous"
+ : "Normal");
+ json_object_string_add(link_json, "percentaje",
+ aux_buf);
+ } else
+ sbuf_push(buf, indent, "%s Link Packet Loss: %g (%%)\n",
+ IS_ANORMAL(exts->pkt_loss) ? "Anomalous"
+ : "Normal",
+ (float)((exts->pkt_loss & TE_EXT_MASK) *
+ LOSS_PRECISION));
+ }
+ if (IS_SUBTLV(exts, EXT_RES_BW)) {
+ if (json) {
+ snprintfrr(aux_buf, sizeof(aux_buf), "%g",
+ (exts->res_bw));
+ json_object_string_add(json,
+ "unidir-residual-band-bytes-sec",
+ aux_buf);
+ } else
+ sbuf_push(
+ buf, indent,
+ "Unidir. Residual Bandwidth: %g (Bytes/sec)\n",
+ exts->res_bw);
+ }
+ if (IS_SUBTLV(exts, EXT_AVA_BW)) {
+ if (json) {
+ snprintfrr(aux_buf, sizeof(aux_buf), "%g",
+ (exts->ava_bw));
+ json_object_string_add(
+ json, "unidir-available-band-bytes-sec",
+ aux_buf);
+ } else
+ sbuf_push(
+ buf, indent,
+ "Unidir. Available Bandwidth: %g (Bytes/sec)\n",
+ exts->ava_bw);
+ }
+ if (IS_SUBTLV(exts, EXT_USE_BW)) {
+ if (json) {
+ snprintfrr(aux_buf, sizeof(aux_buf), "%g",
+ (exts->use_bw));
+ json_object_string_add(json,
+ "unidir-utilized-band-bytes-sec",
+ aux_buf);
+ } else
+ sbuf_push(
+ buf, indent,
+ "Unidir. Utilized Bandwidth: %g (Bytes/sec)\n",
+ exts->use_bw);
+ }
/* Segment Routing Adjacency as per RFC8667 section #2.2.1 */
if (IS_SUBTLV(exts, EXT_ADJ_SID)) {
struct isis_adj_sid *adj;
- for (adj = (struct isis_adj_sid *)exts->adj_sid.head; adj;
- adj = adj->next) {
- sbuf_push(
- buf, indent,
- "Adjacency-SID: %u, Weight: %hhu, Flags: F:%c B:%c, V:%c, L:%c, S:%c, P:%c\n",
- adj->sid, adj->weight,
- adj->flags & EXT_SUBTLV_LINK_ADJ_SID_FFLG ? '1'
- : '0',
- adj->flags & EXT_SUBTLV_LINK_ADJ_SID_BFLG ? '1'
- : '0',
- adj->flags & EXT_SUBTLV_LINK_ADJ_SID_VFLG ? '1'
- : '0',
- adj->flags & EXT_SUBTLV_LINK_ADJ_SID_LFLG ? '1'
- : '0',
- adj->flags & EXT_SUBTLV_LINK_ADJ_SID_SFLG ? '1'
- : '0',
- adj->flags & EXT_SUBTLV_LINK_ADJ_SID_PFLG
- ? '1'
- : '0');
- }
+ if (json) {
+ struct json_object *arr_adj_json, *flags_json;
+ arr_adj_json = json_object_new_array();
+ json_object_object_add(json, "adj-sid", arr_adj_json);
+ for (adj = (struct isis_adj_sid *)exts->adj_sid.head;
+ adj; adj = adj->next) {
+ snprintfrr(cnt_buf, sizeof(cnt_buf), "%d",
+ adj->sid);
+ flags_json = json_object_new_object();
+ json_object_int_add(flags_json, "sid",
+ adj->sid);
+ json_object_int_add(flags_json, "weight",
+ adj->weight);
+ json_object_string_add(
+ flags_json, "flag-f",
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_FFLG
+ ? "1"
+ : "0");
+ json_object_string_add(
+ flags_json, "flag-b",
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_BFLG
+ ? "1"
+ : "0");
+ json_object_string_add(
+ flags_json, "flag-v",
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_VFLG
+ ? "1"
+ : "0");
+ json_object_string_add(
+ flags_json, "flag-l",
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_LFLG
+ ? "1"
+ : "0");
+ json_object_string_add(
+ flags_json, "flag-s",
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_SFLG
+ ? "1"
+ : "0");
+ json_object_string_add(
+ flags_json, "flag-p",
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_PFLG
+ ? "1"
+ : "0");
+ json_object_array_add(arr_adj_json, flags_json);
+ }
+ } else
+ for (adj = (struct isis_adj_sid *)exts->adj_sid.head;
+ adj; adj = adj->next) {
+ sbuf_push(
+ buf, indent,
+ "Adjacency-SID: %u, Weight: %hhu, Flags: F:%c B:%c, V:%c, L:%c, S:%c, P:%c\n",
+ adj->sid, adj->weight,
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_FFLG
+ ? '1'
+ : '0',
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_BFLG
+ ? '1'
+ : '0',
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_VFLG
+ ? '1'
+ : '0',
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_LFLG
+ ? '1'
+ : '0',
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_SFLG
+ ? '1'
+ : '0',
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_PFLG
+ ? '1'
+ : '0');
+ }
}
/* Segment Routing LAN-Adjacency as per RFC8667 section #2.2.2 */
if (IS_SUBTLV(exts, EXT_LAN_ADJ_SID)) {
struct isis_lan_adj_sid *lan;
-
- for (lan = (struct isis_lan_adj_sid *)exts->lan_sid.head;
- lan; lan = lan->next) {
- continue;
- sbuf_push(buf, indent,
- "Lan-Adjacency-SID: %u, Weight: %hhu, Flags: F:%c B:%c, V:%c, L:%c, S:%c, P:%c\n"
- " Neighbor-ID: %s\n",
- lan->sid, lan->weight,
- lan->flags & EXT_SUBTLV_LINK_ADJ_SID_FFLG
- ? '1'
- : '0',
- lan->flags & EXT_SUBTLV_LINK_ADJ_SID_BFLG
- ? '1'
- : '0',
- lan->flags & EXT_SUBTLV_LINK_ADJ_SID_VFLG
- ? '1'
- : '0',
- lan->flags & EXT_SUBTLV_LINK_ADJ_SID_LFLG
- ? '1'
- : '0',
- lan->flags & EXT_SUBTLV_LINK_ADJ_SID_SFLG
- ? '1'
- : '0',
- lan->flags & EXT_SUBTLV_LINK_ADJ_SID_PFLG
- ? '1'
- : '0',
- isis_format_id(lan->neighbor_id, 6));
- }
+ if (json) {
+ struct json_object *arr_adj_json, *flags_json;
+ arr_adj_json = json_object_new_array();
+ json_object_object_add(json, "lan-adj-sid",
+ arr_adj_json);
+ for (lan = (struct isis_lan_adj_sid *)
+ exts->adj_sid.head;
+ lan; lan = lan->next) {
+ if (((mtid == ISIS_MT_IPV4_UNICAST) &&
+ (lan->family != AF_INET)) ||
+ ((mtid == ISIS_MT_IPV6_UNICAST) &&
+ (lan->family != AF_INET6)))
+ continue;
+ snprintfrr(cnt_buf, sizeof(cnt_buf), "%d",
+ lan->sid);
+ flags_json = json_object_new_object();
+ json_object_int_add(flags_json, "sid",
+ lan->sid);
+ json_object_int_add(flags_json, "weight",
+ lan->weight);
+ json_object_string_add(
+ flags_json, "flag-f",
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_FFLG
+ ? "1"
+ : "0");
+ json_object_string_add(
+ flags_json, "flag-b",
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_BFLG
+ ? "1"
+ : "0");
+ json_object_string_add(
+ flags_json, "flag-v",
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_VFLG
+ ? "1"
+ : "0");
+ json_object_string_add(
+ flags_json, "flag-l",
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_LFLG
+ ? "1"
+ : "0");
+ json_object_string_add(
+ flags_json, "flag-s",
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_SFLG
+ ? "1"
+ : "0");
+ json_object_string_add(
+ flags_json, "flag-p",
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_PFLG
+ ? "1"
+ : "0");
+ json_object_array_add(arr_adj_json, flags_json);
+ }
+ } else
+
+ for (lan = (struct isis_lan_adj_sid *)
+ exts->lan_sid.head;
+ lan; lan = lan->next) {
+ if (((mtid == ISIS_MT_IPV4_UNICAST) &&
+ (lan->family != AF_INET)) ||
+ ((mtid == ISIS_MT_IPV6_UNICAST) &&
+ (lan->family != AF_INET6)))
+ continue;
+ sbuf_push(
+ buf, indent,
+ "Lan-Adjacency-SID: %u, Weight: %hhu, Flags: F:%c B:%c, V:%c, L:%c, S:%c, P:%c\n"
+ " Neighbor-ID: %s\n",
+ lan->sid, lan->weight,
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_FFLG
+ ? '1'
+ : '0',
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_BFLG
+ ? '1'
+ : '0',
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_VFLG
+ ? '1'
+ : '0',
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_LFLG
+ ? '1'
+ : '0',
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_SFLG
+ ? '1'
+ : '0',
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_PFLG
+ ? '1'
+ : '0',
+ isis_format_id(lan->neighbor_id, 6));
+ }
}
}
@@ -880,26 +1160,64 @@ static struct isis_item *copy_item_prefix_sid(struct isis_item *i)
}
static void format_item_prefix_sid(uint16_t mtid, struct isis_item *i,
- struct sbuf *buf, int indent)
+ struct sbuf *buf, struct json_object *json,
+ int indent)
{
struct isis_prefix_sid *sid = (struct isis_prefix_sid *)i;
- sbuf_push(buf, indent, "SR Prefix-SID ");
- if (sid->flags & ISIS_PREFIX_SID_VALUE) {
- sbuf_push(buf, 0, "Label: %u, ", sid->value);
+ if (json) {
+ struct json_object *sr_json;
+ sr_json = json_object_new_object();
+ json_object_object_add(json, "sr", sr_json);
+ if (sid->flags & ISIS_PREFIX_SID_VALUE) {
+ json_object_int_add(sr_json, "label", sid->value);
+ } else {
+ json_object_int_add(sr_json, "index", sid->value);
+ }
+ json_object_int_add(sr_json, "alg", sid->algorithm);
+ json_object_string_add(
+ sr_json, "readvertised",
+ ((sid->flags & ISIS_PREFIX_SID_READVERTISED) ? "yes"
+ : ""));
+ json_object_string_add(
+ sr_json, "node",
+ ((sid->flags & ISIS_PREFIX_SID_NODE) ? "yes" : ""));
+ json_object_string_add(sr_json, "php",
+ ((sid->flags & ISIS_PREFIX_SID_NO_PHP)
+ ? "no-php"
+ : "php"));
+ json_object_string_add(
+ sr_json, "explicit-null",
+ ((sid->flags & ISIS_PREFIX_SID_EXPLICIT_NULL) ? "yes"
+ : ""));
+ json_object_string_add(
+ sr_json, "value",
+ ((sid->flags & ISIS_PREFIX_SID_VALUE) ? "yes" : ""));
+ json_object_string_add(
+ sr_json, "local",
+ ((sid->flags & ISIS_PREFIX_SID_LOCAL) ? "yes" : ""));
+
} else {
- sbuf_push(buf, 0, "Index: %u, ", sid->value);
+ sbuf_push(buf, indent, "SR Prefix-SID ");
+ if (sid->flags & ISIS_PREFIX_SID_VALUE) {
+ sbuf_push(buf, 0, "Label: %u, ", sid->value);
+ } else {
+ sbuf_push(buf, 0, "Index: %u, ", sid->value);
+ }
+ sbuf_push(buf, 0, "Algorithm: %hhu, ", sid->algorithm);
+ sbuf_push(buf, 0, "Flags:%s%s%s%s%s%s\n",
+ sid->flags & ISIS_PREFIX_SID_READVERTISED
+ ? " READVERTISED"
+ : "",
+ sid->flags & ISIS_PREFIX_SID_NODE ? " NODE" : "",
+ sid->flags & ISIS_PREFIX_SID_NO_PHP ? " NO-PHP"
+ : " PHP",
+ sid->flags & ISIS_PREFIX_SID_EXPLICIT_NULL
+ ? " EXPLICIT-NULL"
+ : "",
+ sid->flags & ISIS_PREFIX_SID_VALUE ? " VALUE" : "",
+ sid->flags & ISIS_PREFIX_SID_LOCAL ? " LOCAL" : "");
}
- sbuf_push(buf, 0, "Algorithm: %hhu, ", sid->algorithm);
- sbuf_push(buf, 0, "Flags:%s%s%s%s%s%s\n",
- sid->flags & ISIS_PREFIX_SID_READVERTISED ? " READVERTISED"
- : "",
- sid->flags & ISIS_PREFIX_SID_NODE ? " NODE" : "",
- sid->flags & ISIS_PREFIX_SID_NO_PHP ? " NO-PHP" : " PHP",
- sid->flags & ISIS_PREFIX_SID_EXPLICIT_NULL ? " EXPLICIT-NULL"
- : "",
- sid->flags & ISIS_PREFIX_SID_VALUE ? " VALUE" : "",
- sid->flags & ISIS_PREFIX_SID_LOCAL ? " LOCAL" : "");
}
static void free_item_prefix_sid(struct isis_item *i)
@@ -977,7 +1295,7 @@ static int unpack_item_prefix_sid(uint16_t mtid, uint8_t len, struct stream *s,
sid.value = stream_getl(s);
}
- format_item_prefix_sid(mtid, (struct isis_item *)&sid, log, indent + 2);
+ format_item_prefix_sid(mtid, (struct isis_item *)&sid, log, NULL, indent + 2);
append_item(&subtlvs->prefix_sids, copy_item_prefix_sid((struct isis_item *)&sid));
return 0;
}
@@ -997,14 +1315,21 @@ static struct prefix_ipv6 *copy_subtlv_ipv6_source_prefix(struct prefix_ipv6 *p)
}
static void format_subtlv_ipv6_source_prefix(struct prefix_ipv6 *p,
- struct sbuf *buf, int indent)
+ struct sbuf *buf,
+ struct json_object *json,
+ int indent)
{
if (!p)
return;
char prefixbuf[PREFIX2STR_BUFFER];
- sbuf_push(buf, indent, "IPv6 Source Prefix: %s\n",
- prefix2str(p, prefixbuf, sizeof(prefixbuf)));
+ if (json) {
+ prefix2str(p, prefixbuf, sizeof(prefixbuf));
+ json_object_string_add(json, "ipv6-src-prefix", prefixbuf);
+ } else {
+ sbuf_push(buf, indent, "IPv6 Source Prefix: %s\n",
+ prefix2str(p, prefixbuf, sizeof(prefixbuf)));
+ }
}
static int pack_subtlv_ipv6_source_prefix(struct prefix_ipv6 *p,
@@ -1080,7 +1405,8 @@ static void copy_items(enum isis_tlv_context context, enum isis_tlv_type type,
struct isis_item_list *src, struct isis_item_list *dest);
static void format_items_(uint16_t mtid, enum isis_tlv_context context,
enum isis_tlv_type type, struct isis_item_list *items,
- struct sbuf *buf, int indent);
+ struct sbuf *buf, struct json_object *json,
+ int indent);
#define format_items(...) format_items_(ISIS_MT_IPV4_UNICAST, __VA_ARGS__)
static void free_items(enum isis_tlv_context context, enum isis_tlv_type type,
struct isis_item_list *items);
@@ -1124,12 +1450,12 @@ static struct isis_subtlvs *copy_subtlvs(struct isis_subtlvs *subtlvs)
}
static void format_subtlvs(struct isis_subtlvs *subtlvs, struct sbuf *buf,
- int indent)
+ struct json_object *json, int indent)
{
format_items(subtlvs->context, ISIS_SUBTLV_PREFIX_SID,
- &subtlvs->prefix_sids, buf, indent);
+ &subtlvs->prefix_sids, buf, json, indent);
- format_subtlv_ipv6_source_prefix(subtlvs->source_prefix, buf, indent);
+ format_subtlv_ipv6_source_prefix(subtlvs->source_prefix, buf, json, indent);
}
static void isis_free_subtlvs(struct isis_subtlvs *subtlvs)
@@ -1189,12 +1515,18 @@ static struct isis_item *copy_item_area_address(struct isis_item *i)
}
static void format_item_area_address(uint16_t mtid, struct isis_item *i,
- struct sbuf *buf, int indent)
+ struct sbuf *buf, struct json_object *json,
+ int indent)
{
struct isis_area_address *addr = (struct isis_area_address *)i;
- sbuf_push(buf, indent, "Area Address: %s\n",
- isonet_print(addr->addr, addr->len));
+ if (json) {
+ json_object_string_add(json, "area-addr",
+ isonet_print(addr->addr, addr->len));
+ } else {
+ sbuf_push(buf, indent, "Area Address: %s\n",
+ isonet_print(addr->addr, addr->len));
+ }
}
static void free_item_area_address(struct isis_item *i)
@@ -1251,7 +1583,7 @@ static int unpack_item_area_address(uint16_t mtid, uint8_t len,
stream_get(rv->addr, s, rv->len);
format_item_area_address(ISIS_MT_IPV4_UNICAST, (struct isis_item *)rv,
- log, indent + 2);
+ log, NULL, indent + 2);
append_item(&tlvs->area_addresses, (struct isis_item *)rv);
return 0;
out:
@@ -1271,12 +1603,21 @@ static struct isis_item *copy_item_oldstyle_reach(struct isis_item *i)
}
static void format_item_oldstyle_reach(uint16_t mtid, struct isis_item *i,
- struct sbuf *buf, int indent)
+ struct sbuf *buf,
+ struct json_object *json, int indent)
{
struct isis_oldstyle_reach *r = (struct isis_oldstyle_reach *)i;
- sbuf_push(buf, indent, "IS Reachability: %s (Metric: %hhu)\n",
- isis_format_id(r->id, 7), r->metric);
+ if (json) {
+ struct json_object *old_json;
+ old_json = json_object_new_object();
+ json_object_object_add(json, "old-reach-style", old_json);
+ json_object_string_add(old_json, "is-reach",
+ isis_format_id(r->id, 7));
+ json_object_int_add(old_json, "metric", r->metric);
+ } else
+ sbuf_push(buf, indent, "IS Reachability: %s (Metric: %hhu)\n",
+ isis_format_id(r->id, 7), r->metric);
}
static void free_item_oldstyle_reach(struct isis_item *i)
@@ -1327,7 +1668,7 @@ static int unpack_item_oldstyle_reach(uint16_t mtid, uint8_t len,
stream_forward_getp(s, 3); /* Skip other metrics */
stream_get(rv->id, s, 7);
- format_item_oldstyle_reach(mtid, (struct isis_item *)rv, log,
+ format_item_oldstyle_reach(mtid, (struct isis_item *)rv, log, NULL,
indent + 2);
append_item(&tlvs->oldstyle_reach, (struct isis_item *)rv);
return 0;
@@ -1344,11 +1685,17 @@ static struct isis_item *copy_item_lan_neighbor(struct isis_item *i)
}
static void format_item_lan_neighbor(uint16_t mtid, struct isis_item *i,
- struct sbuf *buf, int indent)
+ struct sbuf *buf, struct json_object *json,
+ int indent)
{
struct isis_lan_neighbor *n = (struct isis_lan_neighbor *)i;
- sbuf_push(buf, indent, "LAN Neighbor: %s\n", isis_format_id(n->mac, 6));
+ if (json) {
+ json_object_string_add(json, "lan-neighbor",
+ isis_format_id(n->mac, 6));
+ } else
+ sbuf_push(buf, indent, "LAN Neighbor: %s\n",
+ isis_format_id(n->mac, 6));
}
static void free_item_lan_neighbor(struct isis_item *i)
@@ -1389,7 +1736,7 @@ static int unpack_item_lan_neighbor(uint16_t mtid, uint8_t len,
struct isis_lan_neighbor *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
stream_get(rv->mac, s, 6);
- format_item_lan_neighbor(mtid, (struct isis_item *)rv, log, indent + 2);
+ format_item_lan_neighbor(mtid, (struct isis_item *)rv, log, NULL, indent + 2);
append_item(&tlvs->lan_neighbor, (struct isis_item *)rv);
return 0;
}
@@ -1409,10 +1756,23 @@ static struct isis_item *copy_item_lsp_entry(struct isis_item *i)
}
static void format_item_lsp_entry(uint16_t mtid, struct isis_item *i,
- struct sbuf *buf, int indent)
+ struct sbuf *buf, struct json_object *json,
+ int indent)
{
struct isis_lsp_entry *e = (struct isis_lsp_entry *)i;
+ if (json) {
+ char buf[255];
+ struct json_object *lsp_json;
+ lsp_json = json_object_new_object();
+ json_object_object_add(json, "lsp-entry", lsp_json);
+ json_object_string_add(lsp_json, "id", isis_format_id(e->id, 8));
+ snprintfrr(buf,sizeof(buf),"0x%08x",e->seqno);
+ json_object_string_add(lsp_json, "seq", buf);
+ snprintfrr(buf,sizeof(buf),"0x%04hx",e->checksum);
+ json_object_string_add(lsp_json, "chksum", buf);
+ json_object_int_add(lsp_json, "lifetime", e->checksum);
+ } else
sbuf_push(buf, indent,
"LSP Entry: %s, seq 0x%08x, cksum 0x%04hx, lifetime %hus\n",
isis_format_id(e->id, 8), e->seqno, e->checksum,
@@ -1462,7 +1822,7 @@ static int unpack_item_lsp_entry(uint16_t mtid, uint8_t len, struct stream *s,
rv->seqno = stream_getl(s);
rv->checksum = stream_getw(s);
- format_item_lsp_entry(mtid, (struct isis_item *)rv, log, indent + 2);
+ format_item_lsp_entry(mtid, (struct isis_item *)rv, log, NULL, indent + 2);
append_item(&tlvs->lsp_entries, (struct isis_item *)rv);
return 0;
}
@@ -1484,19 +1844,40 @@ static struct isis_item *copy_item_extended_reach(struct isis_item *i)
}
static void format_item_extended_reach(uint16_t mtid, struct isis_item *i,
- struct sbuf *buf, int indent)
+ struct sbuf *buf,
+ struct json_object *json, int indent)
{
struct isis_extended_reach *r = (struct isis_extended_reach *)i;
- sbuf_push(buf, indent, "%s Reachability: %s (Metric: %u)",
- (mtid == ISIS_MT_IPV4_UNICAST) ? "Extended" : "MT",
- isis_format_id(r->id, 7), r->metric);
- if (mtid != ISIS_MT_IPV4_UNICAST)
- sbuf_push(buf, 0, " %s", isis_mtid2str(mtid));
- sbuf_push(buf, 0, "\n");
+ if (json) {
+ struct json_object *reach_json;
+ reach_json = json_object_new_object();
+ json_object_object_add(json, "ext-reach", reach_json);
+ json_object_string_add(
+ reach_json, "mt-id",
+ (mtid == ISIS_MT_IPV4_UNICAST) ? "Extended" : "MT");
+ json_object_string_add(reach_json, "id",
+ isis_format_id(r->id, 7));
+ json_object_int_add(reach_json, "metric", r->metric);
+ if (mtid != ISIS_MT_IPV4_UNICAST)
+ json_object_string_add(reach_json, "mt-name",
+ isis_mtid2str(mtid));
+
+ if (r->subtlvs)
+ format_item_ext_subtlvs(r->subtlvs, NULL, json,
+ indent + 2, mtid);
+ } else {
+ sbuf_push(buf, indent, "%s Reachability: %s (Metric: %u)",
+ (mtid == ISIS_MT_IPV4_UNICAST) ? "Extended" : "MT",
+ isis_format_id(r->id, 7), r->metric);
+ if (mtid != ISIS_MT_IPV4_UNICAST)
+ sbuf_push(buf, 0, " %s", isis_mtid2str(mtid));
+ sbuf_push(buf, 0, "\n");
- if (r->subtlvs)
- format_item_ext_subtlvs(r->subtlvs, buf, indent + 2, mtid);
+ if (r->subtlvs)
+ format_item_ext_subtlvs(r->subtlvs, buf, NULL,
+ indent + 2, mtid);
+ }
}
static void free_item_extended_reach(struct isis_item *i)
@@ -1579,7 +1960,7 @@ static int unpack_item_extended_reach(uint16_t mtid, uint8_t len,
}
}
- format_item_extended_reach(mtid, (struct isis_item *)rv, log,
+ format_item_extended_reach(mtid, (struct isis_item *)rv, log, NULL,
indent + 2);
append_item(items, (struct isis_item *)rv);
return 0;
@@ -1603,11 +1984,20 @@ static struct isis_item *copy_item_oldstyle_ip_reach(struct isis_item *i)
}
static void format_item_oldstyle_ip_reach(uint16_t mtid, struct isis_item *i,
- struct sbuf *buf, int indent)
+ struct sbuf *buf,
+ struct json_object *json, int indent)
{
struct isis_oldstyle_ip_reach *r = (struct isis_oldstyle_ip_reach *)i;
char prefixbuf[PREFIX2STR_BUFFER];
+ if (json) {
+ struct json_object *old_json;
+ old_json = json_object_new_object();
+ json_object_object_add(json, "old-ip-reach-style", old_json);
+ json_object_string_add(old_json, "prefix",
+ prefix2str(&r->prefix, prefixbuf, sizeof(prefixbuf)));
+ json_object_int_add(old_json, "metric", r->metric);
+ } else
sbuf_push(buf, indent, "IP Reachability: %s (Metric: %hhu)\n",
prefix2str(&r->prefix, prefixbuf, sizeof(prefixbuf)),
r->metric);
@@ -1669,7 +2059,7 @@ static int unpack_item_oldstyle_ip_reach(uint16_t mtid, uint8_t len,
stream_get(&mask, s, 4);
rv->prefix.prefixlen = ip_masklen(mask);
- format_item_oldstyle_ip_reach(mtid, (struct isis_item *)rv, log,
+ format_item_oldstyle_ip_reach(mtid, (struct isis_item *)rv, log, NULL,
indent + 2);
append_item(dest, (struct isis_item *)rv);
return 0;
@@ -1689,17 +2079,32 @@ static void copy_tlv_protocols_supported(struct isis_protocols_supported *src,
}
static void format_tlv_protocols_supported(struct isis_protocols_supported *p,
- struct sbuf *buf, int indent)
+ struct sbuf *buf,
+ struct json_object *json, int indent)
{
if (!p || !p->count || !p->protocols)
return;
- sbuf_push(buf, indent, "Protocols Supported: ");
- for (uint8_t i = 0; i < p->count; i++) {
- sbuf_push(buf, 0, "%s%s", nlpid2str(p->protocols[i]),
- (i + 1 < p->count) ? ", " : "");
+ if (json) {
+ struct json_object *protocol_json;
+ char buf[255];
+
+ protocol_json = json_object_new_object();
+ json_object_object_add(json, "protocols-supported",
+ protocol_json);
+ for (uint8_t i = 0; i < p->count; i++) {
+ snprintfrr(buf, sizeof(buf), "%d", i);
+ json_object_string_add(protocol_json, buf,
+ nlpid2str(p->protocols[i]));
+ }
+ } else {
+ sbuf_push(buf, indent, "Protocols Supported: ");
+ for (uint8_t i = 0; i < p->count; i++) {
+ sbuf_push(buf, 0, "%s%s", nlpid2str(p->protocols[i]),
+ (i + 1 < p->count) ? ", " : "");
+ }
+ sbuf_push(buf, 0, "\n");
}
- sbuf_push(buf, 0, "\n");
}
static void free_tlv_protocols_supported(struct isis_protocols_supported *p)
@@ -1746,7 +2151,7 @@ static int unpack_tlv_protocols_supported(enum isis_tlv_context context,
tlvs->protocols_supported.protocols = XCALLOC(MTYPE_ISIS_TLV, tlv_len);
stream_get(tlvs->protocols_supported.protocols, s, tlv_len);
- format_tlv_protocols_supported(&tlvs->protocols_supported, log,
+ format_tlv_protocols_supported(&tlvs->protocols_supported, log, NULL,
indent + 2);
return 0;
}
@@ -1762,13 +2167,18 @@ static struct isis_item *copy_item_ipv4_address(struct isis_item *i)
}
static void format_item_ipv4_address(uint16_t mtid, struct isis_item *i,
- struct sbuf *buf, int indent)
+ struct sbuf *buf, struct json_object *json,
+ int indent)
{
struct isis_ipv4_address *a = (struct isis_ipv4_address *)i;
char addrbuf[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &a->addr, addrbuf, sizeof(addrbuf));
- sbuf_push(buf, indent, "IPv4 Interface Address: %s\n", addrbuf);
+ if (json) {
+ json_object_string_add(json, "ipv4", addrbuf);
+ } else {
+ sbuf_push(buf, indent, "IPv4 Interface Address: %s\n", addrbuf);
+ }
}
static void free_item_ipv4_address(struct isis_item *i)
@@ -1809,7 +2219,7 @@ static int unpack_item_ipv4_address(uint16_t mtid, uint8_t len,
struct isis_ipv4_address *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
stream_get(&rv->addr, s, 4);
- format_item_ipv4_address(mtid, (struct isis_item *)rv, log, indent + 2);
+ format_item_ipv4_address(mtid, (struct isis_item *)rv, log, NULL, indent + 2);
append_item(&tlvs->ipv4_address, (struct isis_item *)rv);
return 0;
}
@@ -1826,13 +2236,17 @@ static struct isis_item *copy_item_ipv6_address(struct isis_item *i)
}
static void format_item_ipv6_address(uint16_t mtid, struct isis_item *i,
- struct sbuf *buf, int indent)
+ struct sbuf *buf, struct json_object *json,
+ int indent)
{
struct isis_ipv6_address *a = (struct isis_ipv6_address *)i;
char addrbuf[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &a->addr, addrbuf, sizeof(addrbuf));
- sbuf_push(buf, indent, "IPv6 Interface Address: %s\n", addrbuf);
+ if (json)
+ json_object_string_add(json, "ipv6", addrbuf);
+ else
+ sbuf_push(buf, indent, "IPv6 Interface Address: %s\n", addrbuf);
}
static void free_item_ipv6_address(struct isis_item *i)
@@ -1873,7 +2287,7 @@ static int unpack_item_ipv6_address(uint16_t mtid, uint8_t len,
struct isis_ipv6_address *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
stream_get(&rv->addr, s, IPV6_MAX_BYTELEN);
- format_item_ipv6_address(mtid, (struct isis_item *)rv, log, indent + 2);
+ format_item_ipv6_address(mtid, (struct isis_item *)rv, log, NULL, indent + 2);
append_item(&tlvs->ipv6_address, (struct isis_item *)rv);
return 0;
}
@@ -1890,13 +2304,19 @@ static struct isis_item *copy_item_global_ipv6_address(struct isis_item *i)
}
static void format_item_global_ipv6_address(uint16_t mtid, struct isis_item *i,
- struct sbuf *buf, int indent)
+ struct sbuf *buf,
+ struct json_object *json,
+ int indent)
{
struct isis_ipv6_address *a = (struct isis_ipv6_address *)i;
char addrbuf[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &a->addr, addrbuf, sizeof(addrbuf));
- sbuf_push(buf, indent, "Global IPv6 Interface Address: %s\n", addrbuf);
+ if (json)
+ json_object_string_add(json, "global-ipv6", addrbuf);
+ else
+ sbuf_push(buf, indent, "Global IPv6 Interface Address: %s\n",
+ addrbuf);
}
static void free_item_global_ipv6_address(struct isis_item *i)
@@ -1937,7 +2357,7 @@ static int unpack_item_global_ipv6_address(uint16_t mtid, uint8_t len,
struct isis_ipv6_address *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
stream_get(&rv->addr, s, IPV6_MAX_BYTELEN);
- format_item_global_ipv6_address(mtid, (struct isis_item *)rv, log,
+ format_item_global_ipv6_address(mtid, (struct isis_item *)rv, log, NULL,
indent + 2);
append_item(&tlvs->global_ipv6_address, (struct isis_item *)rv);
return 0;
@@ -1956,14 +2376,23 @@ static struct isis_item *copy_item_mt_router_info(struct isis_item *i)
}
static void format_item_mt_router_info(uint16_t mtid, struct isis_item *i,
- struct sbuf *buf, int indent)
+ struct sbuf *buf,
+ struct json_object *json, int indent)
{
struct isis_mt_router_info *info = (struct isis_mt_router_info *)i;
- sbuf_push(buf, indent, "MT Router Info: %s%s%s\n",
- isis_mtid2str(info->mtid),
- info->overload ? " Overload" : "",
- info->attached ? " Attached" : "");
+ if (json) {
+ struct json_object *mt_json;
+ mt_json = json_object_new_object();
+ json_object_object_add(json, "mt", mt_json);
+ json_object_int_add(mt_json, "mtid", info->mtid);
+ json_object_string_add(mt_json, "overload", info->overload?"true":"false");
+ json_object_string_add(mt_json, "attached", info->attached?"true":"false");
+ } else
+ sbuf_push(buf, indent, "MT Router Info: %s%s%s\n",
+ isis_mtid2str(info->mtid),
+ info->overload ? " Overload" : "",
+ info->attached ? " Attached" : "");
}
static void free_item_mt_router_info(struct isis_item *i)
@@ -2015,7 +2444,7 @@ static int unpack_item_mt_router_info(uint16_t mtid, uint8_t len,
rv->attached = entry & ISIS_MT_AT_MASK;
rv->mtid = entry & ISIS_MT_MASK;
- format_item_mt_router_info(mtid, (struct isis_item *)rv, log,
+ format_item_mt_router_info(mtid, (struct isis_item *)rv, log, NULL,
indent + 2);
append_item(&tlvs->mt_router_info, (struct isis_item *)rv);
return 0;
@@ -2034,14 +2463,17 @@ static struct in_addr *copy_tlv_te_router_id(const struct in_addr *id)
}
static void format_tlv_te_router_id(const struct in_addr *id, struct sbuf *buf,
- int indent)
+ struct json_object *json, int indent)
{
if (!id)
return;
char addrbuf[INET_ADDRSTRLEN];
inet_ntop(AF_INET, id, addrbuf, sizeof(addrbuf));
- sbuf_push(buf, indent, "TE Router ID: %s\n", addrbuf);
+ if (json)
+ json_object_string_add(json, "te-router-id", addrbuf);
+ else
+ sbuf_push(buf, indent, "TE Router ID: %s\n", addrbuf);
}
static void free_tlv_te_router_id(struct in_addr *id)
@@ -2085,7 +2517,7 @@ static int unpack_tlv_te_router_id(enum isis_tlv_context context,
tlvs->te_router_id = XCALLOC(MTYPE_ISIS_TLV, 4);
stream_get(tlvs->te_router_id, s, 4);
- format_tlv_te_router_id(tlvs->te_router_id, log, indent + 2);
+ format_tlv_te_router_id(tlvs->te_router_id, log, NULL, indent + 2);
return 0;
}
@@ -2107,22 +2539,46 @@ static struct isis_item *copy_item_extended_ip_reach(struct isis_item *i)
}
static void format_item_extended_ip_reach(uint16_t mtid, struct isis_item *i,
- struct sbuf *buf, int indent)
+ struct sbuf *buf,
+ struct json_object *json, int indent)
{
struct isis_extended_ip_reach *r = (struct isis_extended_ip_reach *)i;
char prefixbuf[PREFIX2STR_BUFFER];
- sbuf_push(buf, indent, "%s IP Reachability: %s (Metric: %u)%s",
- (mtid == ISIS_MT_IPV4_UNICAST) ? "Extended" : "MT",
- prefix2str(&r->prefix, prefixbuf, sizeof(prefixbuf)), r->metric,
- r->down ? " Down" : "");
- if (mtid != ISIS_MT_IPV4_UNICAST)
- sbuf_push(buf, 0, " %s", isis_mtid2str(mtid));
- sbuf_push(buf, 0, "\n");
-
- if (r->subtlvs) {
- sbuf_push(buf, indent, " Subtlvs:\n");
- format_subtlvs(r->subtlvs, buf, indent + 4);
+ if (json) {
+ struct json_object *ext_json;
+ ext_json = json_object_new_object();
+ json_object_object_add(json, "ext-ip-reach", ext_json);
+ json_object_string_add(
+ json, "mt-id",
+ (mtid == ISIS_MT_IPV4_UNICAST) ? "Extended" : "MT");
+ json_object_string_add(
+ json, "ip-reach",
+ prefix2str(&r->prefix, prefixbuf, sizeof(prefixbuf)));
+ json_object_int_add(json, "ip-reach-metric", r->metric);
+ json_object_string_add(json, "down", r->down ? "yes" : "");
+ if (mtid != ISIS_MT_IPV4_UNICAST)
+ json_object_string_add(json, "mt-name",
+ isis_mtid2str(mtid));
+ if (r->subtlvs) {
+ struct json_object *subtlv_json;
+ subtlv_json = json_object_new_object();
+ json_object_object_add(json, "subtlvs", subtlv_json);
+ format_subtlvs(r->subtlvs, NULL, subtlv_json, 0);
+ }
+ } else {
+ sbuf_push(buf, indent, "%s IP Reachability: %s (Metric: %u)%s",
+ (mtid == ISIS_MT_IPV4_UNICAST) ? "Extended" : "MT",
+ prefix2str(&r->prefix, prefixbuf, sizeof(prefixbuf)),
+ r->metric, r->down ? " Down" : "");
+ if (mtid != ISIS_MT_IPV4_UNICAST)
+ sbuf_push(buf, 0, " %s", isis_mtid2str(mtid));
+ sbuf_push(buf, 0, "\n");
+
+ if (r->subtlvs) {
+ sbuf_push(buf, indent, " Subtlvs:\n");
+ format_subtlvs(r->subtlvs, buf, NULL, indent + 4);
+ }
}
}
@@ -2216,7 +2672,7 @@ static int unpack_item_extended_ip_reach(uint16_t mtid, uint8_t len,
if (orig_prefix != rv->prefix.prefix.s_addr)
sbuf_push(log, indent + 2,
"WARNING: Prefix had hostbits set.\n");
- format_item_extended_ip_reach(mtid, (struct isis_item *)rv, log,
+ format_item_extended_ip_reach(mtid, (struct isis_item *)rv, log, NULL,
indent + 2);
if (control & ISIS_EXTENDED_IP_REACH_SUBTLV) {
@@ -2273,12 +2729,15 @@ static char *copy_tlv_dynamic_hostname(const char *hostname)
}
static void format_tlv_dynamic_hostname(const char *hostname, struct sbuf *buf,
- int indent)
+ struct json_object *json, int indent)
{
if (!hostname)
return;
- sbuf_push(buf, indent, "Hostname: %s\n", hostname);
+ if (json)
+ json_object_string_add(json, "hostname", hostname);
+ else
+ sbuf_push(buf, indent, "Hostname: %s\n", hostname);
}
static void free_tlv_dynamic_hostname(char *hostname)
@@ -2356,14 +2815,18 @@ static struct in6_addr *copy_tlv_te_router_id_ipv6(const struct in6_addr *id)
}
static void format_tlv_te_router_id_ipv6(const struct in6_addr *id,
- struct sbuf *buf, int indent)
+ struct sbuf *buf,
+ struct json_object *json, int indent)
{
if (!id)
return;
char addrbuf[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, id, addrbuf, sizeof(addrbuf));
- sbuf_push(buf, indent, "IPv6 TE Router ID: %s\n", addrbuf);
+ if (json)
+ json_object_string_add(json, "ipv6-te-router-id", addrbuf);
+ else
+ sbuf_push(buf, indent, "IPv6 TE Router ID: %s\n", addrbuf);
}
static void free_tlv_te_router_id_ipv6(struct in6_addr *id)
@@ -2409,7 +2872,7 @@ static int unpack_tlv_te_router_id_ipv6(enum isis_tlv_context context,
tlvs->te_router_id_ipv6 = XCALLOC(MTYPE_ISIS_TLV, IPV6_MAX_BYTELEN);
stream_get(tlvs->te_router_id_ipv6, s, IPV6_MAX_BYTELEN);
- format_tlv_te_router_id_ipv6(tlvs->te_router_id_ipv6, log, indent + 2);
+ format_tlv_te_router_id_ipv6(tlvs->te_router_id_ipv6, log, NULL, indent + 2);
return 0;
}
@@ -2429,26 +2892,50 @@ static struct isis_spine_leaf *copy_tlv_spine_leaf(
}
static void format_tlv_spine_leaf(const struct isis_spine_leaf *spine_leaf,
- struct sbuf *buf, int indent)
+ struct sbuf *buf, struct json_object *json,
+ int indent)
{
if (!spine_leaf)
return;
- sbuf_push(buf, indent, "Spine-Leaf-Extension:\n");
- if (spine_leaf->has_tier) {
- if (spine_leaf->tier == ISIS_TIER_UNDEFINED) {
- sbuf_push(buf, indent, " Tier: undefined\n");
- } else {
- sbuf_push(buf, indent, " Tier: %hhu\n",
- spine_leaf->tier);
+ char aux_buf[255];
+
+ if (json) {
+ struct json_object *spine_json;
+ spine_json = json_object_new_object();
+ json_object_object_add(json, "spine-leaf-extension",
+ spine_json);
+ if (spine_leaf->has_tier) {
+ snprintfrr(aux_buf, sizeof(aux_buf), "%hhu",
+ spine_leaf->tier);
+ json_object_string_add(
+ spine_json, "tier",
+ (spine_leaf->tier == ISIS_TIER_UNDEFINED)
+ ? "undefined"
+ : aux_buf);
+ }
+ json_object_string_add(spine_json, "flag-leaf",
+ spine_leaf->is_leaf ? "yes" : "");
+ json_object_string_add(spine_json, "flag-spine",
+ spine_leaf->is_spine ? "yes" : "");
+ json_object_string_add(spine_json, "flag-backup",
+ spine_leaf->is_backup ? "yes" : "");
+ } else {
+ sbuf_push(buf, indent, "Spine-Leaf-Extension:\n");
+ if (spine_leaf->has_tier) {
+ if (spine_leaf->tier == ISIS_TIER_UNDEFINED) {
+ sbuf_push(buf, indent, " Tier: undefined\n");
+ } else {
+ sbuf_push(buf, indent, " Tier: %hhu\n",
+ spine_leaf->tier);
+ }
}
- }
-
- sbuf_push(buf, indent, " Flags:%s%s%s\n",
- spine_leaf->is_leaf ? " LEAF" : "",
- spine_leaf->is_spine ? " SPINE" : "",
- spine_leaf->is_backup ? " BACKUP" : "");
+ sbuf_push(buf, indent, " Flags:%s%s%s\n",
+ spine_leaf->is_leaf ? " LEAF" : "",
+ spine_leaf->is_spine ? " SPINE" : "",
+ spine_leaf->is_backup ? " BACKUP" : "");
+ }
}
static void free_tlv_spine_leaf(struct isis_spine_leaf *spine_leaf)
@@ -2562,25 +3049,45 @@ static struct isis_threeway_adj *copy_tlv_threeway_adj(
return rv;
}
-static void format_tlv_threeway_adj(const struct isis_threeway_adj *threeway_adj,
- struct sbuf *buf, int indent)
+static void
+format_tlv_threeway_adj(const struct isis_threeway_adj *threeway_adj,
+ struct sbuf *buf, struct json_object *json, int indent)
{
if (!threeway_adj)
return;
- sbuf_push(buf, indent, "P2P Three-Way Adjacency:\n");
- sbuf_push(buf, indent, " State: %s (%d)\n",
- isis_threeway_state_name(threeway_adj->state),
- threeway_adj->state);
- sbuf_push(buf, indent, " Extended Local Circuit ID: %u\n",
- threeway_adj->local_circuit_id);
- if (!threeway_adj->neighbor_set)
- return;
+ if (json) {
+ struct json_object *three_json;
+ three_json = json_object_new_object();
+ json_object_object_add(json, "p2p-three-way-adj", three_json);
+ json_object_string_add(
+ three_json, "state-name",
+ isis_threeway_state_name(threeway_adj->state));
+ json_object_int_add(three_json, "state", threeway_adj->state);
+ json_object_int_add(three_json, "ext-local-circuit-id",
+ threeway_adj->local_circuit_id);
+ if (!threeway_adj->neighbor_set)
+ return;
+ json_object_string_add(
+ three_json, "neigh-system-id",
+ isis_format_id(threeway_adj->neighbor_id, 6));
+ json_object_int_add(three_json, "neigh-ext-circuit-id",
+ threeway_adj->neighbor_circuit_id);
+ } else {
+ sbuf_push(buf, indent, "P2P Three-Way Adjacency:\n");
+ sbuf_push(buf, indent, " State: %s (%d)\n",
+ isis_threeway_state_name(threeway_adj->state),
+ threeway_adj->state);
+ sbuf_push(buf, indent, " Extended Local Circuit ID: %u\n",
+ threeway_adj->local_circuit_id);
+ if (!threeway_adj->neighbor_set)
+ return;
- sbuf_push(buf, indent, " Neighbor System ID: %s\n",
- isis_format_id(threeway_adj->neighbor_id, 6));
- sbuf_push(buf, indent, " Neighbor Extended Circuit ID: %u\n",
- threeway_adj->neighbor_circuit_id);
+ sbuf_push(buf, indent, " Neighbor System ID: %s\n",
+ isis_format_id(threeway_adj->neighbor_id, 6));
+ sbuf_push(buf, indent, " Neighbor Extended Circuit ID: %u\n",
+ threeway_adj->neighbor_circuit_id);
+ }
}
static void free_tlv_threeway_adj(struct isis_threeway_adj *threeway_adj)
@@ -2663,24 +3170,51 @@ static struct isis_item *copy_item_ipv6_reach(struct isis_item *i)
}
static void format_item_ipv6_reach(uint16_t mtid, struct isis_item *i,
- struct sbuf *buf, int indent)
+ struct sbuf *buf, struct json_object *json,
+ int indent)
{
struct isis_ipv6_reach *r = (struct isis_ipv6_reach *)i;
char prefixbuf[PREFIX2STR_BUFFER];
- sbuf_push(buf, indent, "%sIPv6 Reachability: %s (Metric: %u)%s%s",
- (mtid == ISIS_MT_IPV4_UNICAST) ? "" : "MT ",
- prefix2str(&r->prefix, prefixbuf, sizeof(prefixbuf)),
- r->metric,
- r->down ? " Down" : "",
- r->external ? " External" : "");
- if (mtid != ISIS_MT_IPV4_UNICAST)
- sbuf_push(buf, 0, " %s", isis_mtid2str(mtid));
- sbuf_push(buf, 0, "\n");
-
- if (r->subtlvs) {
- sbuf_push(buf, indent, " Subtlvs:\n");
- format_subtlvs(r->subtlvs, buf, indent + 4);
+ if (json) {
+ struct json_object *reach_json;
+ reach_json = json_object_new_object();
+ json_object_object_add(json, "ipv6-reach", reach_json);
+ json_object_string_add(reach_json, "mt-id",
+ (mtid == ISIS_MT_IPV4_UNICAST) ? ""
+ : "mt");
+ json_object_string_add(
+ reach_json, "prefix",
+ prefix2str(&r->prefix, prefixbuf, sizeof(prefixbuf)));
+ json_object_int_add(reach_json, "metric", r->metric);
+ json_object_string_add(reach_json, "down",
+ r->down ? "yes" : "");
+ json_object_string_add(reach_json, "external",
+ r->external ? "yes" : "");
+ if (mtid != ISIS_MT_IPV4_UNICAST)
+ json_object_string_add(reach_json, "mt-name",
+ isis_mtid2str(mtid));
+ if (r->subtlvs) {
+ struct json_object *subtlvs_json;
+ subtlvs_json = json_object_new_object();
+ json_object_object_add(json, "subtlvs", subtlvs_json);
+ format_subtlvs(r->subtlvs, NULL, subtlvs_json, 0);
+ }
+ } else {
+ sbuf_push(buf, indent,
+ "%sIPv6 Reachability: %s (Metric: %u)%s%s",
+ (mtid == ISIS_MT_IPV4_UNICAST) ? "" : "MT ",
+ prefix2str(&r->prefix, prefixbuf, sizeof(prefixbuf)),
+ r->metric, r->down ? " Down" : "",
+ r->external ? " External" : "");
+ if (mtid != ISIS_MT_IPV4_UNICAST)
+ sbuf_push(buf, 0, " %s", isis_mtid2str(mtid));
+ sbuf_push(buf, 0, "\n");
+
+ if (r->subtlvs) {
+ sbuf_push(buf, indent, " Subtlvs:\n");
+ format_subtlvs(r->subtlvs, buf, NULL, indent + 4);
+ }
}
}
@@ -2773,7 +3307,7 @@ static int unpack_item_ipv6_reach(uint16_t mtid, uint8_t len, struct stream *s,
if (memcmp(&orig_prefix, &rv->prefix.prefix, sizeof(orig_prefix)))
sbuf_push(log, indent + 2,
"WARNING: Prefix had hostbits set.\n");
- format_item_ipv6_reach(mtid, (struct isis_item *)rv, log, indent + 2);
+ format_item_ipv6_reach(mtid, (struct isis_item *)rv, log, NULL, indent + 2);
if (control & ISIS_IPV6_REACH_SUBTLV) {
consume += 1;
@@ -2834,6 +3368,77 @@ static struct isis_router_cap *copy_tlv_router_cap(
return rv;
}
+static void format_tlv_router_cap_json(const struct isis_router_cap *router_cap,
+ struct json_object *json)
+{
+ char addrbuf[INET_ADDRSTRLEN];
+
+ if (!router_cap)
+ return;
+
+ /* Router ID and Flags */
+ struct json_object *cap_json;
+ cap_json = json_object_new_object();
+ json_object_object_add(json, "router-capability", cap_json);
+ inet_ntop(AF_INET, &router_cap->router_id, addrbuf, sizeof(addrbuf));
+ json_object_string_add(cap_json, "id", addrbuf);
+ json_object_string_add(
+ cap_json, "flag-d",
+ router_cap->flags & ISIS_ROUTER_CAP_FLAG_D ? "1" : "0");
+ json_object_string_add(
+ cap_json, "flag-s",
+ router_cap->flags & ISIS_ROUTER_CAP_FLAG_S ? "1" : "0");
+
+ /* Segment Routing Global Block as per RFC8667 section #3.1 */
+ if (router_cap->srgb.range_size != 0) {
+ struct json_object *gb_json;
+ gb_json = json_object_new_object();
+ json_object_object_add(json, "segment-routing-gb", gb_json);
+ json_object_string_add(gb_json, "ipv4",
+ IS_SR_IPV4(&router_cap->srgb) ? "1"
+ : "0");
+ json_object_string_add(gb_json, "ipv6",
+ IS_SR_IPV6(&router_cap->srgb) ? "1"
+ : "0");
+ json_object_int_add(gb_json, "global-block-base",
+ router_cap->srgb.lower_bound);
+ json_object_int_add(gb_json, "global-block-range",
+ router_cap->srgb.range_size);
+ }
+
+ /* Segment Routing Local Block as per RFC8667 section #3.3 */
+ if (router_cap->srlb.range_size != 0) {
+ struct json_object *lb_json;
+ lb_json = json_object_new_object();
+ json_object_object_add(json, "segment-routing-lb", lb_json);
+ json_object_int_add(lb_json, "global-block-base",
+ router_cap->srlb.lower_bound);
+ json_object_int_add(lb_json, "global-block-range",
+ router_cap->srlb.range_size);
+ }
+
+ /* Segment Routing Algorithms as per RFC8667 section #3.2 */
+ if (router_cap->algo[0] != SR_ALGORITHM_UNSET) {
+ char buf[255];
+ struct json_object *alg_json;
+ alg_json = json_object_new_object();
+ json_object_object_add(json, "segment-routing-algorithm",
+ alg_json);
+ for (int i = 0; i < SR_ALGORITHM_COUNT; i++)
+ if (router_cap->algo[i] != SR_ALGORITHM_UNSET) {
+ snprintfrr(buf, sizeof(buf), "%d", i);
+ json_object_string_add(alg_json, buf,
+ router_cap->algo[i] == 0
+ ? "SPF"
+ : "Strict SPF");
+ }
+ }
+
+ /* Segment Routing Node MSD as per RFC8491 section #2 */
+ if (router_cap->msd != 0)
+ json_object_int_add(json, "msd", router_cap->msd);
+}
+
static void format_tlv_router_cap(const struct isis_router_cap *router_cap,
struct sbuf *buf, int indent)
{
@@ -3177,26 +3782,40 @@ static struct isis_item *copy_item_auth(struct isis_item *i)
}
static void format_item_auth(uint16_t mtid, struct isis_item *i,
- struct sbuf *buf, int indent)
+ struct sbuf *buf, struct json_object *json,
+ int indent)
{
struct isis_auth *auth = (struct isis_auth *)i;
char obuf[768];
- sbuf_push(buf, indent, "Authentication:\n");
+ if (json)
+ json_object_string_add(json, "test-auth", "ok");
+ else
+ sbuf_push(buf, indent, "Authentication:\n");
switch (auth->type) {
case ISIS_PASSWD_TYPE_CLEARTXT:
zlog_sanitize(obuf, sizeof(obuf), auth->value, auth->length);
- sbuf_push(buf, indent, " Password: %s\n", obuf);
+ if (json)
+ json_object_string_add(json, "auth-pass", obuf);
+ else
+ sbuf_push(buf, indent, " Password: %s\n", obuf);
break;
case ISIS_PASSWD_TYPE_HMAC_MD5:
for (unsigned int j = 0; j < 16; j++) {
- snprintf(obuf + 2 * j, sizeof(obuf) - 2 * j,
- "%02hhx", auth->value[j]);
+ snprintf(obuf + 2 * j, sizeof(obuf) - 2 * j, "%02hhx",
+ auth->value[j]);
}
- sbuf_push(buf, indent, " HMAC-MD5: %s\n", obuf);
+ if (json)
+ json_object_string_add(json, "auth-hmac-md5", obuf);
+ else
+ sbuf_push(buf, indent, " HMAC-MD5: %s\n", obuf);
break;
default:
- sbuf_push(buf, indent, " Unknown (%hhu)\n", auth->type);
+ if (json)
+ json_object_int_add(json, "auth-unknown", auth->type);
+ else
+ sbuf_push(buf, indent, " Unknown (%hhu)\n",
+ auth->type);
break;
}
}
@@ -3270,7 +3889,7 @@ static int unpack_item_auth(uint16_t mtid, uint8_t len, struct stream *s,
rv->offset = stream_get_getp(s);
stream_get(rv->value, s, rv->length);
- format_item_auth(mtid, (struct isis_item *)rv, log, indent + 2);
+ format_item_auth(mtid, (struct isis_item *)rv, log, NULL, indent + 2);
append_item(&tlvs->isis_auth, (struct isis_item *)rv);
return 0;
}
@@ -3294,17 +3913,36 @@ static struct isis_purge_originator *copy_tlv_purge_originator(
}
static void format_tlv_purge_originator(struct isis_purge_originator *poi,
- struct sbuf *buf, int indent)
+ struct sbuf *buf,
+ struct json_object *json, int indent)
{
if (!poi)
return;
- sbuf_push(buf, indent, "Purge Originator Identification:\n");
- sbuf_push(buf, indent, " Generator: %s\n",
- isis_format_id(poi->generator, sizeof(poi->generator)));
- if (poi->sender_set) {
- sbuf_push(buf, indent, " Received-From: %s\n",
- isis_format_id(poi->sender, sizeof(poi->sender)));
+ if (json) {
+ struct json_object *purge_json;
+ purge_json = json_object_new_object();
+ json_object_object_add(json, "purge_originator", purge_json);
+
+ json_object_string_add(
+ purge_json, "id",
+ isis_format_id(poi->generator, sizeof(poi->generator)));
+ if (poi->sender_set) {
+ json_object_string_add(
+ purge_json, "rec-from",
+ isis_format_id(poi->sender,
+ sizeof(poi->sender)));
+ }
+ } else {
+ sbuf_push(buf, indent, "Purge Originator Identification:\n");
+ sbuf_push(
+ buf, indent, " Generator: %s\n",
+ isis_format_id(poi->generator, sizeof(poi->generator)));
+ if (poi->sender_set) {
+ sbuf_push(buf, indent, " Received-From: %s\n",
+ isis_format_id(poi->sender,
+ sizeof(poi->sender)));
+ }
}
}
@@ -3417,12 +4055,12 @@ static void copy_items(enum isis_tlv_context context, enum isis_tlv_type type,
static void format_item(uint16_t mtid, enum isis_tlv_context context,
enum isis_tlv_type type, struct isis_item *i,
- struct sbuf *buf, int indent)
+ struct sbuf *buf, struct json_object *json, int indent)
{
const struct tlv_ops *ops = tlv_table[context][type];
if (ops && ops->format_item) {
- ops->format_item(mtid, i, buf, indent);
+ ops->format_item(mtid, i, buf, json, indent);
return;
}
@@ -3431,12 +4069,13 @@ static void format_item(uint16_t mtid, enum isis_tlv_context context,
static void format_items_(uint16_t mtid, enum isis_tlv_context context,
enum isis_tlv_type type, struct isis_item_list *items,
- struct sbuf *buf, int indent)
+ struct sbuf *buf, struct json_object *json,
+ int indent)
{
struct isis_item *i;
for (i = items->head; i; i = i->next)
- format_item(mtid, context, type, i, buf, indent);
+ format_item(mtid, context, type, i, buf, json, indent);
}
static void free_item(enum isis_tlv_context tlv_context,
@@ -3765,12 +4404,12 @@ static void free_mt_items(enum isis_tlv_context context,
static void format_mt_items(enum isis_tlv_context context,
enum isis_tlv_type type,
struct isis_mt_item_list *m, struct sbuf *buf,
- int indent)
+ struct json_object *json, int indent)
{
struct isis_item_list *n;
RB_FOREACH (n, isis_mt_item_list, m) {
- format_items_(n->mtid, context, type, n, buf, indent);
+ format_items_(n->mtid, context, type, n, buf, json, indent);
}
}
@@ -3917,87 +4556,100 @@ struct isis_tlvs *isis_copy_tlvs(struct isis_tlvs *tlvs)
return rv;
}
-static void format_tlvs(struct isis_tlvs *tlvs, struct sbuf *buf, int indent)
+static void format_tlvs(struct isis_tlvs *tlvs, struct sbuf *buf, struct json_object *json, int indent)
{
- format_tlv_protocols_supported(&tlvs->protocols_supported, buf, indent);
+ format_tlv_protocols_supported(&tlvs->protocols_supported, buf, json,
+ indent);
format_items(ISIS_CONTEXT_LSP, ISIS_TLV_AUTH, &tlvs->isis_auth, buf,
- indent);
+ json, indent);
- format_tlv_purge_originator(tlvs->purge_originator, buf, indent);
+ format_tlv_purge_originator(tlvs->purge_originator, buf, json, indent);
format_items(ISIS_CONTEXT_LSP, ISIS_TLV_AREA_ADDRESSES,
- &tlvs->area_addresses, buf, indent);
+ &tlvs->area_addresses, buf, json, indent);
if (tlvs->mt_router_info_empty) {
- sbuf_push(buf, indent, "MT Router Info: None\n");
+ if (json)
+ json_object_string_add(json, "mt-router-info", "none");
+ else
+ sbuf_push(buf, indent, "MT Router Info: None\n");
} else {
format_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_ROUTER_INFO,
- &tlvs->mt_router_info, buf, indent);
+ &tlvs->mt_router_info, buf, json, indent);
}
format_items(ISIS_CONTEXT_LSP, ISIS_TLV_OLDSTYLE_REACH,
- &tlvs->oldstyle_reach, buf, indent);
+ &tlvs->oldstyle_reach, buf, json, indent);
format_items(ISIS_CONTEXT_LSP, ISIS_TLV_LAN_NEIGHBORS,
- &tlvs->lan_neighbor, buf, indent);
+ &tlvs->lan_neighbor, buf, json, indent);
format_items(ISIS_CONTEXT_LSP, ISIS_TLV_LSP_ENTRY, &tlvs->lsp_entries,
- buf, indent);
-
- format_tlv_dynamic_hostname(tlvs->hostname, buf, indent);
- format_tlv_te_router_id(tlvs->te_router_id, buf, indent);
- format_tlv_te_router_id_ipv6(tlvs->te_router_id_ipv6, buf, indent);
- format_tlv_router_cap(tlvs->router_cap, buf, indent);
+ buf, json, indent);
+
+ format_tlv_dynamic_hostname(tlvs->hostname, buf, json, indent);
+ format_tlv_te_router_id(tlvs->te_router_id, buf, json, indent);
+ format_tlv_te_router_id_ipv6(tlvs->te_router_id_ipv6, buf, json,
+ indent);
+ if (json)
+ format_tlv_router_cap_json(tlvs->router_cap, json);
+ else
+ format_tlv_router_cap(tlvs->router_cap, buf, indent);
format_items(ISIS_CONTEXT_LSP, ISIS_TLV_EXTENDED_REACH,
- &tlvs->extended_reach, buf, indent);
+ &tlvs->extended_reach, buf, json, indent);
format_mt_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_REACH, &tlvs->mt_reach,
- buf, indent);
+ buf, json, indent);
format_items(ISIS_CONTEXT_LSP, ISIS_TLV_OLDSTYLE_IP_REACH,
- &tlvs->oldstyle_ip_reach, buf, indent);
+ &tlvs->oldstyle_ip_reach, buf, json, indent);
format_items(ISIS_CONTEXT_LSP, ISIS_TLV_OLDSTYLE_IP_REACH_EXT,
- &tlvs->oldstyle_ip_reach_ext, buf, indent);
+ &tlvs->oldstyle_ip_reach_ext, buf, json, indent);
format_items(ISIS_CONTEXT_LSP, ISIS_TLV_IPV4_ADDRESS,
- &tlvs->ipv4_address, buf, indent);
+ &tlvs->ipv4_address, buf, json, indent);
format_items(ISIS_CONTEXT_LSP, ISIS_TLV_IPV6_ADDRESS,
- &tlvs->ipv6_address, buf, indent);
+ &tlvs->ipv6_address, buf, json, indent);
format_items(ISIS_CONTEXT_LSP, ISIS_TLV_GLOBAL_IPV6_ADDRESS,
- &tlvs->global_ipv6_address, buf, indent);
+ &tlvs->global_ipv6_address, buf, json, indent);
format_items(ISIS_CONTEXT_LSP, ISIS_TLV_EXTENDED_IP_REACH,
- &tlvs->extended_ip_reach, buf, indent);
+ &tlvs->extended_ip_reach, buf, json, indent);
format_mt_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_IP_REACH,
- &tlvs->mt_ip_reach, buf, indent);
+ &tlvs->mt_ip_reach, buf, json, indent);
format_items(ISIS_CONTEXT_LSP, ISIS_TLV_IPV6_REACH, &tlvs->ipv6_reach,
- buf, indent);
+ buf, json, indent);
format_mt_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_IPV6_REACH,
- &tlvs->mt_ipv6_reach, buf, indent);
+ &tlvs->mt_ipv6_reach, buf, json, indent);
- format_tlv_threeway_adj(tlvs->threeway_adj, buf, indent);
+ format_tlv_threeway_adj(tlvs->threeway_adj, buf, json, indent);
- format_tlv_spine_leaf(tlvs->spine_leaf, buf, indent);
+ format_tlv_spine_leaf(tlvs->spine_leaf, buf, json, indent);
}
-const char *isis_format_tlvs(struct isis_tlvs *tlvs)
+const char *isis_format_tlvs(struct isis_tlvs *tlvs, struct json_object *json)
{
- static struct sbuf buf;
+ if (json) {
+ format_tlvs(tlvs, NULL, json, 0);
+ return NULL;
+ } else {
+ static struct sbuf buf;
- if (!sbuf_buf(&buf))
- sbuf_init(&buf, NULL, 0);
+ if (!sbuf_buf(&buf))
+ sbuf_init(&buf, NULL, 0);
- sbuf_reset(&buf);
- format_tlvs(tlvs, &buf, 0);
- return sbuf_buf(&buf);
+ sbuf_reset(&buf);
+ format_tlvs(tlvs, &buf, NULL, 0);
+ return sbuf_buf(&buf);
+ }
}
void isis_free_tlvs(struct isis_tlvs *tlvs)
diff --git a/isisd/isis_tlvs.h b/isisd/isis_tlvs.h
index 0c6ed11cb..364e38aba 100644
--- a/isisd/isis_tlvs.h
+++ b/isisd/isis_tlvs.h
@@ -549,7 +549,7 @@ void isis_free_tlvs(struct isis_tlvs *tlvs);
struct isis_tlvs *isis_alloc_tlvs(void);
int isis_unpack_tlvs(size_t avail_len, struct stream *stream,
struct isis_tlvs **dest, const char **error_log);
-const char *isis_format_tlvs(struct isis_tlvs *tlvs);
+const char *isis_format_tlvs(struct isis_tlvs *tlvs, struct json_object *json);
struct isis_tlvs *isis_copy_tlvs(struct isis_tlvs *tlvs);
struct list *isis_fragment_tlvs(struct isis_tlvs *tlvs, size_t size);
diff --git a/isisd/isisd.c b/isisd/isisd.c
index 3fa2b7cc2..369b83396 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -109,12 +109,19 @@ DEFINE_HOOK(isis_hook_db_overload, (const struct isis_area *area), (area));
int isis_area_get(struct vty *, const char *);
int area_net_title(struct vty *, const char *);
int area_clear_net_title(struct vty *, const char *);
-int show_isis_interface_common(struct vty *, const char *ifname, char,
- const char *vrf_name, bool all_vrf);
-int show_isis_neighbor_common(struct vty *, const char *id, char,
- const char *vrf_name, bool all_vrf);
-int clear_isis_neighbor_common(struct vty *, const char *id, const char *vrf_name,
+int show_isis_interface_common(struct vty *, struct json_object *json,
+ const char *ifname, char, const char *vrf_name,
bool all_vrf);
+int show_isis_interface_common_vty(struct vty *, const char *ifname, char,
+ const char *vrf_name, bool all_vrf);
+int show_isis_interface_common_json(struct json_object *json,
+ const char *ifname, char,
+ const char *vrf_name, bool all_vrf);
+int show_isis_neighbor_common(struct vty *, struct json_object *json,
+ const char *id, char, const char *vrf_name,
+ bool all_vrf);
+int clear_isis_neighbor_common(struct vty *, const char *id,
+ const char *vrf_name, bool all_vrf);
/* Link ISIS instance to VRF. */
void isis_vrf_link(struct isis *isis, struct vrf *vrf)
@@ -202,7 +209,7 @@ struct isis *isis_new(const char *vrf_name)
/*
* Default values
*/
- isis->max_area_addrs = 3;
+ isis->max_area_addrs = ISIS_DEFAULT_MAX_AREA_ADDRESSES;
isis->process_id = getpid();
isis->router_id = 0;
isis->area_list = list_new();
@@ -933,10 +940,125 @@ int area_clear_net_title(struct vty *vty, const char *net_title)
/*
* 'show isis interface' command
*/
-
-int show_isis_interface_common(struct vty *vty, const char *ifname, char detail,
+int show_isis_interface_common(struct vty *vty, struct json_object *json,
+ const char *ifname, char detail,
const char *vrf_name, bool all_vrf)
{
+ if (json) {
+ return show_isis_interface_common_json(json, ifname, detail,
+ vrf_name, all_vrf);
+ } else {
+ return show_isis_interface_common_vty(vty, ifname, detail,
+ vrf_name, all_vrf);
+ }
+}
+
+int show_isis_interface_common_json(struct json_object *json,
+ const char *ifname, char detail,
+ const char *vrf_name, bool all_vrf)
+{
+ struct listnode *anode, *cnode, *inode;
+ struct isis_area *area;
+ struct isis_circuit *circuit;
+ struct isis *isis;
+ struct json_object *areas_json, *area_json;
+ struct json_object *circuits_json, *circuit_json;
+ if (!im) {
+ // IS-IS Routing Process not enabled
+ json_object_string_add(json, "is-is-routing-process-enabled",
+ "no");
+ return CMD_SUCCESS;
+ }
+ if (vrf_name) {
+ if (all_vrf) {
+ for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) {
+ areas_json = json_object_new_array();
+ json_object_object_add(json, "areas",
+ areas_json);
+ for (ALL_LIST_ELEMENTS_RO(isis->area_list,
+ anode, area)) {
+ area_json = json_object_new_object();
+ json_object_string_add(
+ area_json, "area",
+ area->area_tag ? area->area_tag
+ : "null");
+ circuits_json = json_object_new_array();
+ json_object_object_add(area_json,
+ "circuits",
+ circuits_json);
+ for (ALL_LIST_ELEMENTS_RO(
+ area->circuit_list, cnode,
+ circuit)) {
+ circuit_json =
+ json_object_new_object();
+ json_object_int_add(
+ circuit_json, "circuit",
+ circuit->circuit_id);
+ if (!ifname)
+ isis_circuit_print_json(
+ circuit,
+ circuit_json,
+ detail);
+ else if (strcmp(circuit->interface->name, ifname) == 0)
+ isis_circuit_print_json(
+ circuit,
+ circuit_json,
+ detail);
+ json_object_array_add(
+ circuits_json,
+ circuit_json);
+ }
+ json_object_array_add(areas_json,
+ area_json);
+ }
+ }
+ return CMD_SUCCESS;
+ }
+ isis = isis_lookup_by_vrfname(vrf_name);
+ if (isis != NULL) {
+ areas_json = json_object_new_array();
+ json_object_object_add(json, "areas", areas_json);
+ for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode,
+ area)) {
+ area_json = json_object_new_object();
+ json_object_string_add(area_json, "area",
+ area->area_tag
+ ? area->area_tag
+ : "null");
+
+ circuits_json = json_object_new_array();
+ json_object_object_add(area_json, "circuits",
+ circuits_json);
+ for (ALL_LIST_ELEMENTS_RO(area->circuit_list,
+ cnode, circuit)) {
+ circuit_json = json_object_new_object();
+ json_object_int_add(
+ circuit_json, "circuit",
+ circuit->circuit_id);
+ if (!ifname)
+ isis_circuit_print_json(
+ circuit, circuit_json,
+ detail);
+ else if (
+ strcmp(circuit->interface->name,
+ ifname) == 0)
+ isis_circuit_print_json(
+ circuit, circuit_json,
+ detail);
+ json_object_array_add(circuits_json,
+ circuit_json);
+ }
+ json_object_array_add(areas_json, area_json);
+ }
+ }
+ }
+ return CMD_SUCCESS;
+}
+
+int show_isis_interface_common_vty(struct vty *vty, const char *ifname,
+ char detail, const char *vrf_name,
+ bool all_vrf)
+{
struct listnode *anode, *cnode, *inode;
struct isis_area *area;
struct isis_circuit *circuit;
@@ -990,8 +1112,7 @@ int show_isis_interface_common(struct vty *vty, const char *ifname, char detail,
circuit, vty, detail);
else if (
strcmp(circuit->interface->name,
- ifname)
- == 0)
+ ifname) == 0)
isis_circuit_print_vty(
circuit, vty, detail);
}
@@ -1003,63 +1124,90 @@ int show_isis_interface_common(struct vty *vty, const char *ifname, char detail,
DEFUN(show_isis_interface,
show_isis_interface_cmd,
- "show " PROTO_NAME " [vrf <NAME|all>] interface",
+ "show " PROTO_NAME " [vrf <NAME|all>] interface [json]",
SHOW_STR
PROTO_HELP
VRF_CMD_HELP_STR
"All VRFs\n"
+ "json output\n"
"IS-IS interface\n")
{
+ int res = CMD_SUCCESS;
const char *vrf_name = VRF_DEFAULT_NAME;
bool all_vrf = false;
int idx_vrf = 0;
+ bool uj = use_json(argc, argv);
+ json_object *json = NULL;
ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
- return show_isis_interface_common(vty, NULL, ISIS_UI_LEVEL_BRIEF,
- vrf_name, all_vrf);
+ if (uj)
+ json = json_object_new_object();
+ res = show_isis_interface_common(vty, json, NULL, ISIS_UI_LEVEL_BRIEF,
+ vrf_name, all_vrf);
+ if (uj)
+ vty_json(vty, json);
+ return res;
}
DEFUN(show_isis_interface_detail,
show_isis_interface_detail_cmd,
- "show " PROTO_NAME " [vrf <NAME|all>] interface detail",
+ "show " PROTO_NAME " [vrf <NAME|all>] interface detail [json]",
SHOW_STR
PROTO_HELP
VRF_CMD_HELP_STR
"All VRFs\n"
"IS-IS interface\n"
- "show detailed information\n")
+ "show detailed information\n"
+ "json output\n")
{
+ int res = CMD_SUCCESS;
const char *vrf_name = VRF_DEFAULT_NAME;
bool all_vrf = false;
int idx_vrf = 0;
+ bool uj = use_json(argc, argv);
+ json_object *json = NULL;
ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
- return show_isis_interface_common(vty, NULL, ISIS_UI_LEVEL_DETAIL,
- vrf_name, all_vrf);
+ if (uj)
+ json = json_object_new_object();
+ res = show_isis_interface_common(vty, json, NULL, ISIS_UI_LEVEL_DETAIL,
+ vrf_name, all_vrf);
+ if (uj)
+ vty_json(vty, json);
+ return res;
}
DEFUN(show_isis_interface_arg,
show_isis_interface_arg_cmd,
- "show " PROTO_NAME " [vrf <NAME|all>] interface WORD",
+ "show " PROTO_NAME " [vrf <NAME|all>] interface WORD [json]",
SHOW_STR
PROTO_HELP
VRF_CMD_HELP_STR
"All VRFs\n"
"IS-IS interface\n"
- "IS-IS interface name\n")
+ "IS-IS interface name\n"
+ "json output\n")
{
+ int res = CMD_SUCCESS;
int idx_word = 0;
const char *vrf_name = VRF_DEFAULT_NAME;
bool all_vrf = false;
int idx_vrf = 0;
+ bool uj = use_json(argc, argv);
+ json_object *json = NULL;
ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+ if (uj)
+ json = json_object_new_object();
char *ifname = argv_find(argv, argc, "WORD", &idx_word)
? argv[idx_word]->arg
: NULL;
- return show_isis_interface_common(vty, ifname, ISIS_UI_LEVEL_DETAIL,
- vrf_name, all_vrf);
+ res = show_isis_interface_common(
+ vty, json, ifname, ISIS_UI_LEVEL_DETAIL, vrf_name, all_vrf);
+ if (uj)
+ vty_json(vty, json);
+ return res;
}
static int id_to_sysid(struct isis *isis, const char *id, uint8_t *sysid)
@@ -1079,8 +1227,65 @@ static int id_to_sysid(struct isis *isis, const char *id, uint8_t *sysid)
return 0;
}
-static void isis_neighbor_common(struct vty *vty, const char *id, char detail,
- struct isis *isis, uint8_t *sysid)
+static void isis_neighbor_common_json(struct json_object *json, const char *id,
+ char detail, struct isis *isis,
+ uint8_t *sysid)
+{
+ struct listnode *anode, *cnode, *node;
+ struct isis_area *area;
+ struct isis_circuit *circuit;
+ struct list *adjdb;
+ struct isis_adjacency *adj;
+ struct json_object *areas_json, *area_json;
+ struct json_object *circuits_json, *circuit_json;
+ int i;
+
+ areas_json = json_object_new_array();
+ json_object_object_add(json, "areas", areas_json);
+ for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) {
+ area_json = json_object_new_object();
+ json_object_string_add(area_json, "area",
+ area->area_tag ? area->area_tag
+ : "null");
+ circuits_json = json_object_new_array();
+ json_object_object_add(area_json, "circuits", circuits_json);
+ for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit)) {
+ circuit_json = json_object_new_object();
+ json_object_int_add(circuit_json, "circuit",
+ circuit->circuit_id);
+ if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
+ for (i = 0; i < 2; i++) {
+ adjdb = circuit->u.bc.adjdb[i];
+ if (adjdb && adjdb->count) {
+ for (ALL_LIST_ELEMENTS_RO(
+ adjdb, node, adj))
+ if (!id ||
+ !memcmp(adj->sysid,
+ sysid,
+ ISIS_SYS_ID_LEN))
+ isis_adj_print_json(
+ adj,
+ circuit_json,
+ detail);
+ }
+ }
+ } else if (circuit->circ_type == CIRCUIT_T_P2P &&
+ circuit->u.p2p.neighbor) {
+ adj = circuit->u.p2p.neighbor;
+ if (!id ||
+ !memcmp(adj->sysid, sysid, ISIS_SYS_ID_LEN))
+ isis_adj_print_json(adj, circuit_json,
+ detail);
+ }
+ json_object_array_add(circuits_json, circuit_json);
+ }
+ json_object_array_add(areas_json, area_json);
+ }
+}
+
+static void isis_neighbor_common_vty(struct vty *vty, const char *id,
+ char detail, struct isis *isis,
+ uint8_t *sysid)
{
struct listnode *anode, *cnode, *node;
struct isis_area *area;
@@ -1103,9 +1308,8 @@ static void isis_neighbor_common(struct vty *vty, const char *id, char detail,
if (adjdb && adjdb->count) {
for (ALL_LIST_ELEMENTS_RO(
adjdb, node, adj))
- if (!id
- || !memcmp(
- adj->sysid,
+ if (!id ||
+ !memcmp(adj->sysid,
sysid,
ISIS_SYS_ID_LEN))
isis_adj_print_vty(
@@ -1114,24 +1318,35 @@ static void isis_neighbor_common(struct vty *vty, const char *id, char detail,
detail);
}
}
- } else if (circuit->circ_type == CIRCUIT_T_P2P
- && circuit->u.p2p.neighbor) {
+ } else if (circuit->circ_type == CIRCUIT_T_P2P &&
+ circuit->u.p2p.neighbor) {
adj = circuit->u.p2p.neighbor;
- if (!id
- || !memcmp(adj->sysid, sysid,
- ISIS_SYS_ID_LEN))
+ if (!id ||
+ !memcmp(adj->sysid, sysid, ISIS_SYS_ID_LEN))
isis_adj_print_vty(adj, vty, detail);
}
}
}
+}
+static void isis_neighbor_common(struct vty *vty, struct json_object *json,
+ const char *id, char detail, struct isis *isis,
+ uint8_t *sysid)
+{
+ if (json) {
+ isis_neighbor_common_json(json, id, detail,isis,sysid);
+ } else {
+ isis_neighbor_common_vty(vty, id, detail,isis,sysid);
+ }
}
+
/*
* 'show isis neighbor' command
*/
-int show_isis_neighbor_common(struct vty *vty, const char *id, char detail,
- const char *vrf_name, bool all_vrf)
+int show_isis_neighbor_common(struct vty *vty, struct json_object *json,
+ const char *id, char detail, const char *vrf_name,
+ bool all_vrf)
{
struct listnode *node;
uint8_t sysid[ISIS_SYS_ID_LEN];
@@ -1150,8 +1365,8 @@ int show_isis_neighbor_common(struct vty *vty, const char *id, char detail,
id);
return CMD_SUCCESS;
}
- isis_neighbor_common(vty, id, detail, isis,
- sysid);
+ isis_neighbor_common(vty, json, id, detail,
+ isis, sysid);
}
return CMD_SUCCESS;
}
@@ -1161,7 +1376,8 @@ int show_isis_neighbor_common(struct vty *vty, const char *id, char detail,
vty_out(vty, "Invalid system id %s\n", id);
return CMD_SUCCESS;
}
- isis_neighbor_common(vty, id, detail, isis, sysid);
+ isis_neighbor_common(vty, json, id, detail, isis,
+ sysid);
}
}
@@ -1254,64 +1470,91 @@ int clear_isis_neighbor_common(struct vty *vty, const char *id, const char *vrf_
DEFUN(show_isis_neighbor,
show_isis_neighbor_cmd,
- "show " PROTO_NAME " [vrf <NAME|all>] neighbor",
+ "show " PROTO_NAME " [vrf <NAME|all>] neighbor [json]",
SHOW_STR
PROTO_HELP
VRF_CMD_HELP_STR
"All vrfs\n"
- "IS-IS neighbor adjacencies\n")
+ "IS-IS neighbor adjacencies\n"
+ "json output\n")
{
+ int res = CMD_SUCCESS;
const char *vrf_name = VRF_DEFAULT_NAME;
bool all_vrf = false;
int idx_vrf = 0;
+ bool uj = use_json(argc, argv);
+ json_object *json = NULL;
ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
- return show_isis_neighbor_common(vty, NULL, ISIS_UI_LEVEL_BRIEF,
- vrf_name, all_vrf);
+ if (uj)
+ json = json_object_new_object();
+ res = show_isis_neighbor_common(vty, json, NULL, ISIS_UI_LEVEL_BRIEF,
+ vrf_name, all_vrf);
+ if (uj)
+ vty_json(vty, json);
+ return res;
}
DEFUN(show_isis_neighbor_detail,
show_isis_neighbor_detail_cmd,
- "show " PROTO_NAME " [vrf <NAME|all>] neighbor detail",
+ "show " PROTO_NAME " [vrf <NAME|all>] neighbor detail [json]",
SHOW_STR
PROTO_HELP
VRF_CMD_HELP_STR
"all vrfs\n"
"IS-IS neighbor adjacencies\n"
- "show detailed information\n")
+ "show detailed information\n"
+ "json output\n")
{
+ int res = CMD_SUCCESS;
const char *vrf_name = VRF_DEFAULT_NAME;
bool all_vrf = false;
int idx_vrf = 0;
+ bool uj = use_json(argc, argv);
+ json_object *json = NULL;
ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+ if (uj)
+ json = json_object_new_object();
- return show_isis_neighbor_common(vty, NULL, ISIS_UI_LEVEL_DETAIL,
- vrf_name, all_vrf);
+ res = show_isis_neighbor_common(vty, json, NULL, ISIS_UI_LEVEL_DETAIL,
+ vrf_name, all_vrf);
+ if (uj)
+ vty_json(vty, json);
+ return res;
}
DEFUN(show_isis_neighbor_arg,
show_isis_neighbor_arg_cmd,
- "show " PROTO_NAME " [vrf <NAME|all>] neighbor WORD",
+ "show " PROTO_NAME " [vrf <NAME|all>] neighbor WORD [json]",
SHOW_STR
PROTO_HELP
VRF_CMD_HELP_STR
"All vrfs\n"
"IS-IS neighbor adjacencies\n"
- "System id\n")
+ "System id\n"
+ "json output\n")
{
+ int res = CMD_SUCCESS;
int idx_word = 0;
const char *vrf_name = VRF_DEFAULT_NAME;
bool all_vrf = false;
int idx_vrf = 0;
+ bool uj = use_json(argc, argv);
+ json_object *json = NULL;
ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+ if (uj)
+ json = json_object_new_object();
char *id = argv_find(argv, argc, "WORD", &idx_word)
? argv[idx_word]->arg
: NULL;
- return show_isis_neighbor_common(vty, id, ISIS_UI_LEVEL_DETAIL,
- vrf_name, all_vrf);
+ res = show_isis_neighbor_common(vty, json, id, ISIS_UI_LEVEL_DETAIL,
+ vrf_name, all_vrf);
+ if (uj)
+ vty_json(vty, json);
+ return res;
}
DEFUN(clear_isis_neighbor,
@@ -2056,7 +2299,152 @@ DEFUN(show_isis_spf_ietf, show_isis_spf_ietf_cmd,
return CMD_SUCCESS;
}
-static void common_isis_summary(struct vty *vty, struct isis *isis)
+
+static const char *pdu_counter_index_to_name_json(enum pdu_counter_index index)
+{
+ switch (index) {
+ case L1_LAN_HELLO_INDEX:
+ return "l1-iih";
+ case L2_LAN_HELLO_INDEX:
+ return "l2-iih";
+ case P2P_HELLO_INDEX:
+ return "p2p-iih";
+ case L1_LINK_STATE_INDEX:
+ return "l1-lsp";
+ case L2_LINK_STATE_INDEX:
+ return "l2-lsp";
+ case FS_LINK_STATE_INDEX:
+ return "fs-lsp";
+ case L1_COMPLETE_SEQ_NUM_INDEX:
+ return "l1-csnp";
+ case L2_COMPLETE_SEQ_NUM_INDEX:
+ return "l2-csnp";
+ case L1_PARTIAL_SEQ_NUM_INDEX:
+ return "l1-psnp";
+ case L2_PARTIAL_SEQ_NUM_INDEX:
+ return "l2-psnp";
+ default:
+ return "???????";
+ }
+}
+
+static void common_isis_summary_json(struct json_object *json,
+ struct isis *isis)
+{
+ int level;
+ json_object *areas_json, *area_json, *tx_pdu_json, *rx_pdu_json,
+ *levels_json, *level_json;
+ struct listnode *node, *node2;
+ struct isis_area *area;
+ time_t cur;
+ char uptime[MONOTIME_STRLEN];
+ char stier[5];
+ json_object_string_add(json, "vrf", isis->name);
+ json_object_int_add(json, "process-id", isis->process_id);
+ if (isis->sysid_set)
+ json_object_string_add(json, "system-id",
+ sysid_print(isis->sysid));
+
+ cur = time(NULL);
+ cur -= isis->uptime;
+ frrtime_to_interval(cur, uptime, sizeof(uptime));
+ json_object_string_add(json, "up-time", uptime);
+ if (isis->area_list)
+ json_object_int_add(json, "number-areas",
+ isis->area_list->count);
+ areas_json = json_object_new_array();
+ json_object_object_add(json, "areas", areas_json);
+ for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) {
+ area_json = json_object_new_object();
+ json_object_string_add(area_json, "area",
+ area->area_tag ? area->area_tag
+ : "null");
+
+
+ if (fabricd) {
+ uint8_t tier = fabricd_tier(area);
+ snprintfrr(stier, sizeof(stier), "%s", &tier);
+ json_object_string_add(area_json, "tier",
+ tier == ISIS_TIER_UNDEFINED
+ ? "undefined"
+ : stier);
+ }
+
+ if (listcount(area->area_addrs) > 0) {
+ struct area_addr *area_addr;
+ for (ALL_LIST_ELEMENTS_RO(area->area_addrs, node2,
+ area_addr)) {
+ json_object_string_add(
+ area_json, "net",
+ isonet_print(area_addr->area_addr,
+ area_addr->addr_len +
+ ISIS_SYS_ID_LEN +
+ 1));
+ }
+ }
+
+ tx_pdu_json = json_object_new_object();
+ json_object_object_add(area_json, "tx-pdu-type", tx_pdu_json);
+ for (int i = 0; i < PDU_COUNTER_SIZE; i++) {
+ if (!area->pdu_tx_counters[i])
+ continue;
+ json_object_int_add(tx_pdu_json,
+ pdu_counter_index_to_name_json(i),
+ area->pdu_tx_counters[i]);
+ }
+ json_object_int_add(tx_pdu_json, "lsp-rxmt",
+ area->lsp_rxmt_count);
+
+ rx_pdu_json = json_object_new_object();
+ json_object_object_add(area_json, "rx-pdu-type", rx_pdu_json);
+ for (int i = 0; i < PDU_COUNTER_SIZE; i++) {
+ if (!area->pdu_rx_counters[i])
+ continue;
+ json_object_int_add(rx_pdu_json,
+ pdu_counter_index_to_name_json(i),
+ area->pdu_rx_counters[i]);
+ }
+
+ levels_json = json_object_new_array();
+ json_object_object_add(area_json, "levels", levels_json);
+ for (level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) {
+ if ((area->is_type & level) == 0)
+ continue;
+ level_json = json_object_new_object();
+ json_object_int_add(level_json, "id", level);
+ json_object_int_add(level_json, "lsp0-regenerated",
+ area->lsp_gen_count[level - 1]);
+ json_object_int_add(level_json, "lsp-purged",
+ area->lsp_purge_count[level - 1]);
+ if (area->spf_timer[level - 1])
+ json_object_string_add(level_json, "spf",
+ "pending");
+ else
+ json_object_string_add(level_json, "spf",
+ "no pending");
+ json_object_int_add(level_json, "minimum-interval",
+ area->min_spf_interval[level - 1]);
+ if (area->spf_delay_ietf[level - 1])
+ json_object_string_add(
+ level_json, "ietf-spf-delay-activated",
+ "not used");
+ if (area->ip_circuits) {
+ isis_spf_print_json(
+ area->spftree[SPFTREE_IPV4][level - 1],
+ level_json);
+ }
+ if (area->ipv6_circuits) {
+ isis_spf_print_json(
+ area->spftree[SPFTREE_IPV6][level - 1],
+ level_json);
+ }
+ json_object_array_add(levels_json, level_json);
+ }
+ json_object_array_add(areas_json, area_json);
+ }
+}
+
+static void common_isis_summary_vty(struct vty *vty, struct isis *isis)
{
struct listnode *node, *node2;
struct isis_area *area;
@@ -2156,10 +2544,21 @@ static void common_isis_summary(struct vty *vty, struct isis *isis)
}
}
+static void common_isis_summary(struct vty *vty, struct json_object *json,
+ struct isis *isis)
+{
+ if (json) {
+ common_isis_summary_json(json, isis);
+ } else {
+ common_isis_summary_vty(vty, isis);
+ }
+}
+
DEFUN(show_isis_summary, show_isis_summary_cmd,
- "show " PROTO_NAME " [vrf <NAME|all>] summary",
+ "show " PROTO_NAME " [vrf <NAME|all>] summary [json]",
SHOW_STR PROTO_HELP VRF_CMD_HELP_STR
"All VRFs\n"
+ "json output\n"
"summary\n")
{
struct listnode *node;
@@ -2167,25 +2566,30 @@ DEFUN(show_isis_summary, show_isis_summary_cmd,
struct isis *isis;
const char *vrf_name = VRF_DEFAULT_NAME;
bool all_vrf = false;
+ bool uj = use_json(argc, argv);
+ json_object *json = NULL;
ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf)
if (!im) {
vty_out(vty, PROTO_NAME " is not running\n");
return CMD_SUCCESS;
}
+ if (uj)
+ json = json_object_new_object();
if (vrf_name) {
if (all_vrf) {
for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis))
- common_isis_summary(vty, isis);
+ common_isis_summary(vty, json, isis);
return CMD_SUCCESS;
}
isis = isis_lookup_by_vrfname(vrf_name);
if (isis != NULL)
- common_isis_summary(vty, isis);
+ common_isis_summary(vty, json, isis);
}
- vty_out(vty, "\n");
+ if (uj)
+ vty_json(vty, json);
return CMD_SUCCESS;
}
@@ -2250,9 +2654,40 @@ struct isis_lsp *lsp_for_sysid(struct lspdb_head *head, const char *sysid_str,
return lsp;
}
-void show_isis_database_lspdb(struct vty *vty, struct isis_area *area,
- int level, struct lspdb_head *lspdb,
- const char *sysid_str, int ui_level)
+void show_isis_database_lspdb_json(struct json_object *json,
+ struct isis_area *area, int level,
+ struct lspdb_head *lspdb,
+ const char *sysid_str, int ui_level)
+{
+ struct isis_lsp *lsp;
+ int lsp_count;
+
+ if (lspdb_count(lspdb) > 0) {
+ lsp = lsp_for_sysid(lspdb, sysid_str, area->isis);
+
+ if (lsp != NULL || sysid_str == NULL) {
+ json_object_int_add(json, "id", level + 1);
+ }
+
+ if (lsp) {
+ if (ui_level == ISIS_UI_LEVEL_DETAIL)
+ lsp_print_detail(lsp, NULL, json,
+ area->dynhostname, area->isis);
+ else
+ lsp_print_json(lsp, json, area->dynhostname,
+ area->isis);
+ } else if (sysid_str == NULL) {
+ lsp_count =
+ lsp_print_all(NULL, json, lspdb, ui_level,
+ area->dynhostname, area->isis);
+
+ json_object_int_add(json, "count", lsp_count);
+ }
+ }
+}
+void show_isis_database_lspdb_vty(struct vty *vty, struct isis_area *area,
+ int level, struct lspdb_head *lspdb,
+ const char *sysid_str, int ui_level)
{
struct isis_lsp *lsp;
int lsp_count;
@@ -2271,14 +2706,14 @@ void show_isis_database_lspdb(struct vty *vty, struct isis_area *area,
if (lsp) {
if (ui_level == ISIS_UI_LEVEL_DETAIL)
- lsp_print_detail(lsp, vty, area->dynhostname,
- area->isis);
+ lsp_print_detail(lsp, vty, NULL,
+ area->dynhostname, area->isis);
else
- lsp_print(lsp, vty, area->dynhostname,
- area->isis);
+ lsp_print_vty(lsp, vty, area->dynhostname,
+ area->isis);
} else if (sysid_str == NULL) {
lsp_count =
- lsp_print_all(vty, lspdb, ui_level,
+ lsp_print_all(vty, NULL, lspdb, ui_level,
area->dynhostname, area->isis);
vty_out(vty, " %u LSPs\n\n", lsp_count);
@@ -2286,7 +2721,43 @@ void show_isis_database_lspdb(struct vty *vty, struct isis_area *area,
}
}
-static void show_isis_database_common(struct vty *vty, const char *sysid_str,
+static void show_isis_database_json(struct json_object *json, const char *sysid_str,
+ int ui_level, struct isis *isis)
+{
+ struct listnode *node;
+ struct isis_area *area;
+ int level;
+ struct json_object *tag_area_json,*area_json, *lsp_json, *area_arr_json, *arr_json;
+ uint8_t area_cnt = 0;
+
+ if (isis->area_list->count == 0)
+ return;
+
+ area_arr_json = json_object_new_array();
+ json_object_object_add(json, "areas", area_arr_json);
+ for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) {
+ area_json = json_object_new_object();
+ tag_area_json = json_object_new_object();
+ json_object_string_add(tag_area_json, "name",
+ area->area_tag ? area->area_tag
+ : "null");
+
+ arr_json = json_object_new_array();
+ json_object_object_add(area_json,"area",tag_area_json);
+ json_object_object_add(area_json,"levels",arr_json);
+ for (level = 0; level < ISIS_LEVELS; level++) {
+ lsp_json = json_object_new_object();
+ show_isis_database_lspdb_json(lsp_json, area, level,
+ &area->lspdb[level],
+ sysid_str, ui_level);
+ json_object_array_add(arr_json, lsp_json);
+ }
+ json_object_array_add(area_arr_json, area_json);
+ area_cnt++;
+ }
+}
+
+static void show_isis_database_vty(struct vty *vty, const char *sysid_str,
int ui_level, struct isis *isis)
{
struct listnode *node;
@@ -2301,11 +2772,22 @@ static void show_isis_database_common(struct vty *vty, const char *sysid_str,
area->area_tag ? area->area_tag : "null");
for (level = 0; level < ISIS_LEVELS; level++)
- show_isis_database_lspdb(vty, area, level,
+ show_isis_database_lspdb_vty(vty, area, level,
&area->lspdb[level], sysid_str,
ui_level);
}
}
+
+static void show_isis_database_common(struct vty *vty, struct json_object *json, const char *sysid_str,
+ int ui_level, struct isis *isis)
+{
+ if (json) {
+ show_isis_database_json(json, sysid_str, ui_level, isis);
+ } else {
+ show_isis_database_vty(vty, sysid_str, ui_level, isis);
+ }
+}
+
/*
* This function supports following display options:
* [ show isis database [detail] ]
@@ -2322,7 +2804,7 @@ static void show_isis_database_common(struct vty *vty, const char *sysid_str,
* [ show isis database detail <sysid>.<pseudo-id>-<fragment-number> ]
* [ show isis database detail <hostname>.<pseudo-id>-<fragment-number> ]
*/
-static int show_isis_database(struct vty *vty, const char *sysid_str,
+static int show_isis_database(struct vty *vty, struct json_object *json, const char *sysid_str,
int ui_level, const char *vrf_name, bool all_vrf)
{
struct listnode *node;
@@ -2331,28 +2813,30 @@ static int show_isis_database(struct vty *vty, const char *sysid_str,
if (vrf_name) {
if (all_vrf) {
for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis))
- show_isis_database_common(vty, sysid_str,
+ show_isis_database_common(vty, json, sysid_str,
ui_level, isis);
return CMD_SUCCESS;
}
isis = isis_lookup_by_vrfname(vrf_name);
if (isis)
- show_isis_database_common(vty, sysid_str, ui_level,
- isis);
+ show_isis_database_common(vty, json, sysid_str,
+ ui_level, isis);
}
return CMD_SUCCESS;
}
DEFUN(show_database, show_database_cmd,
- "show " PROTO_NAME " [vrf <NAME|all>] database [detail] [WORD]",
+ "show " PROTO_NAME " [vrf <NAME|all>] database [detail] [WORD] [json]",
SHOW_STR PROTO_HELP VRF_CMD_HELP_STR
"All VRFs\n"
"Link state database\n"
"Detailed information\n"
- "LSP ID\n")
+ "LSP ID\n"
+ "json output\n")
{
+ int res = CMD_SUCCESS;
int idx = 0;
int idx_vrf = 0;
const char *vrf_name = VRF_DEFAULT_NAME;
@@ -2361,8 +2845,17 @@ DEFUN(show_database, show_database_cmd,
? ISIS_UI_LEVEL_DETAIL
: ISIS_UI_LEVEL_BRIEF;
char *id = argv_find(argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL;
+ bool uj = use_json(argc, argv);
+ json_object *json = NULL;
+
ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
- return show_isis_database(vty, id, uilevel, vrf_name, all_vrf);
+ if (uj)
+ json = json_object_new_object();
+
+ res = show_isis_database(vty, json, id, uilevel, vrf_name, all_vrf);
+ if (uj)
+ vty_json(vty, json);
+ return res;
}
#ifdef FABRICD
diff --git a/isisd/isisd.h b/isisd/isisd.h
index 7f8474a5f..c313fd9ef 100644
--- a/isisd/isisd.h
+++ b/isisd/isisd.h
@@ -89,6 +89,8 @@ struct isis_master {
};
#define F_ISIS_UNIT_TEST 0x01
+#define ISIS_DEFAULT_MAX_AREA_ADDRESSES 3
+
struct isis {
vrf_id_t vrf_id;
char *name;
@@ -305,9 +307,13 @@ int isis_area_passwd_cleartext_set(struct isis_area *area, int level,
const char *passwd, uint8_t snp_auth);
int isis_area_passwd_hmac_md5_set(struct isis_area *area, int level,
const char *passwd, uint8_t snp_auth);
-void show_isis_database_lspdb(struct vty *vty, struct isis_area *area,
- int level, struct lspdb_head *lspdb,
- const char *argv, int ui_level);
+void show_isis_database_lspdb_json(struct json_object *json,
+ struct isis_area *area, int level,
+ struct lspdb_head *lspdb, const char *argv,
+ int ui_level);
+void show_isis_database_lspdb_vty(struct vty *vty, struct isis_area *area,
+ int level, struct lspdb_head *lspdb,
+ const char *argv, int ui_level);
/* YANG paths */
#define ISIS_INSTANCE "/frr-isisd:isis/instance"
diff --git a/tests/isisd/test_fuzz_isis_tlv.c b/tests/isisd/test_fuzz_isis_tlv.c
index 97aade657..8f0b92d0f 100644
--- a/tests/isisd/test_fuzz_isis_tlv.c
+++ b/tests/isisd/test_fuzz_isis_tlv.c
@@ -108,12 +108,12 @@ static int test(FILE *input, FILE *output)
}
fprintf(output, "Unpack log:\n%s", log);
- const char *s_tlvs = isis_format_tlvs(tlvs);
+ const char *s_tlvs = isis_format_tlvs(tlvs, NULL);
fprintf(output, "Unpacked TLVs:\n%s", s_tlvs);
struct isis_item *orig_auth = tlvs->isis_auth.head;
tlvs->isis_auth.head = NULL;
- s_tlvs = isis_format_tlvs(tlvs);
+ s_tlvs = isis_format_tlvs(tlvs, NULL);
struct isis_tlvs *tlv_copy = isis_copy_tlvs(tlvs);
tlvs->isis_auth.head = orig_auth;
isis_free_tlvs(tlvs);
@@ -133,7 +133,7 @@ static int test(FILE *input, FILE *output)
}
char *orig_tlvs = XSTRDUP(MTYPE_TMP, s_tlvs);
- s_tlvs = isis_format_tlvs(tlvs);
+ s_tlvs = isis_format_tlvs(tlvs, NULL);
if (strcmp(orig_tlvs, s_tlvs)) {
fprintf(output,
@@ -166,7 +166,7 @@ static int test(FILE *input, FILE *output)
fprintf(output, "Could not pack fragment, too large.\n");
assert(0);
}
- sbuf_push(&fragment_format, 0, "%s", isis_format_tlvs(tlvs));
+ sbuf_push(&fragment_format, 0, "%s", isis_format_tlvs(tlvs, NULL));
isis_free_tlvs(tlvs);
}
list_delete(&fragments);
diff --git a/tests/isisd/test_isis_spf.c b/tests/isisd/test_isis_spf.c
index a30f33cca..971aba4c4 100644
--- a/tests/isisd/test_isis_spf.c
+++ b/tests/isisd/test_isis_spf.c
@@ -294,7 +294,7 @@ static int test_run(struct vty *vty, const struct isis_topology *topology,
/* Print the LDPDB. */
if (CHECK_FLAG(flags, F_DISPLAY_LSPDB))
- show_isis_database_lspdb(vty, area, level - 1,
+ show_isis_database_lspdb_vty(vty, area, level - 1,
&area->lspdb[level - 1], NULL,
ISIS_UI_LEVEL_DETAIL);
diff --git a/tests/topotests/isis_topo1/test_isis_topo1.py b/tests/topotests/isis_topo1/test_isis_topo1.py
index 94c5faf2e..014722387 100644
--- a/tests/topotests/isis_topo1/test_isis_topo1.py
+++ b/tests/topotests/isis_topo1/test_isis_topo1.py
@@ -236,6 +236,94 @@ def test_isis_linux_route6_installation():
assert topotest.json_cmp(actual, expected) is None, assertmsg
+def test_isis_summary_json():
+ "Check json struct in show isis summary json"
+
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Checking 'show isis summary json'")
+ for rname, router in tgen.routers().items():
+ logger.info("Checking router %s", rname)
+ json_output = tgen.gears[rname].vtysh_cmd("show isis summary json", isjson=True)
+ assertmsg = "Test isis summary json failed in '{}' data '{}'".format(rname, json_output)
+ assert json_output['vrf'] == "default", assertmsg
+ assert json_output['areas'][0]['area'] == "1", assertmsg
+ assert json_output['areas'][0]['levels'][0]['id'] != '3', assertmsg
+
+
+def test_isis_interface_json():
+ "Check json struct in show isis interface json"
+
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Checking 'show isis interface json'")
+ for rname, router in tgen.routers().items():
+ logger.info("Checking router %s", rname)
+ json_output = tgen.gears[rname].vtysh_cmd("show isis interface json", isjson=True)
+ assertmsg = "Test isis interface json failed in '{}' data '{}'".format(rname, json_output)
+ assert json_output['areas'][0]['circuits'][0]['interface']['name'] == rname+"-eth0", assertmsg
+
+ for rname, router in tgen.routers().items():
+ logger.info("Checking router %s", rname)
+ json_output = tgen.gears[rname].vtysh_cmd("show isis interface detail json", isjson=True)
+ assertmsg = "Test isis interface json failed in '{}' data '{}'".format(rname, json_output)
+ assert json_output['areas'][0]['circuits'][0]['interface']['name'] == rname+"-eth0", assertmsg
+
+
+def test_isis_neighbor_json():
+ "Check json struct in show isis neighbor json"
+
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ #tgen.mininet_cli()
+ logger.info("Checking 'show isis neighbor json'")
+ for rname, router in tgen.routers().items():
+ logger.info("Checking router %s", rname)
+ json_output = tgen.gears[rname].vtysh_cmd("show isis neighbor json", isjson=True)
+ assertmsg = "Test isis neighbor json failed in '{}' data '{}'".format(rname, json_output)
+ assert json_output['areas'][0]['circuits'][0]['interface'] == rname+"-eth0", assertmsg
+
+ for rname, router in tgen.routers().items():
+ logger.info("Checking router %s", rname)
+ json_output = tgen.gears[rname].vtysh_cmd("show isis neighbor detail json", isjson=True)
+ assertmsg = "Test isis neighbor json failed in '{}' data '{}'".format(rname, json_output)
+ assert json_output['areas'][0]['circuits'][0]['interface']['name'] == rname+"-eth0", assertmsg
+
+
+def test_isis_database_json():
+ "Check json struct in show isis database json"
+
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ #tgen.mininet_cli()
+ logger.info("Checking 'show isis database json'")
+ for rname, router in tgen.routers().items():
+ logger.info("Checking router %s", rname)
+ json_output = tgen.gears[rname].vtysh_cmd("show isis database json", isjson=True)
+ assertmsg = "Test isis database json failed in '{}' data '{}'".format(rname, json_output)
+ assert json_output['areas'][0]['area']['name'] == "1", assertmsg
+ assert json_output['areas'][0]['levels'][0]['id'] != '3', assertmsg
+
+ for rname, router in tgen.routers().items():
+ logger.info("Checking router %s", rname)
+ json_output = tgen.gears[rname].vtysh_cmd("show isis database detail json", isjson=True)
+ assertmsg = "Test isis database json failed in '{}' data '{}'".format(rname, json_output)
+ assert json_output['areas'][0]['area']['name'] == "1", assertmsg
+ assert json_output['areas'][0]['levels'][0]['id'] != '3', assertmsg
+
+
def test_memory_leak():
"Run the memory leak test and report results."
tgen = get_topogen()