]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_ri.c
pathd: some traces are added to 'debug pathd ted' command.
[mirror_frr.git] / ospfd / ospf_ri.c
CommitLineData
0ef4bcdc
OD
1/*
2 * This is an implementation of RFC4970 Router Information
3 * with support of RFC5088 PCE Capabilites announcement
4 *
5 * Module name: Router Information
cf9b9f77
OD
6 * Author: Olivier Dugeon <olivier.dugeon@orange.com>
7 * Copyright (C) 2012 - 2017 Orange Labs http://www.orange.com/
0ef4bcdc
OD
8 *
9 * This file is part of GNU Quagga.
10 *
11 * GNU Zebra is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2, or (at your option) any
14 * later version.
15 *
16 * GNU Quagga is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
896014f4
DL
21 * You should have received a copy of the GNU General Public License along
22 * with this program; see the file COPYING; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
0ef4bcdc
OD
24 */
25
26#include <zebra.h>
27#include <math.h>
28
29#include "linklist.h"
30#include "prefix.h"
31#include "if.h"
32#include "table.h"
33#include "memory.h"
34#include "command.h"
35#include "vty.h"
36#include "stream.h"
37#include "log.h"
38#include "thread.h"
39#include "hash.h"
d62a17ae 40#include "sockunion.h" /* for inet_aton() */
cf9b9f77 41#include "mpls.h"
0ef4bcdc
OD
42
43#include "ospfd/ospfd.h"
44#include "ospfd/ospf_interface.h"
45#include "ospfd/ospf_ism.h"
46#include "ospfd/ospf_asbr.h"
47#include "ospfd/ospf_lsa.h"
48#include "ospfd/ospf_lsdb.h"
49#include "ospfd/ospf_neighbor.h"
50#include "ospfd/ospf_nsm.h"
51#include "ospfd/ospf_flood.h"
52#include "ospfd/ospf_packet.h"
53#include "ospfd/ospf_spf.h"
54#include "ospfd/ospf_dump.h"
55#include "ospfd/ospf_route.h"
56#include "ospfd/ospf_ase.h"
57#include "ospfd/ospf_zebra.h"
cf9b9f77 58#include "ospfd/ospf_sr.h"
0ef4bcdc 59#include "ospfd/ospf_ri.h"
85c9b439 60#include "ospfd/ospf_errors.h"
0ef4bcdc 61
0ef4bcdc
OD
62/*
63 * Global variable to manage Opaque-LSA/Router Information on this node.
64 * Note that all parameter values are stored in network byte order.
65 */
66static struct ospf_router_info OspfRI;
67
68/*------------------------------------------------------------------------------*
78dfa0c7 69 * Following are initialize/terminate functions for Router Information
d62a17ae 70 *handling.
0ef4bcdc
OD
71 *------------------------------------------------------------------------------*/
72
d62a17ae 73static void ospf_router_info_ism_change(struct ospf_interface *oi,
74 int old_status);
d62a17ae 75static void ospf_router_info_config_write_router(struct vty *vty);
3e63092b
RW
76static void ospf_router_info_show_info(struct vty *vty,
77 struct json_object *json,
78 struct ospf_lsa *lsa);
d62a17ae 79static int ospf_router_info_lsa_originate(void *arg);
80static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa);
ddd73a96
OD
81static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info *ai,
82 enum lsa_opcode opcode);
d62a17ae 83static void ospf_router_info_register_vty(void);
cf9b9f77 84static int ospf_router_info_lsa_update(struct ospf_lsa *lsa);
ddd73a96 85static void del_area_info(void *val);
d62a17ae 86static void del_pce_info(void *val);
87
88int ospf_router_info_init(void)
0ef4bcdc
OD
89{
90
ddd73a96 91 zlog_info("RI (%s): Initialize Router Information", __func__);
cf9b9f77 92
6006b807 93 memset(&OspfRI, 0, sizeof(OspfRI));
32ab5cf4 94 OspfRI.enabled = false;
d62a17ae 95 OspfRI.registered = 0;
96 OspfRI.scope = OSPF_OPAQUE_AS_LSA;
ddd73a96
OD
97 OspfRI.as_flags = RIFLG_LSA_INACTIVE;
98 OspfRI.area_info = list_new();
99 OspfRI.area_info->del = del_area_info;
0ef4bcdc 100
d62a17ae 101 /* Initialize pce domain and neighbor list */
32ab5cf4 102 OspfRI.pce_info.enabled = false;
d62a17ae 103 OspfRI.pce_info.pce_domain = list_new();
104 OspfRI.pce_info.pce_domain->del = del_pce_info;
105 OspfRI.pce_info.pce_neighbor = list_new();
106 OspfRI.pce_info.pce_neighbor->del = del_pce_info;
0ef4bcdc 107
cf9b9f77
OD
108 /* Initialize Segment Routing information structure */
109 OspfRI.sr_info.enabled = false;
110
d62a17ae 111 ospf_router_info_register_vty();
0ef4bcdc 112
d62a17ae 113 return 0;
0ef4bcdc
OD
114}
115
d7c0a89a 116static int ospf_router_info_register(uint8_t scope)
0ef4bcdc 117{
d62a17ae 118 int rc = 0;
119
120 if (OspfRI.registered)
ead99d5f 121 return rc;
d62a17ae 122
ddd73a96
OD
123 zlog_info("RI (%s): Register Router Information with scope %s(%d)",
124 __func__,
d62a17ae 125 scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS", scope);
126 rc = ospf_register_opaque_functab(
127 scope, OPAQUE_TYPE_ROUTER_INFORMATION_LSA,
128 NULL, /* new interface */
129 NULL, /* del interface */
ddd73a96
OD
130 ospf_router_info_ism_change,
131 NULL, /* NSM change */
d62a17ae 132 ospf_router_info_config_write_router,
133 NULL, /* Config. write interface */
134 NULL, /* Config. write debug */
996c9314
LB
135 ospf_router_info_show_info, ospf_router_info_lsa_originate,
136 ospf_router_info_lsa_refresh, ospf_router_info_lsa_update,
cf9b9f77 137 NULL); /* del_lsa_hook */
d62a17ae 138
139 if (rc != 0) {
ade6974d 140 flog_warn(
cf444bcf 141 EC_OSPF_OPAQUE_REGISTRATION,
ddd73a96 142 "RI (%s): Failed to register functions", __func__);
d62a17ae 143 return rc;
144 }
145
146 OspfRI.registered = 1;
147 OspfRI.scope = scope;
ead99d5f 148 return rc;
0ef4bcdc
OD
149}
150
4d762f26 151static int ospf_router_info_unregister(void)
bcf4475e
OD
152{
153
154 if ((OspfRI.scope != OSPF_OPAQUE_AS_LSA)
155 && (OspfRI.scope != OSPF_OPAQUE_AREA_LSA)) {
ade6974d
QY
156 assert("Unable to unregister Router Info functions: Wrong scope!"
157 == NULL);
bcf4475e
OD
158 return -1;
159 }
160
161 ospf_delete_opaque_functab(OspfRI.scope,
162 OPAQUE_TYPE_ROUTER_INFORMATION_LSA);
163
164 OspfRI.registered = 0;
165 return 0;
166}
167
d62a17ae 168void ospf_router_info_term(void)
0ef4bcdc
OD
169{
170
6a154c88
DL
171 list_delete(&OspfRI.pce_info.pce_domain);
172 list_delete(&OspfRI.pce_info.pce_neighbor);
0ef4bcdc 173
32ab5cf4 174 OspfRI.enabled = false;
0ef4bcdc 175
bcf4475e
OD
176 ospf_router_info_unregister();
177
d62a17ae 178 return;
0ef4bcdc
OD
179}
180
bcf4475e
OD
181void ospf_router_info_finish(void)
182{
731271b0
OD
183 struct listnode *node, *nnode;
184 struct ospf_ri_area_info *ai;
185
186 /* Flush Router Info LSA */
187 for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai))
188 if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED))
189 ospf_router_info_lsa_schedule(ai, FLUSH_THIS_LSA);
190
bcf4475e
OD
191 list_delete_all_node(OspfRI.pce_info.pce_domain);
192 list_delete_all_node(OspfRI.pce_info.pce_neighbor);
193
194 OspfRI.enabled = false;
195}
196
ddd73a96
OD
197static void del_area_info(void *val)
198{
199 XFREE(MTYPE_OSPF_ROUTER_INFO, val);
200}
201
d62a17ae 202static void del_pce_info(void *val)
0ef4bcdc 203{
d62a17ae 204 XFREE(MTYPE_OSPF_PCE_PARAMS, val);
0ef4bcdc
OD
205}
206
cf9b9f77
OD
207/* Catch RI LSA flooding Scope for ospf_ext.[h,c] code */
208struct scope_info ospf_router_info_get_flooding_scope(void)
209{
210 struct scope_info flooding_scope;
7743f2f8 211
cf9b9f77
OD
212 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
213 flooding_scope.scope = OSPF_OPAQUE_AS_LSA;
ddd73a96 214 flooding_scope.areas = NULL;
cf9b9f77
OD
215 return flooding_scope;
216 }
217 flooding_scope.scope = OSPF_OPAQUE_AREA_LSA;
ddd73a96 218 flooding_scope.areas = OspfRI.area_info;
cf9b9f77
OD
219 return flooding_scope;
220}
221
ddd73a96
OD
222static struct ospf_ri_area_info *lookup_by_area(struct ospf_area *area)
223{
224 struct listnode *node, *nnode;
225 struct ospf_ri_area_info *ai;
226
227 for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai))
228 if (ai->area == area)
229 return ai;
230
231 return NULL;
232}
233
0ef4bcdc 234/*------------------------------------------------------------------------*
78dfa0c7 235 * Following are control functions for ROUTER INFORMATION parameters
d62a17ae 236 *management.
0ef4bcdc
OD
237 *------------------------------------------------------------------------*/
238
d62a17ae 239static void set_router_info_capabilities(struct ri_tlv_router_cap *ric,
d7c0a89a 240 uint32_t cap)
0ef4bcdc 241{
d62a17ae 242 ric->header.type = htons(RI_TLV_CAPABILITIES);
243 ric->header.length = htons(RI_TLV_LENGTH);
244 ric->value = htonl(cap);
245 return;
0ef4bcdc
OD
246}
247
d62a17ae 248static int set_pce_header(struct ospf_pce_info *pce)
0ef4bcdc 249{
d7c0a89a 250 uint16_t length = 0;
d62a17ae 251 struct listnode *node;
252 struct ri_pce_subtlv_domain *domain;
253 struct ri_pce_subtlv_neighbor *neighbor;
254
255 /* PCE Address */
256 if (ntohs(pce->pce_address.header.type) != 0)
ead99d5f 257 length += TLV_SIZE(&pce->pce_address.header);
d62a17ae 258
259 /* PCE Path Scope */
260 if (ntohs(pce->pce_scope.header.type) != 0)
ead99d5f 261 length += TLV_SIZE(&pce->pce_scope.header);
d62a17ae 262
263 /* PCE Domain */
264 for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
265 if (ntohs(domain->header.type) != 0)
ead99d5f 266 length += TLV_SIZE(&domain->header);
d62a17ae 267 }
268
269 /* PCE Neighbor */
270 for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
271 if (ntohs(neighbor->header.type) != 0)
ead99d5f 272 length += TLV_SIZE(&neighbor->header);
d62a17ae 273 }
274
275 /* PCE Capabilities */
276 if (ntohs(pce->pce_cap_flag.header.type) != 0)
ead99d5f 277 length += TLV_SIZE(&pce->pce_cap_flag.header);
d62a17ae 278
279 if (length != 0) {
280 pce->pce_header.header.type = htons(RI_TLV_PCE);
281 pce->pce_header.header.length = htons(length);
32ab5cf4 282 pce->enabled = true;
d62a17ae 283 } else {
284 pce->pce_header.header.type = 0;
285 pce->pce_header.header.length = 0;
32ab5cf4 286 pce->enabled = false;
d62a17ae 287 }
288
289 return length;
0ef4bcdc
OD
290}
291
d62a17ae 292static void set_pce_address(struct in_addr ipv4, struct ospf_pce_info *pce)
0ef4bcdc
OD
293{
294
d62a17ae 295 /* Enable PCE Info */
296 pce->pce_header.header.type = htons(RI_TLV_PCE);
297 /* Set PCE Address */
298 pce->pce_address.header.type = htons(RI_PCE_SUBTLV_ADDRESS);
8db278b5
OD
299 pce->pce_address.header.length = htons(PCE_ADDRESS_IPV4_SIZE);
300 pce->pce_address.address.type = htons(PCE_ADDRESS_IPV4);
d62a17ae 301 pce->pce_address.address.value = ipv4;
0ef4bcdc 302
d62a17ae 303 return;
0ef4bcdc
OD
304}
305
d7c0a89a 306static void set_pce_path_scope(uint32_t scope, struct ospf_pce_info *pce)
0ef4bcdc
OD
307{
308
d62a17ae 309 /* Set PCE Scope */
310 pce->pce_scope.header.type = htons(RI_PCE_SUBTLV_PATH_SCOPE);
311 pce->pce_scope.header.length = htons(RI_TLV_LENGTH);
312 pce->pce_scope.value = htonl(scope);
0ef4bcdc 313
d62a17ae 314 return;
0ef4bcdc
OD
315}
316
d7c0a89a 317static void set_pce_domain(uint16_t type, uint32_t domain,
d62a17ae 318 struct ospf_pce_info *pce)
0ef4bcdc
OD
319{
320
d62a17ae 321 struct ri_pce_subtlv_domain *new;
0ef4bcdc 322
d62a17ae 323 /* Create new domain info */
324 new = XCALLOC(MTYPE_OSPF_PCE_PARAMS,
325 sizeof(struct ri_pce_subtlv_domain));
0ef4bcdc 326
d62a17ae 327 new->header.type = htons(RI_PCE_SUBTLV_DOMAIN);
8db278b5 328 new->header.length = htons(PCE_ADDRESS_IPV4_SIZE);
d62a17ae 329 new->type = htons(type);
330 new->value = htonl(domain);
0ef4bcdc 331
d62a17ae 332 /* Add new domain to the list */
333 listnode_add(pce->pce_domain, new);
0ef4bcdc 334
d62a17ae 335 return;
0ef4bcdc
OD
336}
337
d7c0a89a 338static void unset_pce_domain(uint16_t type, uint32_t domain,
d62a17ae 339 struct ospf_pce_info *pce)
0ef4bcdc 340{
d62a17ae 341 struct listnode *node;
342 struct ri_pce_subtlv_domain *old = NULL;
343 int found = 0;
344
345 /* Search the corresponding node */
346 for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, old)) {
347 if ((old->type == htons(type))
348 && (old->value == htonl(domain))) {
349 found = 1;
350 break;
351 }
352 }
353
354 /* if found remove it */
355 if (found) {
356 listnode_delete(pce->pce_domain, old);
357
d62a17ae 358 /* Finally free the old domain */
359 XFREE(MTYPE_OSPF_PCE_PARAMS, old);
360 }
0ef4bcdc
OD
361}
362
d7c0a89a 363static void set_pce_neighbor(uint16_t type, uint32_t domain,
d62a17ae 364 struct ospf_pce_info *pce)
0ef4bcdc
OD
365{
366
d62a17ae 367 struct ri_pce_subtlv_neighbor *new;
0ef4bcdc 368
d62a17ae 369 /* Create new neighbor info */
370 new = XCALLOC(MTYPE_OSPF_PCE_PARAMS,
371 sizeof(struct ri_pce_subtlv_neighbor));
0ef4bcdc 372
d62a17ae 373 new->header.type = htons(RI_PCE_SUBTLV_NEIGHBOR);
8db278b5 374 new->header.length = htons(PCE_ADDRESS_IPV4_SIZE);
d62a17ae 375 new->type = htons(type);
376 new->value = htonl(domain);
0ef4bcdc 377
d62a17ae 378 /* Add new domain to the list */
379 listnode_add(pce->pce_neighbor, new);
0ef4bcdc 380
d62a17ae 381 return;
0ef4bcdc
OD
382}
383
d7c0a89a 384static void unset_pce_neighbor(uint16_t type, uint32_t domain,
d62a17ae 385 struct ospf_pce_info *pce)
0ef4bcdc 386{
d62a17ae 387 struct listnode *node;
388 struct ri_pce_subtlv_neighbor *old = NULL;
389 int found = 0;
390
391 /* Search the corresponding node */
392 for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, old)) {
393 if ((old->type == htons(type))
394 && (old->value == htonl(domain))) {
395 found = 1;
396 break;
397 }
398 }
399
400 /* if found remove it */
401 if (found) {
402 listnode_delete(pce->pce_neighbor, old);
403
d62a17ae 404 /* Finally free the old domain */
405 XFREE(MTYPE_OSPF_PCE_PARAMS, old);
406 }
0ef4bcdc
OD
407}
408
d7c0a89a 409static void set_pce_cap_flag(uint32_t cap, struct ospf_pce_info *pce)
0ef4bcdc
OD
410{
411
d62a17ae 412 /* Set PCE Capabilities flag */
413 pce->pce_cap_flag.header.type = htons(RI_PCE_SUBTLV_CAP_FLAG);
414 pce->pce_cap_flag.header.length = htons(RI_TLV_LENGTH);
415 pce->pce_cap_flag.value = htonl(cap);
0ef4bcdc 416
d62a17ae 417 return;
0ef4bcdc
OD
418}
419
cf9b9f77
OD
420/* Segment Routing TLV setter */
421
422/* Algorithm SubTLV - section 3.1 */
93f0a26e 423static void set_sr_algorithm(uint8_t algo)
cf9b9f77
OD
424{
425
426 OspfRI.sr_info.algo.value[0] = algo;
427 for (int i = 1; i < ALGORITHM_COUNT; i++)
428 OspfRI.sr_info.algo.value[i] = SR_ALGORITHM_UNSET;
429
430 /* Set TLV type and length == only 1 Algorithm */
431 TLV_TYPE(OspfRI.sr_info.algo) = htons(RI_SR_TLV_SR_ALGORITHM);
93f0a26e 432 TLV_LEN(OspfRI.sr_info.algo) = htons(sizeof(uint8_t));
cf9b9f77
OD
433}
434
435/* unset Aglogithm SubTLV */
93f0a26e 436static void unset_sr_algorithm(uint8_t algo)
cf9b9f77
OD
437{
438
439 for (int i = 0; i < ALGORITHM_COUNT; i++)
440 OspfRI.sr_info.algo.value[i] = SR_ALGORITHM_UNSET;
441
442 /* Unset TLV type and length */
443 TLV_TYPE(OspfRI.sr_info.algo) = htons(0);
444 TLV_LEN(OspfRI.sr_info.algo) = htons(0);
cf9b9f77
OD
445}
446
6f751f14
OD
447/* Set Segment Routing Global Block SubTLV - section 3.2 */
448static void set_sr_global_label_range(struct sr_block srgb)
cf9b9f77
OD
449{
450 /* Set Header */
6f751f14 451 TLV_TYPE(OspfRI.sr_info.srgb) = htons(RI_SR_TLV_SRGB_LABEL_RANGE);
bc298f5d 452 TLV_LEN(OspfRI.sr_info.srgb) = htons(RI_SR_TLV_LABEL_RANGE_SIZE);
cf9b9f77 453 /* Set Range Size */
6f751f14 454 OspfRI.sr_info.srgb.size = htonl(SET_RANGE_SIZE(srgb.range_size));
cf9b9f77 455 /* Set Lower bound label SubTLV */
6f751f14
OD
456 TLV_TYPE(OspfRI.sr_info.srgb.lower) = htons(SUBTLV_SID_LABEL);
457 TLV_LEN(OspfRI.sr_info.srgb.lower) = htons(SID_RANGE_LABEL_LENGTH);
458 OspfRI.sr_info.srgb.lower.value = htonl(SET_LABEL(srgb.lower_bound));
cf9b9f77
OD
459}
460
6f751f14
OD
461/* Unset Segment Routing Global Block SubTLV */
462static void unset_sr_global_label_range(void)
cf9b9f77 463{
6f751f14
OD
464 TLV_TYPE(OspfRI.sr_info.srgb) = htons(0);
465 TLV_LEN(OspfRI.sr_info.srgb) = htons(0);
466 TLV_TYPE(OspfRI.sr_info.srgb.lower) = htons(0);
467 TLV_LEN(OspfRI.sr_info.srgb.lower) = htons(0);
468}
cf9b9f77 469
6f751f14
OD
470/* Set Segment Routing Local Block SubTLV - section 3.2 */
471static void set_sr_local_label_range(struct sr_block srlb)
472{
473 /* Set Header */
474 TLV_TYPE(OspfRI.sr_info.srlb) = htons(RI_SR_TLV_SRLB_LABEL_RANGE);
bc298f5d 475 TLV_LEN(OspfRI.sr_info.srlb) = htons(RI_SR_TLV_LABEL_RANGE_SIZE);
6f751f14
OD
476 /* Set Range Size */
477 OspfRI.sr_info.srlb.size = htonl(SET_RANGE_SIZE(srlb.range_size));
478 /* Set Lower bound label SubTLV */
479 TLV_TYPE(OspfRI.sr_info.srlb.lower) = htons(SUBTLV_SID_LABEL);
480 TLV_LEN(OspfRI.sr_info.srlb.lower) = htons(SID_RANGE_LABEL_LENGTH);
481 OspfRI.sr_info.srlb.lower.value = htonl(SET_LABEL(srlb.lower_bound));
482}
483
484/* Unset Segment Routing Local Block SubTLV */
485static void unset_sr_local_label_range(void)
486{
487 TLV_TYPE(OspfRI.sr_info.srlb) = htons(0);
488 TLV_LEN(OspfRI.sr_info.srlb) = htons(0);
489 TLV_TYPE(OspfRI.sr_info.srlb.lower) = htons(0);
490 TLV_LEN(OspfRI.sr_info.srlb.lower) = htons(0);
cf9b9f77
OD
491}
492
493/* Set Maximum Stack Depth for this router */
93f0a26e 494static void set_sr_node_msd(uint8_t msd)
cf9b9f77
OD
495{
496 TLV_TYPE(OspfRI.sr_info.msd) = htons(RI_SR_TLV_NODE_MSD);
93f0a26e 497 TLV_LEN(OspfRI.sr_info.msd) = htons(sizeof(uint32_t));
cf9b9f77 498 OspfRI.sr_info.msd.value = msd;
cf9b9f77
OD
499}
500
501/* Unset this router MSD */
7743f2f8 502static void unset_sr_node_msd(void)
cf9b9f77
OD
503{
504 TLV_TYPE(OspfRI.sr_info.msd) = htons(0);
505 TLV_LEN(OspfRI.sr_info.msd) = htons(0);
cf9b9f77 506}
0ef4bcdc 507
9ffaacb0 508static void unset_param(void *tlv_buffer)
0ef4bcdc 509{
9ffaacb0 510 struct tlv_header *tlv = (struct tlv_header *)tlv_buffer;
0ef4bcdc 511
d62a17ae 512 tlv->type = 0;
513 /* Fill the Value to 0 */
9ffaacb0 514 memset(TLV_DATA(tlv_buffer), 0, TLV_BODY_SIZE(tlv));
d62a17ae 515 tlv->length = 0;
0ef4bcdc 516
d62a17ae 517 return;
0ef4bcdc
OD
518}
519
d62a17ae 520static void initialize_params(struct ospf_router_info *ori)
0ef4bcdc 521{
d7c0a89a 522 uint32_t cap = 0;
d62a17ae 523 struct ospf *top;
ddd73a96
OD
524 struct listnode *node, *nnode;
525 struct ospf_area *area;
526 struct ospf_ri_area_info *new;
d62a17ae 527
528 /*
529 * Initialize default Router Information Capabilities.
530 */
ead99d5f 531 cap = RI_TE_SUPPORT;
d62a17ae 532
533 set_router_info_capabilities(&ori->router_cap, cap);
534
535 /* If Area address is not null and exist, retrieve corresponding
536 * structure */
b5a8894d 537 top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
ddd73a96
OD
538 zlog_info("RI (%s): Initialize Router Info for %s scope", __func__,
539 OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS");
d62a17ae 540
ddd73a96
OD
541 /* Try to get available Area's context from ospf at this step.
542 * Do it latter if not available */
543 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
731271b0
OD
544 if (!list_isempty(OspfRI.area_info))
545 list_delete_all_node(OspfRI.area_info);
ddd73a96 546 for (ALL_LIST_ELEMENTS(top->areas, node, nnode, area)) {
96b663a3
MS
547 zlog_debug("RI (%s): Add area %pI4 to Router Information",
548 __func__, &area->area_id);
ddd73a96
OD
549 new = XCALLOC(MTYPE_OSPF_ROUTER_INFO,
550 sizeof(struct ospf_ri_area_info));
551 new->area = area;
552 new->flags = RIFLG_LSA_INACTIVE;
553 listnode_add(OspfRI.area_info, new);
554 }
555 }
d62a17ae 556
557 /*
558 * Initialize default PCE Information values
559 */
560 /* PCE address == OSPF Router ID */
561 set_pce_address(top->router_id, &ori->pce_info);
562
563 /* PCE scope */
564 cap = 7; /* Set L, R and Rd bits to one = intra & inter-area path
565 computation */
566 set_pce_path_scope(cap, &ori->pce_info);
567
568 /* PCE Capabilities */
569 cap = PCE_CAP_BIDIRECTIONAL | PCE_CAP_DIVERSE_PATH | PCE_CAP_OBJECTIVES
570 | PCE_CAP_ADDITIVE | PCE_CAP_MULTIPLE_REQ;
571 set_pce_cap_flag(cap, &ori->pce_info);
572
d62a17ae 573 return;
0ef4bcdc
OD
574}
575
83df36e8 576static int is_mandated_params_set(struct ospf_router_info *ori)
0ef4bcdc 577{
d62a17ae 578 int rc = 0;
0ef4bcdc 579
83df36e8 580 if (ori == NULL)
ead99d5f 581 return rc;
0ef4bcdc 582
83df36e8 583 if (ntohs(ori->router_cap.header.type) == 0)
ead99d5f 584 return rc;
0ef4bcdc 585
83df36e8
OD
586 if ((ntohs(ori->pce_info.pce_header.header.type) == RI_TLV_PCE)
587 && (ntohs(ori->pce_info.pce_address.header.type) == 0)
588 && (ntohs(ori->pce_info.pce_cap_flag.header.type) == 0))
589 return rc;
590
591 if ((ori->sr_info.enabled) && (ntohs(TLV_TYPE(ori->sr_info.algo)) == 0)
592 && (ntohs(TLV_TYPE(ori->sr_info.srgb)) == 0))
cf9b9f77
OD
593 return rc;
594
d62a17ae 595 rc = 1;
0ef4bcdc 596
d62a17ae 597 return rc;
0ef4bcdc
OD
598}
599
cf9b9f77
OD
600/*
601 * Used by Segment Routing to set new TLVs and Sub-TLVs values
602 *
603 * @param enable To activate or not Segment Routing router Information flooding
6f751f14 604 * @param srn Self Segment Routing node
cf9b9f77
OD
605 *
606 * @return none
607 */
6f751f14 608void ospf_router_info_update_sr(bool enable, struct sr_node *srn)
cf9b9f77 609{
ddd73a96
OD
610 struct listnode *node, *nnode;
611 struct ospf_ri_area_info *ai;
612
613 /* First, check if Router Information is registered or not */
614 if (!OspfRI.registered)
615 ospf_router_info_register(OSPF_OPAQUE_AREA_LSA);
616
617 /* Verify that scope is AREA */
618 if (OspfRI.scope != OSPF_OPAQUE_AREA_LSA) {
619 zlog_err(
620 "RI (%s): Router Info is %s flooding: Change scope to Area flooding for Segment Routing",
621 __func__,
622 OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS");
623 return;
624 }
cf9b9f77 625
ddd73a96 626 /* Then, activate and initialize Router Information if necessary */
cf9b9f77
OD
627 if (!OspfRI.enabled) {
628 OspfRI.enabled = true;
629 initialize_params(&OspfRI);
630 }
631
83df36e8
OD
632 /* Check that SR node is valid */
633 if (srn == NULL)
634 return;
635
cf9b9f77 636 if (IS_DEBUG_OSPF_SR)
ddd73a96
OD
637 zlog_debug("RI (%s): %s Routing Information for Segment Routing",
638 __func__, enable ? "Enable" : "Disable");
cf9b9f77
OD
639
640 /* Unset or Set SR parameters */
641 if (!enable) {
642 unset_sr_algorithm(SR_ALGORITHM_SPF);
6f751f14
OD
643 unset_sr_global_label_range();
644 unset_sr_local_label_range();
cf9b9f77
OD
645 unset_sr_node_msd();
646 OspfRI.sr_info.enabled = false;
647 } else {
648 // Only SR_ALGORITHM_SPF is supported
649 set_sr_algorithm(SR_ALGORITHM_SPF);
6f751f14
OD
650 set_sr_global_label_range(srn->srgb);
651 set_sr_local_label_range(srn->srlb);
652 if (srn->msd != 0)
653 set_sr_node_msd(srn->msd);
cf9b9f77
OD
654 else
655 unset_sr_node_msd();
656 OspfRI.sr_info.enabled = true;
657 }
658
659 /* Refresh if already engaged or originate RI LSA */
ddd73a96
OD
660 for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai)) {
661 if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED))
662 ospf_router_info_lsa_schedule(ai, REFRESH_THIS_LSA);
663 else
664 ospf_router_info_lsa_schedule(ai,
665 REORIGINATE_THIS_LSA);
666
667 }
cf9b9f77
OD
668}
669
0ef4bcdc 670/*------------------------------------------------------------------------*
78dfa0c7 671 * Following are callback functions against generic Opaque-LSAs handling.
0ef4bcdc 672 *------------------------------------------------------------------------*/
d62a17ae 673static void ospf_router_info_ism_change(struct ospf_interface *oi,
674 int old_state)
0ef4bcdc 675{
0ef4bcdc 676
ddd73a96
OD
677 struct ospf_ri_area_info *ai;
678
679 /* Collect area information */
680 ai = lookup_by_area(oi->area);
681
682 /* Check if area is not yet registered */
683 if (ai != NULL)
684 return;
685
686 /* Add this new area to the list */
687 ai = XCALLOC(MTYPE_OSPF_ROUTER_INFO, sizeof(struct ospf_ri_area_info));
688 ai->area = oi->area;
689 ai->flags = RIFLG_LSA_INACTIVE;
690 listnode_add(OspfRI.area_info, ai);
691
d62a17ae 692 return;
0ef4bcdc
OD
693}
694
695/*------------------------------------------------------------------------*
78dfa0c7 696 * Following are OSPF protocol processing functions for ROUTER INFORMATION
0ef4bcdc
OD
697 *------------------------------------------------------------------------*/
698
ead99d5f 699static void build_tlv_header(struct stream *s, struct tlv_header *tlvh)
0ef4bcdc
OD
700{
701
ead99d5f 702 stream_put(s, tlvh, sizeof(struct tlv_header));
d62a17ae 703 return;
0ef4bcdc
OD
704}
705
ead99d5f 706static void build_tlv(struct stream *s, struct tlv_header *tlvh)
0ef4bcdc
OD
707{
708
d62a17ae 709 if (ntohs(tlvh->type) != 0) {
710 build_tlv_header(s, tlvh);
5d0df50f 711 stream_put(s, TLV_DATA(tlvh), TLV_BODY_SIZE(tlvh));
d62a17ae 712 }
713 return;
0ef4bcdc
OD
714}
715
d62a17ae 716static void ospf_router_info_lsa_body_set(struct stream *s)
0ef4bcdc
OD
717{
718
d62a17ae 719 struct listnode *node;
720 struct ri_pce_subtlv_domain *domain;
721 struct ri_pce_subtlv_neighbor *neighbor;
0ef4bcdc 722
d62a17ae 723 /* Build Router Information TLV */
724 build_tlv(s, &OspfRI.router_cap.header);
0ef4bcdc 725
cf9b9f77
OD
726 /* Build Segment Routing TLVs if enabled */
727 if (OspfRI.sr_info.enabled) {
728 /* Build Algorithm TLV */
729 build_tlv(s, &TLV_HDR(OspfRI.sr_info.algo));
730 /* Build SRGB TLV */
6f751f14
OD
731 build_tlv(s, &TLV_HDR(OspfRI.sr_info.srgb));
732 /* Build SRLB TLV */
733 build_tlv(s, &TLV_HDR(OspfRI.sr_info.srlb));
cf9b9f77
OD
734 /* Build MSD TLV */
735 build_tlv(s, &TLV_HDR(OspfRI.sr_info.msd));
736 }
ead99d5f
OD
737
738 /* Add RI PCE TLV if it is set */
32ab5cf4 739 if (OspfRI.pce_info.enabled) {
0ef4bcdc 740
cf9b9f77 741 /* Compute PCE Info header first */
996c9314 742 set_pce_header(&OspfRI.pce_info);
cf9b9f77 743
d62a17ae 744 /* Build PCE TLV */
745 build_tlv_header(s, &OspfRI.pce_info.pce_header.header);
0ef4bcdc 746
d62a17ae 747 /* Build PCE address sub-tlv */
748 build_tlv(s, &OspfRI.pce_info.pce_address.header);
0ef4bcdc 749
d62a17ae 750 /* Build PCE path scope sub-tlv */
751 build_tlv(s, &OspfRI.pce_info.pce_scope.header);
0ef4bcdc 752
d62a17ae 753 /* Build PCE domain sub-tlv */
754 for (ALL_LIST_ELEMENTS_RO(OspfRI.pce_info.pce_domain, node,
755 domain))
756 build_tlv(s, &domain->header);
0ef4bcdc 757
d62a17ae 758 /* Build PCE neighbor sub-tlv */
759 for (ALL_LIST_ELEMENTS_RO(OspfRI.pce_info.pce_neighbor, node,
760 neighbor))
761 build_tlv(s, &neighbor->header);
0ef4bcdc 762
d62a17ae 763 /* Build PCE cap flag sub-tlv */
764 build_tlv(s, &OspfRI.pce_info.pce_cap_flag.header);
765 }
0ef4bcdc 766
d62a17ae 767 return;
0ef4bcdc
OD
768}
769
770/* Create new opaque-LSA. */
ddd73a96 771static struct ospf_lsa *ospf_router_info_lsa_new(struct ospf_area *area)
0ef4bcdc 772{
d62a17ae 773 struct ospf *top;
774 struct stream *s;
775 struct lsa_header *lsah;
776 struct ospf_lsa *new = NULL;
d7c0a89a 777 uint8_t options, lsa_type;
d62a17ae 778 struct in_addr lsa_id;
d7c0a89a
QY
779 uint32_t tmp;
780 uint16_t length;
d62a17ae 781
782 /* Create a stream for LSA. */
266469eb
DS
783 s = stream_new(OSPF_MAX_LSA_SIZE);
784
d62a17ae 785 lsah = (struct lsa_header *)STREAM_DATA(s);
786
787 options = OSPF_OPTION_E; /* Enable AS external as we flood RI with
788 Opaque Type 11 */
789 options |= OSPF_OPTION_O; /* Don't forget this :-) */
790
791 lsa_type = OspfRI.scope;
792 /* LSA ID == 0 for Router Information see RFC 4970 */
793 tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_ROUTER_INFORMATION_LSA, 0);
794 lsa_id.s_addr = htonl(tmp);
795
796 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
797 zlog_debug(
96b663a3
MS
798 "LSA[Type%d:%pI4]: Create an Opaque-LSA/ROUTER INFORMATION instance",
799 lsa_type, &lsa_id);
d62a17ae 800
b5a8894d 801 top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
d62a17ae 802
803 /* Set opaque-LSA header fields. */
804 lsa_header_set(s, options, lsa_type, lsa_id, top->router_id);
805
806 /* Set opaque-LSA body fields. */
807 ospf_router_info_lsa_body_set(s);
808
809 /* Set length. */
810 length = stream_get_endp(s);
811 lsah->length = htons(length);
812
813 /* Now, create an OSPF LSA instance. */
5b3d4186 814 new = ospf_lsa_new_and_data(length);
d62a17ae 815
ddd73a96 816 new->area = area;
d62a17ae 817
b5a8894d
CS
818 if (new->area && new->area->ospf)
819 new->vrf_id = new->area->ospf->vrf_id;
820 else
821 new->vrf_id = VRF_DEFAULT;
822
d62a17ae 823 SET_FLAG(new->flags, OSPF_LSA_SELF);
824 memcpy(new->data, lsah, length);
825 stream_free(s);
826
d62a17ae 827 return new;
0ef4bcdc
OD
828}
829
ddd73a96 830static int ospf_router_info_lsa_originate_as(void *arg)
0ef4bcdc 831{
d62a17ae 832 struct ospf_lsa *new;
833 struct ospf *top;
d62a17ae 834 int rc = -1;
b5a8894d 835 vrf_id_t vrf_id = VRF_DEFAULT;
d62a17ae 836
ddd73a96 837 /* Sanity Check */
d62a17ae 838 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
ddd73a96
OD
839 flog_warn(
840 EC_OSPF_LSA_INSTALL_FAILURE,
841 "RI (%s): wrong flooding scope AREA instead of AS ?",
842 __func__);
843 return rc;
d62a17ae 844 }
845
846 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
ddd73a96
OD
847 new = ospf_router_info_lsa_new(NULL);
848 new->vrf_id = VRF_DEFAULT;
849 top = (struct ospf *)arg;
d62a17ae 850
ddd73a96 851 /* Check ospf info */
b5a8894d 852 if (top == NULL) {
ddd73a96
OD
853 zlog_debug("RI (%s): ospf instance not found for vrf id %u",
854 __func__, vrf_id);
c2a2f37b 855 ospf_lsa_unlock(&new);
b5a8894d
CS
856 return rc;
857 }
d62a17ae 858
859 /* Install this LSA into LSDB. */
860 if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
542a208f 861 flog_warn(
cf444bcf 862 EC_OSPF_LSA_INSTALL_FAILURE,
ddd73a96
OD
863 "RI (%s): ospf_lsa_install() ?", __func__);
864 ospf_lsa_unlock(&new);
865 return rc;
866 }
867
868 /* Update new LSA origination count. */
869 top->lsa_originate_count++;
870
871 /* Flood new LSA through AREA or AS. */
872 SET_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED);
873 ospf_flood_through_as(top, NULL /*nbr */, new);
874
875 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
876 zlog_debug(
96b663a3
MS
877 "LSA[Type%d:%pI4]: Originate Opaque-LSA/ROUTER INFORMATION",
878 new->data->type, &new->data->id);
ddd73a96
OD
879 ospf_lsa_header_dump(new->data);
880 }
881
882 rc = 0;
883 return rc;
884}
885
886static int ospf_router_info_lsa_originate_area(void *arg)
887{
888 struct ospf_lsa *new;
889 struct ospf *top;
890 struct ospf_ri_area_info *ai = NULL;
891 int rc = -1;
892 vrf_id_t vrf_id = VRF_DEFAULT;
893
894 /* Sanity Check */
895 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
896 flog_warn(
897 EC_OSPF_LSA_INSTALL_FAILURE,
898 "RI (%s): wrong flooding scope AS instead of AREA ?",
899 __func__);
900 return rc;
901 }
902
903 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
904 ai = lookup_by_area((struct ospf_area *)arg);
905 if (ai == NULL) {
906 zlog_debug(
907 "RI (%s): There is no context for this Router Information. Stop processing",
908 __func__);
909 return rc;
910 }
911 if (ai->area->ospf) {
912 vrf_id = ai->area->ospf->vrf_id;
913 top = ai->area->ospf;
914 } else {
915 top = ospf_lookup_by_vrf_id(vrf_id);
916 }
917 new = ospf_router_info_lsa_new(ai->area);
918 new->vrf_id = vrf_id;
919
920 /* Check ospf info */
921 if (top == NULL) {
922 zlog_debug("RI (%s): ospf instance not found for vrf id %u",
923 __func__, vrf_id);
d62a17ae 924 ospf_lsa_unlock(&new);
ead99d5f 925 return rc;
d62a17ae 926 }
927
ddd73a96
OD
928 /* Install this LSA into LSDB. */
929 if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
930 flog_warn(
931 EC_OSPF_LSA_INSTALL_FAILURE,
932 "RI (%s): ospf_lsa_install() ?", __func__);
933 ospf_lsa_unlock(&new);
934 return rc;
935 }
d62a17ae 936
937 /* Update new LSA origination count. */
938 top->lsa_originate_count++;
939
ddd73a96
OD
940 /* Flood new LSA through AREA or AS. */
941 SET_FLAG(ai->flags, RIFLG_LSA_ENGAGED);
942 ospf_flood_through_area(ai->area, NULL /*nbr */, new);
d62a17ae 943
944 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
945 zlog_debug(
96b663a3
MS
946 "LSA[Type%d:%pI4]: Originate Opaque-LSA/ROUTER INFORMATION",
947 new->data->type, &new->data->id);
d62a17ae 948 ospf_lsa_header_dump(new->data);
949 }
950
951 rc = 0;
d62a17ae 952 return rc;
0ef4bcdc
OD
953}
954
d62a17ae 955static int ospf_router_info_lsa_originate(void *arg)
0ef4bcdc
OD
956{
957
ddd73a96 958 struct ospf_ri_area_info *ai;
d62a17ae 959 int rc = -1;
960
32ab5cf4 961 if (!OspfRI.enabled) {
ddd73a96
OD
962 zlog_info("RI (%s): ROUTER INFORMATION is disabled now.",
963 __func__);
d62a17ae 964 rc = 0; /* This is not an error case. */
ead99d5f 965 return rc;
d62a17ae 966 }
967
968 /* Check if Router Information LSA is already engaged */
ddd73a96
OD
969 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
970 if ((CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED))
971 && (CHECK_FLAG(OspfRI.as_flags,
972 RIFLG_LSA_FORCED_REFRESH))) {
973 UNSET_FLAG(OspfRI.as_flags, RIFLG_LSA_FORCED_REFRESH);
974 ospf_router_info_lsa_schedule(NULL, REFRESH_THIS_LSA);
975 rc = 0;
976 return rc;
d62a17ae 977 }
978 } else {
ddd73a96
OD
979 ai = lookup_by_area((struct ospf_area *)arg);
980 if (ai == NULL) {
239697e3 981 flog_warn(
cf444bcf 982 EC_OSPF_LSA,
ddd73a96 983 "RI (%s): Missing area information", __func__);
ead99d5f 984 return rc;
ddd73a96
OD
985 }
986 if ((CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED))
987 && (CHECK_FLAG(ai->flags, RIFLG_LSA_FORCED_REFRESH))) {
988 UNSET_FLAG(ai->flags, RIFLG_LSA_FORCED_REFRESH);
989 ospf_router_info_lsa_schedule(ai, REFRESH_THIS_LSA);
990 rc = 0;
991 return rc;
992 }
d62a17ae 993 }
994
ddd73a96 995 /* Router Information is not yet Engaged, check parameters */
83df36e8 996 if (!is_mandated_params_set(&OspfRI))
ddd73a96
OD
997 flog_warn(
998 EC_OSPF_LSA,
999 "RI (%s): lacks mandated ROUTER INFORMATION parameters",
1000 __func__);
1001
1002 /* Ok, let's try to originate an LSA */
1003 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
1004 rc = ospf_router_info_lsa_originate_as(arg);
1005 else
1006 rc = ospf_router_info_lsa_originate_area(arg);
1007
d62a17ae 1008 return rc;
0ef4bcdc
OD
1009}
1010
d62a17ae 1011static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa)
0ef4bcdc 1012{
ddd73a96 1013 struct ospf_ri_area_info *ai = NULL;
d62a17ae 1014 struct ospf_lsa *new = NULL;
1015 struct ospf *top;
1016
32ab5cf4 1017 if (!OspfRI.enabled) {
d62a17ae 1018 /*
1019 * This LSA must have flushed before due to ROUTER INFORMATION
1020 * status change.
1021 * It seems a slip among routers in the routing domain.
1022 */
ddd73a96
OD
1023 zlog_info("RI (%s): ROUTER INFORMATION is disabled now.",
1024 __func__);
d62a17ae 1025 lsa->data->ls_age =
1026 htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
1027 }
1028
1029 /* Verify that the Router Information ID is supported */
1030 if (GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)) != 0) {
239697e3 1031 flog_warn(
cf444bcf 1032 EC_OSPF_LSA,
ddd73a96
OD
1033 "RI (%s): Unsupported Router Information ID",
1034 __func__);
ead99d5f 1035 return NULL;
d62a17ae 1036 }
1037
ddd73a96
OD
1038 /* Process LSA depending of the flooding scope */
1039 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
1040 /* Get context AREA context */
1041 ai = lookup_by_area(lsa->area);
1042 if (ai == NULL) {
1043 flog_warn(
1044 EC_OSPF_LSA,
1045 "RI (%s): No associated Area", __func__);
1046 return NULL;
1047 }
1048 /* Flush LSA, if the lsa's age reached to MaxAge. */
1049 if (IS_LSA_MAXAGE(lsa)) {
1050 UNSET_FLAG(ai->flags, RIFLG_LSA_ENGAGED);
1051 ospf_opaque_lsa_flush_schedule(lsa);
1052 return NULL;
1053 }
1054 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
1055 new = ospf_router_info_lsa_new(ai->area);
1056 new->data->ls_seqnum = lsa_seqnum_increment(lsa);
1057 new->vrf_id = lsa->vrf_id;
1058 /* Install this LSA into LSDB. */
1059 /* Given "lsa" will be freed in the next function. */
1060 top = ospf_lookup_by_vrf_id(lsa->vrf_id);
1061 if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
1062 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
1063 "RI (%s): ospf_lsa_install() ?", __func__);
1064 ospf_lsa_unlock(&new);
1065 return new;
1066 }
1067 /* Flood updated LSA through AREA */
1068 ospf_flood_through_area(ai->area, NULL /*nbr */, new);
1069
1070 } else { /* AS Flooding scope */
1071 /* Flush LSA, if the lsa's age reached to MaxAge. */
1072 if (IS_LSA_MAXAGE(lsa)) {
1073 UNSET_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED);
1074 ospf_opaque_lsa_flush_schedule(lsa);
1075 return NULL;
1076 }
1077 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
1078 new = ospf_router_info_lsa_new(NULL);
1079 new->data->ls_seqnum = lsa_seqnum_increment(lsa);
1080 new->vrf_id = lsa->vrf_id;
1081 /* Install this LSA into LSDB. */
1082 /* Given "lsa" will be freed in the next function. */
1083 top = ospf_lookup_by_vrf_id(lsa->vrf_id);
1084 if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
1085 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
1086 "RI (%s): ospf_lsa_install() ?", __func__);
1087 ospf_lsa_unlock(&new);
1088 return new;
1089 }
1090 /* Flood updated LSA through AS */
d62a17ae 1091 ospf_flood_through_as(top, NULL /*nbr */, new);
ddd73a96 1092 }
d62a17ae 1093
1094 /* Debug logging. */
1095 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
1096 zlog_debug(
96b663a3
MS
1097 "LSA[Type%d:%pI4]: Refresh Opaque-LSA/ROUTER INFORMATION",
1098 new->data->type, &new->data->id);
d62a17ae 1099 ospf_lsa_header_dump(new->data);
1100 }
1101
d62a17ae 1102 return new;
0ef4bcdc
OD
1103}
1104
ddd73a96
OD
1105static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info *ai,
1106 enum lsa_opcode opcode)
0ef4bcdc 1107{
d62a17ae 1108 struct ospf_lsa lsa;
1109 struct lsa_header lsah;
1110 struct ospf *top;
d7c0a89a 1111 uint32_t tmp;
d62a17ae 1112
1113 memset(&lsa, 0, sizeof(lsa));
1114 memset(&lsah, 0, sizeof(lsah));
1115
ddd73a96 1116 zlog_debug("RI (%s): LSA schedule %s%s%s", __func__,
d62a17ae 1117 opcode == REORIGINATE_THIS_LSA ? "Re-Originate" : "",
1118 opcode == REFRESH_THIS_LSA ? "Refresh" : "",
1119 opcode == FLUSH_THIS_LSA ? "Flush" : "");
1120
ddd73a96
OD
1121 /* Check LSA flags state coherence and collect area information */
1122 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
1123 if ((ai == NULL) || (ai->area == NULL)) {
1124 flog_warn(
1125 EC_OSPF_LSA,
1126 "RI (%s): Router Info is Area scope flooding but area is not set",
1127 __func__);
1128 return;
1129 }
ead99d5f 1130
ddd73a96
OD
1131 if (!CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED)
1132 && (opcode != REORIGINATE_THIS_LSA))
1133 return;
ead99d5f 1134
ddd73a96
OD
1135 if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED)
1136 && (opcode == REORIGINATE_THIS_LSA))
1137 opcode = REFRESH_THIS_LSA;
1138
1139 lsa.area = ai->area;
1140 top = ai->area->ospf;
1141 } else {
1142 if (!CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED)
1143 && (opcode != REORIGINATE_THIS_LSA))
1144 return;
1145
1146 if (CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED)
1147 && (opcode == REORIGINATE_THIS_LSA))
1148 opcode = REFRESH_THIS_LSA;
1149
1150 top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1151 lsa.area = NULL;
d62a17ae 1152 }
ddd73a96 1153
d62a17ae 1154 lsa.data = &lsah;
1155 lsah.type = OspfRI.scope;
1156
1157 /* LSA ID is set to 0 for the Router Information. See RFC 4970 */
1158 tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_ROUTER_INFORMATION_LSA, 0);
1159 lsah.id.s_addr = htonl(tmp);
1160
1161 switch (opcode) {
1162 case REORIGINATE_THIS_LSA:
1163 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA)
1164 ospf_opaque_lsa_reoriginate_schedule(
ddd73a96 1165 (void *)ai->area, OSPF_OPAQUE_AREA_LSA,
d62a17ae 1166 OPAQUE_TYPE_ROUTER_INFORMATION_LSA);
1167 else
1168 ospf_opaque_lsa_reoriginate_schedule(
1169 (void *)top, OSPF_OPAQUE_AS_LSA,
1170 OPAQUE_TYPE_ROUTER_INFORMATION_LSA);
1171 break;
1172 case REFRESH_THIS_LSA:
1173 ospf_opaque_lsa_refresh_schedule(&lsa);
1174 break;
1175 case FLUSH_THIS_LSA:
ddd73a96
OD
1176 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA)
1177 UNSET_FLAG(ai->flags, RIFLG_LSA_ENGAGED);
1178 else
1179 UNSET_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED);
d62a17ae 1180 ospf_opaque_lsa_flush_schedule(&lsa);
1181 break;
d62a17ae 1182 }
1183
1184 return;
0ef4bcdc
OD
1185}
1186
cf9b9f77
OD
1187/* Callback to handle Segment Routing information */
1188static int ospf_router_info_lsa_update(struct ospf_lsa *lsa)
1189{
1190
1191 /* Sanity Check */
1192 if (lsa == NULL) {
ddd73a96 1193 flog_warn(EC_OSPF_LSA, "RI (%s): Abort! LSA is NULL",
239697e3 1194 __func__);
cf9b9f77
OD
1195 return -1;
1196 }
1197
6aaf0fdd
OD
1198 /* Process only Opaque LSA */
1199 if ((lsa->data->type != OSPF_OPAQUE_AREA_LSA)
1200 && (lsa->data->type != OSPF_OPAQUE_AS_LSA))
cf9b9f77
OD
1201 return 0;
1202
1203 /* Process only Router Information LSA */
996c9314
LB
1204 if (GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr))
1205 != OPAQUE_TYPE_ROUTER_INFORMATION_LSA)
cf9b9f77
OD
1206 return 0;
1207
6aaf0fdd
OD
1208 /* Check if it is not my LSA */
1209 if (IS_LSA_SELF(lsa))
1210 return 0;
1211
cf9b9f77
OD
1212 /* Check if Router Info & Segment Routing are enable */
1213 if (!OspfRI.enabled || !OspfRI.sr_info.enabled)
1214 return 0;
1215
1216 /* Call Segment Routing LSA update or deletion */
1217 if (!IS_LSA_MAXAGE(lsa))
1218 ospf_sr_ri_lsa_update(lsa);
1219 else
1220 ospf_sr_ri_lsa_delete(lsa);
1221
1222 return 0;
1223}
1224
0ef4bcdc 1225/*------------------------------------------------------------------------*
78dfa0c7 1226 * Following are vty session control functions.
0ef4bcdc
OD
1227 *------------------------------------------------------------------------*/
1228
8db278b5
OD
1229#define check_tlv_size(size, msg) \
1230 do { \
1231 if (ntohs(tlvh->length) > size) { \
1232 if (vty != NULL) \
1233 vty_out(vty, " Wrong %s TLV size: %d(%d)\n", \
1234 msg, ntohs(tlvh->length), size); \
1235 else \
55370b95 1236 zlog_debug(" Wrong %s TLV size: %d(%d)", \
8db278b5
OD
1237 msg, ntohs(tlvh->length), size); \
1238 return size + TLV_HDR_SIZE; \
1239 } \
1240 } while (0)
1241
d7c0a89a 1242static uint16_t show_vty_router_cap(struct vty *vty, struct tlv_header *tlvh)
0ef4bcdc 1243{
d62a17ae 1244 struct ri_tlv_router_cap *top = (struct ri_tlv_router_cap *)tlvh;
0ef4bcdc 1245
8db278b5
OD
1246 check_tlv_size(RI_TLV_CAPABILITIES_SIZE, "Router Capabilities");
1247
d62a17ae 1248 if (vty != NULL)
1249 vty_out(vty, " Router Capabilities: 0x%x\n",
1250 ntohl(top->value));
1251 else
1252 zlog_debug(" Router Capabilities: 0x%x", ntohl(top->value));
0ef4bcdc 1253
ead99d5f 1254 return TLV_SIZE(tlvh);
0ef4bcdc
OD
1255}
1256
d7c0a89a
QY
1257static uint16_t show_vty_pce_subtlv_address(struct vty *vty,
1258 struct tlv_header *tlvh)
0ef4bcdc 1259{
d62a17ae 1260 struct ri_pce_subtlv_address *top =
1261 (struct ri_pce_subtlv_address *)tlvh;
1262
8db278b5
OD
1263 if (ntohs(top->address.type) == PCE_ADDRESS_IPV4) {
1264 check_tlv_size(PCE_ADDRESS_IPV4_SIZE, "PCE Address");
d62a17ae 1265 if (vty != NULL)
96b663a3
MS
1266 vty_out(vty, " PCE Address: %pI4\n",
1267 &top->address.value);
d62a17ae 1268 else
96b663a3
MS
1269 zlog_debug(" PCE Address: %pI4",
1270 &top->address.value);
8db278b5 1271 } else if (ntohs(top->address.type) == PCE_ADDRESS_IPV6) {
d62a17ae 1272 /* TODO: Add support to IPv6 with inet_ntop() */
8db278b5 1273 check_tlv_size(PCE_ADDRESS_IPV6_SIZE, "PCE Address");
d62a17ae 1274 if (vty != NULL)
1275 vty_out(vty, " PCE Address: 0x%x\n",
1276 ntohl(top->address.value.s_addr));
1277 else
1278 zlog_debug(" PCE Address: 0x%x",
1279 ntohl(top->address.value.s_addr));
8db278b5
OD
1280 } else {
1281 if (vty != NULL)
1282 vty_out(vty, " Wrong PCE Address type: 0x%x\n",
1283 ntohl(top->address.type));
1284 else
1285 zlog_debug(" Wrong PCE Address type: 0x%x",
1286 ntohl(top->address.type));
d62a17ae 1287 }
1288
ead99d5f 1289 return TLV_SIZE(tlvh);
0ef4bcdc
OD
1290}
1291
d7c0a89a
QY
1292static uint16_t show_vty_pce_subtlv_path_scope(struct vty *vty,
1293 struct tlv_header *tlvh)
0ef4bcdc 1294{
d62a17ae 1295 struct ri_pce_subtlv_path_scope *top =
1296 (struct ri_pce_subtlv_path_scope *)tlvh;
0ef4bcdc 1297
8db278b5
OD
1298 check_tlv_size(RI_PCE_SUBTLV_PATH_SCOPE_SIZE, "PCE Path Scope");
1299
d62a17ae 1300 if (vty != NULL)
1301 vty_out(vty, " PCE Path Scope: 0x%x\n", ntohl(top->value));
1302 else
1303 zlog_debug(" PCE Path Scope: 0x%x", ntohl(top->value));
0ef4bcdc 1304
ead99d5f 1305 return TLV_SIZE(tlvh);
0ef4bcdc
OD
1306}
1307
d7c0a89a
QY
1308static uint16_t show_vty_pce_subtlv_domain(struct vty *vty,
1309 struct tlv_header *tlvh)
0ef4bcdc 1310{
d62a17ae 1311 struct ri_pce_subtlv_domain *top = (struct ri_pce_subtlv_domain *)tlvh;
1312 struct in_addr tmp;
1313
8db278b5
OD
1314 check_tlv_size(RI_PCE_SUBTLV_DOMAIN_SIZE, "PCE Domain");
1315
d62a17ae 1316 if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) {
1317 tmp.s_addr = top->value;
1318 if (vty != NULL)
8db278b5 1319 vty_out(vty, " PCE Domain Area: %pI4\n", &tmp);
d62a17ae 1320 else
8db278b5
OD
1321 zlog_debug(" PCE Domain Area: %pI4", &tmp);
1322 } else if (ntohs(top->type) == PCE_DOMAIN_TYPE_AS) {
d62a17ae 1323 if (vty != NULL)
8db278b5 1324 vty_out(vty, " PCE Domain AS: %d\n",
d62a17ae 1325 ntohl(top->value));
1326 else
8db278b5
OD
1327 zlog_debug(" PCE Domain AS: %d", ntohl(top->value));
1328 } else {
1329 if (vty != NULL)
1330 vty_out(vty, " Wrong PCE Domain type: %d\n",
1331 ntohl(top->type));
1332 else
1333 zlog_debug(" Wrong PCE Domain type: %d",
1334 ntohl(top->type));
d62a17ae 1335 }
8db278b5 1336
ead99d5f 1337 return TLV_SIZE(tlvh);
0ef4bcdc
OD
1338}
1339
d7c0a89a
QY
1340static uint16_t show_vty_pce_subtlv_neighbor(struct vty *vty,
1341 struct tlv_header *tlvh)
0ef4bcdc
OD
1342{
1343
d62a17ae 1344 struct ri_pce_subtlv_neighbor *top =
1345 (struct ri_pce_subtlv_neighbor *)tlvh;
1346 struct in_addr tmp;
1347
8db278b5
OD
1348 check_tlv_size(RI_PCE_SUBTLV_NEIGHBOR_SIZE, "PCE Neighbor");
1349
d62a17ae 1350 if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) {
1351 tmp.s_addr = top->value;
1352 if (vty != NULL)
8db278b5 1353 vty_out(vty, " PCE Neighbor Area: %pI4\n", &tmp);
d62a17ae 1354 else
8db278b5
OD
1355 zlog_debug(" PCE Neighbor Area: %pI4", &tmp);
1356 } else if (ntohs(top->type) == PCE_DOMAIN_TYPE_AS) {
d62a17ae 1357 if (vty != NULL)
8db278b5 1358 vty_out(vty, " PCE Neighbor AS: %d\n",
d62a17ae 1359 ntohl(top->value));
1360 else
8db278b5 1361 zlog_debug(" PCE Neighbor AS: %d",
d62a17ae 1362 ntohl(top->value));
8db278b5
OD
1363 } else {
1364 if (vty != NULL)
1365 vty_out(vty, " Wrong PCE Neighbor type: %d\n",
1366 ntohl(top->type));
1367 else
1368 zlog_debug(" Wrong PCE Neighbor type: %d",
1369 ntohl(top->type));
d62a17ae 1370 }
8db278b5 1371
ead99d5f 1372 return TLV_SIZE(tlvh);
0ef4bcdc
OD
1373}
1374
d7c0a89a
QY
1375static uint16_t show_vty_pce_subtlv_cap_flag(struct vty *vty,
1376 struct tlv_header *tlvh)
0ef4bcdc 1377{
d62a17ae 1378 struct ri_pce_subtlv_cap_flag *top =
1379 (struct ri_pce_subtlv_cap_flag *)tlvh;
0ef4bcdc 1380
8db278b5
OD
1381 check_tlv_size(RI_PCE_SUBTLV_CAP_FLAG_SIZE, "PCE Capabilities");
1382
d62a17ae 1383 if (vty != NULL)
1384 vty_out(vty, " PCE Capabilities Flag: 0x%x\n",
1385 ntohl(top->value));
1386 else
1387 zlog_debug(" PCE Capabilities Flag: 0x%x",
1388 ntohl(top->value));
0ef4bcdc 1389
ead99d5f 1390 return TLV_SIZE(tlvh);
0ef4bcdc
OD
1391}
1392
8db278b5
OD
1393static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh,
1394 size_t buf_size)
0ef4bcdc 1395{
8db278b5
OD
1396 if (TLV_SIZE(tlvh) > buf_size) {
1397 if (vty != NULL)
1398 vty_out(vty,
1399 " TLV size %d exceeds buffer size. Abort!",
1400 TLV_SIZE(tlvh));
1401 else
1402 zlog_debug(
1403 " TLV size %d exceeds buffer size. Abort!",
1404 TLV_SIZE(tlvh));
1405 return buf_size;
1406 }
1407
d62a17ae 1408 if (vty != NULL)
1409 vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
1410 ntohs(tlvh->type), ntohs(tlvh->length));
1411 else
1412 zlog_debug(" Unknown TLV: [type(0x%x), length(0x%x)]",
1413 ntohs(tlvh->type), ntohs(tlvh->length));
1414
ead99d5f 1415 return TLV_SIZE(tlvh);
0ef4bcdc
OD
1416}
1417
d7c0a89a 1418static uint16_t show_vty_pce_info(struct vty *vty, struct tlv_header *ri,
8db278b5 1419 size_t buf_size)
0ef4bcdc 1420{
ead99d5f 1421 struct tlv_header *tlvh;
8db278b5 1422 uint16_t length = ntohs(ri->length);
d7c0a89a 1423 uint16_t sum = 0;
d62a17ae 1424
8db278b5
OD
1425 /* Verify that TLV length is valid against remaining buffer size */
1426 if (length > buf_size) {
1427 vty_out(vty,
1428 " PCE Info TLV size %d exceeds buffer size. Abort!\n",
1429 length);
1430 return buf_size;
1431 }
1432
1433 for (tlvh = ri; sum < length; tlvh = TLV_HDR_NEXT(tlvh)) {
d62a17ae 1434 switch (ntohs(tlvh->type)) {
1435 case RI_PCE_SUBTLV_ADDRESS:
1436 sum += show_vty_pce_subtlv_address(vty, tlvh);
1437 break;
1438 case RI_PCE_SUBTLV_PATH_SCOPE:
1439 sum += show_vty_pce_subtlv_path_scope(vty, tlvh);
1440 break;
1441 case RI_PCE_SUBTLV_DOMAIN:
1442 sum += show_vty_pce_subtlv_domain(vty, tlvh);
1443 break;
1444 case RI_PCE_SUBTLV_NEIGHBOR:
1445 sum += show_vty_pce_subtlv_neighbor(vty, tlvh);
1446 break;
1447 case RI_PCE_SUBTLV_CAP_FLAG:
1448 sum += show_vty_pce_subtlv_cap_flag(vty, tlvh);
1449 break;
1450 default:
8db278b5 1451 sum += show_vty_unknown_tlv(vty, tlvh, length - sum);
d62a17ae 1452 break;
1453 }
1454 }
1455 return sum;
0ef4bcdc
OD
1456}
1457
cf9b9f77 1458/* Display Segment Routing Algorithm TLV information */
93f0a26e 1459static uint16_t show_vty_sr_algorithm(struct vty *vty, struct tlv_header *tlvh)
cf9b9f77
OD
1460{
1461 struct ri_sr_tlv_sr_algorithm *algo =
1462 (struct ri_sr_tlv_sr_algorithm *)tlvh;
1463 int i;
7743f2f8 1464
8db278b5
OD
1465 check_tlv_size(ALGORITHM_COUNT, "Segment Routing Algorithm");
1466
cf9b9f77
OD
1467 if (vty != NULL) {
1468 vty_out(vty, " Segment Routing Algorithm TLV:\n");
1469 for (i = 0; i < ntohs(algo->header.length); i++) {
1470 switch (algo->value[i]) {
1471 case 0:
1472 vty_out(vty, " Algorithm %d: SPF\n", i);
1473 break;
1474 case 1:
1475 vty_out(vty, " Algorithm %d: Strict SPF\n",
1476 i);
1477 break;
1478 default:
1479 vty_out(vty,
1480 " Algorithm %d: Unknown value %d\n", i,
1481 algo->value[i]);
1482 break;
1483 }
1484 }
8db278b5 1485 } else {
9165c5f5 1486 zlog_debug(" Segment Routing Algorithm TLV:");
cf9b9f77
OD
1487 for (i = 0; i < ntohs(algo->header.length); i++)
1488 switch (algo->value[i]) {
1489 case 0:
9165c5f5 1490 zlog_debug(" Algorithm %d: SPF", i);
cf9b9f77
OD
1491 break;
1492 case 1:
9165c5f5 1493 zlog_debug(" Algorithm %d: Strict SPF", i);
cf9b9f77
OD
1494 break;
1495 default:
63efca0e
DL
1496 zlog_debug(" Algorithm %d: Unknown value %d",
1497 i, algo->value[i]);
cf9b9f77
OD
1498 break;
1499 }
1500 }
1501
1502 return TLV_SIZE(tlvh);
1503}
1504
1505/* Display Segment Routing SID/Label Range TLV information */
93f0a26e 1506static uint16_t show_vty_sr_range(struct vty *vty, struct tlv_header *tlvh)
cf9b9f77
OD
1507{
1508 struct ri_sr_tlv_sid_label_range *range =
1509 (struct ri_sr_tlv_sid_label_range *)tlvh;
1510
8db278b5
OD
1511 check_tlv_size(RI_SR_TLV_LABEL_RANGE_SIZE, "SR Label Range");
1512
cf9b9f77
OD
1513 if (vty != NULL) {
1514 vty_out(vty,
6f751f14 1515 " Segment Routing %s Range TLV:\n"
cf9b9f77
OD
1516 " Range Size = %d\n"
1517 " SID Label = %d\n\n",
6f751f14
OD
1518 ntohs(range->header.type) == RI_SR_TLV_SRGB_LABEL_RANGE
1519 ? "Global"
1520 : "Local",
cf9b9f77
OD
1521 GET_RANGE_SIZE(ntohl(range->size)),
1522 GET_LABEL(ntohl(range->lower.value)));
1523 } else {
1524 zlog_debug(
1d5453d6 1525 " Segment Routing %s Range TLV: Range Size = %d SID Label = %d",
6f751f14
OD
1526 ntohs(range->header.type) == RI_SR_TLV_SRGB_LABEL_RANGE
1527 ? "Global"
1528 : "Local",
cf9b9f77
OD
1529 GET_RANGE_SIZE(ntohl(range->size)),
1530 GET_LABEL(ntohl(range->lower.value)));
1531 }
1532
1533 return TLV_SIZE(tlvh);
1534}
1535
1536/* Display Segment Routing Maximum Stack Depth TLV information */
93f0a26e 1537static uint16_t show_vty_sr_msd(struct vty *vty, struct tlv_header *tlvh)
cf9b9f77
OD
1538{
1539 struct ri_sr_tlv_node_msd *msd = (struct ri_sr_tlv_node_msd *)tlvh;
1540
8db278b5
OD
1541 check_tlv_size(RI_SR_TLV_NODE_MSD_SIZE, "Node Maximum Stack Depth");
1542
cf9b9f77
OD
1543 if (vty != NULL) {
1544 vty_out(vty,
1545 " Segment Routing MSD TLV:\n"
1546 " Node Maximum Stack Depth = %d\n",
1547 msd->value);
1548 } else {
1549 zlog_debug(
1d5453d6 1550 " Segment Routing MSD TLV: Node Maximum Stack Depth = %d",
cf9b9f77
OD
1551 msd->value);
1552 }
1553
1554 return TLV_SIZE(tlvh);
1555}
1556
3e63092b
RW
1557static void ospf_router_info_show_info(struct vty *vty,
1558 struct json_object *json,
1559 struct ospf_lsa *lsa)
0ef4bcdc 1560{
c4efd0f4 1561 struct lsa_header *lsah = lsa->data;
ead99d5f 1562 struct tlv_header *tlvh;
d7c0a89a 1563 uint16_t length = 0, sum = 0;
d62a17ae 1564
3e63092b
RW
1565 if (json)
1566 return;
1567
d62a17ae 1568 /* Initialize TLV browsing */
8db278b5 1569 length = lsa->size - OSPF_LSA_HEADER_SIZE;
d62a17ae 1570
8db278b5 1571 for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh;
ead99d5f 1572 tlvh = TLV_HDR_NEXT(tlvh)) {
d62a17ae 1573 switch (ntohs(tlvh->type)) {
1574 case RI_TLV_CAPABILITIES:
1575 sum += show_vty_router_cap(vty, tlvh);
1576 break;
1577 case RI_TLV_PCE:
1578 tlvh++;
ead99d5f 1579 sum += TLV_HDR_SIZE;
d62a17ae 1580 sum += show_vty_pce_info(vty, tlvh, length - sum);
1581 break;
cf9b9f77
OD
1582 case RI_SR_TLV_SR_ALGORITHM:
1583 sum += show_vty_sr_algorithm(vty, tlvh);
1584 break;
6f751f14
OD
1585 case RI_SR_TLV_SRGB_LABEL_RANGE:
1586 case RI_SR_TLV_SRLB_LABEL_RANGE:
cf9b9f77
OD
1587 sum += show_vty_sr_range(vty, tlvh);
1588 break;
1589 case RI_SR_TLV_NODE_MSD:
1590 sum += show_vty_sr_msd(vty, tlvh);
1591 break;
1592
d62a17ae 1593 default:
8db278b5 1594 sum += show_vty_unknown_tlv(vty, tlvh, length);
d62a17ae 1595 break;
1596 }
1597 }
1598
1599 return;
0ef4bcdc
OD
1600}
1601
d62a17ae 1602static void ospf_router_info_config_write_router(struct vty *vty)
0ef4bcdc 1603{
d62a17ae 1604 struct ospf_pce_info *pce = &OspfRI.pce_info;
1605 struct listnode *node;
1606 struct ri_pce_subtlv_domain *domain;
1607 struct ri_pce_subtlv_neighbor *neighbor;
1608 struct in_addr tmp;
1609
cf9b9f77
OD
1610 if (!OspfRI.enabled)
1611 return;
1612
1613 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
1614 vty_out(vty, " router-info as\n");
1615 else
ddd73a96 1616 vty_out(vty, " router-info area\n");
cf9b9f77
OD
1617
1618 if (OspfRI.pce_info.enabled) {
1619
1620 if (pce->pce_address.header.type != 0)
96b663a3
MS
1621 vty_out(vty, " pce address %pI4\n",
1622 &pce->pce_address.address.value);
cf9b9f77
OD
1623
1624 if (pce->pce_cap_flag.header.type != 0)
1625 vty_out(vty, " pce flag 0x%x\n",
1626 ntohl(pce->pce_cap_flag.value));
1627
1628 for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
1629 if (domain->header.type != 0) {
1630 if (domain->type == PCE_DOMAIN_TYPE_AREA) {
1631 tmp.s_addr = domain->value;
96b663a3
MS
1632 vty_out(vty, " pce domain area %pI4\n",
1633 &tmp);
cf9b9f77
OD
1634 } else {
1635 vty_out(vty, " pce domain as %d\n",
1636 ntohl(domain->value));
d62a17ae 1637 }
1638 }
cf9b9f77 1639 }
d62a17ae 1640
cf9b9f77
OD
1641 for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
1642 if (neighbor->header.type != 0) {
1643 if (neighbor->type == PCE_DOMAIN_TYPE_AREA) {
1644 tmp.s_addr = neighbor->value;
96b663a3
MS
1645 vty_out(vty,
1646 " pce neighbor area %pI4\n",
1647 &tmp);
cf9b9f77
OD
1648 } else {
1649 vty_out(vty, " pce neighbor as %d\n",
1650 ntohl(neighbor->value));
d62a17ae 1651 }
1652 }
ead99d5f 1653 }
cf9b9f77
OD
1654
1655 if (pce->pce_scope.header.type != 0)
1656 vty_out(vty, " pce scope 0x%x\n",
1657 ntohl(OspfRI.pce_info.pce_scope.value));
d62a17ae 1658 }
1659 return;
0ef4bcdc
OD
1660}
1661
1662/*------------------------------------------------------------------------*
78dfa0c7 1663 * Following are vty command functions.
0ef4bcdc 1664 *------------------------------------------------------------------------*/
ddd73a96
OD
1665/* Simple wrapper schedule RI LSA action in function of the scope */
1666static void ospf_router_info_schedule(enum lsa_opcode opcode)
1667{
1668 struct listnode *node, *nnode;
1669 struct ospf_ri_area_info *ai;
1670
1671 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
1672 if (CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED))
1673 ospf_router_info_lsa_schedule(NULL, opcode);
1674 else if (opcode == REORIGINATE_THIS_LSA)
1675 ospf_router_info_lsa_schedule(NULL, opcode);
1676 } else {
1677 for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai)) {
1678 if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED))
1679 ospf_router_info_lsa_schedule(ai, opcode);
1680 }
1681 }
1682}
0ef4bcdc
OD
1683
1684DEFUN (router_info,
1685 router_info_area_cmd,
ddd73a96 1686 "router-info <as|area [A.B.C.D]>",
0ef4bcdc 1687 OSPF_RI_STR
692b4c65 1688 "Enable the Router Information functionality with AS flooding scope\n"
0ef4bcdc 1689 "Enable the Router Information functionality with Area flooding scope\n"
ddd73a96 1690 "OSPF area ID in IP format (deprecated)\n")
0ef4bcdc 1691{
ddd73a96 1692 int idx_mode = 1;
d7c0a89a 1693 uint8_t scope;
d62a17ae 1694
32ab5cf4 1695 if (OspfRI.enabled)
d62a17ae 1696 return CMD_SUCCESS;
1697
1698 /* Check and get Area value if present */
ddd73a96 1699 if (strncmp(argv[idx_mode]->arg, "as", 2) == 0)
d62a17ae 1700 scope = OSPF_OPAQUE_AS_LSA;
ddd73a96
OD
1701 else
1702 scope = OSPF_OPAQUE_AREA_LSA;
d62a17ae 1703
1704 /* First start to register Router Information callbacks */
ddd73a96 1705 if (!OspfRI.registered && (ospf_router_info_register(scope)) != 0) {
239697e3
DS
1706 vty_out(vty,
1707 "%% Unable to register Router Information callbacks.");
1708 flog_err(
cf444bcf 1709 EC_OSPF_INIT_FAIL,
ddd73a96
OD
1710 "RI (%s): Unable to register Router Information callbacks. Abort!",
1711 __func__);
d62a17ae 1712 return CMD_WARNING_CONFIG_FAILED;
1713 }
1714
32ab5cf4 1715 OspfRI.enabled = true;
d62a17ae 1716
1717 if (IS_DEBUG_OSPF_EVENT)
1718 zlog_debug("RI-> Router Information (%s flooding): OFF -> ON",
1719 OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area"
1720 : "AS");
1721
1722 /*
1723 * Following code is intended to handle two cases;
1724 *
1725 * 1) Router Information was disabled at startup time, but now become
1726 * enabled.
1727 * 2) Router Information was once enabled then disabled, and now enabled
1728 * again.
1729 */
1730
1731 initialize_params(&OspfRI);
1732
ddd73a96
OD
1733 /* Originate or Refresh RI LSA if already engaged */
1734 ospf_router_info_schedule(REORIGINATE_THIS_LSA);
d62a17ae 1735 return CMD_SUCCESS;
0ef4bcdc
OD
1736}
1737
0ef4bcdc
OD
1738
1739DEFUN (no_router_info,
1740 no_router_info_cmd,
1741 "no router-info",
1742 NO_STR
1743 "Disable the Router Information functionality\n")
1744{
1745
32ab5cf4 1746 if (!OspfRI.enabled)
d62a17ae 1747 return CMD_SUCCESS;
0ef4bcdc 1748
d62a17ae 1749 if (IS_DEBUG_OSPF_EVENT)
1750 zlog_debug("RI-> Router Information: ON -> OFF");
0ef4bcdc 1751
ddd73a96 1752 ospf_router_info_schedule(FLUSH_THIS_LSA);
0ef4bcdc 1753
32ab5cf4 1754 OspfRI.enabled = false;
0ef4bcdc 1755
d62a17ae 1756 return CMD_SUCCESS;
0ef4bcdc
OD
1757}
1758
d62a17ae 1759static int ospf_ri_enabled(struct vty *vty)
284a4a0c 1760{
32ab5cf4 1761 if (OspfRI.enabled)
d62a17ae 1762 return 1;
284a4a0c 1763
d62a17ae 1764 if (vty)
1765 vty_out(vty, "%% OSPF RI is not turned on\n");
284a4a0c 1766
d62a17ae 1767 return 0;
284a4a0c
DS
1768}
1769
0ef4bcdc
OD
1770DEFUN (pce_address,
1771 pce_address_cmd,
1772 "pce address A.B.C.D",
1773 PCE_STR
1774 "Stable IP address of the PCE\n"
1775 "PCE address in IPv4 address format\n")
1776{
d62a17ae 1777 int idx_ipv4 = 2;
1778 struct in_addr value;
1779 struct ospf_pce_info *pi = &OspfRI.pce_info;
0ef4bcdc 1780
d62a17ae 1781 if (!ospf_ri_enabled(vty))
1782 return CMD_WARNING_CONFIG_FAILED;
284a4a0c 1783
d62a17ae 1784 if (!inet_aton(argv[idx_ipv4]->arg, &value)) {
1785 vty_out(vty, "Please specify PCE Address by A.B.C.D\n");
1786 return CMD_WARNING_CONFIG_FAILED;
1787 }
0ef4bcdc 1788
d62a17ae 1789 if (ntohs(pi->pce_address.header.type) == 0
1790 || ntohl(pi->pce_address.address.value.s_addr)
1791 != ntohl(value.s_addr)) {
0ef4bcdc 1792
d62a17ae 1793 set_pce_address(value, pi);
0ef4bcdc 1794
d62a17ae 1795 /* Refresh RI LSA if already engaged */
ddd73a96 1796 ospf_router_info_schedule(REFRESH_THIS_LSA);
d62a17ae 1797 }
0ef4bcdc 1798
d62a17ae 1799 return CMD_SUCCESS;
0ef4bcdc
OD
1800}
1801
1802DEFUN (no_pce_address,
1803 no_pce_address_cmd,
2328428d 1804 "no pce address [A.B.C.D]",
0ef4bcdc
OD
1805 NO_STR
1806 PCE_STR
59768a63
DS
1807 "Disable PCE address\n"
1808 "PCE address in IPv4 address format\n")
0ef4bcdc
OD
1809{
1810
9ffaacb0 1811 unset_param(&OspfRI.pce_info.pce_address);
0ef4bcdc 1812
d62a17ae 1813 /* Refresh RI LSA if already engaged */
ddd73a96 1814 ospf_router_info_schedule(REFRESH_THIS_LSA);
0ef4bcdc 1815
d62a17ae 1816 return CMD_SUCCESS;
0ef4bcdc
OD
1817}
1818
1819DEFUN (pce_path_scope,
1820 pce_path_scope_cmd,
1821 "pce scope BITPATTERN",
1822 PCE_STR
1823 "Path scope visibilities of the PCE for path computation\n"
1824 "32-bit Hexadecimal value\n")
1825{
d62a17ae 1826 int idx_bitpattern = 2;
1827 uint32_t scope;
1828 struct ospf_pce_info *pi = &OspfRI.pce_info;
0ef4bcdc 1829
d62a17ae 1830 if (!ospf_ri_enabled(vty))
1831 return CMD_WARNING_CONFIG_FAILED;
284a4a0c 1832
d62a17ae 1833 if (sscanf(argv[idx_bitpattern]->arg, "0x%x", &scope) != 1) {
1834 vty_out(vty, "pce_path_scope: fscanf: %s\n",
1835 safe_strerror(errno));
1836 return CMD_WARNING_CONFIG_FAILED;
1837 }
0ef4bcdc 1838
d62a17ae 1839 if (ntohl(pi->pce_scope.header.type) == 0
1840 || scope != pi->pce_scope.value) {
1841 set_pce_path_scope(scope, pi);
0ef4bcdc 1842
d62a17ae 1843 /* Refresh RI LSA if already engaged */
ddd73a96 1844 ospf_router_info_schedule(REFRESH_THIS_LSA);
d62a17ae 1845 }
0ef4bcdc 1846
d62a17ae 1847 return CMD_SUCCESS;
0ef4bcdc
OD
1848}
1849
1850DEFUN (no_pce_path_scope,
1851 no_pce_path_scope_cmd,
2328428d 1852 "no pce scope [BITPATTERN]",
0ef4bcdc
OD
1853 NO_STR
1854 PCE_STR
59768a63
DS
1855 "Disable PCE path scope\n"
1856 "32-bit Hexadecimal value\n")
0ef4bcdc
OD
1857{
1858
9ffaacb0 1859 unset_param(&OspfRI.pce_info.pce_address);
0ef4bcdc 1860
d62a17ae 1861 /* Refresh RI LSA if already engaged */
ddd73a96 1862 ospf_router_info_schedule(REFRESH_THIS_LSA);
0ef4bcdc 1863
d62a17ae 1864 return CMD_SUCCESS;
0ef4bcdc
OD
1865}
1866
1867DEFUN (pce_domain,
1868 pce_domain_cmd,
6147e2c6 1869 "pce domain as (0-65535)",
0ef4bcdc
OD
1870 PCE_STR
1871 "Configure PCE domain AS number\n"
1872 "AS number where the PCE as visibilities for path computation\n"
1873 "AS number in decimal <0-65535>\n")
1874{
d62a17ae 1875 int idx_number = 3;
0ef4bcdc 1876
d62a17ae 1877 uint32_t as;
1878 struct ospf_pce_info *pce = &OspfRI.pce_info;
1879 struct listnode *node;
1880 struct ri_pce_subtlv_domain *domain;
0ef4bcdc 1881
d62a17ae 1882 if (!ospf_ri_enabled(vty))
1883 return CMD_WARNING_CONFIG_FAILED;
284a4a0c 1884
0651460e 1885 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
d62a17ae 1886 vty_out(vty, "pce_domain: fscanf: %s\n", safe_strerror(errno));
1887 return CMD_WARNING_CONFIG_FAILED;
1888 }
0ef4bcdc 1889
d62a17ae 1890 /* Check if the domain is not already in the domain list */
1891 for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
1892 if (ntohl(domain->header.type) == 0 && as == domain->value)
1893 return CMD_SUCCESS;
1894 }
0ef4bcdc 1895
d62a17ae 1896 /* Create new domain if not found */
1897 set_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce);
0ef4bcdc 1898
d62a17ae 1899 /* Refresh RI LSA if already engaged */
ddd73a96 1900 ospf_router_info_schedule(REFRESH_THIS_LSA);
0ef4bcdc 1901
d62a17ae 1902 return CMD_SUCCESS;
0ef4bcdc
OD
1903}
1904
1905DEFUN (no_pce_domain,
1906 no_pce_domain_cmd,
6147e2c6 1907 "no pce domain as (0-65535)",
0ef4bcdc
OD
1908 NO_STR
1909 PCE_STR
1910 "Disable PCE domain AS number\n"
1911 "AS number where the PCE as visibilities for path computation\n"
1912 "AS number in decimal <0-65535>\n")
1913{
d62a17ae 1914 int idx_number = 4;
0ef4bcdc 1915
d62a17ae 1916 uint32_t as;
1917 struct ospf_pce_info *pce = &OspfRI.pce_info;
0ef4bcdc 1918
0651460e 1919 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
d62a17ae 1920 vty_out(vty, "no_pce_domain: fscanf: %s\n",
1921 safe_strerror(errno));
1922 return CMD_WARNING_CONFIG_FAILED;
1923 }
0ef4bcdc 1924
d62a17ae 1925 /* Unset corresponding PCE domain */
1926 unset_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce);
0ef4bcdc 1927
d62a17ae 1928 /* Refresh RI LSA if already engaged */
ddd73a96 1929 ospf_router_info_schedule(REFRESH_THIS_LSA);
0ef4bcdc 1930
d62a17ae 1931 return CMD_SUCCESS;
0ef4bcdc
OD
1932}
1933
1934DEFUN (pce_neigbhor,
1935 pce_neighbor_cmd,
6147e2c6 1936 "pce neighbor as (0-65535)",
0ef4bcdc
OD
1937 PCE_STR
1938 "Configure PCE neighbor domain AS number\n"
1939 "AS number of PCE neighbors\n"
1940 "AS number in decimal <0-65535>\n")
1941{
d62a17ae 1942 int idx_number = 3;
0ef4bcdc 1943
d62a17ae 1944 uint32_t as;
1945 struct ospf_pce_info *pce = &OspfRI.pce_info;
1946 struct listnode *node;
1947 struct ri_pce_subtlv_neighbor *neighbor;
0ef4bcdc 1948
d62a17ae 1949 if (!ospf_ri_enabled(vty))
1950 return CMD_WARNING_CONFIG_FAILED;
284a4a0c 1951
0651460e 1952 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
d62a17ae 1953 vty_out(vty, "pce_neighbor: fscanf: %s\n",
1954 safe_strerror(errno));
1955 return CMD_WARNING_CONFIG_FAILED;
1956 }
0ef4bcdc 1957
d62a17ae 1958 /* Check if the domain is not already in the domain list */
1959 for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
1960 if (ntohl(neighbor->header.type) == 0 && as == neighbor->value)
1961 return CMD_SUCCESS;
1962 }
0ef4bcdc 1963
d62a17ae 1964 /* Create new domain if not found */
1965 set_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce);
0ef4bcdc 1966
d62a17ae 1967 /* Refresh RI LSA if already engaged */
ddd73a96 1968 ospf_router_info_schedule(REFRESH_THIS_LSA);
0ef4bcdc 1969
d62a17ae 1970 return CMD_SUCCESS;
0ef4bcdc
OD
1971}
1972
1973DEFUN (no_pce_neighbor,
1974 no_pce_neighbor_cmd,
6147e2c6 1975 "no pce neighbor as (0-65535)",
0ef4bcdc
OD
1976 NO_STR
1977 PCE_STR
1978 "Disable PCE neighbor AS number\n"
1979 "AS number of PCE neighbor\n"
1980 "AS number in decimal <0-65535>\n")
1981{
d62a17ae 1982 int idx_number = 4;
0ef4bcdc 1983
d62a17ae 1984 uint32_t as;
1985 struct ospf_pce_info *pce = &OspfRI.pce_info;
0ef4bcdc 1986
0651460e 1987 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
d62a17ae 1988 vty_out(vty, "no_pce_neighbor: fscanf: %s\n",
1989 safe_strerror(errno));
1990 return CMD_WARNING_CONFIG_FAILED;
1991 }
0ef4bcdc 1992
d62a17ae 1993 /* Unset corresponding PCE domain */
1994 unset_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce);
0ef4bcdc 1995
d62a17ae 1996 /* Refresh RI LSA if already engaged */
ddd73a96 1997 ospf_router_info_schedule(REFRESH_THIS_LSA);
0ef4bcdc 1998
d62a17ae 1999 return CMD_SUCCESS;
0ef4bcdc
OD
2000}
2001
2002DEFUN (pce_cap_flag,
2003 pce_cap_flag_cmd,
2004 "pce flag BITPATTERN",
2005 PCE_STR
2006 "Capabilities of the PCE for path computation\n"
2007 "32-bit Hexadecimal value\n")
2008{
d62a17ae 2009 int idx_bitpattern = 2;
0ef4bcdc 2010
d62a17ae 2011 uint32_t cap;
2012 struct ospf_pce_info *pce = &OspfRI.pce_info;
0ef4bcdc 2013
d62a17ae 2014 if (!ospf_ri_enabled(vty))
2015 return CMD_WARNING_CONFIG_FAILED;
284a4a0c 2016
d62a17ae 2017 if (sscanf(argv[idx_bitpattern]->arg, "0x%x", &cap) != 1) {
2018 vty_out(vty, "pce_cap_flag: fscanf: %s\n",
2019 safe_strerror(errno));
2020 return CMD_WARNING_CONFIG_FAILED;
2021 }
0ef4bcdc 2022
d62a17ae 2023 if (ntohl(pce->pce_cap_flag.header.type) == 0
2024 || cap != pce->pce_cap_flag.value) {
2025 set_pce_cap_flag(cap, pce);
0ef4bcdc 2026
d62a17ae 2027 /* Refresh RI LSA if already engaged */
ddd73a96 2028 ospf_router_info_schedule(REFRESH_THIS_LSA);
d62a17ae 2029 }
0ef4bcdc 2030
d62a17ae 2031 return CMD_SUCCESS;
0ef4bcdc
OD
2032}
2033
2034DEFUN (no_pce_cap_flag,
2035 no_pce_cap_flag_cmd,
2036 "no pce flag",
2037 NO_STR
2038 PCE_STR
2039 "Disable PCE capabilities\n")
2040{
2041
9ffaacb0 2042 unset_param(&OspfRI.pce_info.pce_cap_flag);
0ef4bcdc 2043
d62a17ae 2044 /* Refresh RI LSA if already engaged */
ddd73a96 2045 ospf_router_info_schedule(REFRESH_THIS_LSA);
0ef4bcdc 2046
d62a17ae 2047 return CMD_SUCCESS;
0ef4bcdc
OD
2048}
2049
2050DEFUN (show_ip_ospf_router_info,
2051 show_ip_ospf_router_info_cmd,
2052 "show ip ospf router-info",
2053 SHOW_STR
2054 IP_STR
2055 OSPF_STR
2056 "Router Information\n")
2057{
2058
32ab5cf4 2059 if (OspfRI.enabled) {
d62a17ae 2060 vty_out(vty, "--- Router Information parameters ---\n");
2061 show_vty_router_cap(vty, &OspfRI.router_cap.header);
2062 } else {
2063 if (vty != NULL)
2064 vty_out(vty,
2065 " Router Information is disabled on this router\n");
2066 }
2067 return CMD_SUCCESS;
0ef4bcdc
OD
2068}
2069
2070DEFUN (show_ip_opsf_router_info_pce,
2071 show_ip_ospf_router_info_pce_cmd,
2072 "show ip ospf router-info pce",
2073 SHOW_STR
2074 IP_STR
2075 OSPF_STR
2076 "Router Information\n"
2077 "PCE information\n")
2078{
2079
d62a17ae 2080 struct ospf_pce_info *pce = &OspfRI.pce_info;
2081 struct listnode *node;
2082 struct ri_pce_subtlv_domain *domain;
2083 struct ri_pce_subtlv_neighbor *neighbor;
0ef4bcdc 2084
cf9b9f77 2085 if ((OspfRI.enabled) && (OspfRI.pce_info.enabled)) {
d62a17ae 2086 vty_out(vty, "--- PCE parameters ---\n");
0ef4bcdc 2087
d62a17ae 2088 if (pce->pce_address.header.type != 0)
2089 show_vty_pce_subtlv_address(vty,
2090 &pce->pce_address.header);
0ef4bcdc 2091
d62a17ae 2092 if (pce->pce_scope.header.type != 0)
2093 show_vty_pce_subtlv_path_scope(vty,
2094 &pce->pce_scope.header);
0ef4bcdc 2095
d62a17ae 2096 for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
2097 if (domain->header.type != 0)
2098 show_vty_pce_subtlv_domain(vty,
2099 &domain->header);
2100 }
0ef4bcdc 2101
d62a17ae 2102 for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
2103 if (neighbor->header.type != 0)
2104 show_vty_pce_subtlv_neighbor(vty,
2105 &neighbor->header);
2106 }
0ef4bcdc 2107
d62a17ae 2108 if (pce->pce_cap_flag.header.type != 0)
2109 show_vty_pce_subtlv_cap_flag(vty,
2110 &pce->pce_cap_flag.header);
0ef4bcdc 2111
d62a17ae 2112 } else {
996c9314 2113 vty_out(vty, " PCE info is disabled on this router\n");
d62a17ae 2114 }
0ef4bcdc 2115
d62a17ae 2116 return CMD_SUCCESS;
0ef4bcdc
OD
2117}
2118
2119/* Install new CLI commands */
d62a17ae 2120static void ospf_router_info_register_vty(void)
0ef4bcdc 2121{
d62a17ae 2122 install_element(VIEW_NODE, &show_ip_ospf_router_info_cmd);
2123 install_element(VIEW_NODE, &show_ip_ospf_router_info_pce_cmd);
2124
2125 install_element(OSPF_NODE, &router_info_area_cmd);
2126 install_element(OSPF_NODE, &no_router_info_cmd);
2127 install_element(OSPF_NODE, &pce_address_cmd);
2128 install_element(OSPF_NODE, &no_pce_address_cmd);
2129 install_element(OSPF_NODE, &pce_path_scope_cmd);
2130 install_element(OSPF_NODE, &no_pce_path_scope_cmd);
2131 install_element(OSPF_NODE, &pce_domain_cmd);
2132 install_element(OSPF_NODE, &no_pce_domain_cmd);
2133 install_element(OSPF_NODE, &pce_neighbor_cmd);
2134 install_element(OSPF_NODE, &no_pce_neighbor_cmd);
2135 install_element(OSPF_NODE, &pce_cap_flag_cmd);
2136 install_element(OSPF_NODE, &no_pce_cap_flag_cmd);
2137
2138 return;
0ef4bcdc 2139}