ospfd: Decode Router Info. TLVs for json output

When dumping ospf database with json output, decode Router Information TLVs
and sub-TLVs.

Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
This commit is contained in:
Olivier Dugeon 2023-12-19 15:59:33 +01:00
parent 95c9cb9aa9
commit b27d9e4d3b

View file

@ -24,6 +24,7 @@
#include "hash.h" #include "hash.h"
#include "sockunion.h" /* for inet_aton() */ #include "sockunion.h" /* for inet_aton() */
#include "mpls.h" #include "mpls.h"
#include <lib/json.h>
#include "ospfd/ospfd.h" #include "ospfd/ospfd.h"
#include "ospfd/ospf_interface.h" #include "ospfd/ospf_interface.h"
@ -1216,15 +1217,20 @@ static int ospf_router_info_lsa_update(struct ospf_lsa *lsa)
} \ } \
} while (0) } 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; struct ri_tlv_router_cap *top = (struct ri_tlv_router_cap *)tlvh;
check_tlv_size(RI_TLV_CAPABILITIES_SIZE, "Router Capabilities"); check_tlv_size(RI_TLV_CAPABILITIES_SIZE, "Router Capabilities");
if (vty != NULL) if (vty != NULL)
vty_out(vty, " Router Capabilities: 0x%x\n", if (!json)
ntohl(top->value)); vty_out(vty, " Router Capabilities: 0x%x\n",
ntohl(top->value));
else
json_object_string_addf(json, "routerCapabilities",
"0x%x", ntohl(top->value));
else else
zlog_debug(" Router Capabilities: 0x%x", ntohl(top->value)); zlog_debug(" Router Capabilities: 0x%x", ntohl(top->value));
@ -1232,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, 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 *top =
(struct ri_pce_subtlv_address *)tlvh; (struct ri_pce_subtlv_address *)tlvh;
@ -1240,20 +1247,28 @@ static uint16_t show_vty_pce_subtlv_address(struct vty *vty,
if (ntohs(top->address.type) == PCE_ADDRESS_IPV4) { if (ntohs(top->address.type) == PCE_ADDRESS_IPV4) {
check_tlv_size(PCE_ADDRESS_IPV4_SIZE, "PCE Address"); check_tlv_size(PCE_ADDRESS_IPV4_SIZE, "PCE Address");
if (vty != NULL) if (vty != NULL)
vty_out(vty, " PCE Address: %pI4\n", if (!json)
&top->address.value); vty_out(vty, " PCE Address: %pI4\n",
&top->address.value);
else
json_object_string_addf(json, "pceAddress",
"%pI4",
&top->address.value);
else else
zlog_debug(" PCE Address: %pI4", zlog_debug(" PCE Address: %pI4",
&top->address.value); &top->address.value);
} else if (ntohs(top->address.type) == PCE_ADDRESS_IPV6) { } 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"); check_tlv_size(PCE_ADDRESS_IPV6_SIZE, "PCE Address");
if (vty != NULL) if (vty != NULL)
vty_out(vty, " PCE Address: 0x%x\n", if (!json)
ntohl(top->address.value.s_addr)); vty_out(vty,
" PCE Address: unsupported IPv6\n");
else
json_object_string_add(json, "pceAddress",
"unsupported IPv6");
else else
zlog_debug(" PCE Address: 0x%x", zlog_debug(" PCE Address: unsupported IPv6");
ntohl(top->address.value.s_addr));
} else { } else {
if (vty != NULL) if (vty != NULL)
vty_out(vty, " Wrong PCE Address type: 0x%x\n", vty_out(vty, " Wrong PCE Address type: 0x%x\n",
@ -1267,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, 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 *top =
(struct ri_pce_subtlv_path_scope *)tlvh; (struct ri_pce_subtlv_path_scope *)tlvh;
@ -1275,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"); check_tlv_size(RI_PCE_SUBTLV_PATH_SCOPE_SIZE, "PCE Path Scope");
if (vty != NULL) 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 else
zlog_debug(" PCE Path Scope: 0x%x", ntohl(top->value)); zlog_debug(" PCE Path Scope: 0x%x", ntohl(top->value));
@ -1283,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, 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 ri_pce_subtlv_domain *top = (struct ri_pce_subtlv_domain *)tlvh;
struct in_addr tmp; struct in_addr tmp;
@ -1293,13 +1315,21 @@ static uint16_t show_vty_pce_subtlv_domain(struct vty *vty,
if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) { if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) {
tmp.s_addr = top->value; tmp.s_addr = top->value;
if (vty != NULL) 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 else
zlog_debug(" PCE Domain Area: %pI4", &tmp); zlog_debug(" PCE Domain Area: %pI4", &tmp);
} else if (ntohs(top->type) == PCE_DOMAIN_TYPE_AS) { } else if (ntohs(top->type) == PCE_DOMAIN_TYPE_AS) {
if (vty != NULL) if (vty != NULL)
vty_out(vty, " PCE Domain AS: %d\n", if (!json)
ntohl(top->value)); vty_out(vty, " PCE Domain AS: %d\n",
ntohl(top->value));
else
json_object_int_add(json, "pceDomainAS",
ntohl(top->value));
else else
zlog_debug(" PCE Domain AS: %d", ntohl(top->value)); zlog_debug(" PCE Domain AS: %d", ntohl(top->value));
} else { } else {
@ -1315,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, 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 = struct ri_pce_subtlv_neighbor *top =
@ -1327,13 +1358,22 @@ static uint16_t show_vty_pce_subtlv_neighbor(struct vty *vty,
if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) { if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) {
tmp.s_addr = top->value; tmp.s_addr = top->value;
if (vty != NULL) 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 else
zlog_debug(" PCE Neighbor Area: %pI4", &tmp); zlog_debug(" PCE Neighbor Area: %pI4", &tmp);
} else if (ntohs(top->type) == PCE_DOMAIN_TYPE_AS) { } else if (ntohs(top->type) == PCE_DOMAIN_TYPE_AS) {
if (vty != NULL) if (vty != NULL)
vty_out(vty, " PCE Neighbor AS: %d\n", if (!json)
ntohl(top->value)); vty_out(vty, " PCE Neighbor AS: %d\n",
ntohl(top->value));
else
json_object_int_add(json, "pceNeighborAS",
ntohl(top->value));
else else
zlog_debug(" PCE Neighbor AS: %d", zlog_debug(" PCE Neighbor AS: %d",
ntohl(top->value)); ntohl(top->value));
@ -1350,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, 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 *top =
(struct ri_pce_subtlv_cap_flag *)tlvh; (struct ri_pce_subtlv_cap_flag *)tlvh;
@ -1358,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"); check_tlv_size(RI_PCE_SUBTLV_CAP_FLAG_SIZE, "PCE Capabilities");
if (vty != NULL) if (vty != NULL)
vty_out(vty, " PCE Capabilities Flag: 0x%x\n", if (!json)
ntohl(top->value)); 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 else
zlog_debug(" PCE Capabilities Flag: 0x%x", zlog_debug(" PCE Capabilities Flag: 0x%x",
ntohl(top->value)); ntohl(top->value));
@ -1368,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, 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 (TLV_SIZE(tlvh) > buf_size) {
if (vty != NULL) if (vty != NULL)
vty_out(vty, vty_out(vty,
@ -1383,8 +1430,18 @@ static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh,
} }
if (vty != NULL) if (vty != NULL)
vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n", if (!json)
ntohs(tlvh->type), ntohs(tlvh->length)); 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 else
zlog_debug(" Unknown TLV: [type(0x%x), length(0x%x)]", zlog_debug(" Unknown TLV: [type(0x%x), length(0x%x)]",
ntohs(tlvh->type), ntohs(tlvh->length)); ntohs(tlvh->type), ntohs(tlvh->length));
@ -1393,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, 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; struct tlv_header *tlvh;
uint16_t length = ntohs(ri->length); uint16_t length = ntohs(ri->length);
@ -1410,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)) { for (tlvh = ri; sum < length; tlvh = TLV_HDR_NEXT(tlvh)) {
switch (ntohs(tlvh->type)) { switch (ntohs(tlvh->type)) {
case RI_PCE_SUBTLV_ADDRESS: case RI_PCE_SUBTLV_ADDRESS:
sum += show_vty_pce_subtlv_address(vty, tlvh); sum += show_vty_pce_subtlv_address(vty, tlvh, json);
break; break;
case RI_PCE_SUBTLV_PATH_SCOPE: 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; break;
case RI_PCE_SUBTLV_DOMAIN: case RI_PCE_SUBTLV_DOMAIN:
sum += show_vty_pce_subtlv_domain(vty, tlvh); sum += show_vty_pce_subtlv_domain(vty, tlvh, json);
break; break;
case RI_PCE_SUBTLV_NEIGHBOR: case RI_PCE_SUBTLV_NEIGHBOR:
sum += show_vty_pce_subtlv_neighbor(vty, tlvh); sum += show_vty_pce_subtlv_neighbor(vty, tlvh, json);
break; break;
case RI_PCE_SUBTLV_CAP_FLAG: 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; break;
default: default:
sum += show_vty_unknown_tlv(vty, tlvh, length - sum); sum += show_vty_unknown_tlv(vty, tlvh, length - sum,
json);
break; break;
} }
} }
@ -1433,33 +1491,62 @@ static uint16_t show_vty_pce_info(struct vty *vty, struct tlv_header *ri,
} }
/* Display Segment Routing Algorithm TLV information */ /* 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 *algo =
(struct ri_sr_tlv_sr_algorithm *)tlvh; (struct ri_sr_tlv_sr_algorithm *)tlvh;
int i; int i;
json_object *json_algo, *obj;
char buf[2];
check_tlv_size(ALGORITHM_COUNT, "Segment Routing Algorithm"); check_tlv_size(ALGORITHM_COUNT, "Segment Routing Algorithm");
if (vty != NULL) { if (vty != NULL)
vty_out(vty, " Segment Routing Algorithm TLV:\n"); if (!json) {
for (i = 0; i < ntohs(algo->header.length); i++) { vty_out(vty, " Segment Routing Algorithm TLV:\n");
switch (algo->value[i]) { for (i = 0; i < ntohs(algo->header.length); i++) {
case 0: switch (algo->value[i]) {
vty_out(vty, " Algorithm %d: SPF\n", i); case 0:
break; vty_out(vty,
case 1: " Algorithm %d: SPF\n", i);
vty_out(vty, " Algorithm %d: Strict SPF\n", break;
i); case 1:
break; vty_out(vty,
default: " Algorithm %d: Strict SPF\n",
vty_out(vty, i);
" Algorithm %d: Unknown value %d\n", i, break;
algo->value[i]); default:
break; 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:"); zlog_debug(" Segment Routing Algorithm TLV:");
for (i = 0; i < ntohs(algo->header.length); i++) for (i = 0; i < ntohs(algo->header.length); i++)
switch (algo->value[i]) { switch (algo->value[i]) {
@ -1480,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 */ /* 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 *range =
(struct ri_sr_tlv_sid_label_range *)tlvh; (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"); check_tlv_size(RI_SR_TLV_LABEL_RANGE_SIZE, "SR Label Range");
if (vty != NULL) { if (vty != NULL)
vty_out(vty, if (!json) {
" Segment Routing %s Range TLV:\n" vty_out(vty,
" Range Size = %d\n" " Segment Routing %s Range TLV:\n"
" SID Label = %d\n\n", " Range Size = %d\n"
ntohs(range->header.type) == RI_SR_TLV_SRGB_LABEL_RANGE " SID Label = %d\n\n",
? "Global" ntohs(range->header.type) ==
: "Local", RI_SR_TLV_SRGB_LABEL_RANGE
GET_RANGE_SIZE(ntohl(range->size)), ? "Global"
GET_LABEL(ntohl(range->lower.value))); : "Local",
} else { 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( zlog_debug(
" Segment Routing %s Range TLV: Range Size = %d SID Label = %d", " Segment Routing %s Range TLV: Range Size = %d SID Label = %d",
ntohs(range->header.type) == RI_SR_TLV_SRGB_LABEL_RANGE ntohs(range->header.type) == RI_SR_TLV_SRGB_LABEL_RANGE
@ -1511,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 */ /* 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; 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"); check_tlv_size(RI_SR_TLV_NODE_MSD_SIZE, "Node Maximum Stack Depth");
if (vty != NULL) { if (vty != NULL)
vty_out(vty, if (!json)
" Segment Routing MSD TLV:\n" vty_out(vty,
" Node Maximum Stack Depth = %d\n", " Segment Routing MSD TLV:\n"
msd->value); " Node Maximum Stack Depth = %d\n",
} else { msd->value);
else
json_object_int_add(json, "nodeMsd", msd->value);
else
zlog_debug( zlog_debug(
" Segment Routing MSD TLV: Node Maximum Stack Depth = %d", " Segment Routing MSD TLV: Node Maximum Stack Depth = %d",
msd->value); msd->value);
}
return TLV_SIZE(tlvh); return TLV_SIZE(tlvh);
} }
@ -1538,9 +1651,14 @@ static void ospf_router_info_show_info(struct vty *vty,
struct lsa_header *lsah = lsa->data; struct lsa_header *lsah = lsa->data;
struct tlv_header *tlvh; struct tlv_header *tlvh;
uint16_t length = 0, sum = 0; uint16_t length = 0, sum = 0;
json_object *jri = NULL, *jpce = NULL, *jsr = NULL;
if (json) if (json) {
return; 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 */ /* Initialize TLV browsing */
length = lsa->size - OSPF_LSA_HEADER_SIZE; length = lsa->size - OSPF_LSA_HEADER_SIZE;
@ -1549,30 +1667,36 @@ static void ospf_router_info_show_info(struct vty *vty,
tlvh = TLV_HDR_NEXT(tlvh)) { tlvh = TLV_HDR_NEXT(tlvh)) {
switch (ntohs(tlvh->type)) { switch (ntohs(tlvh->type)) {
case RI_TLV_CAPABILITIES: case RI_TLV_CAPABILITIES:
sum += show_vty_router_cap(vty, tlvh); sum += show_vty_router_cap(vty, tlvh, jri);
break; break;
case RI_TLV_PCE: case RI_TLV_PCE:
tlvh++; tlvh++;
sum += TLV_HDR_SIZE; sum += TLV_HDR_SIZE;
sum += show_vty_pce_info(vty, tlvh, length - sum); sum += show_vty_pce_info(vty, tlvh, length - sum, jpce);
break; break;
case RI_SR_TLV_SR_ALGORITHM: case RI_SR_TLV_SR_ALGORITHM:
sum += show_vty_sr_algorithm(vty, tlvh); sum += show_vty_sr_algorithm(vty, tlvh, jsr);
break; break;
case RI_SR_TLV_SRGB_LABEL_RANGE: case RI_SR_TLV_SRGB_LABEL_RANGE:
case RI_SR_TLV_SRLB_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; break;
case RI_SR_TLV_NODE_MSD: case RI_SR_TLV_NODE_MSD:
sum += show_vty_sr_msd(vty, tlvh); sum += show_vty_sr_msd(vty, tlvh, jsr);
break; break;
default: default:
sum += show_vty_unknown_tlv(vty, tlvh, length); sum += show_vty_unknown_tlv(vty, tlvh, length, jri);
break; 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; return;
} }
@ -2045,7 +2169,7 @@ DEFUN (show_ip_ospf_router_info,
if (OspfRI.enabled) { if (OspfRI.enabled) {
vty_out(vty, "--- Router Information parameters ---\n"); 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 { } else {
if (vty != NULL) if (vty != NULL)
vty_out(vty, vty_out(vty,
@ -2074,27 +2198,32 @@ DEFUN (show_ip_opsf_router_info_pce,
if (pce->pce_address.header.type != 0) if (pce->pce_address.header.type != 0)
show_vty_pce_subtlv_address(vty, show_vty_pce_subtlv_address(vty,
&pce->pce_address.header); &pce->pce_address.header,
NULL);
if (pce->pce_scope.header.type != 0) if (pce->pce_scope.header.type != 0)
show_vty_pce_subtlv_path_scope(vty, 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)) { for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
if (domain->header.type != 0) if (domain->header.type != 0)
show_vty_pce_subtlv_domain(vty, show_vty_pce_subtlv_domain(vty,
&domain->header); &domain->header,
NULL);
} }
for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) { for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
if (neighbor->header.type != 0) if (neighbor->header.type != 0)
show_vty_pce_subtlv_neighbor(vty, show_vty_pce_subtlv_neighbor(vty,
&neighbor->header); &neighbor->header,
NULL);
} }
if (pce->pce_cap_flag.header.type != 0) if (pce->pce_cap_flag.header.type != 0)
show_vty_pce_subtlv_cap_flag(vty, show_vty_pce_subtlv_cap_flag(vty,
&pce->pce_cap_flag.header); &pce->pce_cap_flag.header,
NULL);
} else { } else {
vty_out(vty, " PCE info is disabled on this router\n"); vty_out(vty, " PCE info is disabled on this router\n");