]> git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_ri.c
Merge pull request #8465 from opensourcerouting/vtysh-scan-snafu
[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 * Followings 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, struct ospf_lsa *lsa);
77 static int ospf_router_info_lsa_originate(void *arg);
78 static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa);
79 static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info *ai,
80 enum lsa_opcode opcode);
81 static void ospf_router_info_register_vty(void);
82 static int ospf_router_info_lsa_update(struct ospf_lsa *lsa);
83 static void del_area_info(void *val);
84 static void del_pce_info(void *val);
85
86 int ospf_router_info_init(void)
87 {
88
89 zlog_info("RI (%s): Initialize Router Information", __func__);
90
91 memset(&OspfRI, 0, sizeof(struct ospf_router_info));
92 OspfRI.enabled = false;
93 OspfRI.registered = 0;
94 OspfRI.scope = OSPF_OPAQUE_AS_LSA;
95 OspfRI.as_flags = RIFLG_LSA_INACTIVE;
96 OspfRI.area_info = list_new();
97 OspfRI.area_info->del = del_area_info;
98
99 /* Initialize pce domain and neighbor list */
100 OspfRI.pce_info.enabled = false;
101 OspfRI.pce_info.pce_domain = list_new();
102 OspfRI.pce_info.pce_domain->del = del_pce_info;
103 OspfRI.pce_info.pce_neighbor = list_new();
104 OspfRI.pce_info.pce_neighbor->del = del_pce_info;
105
106 /* Initialize Segment Routing information structure */
107 OspfRI.sr_info.enabled = false;
108
109 ospf_router_info_register_vty();
110
111 return 0;
112 }
113
114 static int ospf_router_info_register(uint8_t scope)
115 {
116 int rc = 0;
117
118 if (OspfRI.registered)
119 return rc;
120
121 zlog_info("RI (%s): Register Router Information with scope %s(%d)",
122 __func__,
123 scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS", scope);
124 rc = ospf_register_opaque_functab(
125 scope, OPAQUE_TYPE_ROUTER_INFORMATION_LSA,
126 NULL, /* new interface */
127 NULL, /* del interface */
128 ospf_router_info_ism_change,
129 NULL, /* NSM change */
130 ospf_router_info_config_write_router,
131 NULL, /* Config. write interface */
132 NULL, /* Config. write debug */
133 ospf_router_info_show_info, ospf_router_info_lsa_originate,
134 ospf_router_info_lsa_refresh, ospf_router_info_lsa_update,
135 NULL); /* del_lsa_hook */
136
137 if (rc != 0) {
138 flog_warn(
139 EC_OSPF_OPAQUE_REGISTRATION,
140 "RI (%s): Failed to register functions", __func__);
141 return rc;
142 }
143
144 OspfRI.registered = 1;
145 OspfRI.scope = scope;
146 return rc;
147 }
148
149 static int ospf_router_info_unregister(void)
150 {
151
152 if ((OspfRI.scope != OSPF_OPAQUE_AS_LSA)
153 && (OspfRI.scope != OSPF_OPAQUE_AREA_LSA)) {
154 assert("Unable to unregister Router Info functions: Wrong scope!"
155 == NULL);
156 return -1;
157 }
158
159 ospf_delete_opaque_functab(OspfRI.scope,
160 OPAQUE_TYPE_ROUTER_INFORMATION_LSA);
161
162 OspfRI.registered = 0;
163 return 0;
164 }
165
166 void ospf_router_info_term(void)
167 {
168
169 list_delete(&OspfRI.pce_info.pce_domain);
170 list_delete(&OspfRI.pce_info.pce_neighbor);
171
172 OspfRI.enabled = false;
173
174 ospf_router_info_unregister();
175
176 return;
177 }
178
179 void ospf_router_info_finish(void)
180 {
181 struct listnode *node, *nnode;
182 struct ospf_ri_area_info *ai;
183
184 /* Flush Router Info LSA */
185 for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai))
186 if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED))
187 ospf_router_info_lsa_schedule(ai, FLUSH_THIS_LSA);
188
189 list_delete_all_node(OspfRI.pce_info.pce_domain);
190 list_delete_all_node(OspfRI.pce_info.pce_neighbor);
191
192 OspfRI.enabled = false;
193 }
194
195 static void del_area_info(void *val)
196 {
197 XFREE(MTYPE_OSPF_ROUTER_INFO, val);
198 }
199
200 static void del_pce_info(void *val)
201 {
202 XFREE(MTYPE_OSPF_PCE_PARAMS, val);
203 }
204
205 /* Catch RI LSA flooding Scope for ospf_ext.[h,c] code */
206 struct scope_info ospf_router_info_get_flooding_scope(void)
207 {
208 struct scope_info flooding_scope;
209
210 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
211 flooding_scope.scope = OSPF_OPAQUE_AS_LSA;
212 flooding_scope.areas = NULL;
213 return flooding_scope;
214 }
215 flooding_scope.scope = OSPF_OPAQUE_AREA_LSA;
216 flooding_scope.areas = OspfRI.area_info;
217 return flooding_scope;
218 }
219
220 static struct ospf_ri_area_info *lookup_by_area(struct ospf_area *area)
221 {
222 struct listnode *node, *nnode;
223 struct ospf_ri_area_info *ai;
224
225 for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai))
226 if (ai->area == area)
227 return ai;
228
229 return NULL;
230 }
231
232 /*------------------------------------------------------------------------*
233 * Followings are control functions for ROUTER INFORMATION parameters
234 *management.
235 *------------------------------------------------------------------------*/
236
237 static void set_router_info_capabilities(struct ri_tlv_router_cap *ric,
238 uint32_t cap)
239 {
240 ric->header.type = htons(RI_TLV_CAPABILITIES);
241 ric->header.length = htons(RI_TLV_LENGTH);
242 ric->value = htonl(cap);
243 return;
244 }
245
246 static int set_pce_header(struct ospf_pce_info *pce)
247 {
248 uint16_t length = 0;
249 struct listnode *node;
250 struct ri_pce_subtlv_domain *domain;
251 struct ri_pce_subtlv_neighbor *neighbor;
252
253 /* PCE Address */
254 if (ntohs(pce->pce_address.header.type) != 0)
255 length += TLV_SIZE(&pce->pce_address.header);
256
257 /* PCE Path Scope */
258 if (ntohs(pce->pce_scope.header.type) != 0)
259 length += TLV_SIZE(&pce->pce_scope.header);
260
261 /* PCE Domain */
262 for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
263 if (ntohs(domain->header.type) != 0)
264 length += TLV_SIZE(&domain->header);
265 }
266
267 /* PCE Neighbor */
268 for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
269 if (ntohs(neighbor->header.type) != 0)
270 length += TLV_SIZE(&neighbor->header);
271 }
272
273 /* PCE Capabilities */
274 if (ntohs(pce->pce_cap_flag.header.type) != 0)
275 length += TLV_SIZE(&pce->pce_cap_flag.header);
276
277 if (length != 0) {
278 pce->pce_header.header.type = htons(RI_TLV_PCE);
279 pce->pce_header.header.length = htons(length);
280 pce->enabled = true;
281 } else {
282 pce->pce_header.header.type = 0;
283 pce->pce_header.header.length = 0;
284 pce->enabled = false;
285 }
286
287 return length;
288 }
289
290 static void set_pce_address(struct in_addr ipv4, struct ospf_pce_info *pce)
291 {
292
293 /* Enable PCE Info */
294 pce->pce_header.header.type = htons(RI_TLV_PCE);
295 /* Set PCE Address */
296 pce->pce_address.header.type = htons(RI_PCE_SUBTLV_ADDRESS);
297 pce->pce_address.header.length = htons(PCE_ADDRESS_LENGTH_IPV4);
298 pce->pce_address.address.type = htons(PCE_ADDRESS_TYPE_IPV4);
299 pce->pce_address.address.value = ipv4;
300
301 return;
302 }
303
304 static void set_pce_path_scope(uint32_t scope, struct ospf_pce_info *pce)
305 {
306
307 /* Set PCE Scope */
308 pce->pce_scope.header.type = htons(RI_PCE_SUBTLV_PATH_SCOPE);
309 pce->pce_scope.header.length = htons(RI_TLV_LENGTH);
310 pce->pce_scope.value = htonl(scope);
311
312 return;
313 }
314
315 static void set_pce_domain(uint16_t type, uint32_t domain,
316 struct ospf_pce_info *pce)
317 {
318
319 struct ri_pce_subtlv_domain *new;
320
321 /* Create new domain info */
322 new = XCALLOC(MTYPE_OSPF_PCE_PARAMS,
323 sizeof(struct ri_pce_subtlv_domain));
324
325 new->header.type = htons(RI_PCE_SUBTLV_DOMAIN);
326 new->header.length = htons(PCE_ADDRESS_LENGTH_IPV4);
327 new->type = htons(type);
328 new->value = htonl(domain);
329
330 /* Add new domain to the list */
331 listnode_add(pce->pce_domain, new);
332
333 return;
334 }
335
336 static void unset_pce_domain(uint16_t type, uint32_t domain,
337 struct ospf_pce_info *pce)
338 {
339 struct listnode *node;
340 struct ri_pce_subtlv_domain *old = NULL;
341 int found = 0;
342
343 /* Search the corresponding node */
344 for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, old)) {
345 if ((old->type == htons(type))
346 && (old->value == htonl(domain))) {
347 found = 1;
348 break;
349 }
350 }
351
352 /* if found remove it */
353 if (found) {
354 listnode_delete(pce->pce_domain, old);
355
356 /* Finally free the old domain */
357 XFREE(MTYPE_OSPF_PCE_PARAMS, old);
358 }
359 }
360
361 static void set_pce_neighbor(uint16_t type, uint32_t domain,
362 struct ospf_pce_info *pce)
363 {
364
365 struct ri_pce_subtlv_neighbor *new;
366
367 /* Create new neighbor info */
368 new = XCALLOC(MTYPE_OSPF_PCE_PARAMS,
369 sizeof(struct ri_pce_subtlv_neighbor));
370
371 new->header.type = htons(RI_PCE_SUBTLV_NEIGHBOR);
372 new->header.length = htons(PCE_ADDRESS_LENGTH_IPV4);
373 new->type = htons(type);
374 new->value = htonl(domain);
375
376 /* Add new domain to the list */
377 listnode_add(pce->pce_neighbor, new);
378
379 return;
380 }
381
382 static void unset_pce_neighbor(uint16_t type, uint32_t domain,
383 struct ospf_pce_info *pce)
384 {
385 struct listnode *node;
386 struct ri_pce_subtlv_neighbor *old = NULL;
387 int found = 0;
388
389 /* Search the corresponding node */
390 for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, old)) {
391 if ((old->type == htons(type))
392 && (old->value == htonl(domain))) {
393 found = 1;
394 break;
395 }
396 }
397
398 /* if found remove it */
399 if (found) {
400 listnode_delete(pce->pce_neighbor, old);
401
402 /* Finally free the old domain */
403 XFREE(MTYPE_OSPF_PCE_PARAMS, old);
404 }
405 }
406
407 static void set_pce_cap_flag(uint32_t cap, struct ospf_pce_info *pce)
408 {
409
410 /* Set PCE Capabilities flag */
411 pce->pce_cap_flag.header.type = htons(RI_PCE_SUBTLV_CAP_FLAG);
412 pce->pce_cap_flag.header.length = htons(RI_TLV_LENGTH);
413 pce->pce_cap_flag.value = htonl(cap);
414
415 return;
416 }
417
418 /* Segment Routing TLV setter */
419
420 /* Algorithm SubTLV - section 3.1 */
421 static void set_sr_algorithm(uint8_t algo)
422 {
423
424 OspfRI.sr_info.algo.value[0] = algo;
425 for (int i = 1; i < ALGORITHM_COUNT; i++)
426 OspfRI.sr_info.algo.value[i] = SR_ALGORITHM_UNSET;
427
428 /* Set TLV type and length == only 1 Algorithm */
429 TLV_TYPE(OspfRI.sr_info.algo) = htons(RI_SR_TLV_SR_ALGORITHM);
430 TLV_LEN(OspfRI.sr_info.algo) = htons(sizeof(uint8_t));
431 }
432
433 /* unset Aglogithm SubTLV */
434 static void unset_sr_algorithm(uint8_t algo)
435 {
436
437 for (int i = 0; i < ALGORITHM_COUNT; i++)
438 OspfRI.sr_info.algo.value[i] = SR_ALGORITHM_UNSET;
439
440 /* Unset TLV type and length */
441 TLV_TYPE(OspfRI.sr_info.algo) = htons(0);
442 TLV_LEN(OspfRI.sr_info.algo) = htons(0);
443 }
444
445 /* Set Segment Routing Global Block SubTLV - section 3.2 */
446 static void set_sr_global_label_range(struct sr_block srgb)
447 {
448 /* Set Header */
449 TLV_TYPE(OspfRI.sr_info.srgb) = htons(RI_SR_TLV_SRGB_LABEL_RANGE);
450 TLV_LEN(OspfRI.sr_info.srgb) =
451 htons(SUBTLV_SID_LABEL_SIZE + sizeof(uint32_t));
452 /* Set Range Size */
453 OspfRI.sr_info.srgb.size = htonl(SET_RANGE_SIZE(srgb.range_size));
454 /* Set Lower bound label SubTLV */
455 TLV_TYPE(OspfRI.sr_info.srgb.lower) = htons(SUBTLV_SID_LABEL);
456 TLV_LEN(OspfRI.sr_info.srgb.lower) = htons(SID_RANGE_LABEL_LENGTH);
457 OspfRI.sr_info.srgb.lower.value = htonl(SET_LABEL(srgb.lower_bound));
458 }
459
460 /* Unset Segment Routing Global Block SubTLV */
461 static void unset_sr_global_label_range(void)
462 {
463 TLV_TYPE(OspfRI.sr_info.srgb) = htons(0);
464 TLV_LEN(OspfRI.sr_info.srgb) = htons(0);
465 TLV_TYPE(OspfRI.sr_info.srgb.lower) = htons(0);
466 TLV_LEN(OspfRI.sr_info.srgb.lower) = htons(0);
467 }
468
469 /* Set Segment Routing Local Block SubTLV - section 3.2 */
470 static void set_sr_local_label_range(struct sr_block srlb)
471 {
472 /* Set Header */
473 TLV_TYPE(OspfRI.sr_info.srlb) = htons(RI_SR_TLV_SRLB_LABEL_RANGE);
474 TLV_LEN(OspfRI.sr_info.srlb) =
475 htons(SUBTLV_SID_LABEL_SIZE + sizeof(uint32_t));
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 * Followings 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 * Followings 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 * Followings are vty session control functions.
1227 *------------------------------------------------------------------------*/
1228
1229 static uint16_t show_vty_router_cap(struct vty *vty, struct tlv_header *tlvh)
1230 {
1231 struct ri_tlv_router_cap *top = (struct ri_tlv_router_cap *)tlvh;
1232
1233 if (vty != NULL)
1234 vty_out(vty, " Router Capabilities: 0x%x\n",
1235 ntohl(top->value));
1236 else
1237 zlog_debug(" Router Capabilities: 0x%x", ntohl(top->value));
1238
1239 return TLV_SIZE(tlvh);
1240 }
1241
1242 static uint16_t show_vty_pce_subtlv_address(struct vty *vty,
1243 struct tlv_header *tlvh)
1244 {
1245 struct ri_pce_subtlv_address *top =
1246 (struct ri_pce_subtlv_address *)tlvh;
1247
1248 if (ntohs(top->address.type) == PCE_ADDRESS_TYPE_IPV4) {
1249 if (vty != NULL)
1250 vty_out(vty, " PCE Address: %pI4\n",
1251 &top->address.value);
1252 else
1253 zlog_debug(" PCE Address: %pI4",
1254 &top->address.value);
1255 } else {
1256 /* TODO: Add support to IPv6 with inet_ntop() */
1257 if (vty != NULL)
1258 vty_out(vty, " PCE Address: 0x%x\n",
1259 ntohl(top->address.value.s_addr));
1260 else
1261 zlog_debug(" PCE Address: 0x%x",
1262 ntohl(top->address.value.s_addr));
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 if (vty != NULL)
1275 vty_out(vty, " PCE Path Scope: 0x%x\n", ntohl(top->value));
1276 else
1277 zlog_debug(" PCE Path Scope: 0x%x", ntohl(top->value));
1278
1279 return TLV_SIZE(tlvh);
1280 }
1281
1282 static uint16_t show_vty_pce_subtlv_domain(struct vty *vty,
1283 struct tlv_header *tlvh)
1284 {
1285 struct ri_pce_subtlv_domain *top = (struct ri_pce_subtlv_domain *)tlvh;
1286 struct in_addr tmp;
1287
1288 if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) {
1289 tmp.s_addr = top->value;
1290 if (vty != NULL)
1291 vty_out(vty, " PCE domain Area: %pI4\n", &tmp);
1292 else
1293 zlog_debug(" PCE domain Area: %pI4", &tmp);
1294 } else {
1295 if (vty != NULL)
1296 vty_out(vty, " PCE domain AS: %d\n",
1297 ntohl(top->value));
1298 else
1299 zlog_debug(" PCE domain AS: %d", ntohl(top->value));
1300 }
1301 return TLV_SIZE(tlvh);
1302 }
1303
1304 static uint16_t show_vty_pce_subtlv_neighbor(struct vty *vty,
1305 struct tlv_header *tlvh)
1306 {
1307
1308 struct ri_pce_subtlv_neighbor *top =
1309 (struct ri_pce_subtlv_neighbor *)tlvh;
1310 struct in_addr tmp;
1311
1312 if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) {
1313 tmp.s_addr = top->value;
1314 if (vty != NULL)
1315 vty_out(vty, " PCE neighbor Area: %pI4\n",
1316 &tmp);
1317 else
1318 zlog_debug(" PCE neighbor Area: %pI4", &tmp);
1319 } else {
1320 if (vty != NULL)
1321 vty_out(vty, " PCE neighbor AS: %d\n",
1322 ntohl(top->value));
1323 else
1324 zlog_debug(" PCE neighbor AS: %d",
1325 ntohl(top->value));
1326 }
1327 return TLV_SIZE(tlvh);
1328 }
1329
1330 static uint16_t show_vty_pce_subtlv_cap_flag(struct vty *vty,
1331 struct tlv_header *tlvh)
1332 {
1333 struct ri_pce_subtlv_cap_flag *top =
1334 (struct ri_pce_subtlv_cap_flag *)tlvh;
1335
1336 if (vty != NULL)
1337 vty_out(vty, " PCE Capabilities Flag: 0x%x\n",
1338 ntohl(top->value));
1339 else
1340 zlog_debug(" PCE Capabilities Flag: 0x%x",
1341 ntohl(top->value));
1342
1343 return TLV_SIZE(tlvh);
1344 }
1345
1346 static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh)
1347 {
1348 if (vty != NULL)
1349 vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
1350 ntohs(tlvh->type), ntohs(tlvh->length));
1351 else
1352 zlog_debug(" Unknown TLV: [type(0x%x), length(0x%x)]",
1353 ntohs(tlvh->type), ntohs(tlvh->length));
1354
1355 return TLV_SIZE(tlvh);
1356 }
1357
1358 static uint16_t show_vty_pce_info(struct vty *vty, struct tlv_header *ri,
1359 uint32_t total)
1360 {
1361 struct tlv_header *tlvh;
1362 uint16_t sum = 0;
1363
1364 for (tlvh = ri; sum < total; tlvh = TLV_HDR_NEXT(tlvh)) {
1365 switch (ntohs(tlvh->type)) {
1366 case RI_PCE_SUBTLV_ADDRESS:
1367 sum += show_vty_pce_subtlv_address(vty, tlvh);
1368 break;
1369 case RI_PCE_SUBTLV_PATH_SCOPE:
1370 sum += show_vty_pce_subtlv_path_scope(vty, tlvh);
1371 break;
1372 case RI_PCE_SUBTLV_DOMAIN:
1373 sum += show_vty_pce_subtlv_domain(vty, tlvh);
1374 break;
1375 case RI_PCE_SUBTLV_NEIGHBOR:
1376 sum += show_vty_pce_subtlv_neighbor(vty, tlvh);
1377 break;
1378 case RI_PCE_SUBTLV_CAP_FLAG:
1379 sum += show_vty_pce_subtlv_cap_flag(vty, tlvh);
1380 break;
1381 default:
1382 sum += show_vty_unknown_tlv(vty, tlvh);
1383 break;
1384 }
1385 }
1386 return sum;
1387 }
1388
1389 /* Display Segment Routing Algorithm TLV information */
1390 static uint16_t show_vty_sr_algorithm(struct vty *vty, struct tlv_header *tlvh)
1391 {
1392 struct ri_sr_tlv_sr_algorithm *algo =
1393 (struct ri_sr_tlv_sr_algorithm *)tlvh;
1394 int i;
1395
1396 if (vty != NULL) {
1397 vty_out(vty, " Segment Routing Algorithm TLV:\n");
1398 for (i = 0; i < ntohs(algo->header.length); i++) {
1399 switch (algo->value[i]) {
1400 case 0:
1401 vty_out(vty, " Algorithm %d: SPF\n", i);
1402 break;
1403 case 1:
1404 vty_out(vty, " Algorithm %d: Strict SPF\n",
1405 i);
1406 break;
1407 default:
1408 vty_out(vty,
1409 " Algorithm %d: Unknown value %d\n", i,
1410 algo->value[i]);
1411 break;
1412 }
1413 }
1414 }
1415
1416 else {
1417 zlog_debug(" Segment Routing Algorithm TLV:");
1418 for (i = 0; i < ntohs(algo->header.length); i++)
1419 switch (algo->value[i]) {
1420 case 0:
1421 zlog_debug(" Algorithm %d: SPF", i);
1422 break;
1423 case 1:
1424 zlog_debug(" Algorithm %d: Strict SPF", i);
1425 break;
1426 default:
1427 zlog_debug(" Algorithm %d: Unknown value %d",
1428 i, algo->value[i]);
1429 break;
1430 }
1431 }
1432
1433 return TLV_SIZE(tlvh);
1434 }
1435
1436 /* Display Segment Routing SID/Label Range TLV information */
1437 static uint16_t show_vty_sr_range(struct vty *vty, struct tlv_header *tlvh)
1438 {
1439 struct ri_sr_tlv_sid_label_range *range =
1440 (struct ri_sr_tlv_sid_label_range *)tlvh;
1441
1442 if (vty != NULL) {
1443 vty_out(vty,
1444 " Segment Routing %s Range TLV:\n"
1445 " Range Size = %d\n"
1446 " SID Label = %d\n\n",
1447 ntohs(range->header.type) == RI_SR_TLV_SRGB_LABEL_RANGE
1448 ? "Global"
1449 : "Local",
1450 GET_RANGE_SIZE(ntohl(range->size)),
1451 GET_LABEL(ntohl(range->lower.value)));
1452 } else {
1453 zlog_debug(
1454 " Segment Routing %s Range TLV: Range Size = %d SID Label = %d",
1455 ntohs(range->header.type) == RI_SR_TLV_SRGB_LABEL_RANGE
1456 ? "Global"
1457 : "Local",
1458 GET_RANGE_SIZE(ntohl(range->size)),
1459 GET_LABEL(ntohl(range->lower.value)));
1460 }
1461
1462 return TLV_SIZE(tlvh);
1463 }
1464
1465 /* Display Segment Routing Maximum Stack Depth TLV information */
1466 static uint16_t show_vty_sr_msd(struct vty *vty, struct tlv_header *tlvh)
1467 {
1468 struct ri_sr_tlv_node_msd *msd = (struct ri_sr_tlv_node_msd *)tlvh;
1469
1470 if (vty != NULL) {
1471 vty_out(vty,
1472 " Segment Routing MSD TLV:\n"
1473 " Node Maximum Stack Depth = %d\n",
1474 msd->value);
1475 } else {
1476 zlog_debug(
1477 " Segment Routing MSD TLV: Node Maximum Stack Depth = %d",
1478 msd->value);
1479 }
1480
1481 return TLV_SIZE(tlvh);
1482 }
1483
1484 static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa)
1485 {
1486 struct lsa_header *lsah = lsa->data;
1487 struct tlv_header *tlvh;
1488 uint16_t length = 0, sum = 0;
1489
1490 /* Initialize TLV browsing */
1491 length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
1492
1493 for (tlvh = TLV_HDR_TOP(lsah); sum < length;
1494 tlvh = TLV_HDR_NEXT(tlvh)) {
1495 switch (ntohs(tlvh->type)) {
1496 case RI_TLV_CAPABILITIES:
1497 sum += show_vty_router_cap(vty, tlvh);
1498 break;
1499 case RI_TLV_PCE:
1500 tlvh++;
1501 sum += TLV_HDR_SIZE;
1502 sum += show_vty_pce_info(vty, tlvh, length - sum);
1503 break;
1504 case RI_SR_TLV_SR_ALGORITHM:
1505 sum += show_vty_sr_algorithm(vty, tlvh);
1506 break;
1507 case RI_SR_TLV_SRGB_LABEL_RANGE:
1508 case RI_SR_TLV_SRLB_LABEL_RANGE:
1509 sum += show_vty_sr_range(vty, tlvh);
1510 break;
1511 case RI_SR_TLV_NODE_MSD:
1512 sum += show_vty_sr_msd(vty, tlvh);
1513 break;
1514
1515 default:
1516 sum += show_vty_unknown_tlv(vty, tlvh);
1517 break;
1518 }
1519 }
1520
1521 return;
1522 }
1523
1524 static void ospf_router_info_config_write_router(struct vty *vty)
1525 {
1526 struct ospf_pce_info *pce = &OspfRI.pce_info;
1527 struct listnode *node;
1528 struct ri_pce_subtlv_domain *domain;
1529 struct ri_pce_subtlv_neighbor *neighbor;
1530 struct in_addr tmp;
1531
1532 if (!OspfRI.enabled)
1533 return;
1534
1535 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
1536 vty_out(vty, " router-info as\n");
1537 else
1538 vty_out(vty, " router-info area\n");
1539
1540 if (OspfRI.pce_info.enabled) {
1541
1542 if (pce->pce_address.header.type != 0)
1543 vty_out(vty, " pce address %pI4\n",
1544 &pce->pce_address.address.value);
1545
1546 if (pce->pce_cap_flag.header.type != 0)
1547 vty_out(vty, " pce flag 0x%x\n",
1548 ntohl(pce->pce_cap_flag.value));
1549
1550 for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
1551 if (domain->header.type != 0) {
1552 if (domain->type == PCE_DOMAIN_TYPE_AREA) {
1553 tmp.s_addr = domain->value;
1554 vty_out(vty, " pce domain area %pI4\n",
1555 &tmp);
1556 } else {
1557 vty_out(vty, " pce domain as %d\n",
1558 ntohl(domain->value));
1559 }
1560 }
1561 }
1562
1563 for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
1564 if (neighbor->header.type != 0) {
1565 if (neighbor->type == PCE_DOMAIN_TYPE_AREA) {
1566 tmp.s_addr = neighbor->value;
1567 vty_out(vty,
1568 " pce neighbor area %pI4\n",
1569 &tmp);
1570 } else {
1571 vty_out(vty, " pce neighbor as %d\n",
1572 ntohl(neighbor->value));
1573 }
1574 }
1575 }
1576
1577 if (pce->pce_scope.header.type != 0)
1578 vty_out(vty, " pce scope 0x%x\n",
1579 ntohl(OspfRI.pce_info.pce_scope.value));
1580 }
1581 return;
1582 }
1583
1584 /*------------------------------------------------------------------------*
1585 * Followings are vty command functions.
1586 *------------------------------------------------------------------------*/
1587 /* Simple wrapper schedule RI LSA action in function of the scope */
1588 static void ospf_router_info_schedule(enum lsa_opcode opcode)
1589 {
1590 struct listnode *node, *nnode;
1591 struct ospf_ri_area_info *ai;
1592
1593 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
1594 if (CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED))
1595 ospf_router_info_lsa_schedule(NULL, opcode);
1596 else if (opcode == REORIGINATE_THIS_LSA)
1597 ospf_router_info_lsa_schedule(NULL, opcode);
1598 } else {
1599 for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai)) {
1600 if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED))
1601 ospf_router_info_lsa_schedule(ai, opcode);
1602 }
1603 }
1604 }
1605
1606 DEFUN (router_info,
1607 router_info_area_cmd,
1608 "router-info <as|area [A.B.C.D]>",
1609 OSPF_RI_STR
1610 "Enable the Router Information functionality with AS flooding scope\n"
1611 "Enable the Router Information functionality with Area flooding scope\n"
1612 "OSPF area ID in IP format (deprecated)\n")
1613 {
1614 int idx_mode = 1;
1615 uint8_t scope;
1616
1617 if (OspfRI.enabled)
1618 return CMD_SUCCESS;
1619
1620 /* Check and get Area value if present */
1621 if (strncmp(argv[idx_mode]->arg, "as", 2) == 0)
1622 scope = OSPF_OPAQUE_AS_LSA;
1623 else
1624 scope = OSPF_OPAQUE_AREA_LSA;
1625
1626 /* First start to register Router Information callbacks */
1627 if (!OspfRI.registered && (ospf_router_info_register(scope)) != 0) {
1628 vty_out(vty,
1629 "%% Unable to register Router Information callbacks.");
1630 flog_err(
1631 EC_OSPF_INIT_FAIL,
1632 "RI (%s): Unable to register Router Information callbacks. Abort!",
1633 __func__);
1634 return CMD_WARNING_CONFIG_FAILED;
1635 }
1636
1637 OspfRI.enabled = true;
1638
1639 if (IS_DEBUG_OSPF_EVENT)
1640 zlog_debug("RI-> Router Information (%s flooding): OFF -> ON",
1641 OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area"
1642 : "AS");
1643
1644 /*
1645 * Following code is intended to handle two cases;
1646 *
1647 * 1) Router Information was disabled at startup time, but now become
1648 * enabled.
1649 * 2) Router Information was once enabled then disabled, and now enabled
1650 * again.
1651 */
1652
1653 initialize_params(&OspfRI);
1654
1655 /* Originate or Refresh RI LSA if already engaged */
1656 ospf_router_info_schedule(REORIGINATE_THIS_LSA);
1657 return CMD_SUCCESS;
1658 }
1659
1660
1661 DEFUN (no_router_info,
1662 no_router_info_cmd,
1663 "no router-info",
1664 NO_STR
1665 "Disable the Router Information functionality\n")
1666 {
1667
1668 if (!OspfRI.enabled)
1669 return CMD_SUCCESS;
1670
1671 if (IS_DEBUG_OSPF_EVENT)
1672 zlog_debug("RI-> Router Information: ON -> OFF");
1673
1674 ospf_router_info_schedule(FLUSH_THIS_LSA);
1675
1676 OspfRI.enabled = false;
1677
1678 return CMD_SUCCESS;
1679 }
1680
1681 static int ospf_ri_enabled(struct vty *vty)
1682 {
1683 if (OspfRI.enabled)
1684 return 1;
1685
1686 if (vty)
1687 vty_out(vty, "%% OSPF RI is not turned on\n");
1688
1689 return 0;
1690 }
1691
1692 DEFUN (pce_address,
1693 pce_address_cmd,
1694 "pce address A.B.C.D",
1695 PCE_STR
1696 "Stable IP address of the PCE\n"
1697 "PCE address in IPv4 address format\n")
1698 {
1699 int idx_ipv4 = 2;
1700 struct in_addr value;
1701 struct ospf_pce_info *pi = &OspfRI.pce_info;
1702
1703 if (!ospf_ri_enabled(vty))
1704 return CMD_WARNING_CONFIG_FAILED;
1705
1706 if (!inet_aton(argv[idx_ipv4]->arg, &value)) {
1707 vty_out(vty, "Please specify PCE Address by A.B.C.D\n");
1708 return CMD_WARNING_CONFIG_FAILED;
1709 }
1710
1711 if (ntohs(pi->pce_address.header.type) == 0
1712 || ntohl(pi->pce_address.address.value.s_addr)
1713 != ntohl(value.s_addr)) {
1714
1715 set_pce_address(value, pi);
1716
1717 /* Refresh RI LSA if already engaged */
1718 ospf_router_info_schedule(REFRESH_THIS_LSA);
1719 }
1720
1721 return CMD_SUCCESS;
1722 }
1723
1724 DEFUN (no_pce_address,
1725 no_pce_address_cmd,
1726 "no pce address [A.B.C.D]",
1727 NO_STR
1728 PCE_STR
1729 "Disable PCE address\n"
1730 "PCE address in IPv4 address format\n")
1731 {
1732
1733 unset_param(&OspfRI.pce_info.pce_address);
1734
1735 /* Refresh RI LSA if already engaged */
1736 ospf_router_info_schedule(REFRESH_THIS_LSA);
1737
1738 return CMD_SUCCESS;
1739 }
1740
1741 DEFUN (pce_path_scope,
1742 pce_path_scope_cmd,
1743 "pce scope BITPATTERN",
1744 PCE_STR
1745 "Path scope visibilities of the PCE for path computation\n"
1746 "32-bit Hexadecimal value\n")
1747 {
1748 int idx_bitpattern = 2;
1749 uint32_t scope;
1750 struct ospf_pce_info *pi = &OspfRI.pce_info;
1751
1752 if (!ospf_ri_enabled(vty))
1753 return CMD_WARNING_CONFIG_FAILED;
1754
1755 if (sscanf(argv[idx_bitpattern]->arg, "0x%x", &scope) != 1) {
1756 vty_out(vty, "pce_path_scope: fscanf: %s\n",
1757 safe_strerror(errno));
1758 return CMD_WARNING_CONFIG_FAILED;
1759 }
1760
1761 if (ntohl(pi->pce_scope.header.type) == 0
1762 || scope != pi->pce_scope.value) {
1763 set_pce_path_scope(scope, pi);
1764
1765 /* Refresh RI LSA if already engaged */
1766 ospf_router_info_schedule(REFRESH_THIS_LSA);
1767 }
1768
1769 return CMD_SUCCESS;
1770 }
1771
1772 DEFUN (no_pce_path_scope,
1773 no_pce_path_scope_cmd,
1774 "no pce scope [BITPATTERN]",
1775 NO_STR
1776 PCE_STR
1777 "Disable PCE path scope\n"
1778 "32-bit Hexadecimal value\n")
1779 {
1780
1781 unset_param(&OspfRI.pce_info.pce_address);
1782
1783 /* Refresh RI LSA if already engaged */
1784 ospf_router_info_schedule(REFRESH_THIS_LSA);
1785
1786 return CMD_SUCCESS;
1787 }
1788
1789 DEFUN (pce_domain,
1790 pce_domain_cmd,
1791 "pce domain as (0-65535)",
1792 PCE_STR
1793 "Configure PCE domain AS number\n"
1794 "AS number where the PCE as visibilities for path computation\n"
1795 "AS number in decimal <0-65535>\n")
1796 {
1797 int idx_number = 3;
1798
1799 uint32_t as;
1800 struct ospf_pce_info *pce = &OspfRI.pce_info;
1801 struct listnode *node;
1802 struct ri_pce_subtlv_domain *domain;
1803
1804 if (!ospf_ri_enabled(vty))
1805 return CMD_WARNING_CONFIG_FAILED;
1806
1807 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
1808 vty_out(vty, "pce_domain: fscanf: %s\n", safe_strerror(errno));
1809 return CMD_WARNING_CONFIG_FAILED;
1810 }
1811
1812 /* Check if the domain is not already in the domain list */
1813 for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
1814 if (ntohl(domain->header.type) == 0 && as == domain->value)
1815 return CMD_SUCCESS;
1816 }
1817
1818 /* Create new domain if not found */
1819 set_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce);
1820
1821 /* Refresh RI LSA if already engaged */
1822 ospf_router_info_schedule(REFRESH_THIS_LSA);
1823
1824 return CMD_SUCCESS;
1825 }
1826
1827 DEFUN (no_pce_domain,
1828 no_pce_domain_cmd,
1829 "no pce domain as (0-65535)",
1830 NO_STR
1831 PCE_STR
1832 "Disable PCE domain AS number\n"
1833 "AS number where the PCE as visibilities for path computation\n"
1834 "AS number in decimal <0-65535>\n")
1835 {
1836 int idx_number = 4;
1837
1838 uint32_t as;
1839 struct ospf_pce_info *pce = &OspfRI.pce_info;
1840
1841 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
1842 vty_out(vty, "no_pce_domain: fscanf: %s\n",
1843 safe_strerror(errno));
1844 return CMD_WARNING_CONFIG_FAILED;
1845 }
1846
1847 /* Unset corresponding PCE domain */
1848 unset_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce);
1849
1850 /* Refresh RI LSA if already engaged */
1851 ospf_router_info_schedule(REFRESH_THIS_LSA);
1852
1853 return CMD_SUCCESS;
1854 }
1855
1856 DEFUN (pce_neigbhor,
1857 pce_neighbor_cmd,
1858 "pce neighbor as (0-65535)",
1859 PCE_STR
1860 "Configure PCE neighbor domain AS number\n"
1861 "AS number of PCE neighbors\n"
1862 "AS number in decimal <0-65535>\n")
1863 {
1864 int idx_number = 3;
1865
1866 uint32_t as;
1867 struct ospf_pce_info *pce = &OspfRI.pce_info;
1868 struct listnode *node;
1869 struct ri_pce_subtlv_neighbor *neighbor;
1870
1871 if (!ospf_ri_enabled(vty))
1872 return CMD_WARNING_CONFIG_FAILED;
1873
1874 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
1875 vty_out(vty, "pce_neighbor: fscanf: %s\n",
1876 safe_strerror(errno));
1877 return CMD_WARNING_CONFIG_FAILED;
1878 }
1879
1880 /* Check if the domain is not already in the domain list */
1881 for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
1882 if (ntohl(neighbor->header.type) == 0 && as == neighbor->value)
1883 return CMD_SUCCESS;
1884 }
1885
1886 /* Create new domain if not found */
1887 set_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce);
1888
1889 /* Refresh RI LSA if already engaged */
1890 ospf_router_info_schedule(REFRESH_THIS_LSA);
1891
1892 return CMD_SUCCESS;
1893 }
1894
1895 DEFUN (no_pce_neighbor,
1896 no_pce_neighbor_cmd,
1897 "no pce neighbor as (0-65535)",
1898 NO_STR
1899 PCE_STR
1900 "Disable PCE neighbor AS number\n"
1901 "AS number of PCE neighbor\n"
1902 "AS number in decimal <0-65535>\n")
1903 {
1904 int idx_number = 4;
1905
1906 uint32_t as;
1907 struct ospf_pce_info *pce = &OspfRI.pce_info;
1908
1909 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
1910 vty_out(vty, "no_pce_neighbor: fscanf: %s\n",
1911 safe_strerror(errno));
1912 return CMD_WARNING_CONFIG_FAILED;
1913 }
1914
1915 /* Unset corresponding PCE domain */
1916 unset_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce);
1917
1918 /* Refresh RI LSA if already engaged */
1919 ospf_router_info_schedule(REFRESH_THIS_LSA);
1920
1921 return CMD_SUCCESS;
1922 }
1923
1924 DEFUN (pce_cap_flag,
1925 pce_cap_flag_cmd,
1926 "pce flag BITPATTERN",
1927 PCE_STR
1928 "Capabilities of the PCE for path computation\n"
1929 "32-bit Hexadecimal value\n")
1930 {
1931 int idx_bitpattern = 2;
1932
1933 uint32_t cap;
1934 struct ospf_pce_info *pce = &OspfRI.pce_info;
1935
1936 if (!ospf_ri_enabled(vty))
1937 return CMD_WARNING_CONFIG_FAILED;
1938
1939 if (sscanf(argv[idx_bitpattern]->arg, "0x%x", &cap) != 1) {
1940 vty_out(vty, "pce_cap_flag: fscanf: %s\n",
1941 safe_strerror(errno));
1942 return CMD_WARNING_CONFIG_FAILED;
1943 }
1944
1945 if (ntohl(pce->pce_cap_flag.header.type) == 0
1946 || cap != pce->pce_cap_flag.value) {
1947 set_pce_cap_flag(cap, pce);
1948
1949 /* Refresh RI LSA if already engaged */
1950 ospf_router_info_schedule(REFRESH_THIS_LSA);
1951 }
1952
1953 return CMD_SUCCESS;
1954 }
1955
1956 DEFUN (no_pce_cap_flag,
1957 no_pce_cap_flag_cmd,
1958 "no pce flag",
1959 NO_STR
1960 PCE_STR
1961 "Disable PCE capabilities\n")
1962 {
1963
1964 unset_param(&OspfRI.pce_info.pce_cap_flag);
1965
1966 /* Refresh RI LSA if already engaged */
1967 ospf_router_info_schedule(REFRESH_THIS_LSA);
1968
1969 return CMD_SUCCESS;
1970 }
1971
1972 DEFUN (show_ip_ospf_router_info,
1973 show_ip_ospf_router_info_cmd,
1974 "show ip ospf router-info",
1975 SHOW_STR
1976 IP_STR
1977 OSPF_STR
1978 "Router Information\n")
1979 {
1980
1981 if (OspfRI.enabled) {
1982 vty_out(vty, "--- Router Information parameters ---\n");
1983 show_vty_router_cap(vty, &OspfRI.router_cap.header);
1984 } else {
1985 if (vty != NULL)
1986 vty_out(vty,
1987 " Router Information is disabled on this router\n");
1988 }
1989 return CMD_SUCCESS;
1990 }
1991
1992 DEFUN (show_ip_opsf_router_info_pce,
1993 show_ip_ospf_router_info_pce_cmd,
1994 "show ip ospf router-info pce",
1995 SHOW_STR
1996 IP_STR
1997 OSPF_STR
1998 "Router Information\n"
1999 "PCE information\n")
2000 {
2001
2002 struct ospf_pce_info *pce = &OspfRI.pce_info;
2003 struct listnode *node;
2004 struct ri_pce_subtlv_domain *domain;
2005 struct ri_pce_subtlv_neighbor *neighbor;
2006
2007 if ((OspfRI.enabled) && (OspfRI.pce_info.enabled)) {
2008 vty_out(vty, "--- PCE parameters ---\n");
2009
2010 if (pce->pce_address.header.type != 0)
2011 show_vty_pce_subtlv_address(vty,
2012 &pce->pce_address.header);
2013
2014 if (pce->pce_scope.header.type != 0)
2015 show_vty_pce_subtlv_path_scope(vty,
2016 &pce->pce_scope.header);
2017
2018 for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
2019 if (domain->header.type != 0)
2020 show_vty_pce_subtlv_domain(vty,
2021 &domain->header);
2022 }
2023
2024 for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
2025 if (neighbor->header.type != 0)
2026 show_vty_pce_subtlv_neighbor(vty,
2027 &neighbor->header);
2028 }
2029
2030 if (pce->pce_cap_flag.header.type != 0)
2031 show_vty_pce_subtlv_cap_flag(vty,
2032 &pce->pce_cap_flag.header);
2033
2034 } else {
2035 vty_out(vty, " PCE info is disabled on this router\n");
2036 }
2037
2038 return CMD_SUCCESS;
2039 }
2040
2041 /* Install new CLI commands */
2042 static void ospf_router_info_register_vty(void)
2043 {
2044 install_element(VIEW_NODE, &show_ip_ospf_router_info_cmd);
2045 install_element(VIEW_NODE, &show_ip_ospf_router_info_pce_cmd);
2046
2047 install_element(OSPF_NODE, &router_info_area_cmd);
2048 install_element(OSPF_NODE, &no_router_info_cmd);
2049 install_element(OSPF_NODE, &pce_address_cmd);
2050 install_element(OSPF_NODE, &no_pce_address_cmd);
2051 install_element(OSPF_NODE, &pce_path_scope_cmd);
2052 install_element(OSPF_NODE, &no_pce_path_scope_cmd);
2053 install_element(OSPF_NODE, &pce_domain_cmd);
2054 install_element(OSPF_NODE, &no_pce_domain_cmd);
2055 install_element(OSPF_NODE, &pce_neighbor_cmd);
2056 install_element(OSPF_NODE, &no_pce_neighbor_cmd);
2057 install_element(OSPF_NODE, &pce_cap_flag_cmd);
2058 install_element(OSPF_NODE, &no_pce_cap_flag_cmd);
2059
2060 return;
2061 }