From: Javier Garcia Date: Wed, 23 Feb 2022 15:51:07 +0000 (+0100) Subject: isisd: Add json to show isis interface command. X-Git-Tag: frr-8.5.1~1184^2~3 X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=9fee4d4c6038ef6b14e9f509d6b04d189660c4cd;p=mirror_frr.git isisd: Add json to show isis interface command. Signed-off-by: Javier Garcia --- diff --git a/doc/user/isisd.rst b/doc/user/isisd.rst index 2bb45a37f..d9497ea6e 100644 --- a/doc/user/isisd.rst +++ b/doc/user/isisd.rst @@ -280,7 +280,7 @@ Showing ISIS information Show information about ISIS node. -.. clicmd:: show isis interface [detail] [IFNAME] +.. clicmd:: show isis [vrf ] interface [detail] [IFNAME] [json] Show state and configuration of ISIS specified interface, or all interfaces if no interface is given with or without details. 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/isisd.c b/isisd/isisd.c index 99bf7674a..5f9985ae8 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -109,12 +109,17 @@ 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); /* Link ISIS instance to VRF. */ void isis_vrf_link(struct isis *isis, struct vrf *vrf) @@ -933,9 +938,101 @@ 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; + 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"); + + for (ALL_LIST_ELEMENTS_RO( + area->circuit_list, cnode, + circuit)) + if (!ifname) + isis_circuit_print_json( + circuit, + area_json, + detail); + else if (strcmp(circuit->interface->name, ifname) == 0) + isis_circuit_print_json( + circuit, + area_json, + detail); + 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"); + + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, + cnode, circuit)) + if (!ifname) + isis_circuit_print_json( + circuit, area_json, + detail); + else if ( + strcmp(circuit->interface->name, + ifname) == 0) + isis_circuit_print_json( + circuit, area_json, + detail); + 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; @@ -990,8 +1087,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 +1099,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 ] interface", + "show " PROTO_NAME " [vrf ] 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 ] interface detail", + "show " PROTO_NAME " [vrf ] 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 ] interface WORD", + "show " PROTO_NAME " [vrf ] 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)