]> git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_ri.c
Merge pull request #13649 from donaldsharp/unlock_the_node_or_else
[mirror_frr.git] / ospfd / ospf_ri.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * This is an implementation of RFC4970 Router Information
4 * with support of RFC5088 PCE Capabilites announcement
5 *
6 * Module name: Router Information
7 * Author: Olivier Dugeon <olivier.dugeon@orange.com>
8 * Copyright (C) 2012 - 2017 Orange Labs http://www.orange.com/
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 "frrevent.h"
24 #include "hash.h"
25 #include "sockunion.h" /* for inet_aton() */
26 #include "mpls.h"
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"
43 #include "ospfd/ospf_sr.h"
44 #include "ospfd/ospf_ri.h"
45 #include "ospfd/ospf_errors.h"
46
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 */
51 static struct ospf_router_info OspfRI;
52
53 /*------------------------------------------------------------------------------*
54 * Following are initialize/terminate functions for Router Information
55 *handling.
56 *------------------------------------------------------------------------------*/
57
58 static void ospf_router_info_ism_change(struct ospf_interface *oi,
59 int old_status);
60 static void ospf_router_info_config_write_router(struct vty *vty);
61 static void ospf_router_info_show_info(struct vty *vty,
62 struct json_object *json,
63 struct ospf_lsa *lsa);
64 static int ospf_router_info_lsa_originate(void *arg);
65 static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa);
66 static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info *ai,
67 enum lsa_opcode opcode);
68 static void ospf_router_info_register_vty(void);
69 static int ospf_router_info_lsa_update(struct ospf_lsa *lsa);
70 static void del_area_info(void *val);
71 static void del_pce_info(void *val);
72
73 int ospf_router_info_init(void)
74 {
75
76 zlog_info("RI (%s): Initialize Router Information", __func__);
77
78 memset(&OspfRI, 0, sizeof(OspfRI));
79 OspfRI.enabled = false;
80 OspfRI.registered = 0;
81 OspfRI.scope = OSPF_OPAQUE_AS_LSA;
82 OspfRI.as_flags = RIFLG_LSA_INACTIVE;
83 OspfRI.area_info = list_new();
84 OspfRI.area_info->del = del_area_info;
85
86 /* Initialize pce domain and neighbor list */
87 OspfRI.pce_info.enabled = false;
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;
92
93 /* Initialize Segment Routing information structure */
94 OspfRI.sr_info.enabled = false;
95
96 ospf_router_info_register_vty();
97
98 return 0;
99 }
100
101 static int ospf_router_info_register(uint8_t scope)
102 {
103 int rc = 0;
104
105 if (OspfRI.registered)
106 return rc;
107
108 zlog_info("RI (%s): Register Router Information with scope %s(%d)",
109 __func__,
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 */
115 ospf_router_info_ism_change,
116 NULL, /* NSM change */
117 ospf_router_info_config_write_router,
118 NULL, /* Config. write interface */
119 NULL, /* Config. write debug */
120 ospf_router_info_show_info, ospf_router_info_lsa_originate,
121 ospf_router_info_lsa_refresh, ospf_router_info_lsa_update,
122 NULL); /* del_lsa_hook */
123
124 if (rc != 0) {
125 flog_warn(
126 EC_OSPF_OPAQUE_REGISTRATION,
127 "RI (%s): Failed to register functions", __func__);
128 return rc;
129 }
130
131 OspfRI.registered = 1;
132 OspfRI.scope = scope;
133 return rc;
134 }
135
136 static int ospf_router_info_unregister(void)
137 {
138
139 if ((OspfRI.scope != OSPF_OPAQUE_AS_LSA)
140 && (OspfRI.scope != OSPF_OPAQUE_AREA_LSA)) {
141 assert("Unable to unregister Router Info functions: Wrong scope!"
142 == NULL);
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
153 void ospf_router_info_term(void)
154 {
155
156 list_delete(&OspfRI.pce_info.pce_domain);
157 list_delete(&OspfRI.pce_info.pce_neighbor);
158
159 OspfRI.enabled = false;
160
161 ospf_router_info_unregister();
162
163 return;
164 }
165
166 void ospf_router_info_finish(void)
167 {
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
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
182 static void del_area_info(void *val)
183 {
184 XFREE(MTYPE_OSPF_ROUTER_INFO, val);
185 }
186
187 static void del_pce_info(void *val)
188 {
189 XFREE(MTYPE_OSPF_PCE_PARAMS, val);
190 }
191
192 /* Catch RI LSA flooding Scope for ospf_ext.[h,c] code */
193 struct scope_info ospf_router_info_get_flooding_scope(void)
194 {
195 struct scope_info flooding_scope;
196
197 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
198 flooding_scope.scope = OSPF_OPAQUE_AS_LSA;
199 flooding_scope.areas = NULL;
200 return flooding_scope;
201 }
202 flooding_scope.scope = OSPF_OPAQUE_AREA_LSA;
203 flooding_scope.areas = OspfRI.area_info;
204 return flooding_scope;
205 }
206
207 static 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
219 /*------------------------------------------------------------------------*
220 * Following are control functions for ROUTER INFORMATION parameters
221 *management.
222 *------------------------------------------------------------------------*/
223
224 static void set_router_info_capabilities(struct ri_tlv_router_cap *ric,
225 uint32_t cap)
226 {
227 ric->header.type = htons(RI_TLV_CAPABILITIES);
228 ric->header.length = htons(RI_TLV_LENGTH);
229 ric->value = htonl(cap);
230 return;
231 }
232
233 static int set_pce_header(struct ospf_pce_info *pce)
234 {
235 uint16_t length = 0;
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)
242 length += TLV_SIZE(&pce->pce_address.header);
243
244 /* PCE Path Scope */
245 if (ntohs(pce->pce_scope.header.type) != 0)
246 length += TLV_SIZE(&pce->pce_scope.header);
247
248 /* PCE Domain */
249 for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
250 if (ntohs(domain->header.type) != 0)
251 length += TLV_SIZE(&domain->header);
252 }
253
254 /* PCE Neighbor */
255 for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
256 if (ntohs(neighbor->header.type) != 0)
257 length += TLV_SIZE(&neighbor->header);
258 }
259
260 /* PCE Capabilities */
261 if (ntohs(pce->pce_cap_flag.header.type) != 0)
262 length += TLV_SIZE(&pce->pce_cap_flag.header);
263
264 if (length != 0) {
265 pce->pce_header.header.type = htons(RI_TLV_PCE);
266 pce->pce_header.header.length = htons(length);
267 pce->enabled = true;
268 } else {
269 pce->pce_header.header.type = 0;
270 pce->pce_header.header.length = 0;
271 pce->enabled = false;
272 }
273
274 return length;
275 }
276
277 static void set_pce_address(struct in_addr ipv4, struct ospf_pce_info *pce)
278 {
279
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);
284 pce->pce_address.header.length = htons(PCE_ADDRESS_IPV4_SIZE);
285 pce->pce_address.address.type = htons(PCE_ADDRESS_IPV4);
286 pce->pce_address.address.value = ipv4;
287
288 return;
289 }
290
291 static void set_pce_path_scope(uint32_t scope, struct ospf_pce_info *pce)
292 {
293
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);
298
299 return;
300 }
301
302 static void set_pce_domain(uint16_t type, uint32_t domain,
303 struct ospf_pce_info *pce)
304 {
305
306 struct ri_pce_subtlv_domain *new;
307
308 /* Create new domain info */
309 new = XCALLOC(MTYPE_OSPF_PCE_PARAMS,
310 sizeof(struct ri_pce_subtlv_domain));
311
312 new->header.type = htons(RI_PCE_SUBTLV_DOMAIN);
313 new->header.length = htons(PCE_ADDRESS_IPV4_SIZE);
314 new->type = htons(type);
315 new->value = htonl(domain);
316
317 /* Add new domain to the list */
318 listnode_add(pce->pce_domain, new);
319
320 return;
321 }
322
323 static void unset_pce_domain(uint16_t type, uint32_t domain,
324 struct ospf_pce_info *pce)
325 {
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
343 /* Finally free the old domain */
344 XFREE(MTYPE_OSPF_PCE_PARAMS, old);
345 }
346 }
347
348 static void set_pce_neighbor(uint16_t type, uint32_t domain,
349 struct ospf_pce_info *pce)
350 {
351
352 struct ri_pce_subtlv_neighbor *new;
353
354 /* Create new neighbor info */
355 new = XCALLOC(MTYPE_OSPF_PCE_PARAMS,
356 sizeof(struct ri_pce_subtlv_neighbor));
357
358 new->header.type = htons(RI_PCE_SUBTLV_NEIGHBOR);
359 new->header.length = htons(PCE_ADDRESS_IPV4_SIZE);
360 new->type = htons(type);
361 new->value = htonl(domain);
362
363 /* Add new domain to the list */
364 listnode_add(pce->pce_neighbor, new);
365
366 return;
367 }
368
369 static void unset_pce_neighbor(uint16_t type, uint32_t domain,
370 struct ospf_pce_info *pce)
371 {
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
389 /* Finally free the old domain */
390 XFREE(MTYPE_OSPF_PCE_PARAMS, old);
391 }
392 }
393
394 static void set_pce_cap_flag(uint32_t cap, struct ospf_pce_info *pce)
395 {
396
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);
401
402 return;
403 }
404
405 /* Segment Routing TLV setter */
406
407 /* Algorithm SubTLV - section 3.1 */
408 static void set_sr_algorithm(uint8_t algo)
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);
417 TLV_LEN(OspfRI.sr_info.algo) = htons(sizeof(uint8_t));
418 }
419
420 /* unset Aglogithm SubTLV */
421 static void unset_sr_algorithm(uint8_t algo)
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);
430 }
431
432 /* Set Segment Routing Global Block SubTLV - section 3.2 */
433 static void set_sr_global_label_range(struct sr_block srgb)
434 {
435 /* Set Header */
436 TLV_TYPE(OspfRI.sr_info.srgb) = htons(RI_SR_TLV_SRGB_LABEL_RANGE);
437 TLV_LEN(OspfRI.sr_info.srgb) = htons(RI_SR_TLV_LABEL_RANGE_SIZE);
438 /* Set Range Size */
439 OspfRI.sr_info.srgb.size = htonl(SET_RANGE_SIZE(srgb.range_size));
440 /* Set Lower bound label SubTLV */
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));
444 }
445
446 /* Unset Segment Routing Global Block SubTLV */
447 static void unset_sr_global_label_range(void)
448 {
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 }
454
455 /* Set Segment Routing Local Block SubTLV - section 3.2 */
456 static 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);
460 TLV_LEN(OspfRI.sr_info.srlb) = htons(RI_SR_TLV_LABEL_RANGE_SIZE);
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 */
470 static 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);
476 }
477
478 /* Set Maximum Stack Depth for this router */
479 static void set_sr_node_msd(uint8_t msd)
480 {
481 TLV_TYPE(OspfRI.sr_info.msd) = htons(RI_SR_TLV_NODE_MSD);
482 TLV_LEN(OspfRI.sr_info.msd) = htons(sizeof(uint32_t));
483 OspfRI.sr_info.msd.value = msd;
484 }
485
486 /* Unset this router MSD */
487 static void unset_sr_node_msd(void)
488 {
489 TLV_TYPE(OspfRI.sr_info.msd) = htons(0);
490 TLV_LEN(OspfRI.sr_info.msd) = htons(0);
491 }
492
493 static void unset_param(void *tlv_buffer)
494 {
495 struct tlv_header *tlv = (struct tlv_header *)tlv_buffer;
496
497 tlv->type = 0;
498 /* Fill the Value to 0 */
499 memset(TLV_DATA(tlv_buffer), 0, TLV_BODY_SIZE(tlv));
500 tlv->length = 0;
501
502 return;
503 }
504
505 static void initialize_params(struct ospf_router_info *ori)
506 {
507 uint32_t cap = 0;
508 struct ospf *top;
509 struct listnode *node, *nnode;
510 struct ospf_area *area;
511 struct ospf_ri_area_info *new;
512
513 /*
514 * Initialize default Router Information Capabilities.
515 */
516 cap = RI_TE_SUPPORT;
517
518 set_router_info_capabilities(&ori->router_cap, cap);
519
520 /* If Area address is not null and exist, retrieve corresponding
521 * structure */
522 top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
523 zlog_info("RI (%s): Initialize Router Info for %s scope", __func__,
524 OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS");
525
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) {
529 if (!list_isempty(OspfRI.area_info))
530 list_delete_all_node(OspfRI.area_info);
531 for (ALL_LIST_ELEMENTS(top->areas, node, nnode, area)) {
532 zlog_debug("RI (%s): Add area %pI4 to Router Information",
533 __func__, &area->area_id);
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 }
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
558 return;
559 }
560
561 static int is_mandated_params_set(struct ospf_router_info *ori)
562 {
563 int rc = 0;
564
565 if (ori == NULL)
566 return rc;
567
568 if (ntohs(ori->router_cap.header.type) == 0)
569 return rc;
570
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))
578 return rc;
579
580 rc = 1;
581
582 return rc;
583 }
584
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
589 * @param srn Self Segment Routing node
590 *
591 * @return none
592 */
593 void ospf_router_info_update_sr(bool enable, struct sr_node *srn)
594 {
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 }
610
611 /* Then, activate and initialize Router Information if necessary */
612 if (!OspfRI.enabled) {
613 OspfRI.enabled = true;
614 initialize_params(&OspfRI);
615 }
616
617 /* Check that SR node is valid */
618 if (srn == NULL)
619 return;
620
621 if (IS_DEBUG_OSPF_SR)
622 zlog_debug("RI (%s): %s Routing Information for Segment Routing",
623 __func__, enable ? "Enable" : "Disable");
624
625 /* Unset or Set SR parameters */
626 if (!enable) {
627 unset_sr_algorithm(SR_ALGORITHM_SPF);
628 unset_sr_global_label_range();
629 unset_sr_local_label_range();
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);
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);
639 else
640 unset_sr_node_msd();
641 OspfRI.sr_info.enabled = true;
642 }
643
644 /* Refresh if already engaged or originate RI LSA */
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 }
653 }
654
655 /*------------------------------------------------------------------------*
656 * Following are callback functions against generic Opaque-LSAs handling.
657 *------------------------------------------------------------------------*/
658 static void ospf_router_info_ism_change(struct ospf_interface *oi,
659 int old_state)
660 {
661
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
677 return;
678 }
679
680 /*------------------------------------------------------------------------*
681 * Following are OSPF protocol processing functions for ROUTER INFORMATION
682 *------------------------------------------------------------------------*/
683
684 static void build_tlv_header(struct stream *s, struct tlv_header *tlvh)
685 {
686
687 stream_put(s, tlvh, sizeof(struct tlv_header));
688 return;
689 }
690
691 static void build_tlv(struct stream *s, struct tlv_header *tlvh)
692 {
693
694 if (ntohs(tlvh->type) != 0) {
695 build_tlv_header(s, tlvh);
696 stream_put(s, TLV_DATA(tlvh), TLV_BODY_SIZE(tlvh));
697 }
698 return;
699 }
700
701 static void ospf_router_info_lsa_body_set(struct stream *s)
702 {
703
704 struct listnode *node;
705 struct ri_pce_subtlv_domain *domain;
706 struct ri_pce_subtlv_neighbor *neighbor;
707
708 /* Build Router Information TLV */
709 build_tlv(s, &OspfRI.router_cap.header);
710
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 */
716 build_tlv(s, &TLV_HDR(OspfRI.sr_info.srgb));
717 /* Build SRLB TLV */
718 build_tlv(s, &TLV_HDR(OspfRI.sr_info.srlb));
719 /* Build MSD TLV */
720 build_tlv(s, &TLV_HDR(OspfRI.sr_info.msd));
721 }
722
723 /* Add RI PCE TLV if it is set */
724 if (OspfRI.pce_info.enabled) {
725
726 /* Compute PCE Info header first */
727 set_pce_header(&OspfRI.pce_info);
728
729 /* Build PCE TLV */
730 build_tlv_header(s, &OspfRI.pce_info.pce_header.header);
731
732 /* Build PCE address sub-tlv */
733 build_tlv(s, &OspfRI.pce_info.pce_address.header);
734
735 /* Build PCE path scope sub-tlv */
736 build_tlv(s, &OspfRI.pce_info.pce_scope.header);
737
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);
742
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);
747
748 /* Build PCE cap flag sub-tlv */
749 build_tlv(s, &OspfRI.pce_info.pce_cap_flag.header);
750 }
751
752 return;
753 }
754
755 /* Create new opaque-LSA. */
756 static struct ospf_lsa *ospf_router_info_lsa_new(struct ospf_area *area)
757 {
758 struct ospf *top;
759 struct stream *s;
760 struct lsa_header *lsah;
761 struct ospf_lsa *new = NULL;
762 uint8_t options, lsa_type;
763 struct in_addr lsa_id;
764 uint32_t tmp;
765 uint16_t length;
766
767 /* Create a stream for LSA. */
768 s = stream_new(OSPF_MAX_LSA_SIZE);
769
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(
783 "LSA[Type%d:%pI4]: Create an Opaque-LSA/ROUTER INFORMATION instance",
784 lsa_type, &lsa_id);
785
786 top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
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. */
799 new = ospf_lsa_new_and_data(length);
800
801 /* Routing Information is only supported for default VRF */
802 new->vrf_id = VRF_DEFAULT;
803 new->area = area;
804
805 SET_FLAG(new->flags, OSPF_LSA_SELF);
806 memcpy(new->data, lsah, length);
807 stream_free(s);
808
809 return new;
810 }
811
812 static int ospf_router_info_lsa_originate_as(void *arg)
813 {
814 struct ospf_lsa *new;
815 struct ospf *top;
816 int rc = -1;
817
818 /* Sanity Check */
819 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
820 flog_warn(
821 EC_OSPF_LSA_INSTALL_FAILURE,
822 "RI (%s): wrong flooding scope AREA instead of AS ?",
823 __func__);
824 return rc;
825 }
826
827 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
828 new = ospf_router_info_lsa_new(NULL);
829 top = (struct ospf *)arg;
830
831 /* Check ospf info */
832 if (top == NULL) {
833 zlog_debug("RI (%s): ospf instance not found for vrf id %u",
834 __func__, VRF_DEFAULT);
835 ospf_lsa_unlock(&new);
836 return rc;
837 }
838
839 /* Install this LSA into LSDB. */
840 if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
841 flog_warn(
842 EC_OSPF_LSA_INSTALL_FAILURE,
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(
857 "LSA[Type%d:%pI4]: Originate Opaque-LSA/ROUTER INFORMATION",
858 new->data->type, &new->data->id);
859 ospf_lsa_header_dump(new->data);
860 }
861
862 rc = 0;
863 return rc;
864 }
865
866 static 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;
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 }
890
891 if (ai->area->ospf)
892 top = ai->area->ospf;
893 else
894 top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
895
896 new = ospf_router_info_lsa_new(ai->area);
897
898 /* Check ospf info */
899 if (top == NULL) {
900 zlog_debug("RI (%s): ospf instance not found for vrf id %u",
901 __func__, VRF_DEFAULT);
902 ospf_lsa_unlock(&new);
903 return rc;
904 }
905
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 }
914
915 /* Update new LSA origination count. */
916 top->lsa_originate_count++;
917
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);
921
922 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
923 zlog_debug(
924 "LSA[Type%d:%pI4]: Originate Opaque-LSA/ROUTER INFORMATION",
925 new->data->type, &new->data->id);
926 ospf_lsa_header_dump(new->data);
927 }
928
929 rc = 0;
930 return rc;
931 }
932
933 static int ospf_router_info_lsa_originate(void *arg)
934 {
935
936 struct ospf_ri_area_info *ai;
937 int rc = -1;
938
939 if (!OspfRI.enabled) {
940 zlog_info("RI (%s): ROUTER INFORMATION is disabled now.",
941 __func__);
942 rc = 0; /* This is not an error case. */
943 return rc;
944 }
945
946 /* Check if Router Information LSA is already engaged */
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;
955 }
956 } else {
957 ai = lookup_by_area((struct ospf_area *)arg);
958 if (ai == NULL) {
959 flog_warn(
960 EC_OSPF_LSA,
961 "RI (%s): Missing area information", __func__);
962 return rc;
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 }
971 }
972
973 /* Router Information is not yet Engaged, check parameters */
974 if (!is_mandated_params_set(&OspfRI))
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
986 return rc;
987 }
988
989 static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa)
990 {
991 struct ospf_ri_area_info *ai = NULL;
992 struct ospf_lsa *new = NULL;
993 struct ospf *top;
994
995 if (!OspfRI.enabled) {
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 */
1001 zlog_info("RI (%s): ROUTER INFORMATION is disabled now.",
1002 __func__);
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) {
1009 flog_warn(
1010 EC_OSPF_LSA,
1011 "RI (%s): Unsupported Router Information ID",
1012 __func__);
1013 return NULL;
1014 }
1015
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);
1035 /* Install this LSA into LSDB. */
1036 /* Given "lsa" will be freed in the next function. */
1037 top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
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);
1057 /* Install this LSA into LSDB. */
1058 /* Given "lsa" will be freed in the next function. */
1059 top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
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 */
1067 ospf_flood_through_as(top, NULL /*nbr */, new);
1068 }
1069
1070 /* Debug logging. */
1071 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
1072 zlog_debug(
1073 "LSA[Type%d:%pI4]: Refresh Opaque-LSA/ROUTER INFORMATION",
1074 new->data->type, &new->data->id);
1075 ospf_lsa_header_dump(new->data);
1076 }
1077
1078 return new;
1079 }
1080
1081 static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info *ai,
1082 enum lsa_opcode opcode)
1083 {
1084 struct ospf_lsa lsa;
1085 struct lsa_header lsah;
1086 struct ospf *top;
1087 uint32_t tmp;
1088
1089 memset(&lsa, 0, sizeof(lsa));
1090 memset(&lsah, 0, sizeof(lsah));
1091
1092 zlog_debug("RI (%s): LSA schedule %s%s%s", __func__,
1093 opcode == REORIGINATE_THIS_LSA ? "Re-Originate" : "",
1094 opcode == REFRESH_THIS_LSA ? "Refresh" : "",
1095 opcode == FLUSH_THIS_LSA ? "Flush" : "");
1096
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 }
1106
1107 if (!CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED)
1108 && (opcode != REORIGINATE_THIS_LSA))
1109 return;
1110
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;
1128 }
1129
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(
1141 (void *)ai->area, OSPF_OPAQUE_AREA_LSA,
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:
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);
1156 ospf_opaque_lsa_flush_schedule(&lsa);
1157 break;
1158 }
1159
1160 return;
1161 }
1162
1163 /* Callback to handle Segment Routing information */
1164 static int ospf_router_info_lsa_update(struct ospf_lsa *lsa)
1165 {
1166
1167 /* Sanity Check */
1168 if (lsa == NULL) {
1169 flog_warn(EC_OSPF_LSA, "RI (%s): Abort! LSA is NULL",
1170 __func__);
1171 return -1;
1172 }
1173
1174 /* Process only Opaque LSA */
1175 if ((lsa->data->type != OSPF_OPAQUE_AREA_LSA)
1176 && (lsa->data->type != OSPF_OPAQUE_AS_LSA))
1177 return 0;
1178
1179 /* Process only Router Information LSA */
1180 if (GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr))
1181 != OPAQUE_TYPE_ROUTER_INFORMATION_LSA)
1182 return 0;
1183
1184 /* Check if it is not my LSA */
1185 if (IS_LSA_SELF(lsa))
1186 return 0;
1187
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
1201 /*------------------------------------------------------------------------*
1202 * Following are vty session control functions.
1203 *------------------------------------------------------------------------*/
1204
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 \
1212 zlog_debug(" Wrong %s TLV size: %d(%d)", \
1213 msg, ntohs(tlvh->length), size); \
1214 return size + TLV_HDR_SIZE; \
1215 } \
1216 } while (0)
1217
1218 static uint16_t show_vty_router_cap(struct vty *vty, struct tlv_header *tlvh)
1219 {
1220 struct ri_tlv_router_cap *top = (struct ri_tlv_router_cap *)tlvh;
1221
1222 check_tlv_size(RI_TLV_CAPABILITIES_SIZE, "Router Capabilities");
1223
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));
1229
1230 return TLV_SIZE(tlvh);
1231 }
1232
1233 static uint16_t show_vty_pce_subtlv_address(struct vty *vty,
1234 struct tlv_header *tlvh)
1235 {
1236 struct ri_pce_subtlv_address *top =
1237 (struct ri_pce_subtlv_address *)tlvh;
1238
1239 if (ntohs(top->address.type) == PCE_ADDRESS_IPV4) {
1240 check_tlv_size(PCE_ADDRESS_IPV4_SIZE, "PCE Address");
1241 if (vty != NULL)
1242 vty_out(vty, " PCE Address: %pI4\n",
1243 &top->address.value);
1244 else
1245 zlog_debug(" PCE Address: %pI4",
1246 &top->address.value);
1247 } else if (ntohs(top->address.type) == PCE_ADDRESS_IPV6) {
1248 /* TODO: Add support to IPv6 with inet_ntop() */
1249 check_tlv_size(PCE_ADDRESS_IPV6_SIZE, "PCE Address");
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));
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));
1263 }
1264
1265 return TLV_SIZE(tlvh);
1266 }
1267
1268 static uint16_t show_vty_pce_subtlv_path_scope(struct vty *vty,
1269 struct tlv_header *tlvh)
1270 {
1271 struct ri_pce_subtlv_path_scope *top =
1272 (struct ri_pce_subtlv_path_scope *)tlvh;
1273
1274 check_tlv_size(RI_PCE_SUBTLV_PATH_SCOPE_SIZE, "PCE Path Scope");
1275
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));
1280
1281 return TLV_SIZE(tlvh);
1282 }
1283
1284 static uint16_t show_vty_pce_subtlv_domain(struct vty *vty,
1285 struct tlv_header *tlvh)
1286 {
1287 struct ri_pce_subtlv_domain *top = (struct ri_pce_subtlv_domain *)tlvh;
1288 struct in_addr tmp;
1289
1290 check_tlv_size(RI_PCE_SUBTLV_DOMAIN_SIZE, "PCE Domain");
1291
1292 if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) {
1293 tmp.s_addr = top->value;
1294 if (vty != NULL)
1295 vty_out(vty, " PCE Domain Area: %pI4\n", &tmp);
1296 else
1297 zlog_debug(" PCE Domain Area: %pI4", &tmp);
1298 } else if (ntohs(top->type) == PCE_DOMAIN_TYPE_AS) {
1299 if (vty != NULL)
1300 vty_out(vty, " PCE Domain AS: %d\n",
1301 ntohl(top->value));
1302 else
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));
1311 }
1312
1313 return TLV_SIZE(tlvh);
1314 }
1315
1316 static uint16_t show_vty_pce_subtlv_neighbor(struct vty *vty,
1317 struct tlv_header *tlvh)
1318 {
1319
1320 struct ri_pce_subtlv_neighbor *top =
1321 (struct ri_pce_subtlv_neighbor *)tlvh;
1322 struct in_addr tmp;
1323
1324 check_tlv_size(RI_PCE_SUBTLV_NEIGHBOR_SIZE, "PCE Neighbor");
1325
1326 if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) {
1327 tmp.s_addr = top->value;
1328 if (vty != NULL)
1329 vty_out(vty, " PCE Neighbor Area: %pI4\n", &tmp);
1330 else
1331 zlog_debug(" PCE Neighbor Area: %pI4", &tmp);
1332 } else if (ntohs(top->type) == PCE_DOMAIN_TYPE_AS) {
1333 if (vty != NULL)
1334 vty_out(vty, " PCE Neighbor AS: %d\n",
1335 ntohl(top->value));
1336 else
1337 zlog_debug(" PCE Neighbor AS: %d",
1338 ntohl(top->value));
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));
1346 }
1347
1348 return TLV_SIZE(tlvh);
1349 }
1350
1351 static uint16_t show_vty_pce_subtlv_cap_flag(struct vty *vty,
1352 struct tlv_header *tlvh)
1353 {
1354 struct ri_pce_subtlv_cap_flag *top =
1355 (struct ri_pce_subtlv_cap_flag *)tlvh;
1356
1357 check_tlv_size(RI_PCE_SUBTLV_CAP_FLAG_SIZE, "PCE Capabilities");
1358
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));
1365
1366 return TLV_SIZE(tlvh);
1367 }
1368
1369 static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh,
1370 size_t buf_size)
1371 {
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
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
1391 return TLV_SIZE(tlvh);
1392 }
1393
1394 static uint16_t show_vty_pce_info(struct vty *vty, struct tlv_header *ri,
1395 size_t buf_size)
1396 {
1397 struct tlv_header *tlvh;
1398 uint16_t length = ntohs(ri->length);
1399 uint16_t sum = 0;
1400
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)) {
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:
1427 sum += show_vty_unknown_tlv(vty, tlvh, length - sum);
1428 break;
1429 }
1430 }
1431 return sum;
1432 }
1433
1434 /* Display Segment Routing Algorithm TLV information */
1435 static uint16_t show_vty_sr_algorithm(struct vty *vty, struct tlv_header *tlvh)
1436 {
1437 struct ri_sr_tlv_sr_algorithm *algo =
1438 (struct ri_sr_tlv_sr_algorithm *)tlvh;
1439 int i;
1440
1441 check_tlv_size(ALGORITHM_COUNT, "Segment Routing Algorithm");
1442
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 }
1461 } else {
1462 zlog_debug(" Segment Routing Algorithm TLV:");
1463 for (i = 0; i < ntohs(algo->header.length); i++)
1464 switch (algo->value[i]) {
1465 case 0:
1466 zlog_debug(" Algorithm %d: SPF", i);
1467 break;
1468 case 1:
1469 zlog_debug(" Algorithm %d: Strict SPF", i);
1470 break;
1471 default:
1472 zlog_debug(" Algorithm %d: Unknown value %d",
1473 i, algo->value[i]);
1474 break;
1475 }
1476 }
1477
1478 return TLV_SIZE(tlvh);
1479 }
1480
1481 /* Display Segment Routing SID/Label Range TLV information */
1482 static uint16_t show_vty_sr_range(struct vty *vty, struct tlv_header *tlvh)
1483 {
1484 struct ri_sr_tlv_sid_label_range *range =
1485 (struct ri_sr_tlv_sid_label_range *)tlvh;
1486
1487 check_tlv_size(RI_SR_TLV_LABEL_RANGE_SIZE, "SR Label Range");
1488
1489 if (vty != NULL) {
1490 vty_out(vty,
1491 " Segment Routing %s Range TLV:\n"
1492 " Range Size = %d\n"
1493 " SID Label = %d\n\n",
1494 ntohs(range->header.type) == RI_SR_TLV_SRGB_LABEL_RANGE
1495 ? "Global"
1496 : "Local",
1497 GET_RANGE_SIZE(ntohl(range->size)),
1498 GET_LABEL(ntohl(range->lower.value)));
1499 } else {
1500 zlog_debug(
1501 " Segment Routing %s Range TLV: Range Size = %d SID Label = %d",
1502 ntohs(range->header.type) == RI_SR_TLV_SRGB_LABEL_RANGE
1503 ? "Global"
1504 : "Local",
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 */
1513 static uint16_t show_vty_sr_msd(struct vty *vty, struct tlv_header *tlvh)
1514 {
1515 struct ri_sr_tlv_node_msd *msd = (struct ri_sr_tlv_node_msd *)tlvh;
1516
1517 check_tlv_size(RI_SR_TLV_NODE_MSD_SIZE, "Node Maximum Stack Depth");
1518
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(
1526 " Segment Routing MSD TLV: Node Maximum Stack Depth = %d",
1527 msd->value);
1528 }
1529
1530 return TLV_SIZE(tlvh);
1531 }
1532
1533 static void ospf_router_info_show_info(struct vty *vty,
1534 struct json_object *json,
1535 struct ospf_lsa *lsa)
1536 {
1537 struct lsa_header *lsah = lsa->data;
1538 struct tlv_header *tlvh;
1539 uint16_t length = 0, sum = 0;
1540
1541 if (json)
1542 return;
1543
1544 /* Initialize TLV browsing */
1545 length = lsa->size - OSPF_LSA_HEADER_SIZE;
1546
1547 for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh;
1548 tlvh = TLV_HDR_NEXT(tlvh)) {
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++;
1555 sum += TLV_HDR_SIZE;
1556 sum += show_vty_pce_info(vty, tlvh, length - sum);
1557 break;
1558 case RI_SR_TLV_SR_ALGORITHM:
1559 sum += show_vty_sr_algorithm(vty, tlvh);
1560 break;
1561 case RI_SR_TLV_SRGB_LABEL_RANGE:
1562 case RI_SR_TLV_SRLB_LABEL_RANGE:
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
1569 default:
1570 sum += show_vty_unknown_tlv(vty, tlvh, length);
1571 break;
1572 }
1573 }
1574
1575 return;
1576 }
1577
1578 static void ospf_router_info_config_write_router(struct vty *vty)
1579 {
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
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
1592 vty_out(vty, " router-info area\n");
1593
1594 if (OspfRI.pce_info.enabled) {
1595
1596 if (pce->pce_address.header.type != 0)
1597 vty_out(vty, " pce address %pI4\n",
1598 &pce->pce_address.address.value);
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;
1608 vty_out(vty, " pce domain area %pI4\n",
1609 &tmp);
1610 } else {
1611 vty_out(vty, " pce domain as %d\n",
1612 ntohl(domain->value));
1613 }
1614 }
1615 }
1616
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;
1621 vty_out(vty,
1622 " pce neighbor area %pI4\n",
1623 &tmp);
1624 } else {
1625 vty_out(vty, " pce neighbor as %d\n",
1626 ntohl(neighbor->value));
1627 }
1628 }
1629 }
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));
1634 }
1635 return;
1636 }
1637
1638 /*------------------------------------------------------------------------*
1639 * Following are vty command functions.
1640 *------------------------------------------------------------------------*/
1641 /* Simple wrapper schedule RI LSA action in function of the scope */
1642 static 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 }
1659
1660 DEFUN (router_info,
1661 router_info_area_cmd,
1662 "router-info <as|area [A.B.C.D]>",
1663 OSPF_RI_STR
1664 "Enable the Router Information functionality with AS flooding scope\n"
1665 "Enable the Router Information functionality with Area flooding scope\n"
1666 "OSPF area ID in IP format (deprecated)\n")
1667 {
1668 int idx_mode = 1;
1669 uint8_t scope;
1670 VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
1671
1672 if (OspfRI.enabled)
1673 return CMD_SUCCESS;
1674
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
1682 /* Check and get Area value if present */
1683 if (strncmp(argv[idx_mode]->arg, "as", 2) == 0)
1684 scope = OSPF_OPAQUE_AS_LSA;
1685 else
1686 scope = OSPF_OPAQUE_AREA_LSA;
1687
1688 /* First start to register Router Information callbacks */
1689 if (!OspfRI.registered && (ospf_router_info_register(scope)) != 0) {
1690 vty_out(vty,
1691 "%% Unable to register Router Information callbacks.");
1692 flog_err(
1693 EC_OSPF_INIT_FAIL,
1694 "RI (%s): Unable to register Router Information callbacks. Abort!",
1695 __func__);
1696 return CMD_WARNING_CONFIG_FAILED;
1697 }
1698
1699 OspfRI.enabled = true;
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
1717 /* Originate or Refresh RI LSA if already engaged */
1718 ospf_router_info_schedule(REORIGINATE_THIS_LSA);
1719 return CMD_SUCCESS;
1720 }
1721
1722
1723 DEFUN (no_router_info,
1724 no_router_info_cmd,
1725 "no router-info",
1726 NO_STR
1727 "Disable the Router Information functionality\n")
1728 {
1729
1730 if (!OspfRI.enabled)
1731 return CMD_SUCCESS;
1732
1733 if (IS_DEBUG_OSPF_EVENT)
1734 zlog_debug("RI-> Router Information: ON -> OFF");
1735
1736 ospf_router_info_schedule(FLUSH_THIS_LSA);
1737
1738 OspfRI.enabled = false;
1739
1740 return CMD_SUCCESS;
1741 }
1742
1743 static int ospf_ri_enabled(struct vty *vty)
1744 {
1745 if (OspfRI.enabled)
1746 return 1;
1747
1748 if (vty)
1749 vty_out(vty, "%% OSPF RI is not turned on\n");
1750
1751 return 0;
1752 }
1753
1754 DEFUN (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 {
1761 int idx_ipv4 = 2;
1762 struct in_addr value;
1763 struct ospf_pce_info *pi = &OspfRI.pce_info;
1764
1765 if (!ospf_ri_enabled(vty))
1766 return CMD_WARNING_CONFIG_FAILED;
1767
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 }
1772
1773 if (ntohs(pi->pce_address.header.type) == 0
1774 || ntohl(pi->pce_address.address.value.s_addr)
1775 != ntohl(value.s_addr)) {
1776
1777 set_pce_address(value, pi);
1778
1779 /* Refresh RI LSA if already engaged */
1780 ospf_router_info_schedule(REFRESH_THIS_LSA);
1781 }
1782
1783 return CMD_SUCCESS;
1784 }
1785
1786 DEFUN (no_pce_address,
1787 no_pce_address_cmd,
1788 "no pce address [A.B.C.D]",
1789 NO_STR
1790 PCE_STR
1791 "Disable PCE address\n"
1792 "PCE address in IPv4 address format\n")
1793 {
1794
1795 unset_param(&OspfRI.pce_info.pce_address);
1796
1797 /* Refresh RI LSA if already engaged */
1798 ospf_router_info_schedule(REFRESH_THIS_LSA);
1799
1800 return CMD_SUCCESS;
1801 }
1802
1803 DEFUN (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 {
1810 int idx_bitpattern = 2;
1811 uint32_t scope;
1812 struct ospf_pce_info *pi = &OspfRI.pce_info;
1813
1814 if (!ospf_ri_enabled(vty))
1815 return CMD_WARNING_CONFIG_FAILED;
1816
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 }
1822
1823 if (ntohl(pi->pce_scope.header.type) == 0
1824 || scope != pi->pce_scope.value) {
1825 set_pce_path_scope(scope, pi);
1826
1827 /* Refresh RI LSA if already engaged */
1828 ospf_router_info_schedule(REFRESH_THIS_LSA);
1829 }
1830
1831 return CMD_SUCCESS;
1832 }
1833
1834 DEFUN (no_pce_path_scope,
1835 no_pce_path_scope_cmd,
1836 "no pce scope [BITPATTERN]",
1837 NO_STR
1838 PCE_STR
1839 "Disable PCE path scope\n"
1840 "32-bit Hexadecimal value\n")
1841 {
1842
1843 unset_param(&OspfRI.pce_info.pce_address);
1844
1845 /* Refresh RI LSA if already engaged */
1846 ospf_router_info_schedule(REFRESH_THIS_LSA);
1847
1848 return CMD_SUCCESS;
1849 }
1850
1851 DEFUN (pce_domain,
1852 pce_domain_cmd,
1853 "pce domain as (0-65535)",
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 {
1859 int idx_number = 3;
1860
1861 uint32_t as;
1862 struct ospf_pce_info *pce = &OspfRI.pce_info;
1863 struct listnode *node;
1864 struct ri_pce_subtlv_domain *domain;
1865
1866 if (!ospf_ri_enabled(vty))
1867 return CMD_WARNING_CONFIG_FAILED;
1868
1869 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
1870 vty_out(vty, "pce_domain: fscanf: %s\n", safe_strerror(errno));
1871 return CMD_WARNING_CONFIG_FAILED;
1872 }
1873
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 }
1879
1880 /* Create new domain if not found */
1881 set_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce);
1882
1883 /* Refresh RI LSA if already engaged */
1884 ospf_router_info_schedule(REFRESH_THIS_LSA);
1885
1886 return CMD_SUCCESS;
1887 }
1888
1889 DEFUN (no_pce_domain,
1890 no_pce_domain_cmd,
1891 "no pce domain as (0-65535)",
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 {
1898 int idx_number = 4;
1899
1900 uint32_t as;
1901 struct ospf_pce_info *pce = &OspfRI.pce_info;
1902
1903 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
1904 vty_out(vty, "no_pce_domain: fscanf: %s\n",
1905 safe_strerror(errno));
1906 return CMD_WARNING_CONFIG_FAILED;
1907 }
1908
1909 /* Unset corresponding PCE domain */
1910 unset_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce);
1911
1912 /* Refresh RI LSA if already engaged */
1913 ospf_router_info_schedule(REFRESH_THIS_LSA);
1914
1915 return CMD_SUCCESS;
1916 }
1917
1918 DEFUN (pce_neigbhor,
1919 pce_neighbor_cmd,
1920 "pce neighbor as (0-65535)",
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 {
1926 int idx_number = 3;
1927
1928 uint32_t as;
1929 struct ospf_pce_info *pce = &OspfRI.pce_info;
1930 struct listnode *node;
1931 struct ri_pce_subtlv_neighbor *neighbor;
1932
1933 if (!ospf_ri_enabled(vty))
1934 return CMD_WARNING_CONFIG_FAILED;
1935
1936 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
1937 vty_out(vty, "pce_neighbor: fscanf: %s\n",
1938 safe_strerror(errno));
1939 return CMD_WARNING_CONFIG_FAILED;
1940 }
1941
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 }
1947
1948 /* Create new domain if not found */
1949 set_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce);
1950
1951 /* Refresh RI LSA if already engaged */
1952 ospf_router_info_schedule(REFRESH_THIS_LSA);
1953
1954 return CMD_SUCCESS;
1955 }
1956
1957 DEFUN (no_pce_neighbor,
1958 no_pce_neighbor_cmd,
1959 "no pce neighbor as (0-65535)",
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 {
1966 int idx_number = 4;
1967
1968 uint32_t as;
1969 struct ospf_pce_info *pce = &OspfRI.pce_info;
1970
1971 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
1972 vty_out(vty, "no_pce_neighbor: fscanf: %s\n",
1973 safe_strerror(errno));
1974 return CMD_WARNING_CONFIG_FAILED;
1975 }
1976
1977 /* Unset corresponding PCE domain */
1978 unset_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce);
1979
1980 /* Refresh RI LSA if already engaged */
1981 ospf_router_info_schedule(REFRESH_THIS_LSA);
1982
1983 return CMD_SUCCESS;
1984 }
1985
1986 DEFUN (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 {
1993 int idx_bitpattern = 2;
1994
1995 uint32_t cap;
1996 struct ospf_pce_info *pce = &OspfRI.pce_info;
1997
1998 if (!ospf_ri_enabled(vty))
1999 return CMD_WARNING_CONFIG_FAILED;
2000
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 }
2006
2007 if (ntohl(pce->pce_cap_flag.header.type) == 0
2008 || cap != pce->pce_cap_flag.value) {
2009 set_pce_cap_flag(cap, pce);
2010
2011 /* Refresh RI LSA if already engaged */
2012 ospf_router_info_schedule(REFRESH_THIS_LSA);
2013 }
2014
2015 return CMD_SUCCESS;
2016 }
2017
2018 DEFUN (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
2026 unset_param(&OspfRI.pce_info.pce_cap_flag);
2027
2028 /* Refresh RI LSA if already engaged */
2029 ospf_router_info_schedule(REFRESH_THIS_LSA);
2030
2031 return CMD_SUCCESS;
2032 }
2033
2034 DEFUN (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
2043 if (OspfRI.enabled) {
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;
2052 }
2053
2054 DEFUN (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
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;
2068
2069 if ((OspfRI.enabled) && (OspfRI.pce_info.enabled)) {
2070 vty_out(vty, "--- PCE parameters ---\n");
2071
2072 if (pce->pce_address.header.type != 0)
2073 show_vty_pce_subtlv_address(vty,
2074 &pce->pce_address.header);
2075
2076 if (pce->pce_scope.header.type != 0)
2077 show_vty_pce_subtlv_path_scope(vty,
2078 &pce->pce_scope.header);
2079
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 }
2085
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 }
2091
2092 if (pce->pce_cap_flag.header.type != 0)
2093 show_vty_pce_subtlv_cap_flag(vty,
2094 &pce->pce_cap_flag.header);
2095
2096 } else {
2097 vty_out(vty, " PCE info is disabled on this router\n");
2098 }
2099
2100 return CMD_SUCCESS;
2101 }
2102
2103 /* Install new CLI commands */
2104 static void ospf_router_info_register_vty(void)
2105 {
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;
2123 }