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