]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_ri.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[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"
23#include "thread.h"
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
ddd73a96 801 new->area = area;
d62a17ae 802
b5a8894d
CS
803 if (new->area && new->area->ospf)
804 new->vrf_id = new->area->ospf->vrf_id;
805 else
806 new->vrf_id = VRF_DEFAULT;
807
d62a17ae 808 SET_FLAG(new->flags, OSPF_LSA_SELF);
809 memcpy(new->data, lsah, length);
810 stream_free(s);
811
d62a17ae 812 return new;
0ef4bcdc
OD
813}
814
ddd73a96 815static int ospf_router_info_lsa_originate_as(void *arg)
0ef4bcdc 816{
d62a17ae 817 struct ospf_lsa *new;
818 struct ospf *top;
d62a17ae 819 int rc = -1;
b5a8894d 820 vrf_id_t vrf_id = VRF_DEFAULT;
d62a17ae 821
ddd73a96 822 /* Sanity Check */
d62a17ae 823 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
ddd73a96
OD
824 flog_warn(
825 EC_OSPF_LSA_INSTALL_FAILURE,
826 "RI (%s): wrong flooding scope AREA instead of AS ?",
827 __func__);
828 return rc;
d62a17ae 829 }
830
831 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
ddd73a96
OD
832 new = ospf_router_info_lsa_new(NULL);
833 new->vrf_id = VRF_DEFAULT;
834 top = (struct ospf *)arg;
d62a17ae 835
ddd73a96 836 /* Check ospf info */
b5a8894d 837 if (top == NULL) {
ddd73a96
OD
838 zlog_debug("RI (%s): ospf instance not found for vrf id %u",
839 __func__, vrf_id);
c2a2f37b 840 ospf_lsa_unlock(&new);
b5a8894d
CS
841 return rc;
842 }
d62a17ae 843
844 /* Install this LSA into LSDB. */
845 if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
542a208f 846 flog_warn(
cf444bcf 847 EC_OSPF_LSA_INSTALL_FAILURE,
ddd73a96
OD
848 "RI (%s): ospf_lsa_install() ?", __func__);
849 ospf_lsa_unlock(&new);
850 return rc;
851 }
852
853 /* Update new LSA origination count. */
854 top->lsa_originate_count++;
855
856 /* Flood new LSA through AREA or AS. */
857 SET_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED);
858 ospf_flood_through_as(top, NULL /*nbr */, new);
859
860 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
861 zlog_debug(
96b663a3
MS
862 "LSA[Type%d:%pI4]: Originate Opaque-LSA/ROUTER INFORMATION",
863 new->data->type, &new->data->id);
ddd73a96
OD
864 ospf_lsa_header_dump(new->data);
865 }
866
867 rc = 0;
868 return rc;
869}
870
871static int ospf_router_info_lsa_originate_area(void *arg)
872{
873 struct ospf_lsa *new;
874 struct ospf *top;
875 struct ospf_ri_area_info *ai = NULL;
876 int rc = -1;
877 vrf_id_t vrf_id = VRF_DEFAULT;
878
879 /* Sanity Check */
880 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
881 flog_warn(
882 EC_OSPF_LSA_INSTALL_FAILURE,
883 "RI (%s): wrong flooding scope AS instead of AREA ?",
884 __func__);
885 return rc;
886 }
887
888 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
889 ai = lookup_by_area((struct ospf_area *)arg);
890 if (ai == NULL) {
891 zlog_debug(
892 "RI (%s): There is no context for this Router Information. Stop processing",
893 __func__);
894 return rc;
895 }
896 if (ai->area->ospf) {
897 vrf_id = ai->area->ospf->vrf_id;
898 top = ai->area->ospf;
899 } else {
900 top = ospf_lookup_by_vrf_id(vrf_id);
901 }
902 new = ospf_router_info_lsa_new(ai->area);
903 new->vrf_id = vrf_id;
904
905 /* Check ospf info */
906 if (top == NULL) {
907 zlog_debug("RI (%s): ospf instance not found for vrf id %u",
908 __func__, vrf_id);
d62a17ae 909 ospf_lsa_unlock(&new);
ead99d5f 910 return rc;
d62a17ae 911 }
912
ddd73a96
OD
913 /* Install this LSA into LSDB. */
914 if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
915 flog_warn(
916 EC_OSPF_LSA_INSTALL_FAILURE,
917 "RI (%s): ospf_lsa_install() ?", __func__);
918 ospf_lsa_unlock(&new);
919 return rc;
920 }
d62a17ae 921
922 /* Update new LSA origination count. */
923 top->lsa_originate_count++;
924
ddd73a96
OD
925 /* Flood new LSA through AREA or AS. */
926 SET_FLAG(ai->flags, RIFLG_LSA_ENGAGED);
927 ospf_flood_through_area(ai->area, NULL /*nbr */, new);
d62a17ae 928
929 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
930 zlog_debug(
96b663a3
MS
931 "LSA[Type%d:%pI4]: Originate Opaque-LSA/ROUTER INFORMATION",
932 new->data->type, &new->data->id);
d62a17ae 933 ospf_lsa_header_dump(new->data);
934 }
935
936 rc = 0;
d62a17ae 937 return rc;
0ef4bcdc
OD
938}
939
d62a17ae 940static int ospf_router_info_lsa_originate(void *arg)
0ef4bcdc
OD
941{
942
ddd73a96 943 struct ospf_ri_area_info *ai;
d62a17ae 944 int rc = -1;
945
32ab5cf4 946 if (!OspfRI.enabled) {
ddd73a96
OD
947 zlog_info("RI (%s): ROUTER INFORMATION is disabled now.",
948 __func__);
d62a17ae 949 rc = 0; /* This is not an error case. */
ead99d5f 950 return rc;
d62a17ae 951 }
952
953 /* Check if Router Information LSA is already engaged */
ddd73a96
OD
954 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
955 if ((CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED))
956 && (CHECK_FLAG(OspfRI.as_flags,
957 RIFLG_LSA_FORCED_REFRESH))) {
958 UNSET_FLAG(OspfRI.as_flags, RIFLG_LSA_FORCED_REFRESH);
959 ospf_router_info_lsa_schedule(NULL, REFRESH_THIS_LSA);
960 rc = 0;
961 return rc;
d62a17ae 962 }
963 } else {
ddd73a96
OD
964 ai = lookup_by_area((struct ospf_area *)arg);
965 if (ai == NULL) {
239697e3 966 flog_warn(
cf444bcf 967 EC_OSPF_LSA,
ddd73a96 968 "RI (%s): Missing area information", __func__);
ead99d5f 969 return rc;
ddd73a96
OD
970 }
971 if ((CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED))
972 && (CHECK_FLAG(ai->flags, RIFLG_LSA_FORCED_REFRESH))) {
973 UNSET_FLAG(ai->flags, RIFLG_LSA_FORCED_REFRESH);
974 ospf_router_info_lsa_schedule(ai, REFRESH_THIS_LSA);
975 rc = 0;
976 return rc;
977 }
d62a17ae 978 }
979
ddd73a96 980 /* Router Information is not yet Engaged, check parameters */
83df36e8 981 if (!is_mandated_params_set(&OspfRI))
ddd73a96
OD
982 flog_warn(
983 EC_OSPF_LSA,
984 "RI (%s): lacks mandated ROUTER INFORMATION parameters",
985 __func__);
986
987 /* Ok, let's try to originate an LSA */
988 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
989 rc = ospf_router_info_lsa_originate_as(arg);
990 else
991 rc = ospf_router_info_lsa_originate_area(arg);
992
d62a17ae 993 return rc;
0ef4bcdc
OD
994}
995
d62a17ae 996static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa)
0ef4bcdc 997{
ddd73a96 998 struct ospf_ri_area_info *ai = NULL;
d62a17ae 999 struct ospf_lsa *new = NULL;
1000 struct ospf *top;
1001
32ab5cf4 1002 if (!OspfRI.enabled) {
d62a17ae 1003 /*
1004 * This LSA must have flushed before due to ROUTER INFORMATION
1005 * status change.
1006 * It seems a slip among routers in the routing domain.
1007 */
ddd73a96
OD
1008 zlog_info("RI (%s): ROUTER INFORMATION is disabled now.",
1009 __func__);
d62a17ae 1010 lsa->data->ls_age =
1011 htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
1012 }
1013
1014 /* Verify that the Router Information ID is supported */
1015 if (GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)) != 0) {
239697e3 1016 flog_warn(
cf444bcf 1017 EC_OSPF_LSA,
ddd73a96
OD
1018 "RI (%s): Unsupported Router Information ID",
1019 __func__);
ead99d5f 1020 return NULL;
d62a17ae 1021 }
1022
ddd73a96
OD
1023 /* Process LSA depending of the flooding scope */
1024 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
1025 /* Get context AREA context */
1026 ai = lookup_by_area(lsa->area);
1027 if (ai == NULL) {
1028 flog_warn(
1029 EC_OSPF_LSA,
1030 "RI (%s): No associated Area", __func__);
1031 return NULL;
1032 }
1033 /* Flush LSA, if the lsa's age reached to MaxAge. */
1034 if (IS_LSA_MAXAGE(lsa)) {
1035 UNSET_FLAG(ai->flags, RIFLG_LSA_ENGAGED);
1036 ospf_opaque_lsa_flush_schedule(lsa);
1037 return NULL;
1038 }
1039 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
1040 new = ospf_router_info_lsa_new(ai->area);
1041 new->data->ls_seqnum = lsa_seqnum_increment(lsa);
1042 new->vrf_id = lsa->vrf_id;
1043 /* Install this LSA into LSDB. */
1044 /* Given "lsa" will be freed in the next function. */
1045 top = ospf_lookup_by_vrf_id(lsa->vrf_id);
1046 if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
1047 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
1048 "RI (%s): ospf_lsa_install() ?", __func__);
1049 ospf_lsa_unlock(&new);
1050 return new;
1051 }
1052 /* Flood updated LSA through AREA */
1053 ospf_flood_through_area(ai->area, NULL /*nbr */, new);
1054
1055 } else { /* AS Flooding scope */
1056 /* Flush LSA, if the lsa's age reached to MaxAge. */
1057 if (IS_LSA_MAXAGE(lsa)) {
1058 UNSET_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED);
1059 ospf_opaque_lsa_flush_schedule(lsa);
1060 return NULL;
1061 }
1062 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
1063 new = ospf_router_info_lsa_new(NULL);
1064 new->data->ls_seqnum = lsa_seqnum_increment(lsa);
1065 new->vrf_id = lsa->vrf_id;
1066 /* Install this LSA into LSDB. */
1067 /* Given "lsa" will be freed in the next function. */
1068 top = ospf_lookup_by_vrf_id(lsa->vrf_id);
1069 if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
1070 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
1071 "RI (%s): ospf_lsa_install() ?", __func__);
1072 ospf_lsa_unlock(&new);
1073 return new;
1074 }
1075 /* Flood updated LSA through AS */
d62a17ae 1076 ospf_flood_through_as(top, NULL /*nbr */, new);
ddd73a96 1077 }
d62a17ae 1078
1079 /* Debug logging. */
1080 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
1081 zlog_debug(
96b663a3
MS
1082 "LSA[Type%d:%pI4]: Refresh Opaque-LSA/ROUTER INFORMATION",
1083 new->data->type, &new->data->id);
d62a17ae 1084 ospf_lsa_header_dump(new->data);
1085 }
1086
d62a17ae 1087 return new;
0ef4bcdc
OD
1088}
1089
ddd73a96
OD
1090static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info *ai,
1091 enum lsa_opcode opcode)
0ef4bcdc 1092{
d62a17ae 1093 struct ospf_lsa lsa;
1094 struct lsa_header lsah;
1095 struct ospf *top;
d7c0a89a 1096 uint32_t tmp;
d62a17ae 1097
1098 memset(&lsa, 0, sizeof(lsa));
1099 memset(&lsah, 0, sizeof(lsah));
1100
ddd73a96 1101 zlog_debug("RI (%s): LSA schedule %s%s%s", __func__,
d62a17ae 1102 opcode == REORIGINATE_THIS_LSA ? "Re-Originate" : "",
1103 opcode == REFRESH_THIS_LSA ? "Refresh" : "",
1104 opcode == FLUSH_THIS_LSA ? "Flush" : "");
1105
ddd73a96
OD
1106 /* Check LSA flags state coherence and collect area information */
1107 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
1108 if ((ai == NULL) || (ai->area == NULL)) {
1109 flog_warn(
1110 EC_OSPF_LSA,
1111 "RI (%s): Router Info is Area scope flooding but area is not set",
1112 __func__);
1113 return;
1114 }
ead99d5f 1115
ddd73a96
OD
1116 if (!CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED)
1117 && (opcode != REORIGINATE_THIS_LSA))
1118 return;
ead99d5f 1119
ddd73a96
OD
1120 if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED)
1121 && (opcode == REORIGINATE_THIS_LSA))
1122 opcode = REFRESH_THIS_LSA;
1123
1124 lsa.area = ai->area;
1125 top = ai->area->ospf;
1126 } else {
1127 if (!CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED)
1128 && (opcode != REORIGINATE_THIS_LSA))
1129 return;
1130
1131 if (CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED)
1132 && (opcode == REORIGINATE_THIS_LSA))
1133 opcode = REFRESH_THIS_LSA;
1134
1135 top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1136 lsa.area = NULL;
d62a17ae 1137 }
ddd73a96 1138
d62a17ae 1139 lsa.data = &lsah;
1140 lsah.type = OspfRI.scope;
1141
1142 /* LSA ID is set to 0 for the Router Information. See RFC 4970 */
1143 tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_ROUTER_INFORMATION_LSA, 0);
1144 lsah.id.s_addr = htonl(tmp);
1145
1146 switch (opcode) {
1147 case REORIGINATE_THIS_LSA:
1148 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA)
1149 ospf_opaque_lsa_reoriginate_schedule(
ddd73a96 1150 (void *)ai->area, OSPF_OPAQUE_AREA_LSA,
d62a17ae 1151 OPAQUE_TYPE_ROUTER_INFORMATION_LSA);
1152 else
1153 ospf_opaque_lsa_reoriginate_schedule(
1154 (void *)top, OSPF_OPAQUE_AS_LSA,
1155 OPAQUE_TYPE_ROUTER_INFORMATION_LSA);
1156 break;
1157 case REFRESH_THIS_LSA:
1158 ospf_opaque_lsa_refresh_schedule(&lsa);
1159 break;
1160 case FLUSH_THIS_LSA:
ddd73a96
OD
1161 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA)
1162 UNSET_FLAG(ai->flags, RIFLG_LSA_ENGAGED);
1163 else
1164 UNSET_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED);
d62a17ae 1165 ospf_opaque_lsa_flush_schedule(&lsa);
1166 break;
d62a17ae 1167 }
1168
1169 return;
0ef4bcdc
OD
1170}
1171
cf9b9f77
OD
1172/* Callback to handle Segment Routing information */
1173static int ospf_router_info_lsa_update(struct ospf_lsa *lsa)
1174{
1175
1176 /* Sanity Check */
1177 if (lsa == NULL) {
ddd73a96 1178 flog_warn(EC_OSPF_LSA, "RI (%s): Abort! LSA is NULL",
239697e3 1179 __func__);
cf9b9f77
OD
1180 return -1;
1181 }
1182
6aaf0fdd
OD
1183 /* Process only Opaque LSA */
1184 if ((lsa->data->type != OSPF_OPAQUE_AREA_LSA)
1185 && (lsa->data->type != OSPF_OPAQUE_AS_LSA))
cf9b9f77
OD
1186 return 0;
1187
1188 /* Process only Router Information LSA */
996c9314
LB
1189 if (GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr))
1190 != OPAQUE_TYPE_ROUTER_INFORMATION_LSA)
cf9b9f77
OD
1191 return 0;
1192
6aaf0fdd
OD
1193 /* Check if it is not my LSA */
1194 if (IS_LSA_SELF(lsa))
1195 return 0;
1196
cf9b9f77
OD
1197 /* Check if Router Info & Segment Routing are enable */
1198 if (!OspfRI.enabled || !OspfRI.sr_info.enabled)
1199 return 0;
1200
1201 /* Call Segment Routing LSA update or deletion */
1202 if (!IS_LSA_MAXAGE(lsa))
1203 ospf_sr_ri_lsa_update(lsa);
1204 else
1205 ospf_sr_ri_lsa_delete(lsa);
1206
1207 return 0;
1208}
1209
0ef4bcdc 1210/*------------------------------------------------------------------------*
78dfa0c7 1211 * Following are vty session control functions.
0ef4bcdc
OD
1212 *------------------------------------------------------------------------*/
1213
8db278b5
OD
1214#define check_tlv_size(size, msg) \
1215 do { \
1216 if (ntohs(tlvh->length) > size) { \
1217 if (vty != NULL) \
1218 vty_out(vty, " Wrong %s TLV size: %d(%d)\n", \
1219 msg, ntohs(tlvh->length), size); \
1220 else \
55370b95 1221 zlog_debug(" Wrong %s TLV size: %d(%d)", \
8db278b5
OD
1222 msg, ntohs(tlvh->length), size); \
1223 return size + TLV_HDR_SIZE; \
1224 } \
1225 } while (0)
1226
d7c0a89a 1227static uint16_t show_vty_router_cap(struct vty *vty, struct tlv_header *tlvh)
0ef4bcdc 1228{
d62a17ae 1229 struct ri_tlv_router_cap *top = (struct ri_tlv_router_cap *)tlvh;
0ef4bcdc 1230
8db278b5
OD
1231 check_tlv_size(RI_TLV_CAPABILITIES_SIZE, "Router Capabilities");
1232
d62a17ae 1233 if (vty != NULL)
1234 vty_out(vty, " Router Capabilities: 0x%x\n",
1235 ntohl(top->value));
1236 else
1237 zlog_debug(" Router Capabilities: 0x%x", ntohl(top->value));
0ef4bcdc 1238
ead99d5f 1239 return TLV_SIZE(tlvh);
0ef4bcdc
OD
1240}
1241
d7c0a89a
QY
1242static uint16_t show_vty_pce_subtlv_address(struct vty *vty,
1243 struct tlv_header *tlvh)
0ef4bcdc 1244{
d62a17ae 1245 struct ri_pce_subtlv_address *top =
1246 (struct ri_pce_subtlv_address *)tlvh;
1247
8db278b5
OD
1248 if (ntohs(top->address.type) == PCE_ADDRESS_IPV4) {
1249 check_tlv_size(PCE_ADDRESS_IPV4_SIZE, "PCE Address");
d62a17ae 1250 if (vty != NULL)
96b663a3
MS
1251 vty_out(vty, " PCE Address: %pI4\n",
1252 &top->address.value);
d62a17ae 1253 else
96b663a3
MS
1254 zlog_debug(" PCE Address: %pI4",
1255 &top->address.value);
8db278b5 1256 } else if (ntohs(top->address.type) == PCE_ADDRESS_IPV6) {
d62a17ae 1257 /* TODO: Add support to IPv6 with inet_ntop() */
8db278b5 1258 check_tlv_size(PCE_ADDRESS_IPV6_SIZE, "PCE Address");
d62a17ae 1259 if (vty != NULL)
1260 vty_out(vty, " PCE Address: 0x%x\n",
1261 ntohl(top->address.value.s_addr));
1262 else
1263 zlog_debug(" PCE Address: 0x%x",
1264 ntohl(top->address.value.s_addr));
8db278b5
OD
1265 } else {
1266 if (vty != NULL)
1267 vty_out(vty, " Wrong PCE Address type: 0x%x\n",
1268 ntohl(top->address.type));
1269 else
1270 zlog_debug(" Wrong PCE Address type: 0x%x",
1271 ntohl(top->address.type));
d62a17ae 1272 }
1273
ead99d5f 1274 return TLV_SIZE(tlvh);
0ef4bcdc
OD
1275}
1276
d7c0a89a
QY
1277static uint16_t show_vty_pce_subtlv_path_scope(struct vty *vty,
1278 struct tlv_header *tlvh)
0ef4bcdc 1279{
d62a17ae 1280 struct ri_pce_subtlv_path_scope *top =
1281 (struct ri_pce_subtlv_path_scope *)tlvh;
0ef4bcdc 1282
8db278b5
OD
1283 check_tlv_size(RI_PCE_SUBTLV_PATH_SCOPE_SIZE, "PCE Path Scope");
1284
d62a17ae 1285 if (vty != NULL)
1286 vty_out(vty, " PCE Path Scope: 0x%x\n", ntohl(top->value));
1287 else
1288 zlog_debug(" PCE Path Scope: 0x%x", ntohl(top->value));
0ef4bcdc 1289
ead99d5f 1290 return TLV_SIZE(tlvh);
0ef4bcdc
OD
1291}
1292
d7c0a89a
QY
1293static uint16_t show_vty_pce_subtlv_domain(struct vty *vty,
1294 struct tlv_header *tlvh)
0ef4bcdc 1295{
d62a17ae 1296 struct ri_pce_subtlv_domain *top = (struct ri_pce_subtlv_domain *)tlvh;
1297 struct in_addr tmp;
1298
8db278b5
OD
1299 check_tlv_size(RI_PCE_SUBTLV_DOMAIN_SIZE, "PCE Domain");
1300
d62a17ae 1301 if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) {
1302 tmp.s_addr = top->value;
1303 if (vty != NULL)
8db278b5 1304 vty_out(vty, " PCE Domain Area: %pI4\n", &tmp);
d62a17ae 1305 else
8db278b5
OD
1306 zlog_debug(" PCE Domain Area: %pI4", &tmp);
1307 } else if (ntohs(top->type) == PCE_DOMAIN_TYPE_AS) {
d62a17ae 1308 if (vty != NULL)
8db278b5 1309 vty_out(vty, " PCE Domain AS: %d\n",
d62a17ae 1310 ntohl(top->value));
1311 else
8db278b5
OD
1312 zlog_debug(" PCE Domain AS: %d", ntohl(top->value));
1313 } else {
1314 if (vty != NULL)
1315 vty_out(vty, " Wrong PCE Domain type: %d\n",
1316 ntohl(top->type));
1317 else
1318 zlog_debug(" Wrong PCE Domain type: %d",
1319 ntohl(top->type));
d62a17ae 1320 }
8db278b5 1321
ead99d5f 1322 return TLV_SIZE(tlvh);
0ef4bcdc
OD
1323}
1324
d7c0a89a
QY
1325static uint16_t show_vty_pce_subtlv_neighbor(struct vty *vty,
1326 struct tlv_header *tlvh)
0ef4bcdc
OD
1327{
1328
d62a17ae 1329 struct ri_pce_subtlv_neighbor *top =
1330 (struct ri_pce_subtlv_neighbor *)tlvh;
1331 struct in_addr tmp;
1332
8db278b5
OD
1333 check_tlv_size(RI_PCE_SUBTLV_NEIGHBOR_SIZE, "PCE Neighbor");
1334
d62a17ae 1335 if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) {
1336 tmp.s_addr = top->value;
1337 if (vty != NULL)
8db278b5 1338 vty_out(vty, " PCE Neighbor Area: %pI4\n", &tmp);
d62a17ae 1339 else
8db278b5
OD
1340 zlog_debug(" PCE Neighbor Area: %pI4", &tmp);
1341 } else if (ntohs(top->type) == PCE_DOMAIN_TYPE_AS) {
d62a17ae 1342 if (vty != NULL)
8db278b5 1343 vty_out(vty, " PCE Neighbor AS: %d\n",
d62a17ae 1344 ntohl(top->value));
1345 else
8db278b5 1346 zlog_debug(" PCE Neighbor AS: %d",
d62a17ae 1347 ntohl(top->value));
8db278b5
OD
1348 } else {
1349 if (vty != NULL)
1350 vty_out(vty, " Wrong PCE Neighbor type: %d\n",
1351 ntohl(top->type));
1352 else
1353 zlog_debug(" Wrong PCE Neighbor type: %d",
1354 ntohl(top->type));
d62a17ae 1355 }
8db278b5 1356
ead99d5f 1357 return TLV_SIZE(tlvh);
0ef4bcdc
OD
1358}
1359
d7c0a89a
QY
1360static uint16_t show_vty_pce_subtlv_cap_flag(struct vty *vty,
1361 struct tlv_header *tlvh)
0ef4bcdc 1362{
d62a17ae 1363 struct ri_pce_subtlv_cap_flag *top =
1364 (struct ri_pce_subtlv_cap_flag *)tlvh;
0ef4bcdc 1365
8db278b5
OD
1366 check_tlv_size(RI_PCE_SUBTLV_CAP_FLAG_SIZE, "PCE Capabilities");
1367
d62a17ae 1368 if (vty != NULL)
1369 vty_out(vty, " PCE Capabilities Flag: 0x%x\n",
1370 ntohl(top->value));
1371 else
1372 zlog_debug(" PCE Capabilities Flag: 0x%x",
1373 ntohl(top->value));
0ef4bcdc 1374
ead99d5f 1375 return TLV_SIZE(tlvh);
0ef4bcdc
OD
1376}
1377
8db278b5
OD
1378static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh,
1379 size_t buf_size)
0ef4bcdc 1380{
8db278b5
OD
1381 if (TLV_SIZE(tlvh) > buf_size) {
1382 if (vty != NULL)
1383 vty_out(vty,
1384 " TLV size %d exceeds buffer size. Abort!",
1385 TLV_SIZE(tlvh));
1386 else
1387 zlog_debug(
1388 " TLV size %d exceeds buffer size. Abort!",
1389 TLV_SIZE(tlvh));
1390 return buf_size;
1391 }
1392
d62a17ae 1393 if (vty != NULL)
1394 vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
1395 ntohs(tlvh->type), ntohs(tlvh->length));
1396 else
1397 zlog_debug(" Unknown TLV: [type(0x%x), length(0x%x)]",
1398 ntohs(tlvh->type), ntohs(tlvh->length));
1399
ead99d5f 1400 return TLV_SIZE(tlvh);
0ef4bcdc
OD
1401}
1402
d7c0a89a 1403static uint16_t show_vty_pce_info(struct vty *vty, struct tlv_header *ri,
8db278b5 1404 size_t buf_size)
0ef4bcdc 1405{
ead99d5f 1406 struct tlv_header *tlvh;
8db278b5 1407 uint16_t length = ntohs(ri->length);
d7c0a89a 1408 uint16_t sum = 0;
d62a17ae 1409
8db278b5
OD
1410 /* Verify that TLV length is valid against remaining buffer size */
1411 if (length > buf_size) {
1412 vty_out(vty,
1413 " PCE Info TLV size %d exceeds buffer size. Abort!\n",
1414 length);
1415 return buf_size;
1416 }
1417
1418 for (tlvh = ri; sum < length; tlvh = TLV_HDR_NEXT(tlvh)) {
d62a17ae 1419 switch (ntohs(tlvh->type)) {
1420 case RI_PCE_SUBTLV_ADDRESS:
1421 sum += show_vty_pce_subtlv_address(vty, tlvh);
1422 break;
1423 case RI_PCE_SUBTLV_PATH_SCOPE:
1424 sum += show_vty_pce_subtlv_path_scope(vty, tlvh);
1425 break;
1426 case RI_PCE_SUBTLV_DOMAIN:
1427 sum += show_vty_pce_subtlv_domain(vty, tlvh);
1428 break;
1429 case RI_PCE_SUBTLV_NEIGHBOR:
1430 sum += show_vty_pce_subtlv_neighbor(vty, tlvh);
1431 break;
1432 case RI_PCE_SUBTLV_CAP_FLAG:
1433 sum += show_vty_pce_subtlv_cap_flag(vty, tlvh);
1434 break;
1435 default:
8db278b5 1436 sum += show_vty_unknown_tlv(vty, tlvh, length - sum);
d62a17ae 1437 break;
1438 }
1439 }
1440 return sum;
0ef4bcdc
OD
1441}
1442
cf9b9f77 1443/* Display Segment Routing Algorithm TLV information */
93f0a26e 1444static uint16_t show_vty_sr_algorithm(struct vty *vty, struct tlv_header *tlvh)
cf9b9f77
OD
1445{
1446 struct ri_sr_tlv_sr_algorithm *algo =
1447 (struct ri_sr_tlv_sr_algorithm *)tlvh;
1448 int i;
7743f2f8 1449
8db278b5
OD
1450 check_tlv_size(ALGORITHM_COUNT, "Segment Routing Algorithm");
1451
cf9b9f77
OD
1452 if (vty != NULL) {
1453 vty_out(vty, " Segment Routing Algorithm TLV:\n");
1454 for (i = 0; i < ntohs(algo->header.length); i++) {
1455 switch (algo->value[i]) {
1456 case 0:
1457 vty_out(vty, " Algorithm %d: SPF\n", i);
1458 break;
1459 case 1:
1460 vty_out(vty, " Algorithm %d: Strict SPF\n",
1461 i);
1462 break;
1463 default:
1464 vty_out(vty,
1465 " Algorithm %d: Unknown value %d\n", i,
1466 algo->value[i]);
1467 break;
1468 }
1469 }
8db278b5 1470 } else {
9165c5f5 1471 zlog_debug(" Segment Routing Algorithm TLV:");
cf9b9f77
OD
1472 for (i = 0; i < ntohs(algo->header.length); i++)
1473 switch (algo->value[i]) {
1474 case 0:
9165c5f5 1475 zlog_debug(" Algorithm %d: SPF", i);
cf9b9f77
OD
1476 break;
1477 case 1:
9165c5f5 1478 zlog_debug(" Algorithm %d: Strict SPF", i);
cf9b9f77
OD
1479 break;
1480 default:
63efca0e
DL
1481 zlog_debug(" Algorithm %d: Unknown value %d",
1482 i, algo->value[i]);
cf9b9f77
OD
1483 break;
1484 }
1485 }
1486
1487 return TLV_SIZE(tlvh);
1488}
1489
1490/* Display Segment Routing SID/Label Range TLV information */
93f0a26e 1491static uint16_t show_vty_sr_range(struct vty *vty, struct tlv_header *tlvh)
cf9b9f77
OD
1492{
1493 struct ri_sr_tlv_sid_label_range *range =
1494 (struct ri_sr_tlv_sid_label_range *)tlvh;
1495
8db278b5
OD
1496 check_tlv_size(RI_SR_TLV_LABEL_RANGE_SIZE, "SR Label Range");
1497
cf9b9f77
OD
1498 if (vty != NULL) {
1499 vty_out(vty,
6f751f14 1500 " Segment Routing %s Range TLV:\n"
cf9b9f77
OD
1501 " Range Size = %d\n"
1502 " SID Label = %d\n\n",
6f751f14
OD
1503 ntohs(range->header.type) == RI_SR_TLV_SRGB_LABEL_RANGE
1504 ? "Global"
1505 : "Local",
cf9b9f77
OD
1506 GET_RANGE_SIZE(ntohl(range->size)),
1507 GET_LABEL(ntohl(range->lower.value)));
1508 } else {
1509 zlog_debug(
1d5453d6 1510 " Segment Routing %s Range TLV: Range Size = %d SID Label = %d",
6f751f14
OD
1511 ntohs(range->header.type) == RI_SR_TLV_SRGB_LABEL_RANGE
1512 ? "Global"
1513 : "Local",
cf9b9f77
OD
1514 GET_RANGE_SIZE(ntohl(range->size)),
1515 GET_LABEL(ntohl(range->lower.value)));
1516 }
1517
1518 return TLV_SIZE(tlvh);
1519}
1520
1521/* Display Segment Routing Maximum Stack Depth TLV information */
93f0a26e 1522static uint16_t show_vty_sr_msd(struct vty *vty, struct tlv_header *tlvh)
cf9b9f77
OD
1523{
1524 struct ri_sr_tlv_node_msd *msd = (struct ri_sr_tlv_node_msd *)tlvh;
1525
8db278b5
OD
1526 check_tlv_size(RI_SR_TLV_NODE_MSD_SIZE, "Node Maximum Stack Depth");
1527
cf9b9f77
OD
1528 if (vty != NULL) {
1529 vty_out(vty,
1530 " Segment Routing MSD TLV:\n"
1531 " Node Maximum Stack Depth = %d\n",
1532 msd->value);
1533 } else {
1534 zlog_debug(
1d5453d6 1535 " Segment Routing MSD TLV: Node Maximum Stack Depth = %d",
cf9b9f77
OD
1536 msd->value);
1537 }
1538
1539 return TLV_SIZE(tlvh);
1540}
1541
3e63092b
RW
1542static void ospf_router_info_show_info(struct vty *vty,
1543 struct json_object *json,
1544 struct ospf_lsa *lsa)
0ef4bcdc 1545{
c4efd0f4 1546 struct lsa_header *lsah = lsa->data;
ead99d5f 1547 struct tlv_header *tlvh;
d7c0a89a 1548 uint16_t length = 0, sum = 0;
d62a17ae 1549
3e63092b
RW
1550 if (json)
1551 return;
1552
d62a17ae 1553 /* Initialize TLV browsing */
8db278b5 1554 length = lsa->size - OSPF_LSA_HEADER_SIZE;
d62a17ae 1555
8db278b5 1556 for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh;
ead99d5f 1557 tlvh = TLV_HDR_NEXT(tlvh)) {
d62a17ae 1558 switch (ntohs(tlvh->type)) {
1559 case RI_TLV_CAPABILITIES:
1560 sum += show_vty_router_cap(vty, tlvh);
1561 break;
1562 case RI_TLV_PCE:
1563 tlvh++;
ead99d5f 1564 sum += TLV_HDR_SIZE;
d62a17ae 1565 sum += show_vty_pce_info(vty, tlvh, length - sum);
1566 break;
cf9b9f77
OD
1567 case RI_SR_TLV_SR_ALGORITHM:
1568 sum += show_vty_sr_algorithm(vty, tlvh);
1569 break;
6f751f14
OD
1570 case RI_SR_TLV_SRGB_LABEL_RANGE:
1571 case RI_SR_TLV_SRLB_LABEL_RANGE:
cf9b9f77
OD
1572 sum += show_vty_sr_range(vty, tlvh);
1573 break;
1574 case RI_SR_TLV_NODE_MSD:
1575 sum += show_vty_sr_msd(vty, tlvh);
1576 break;
1577
d62a17ae 1578 default:
8db278b5 1579 sum += show_vty_unknown_tlv(vty, tlvh, length);
d62a17ae 1580 break;
1581 }
1582 }
1583
1584 return;
0ef4bcdc
OD
1585}
1586
d62a17ae 1587static void ospf_router_info_config_write_router(struct vty *vty)
0ef4bcdc 1588{
d62a17ae 1589 struct ospf_pce_info *pce = &OspfRI.pce_info;
1590 struct listnode *node;
1591 struct ri_pce_subtlv_domain *domain;
1592 struct ri_pce_subtlv_neighbor *neighbor;
1593 struct in_addr tmp;
1594
cf9b9f77
OD
1595 if (!OspfRI.enabled)
1596 return;
1597
1598 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
1599 vty_out(vty, " router-info as\n");
1600 else
ddd73a96 1601 vty_out(vty, " router-info area\n");
cf9b9f77
OD
1602
1603 if (OspfRI.pce_info.enabled) {
1604
1605 if (pce->pce_address.header.type != 0)
96b663a3
MS
1606 vty_out(vty, " pce address %pI4\n",
1607 &pce->pce_address.address.value);
cf9b9f77
OD
1608
1609 if (pce->pce_cap_flag.header.type != 0)
1610 vty_out(vty, " pce flag 0x%x\n",
1611 ntohl(pce->pce_cap_flag.value));
1612
1613 for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
1614 if (domain->header.type != 0) {
1615 if (domain->type == PCE_DOMAIN_TYPE_AREA) {
1616 tmp.s_addr = domain->value;
96b663a3
MS
1617 vty_out(vty, " pce domain area %pI4\n",
1618 &tmp);
cf9b9f77
OD
1619 } else {
1620 vty_out(vty, " pce domain as %d\n",
1621 ntohl(domain->value));
d62a17ae 1622 }
1623 }
cf9b9f77 1624 }
d62a17ae 1625
cf9b9f77
OD
1626 for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
1627 if (neighbor->header.type != 0) {
1628 if (neighbor->type == PCE_DOMAIN_TYPE_AREA) {
1629 tmp.s_addr = neighbor->value;
96b663a3
MS
1630 vty_out(vty,
1631 " pce neighbor area %pI4\n",
1632 &tmp);
cf9b9f77
OD
1633 } else {
1634 vty_out(vty, " pce neighbor as %d\n",
1635 ntohl(neighbor->value));
d62a17ae 1636 }
1637 }
ead99d5f 1638 }
cf9b9f77
OD
1639
1640 if (pce->pce_scope.header.type != 0)
1641 vty_out(vty, " pce scope 0x%x\n",
1642 ntohl(OspfRI.pce_info.pce_scope.value));
d62a17ae 1643 }
1644 return;
0ef4bcdc
OD
1645}
1646
1647/*------------------------------------------------------------------------*
78dfa0c7 1648 * Following are vty command functions.
0ef4bcdc 1649 *------------------------------------------------------------------------*/
ddd73a96
OD
1650/* Simple wrapper schedule RI LSA action in function of the scope */
1651static void ospf_router_info_schedule(enum lsa_opcode opcode)
1652{
1653 struct listnode *node, *nnode;
1654 struct ospf_ri_area_info *ai;
1655
1656 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
1657 if (CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED))
1658 ospf_router_info_lsa_schedule(NULL, opcode);
1659 else if (opcode == REORIGINATE_THIS_LSA)
1660 ospf_router_info_lsa_schedule(NULL, opcode);
1661 } else {
1662 for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai)) {
1663 if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED))
1664 ospf_router_info_lsa_schedule(ai, opcode);
1665 }
1666 }
1667}
0ef4bcdc
OD
1668
1669DEFUN (router_info,
1670 router_info_area_cmd,
ddd73a96 1671 "router-info <as|area [A.B.C.D]>",
0ef4bcdc 1672 OSPF_RI_STR
692b4c65 1673 "Enable the Router Information functionality with AS flooding scope\n"
0ef4bcdc 1674 "Enable the Router Information functionality with Area flooding scope\n"
ddd73a96 1675 "OSPF area ID in IP format (deprecated)\n")
0ef4bcdc 1676{
ddd73a96 1677 int idx_mode = 1;
d7c0a89a 1678 uint8_t scope;
d62a17ae 1679
32ab5cf4 1680 if (OspfRI.enabled)
d62a17ae 1681 return CMD_SUCCESS;
1682
1683 /* Check and get Area value if present */
ddd73a96 1684 if (strncmp(argv[idx_mode]->arg, "as", 2) == 0)
d62a17ae 1685 scope = OSPF_OPAQUE_AS_LSA;
ddd73a96
OD
1686 else
1687 scope = OSPF_OPAQUE_AREA_LSA;
d62a17ae 1688
1689 /* First start to register Router Information callbacks */
ddd73a96 1690 if (!OspfRI.registered && (ospf_router_info_register(scope)) != 0) {
239697e3
DS
1691 vty_out(vty,
1692 "%% Unable to register Router Information callbacks.");
1693 flog_err(
cf444bcf 1694 EC_OSPF_INIT_FAIL,
ddd73a96
OD
1695 "RI (%s): Unable to register Router Information callbacks. Abort!",
1696 __func__);
d62a17ae 1697 return CMD_WARNING_CONFIG_FAILED;
1698 }
1699
32ab5cf4 1700 OspfRI.enabled = true;
d62a17ae 1701
1702 if (IS_DEBUG_OSPF_EVENT)
1703 zlog_debug("RI-> Router Information (%s flooding): OFF -> ON",
1704 OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area"
1705 : "AS");
1706
1707 /*
1708 * Following code is intended to handle two cases;
1709 *
1710 * 1) Router Information was disabled at startup time, but now become
1711 * enabled.
1712 * 2) Router Information was once enabled then disabled, and now enabled
1713 * again.
1714 */
1715
1716 initialize_params(&OspfRI);
1717
ddd73a96
OD
1718 /* Originate or Refresh RI LSA if already engaged */
1719 ospf_router_info_schedule(REORIGINATE_THIS_LSA);
d62a17ae 1720 return CMD_SUCCESS;
0ef4bcdc
OD
1721}
1722
0ef4bcdc
OD
1723
1724DEFUN (no_router_info,
1725 no_router_info_cmd,
1726 "no router-info",
1727 NO_STR
1728 "Disable the Router Information functionality\n")
1729{
1730
32ab5cf4 1731 if (!OspfRI.enabled)
d62a17ae 1732 return CMD_SUCCESS;
0ef4bcdc 1733
d62a17ae 1734 if (IS_DEBUG_OSPF_EVENT)
1735 zlog_debug("RI-> Router Information: ON -> OFF");
0ef4bcdc 1736
ddd73a96 1737 ospf_router_info_schedule(FLUSH_THIS_LSA);
0ef4bcdc 1738
32ab5cf4 1739 OspfRI.enabled = false;
0ef4bcdc 1740
d62a17ae 1741 return CMD_SUCCESS;
0ef4bcdc
OD
1742}
1743
d62a17ae 1744static int ospf_ri_enabled(struct vty *vty)
284a4a0c 1745{
32ab5cf4 1746 if (OspfRI.enabled)
d62a17ae 1747 return 1;
284a4a0c 1748
d62a17ae 1749 if (vty)
1750 vty_out(vty, "%% OSPF RI is not turned on\n");
284a4a0c 1751
d62a17ae 1752 return 0;
284a4a0c
DS
1753}
1754
0ef4bcdc
OD
1755DEFUN (pce_address,
1756 pce_address_cmd,
1757 "pce address A.B.C.D",
1758 PCE_STR
1759 "Stable IP address of the PCE\n"
1760 "PCE address in IPv4 address format\n")
1761{
d62a17ae 1762 int idx_ipv4 = 2;
1763 struct in_addr value;
1764 struct ospf_pce_info *pi = &OspfRI.pce_info;
0ef4bcdc 1765
d62a17ae 1766 if (!ospf_ri_enabled(vty))
1767 return CMD_WARNING_CONFIG_FAILED;
284a4a0c 1768
d62a17ae 1769 if (!inet_aton(argv[idx_ipv4]->arg, &value)) {
1770 vty_out(vty, "Please specify PCE Address by A.B.C.D\n");
1771 return CMD_WARNING_CONFIG_FAILED;
1772 }
0ef4bcdc 1773
d62a17ae 1774 if (ntohs(pi->pce_address.header.type) == 0
1775 || ntohl(pi->pce_address.address.value.s_addr)
1776 != ntohl(value.s_addr)) {
0ef4bcdc 1777
d62a17ae 1778 set_pce_address(value, pi);
0ef4bcdc 1779
d62a17ae 1780 /* Refresh RI LSA if already engaged */
ddd73a96 1781 ospf_router_info_schedule(REFRESH_THIS_LSA);
d62a17ae 1782 }
0ef4bcdc 1783
d62a17ae 1784 return CMD_SUCCESS;
0ef4bcdc
OD
1785}
1786
1787DEFUN (no_pce_address,
1788 no_pce_address_cmd,
2328428d 1789 "no pce address [A.B.C.D]",
0ef4bcdc
OD
1790 NO_STR
1791 PCE_STR
59768a63
DS
1792 "Disable PCE address\n"
1793 "PCE address in IPv4 address format\n")
0ef4bcdc
OD
1794{
1795
9ffaacb0 1796 unset_param(&OspfRI.pce_info.pce_address);
0ef4bcdc 1797
d62a17ae 1798 /* Refresh RI LSA if already engaged */
ddd73a96 1799 ospf_router_info_schedule(REFRESH_THIS_LSA);
0ef4bcdc 1800
d62a17ae 1801 return CMD_SUCCESS;
0ef4bcdc
OD
1802}
1803
1804DEFUN (pce_path_scope,
1805 pce_path_scope_cmd,
1806 "pce scope BITPATTERN",
1807 PCE_STR
1808 "Path scope visibilities of the PCE for path computation\n"
1809 "32-bit Hexadecimal value\n")
1810{
d62a17ae 1811 int idx_bitpattern = 2;
1812 uint32_t scope;
1813 struct ospf_pce_info *pi = &OspfRI.pce_info;
0ef4bcdc 1814
d62a17ae 1815 if (!ospf_ri_enabled(vty))
1816 return CMD_WARNING_CONFIG_FAILED;
284a4a0c 1817
d62a17ae 1818 if (sscanf(argv[idx_bitpattern]->arg, "0x%x", &scope) != 1) {
1819 vty_out(vty, "pce_path_scope: fscanf: %s\n",
1820 safe_strerror(errno));
1821 return CMD_WARNING_CONFIG_FAILED;
1822 }
0ef4bcdc 1823
d62a17ae 1824 if (ntohl(pi->pce_scope.header.type) == 0
1825 || scope != pi->pce_scope.value) {
1826 set_pce_path_scope(scope, pi);
0ef4bcdc 1827
d62a17ae 1828 /* Refresh RI LSA if already engaged */
ddd73a96 1829 ospf_router_info_schedule(REFRESH_THIS_LSA);
d62a17ae 1830 }
0ef4bcdc 1831
d62a17ae 1832 return CMD_SUCCESS;
0ef4bcdc
OD
1833}
1834
1835DEFUN (no_pce_path_scope,
1836 no_pce_path_scope_cmd,
2328428d 1837 "no pce scope [BITPATTERN]",
0ef4bcdc
OD
1838 NO_STR
1839 PCE_STR
59768a63
DS
1840 "Disable PCE path scope\n"
1841 "32-bit Hexadecimal value\n")
0ef4bcdc
OD
1842{
1843
9ffaacb0 1844 unset_param(&OspfRI.pce_info.pce_address);
0ef4bcdc 1845
d62a17ae 1846 /* Refresh RI LSA if already engaged */
ddd73a96 1847 ospf_router_info_schedule(REFRESH_THIS_LSA);
0ef4bcdc 1848
d62a17ae 1849 return CMD_SUCCESS;
0ef4bcdc
OD
1850}
1851
1852DEFUN (pce_domain,
1853 pce_domain_cmd,
6147e2c6 1854 "pce domain as (0-65535)",
0ef4bcdc
OD
1855 PCE_STR
1856 "Configure PCE domain AS number\n"
1857 "AS number where the PCE as visibilities for path computation\n"
1858 "AS number in decimal <0-65535>\n")
1859{
d62a17ae 1860 int idx_number = 3;
0ef4bcdc 1861
d62a17ae 1862 uint32_t as;
1863 struct ospf_pce_info *pce = &OspfRI.pce_info;
1864 struct listnode *node;
1865 struct ri_pce_subtlv_domain *domain;
0ef4bcdc 1866
d62a17ae 1867 if (!ospf_ri_enabled(vty))
1868 return CMD_WARNING_CONFIG_FAILED;
284a4a0c 1869
0651460e 1870 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
d62a17ae 1871 vty_out(vty, "pce_domain: fscanf: %s\n", safe_strerror(errno));
1872 return CMD_WARNING_CONFIG_FAILED;
1873 }
0ef4bcdc 1874
d62a17ae 1875 /* Check if the domain is not already in the domain list */
1876 for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
1877 if (ntohl(domain->header.type) == 0 && as == domain->value)
1878 return CMD_SUCCESS;
1879 }
0ef4bcdc 1880
d62a17ae 1881 /* Create new domain if not found */
1882 set_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce);
0ef4bcdc 1883
d62a17ae 1884 /* Refresh RI LSA if already engaged */
ddd73a96 1885 ospf_router_info_schedule(REFRESH_THIS_LSA);
0ef4bcdc 1886
d62a17ae 1887 return CMD_SUCCESS;
0ef4bcdc
OD
1888}
1889
1890DEFUN (no_pce_domain,
1891 no_pce_domain_cmd,
6147e2c6 1892 "no pce domain as (0-65535)",
0ef4bcdc
OD
1893 NO_STR
1894 PCE_STR
1895 "Disable PCE domain AS number\n"
1896 "AS number where the PCE as visibilities for path computation\n"
1897 "AS number in decimal <0-65535>\n")
1898{
d62a17ae 1899 int idx_number = 4;
0ef4bcdc 1900
d62a17ae 1901 uint32_t as;
1902 struct ospf_pce_info *pce = &OspfRI.pce_info;
0ef4bcdc 1903
0651460e 1904 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
d62a17ae 1905 vty_out(vty, "no_pce_domain: fscanf: %s\n",
1906 safe_strerror(errno));
1907 return CMD_WARNING_CONFIG_FAILED;
1908 }
0ef4bcdc 1909
d62a17ae 1910 /* Unset corresponding PCE domain */
1911 unset_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce);
0ef4bcdc 1912
d62a17ae 1913 /* Refresh RI LSA if already engaged */
ddd73a96 1914 ospf_router_info_schedule(REFRESH_THIS_LSA);
0ef4bcdc 1915
d62a17ae 1916 return CMD_SUCCESS;
0ef4bcdc
OD
1917}
1918
1919DEFUN (pce_neigbhor,
1920 pce_neighbor_cmd,
6147e2c6 1921 "pce neighbor as (0-65535)",
0ef4bcdc
OD
1922 PCE_STR
1923 "Configure PCE neighbor domain AS number\n"
1924 "AS number of PCE neighbors\n"
1925 "AS number in decimal <0-65535>\n")
1926{
d62a17ae 1927 int idx_number = 3;
0ef4bcdc 1928
d62a17ae 1929 uint32_t as;
1930 struct ospf_pce_info *pce = &OspfRI.pce_info;
1931 struct listnode *node;
1932 struct ri_pce_subtlv_neighbor *neighbor;
0ef4bcdc 1933
d62a17ae 1934 if (!ospf_ri_enabled(vty))
1935 return CMD_WARNING_CONFIG_FAILED;
284a4a0c 1936
0651460e 1937 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
d62a17ae 1938 vty_out(vty, "pce_neighbor: fscanf: %s\n",
1939 safe_strerror(errno));
1940 return CMD_WARNING_CONFIG_FAILED;
1941 }
0ef4bcdc 1942
d62a17ae 1943 /* Check if the domain is not already in the domain list */
1944 for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
1945 if (ntohl(neighbor->header.type) == 0 && as == neighbor->value)
1946 return CMD_SUCCESS;
1947 }
0ef4bcdc 1948
d62a17ae 1949 /* Create new domain if not found */
1950 set_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce);
0ef4bcdc 1951
d62a17ae 1952 /* Refresh RI LSA if already engaged */
ddd73a96 1953 ospf_router_info_schedule(REFRESH_THIS_LSA);
0ef4bcdc 1954
d62a17ae 1955 return CMD_SUCCESS;
0ef4bcdc
OD
1956}
1957
1958DEFUN (no_pce_neighbor,
1959 no_pce_neighbor_cmd,
6147e2c6 1960 "no pce neighbor as (0-65535)",
0ef4bcdc
OD
1961 NO_STR
1962 PCE_STR
1963 "Disable PCE neighbor AS number\n"
1964 "AS number of PCE neighbor\n"
1965 "AS number in decimal <0-65535>\n")
1966{
d62a17ae 1967 int idx_number = 4;
0ef4bcdc 1968
d62a17ae 1969 uint32_t as;
1970 struct ospf_pce_info *pce = &OspfRI.pce_info;
0ef4bcdc 1971
0651460e 1972 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
d62a17ae 1973 vty_out(vty, "no_pce_neighbor: fscanf: %s\n",
1974 safe_strerror(errno));
1975 return CMD_WARNING_CONFIG_FAILED;
1976 }
0ef4bcdc 1977
d62a17ae 1978 /* Unset corresponding PCE domain */
1979 unset_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce);
0ef4bcdc 1980
d62a17ae 1981 /* Refresh RI LSA if already engaged */
ddd73a96 1982 ospf_router_info_schedule(REFRESH_THIS_LSA);
0ef4bcdc 1983
d62a17ae 1984 return CMD_SUCCESS;
0ef4bcdc
OD
1985}
1986
1987DEFUN (pce_cap_flag,
1988 pce_cap_flag_cmd,
1989 "pce flag BITPATTERN",
1990 PCE_STR
1991 "Capabilities of the PCE for path computation\n"
1992 "32-bit Hexadecimal value\n")
1993{
d62a17ae 1994 int idx_bitpattern = 2;
0ef4bcdc 1995
d62a17ae 1996 uint32_t cap;
1997 struct ospf_pce_info *pce = &OspfRI.pce_info;
0ef4bcdc 1998
d62a17ae 1999 if (!ospf_ri_enabled(vty))
2000 return CMD_WARNING_CONFIG_FAILED;
284a4a0c 2001
d62a17ae 2002 if (sscanf(argv[idx_bitpattern]->arg, "0x%x", &cap) != 1) {
2003 vty_out(vty, "pce_cap_flag: fscanf: %s\n",
2004 safe_strerror(errno));
2005 return CMD_WARNING_CONFIG_FAILED;
2006 }
0ef4bcdc 2007
d62a17ae 2008 if (ntohl(pce->pce_cap_flag.header.type) == 0
2009 || cap != pce->pce_cap_flag.value) {
2010 set_pce_cap_flag(cap, pce);
0ef4bcdc 2011
d62a17ae 2012 /* Refresh RI LSA if already engaged */
ddd73a96 2013 ospf_router_info_schedule(REFRESH_THIS_LSA);
d62a17ae 2014 }
0ef4bcdc 2015
d62a17ae 2016 return CMD_SUCCESS;
0ef4bcdc
OD
2017}
2018
2019DEFUN (no_pce_cap_flag,
2020 no_pce_cap_flag_cmd,
2021 "no pce flag",
2022 NO_STR
2023 PCE_STR
2024 "Disable PCE capabilities\n")
2025{
2026
9ffaacb0 2027 unset_param(&OspfRI.pce_info.pce_cap_flag);
0ef4bcdc 2028
d62a17ae 2029 /* Refresh RI LSA if already engaged */
ddd73a96 2030 ospf_router_info_schedule(REFRESH_THIS_LSA);
0ef4bcdc 2031
d62a17ae 2032 return CMD_SUCCESS;
0ef4bcdc
OD
2033}
2034
2035DEFUN (show_ip_ospf_router_info,
2036 show_ip_ospf_router_info_cmd,
2037 "show ip ospf router-info",
2038 SHOW_STR
2039 IP_STR
2040 OSPF_STR
2041 "Router Information\n")
2042{
2043
32ab5cf4 2044 if (OspfRI.enabled) {
d62a17ae 2045 vty_out(vty, "--- Router Information parameters ---\n");
2046 show_vty_router_cap(vty, &OspfRI.router_cap.header);
2047 } else {
2048 if (vty != NULL)
2049 vty_out(vty,
2050 " Router Information is disabled on this router\n");
2051 }
2052 return CMD_SUCCESS;
0ef4bcdc
OD
2053}
2054
2055DEFUN (show_ip_opsf_router_info_pce,
2056 show_ip_ospf_router_info_pce_cmd,
2057 "show ip ospf router-info pce",
2058 SHOW_STR
2059 IP_STR
2060 OSPF_STR
2061 "Router Information\n"
2062 "PCE information\n")
2063{
2064
d62a17ae 2065 struct ospf_pce_info *pce = &OspfRI.pce_info;
2066 struct listnode *node;
2067 struct ri_pce_subtlv_domain *domain;
2068 struct ri_pce_subtlv_neighbor *neighbor;
0ef4bcdc 2069
cf9b9f77 2070 if ((OspfRI.enabled) && (OspfRI.pce_info.enabled)) {
d62a17ae 2071 vty_out(vty, "--- PCE parameters ---\n");
0ef4bcdc 2072
d62a17ae 2073 if (pce->pce_address.header.type != 0)
2074 show_vty_pce_subtlv_address(vty,
2075 &pce->pce_address.header);
0ef4bcdc 2076
d62a17ae 2077 if (pce->pce_scope.header.type != 0)
2078 show_vty_pce_subtlv_path_scope(vty,
2079 &pce->pce_scope.header);
0ef4bcdc 2080
d62a17ae 2081 for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
2082 if (domain->header.type != 0)
2083 show_vty_pce_subtlv_domain(vty,
2084 &domain->header);
2085 }
0ef4bcdc 2086
d62a17ae 2087 for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
2088 if (neighbor->header.type != 0)
2089 show_vty_pce_subtlv_neighbor(vty,
2090 &neighbor->header);
2091 }
0ef4bcdc 2092
d62a17ae 2093 if (pce->pce_cap_flag.header.type != 0)
2094 show_vty_pce_subtlv_cap_flag(vty,
2095 &pce->pce_cap_flag.header);
0ef4bcdc 2096
d62a17ae 2097 } else {
996c9314 2098 vty_out(vty, " PCE info is disabled on this router\n");
d62a17ae 2099 }
0ef4bcdc 2100
d62a17ae 2101 return CMD_SUCCESS;
0ef4bcdc
OD
2102}
2103
2104/* Install new CLI commands */
d62a17ae 2105static void ospf_router_info_register_vty(void)
0ef4bcdc 2106{
d62a17ae 2107 install_element(VIEW_NODE, &show_ip_ospf_router_info_cmd);
2108 install_element(VIEW_NODE, &show_ip_ospf_router_info_pce_cmd);
2109
2110 install_element(OSPF_NODE, &router_info_area_cmd);
2111 install_element(OSPF_NODE, &no_router_info_cmd);
2112 install_element(OSPF_NODE, &pce_address_cmd);
2113 install_element(OSPF_NODE, &no_pce_address_cmd);
2114 install_element(OSPF_NODE, &pce_path_scope_cmd);
2115 install_element(OSPF_NODE, &no_pce_path_scope_cmd);
2116 install_element(OSPF_NODE, &pce_domain_cmd);
2117 install_element(OSPF_NODE, &no_pce_domain_cmd);
2118 install_element(OSPF_NODE, &pce_neighbor_cmd);
2119 install_element(OSPF_NODE, &no_pce_neighbor_cmd);
2120 install_element(OSPF_NODE, &pce_cap_flag_cmd);
2121 install_element(OSPF_NODE, &no_pce_cap_flag_cmd);
2122
2123 return;
0ef4bcdc 2124}