diff options
Diffstat (limited to '')
-rw-r--r-- | ospfd/ospf_ri.c | 308 |
1 files changed, 220 insertions, 88 deletions
diff --git a/ospfd/ospf_ri.c b/ospfd/ospf_ri.c index 725443f..99326b4 100644 --- a/ospfd/ospf_ri.c +++ b/ospfd/ospf_ri.c @@ -24,6 +24,7 @@ #include "hash.h" #include "sockunion.h" /* for inet_aton() */ #include "mpls.h" +#include <lib/json.h> #include "ospfd/ospfd.h" #include "ospfd/ospf_interface.h" @@ -153,6 +154,7 @@ static int ospf_router_info_unregister(void) void ospf_router_info_term(void) { + list_delete(&OspfRI.area_info); list_delete(&OspfRI.pce_info.pce_domain); list_delete(&OspfRI.pce_info.pce_neighbor); @@ -1215,15 +1217,20 @@ static int ospf_router_info_lsa_update(struct ospf_lsa *lsa) } \ } while (0) -static uint16_t show_vty_router_cap(struct vty *vty, struct tlv_header *tlvh) +static uint16_t show_vty_router_cap(struct vty *vty, struct tlv_header *tlvh, + json_object *json) { struct ri_tlv_router_cap *top = (struct ri_tlv_router_cap *)tlvh; check_tlv_size(RI_TLV_CAPABILITIES_SIZE, "Router Capabilities"); if (vty != NULL) - vty_out(vty, " Router Capabilities: 0x%x\n", - ntohl(top->value)); + if (!json) + vty_out(vty, " Router Capabilities: 0x%x\n", + ntohl(top->value)); + else + json_object_string_addf(json, "routerCapabilities", + "0x%x", ntohl(top->value)); else zlog_debug(" Router Capabilities: 0x%x", ntohl(top->value)); @@ -1231,7 +1238,8 @@ static uint16_t show_vty_router_cap(struct vty *vty, struct tlv_header *tlvh) } static uint16_t show_vty_pce_subtlv_address(struct vty *vty, - struct tlv_header *tlvh) + struct tlv_header *tlvh, + json_object *json) { struct ri_pce_subtlv_address *top = (struct ri_pce_subtlv_address *)tlvh; @@ -1239,20 +1247,28 @@ static uint16_t show_vty_pce_subtlv_address(struct vty *vty, if (ntohs(top->address.type) == PCE_ADDRESS_IPV4) { check_tlv_size(PCE_ADDRESS_IPV4_SIZE, "PCE Address"); if (vty != NULL) - vty_out(vty, " PCE Address: %pI4\n", - &top->address.value); + if (!json) + vty_out(vty, " PCE Address: %pI4\n", + &top->address.value); + else + json_object_string_addf(json, "pceAddress", + "%pI4", + &top->address.value); else zlog_debug(" PCE Address: %pI4", &top->address.value); } else if (ntohs(top->address.type) == PCE_ADDRESS_IPV6) { - /* TODO: Add support to IPv6 with inet_ntop() */ check_tlv_size(PCE_ADDRESS_IPV6_SIZE, "PCE Address"); if (vty != NULL) - vty_out(vty, " PCE Address: 0x%x\n", - ntohl(top->address.value.s_addr)); + if (!json) + vty_out(vty, + " PCE Address: unsupported IPv6\n"); + else + json_object_string_add(json, "pceAddress", + "unsupported IPv6"); + else - zlog_debug(" PCE Address: 0x%x", - ntohl(top->address.value.s_addr)); + zlog_debug(" PCE Address: unsupported IPv6"); } else { if (vty != NULL) vty_out(vty, " Wrong PCE Address type: 0x%x\n", @@ -1266,7 +1282,8 @@ static uint16_t show_vty_pce_subtlv_address(struct vty *vty, } static uint16_t show_vty_pce_subtlv_path_scope(struct vty *vty, - struct tlv_header *tlvh) + struct tlv_header *tlvh, + json_object *json) { struct ri_pce_subtlv_path_scope *top = (struct ri_pce_subtlv_path_scope *)tlvh; @@ -1274,7 +1291,12 @@ static uint16_t show_vty_pce_subtlv_path_scope(struct vty *vty, check_tlv_size(RI_PCE_SUBTLV_PATH_SCOPE_SIZE, "PCE Path Scope"); if (vty != NULL) - vty_out(vty, " PCE Path Scope: 0x%x\n", ntohl(top->value)); + if (!json) + vty_out(vty, " PCE Path Scope: 0x%x\n", + ntohl(top->value)); + else + json_object_string_addf(json, "pcePathScope", "0x%x", + ntohl(top->value)); else zlog_debug(" PCE Path Scope: 0x%x", ntohl(top->value)); @@ -1282,7 +1304,8 @@ static uint16_t show_vty_pce_subtlv_path_scope(struct vty *vty, } static uint16_t show_vty_pce_subtlv_domain(struct vty *vty, - struct tlv_header *tlvh) + struct tlv_header *tlvh, + json_object *json) { struct ri_pce_subtlv_domain *top = (struct ri_pce_subtlv_domain *)tlvh; struct in_addr tmp; @@ -1292,13 +1315,21 @@ static uint16_t show_vty_pce_subtlv_domain(struct vty *vty, if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) { tmp.s_addr = top->value; if (vty != NULL) - vty_out(vty, " PCE Domain Area: %pI4\n", &tmp); + if (!json) + vty_out(vty, " PCE Domain Area: %pI4\n", &tmp); + else + json_object_string_addf(json, "pceDomainArea", + "%pI4", &tmp); else zlog_debug(" PCE Domain Area: %pI4", &tmp); } else if (ntohs(top->type) == PCE_DOMAIN_TYPE_AS) { if (vty != NULL) - vty_out(vty, " PCE Domain AS: %d\n", - ntohl(top->value)); + if (!json) + vty_out(vty, " PCE Domain AS: %d\n", + ntohl(top->value)); + else + json_object_int_add(json, "pceDomainAS", + ntohl(top->value)); else zlog_debug(" PCE Domain AS: %d", ntohl(top->value)); } else { @@ -1314,7 +1345,8 @@ static uint16_t show_vty_pce_subtlv_domain(struct vty *vty, } static uint16_t show_vty_pce_subtlv_neighbor(struct vty *vty, - struct tlv_header *tlvh) + struct tlv_header *tlvh, + json_object *json) { struct ri_pce_subtlv_neighbor *top = @@ -1326,13 +1358,22 @@ static uint16_t show_vty_pce_subtlv_neighbor(struct vty *vty, if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) { tmp.s_addr = top->value; if (vty != NULL) - vty_out(vty, " PCE Neighbor Area: %pI4\n", &tmp); + if (!json) + vty_out(vty, " PCE Neighbor Area: %pI4\n", + &tmp); + else + json_object_string_addf(json, "pceNeighborArea", + "%pI4", &tmp); else zlog_debug(" PCE Neighbor Area: %pI4", &tmp); } else if (ntohs(top->type) == PCE_DOMAIN_TYPE_AS) { if (vty != NULL) - vty_out(vty, " PCE Neighbor AS: %d\n", - ntohl(top->value)); + if (!json) + vty_out(vty, " PCE Neighbor AS: %d\n", + ntohl(top->value)); + else + json_object_int_add(json, "pceNeighborAS", + ntohl(top->value)); else zlog_debug(" PCE Neighbor AS: %d", ntohl(top->value)); @@ -1349,7 +1390,8 @@ static uint16_t show_vty_pce_subtlv_neighbor(struct vty *vty, } static uint16_t show_vty_pce_subtlv_cap_flag(struct vty *vty, - struct tlv_header *tlvh) + struct tlv_header *tlvh, + json_object *json) { struct ri_pce_subtlv_cap_flag *top = (struct ri_pce_subtlv_cap_flag *)tlvh; @@ -1357,8 +1399,12 @@ static uint16_t show_vty_pce_subtlv_cap_flag(struct vty *vty, check_tlv_size(RI_PCE_SUBTLV_CAP_FLAG_SIZE, "PCE Capabilities"); if (vty != NULL) - vty_out(vty, " PCE Capabilities Flag: 0x%x\n", - ntohl(top->value)); + if (!json) + vty_out(vty, " PCE Capabilities Flag: 0x%x\n", + ntohl(top->value)); + else + json_object_string_addf(json, "pceCapabilities", + "0x%x", ntohl(top->value)); else zlog_debug(" PCE Capabilities Flag: 0x%x", ntohl(top->value)); @@ -1367,8 +1413,10 @@ static uint16_t show_vty_pce_subtlv_cap_flag(struct vty *vty, } static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh, - size_t buf_size) + size_t buf_size, json_object *json) { + json_object *obj; + if (TLV_SIZE(tlvh) > buf_size) { if (vty != NULL) vty_out(vty, @@ -1382,8 +1430,18 @@ static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh, } if (vty != NULL) - vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n", - ntohs(tlvh->type), ntohs(tlvh->length)); + if (!json) + vty_out(vty, + " Unknown TLV: [type(0x%x), length(0x%x)]\n", + ntohs(tlvh->type), ntohs(tlvh->length)); + else { + obj = json_object_new_object(); + json_object_string_addf(obj, "type", "0x%x", + ntohs(tlvh->type)); + json_object_string_addf(obj, "length", "0x%x", + ntohs(tlvh->length)); + json_object_object_add(json, "unknownTLV", obj); + } else zlog_debug(" Unknown TLV: [type(0x%x), length(0x%x)]", ntohs(tlvh->type), ntohs(tlvh->length)); @@ -1392,7 +1450,7 @@ static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh, } static uint16_t show_vty_pce_info(struct vty *vty, struct tlv_header *ri, - size_t buf_size) + size_t buf_size, json_object *json) { struct tlv_header *tlvh; uint16_t length = ntohs(ri->length); @@ -1409,22 +1467,23 @@ static uint16_t show_vty_pce_info(struct vty *vty, struct tlv_header *ri, for (tlvh = ri; sum < length; tlvh = TLV_HDR_NEXT(tlvh)) { switch (ntohs(tlvh->type)) { case RI_PCE_SUBTLV_ADDRESS: - sum += show_vty_pce_subtlv_address(vty, tlvh); + sum += show_vty_pce_subtlv_address(vty, tlvh, json); break; case RI_PCE_SUBTLV_PATH_SCOPE: - sum += show_vty_pce_subtlv_path_scope(vty, tlvh); + sum += show_vty_pce_subtlv_path_scope(vty, tlvh, json); break; case RI_PCE_SUBTLV_DOMAIN: - sum += show_vty_pce_subtlv_domain(vty, tlvh); + sum += show_vty_pce_subtlv_domain(vty, tlvh, json); break; case RI_PCE_SUBTLV_NEIGHBOR: - sum += show_vty_pce_subtlv_neighbor(vty, tlvh); + sum += show_vty_pce_subtlv_neighbor(vty, tlvh, json); break; case RI_PCE_SUBTLV_CAP_FLAG: - sum += show_vty_pce_subtlv_cap_flag(vty, tlvh); + sum += show_vty_pce_subtlv_cap_flag(vty, tlvh, json); break; default: - sum += show_vty_unknown_tlv(vty, tlvh, length - sum); + sum += show_vty_unknown_tlv(vty, tlvh, length - sum, + json); break; } } @@ -1432,33 +1491,62 @@ static uint16_t show_vty_pce_info(struct vty *vty, struct tlv_header *ri, } /* Display Segment Routing Algorithm TLV information */ -static uint16_t show_vty_sr_algorithm(struct vty *vty, struct tlv_header *tlvh) +static uint16_t show_vty_sr_algorithm(struct vty *vty, struct tlv_header *tlvh, + json_object *json) { struct ri_sr_tlv_sr_algorithm *algo = (struct ri_sr_tlv_sr_algorithm *)tlvh; int i; + json_object *json_algo, *obj; + char buf[2]; check_tlv_size(ALGORITHM_COUNT, "Segment Routing Algorithm"); - if (vty != NULL) { - vty_out(vty, " Segment Routing Algorithm TLV:\n"); - for (i = 0; i < ntohs(algo->header.length); i++) { - switch (algo->value[i]) { - case 0: - vty_out(vty, " Algorithm %d: SPF\n", i); - break; - case 1: - vty_out(vty, " Algorithm %d: Strict SPF\n", - i); - break; - default: - vty_out(vty, - " Algorithm %d: Unknown value %d\n", i, - algo->value[i]); - break; + if (vty != NULL) + if (!json) { + vty_out(vty, " Segment Routing Algorithm TLV:\n"); + for (i = 0; i < ntohs(algo->header.length); i++) { + switch (algo->value[i]) { + case 0: + vty_out(vty, + " Algorithm %d: SPF\n", i); + break; + case 1: + vty_out(vty, + " Algorithm %d: Strict SPF\n", + i); + break; + default: + vty_out(vty, + " Algorithm %d: Unknown value %d\n", i, + algo->value[i]); + break; + } + } + } else { + json_algo = json_object_new_array(); + json_object_object_add(json, "algorithms", + json_algo); + for (i = 0; i < ntohs(algo->header.length); i++) { + obj = json_object_new_object(); + snprintfrr(buf, 2, "%d", i); + switch (algo->value[i]) { + case 0: + json_object_string_add(obj, buf, "SPF"); + break; + case 1: + json_object_string_add(obj, buf, + "strictSPF"); + break; + default: + json_object_string_add(obj, buf, + "unknown"); + break; + } + json_object_array_add(json_algo, obj); } } - } else { + else { zlog_debug(" Segment Routing Algorithm TLV:"); for (i = 0; i < ntohs(algo->header.length); i++) switch (algo->value[i]) { @@ -1479,24 +1567,47 @@ static uint16_t show_vty_sr_algorithm(struct vty *vty, struct tlv_header *tlvh) } /* Display Segment Routing SID/Label Range TLV information */ -static uint16_t show_vty_sr_range(struct vty *vty, struct tlv_header *tlvh) +static uint16_t show_vty_sr_range(struct vty *vty, struct tlv_header *tlvh, + json_object *json) { struct ri_sr_tlv_sid_label_range *range = (struct ri_sr_tlv_sid_label_range *)tlvh; + json_object *obj; + uint32_t upper; check_tlv_size(RI_SR_TLV_LABEL_RANGE_SIZE, "SR Label Range"); - if (vty != NULL) { - vty_out(vty, - " Segment Routing %s Range TLV:\n" - " Range Size = %d\n" - " SID Label = %d\n\n", - ntohs(range->header.type) == RI_SR_TLV_SRGB_LABEL_RANGE - ? "Global" - : "Local", - GET_RANGE_SIZE(ntohl(range->size)), - GET_LABEL(ntohl(range->lower.value))); - } else { + if (vty != NULL) + if (!json) { + vty_out(vty, + " Segment Routing %s Range TLV:\n" + " Range Size = %d\n" + " SID Label = %d\n\n", + ntohs(range->header.type) == + RI_SR_TLV_SRGB_LABEL_RANGE + ? "Global" + : "Local", + GET_RANGE_SIZE(ntohl(range->size)), + GET_LABEL(ntohl(range->lower.value))); + } else { + /* + * According to draft-ietf-teas-yang-sr-te-topo, SRGB + * and SRLB are describe with lower and upper bounds + */ + upper = GET_LABEL(ntohl(range->lower.value)) + + GET_RANGE_SIZE(ntohl(range->size)) - 1; + obj = json_object_new_object(); + json_object_int_add(obj, "upperBound", upper); + json_object_int_add(obj, "lowerBound", + GET_LABEL(ntohl(range->lower.value))); + json_object_object_add(json, + ntohs(range->header.type) == + RI_SR_TLV_SRGB_LABEL_RANGE + ? "srgb" + : "srlb", + obj); + } + else { zlog_debug( " Segment Routing %s Range TLV: Range Size = %d SID Label = %d", ntohs(range->header.type) == RI_SR_TLV_SRGB_LABEL_RANGE @@ -1510,22 +1621,25 @@ static uint16_t show_vty_sr_range(struct vty *vty, struct tlv_header *tlvh) } /* Display Segment Routing Maximum Stack Depth TLV information */ -static uint16_t show_vty_sr_msd(struct vty *vty, struct tlv_header *tlvh) +static uint16_t show_vty_sr_msd(struct vty *vty, struct tlv_header *tlvh, + json_object *json) { struct ri_sr_tlv_node_msd *msd = (struct ri_sr_tlv_node_msd *)tlvh; check_tlv_size(RI_SR_TLV_NODE_MSD_SIZE, "Node Maximum Stack Depth"); - if (vty != NULL) { - vty_out(vty, - " Segment Routing MSD TLV:\n" - " Node Maximum Stack Depth = %d\n", - msd->value); - } else { + if (vty != NULL) + if (!json) + vty_out(vty, + " Segment Routing MSD TLV:\n" + " Node Maximum Stack Depth = %d\n", + msd->value); + else + json_object_int_add(json, "nodeMsd", msd->value); + else zlog_debug( " Segment Routing MSD TLV: Node Maximum Stack Depth = %d", msd->value); - } return TLV_SIZE(tlvh); } @@ -1537,9 +1651,14 @@ static void ospf_router_info_show_info(struct vty *vty, struct lsa_header *lsah = lsa->data; struct tlv_header *tlvh; uint16_t length = 0, sum = 0; + json_object *jri = NULL, *jpce = NULL, *jsr = NULL; - if (json) - return; + if (json) { + jri = json_object_new_object(); + json_object_object_add(json, "routerInformation", jri); + jpce = json_object_new_object(); + jsr = json_object_new_object(); + } /* Initialize TLV browsing */ length = lsa->size - OSPF_LSA_HEADER_SIZE; @@ -1548,30 +1667,36 @@ static void ospf_router_info_show_info(struct vty *vty, tlvh = TLV_HDR_NEXT(tlvh)) { switch (ntohs(tlvh->type)) { case RI_TLV_CAPABILITIES: - sum += show_vty_router_cap(vty, tlvh); + sum += show_vty_router_cap(vty, tlvh, jri); break; case RI_TLV_PCE: tlvh++; sum += TLV_HDR_SIZE; - sum += show_vty_pce_info(vty, tlvh, length - sum); + sum += show_vty_pce_info(vty, tlvh, length - sum, jpce); break; case RI_SR_TLV_SR_ALGORITHM: - sum += show_vty_sr_algorithm(vty, tlvh); + sum += show_vty_sr_algorithm(vty, tlvh, jsr); break; case RI_SR_TLV_SRGB_LABEL_RANGE: case RI_SR_TLV_SRLB_LABEL_RANGE: - sum += show_vty_sr_range(vty, tlvh); + sum += show_vty_sr_range(vty, tlvh, jsr); break; case RI_SR_TLV_NODE_MSD: - sum += show_vty_sr_msd(vty, tlvh); + sum += show_vty_sr_msd(vty, tlvh, jsr); break; default: - sum += show_vty_unknown_tlv(vty, tlvh, length); + sum += show_vty_unknown_tlv(vty, tlvh, length, jri); break; } } + if (json) { + if (json_object_object_length(jpce) > 1) + json_object_object_add(jri, "pceInformation", jpce); + if (json_object_object_length(jsr) > 1) + json_object_object_add(jri, "segmentRouting", jsr); + } return; } @@ -1722,9 +1847,11 @@ DEFUN (router_info, DEFUN (no_router_info, no_router_info_cmd, - "no router-info", + "no router-info [<area|as>]", NO_STR - "Disable the Router Information functionality\n") + "Disable the Router Information functionality\n" + "Disable the Router Information functionality with AS flooding scope\n" + "Disable the Router Information functionality with Area flooding scope\n") { if (!OspfRI.enabled) @@ -2042,7 +2169,7 @@ DEFUN (show_ip_ospf_router_info, if (OspfRI.enabled) { vty_out(vty, "--- Router Information parameters ---\n"); - show_vty_router_cap(vty, &OspfRI.router_cap.header); + show_vty_router_cap(vty, &OspfRI.router_cap.header, NULL); } else { if (vty != NULL) vty_out(vty, @@ -2071,27 +2198,32 @@ DEFUN (show_ip_opsf_router_info_pce, if (pce->pce_address.header.type != 0) show_vty_pce_subtlv_address(vty, - &pce->pce_address.header); + &pce->pce_address.header, + NULL); if (pce->pce_scope.header.type != 0) show_vty_pce_subtlv_path_scope(vty, - &pce->pce_scope.header); + &pce->pce_scope.header, + NULL); for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) { if (domain->header.type != 0) show_vty_pce_subtlv_domain(vty, - &domain->header); + &domain->header, + NULL); } for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) { if (neighbor->header.type != 0) show_vty_pce_subtlv_neighbor(vty, - &neighbor->header); + &neighbor->header, + NULL); } if (pce->pce_cap_flag.header.type != 0) show_vty_pce_subtlv_cap_flag(vty, - &pce->pce_cap_flag.header); + &pce->pce_cap_flag.header, + NULL); } else { vty_out(vty, " PCE info is disabled on this router\n"); |