From f328dc606e35abea55706452b105bd8d78728d6c Mon Sep 17 00:00:00 2001 From: rgirada Date: Thu, 23 Jul 2020 16:25:04 -0700 Subject: [PATCH] ospfd: json support for ospf database command. Description: Added json support to ospf lsdb command and its subcommands. Added json to the following sub commands. show ip ospf database json show ip ospf database router json show ip ospf database network json show ip ospf database external json show ip ospf database summary json show ip ospf database asbr-summary json show ip ospf database nssa-external json show ip ospf databas max-age json show ip ospf database self-originate json Signed-off-by: Rajesh Girada --- doc/user/ospfd.rst | 68 +-- ospfd/ospf_opaque.c | 23 +- ospfd/ospf_opaque.h | 4 +- ospfd/ospf_vty.c | 1012 +++++++++++++++++++++++++++++++++---------- 4 files changed, 847 insertions(+), 260 deletions(-) diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst index b66774ca0e..d0c1b51820 100644 --- a/doc/user/ospfd.rst +++ b/doc/user/ospfd.rst @@ -905,59 +905,63 @@ Showing Information .. _show-ip-ospf: -.. index:: show ip ospf -.. clicmd:: show ip ospf +.. index:: show ip ospf [json] +.. clicmd:: show ip ospf [json] Show information on a variety of general OSPF and area state and configuration information. -.. index:: show ip ospf interface [INTERFACE] -.. clicmd:: show ip ospf interface [INTERFACE] +.. index:: show ip ospf interface [INTERFACE] [json] +.. clicmd:: show ip ospf interface [INTERFACE] [json] Show state and configuration of OSPF the specified interface, or all interfaces if no interface is given. -.. index:: show ip ospf neighbor -.. clicmd:: show ip ospf neighbor +.. index:: show ip ospf neighbor [json] +.. clicmd:: show ip ospf neighbor [json] -.. index:: show ip ospf neighbor INTERFACE -.. clicmd:: show ip ospf neighbor INTERFACE +.. index:: show ip ospf neighbor INTERFACE [json] +.. clicmd:: show ip ospf neighbor INTERFACE [json] -.. index:: show ip ospf neighbor detail -.. clicmd:: show ip ospf neighbor detail +.. index:: show ip ospf neighbor detail [json] +.. clicmd:: show ip ospf neighbor detail [json] -.. index:: show ip ospf neighbor INTERFACE detail -.. clicmd:: show ip ospf neighbor INTERFACE detail +.. index:: show ip ospf neighbor INTERFACE detail [json] +.. clicmd:: show ip ospf neighbor INTERFACE detail [json] -.. index:: show ip ospf database -.. clicmd:: show ip ospf database + Display lsa information of LSDB. + Json o/p of this command covers base route information + i.e all LSAs except opaque lsa info. -.. index:: show ip ospf database (asbr-summary|external|network|router|summary) -.. clicmd:: show ip ospf database (asbr-summary|external|network|router|summary) +.. index:: show ip ospf database [json] +.. clicmd:: show ip ospf database [json] -.. index:: show ip ospf database (asbr-summary|external|network|router|summary) LINK-STATE-ID -.. clicmd:: show ip ospf database (asbr-summary|external|network|router|summary) LINK-STATE-ID +.. index:: show ip ospf database (asbr-summary|external|network|router|summary) [json] +.. clicmd:: show ip ospf database (asbr-summary|external|network|router|summary) [json] -.. index:: show ip ospf database (asbr-summary|external|network|router|summary) LINK-STATE-ID adv-router ADV-ROUTER -.. clicmd:: show ip ospf database (asbr-summary|external|network|router|summary) LINK-STATE-ID adv-router ADV-ROUTER +.. index:: show ip ospf database (asbr-summary|external|network|router|summary) LINK-STATE-ID [json] +.. clicmd:: show ip ospf database (asbr-summary|external|network|router|summary) LINK-STATE-ID [json] -.. index:: show ip ospf database (asbr-summary|external|network|router|summary) adv-router ADV-ROUTER -.. clicmd:: show ip ospf database (asbr-summary|external|network|router|summary) adv-router ADV-ROUTER +.. index:: show ip ospf database (asbr-summary|external|network|router|summary) LINK-STATE-ID adv-router ADV-ROUTER [json] +.. clicmd:: show ip ospf database (asbr-summary|external|network|router|summary) LINK-STATE-ID adv-router ADV-ROUTER [json] -.. index:: show ip ospf database (asbr-summary|external|network|router|summary) LINK-STATE-ID self-originate -.. clicmd:: show ip ospf database (asbr-summary|external|network|router|summary) LINK-STATE-ID self-originate +.. index:: show ip ospf database (asbr-summary|external|network|router|summary) adv-router ADV-ROUTER [json] +.. clicmd:: show ip ospf database (asbr-summary|external|network|router|summary) adv-router ADV-ROUTER [json] -.. index:: show ip ospf database (asbr-summary|external|network|router|summary) self-originate -.. clicmd:: show ip ospf database (asbr-summary|external|network|router|summary) self-originate +.. index:: show ip ospf database (asbr-summary|external|network|router|summary) LINK-STATE-ID self-originate [json] +.. clicmd:: show ip ospf database (asbr-summary|external|network|router|summary) LINK-STATE-ID self-originate [json] -.. index:: show ip ospf database max-age -.. clicmd:: show ip ospf database max-age +.. index:: show ip ospf database (asbr-summary|external|network|router|summary) self-originate [json] +.. clicmd:: show ip ospf database (asbr-summary|external|network|router|summary) self-originate [json] -.. index:: show ip ospf database self-originate -.. clicmd:: show ip ospf database self-originate +.. index:: show ip ospf database max-age [json] +.. clicmd:: show ip ospf database max-age [json] -.. index:: show ip ospf route -.. clicmd:: show ip ospf route +.. index:: show ip ospf database self-originate [json] +.. clicmd:: show ip ospf database self-originate [json] + +.. index:: show ip ospf route [json] +.. clicmd:: show ip ospf route [json] Show the OSPF routing table, as determined by the most recent SPF calculation. diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index 5ba61b3184..eb0c4a949a 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -1159,7 +1159,8 @@ void ospf_opaque_config_write_debug(struct vty *vty) return; } -void show_opaque_info_detail(struct vty *vty, struct ospf_lsa *lsa) +void show_opaque_info_detail(struct vty *vty, struct ospf_lsa *lsa, + json_object *json) { struct lsa_header *lsah = lsa->data; uint32_t lsid = ntohl(lsah->id.s_addr); @@ -1169,13 +1170,17 @@ void show_opaque_info_detail(struct vty *vty, struct ospf_lsa *lsa) /* Switch output functionality by vty address. */ if (vty != NULL) { - vty_out(vty, " Opaque-Type %u (%s)\n", opaque_type, - ospf_opaque_type_name(opaque_type)); - vty_out(vty, " Opaque-ID 0x%x\n", opaque_id); - - vty_out(vty, " Opaque-Info: %u octets of data%s\n", - ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE, - VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)"); + if (!json) { + vty_out(vty, " Opaque-Type %u (%s)\n", opaque_type, + ospf_opaque_type_name(opaque_type)); + vty_out(vty, " Opaque-ID 0x%x\n", opaque_id); + + vty_out(vty, " Opaque-Info: %u octets of data%s\n", + ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE, + VALID_OPAQUE_INFO_LEN(lsah) + ? "" + : "(Invalid length?)"); + } } else { zlog_debug(" Opaque-Type %u (%s)", opaque_type, ospf_opaque_type_name(opaque_type)); @@ -1200,7 +1205,7 @@ void ospf_opaque_lsa_dump(struct stream *s, uint16_t length) struct ospf_lsa lsa; lsa.data = (struct lsa_header *)stream_pnt(s); - show_opaque_info_detail(NULL, &lsa); + show_opaque_info_detail(NULL, &lsa, NULL); return; } diff --git a/ospfd/ospf_opaque.h b/ospfd/ospf_opaque.h index 96155608b2..f02f34c9af 100644 --- a/ospfd/ospf_opaque.h +++ b/ospfd/ospf_opaque.h @@ -24,6 +24,7 @@ #define _ZEBRA_OSPF_OPAQUE_H #include "vty.h" +#include #define IS_OPAQUE_LSA(type) \ ((type) == OSPF_OPAQUE_LINK_LSA || (type) == OSPF_OPAQUE_AREA_LSA \ @@ -148,7 +149,8 @@ extern void ospf_opaque_nsm_change(struct ospf_neighbor *nbr, int old_status); extern void ospf_opaque_config_write_router(struct vty *vty, struct ospf *ospf); extern void ospf_opaque_config_write_if(struct vty *vty, struct interface *ifp); extern void ospf_opaque_config_write_debug(struct vty *vty); -extern void show_opaque_info_detail(struct vty *vty, struct ospf_lsa *lsa); +extern void show_opaque_info_detail(struct vty *vty, struct ospf_lsa *lsa, + json_object *json); extern void ospf_opaque_lsa_dump(struct stream *s, uint16_t length); extern void ospf_opaque_lsa_originate_schedule(struct ospf_interface *oi, diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 7e41880bca..f8ad1064b7 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -22,6 +22,7 @@ #include #include +#include "printfrr.h" #include "monotime.h" #include "memory.h" #include "thread.h" @@ -55,6 +56,7 @@ #include "ospfd/ospf_bfd.h" #include "ospfd/ospf_ldp_sync.h" + FRR_CFG_DEFAULT_BOOL(OSPF_LOG_ADJACENCY_CHANGES, { .val_bool = true, .match_profile = "datacenter", }, { .val_bool = false }, @@ -5774,27 +5776,62 @@ DEFUN (show_ip_ospf_instance_neighbor_int_detail, } /* Show functions */ -static int show_lsa_summary(struct vty *vty, struct ospf_lsa *lsa, int self) +static int show_lsa_summary(struct vty *vty, struct ospf_lsa *lsa, int self, + json_object *json_lsa) { struct router_lsa *rl; struct summary_lsa *sl; struct as_external_lsa *asel; struct prefix_ipv4 p; + char buf[PREFIX2STR_BUFFER]; if (lsa != NULL) /* If self option is set, check LSA self flag. */ if (self == 0 || IS_LSA_SELF(lsa)) { - /* LSA common part show. */ - vty_out(vty, "%-15pI4 ", &lsa->data->id); - vty_out(vty, "%-15pI4 %4d 0x%08lx 0x%04x", - &lsa->data->adv_router, LS_AGE(lsa), - (unsigned long)ntohl(lsa->data->ls_seqnum), - ntohs(lsa->data->checksum)); + + if (!json_lsa) { + /* LSA common part show. */ + vty_out(vty, "%-15pI4", + &lsa->data->id); + vty_out(vty, "%-15s %4d 0x%08lx 0x%04x", + inet_ntoa(lsa->data->adv_router), + LS_AGE(lsa), + (unsigned long)ntohl( + lsa->data->ls_seqnum), + ntohs(lsa->data->checksum)); + } else { + char seqnum[10]; + char checksum[10]; + + snprintf(seqnum, sizeof(seqnum), "%x", + ntohl(lsa->data->ls_seqnum)); + snprintf(checksum, sizeof(checksum), "%x", + ntohs(lsa->data->checksum)); + json_object_string_add( + json_lsa, "lsId", + inet_ntoa(lsa->data->id)); + json_object_string_add( + json_lsa, "advertisedRouter", + inet_ntoa(lsa->data->adv_router)); + json_object_int_add(json_lsa, "lsaAge", + LS_AGE(lsa)); + json_object_string_add( + json_lsa, "sequenceNumber", seqnum); + json_object_string_add(json_lsa, "checksum", + checksum); + } + /* LSA specific part show. */ switch (lsa->data->type) { case OSPF_ROUTER_LSA: rl = (struct router_lsa *)lsa->data; - vty_out(vty, " %-d", ntohs(rl->links)); + + if (!json_lsa) + vty_out(vty, " %-d", ntohs(rl->links)); + else + json_object_int_add(json_lsa, + "numOfRouterLinks", + ntohs(rl->links)); break; case OSPF_SUMMARY_LSA: sl = (struct summary_lsa *)lsa->data; @@ -5804,7 +5841,14 @@ static int show_lsa_summary(struct vty *vty, struct ospf_lsa *lsa, int self) p.prefixlen = ip_masklen(sl->mask); apply_mask_ipv4(&p); - vty_out(vty, " %pFX", &p); + if (!json_lsa) + vty_out(vty, " %pFX", &p); + else { + prefix2str(&p, buf, sizeof(buf)); + json_object_string_add(json_lsa, + "summaryAddress", + buf); + } break; case OSPF_AS_EXTERNAL_LSA: case OSPF_AS_NSSA_LSA: @@ -5815,13 +5859,30 @@ static int show_lsa_summary(struct vty *vty, struct ospf_lsa *lsa, int self) p.prefixlen = ip_masklen(asel->mask); apply_mask_ipv4(&p); - vty_out(vty, " %s %pFX [0x%lx]", - IS_EXTERNAL_METRIC(asel->e[0].tos) - ? "E2" - : "E1", - &p, - (unsigned long)ntohl( - asel->e[0].route_tag)); + if (!json_lsa) + vty_out(vty, " %s %pFX [0x%lx]", + IS_EXTERNAL_METRIC( + asel->e[0].tos) + ? "E2" + : "E1", + &p, + (unsigned long)ntohl( + asel->e[0].route_tag)); + else { + prefix2str(&p, buf, sizeof(buf)); + json_object_string_add( + json_lsa, "metricType", + IS_EXTERNAL_METRIC( + asel->e[0].tos) + ? "E2" + : "E1"); + json_object_string_add(json_lsa, + "route", buf); + json_object_int_add( + json_lsa, "tag", + (unsigned long)ntohl( + asel->e[0].route_tag)); + } break; case OSPF_NETWORK_LSA: case OSPF_ASBR_SUMMARY_LSA: @@ -5831,7 +5892,9 @@ static int show_lsa_summary(struct vty *vty, struct ospf_lsa *lsa, int self) default: break; } - vty_out(vty, "\n"); + + if (!json_lsa) + vty_out(vty, "\n"); } return 0; @@ -5852,6 +5915,21 @@ static const char *const show_database_desc[] = { "AS-external Opaque-LSA", }; +static const char * const show_database_desc_json[] = { + "unknown", + "routerLinkStates", + "networkLinkStates", + "summaryLinkStates", + "asbrSummaryLinkStates", + "asExternalLinkStates", + "groupMembershipLsa", + "nssaExternalLinkStates", + "type8Lsa", + "linkLocalOpaqueLsa", + "areaLocalOpaqueLsa", + "asExternalOpaqueLsa", +}; + static const char *const show_database_header[] = { "", "Link ID ADV Router Age Seq# CkSum Link count", @@ -5867,41 +5945,97 @@ static const char *const show_database_header[] = { "Opaque-Type/Id ADV Router Age Seq# CkSum", }; -static void show_ip_ospf_database_header(struct vty *vty, struct ospf_lsa *lsa) +static void show_ip_ospf_database_header(struct vty *vty, struct ospf_lsa *lsa, + json_object *json) { struct router_lsa *rlsa = (struct router_lsa *)lsa->data; - vty_out(vty, " LS age: %d\n", LS_AGE(lsa)); - vty_out(vty, " Options: 0x%-2x : %s\n", lsa->data->options, - ospf_options_dump(lsa->data->options)); - vty_out(vty, " LS Flags: 0x%-2x %s\n", lsa->flags, - ((lsa->flags & OSPF_LSA_LOCAL_XLT) ? "(Translated from Type-7)" - : "")); - - if (lsa->data->type == OSPF_ROUTER_LSA) { - vty_out(vty, " Flags: 0x%x", rlsa->flags); - - if (rlsa->flags) - vty_out(vty, " :%s%s%s%s", - IS_ROUTER_LSA_BORDER(rlsa) ? " ABR" : "", - IS_ROUTER_LSA_EXTERNAL(rlsa) ? " ASBR" : "", - IS_ROUTER_LSA_VIRTUAL(rlsa) ? " VL-endpoint" - : "", - IS_ROUTER_LSA_SHORTCUT(rlsa) ? " Shortcut" - : ""); + if (!json) { + vty_out(vty, " LS age: %d\n", LS_AGE(lsa)); + vty_out(vty, " Options: 0x%-2x : %s\n", lsa->data->options, + ospf_options_dump(lsa->data->options)); + vty_out(vty, " LS Flags: 0x%-2x %s\n", lsa->flags, + ((lsa->flags & OSPF_LSA_LOCAL_XLT) + ? "(Translated from Type-7)" + : "")); + + if (lsa->data->type == OSPF_ROUTER_LSA) { + vty_out(vty, " Flags: 0x%x", rlsa->flags); + + if (rlsa->flags) + vty_out(vty, " :%s%s%s%s", + IS_ROUTER_LSA_BORDER(rlsa) ? " ABR" + : "", + IS_ROUTER_LSA_EXTERNAL(rlsa) ? " ASBR" + : "", + IS_ROUTER_LSA_VIRTUAL(rlsa) + ? " VL-endpoint" + : "", + IS_ROUTER_LSA_SHORTCUT(rlsa) + ? " Shortcut" + : ""); - vty_out(vty, "\n"); + vty_out(vty, "\n"); + } + vty_out(vty, " LS Type: %s\n", + lookup_msg(ospf_lsa_type_msg, lsa->data->type, NULL)); + vty_out(vty, " Link State ID: %pI4 %s\n", + &lsa->data->id, + lookup_msg(ospf_link_state_id_type_msg, lsa->data->type, + NULL)); + vty_out(vty, " Advertising Router: %pI4\n", + &lsa->data->adv_router); + vty_out(vty, " LS Seq Number: %08lx\n", + (unsigned long)ntohl(lsa->data->ls_seqnum)); + vty_out(vty, " Checksum: 0x%04x\n", + ntohs(lsa->data->checksum)); + vty_out(vty, " Length: %d\n\n", ntohs(lsa->data->length)); + } else { + char seqnum[10]; + char checksum[10]; + + snprintf(seqnum, 10, "%x", ntohl(lsa->data->ls_seqnum)); + snprintf(checksum, 10, "%x", ntohs(lsa->data->checksum)); + + json_object_int_add(json, "lsaAge", LS_AGE(lsa)); + json_object_string_add(json, "options", + ospf_options_dump(lsa->data->options)); + json_object_int_add(json, "lsaFlags", lsa->flags); + + if (lsa->flags & OSPF_LSA_LOCAL_XLT) + json_object_boolean_true_add(json, + "translatedFromType7"); + + if (lsa->data->type == OSPF_ROUTER_LSA) { + json_object_int_add(json, "flags", rlsa->flags); + + if (rlsa->flags) { + if (IS_ROUTER_LSA_BORDER(rlsa)) + json_object_boolean_true_add(json, + "abr"); + if (IS_ROUTER_LSA_EXTERNAL(rlsa)) + json_object_boolean_true_add(json, + "asbr"); + if (IS_ROUTER_LSA_VIRTUAL(rlsa)) + json_object_boolean_true_add( + json, "vlEndpoint"); + if (IS_ROUTER_LSA_SHORTCUT(rlsa)) + json_object_boolean_true_add( + json, "shortcut"); + } + } + + json_object_string_add( + json, "lsaType", + lookup_msg(ospf_lsa_type_msg, lsa->data->type, NULL)); + json_object_string_add(json, "linkStateId", + inet_ntoa(lsa->data->id)); + json_object_string_add(json, "advertisingRouter", + inet_ntoa(lsa->data->adv_router)); + json_object_string_add(json, "lsaSeqNumber", seqnum); + json_object_string_add(json, "checksum", checksum); + json_object_int_add(json, "length", ntohs(lsa->data->length)); } - vty_out(vty, " LS Type: %s\n", - lookup_msg(ospf_lsa_type_msg, lsa->data->type, NULL)); - vty_out(vty, " Link State ID: %pI4 %s\n", &lsa->data->id, - lookup_msg(ospf_link_state_id_type_msg, lsa->data->type, NULL)); - vty_out(vty, " Advertising Router: %pI4\n", - &lsa->data->adv_router); - vty_out(vty, " LS Seq Number: %08lx\n", - (unsigned long)ntohl(lsa->data->ls_seqnum)); - vty_out(vty, " Checksum: 0x%04x\n", ntohs(lsa->data->checksum)); - vty_out(vty, " Length: %d\n\n", ntohs(lsa->data->length)); } static const char *const link_type_desc[] = { @@ -5922,128 +6056,240 @@ static const char *const link_data_desc[] = { "Network Mask", "Router Interface address", }; +static const char *const link_id_desc_json[] = { + "null", "neighborRouterId", "designatedRouterAddress", + "networkAddress", "neighborRouterId", +}; + +static const char *const link_data_desc_json[] = { + "null", "routerInterfaceAddress", "routerInterfaceAddress", + "networkMask", "routerInterfaceAddress", +}; + /* Show router-LSA each Link information. */ static void show_ip_ospf_database_router_links(struct vty *vty, - struct router_lsa *rl) + struct router_lsa *rl, + json_object *json) { int len, type; - unsigned int i; + unsigned short i; + json_object *json_links = NULL; + json_object *json_link = NULL; + int metric = 0; + + if (json) + json_links = json_object_new_object(); len = ntohs(rl->header.length) - 4; for (i = 0; i < ntohs(rl->links) && len > 0; len -= 12, i++) { type = rl->link[i].type; - vty_out(vty, " Link connected to: %s\n", - link_type_desc[type]); - vty_out(vty, " (Link ID) %s: %pI4\n", link_id_desc[type], - &rl->link[i].link_id); - vty_out(vty, " (Link Data) %s: %pI4\n", - link_data_desc[type], &rl->link[i].link_data); - vty_out(vty, " Number of TOS metrics: 0\n"); - vty_out(vty, " TOS 0 Metric: %d\n", - ntohs(rl->link[i].metric)); - vty_out(vty, "\n"); + if (json) { + char link[16]; + + snprintf(link, sizeof(link), "link%u", i); + json_link = json_object_new_object(); + json_object_string_add(json_link, "linkType", + link_type_desc[type]); + json_object_string_add(json_link, + link_id_desc_json[type], + inet_ntoa(rl->link[i].link_id)); + json_object_string_add( + json_link, link_data_desc_json[type], + inet_ntoa(rl->link[i].link_data)); + json_object_int_add(json_link, "numOfTosMetrics", + metric); + json_object_int_add(json_link, "tos0Metric", + ntohs(rl->link[i].metric)); + json_object_object_add(json_links, link, json_link); + } else { + vty_out(vty, " Link connected to: %s\n", + link_type_desc[type]); + vty_out(vty, " (Link ID) %s: %pI4\n", + link_id_desc[type], + &rl->link[i].link_id); + vty_out(vty, " (Link Data) %s: %pI4\n", + link_data_desc[type], + &rl->link[i].link_data); + vty_out(vty, " Number of TOS metrics: 0\n"); + vty_out(vty, " TOS 0 Metric: %d\n", + ntohs(rl->link[i].metric)); + vty_out(vty, "\n"); + } } + if (json) + json_object_object_add(json, "routerLinks", json_links); } /* Show router-LSA detail information. */ -static int show_router_lsa_detail(struct vty *vty, struct ospf_lsa *lsa) +static int show_router_lsa_detail(struct vty *vty, struct ospf_lsa *lsa, + json_object *json) { if (lsa != NULL) { struct router_lsa *rl = (struct router_lsa *)lsa->data; - show_ip_ospf_database_header(vty, lsa); + show_ip_ospf_database_header(vty, lsa, json); - vty_out(vty, " Number of Links: %d\n\n", ntohs(rl->links)); + if (!json) + vty_out(vty, " Number of Links: %d\n\n", + ntohs(rl->links)); + else + json_object_int_add(json, "numOfLinks", + ntohs(rl->links)); - show_ip_ospf_database_router_links(vty, rl); - vty_out(vty, "\n"); + show_ip_ospf_database_router_links(vty, rl, json); + + if (!json) + vty_out(vty, "\n"); } return 0; } /* Show network-LSA detail information. */ -static int show_network_lsa_detail(struct vty *vty, struct ospf_lsa *lsa) +static int show_network_lsa_detail(struct vty *vty, struct ospf_lsa *lsa, + json_object *json) { int length, i; + json_object *json_attached_rt = NULL; + json_object *json_router = NULL; + + if (json) + json_attached_rt = json_object_new_object(); if (lsa != NULL) { struct network_lsa *nl = (struct network_lsa *)lsa->data; - show_ip_ospf_database_header(vty, lsa); + show_ip_ospf_database_header(vty, lsa, json); - vty_out(vty, " Network Mask: /%d\n", ip_masklen(nl->mask)); + if (!json) + vty_out(vty, " Network Mask: /%d\n", + ip_masklen(nl->mask)); + else + json_object_int_add(json, "networkMask", + ip_masklen(nl->mask)); length = ntohs(lsa->data->length) - OSPF_LSA_HEADER_SIZE - 4; for (i = 0; length > 0; i++, length -= 4) - vty_out(vty, " Attached Router: %pI4\n", - &nl->routers[i]); - - vty_out(vty, "\n"); + if (!json) { + vty_out(vty, " Attached Router: %pI4\n", + &nl->routers[i]); + vty_out(vty, "\n"); + } else { + json_router = json_object_new_object(); + json_object_string_add( + json_router, "attachedRouterId", + inet_ntoa(nl->routers[i])); + json_object_object_add( + json_attached_rt, + inet_ntoa(nl->routers[i]), json_router); + } } + if (json) + json_object_object_add(json, "attchedRouters", + json_attached_rt); + return 0; } /* Show summary-LSA detail information. */ -static int show_summary_lsa_detail(struct vty *vty, struct ospf_lsa *lsa) +static int show_summary_lsa_detail(struct vty *vty, struct ospf_lsa *lsa, + json_object *json) { if (lsa != NULL) { struct summary_lsa *sl = (struct summary_lsa *)lsa->data; - show_ip_ospf_database_header(vty, lsa); + show_ip_ospf_database_header(vty, lsa, json); - vty_out(vty, " Network Mask: /%d\n", ip_masklen(sl->mask)); - vty_out(vty, " TOS: 0 Metric: %d\n", - GET_METRIC(sl->metric)); - vty_out(vty, "\n"); + if (!json) { + vty_out(vty, " Network Mask: /%d\n", + ip_masklen(sl->mask)); + vty_out(vty, " TOS: 0 Metric: %d\n", + GET_METRIC(sl->metric)); + vty_out(vty, "\n"); + } else { + json_object_int_add(json, "networkMask", + ip_masklen(sl->mask)); + json_object_int_add(json, "tos0Metric", + GET_METRIC(sl->metric)); + } } return 0; } /* Show summary-ASBR-LSA detail information. */ -static int show_summary_asbr_lsa_detail(struct vty *vty, struct ospf_lsa *lsa) +static int show_summary_asbr_lsa_detail(struct vty *vty, struct ospf_lsa *lsa, + json_object *json) { if (lsa != NULL) { struct summary_lsa *sl = (struct summary_lsa *)lsa->data; - show_ip_ospf_database_header(vty, lsa); + show_ip_ospf_database_header(vty, lsa, json); - vty_out(vty, " Network Mask: /%d\n", ip_masklen(sl->mask)); - vty_out(vty, " TOS: 0 Metric: %d\n", - GET_METRIC(sl->metric)); - vty_out(vty, "\n"); + if (!json) { + vty_out(vty, " Network Mask: /%d\n", + ip_masklen(sl->mask)); + vty_out(vty, " TOS: 0 Metric: %d\n", + GET_METRIC(sl->metric)); + vty_out(vty, "\n"); + } else { + json_object_int_add(json, "networkMask", + ip_masklen(sl->mask)); + json_object_int_add(json, "tos0Metric", + GET_METRIC(sl->metric)); + } } return 0; } /* Show AS-external-LSA detail information. */ -static int show_as_external_lsa_detail(struct vty *vty, struct ospf_lsa *lsa) +static int show_as_external_lsa_detail(struct vty *vty, struct ospf_lsa *lsa, + json_object *json) { + int tos = 0; + if (lsa != NULL) { struct as_external_lsa *al = (struct as_external_lsa *)lsa->data; - show_ip_ospf_database_header(vty, lsa); - - vty_out(vty, " Network Mask: /%d\n", ip_masklen(al->mask)); - vty_out(vty, " Metric Type: %s\n", - IS_EXTERNAL_METRIC(al->e[0].tos) - ? "2 (Larger than any link state path)" - : "1"); - vty_out(vty, " TOS: 0\n"); - vty_out(vty, " Metric: %d\n", - GET_METRIC(al->e[0].metric)); - vty_out(vty, " Forward Address: %pI4\n", - &al->e[0].fwd_addr); - - vty_out(vty, - " External Route Tag: %" ROUTE_TAG_PRI "\n\n", - (route_tag_t)ntohl(al->e[0].route_tag)); + show_ip_ospf_database_header(vty, lsa, json); + + if (!json) { + vty_out(vty, " Network Mask: /%d\n", + ip_masklen(al->mask)); + vty_out(vty, " Metric Type: %s\n", + IS_EXTERNAL_METRIC(al->e[0].tos) + ? "2 (Larger than any link state path)" + : "1"); + vty_out(vty, " TOS: 0\n"); + vty_out(vty, " Metric: %d\n", + GET_METRIC(al->e[0].metric)); + vty_out(vty, " Forward Address: %pI4\n", + &al->e[0].fwd_addr); + vty_out(vty, + " External Route Tag: %" ROUTE_TAG_PRI "\n\n", + (route_tag_t)ntohl(al->e[0].route_tag)); + } else { + json_object_int_add(json, "networkMask", + ip_masklen(al->mask)); + json_object_string_add( + json, "metricType", + IS_EXTERNAL_METRIC(al->e[0].tos) + ? "E2 (Larger than any link state path)" + : "E1"); + json_object_int_add(json, "tos", tos); + json_object_int_add(json, "metric", + GET_METRIC(al->e[0].metric)); + json_object_string_add(json, "forwardAddress", + inet_ntoa(al->e[0].fwd_addr)); + json_object_int_add( + json, "externalRouteTag", + (route_tag_t)ntohl(al->e[0].route_tag)); + } } return 0; @@ -6074,50 +6320,74 @@ show_as_external_lsa_stdvty (struct ospf_lsa *lsa) } #endif /* Show AS-NSSA-LSA detail information. */ -static int show_as_nssa_lsa_detail(struct vty *vty, struct ospf_lsa *lsa) +static int show_as_nssa_lsa_detail(struct vty *vty, struct ospf_lsa *lsa, + json_object *json) { + int tos = 0; + if (lsa != NULL) { struct as_external_lsa *al = (struct as_external_lsa *)lsa->data; - show_ip_ospf_database_header(vty, lsa); - - vty_out(vty, " Network Mask: /%d\n", ip_masklen(al->mask)); - vty_out(vty, " Metric Type: %s\n", - IS_EXTERNAL_METRIC(al->e[0].tos) - ? "2 (Larger than any link state path)" - : "1"); - vty_out(vty, " TOS: 0\n"); - vty_out(vty, " Metric: %d\n", - GET_METRIC(al->e[0].metric)); - vty_out(vty, " NSSA: Forward Address: %pI4\n", - &al->e[0].fwd_addr); - - vty_out(vty, - " External Route Tag: %" ROUTE_TAG_PRI "\n\n", - (route_tag_t)ntohl(al->e[0].route_tag)); + show_ip_ospf_database_header(vty, lsa, json); + + if (!json) { + vty_out(vty, " Network Mask: /%d\n", + ip_masklen(al->mask)); + vty_out(vty, " Metric Type: %s\n", + IS_EXTERNAL_METRIC(al->e[0].tos) + ? "2 (Larger than any link state path)" + : "1"); + vty_out(vty, " TOS: 0\n"); + vty_out(vty, " Metric: %d\n", + GET_METRIC(al->e[0].metric)); + vty_out(vty, " NSSA: Forward Address: %pI4\n", + &al->e[0].fwd_addr); + vty_out(vty, + " External Route Tag: %" ROUTE_TAG_PRI + "\n\n", + (route_tag_t)ntohl(al->e[0].route_tag)); + } else { + json_object_int_add(json, "networkMask", + ip_masklen(al->mask)); + json_object_string_add( + json, "metricType", + IS_EXTERNAL_METRIC(al->e[0].tos) + ? "E2 (Larger than any link state path)" + : "E1"); + json_object_int_add(json, "tos", tos); + json_object_int_add(json, "metric", + GET_METRIC(al->e[0].metric)); + json_object_string_add(json, "nssaForwardAddress", + inet_ntoa(al->e[0].fwd_addr)); + json_object_int_add( + json, "externalRouteTag", + (route_tag_t)ntohl(al->e[0].route_tag)); + } } return 0; } -static int show_func_dummy(struct vty *vty, struct ospf_lsa *lsa) +static int show_func_dummy(struct vty *vty, struct ospf_lsa *lsa, + json_object *json) { return 0; } -static int show_opaque_lsa_detail(struct vty *vty, struct ospf_lsa *lsa) +static int show_opaque_lsa_detail(struct vty *vty, struct ospf_lsa *lsa, + json_object *json) { if (lsa != NULL) { - show_ip_ospf_database_header(vty, lsa); - show_opaque_info_detail(vty, lsa); - - vty_out(vty, "\n"); + show_ip_ospf_database_header(vty, lsa, json); + show_opaque_info_detail(vty, lsa, json); + if (!json) + vty_out(vty, "\n"); } return 0; } -int (*const show_function[])(struct vty *, struct ospf_lsa *) = { +int (*show_function[])(struct vty *, struct ospf_lsa *, json_object *) = { NULL, show_router_lsa_detail, show_network_lsa_detail, @@ -6150,11 +6420,13 @@ static void show_lsa_prefix_set(struct vty *vty, struct prefix_ls *lp, } static void show_lsa_detail_proc(struct vty *vty, struct route_table *rt, - struct in_addr *id, struct in_addr *adv_router) + struct in_addr *id, struct in_addr *adv_router, + json_object *json) { struct prefix_ls lp; struct route_node *rn, *start; struct ospf_lsa *lsa; + json_object *json_lsa = NULL; show_lsa_prefix_set(vty, &lp, id, adv_router); start = route_node_get(rt, (struct prefix *)&lp); @@ -6162,9 +6434,14 @@ static void show_lsa_detail_proc(struct vty *vty, struct route_table *rt, route_lock_node(start); for (rn = start; rn; rn = route_next_until(rn, start)) if ((lsa = rn->info)) { + if (json) { + json_lsa = json_object_new_object(); + json_object_array_add(json, json_lsa); + } + if (show_function[lsa->data->type] != NULL) - show_function[lsa->data->type](vty, - lsa); + show_function[lsa->data->type]( + vty, lsa, json_lsa); } route_unlock_node(start); } @@ -6173,25 +6450,62 @@ static void show_lsa_detail_proc(struct vty *vty, struct route_table *rt, /* Show detail LSA information -- if id is NULL then show all LSAs. */ static void show_lsa_detail(struct vty *vty, struct ospf *ospf, int type, - struct in_addr *id, struct in_addr *adv_router) + struct in_addr *id, struct in_addr *adv_router, + json_object *json) { struct listnode *node; struct ospf_area *area; + json_object *json_lsa_type = NULL; + json_object *json_areas = NULL; + json_object *json_lsa_array = NULL; + + if (json) + json_lsa_type = json_object_new_object(); switch (type) { case OSPF_AS_EXTERNAL_LSA: case OSPF_OPAQUE_AS_LSA: - vty_out(vty, " %s \n\n", - show_database_desc[type]); - show_lsa_detail_proc(vty, AS_LSDB(ospf, type), id, adv_router); + if (!json) + vty_out(vty, " %s \n\n", + show_database_desc[type]); + else + json_lsa_array = json_object_new_array(); + + show_lsa_detail_proc(vty, AS_LSDB(ospf, type), id, adv_router, + json_lsa_array); + if (json) + json_object_object_add(json, + show_database_desc_json[type], + json_lsa_array); + break; default: + if (json) + json_areas = json_object_new_object(); + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { - vty_out(vty, "\n %s (Area %s)\n\n", - show_database_desc[type], - ospf_area_desc_string(area)); + if (!json) { + vty_out(vty, + "\n %s (Area %s)\n\n", + show_database_desc[type], + ospf_area_desc_string(area)); + } else { + json_lsa_array = json_object_new_array(); + json_object_object_add(json_areas, + inet_ntoa(area->area_id), + json_lsa_array); + } + show_lsa_detail_proc(vty, AREA_LSDB(area, type), id, - adv_router); + adv_router, json_lsa_array); + } + + if (json) { + json_object_object_add(json_lsa_type, "areas", + json_areas); + json_object_object_add(json, + show_database_desc_json[type], + json_lsa_type); } break; } @@ -6199,60 +6513,104 @@ static void show_lsa_detail(struct vty *vty, struct ospf *ospf, int type, static void show_lsa_detail_adv_router_proc(struct vty *vty, struct route_table *rt, - struct in_addr *adv_router) + struct in_addr *adv_router, + json_object *json) { struct route_node *rn; struct ospf_lsa *lsa; for (rn = route_top(rt); rn; rn = route_next(rn)) - if ((lsa = rn->info)) + if ((lsa = rn->info)) { + json_object *json_lsa = NULL; + if (IPV4_ADDR_SAME(adv_router, &lsa->data->adv_router)) { if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT)) continue; + if (json) + json_lsa = json_object_new_object(); + if (show_function[lsa->data->type] != NULL) - show_function[lsa->data->type](vty, - lsa); + show_function[lsa->data->type]( + vty, lsa, json_lsa); + if (json) + json_object_object_add( + json, inet_ntoa(lsa->data->id), + json_lsa); } + } } /* Show detail LSA information. */ static void show_lsa_detail_adv_router(struct vty *vty, struct ospf *ospf, - int type, struct in_addr *adv_router) + int type, struct in_addr *adv_router, + json_object *json) { struct listnode *node; struct ospf_area *area; + json_object *json_lstype = NULL; + json_object *json_area = NULL; + + if (json) + json_lstype = json_object_new_object(); switch (type) { case OSPF_AS_EXTERNAL_LSA: case OSPF_OPAQUE_AS_LSA: - vty_out(vty, " %s \n\n", - show_database_desc[type]); + if (!json) + vty_out(vty, " %s \n\n", + show_database_desc[type]); + show_lsa_detail_adv_router_proc(vty, AS_LSDB(ospf, type), - adv_router); + adv_router, json_lstype); break; default: + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { - vty_out(vty, "\n %s (Area %s)\n\n", - show_database_desc[type], - ospf_area_desc_string(area)); - show_lsa_detail_adv_router_proc( - vty, AREA_LSDB(area, type), adv_router); + if (json) + json_area = json_object_new_object(); + else + vty_out(vty, + "\n %s (Area %s)\n\n", + show_database_desc[type], + ospf_area_desc_string(area)); + show_lsa_detail_adv_router_proc(vty, + AREA_LSDB(area, type), + adv_router, json_area); + + if (json) + json_object_object_add(json_lstype, + inet_ntoa(area->area_id), + json_area); } break; } + + if (json) + json_object_object_add(json, show_database_desc[type], + json_lstype); } static void show_ip_ospf_database_summary(struct vty *vty, struct ospf *ospf, - int self) + int self, json_object *json) { struct ospf_lsa *lsa; struct route_node *rn; struct ospf_area *area; struct listnode *node; + json_object *json_areas = NULL; + json_object *json_area = NULL; + json_object *json_lsa = NULL; int type; + json_object *json_lsa_array = NULL; + + if (json) + json_areas = json_object_new_object(); for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + if (json) + json_area = json_object_new_object(); + for (type = OSPF_MIN_LSA; type < OSPF_MAX_LSA; type++) { switch (type) { case OSPF_AS_EXTERNAL_LSA: @@ -6264,20 +6622,49 @@ static void show_ip_ospf_database_summary(struct vty *vty, struct ospf *ospf, if (ospf_lsdb_count_self(area->lsdb, type) > 0 || (!self && ospf_lsdb_count(area->lsdb, type) > 0)) { - vty_out(vty, " %s (Area %s)\n\n", - show_database_desc[type], - ospf_area_desc_string(area)); - vty_out(vty, "%s\n", - show_database_header[type]); - LSDB_LOOP (AREA_LSDB(area, type), rn, lsa) - show_lsa_summary(vty, lsa, self); + if (!json) { + vty_out(vty, + " %s (Area %s)\n\n", + show_database_desc[type], + ospf_area_desc_string(area)); + vty_out(vty, "%s\n", + show_database_header[type]); + } else { + json_lsa_array = + json_object_new_array(); + json_object_object_add( + json_area, + show_database_desc_json[type], + json_lsa_array); + } + + LSDB_LOOP (AREA_LSDB(area, type), rn, lsa) { + if (json) { + json_lsa = + json_object_new_object(); + json_object_array_add( + json_lsa_array, + json_lsa); + } - vty_out(vty, "\n"); + show_lsa_summary(vty, lsa, self, + json_lsa); + } + + if (!json) + vty_out(vty, "\n"); } } + if (json) + json_object_object_add(json_areas, + inet_ntoa(area->area_id), + json_area); } + if (json) + json_object_object_add(json, "areas", json_areas); + for (type = OSPF_MIN_LSA; type < OSPF_MAX_LSA; type++) { switch (type) { case OSPF_AS_EXTERNAL_LSA: @@ -6288,39 +6675,82 @@ static void show_ip_ospf_database_summary(struct vty *vty, struct ospf *ospf, } if (ospf_lsdb_count_self(ospf->lsdb, type) || (!self && ospf_lsdb_count(ospf->lsdb, type))) { - vty_out(vty, " %s\n\n", - show_database_desc[type]); - vty_out(vty, "%s\n", show_database_header[type]); + if (!json) { + vty_out(vty, " %s\n\n", + show_database_desc[type]); + vty_out(vty, "%s\n", + show_database_header[type]); + } else { + json_lsa_array = json_object_new_array(); + json_object_object_add( + json, show_database_desc_json[type], + json_lsa_array); + } - LSDB_LOOP (AS_LSDB(ospf, type), rn, lsa) - show_lsa_summary(vty, lsa, self); + LSDB_LOOP (AS_LSDB(ospf, type), rn, lsa) { + if (json) { + json_lsa = json_object_new_object(); + json_object_array_add(json_lsa_array, + json_lsa); + } - vty_out(vty, "\n"); + show_lsa_summary(vty, lsa, self, json_lsa); + } + + if (!json) + vty_out(vty, "\n"); } } - vty_out(vty, "\n"); + if (!json) + vty_out(vty, "\n"); } -static void show_ip_ospf_database_maxage(struct vty *vty, struct ospf *ospf) +static void show_ip_ospf_database_maxage(struct vty *vty, struct ospf *ospf, + json_object *json) { struct route_node *rn; + json_object *json_maxage = NULL; - vty_out(vty, "\n MaxAge Link States:\n\n"); + if (!json) + vty_out(vty, "\n MaxAge Link States:\n\n"); + else + json_maxage = json_object_new_object(); for (rn = route_top(ospf->maxage_lsa); rn; rn = route_next(rn)) { struct ospf_lsa *lsa; + json_object *json_lsa = NULL; if ((lsa = rn->info) != NULL) { - vty_out(vty, "Link type: %d\n", lsa->data->type); - vty_out(vty, "Link State ID: %pI4\n", - &lsa->data->id); - vty_out(vty, "Advertising Router: %pI4\n", - &lsa->data->adv_router); - vty_out(vty, "LSA lock count: %d\n", lsa->lock); - vty_out(vty, "\n"); + if (!json) { + vty_out(vty, "Link type: %d\n", + lsa->data->type); + vty_out(vty, "Link State ID: %s\n", + inet_ntoa(lsa->data->id)); + vty_out(vty, "Advertising Router: %pI4\n", + &lsa->data->adv_router); + vty_out(vty, "LSA lock count: %d\n", lsa->lock); + vty_out(vty, "\n"); + } else { + json_lsa = json_object_new_object(); + json_object_int_add(json_lsa, "linkType", + lsa->data->type); + json_object_string_add( + json_lsa, "linkStateId", + inet_ntoa(lsa->data->id)); + json_object_string_add( + json_lsa, "advertisingRouter", + inet_ntoa(lsa->data->adv_router)); + json_object_int_add(json_lsa, "lsaLockCount", + lsa->lock); + json_object_object_add(json_maxage, + inet_ntoa(lsa->data->id), + json_lsa); + } } } + if (json) + json_object_object_add(json, "maxAgeLinkStates", json_maxage); } #define OSPF_LSA_TYPE_NSSA_DESC "NSSA external link state\n" @@ -6343,23 +6773,53 @@ static void show_ip_ospf_database_maxage(struct vty *vty, struct ospf *ospf) static int show_ip_ospf_database_common(struct vty *vty, struct ospf *ospf, int arg_base, int argc, struct cmd_token **argv, - uint8_t use_vrf) + uint8_t use_vrf, json_object *json, + bool uj) { int idx_type = 4; int type, ret; struct in_addr id, adv_router; + json_object *json_vrf = NULL; - if (ospf->instance) - vty_out(vty, "\nOSPF Instance: %d\n", ospf->instance); + if (uj) { + if (use_vrf) + json_vrf = json_object_new_object(); + else + json_vrf = json; + } - ospf_show_vrf_name(ospf, vty, NULL, use_vrf); + if (ospf->instance) { + if (uj) + json_object_int_add(json_vrf, "ospfInstance", + ospf->instance); + else + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + } - vty_out(vty, "\n OSPF Router with ID (%pI4)\n\n", - &ospf->router_id); + ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf); + + /* Show Router ID. */ + if (uj) { + json_object_string_add(json_vrf, "routerId", + inet_ntoa(ospf->router_id)); + } else { + vty_out(vty, "\n OSPF Router with ID (%pI4)\n\n", + &ospf->router_id); + } /* Show all LSA. */ - if (argc == arg_base + 4) { - show_ip_ospf_database_summary(vty, ospf, 0); + if ((argc == arg_base + 4) || (uj && (argc == arg_base + 5))) { + show_ip_ospf_database_summary(vty, ospf, 0, json_vrf); + if (json) { + if (use_vrf) { + if (ospf->vrf_id == VRF_DEFAULT) + json_object_object_add(json, "default", + json_vrf); + else + json_object_object_add(json, ospf->name, + json_vrf); + } + } return CMD_SUCCESS; } @@ -6377,10 +6837,30 @@ static int show_ip_ospf_database_common(struct vty *vty, struct ospf *ospf, else if (strncmp(argv[arg_base + idx_type]->text, "e", 1) == 0) type = OSPF_AS_EXTERNAL_LSA; else if (strncmp(argv[arg_base + idx_type]->text, "se", 2) == 0) { - show_ip_ospf_database_summary(vty, ospf, 1); + show_ip_ospf_database_summary(vty, ospf, 1, json_vrf); + if (json) { + if (use_vrf) { + if (ospf->vrf_id == VRF_DEFAULT) + json_object_object_add(json, "default", + json_vrf); + else + json_object_object_add(json, ospf->name, + json_vrf); + } + } return CMD_SUCCESS; } else if (strncmp(argv[arg_base + idx_type]->text, "m", 1) == 0) { - show_ip_ospf_database_maxage(vty, ospf); + show_ip_ospf_database_maxage(vty, ospf, json_vrf); + if (json) { + if (use_vrf) { + if (ospf->vrf_id == VRF_DEFAULT) + json_object_object_add(json, "default", + json_vrf); + else + json_object_object_add(json, ospf->name, + json_vrf); + } + } return CMD_SUCCESS; } else if (strncmp(argv[arg_base + idx_type]->text, "opaque-l", 8) == 0) type = OSPF_OPAQUE_LINK_LSA; @@ -6392,18 +6872,19 @@ static int show_ip_ospf_database_common(struct vty *vty, struct ospf *ospf, return CMD_WARNING; /* `show ip ospf database LSA'. */ - if (argc == arg_base + 5) - show_lsa_detail(vty, ospf, type, NULL, NULL); + if ((argc == arg_base + 5) || (uj && (argc == arg_base + 6))) + show_lsa_detail(vty, ospf, type, NULL, NULL, json_vrf); else if (argc >= arg_base + 6) { ret = inet_aton(argv[arg_base + 5]->arg, &id); if (!ret) return CMD_WARNING; /* `show ip ospf database LSA ID'. */ - if (argc == arg_base + 6) - show_lsa_detail(vty, ospf, type, &id, NULL); + if ((argc == arg_base + 6) || (uj && (argc == arg_base + 7))) + show_lsa_detail(vty, ospf, type, &id, NULL, json_vrf); /* `show ip ospf database LSA ID adv-router ADV_ROUTER'. */ - else if (argc == arg_base + 7) { + else if ((argc == arg_base + 7) + || (uj && (argc == arg_base + 8))) { if (strncmp(argv[arg_base + 6]->text, "s", 1) == 0) adv_router = ospf->router_id; else { @@ -6412,7 +6893,19 @@ static int show_ip_ospf_database_common(struct vty *vty, struct ospf *ospf, if (!ret) return CMD_WARNING; } - show_lsa_detail(vty, ospf, type, &id, &adv_router); + show_lsa_detail(vty, ospf, type, &id, &adv_router, + json_vrf); + } + } + + if (json) { + if (use_vrf) { + if (ospf->vrf_id == VRF_DEFAULT) + json_object_object_add(json, "default", + json_vrf); + else + json_object_object_add(json, ospf->name, + json_vrf); } } @@ -6421,7 +6914,7 @@ static int show_ip_ospf_database_common(struct vty *vty, struct ospf *ospf, DEFUN (show_ip_ospf_database_max, show_ip_ospf_database_max_cmd, - "show ip ospf [vrf ] database ", + "show ip ospf [vrf ] database [json]", SHOW_STR IP_STR "OSPF information\n" @@ -6429,7 +6922,8 @@ DEFUN (show_ip_ospf_database_max, "All VRFs\n" "Database summary\n" "LSAs in MaxAge list\n" - "Self-originated link states\n") + "Self-originated link states\n" + JSON_STR) { struct ospf *ospf = NULL; struct listnode *node = NULL; @@ -6439,6 +6933,11 @@ DEFUN (show_ip_ospf_database_max, int inst = 0; int idx_vrf = 0; uint8_t use_vrf = 0; + bool uj = use_json(argc, argv); + json_object *json = NULL; + + if (uj) + json = json_object_new_object(); OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); @@ -6454,7 +6953,7 @@ DEFUN (show_ip_ospf_database_max, ospf_output = true; ret = show_ip_ospf_database_common( vty, ospf, idx_vrf ? 2 : 0, argc, argv, - use_vrf); + use_vrf, json, uj); } if (!ospf_output) @@ -6466,8 +6965,8 @@ DEFUN (show_ip_ospf_database_max, return CMD_SUCCESS; } ret = (show_ip_ospf_database_common( - vty, ospf, idx_vrf ? 2 : 0, argc, argv, - use_vrf)); + vty, ospf, idx_vrf ? 2 : 0, argc, argv, use_vrf, + json, uj)); } } else { /* Display default ospf (instance 0) info */ @@ -6478,7 +6977,12 @@ DEFUN (show_ip_ospf_database_max, } ret = show_ip_ospf_database_common(vty, ospf, 0, argc, argv, - use_vrf); + use_vrf, json, uj); + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string(json)); + json_object_free(json); } return ret; @@ -6486,7 +6990,7 @@ DEFUN (show_ip_ospf_database_max, DEFUN (show_ip_ospf_instance_database, show_ip_ospf_instance_database_cmd, - "show ip ospf [{(1-65535)|vrf NAME}] database [ [A.B.C.D []]]", + "show ip ospf [{(1-65535)|vrf NAME}] database [ [A.B.C.D []]] [json]", SHOW_STR IP_STR "OSPF information\n" @@ -6497,7 +7001,8 @@ DEFUN (show_ip_ospf_instance_database, "Link State ID (as an IP address)\n" "Self-originated link states\n" "Advertising Router link states\n" - "Advertising Router (as an IP address)\n") + "Advertising Router (as an IP address)\n" + JSON_STR) { struct ospf *ospf; unsigned short instance = 0; @@ -6508,6 +7013,11 @@ DEFUN (show_ip_ospf_instance_database, int inst = 0; int idx = 0; uint8_t use_vrf = 0; + bool uj = use_json(argc, argv); + json_object *json = NULL; + + if (uj) + json = json_object_new_object(); if (argv_find(argv, argc, "(1-65535)", &idx)) { instance = strtoul(argv[idx]->arg, NULL, 10); @@ -6517,8 +7027,8 @@ DEFUN (show_ip_ospf_instance_database, if (!ospf->oi_running) return CMD_SUCCESS; - return (show_ip_ospf_database_common(vty, ospf, idx ? 1 : 0, - argc, argv, use_vrf)); + return (show_ip_ospf_database_common( + vty, ospf, idx ? 1 : 0, argc, argv, use_vrf, json, uj)); } else if (argv_find(argv, argc, "vrf", &idx)) { vrf_name = argv[++idx]->arg; all_vrf = strmatch(vrf_name, "all"); @@ -6532,7 +7042,7 @@ DEFUN (show_ip_ospf_instance_database, continue; ret = (show_ip_ospf_database_common( vty, ospf, idx ? 2 : 0, argc, argv, - use_vrf)); + use_vrf, json, uj)); } } else { ospf = ospf_lookup_by_inst_name(inst, vrf_name); @@ -6542,7 +7052,8 @@ DEFUN (show_ip_ospf_instance_database, } ret = (show_ip_ospf_database_common( - vty, ospf, idx ? 2 : 0, argc, argv, use_vrf)); + vty, ospf, idx ? 2 : 0, argc, argv, use_vrf, + json, uj)); } } else { /* Display default ospf (instance 0) info */ @@ -6553,7 +7064,12 @@ DEFUN (show_ip_ospf_instance_database, } ret = (show_ip_ospf_database_common(vty, ospf, 0, argc, argv, - use_vrf)); + use_vrf, json, uj)); + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string(json)); + json_object_free(json); } return ret; @@ -6561,18 +7077,24 @@ DEFUN (show_ip_ospf_instance_database, DEFUN (show_ip_ospf_instance_database_max, show_ip_ospf_instance_database_max_cmd, - "show ip ospf (1-65535) database ", + "show ip ospf (1-65535) database [json]", SHOW_STR IP_STR "OSPF information\n" "Instance ID\n" "Database summary\n" "LSAs in MaxAge list\n" - "Self-originated link states\n") + "Self-originated link states\n" + JSON_STR) { int idx_number = 3; struct ospf *ospf; unsigned short instance = 0; + bool uj = use_json(argc, argv); + json_object *json = NULL; + + if (uj) + json = json_object_new_object(); instance = strtoul(argv[idx_number]->arg, NULL, 10); @@ -6585,7 +7107,16 @@ DEFUN (show_ip_ospf_instance_database_max, return CMD_SUCCESS; } - return show_ip_ospf_database_common(vty, ospf, 1, argc, argv, 0); + show_ip_ospf_database_common(vty, ospf, 1, argc, argv, 0, json, uj); + + if (uj) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } + + return CMD_SUCCESS; } @@ -6593,19 +7124,40 @@ static int show_ip_ospf_database_type_adv_router_common(struct vty *vty, struct ospf *ospf, int arg_base, int argc, struct cmd_token **argv, - uint8_t use_vrf) + uint8_t use_vrf, + json_object *json, + bool uj) { int idx_type = 4; int type, ret; struct in_addr adv_router; + json_object *json_vrf = NULL; - if (ospf->instance) - vty_out(vty, "\nOSPF Instance: %d\n", ospf->instance); + if (uj) { + if (use_vrf) + json_vrf = json_object_new_object(); + else + json_vrf = json; + } - ospf_show_vrf_name(ospf, vty, NULL, use_vrf); + if (ospf->instance) { + if (uj) + json_object_int_add(json, "ospfInstance", + ospf->instance); + else + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + } + + ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf); - vty_out(vty, "\n OSPF Router with ID (%pI4)\n\n", - &ospf->router_id); + /* Show Router ID. */ + if (uj) { + json_object_string_add(json_vrf, "routerId", + inet_ntoa(ospf->router_id)); + } else { + vty_out(vty, "\n OSPF Router with ID (%pI4)\n\n", + &ospf->router_id); + } /* Set database type to show. */ if (strncmp(argv[arg_base + idx_type]->text, "r", 1) == 0) @@ -6638,14 +7190,25 @@ static int show_ip_ospf_database_type_adv_router_common(struct vty *vty, return CMD_WARNING; } - show_lsa_detail_adv_router(vty, ospf, type, &adv_router); + show_lsa_detail_adv_router(vty, ospf, type, &adv_router, json_vrf); + + if (json) { + if (use_vrf) { + if (ospf->vrf_id == VRF_DEFAULT) + json_object_object_add(json, "default", + json_vrf); + else + json_object_object_add(json, ospf->name, + json_vrf); + } + } return CMD_SUCCESS; } DEFUN (show_ip_ospf_instance_database_type_adv_router, show_ip_ospf_instance_database_type_adv_router_cmd, - "show ip ospf [{(1-65535)|vrf NAME}] database ", + "show ip ospf [{(1-65535)|vrf NAME}] database [json]", SHOW_STR IP_STR "OSPF information\n" @@ -6655,7 +7218,8 @@ DEFUN (show_ip_ospf_instance_database_type_adv_router, OSPF_LSA_TYPES_DESC "Advertising Router link states\n" "Advertising Router (as an IP address)\n" - "Self-originated link states\n") + "Self-originated link states\n" + JSON_STR) { struct ospf *ospf = NULL; unsigned short instance = 0; @@ -6666,6 +7230,11 @@ DEFUN (show_ip_ospf_instance_database_type_adv_router, int inst = 0; int idx = 0, idx_vrf = 0; uint8_t use_vrf = 0; + bool uj = use_json(argc, argv); + json_object *json = NULL; + + if (uj) + json = json_object_new_object(); if (argv_find(argv, argc, "(1-65535)", &idx)) { instance = strtoul(argv[idx]->arg, NULL, 10); @@ -6678,7 +7247,7 @@ DEFUN (show_ip_ospf_instance_database_type_adv_router, } return (show_ip_ospf_database_type_adv_router_common( - vty, ospf, idx ? 1 : 0, argc, argv, use_vrf)); + vty, ospf, idx ? 1 : 0, argc, argv, use_vrf, json, uj)); } OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); @@ -6695,7 +7264,7 @@ DEFUN (show_ip_ospf_instance_database_type_adv_router, ospf_output = true; ret = show_ip_ospf_database_type_adv_router_common( vty, ospf, idx ? 1 : 0, argc, argv, - use_vrf); + use_vrf, json, uj); } if (!ospf_output) vty_out(vty, "%% OSPF instance not found\n"); @@ -6707,7 +7276,8 @@ DEFUN (show_ip_ospf_instance_database_type_adv_router, } ret = show_ip_ospf_database_type_adv_router_common( - vty, ospf, idx ? 1 : 0, argc, argv, use_vrf); + vty, ospf, idx ? 1 : 0, argc, argv, use_vrf, + json, uj); } } else { /* Display default ospf (instance 0) info */ @@ -6718,8 +7288,14 @@ DEFUN (show_ip_ospf_instance_database_type_adv_router, } ret = show_ip_ospf_database_type_adv_router_common( - vty, ospf, idx ? 1 : 0, argc, argv, use_vrf); + vty, ospf, idx ? 1 : 0, argc, argv, use_vrf, json, uj); } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string(json)); + json_object_free(json); + } + return ret; /*return (show_ip_ospf_database_type_adv_router_common( vty, ospf, idx ? 1 : 0, argc, argv));*/ -- 2.39.5