diff options
Diffstat (limited to 'isisd/isisd.c')
| -rw-r--r-- | isisd/isisd.c | 633 |
1 files changed, 563 insertions, 70 deletions
diff --git a/isisd/isisd.c b/isisd/isisd.c index 3fa2b7cc20..369b83396a 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 |
