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