]> git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_ri.c
Merge pull request #7096 from gpnaveen/ospf_asbr_summarisation
[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_IPV4_SIZE);
298 pce->pce_address.address.type = htons(PCE_ADDRESS_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_IPV4_SIZE);
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_IPV4_SIZE);
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) = htons(RI_SR_TLV_LABEL_RANGE_SIZE);
451 /* Set Range Size */
452 OspfRI.sr_info.srgb.size = htonl(SET_RANGE_SIZE(srgb.range_size));
453 /* Set Lower bound label SubTLV */
454 TLV_TYPE(OspfRI.sr_info.srgb.lower) = htons(SUBTLV_SID_LABEL);
455 TLV_LEN(OspfRI.sr_info.srgb.lower) = htons(SID_RANGE_LABEL_LENGTH);
456 OspfRI.sr_info.srgb.lower.value = htonl(SET_LABEL(srgb.lower_bound));
457 }
458
459 /* Unset Segment Routing Global Block SubTLV */
460 static void unset_sr_global_label_range(void)
461 {
462 TLV_TYPE(OspfRI.sr_info.srgb) = htons(0);
463 TLV_LEN(OspfRI.sr_info.srgb) = htons(0);
464 TLV_TYPE(OspfRI.sr_info.srgb.lower) = htons(0);
465 TLV_LEN(OspfRI.sr_info.srgb.lower) = htons(0);
466 }
467
468 /* Set Segment Routing Local Block SubTLV - section 3.2 */
469 static void set_sr_local_label_range(struct sr_block srlb)
470 {
471 /* Set Header */
472 TLV_TYPE(OspfRI.sr_info.srlb) = htons(RI_SR_TLV_SRLB_LABEL_RANGE);
473 TLV_LEN(OspfRI.sr_info.srlb) = htons(RI_SR_TLV_LABEL_RANGE_SIZE);
474 /* Set Range Size */
475 OspfRI.sr_info.srlb.size = htonl(SET_RANGE_SIZE(srlb.range_size));
476 /* Set Lower bound label SubTLV */
477 TLV_TYPE(OspfRI.sr_info.srlb.lower) = htons(SUBTLV_SID_LABEL);
478 TLV_LEN(OspfRI.sr_info.srlb.lower) = htons(SID_RANGE_LABEL_LENGTH);
479 OspfRI.sr_info.srlb.lower.value = htonl(SET_LABEL(srlb.lower_bound));
480 }
481
482 /* Unset Segment Routing Local Block SubTLV */
483 static void unset_sr_local_label_range(void)
484 {
485 TLV_TYPE(OspfRI.sr_info.srlb) = htons(0);
486 TLV_LEN(OspfRI.sr_info.srlb) = htons(0);
487 TLV_TYPE(OspfRI.sr_info.srlb.lower) = htons(0);
488 TLV_LEN(OspfRI.sr_info.srlb.lower) = htons(0);
489 }
490
491 /* Set Maximum Stack Depth for this router */
492 static void set_sr_node_msd(uint8_t msd)
493 {
494 TLV_TYPE(OspfRI.sr_info.msd) = htons(RI_SR_TLV_NODE_MSD);
495 TLV_LEN(OspfRI.sr_info.msd) = htons(sizeof(uint32_t));
496 OspfRI.sr_info.msd.value = msd;
497 }
498
499 /* Unset this router MSD */
500 static void unset_sr_node_msd(void)
501 {
502 TLV_TYPE(OspfRI.sr_info.msd) = htons(0);
503 TLV_LEN(OspfRI.sr_info.msd) = htons(0);
504 }
505
506 static void unset_param(void *tlv_buffer)
507 {
508 struct tlv_header *tlv = (struct tlv_header *)tlv_buffer;
509
510 tlv->type = 0;
511 /* Fill the Value to 0 */
512 memset(TLV_DATA(tlv_buffer), 0, TLV_BODY_SIZE(tlv));
513 tlv->length = 0;
514
515 return;
516 }
517
518 static void initialize_params(struct ospf_router_info *ori)
519 {
520 uint32_t cap = 0;
521 struct ospf *top;
522 struct listnode *node, *nnode;
523 struct ospf_area *area;
524 struct ospf_ri_area_info *new;
525
526 /*
527 * Initialize default Router Information Capabilities.
528 */
529 cap = RI_TE_SUPPORT;
530
531 set_router_info_capabilities(&ori->router_cap, cap);
532
533 /* If Area address is not null and exist, retrieve corresponding
534 * structure */
535 top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
536 zlog_info("RI (%s): Initialize Router Info for %s scope", __func__,
537 OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS");
538
539 /* Try to get available Area's context from ospf at this step.
540 * Do it latter if not available */
541 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
542 if (!list_isempty(OspfRI.area_info))
543 list_delete_all_node(OspfRI.area_info);
544 for (ALL_LIST_ELEMENTS(top->areas, node, nnode, area)) {
545 zlog_debug("RI (%s): Add area %pI4 to Router Information",
546 __func__, &area->area_id);
547 new = XCALLOC(MTYPE_OSPF_ROUTER_INFO,
548 sizeof(struct ospf_ri_area_info));
549 new->area = area;
550 new->flags = RIFLG_LSA_INACTIVE;
551 listnode_add(OspfRI.area_info, new);
552 }
553 }
554
555 /*
556 * Initialize default PCE Information values
557 */
558 /* PCE address == OSPF Router ID */
559 set_pce_address(top->router_id, &ori->pce_info);
560
561 /* PCE scope */
562 cap = 7; /* Set L, R and Rd bits to one = intra & inter-area path
563 computation */
564 set_pce_path_scope(cap, &ori->pce_info);
565
566 /* PCE Capabilities */
567 cap = PCE_CAP_BIDIRECTIONAL | PCE_CAP_DIVERSE_PATH | PCE_CAP_OBJECTIVES
568 | PCE_CAP_ADDITIVE | PCE_CAP_MULTIPLE_REQ;
569 set_pce_cap_flag(cap, &ori->pce_info);
570
571 return;
572 }
573
574 static int is_mandated_params_set(struct ospf_router_info *ori)
575 {
576 int rc = 0;
577
578 if (ori == NULL)
579 return rc;
580
581 if (ntohs(ori->router_cap.header.type) == 0)
582 return rc;
583
584 if ((ntohs(ori->pce_info.pce_header.header.type) == RI_TLV_PCE)
585 && (ntohs(ori->pce_info.pce_address.header.type) == 0)
586 && (ntohs(ori->pce_info.pce_cap_flag.header.type) == 0))
587 return rc;
588
589 if ((ori->sr_info.enabled) && (ntohs(TLV_TYPE(ori->sr_info.algo)) == 0)
590 && (ntohs(TLV_TYPE(ori->sr_info.srgb)) == 0))
591 return rc;
592
593 rc = 1;
594
595 return rc;
596 }
597
598 /*
599 * Used by Segment Routing to set new TLVs and Sub-TLVs values
600 *
601 * @param enable To activate or not Segment Routing router Information flooding
602 * @param srn Self Segment Routing node
603 *
604 * @return none
605 */
606 void ospf_router_info_update_sr(bool enable, struct sr_node *srn)
607 {
608 struct listnode *node, *nnode;
609 struct ospf_ri_area_info *ai;
610
611 /* First, check if Router Information is registered or not */
612 if (!OspfRI.registered)
613 ospf_router_info_register(OSPF_OPAQUE_AREA_LSA);
614
615 /* Verify that scope is AREA */
616 if (OspfRI.scope != OSPF_OPAQUE_AREA_LSA) {
617 zlog_err(
618 "RI (%s): Router Info is %s flooding: Change scope to Area flooding for Segment Routing",
619 __func__,
620 OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS");
621 return;
622 }
623
624 /* Then, activate and initialize Router Information if necessary */
625 if (!OspfRI.enabled) {
626 OspfRI.enabled = true;
627 initialize_params(&OspfRI);
628 }
629
630 /* Check that SR node is valid */
631 if (srn == NULL)
632 return;
633
634 if (IS_DEBUG_OSPF_SR)
635 zlog_debug("RI (%s): %s Routing Information for Segment Routing",
636 __func__, enable ? "Enable" : "Disable");
637
638 /* Unset or Set SR parameters */
639 if (!enable) {
640 unset_sr_algorithm(SR_ALGORITHM_SPF);
641 unset_sr_global_label_range();
642 unset_sr_local_label_range();
643 unset_sr_node_msd();
644 OspfRI.sr_info.enabled = false;
645 } else {
646 // Only SR_ALGORITHM_SPF is supported
647 set_sr_algorithm(SR_ALGORITHM_SPF);
648 set_sr_global_label_range(srn->srgb);
649 set_sr_local_label_range(srn->srlb);
650 if (srn->msd != 0)
651 set_sr_node_msd(srn->msd);
652 else
653 unset_sr_node_msd();
654 OspfRI.sr_info.enabled = true;
655 }
656
657 /* Refresh if already engaged or originate RI LSA */
658 for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai)) {
659 if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED))
660 ospf_router_info_lsa_schedule(ai, REFRESH_THIS_LSA);
661 else
662 ospf_router_info_lsa_schedule(ai,
663 REORIGINATE_THIS_LSA);
664
665 }
666 }
667
668 /*------------------------------------------------------------------------*
669 * Followings are callback functions against generic Opaque-LSAs handling.
670 *------------------------------------------------------------------------*/
671 static void ospf_router_info_ism_change(struct ospf_interface *oi,
672 int old_state)
673 {
674
675 struct ospf_ri_area_info *ai;
676
677 /* Collect area information */
678 ai = lookup_by_area(oi->area);
679
680 /* Check if area is not yet registered */
681 if (ai != NULL)
682 return;
683
684 /* Add this new area to the list */
685 ai = XCALLOC(MTYPE_OSPF_ROUTER_INFO, sizeof(struct ospf_ri_area_info));
686 ai->area = oi->area;
687 ai->flags = RIFLG_LSA_INACTIVE;
688 listnode_add(OspfRI.area_info, ai);
689
690 return;
691 }
692
693 /*------------------------------------------------------------------------*
694 * Followings are OSPF protocol processing functions for ROUTER INFORMATION
695 *------------------------------------------------------------------------*/
696
697 static void build_tlv_header(struct stream *s, struct tlv_header *tlvh)
698 {
699
700 stream_put(s, tlvh, sizeof(struct tlv_header));
701 return;
702 }
703
704 static void build_tlv(struct stream *s, struct tlv_header *tlvh)
705 {
706
707 if (ntohs(tlvh->type) != 0) {
708 build_tlv_header(s, tlvh);
709 stream_put(s, TLV_DATA(tlvh), TLV_BODY_SIZE(tlvh));
710 }
711 return;
712 }
713
714 static void ospf_router_info_lsa_body_set(struct stream *s)
715 {
716
717 struct listnode *node;
718 struct ri_pce_subtlv_domain *domain;
719 struct ri_pce_subtlv_neighbor *neighbor;
720
721 /* Build Router Information TLV */
722 build_tlv(s, &OspfRI.router_cap.header);
723
724 /* Build Segment Routing TLVs if enabled */
725 if (OspfRI.sr_info.enabled) {
726 /* Build Algorithm TLV */
727 build_tlv(s, &TLV_HDR(OspfRI.sr_info.algo));
728 /* Build SRGB TLV */
729 build_tlv(s, &TLV_HDR(OspfRI.sr_info.srgb));
730 /* Build SRLB TLV */
731 build_tlv(s, &TLV_HDR(OspfRI.sr_info.srlb));
732 /* Build MSD TLV */
733 build_tlv(s, &TLV_HDR(OspfRI.sr_info.msd));
734 }
735
736 /* Add RI PCE TLV if it is set */
737 if (OspfRI.pce_info.enabled) {
738
739 /* Compute PCE Info header first */
740 set_pce_header(&OspfRI.pce_info);
741
742 /* Build PCE TLV */
743 build_tlv_header(s, &OspfRI.pce_info.pce_header.header);
744
745 /* Build PCE address sub-tlv */
746 build_tlv(s, &OspfRI.pce_info.pce_address.header);
747
748 /* Build PCE path scope sub-tlv */
749 build_tlv(s, &OspfRI.pce_info.pce_scope.header);
750
751 /* Build PCE domain sub-tlv */
752 for (ALL_LIST_ELEMENTS_RO(OspfRI.pce_info.pce_domain, node,
753 domain))
754 build_tlv(s, &domain->header);
755
756 /* Build PCE neighbor sub-tlv */
757 for (ALL_LIST_ELEMENTS_RO(OspfRI.pce_info.pce_neighbor, node,
758 neighbor))
759 build_tlv(s, &neighbor->header);
760
761 /* Build PCE cap flag sub-tlv */
762 build_tlv(s, &OspfRI.pce_info.pce_cap_flag.header);
763 }
764
765 return;
766 }
767
768 /* Create new opaque-LSA. */
769 static struct ospf_lsa *ospf_router_info_lsa_new(struct ospf_area *area)
770 {
771 struct ospf *top;
772 struct stream *s;
773 struct lsa_header *lsah;
774 struct ospf_lsa *new = NULL;
775 uint8_t options, lsa_type;
776 struct in_addr lsa_id;
777 uint32_t tmp;
778 uint16_t length;
779
780 /* Create a stream for LSA. */
781 s = stream_new(OSPF_MAX_LSA_SIZE);
782
783 lsah = (struct lsa_header *)STREAM_DATA(s);
784
785 options = OSPF_OPTION_E; /* Enable AS external as we flood RI with
786 Opaque Type 11 */
787 options |= OSPF_OPTION_O; /* Don't forget this :-) */
788
789 lsa_type = OspfRI.scope;
790 /* LSA ID == 0 for Router Information see RFC 4970 */
791 tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_ROUTER_INFORMATION_LSA, 0);
792 lsa_id.s_addr = htonl(tmp);
793
794 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
795 zlog_debug(
796 "LSA[Type%d:%pI4]: Create an Opaque-LSA/ROUTER INFORMATION instance",
797 lsa_type, &lsa_id);
798
799 top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
800
801 /* Set opaque-LSA header fields. */
802 lsa_header_set(s, options, lsa_type, lsa_id, top->router_id);
803
804 /* Set opaque-LSA body fields. */
805 ospf_router_info_lsa_body_set(s);
806
807 /* Set length. */
808 length = stream_get_endp(s);
809 lsah->length = htons(length);
810
811 /* Now, create an OSPF LSA instance. */
812 new = ospf_lsa_new_and_data(length);
813
814 new->area = area;
815
816 if (new->area && new->area->ospf)
817 new->vrf_id = new->area->ospf->vrf_id;
818 else
819 new->vrf_id = VRF_DEFAULT;
820
821 SET_FLAG(new->flags, OSPF_LSA_SELF);
822 memcpy(new->data, lsah, length);
823 stream_free(s);
824
825 return new;
826 }
827
828 static int ospf_router_info_lsa_originate_as(void *arg)
829 {
830 struct ospf_lsa *new;
831 struct ospf *top;
832 int rc = -1;
833 vrf_id_t vrf_id = VRF_DEFAULT;
834
835 /* Sanity Check */
836 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
837 flog_warn(
838 EC_OSPF_LSA_INSTALL_FAILURE,
839 "RI (%s): wrong flooding scope AREA instead of AS ?",
840 __func__);
841 return rc;
842 }
843
844 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
845 new = ospf_router_info_lsa_new(NULL);
846 new->vrf_id = VRF_DEFAULT;
847 top = (struct ospf *)arg;
848
849 /* Check ospf info */
850 if (top == NULL) {
851 zlog_debug("RI (%s): ospf instance not found for vrf id %u",
852 __func__, vrf_id);
853 ospf_lsa_unlock(&new);
854 return rc;
855 }
856
857 /* Install this LSA into LSDB. */
858 if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
859 flog_warn(
860 EC_OSPF_LSA_INSTALL_FAILURE,
861 "RI (%s): ospf_lsa_install() ?", __func__);
862 ospf_lsa_unlock(&new);
863 return rc;
864 }
865
866 /* Update new LSA origination count. */
867 top->lsa_originate_count++;
868
869 /* Flood new LSA through AREA or AS. */
870 SET_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED);
871 ospf_flood_through_as(top, NULL /*nbr */, new);
872
873 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
874 zlog_debug(
875 "LSA[Type%d:%pI4]: Originate Opaque-LSA/ROUTER INFORMATION",
876 new->data->type, &new->data->id);
877 ospf_lsa_header_dump(new->data);
878 }
879
880 rc = 0;
881 return rc;
882 }
883
884 static int ospf_router_info_lsa_originate_area(void *arg)
885 {
886 struct ospf_lsa *new;
887 struct ospf *top;
888 struct ospf_ri_area_info *ai = NULL;
889 int rc = -1;
890 vrf_id_t vrf_id = VRF_DEFAULT;
891
892 /* Sanity Check */
893 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
894 flog_warn(
895 EC_OSPF_LSA_INSTALL_FAILURE,
896 "RI (%s): wrong flooding scope AS instead of AREA ?",
897 __func__);
898 return rc;
899 }
900
901 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
902 ai = lookup_by_area((struct ospf_area *)arg);
903 if (ai == NULL) {
904 zlog_debug(
905 "RI (%s): There is no context for this Router Information. Stop processing",
906 __func__);
907 return rc;
908 }
909 if (ai->area->ospf) {
910 vrf_id = ai->area->ospf->vrf_id;
911 top = ai->area->ospf;
912 } else {
913 top = ospf_lookup_by_vrf_id(vrf_id);
914 }
915 new = ospf_router_info_lsa_new(ai->area);
916 new->vrf_id = vrf_id;
917
918 /* Check ospf info */
919 if (top == NULL) {
920 zlog_debug("RI (%s): ospf instance not found for vrf id %u",
921 __func__, vrf_id);
922 ospf_lsa_unlock(&new);
923 return rc;
924 }
925
926 /* Install this LSA into LSDB. */
927 if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
928 flog_warn(
929 EC_OSPF_LSA_INSTALL_FAILURE,
930 "RI (%s): ospf_lsa_install() ?", __func__);
931 ospf_lsa_unlock(&new);
932 return rc;
933 }
934
935 /* Update new LSA origination count. */
936 top->lsa_originate_count++;
937
938 /* Flood new LSA through AREA or AS. */
939 SET_FLAG(ai->flags, RIFLG_LSA_ENGAGED);
940 ospf_flood_through_area(ai->area, NULL /*nbr */, new);
941
942 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
943 zlog_debug(
944 "LSA[Type%d:%pI4]: Originate Opaque-LSA/ROUTER INFORMATION",
945 new->data->type, &new->data->id);
946 ospf_lsa_header_dump(new->data);
947 }
948
949 rc = 0;
950 return rc;
951 }
952
953 static int ospf_router_info_lsa_originate(void *arg)
954 {
955
956 struct ospf_ri_area_info *ai;
957 int rc = -1;
958
959 if (!OspfRI.enabled) {
960 zlog_info("RI (%s): ROUTER INFORMATION is disabled now.",
961 __func__);
962 rc = 0; /* This is not an error case. */
963 return rc;
964 }
965
966 /* Check if Router Information LSA is already engaged */
967 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
968 if ((CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED))
969 && (CHECK_FLAG(OspfRI.as_flags,
970 RIFLG_LSA_FORCED_REFRESH))) {
971 UNSET_FLAG(OspfRI.as_flags, RIFLG_LSA_FORCED_REFRESH);
972 ospf_router_info_lsa_schedule(NULL, REFRESH_THIS_LSA);
973 rc = 0;
974 return rc;
975 }
976 } else {
977 ai = lookup_by_area((struct ospf_area *)arg);
978 if (ai == NULL) {
979 flog_warn(
980 EC_OSPF_LSA,
981 "RI (%s): Missing area information", __func__);
982 return rc;
983 }
984 if ((CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED))
985 && (CHECK_FLAG(ai->flags, RIFLG_LSA_FORCED_REFRESH))) {
986 UNSET_FLAG(ai->flags, RIFLG_LSA_FORCED_REFRESH);
987 ospf_router_info_lsa_schedule(ai, REFRESH_THIS_LSA);
988 rc = 0;
989 return rc;
990 }
991 }
992
993 /* Router Information is not yet Engaged, check parameters */
994 if (!is_mandated_params_set(&OspfRI))
995 flog_warn(
996 EC_OSPF_LSA,
997 "RI (%s): lacks mandated ROUTER INFORMATION parameters",
998 __func__);
999
1000 /* Ok, let's try to originate an LSA */
1001 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
1002 rc = ospf_router_info_lsa_originate_as(arg);
1003 else
1004 rc = ospf_router_info_lsa_originate_area(arg);
1005
1006 return rc;
1007 }
1008
1009 static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa)
1010 {
1011 struct ospf_ri_area_info *ai = NULL;
1012 struct ospf_lsa *new = NULL;
1013 struct ospf *top;
1014
1015 if (!OspfRI.enabled) {
1016 /*
1017 * This LSA must have flushed before due to ROUTER INFORMATION
1018 * status change.
1019 * It seems a slip among routers in the routing domain.
1020 */
1021 zlog_info("RI (%s): ROUTER INFORMATION is disabled now.",
1022 __func__);
1023 lsa->data->ls_age =
1024 htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
1025 }
1026
1027 /* Verify that the Router Information ID is supported */
1028 if (GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)) != 0) {
1029 flog_warn(
1030 EC_OSPF_LSA,
1031 "RI (%s): Unsupported Router Information ID",
1032 __func__);
1033 return NULL;
1034 }
1035
1036 /* Process LSA depending of the flooding scope */
1037 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
1038 /* Get context AREA context */
1039 ai = lookup_by_area(lsa->area);
1040 if (ai == NULL) {
1041 flog_warn(
1042 EC_OSPF_LSA,
1043 "RI (%s): No associated Area", __func__);
1044 return NULL;
1045 }
1046 /* Flush LSA, if the lsa's age reached to MaxAge. */
1047 if (IS_LSA_MAXAGE(lsa)) {
1048 UNSET_FLAG(ai->flags, RIFLG_LSA_ENGAGED);
1049 ospf_opaque_lsa_flush_schedule(lsa);
1050 return NULL;
1051 }
1052 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
1053 new = ospf_router_info_lsa_new(ai->area);
1054 new->data->ls_seqnum = lsa_seqnum_increment(lsa);
1055 new->vrf_id = lsa->vrf_id;
1056 /* Install this LSA into LSDB. */
1057 /* Given "lsa" will be freed in the next function. */
1058 top = ospf_lookup_by_vrf_id(lsa->vrf_id);
1059 if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
1060 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
1061 "RI (%s): ospf_lsa_install() ?", __func__);
1062 ospf_lsa_unlock(&new);
1063 return new;
1064 }
1065 /* Flood updated LSA through AREA */
1066 ospf_flood_through_area(ai->area, NULL /*nbr */, new);
1067
1068 } else { /* AS Flooding scope */
1069 /* Flush LSA, if the lsa's age reached to MaxAge. */
1070 if (IS_LSA_MAXAGE(lsa)) {
1071 UNSET_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED);
1072 ospf_opaque_lsa_flush_schedule(lsa);
1073 return NULL;
1074 }
1075 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
1076 new = ospf_router_info_lsa_new(NULL);
1077 new->data->ls_seqnum = lsa_seqnum_increment(lsa);
1078 new->vrf_id = lsa->vrf_id;
1079 /* Install this LSA into LSDB. */
1080 /* Given "lsa" will be freed in the next function. */
1081 top = ospf_lookup_by_vrf_id(lsa->vrf_id);
1082 if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
1083 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
1084 "RI (%s): ospf_lsa_install() ?", __func__);
1085 ospf_lsa_unlock(&new);
1086 return new;
1087 }
1088 /* Flood updated LSA through AS */
1089 ospf_flood_through_as(top, NULL /*nbr */, new);
1090 }
1091
1092 /* Debug logging. */
1093 if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
1094 zlog_debug(
1095 "LSA[Type%d:%pI4]: Refresh Opaque-LSA/ROUTER INFORMATION",
1096 new->data->type, &new->data->id);
1097 ospf_lsa_header_dump(new->data);
1098 }
1099
1100 return new;
1101 }
1102
1103 static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info *ai,
1104 enum lsa_opcode opcode)
1105 {
1106 struct ospf_lsa lsa;
1107 struct lsa_header lsah;
1108 struct ospf *top;
1109 uint32_t tmp;
1110
1111 memset(&lsa, 0, sizeof(lsa));
1112 memset(&lsah, 0, sizeof(lsah));
1113
1114 zlog_debug("RI (%s): LSA schedule %s%s%s", __func__,
1115 opcode == REORIGINATE_THIS_LSA ? "Re-Originate" : "",
1116 opcode == REFRESH_THIS_LSA ? "Refresh" : "",
1117 opcode == FLUSH_THIS_LSA ? "Flush" : "");
1118
1119 /* Check LSA flags state coherence and collect area information */
1120 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) {
1121 if ((ai == NULL) || (ai->area == NULL)) {
1122 flog_warn(
1123 EC_OSPF_LSA,
1124 "RI (%s): Router Info is Area scope flooding but area is not set",
1125 __func__);
1126 return;
1127 }
1128
1129 if (!CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED)
1130 && (opcode != REORIGINATE_THIS_LSA))
1131 return;
1132
1133 if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED)
1134 && (opcode == REORIGINATE_THIS_LSA))
1135 opcode = REFRESH_THIS_LSA;
1136
1137 lsa.area = ai->area;
1138 top = ai->area->ospf;
1139 } else {
1140 if (!CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED)
1141 && (opcode != REORIGINATE_THIS_LSA))
1142 return;
1143
1144 if (CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED)
1145 && (opcode == REORIGINATE_THIS_LSA))
1146 opcode = REFRESH_THIS_LSA;
1147
1148 top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
1149 lsa.area = NULL;
1150 }
1151
1152 lsa.data = &lsah;
1153 lsah.type = OspfRI.scope;
1154
1155 /* LSA ID is set to 0 for the Router Information. See RFC 4970 */
1156 tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_ROUTER_INFORMATION_LSA, 0);
1157 lsah.id.s_addr = htonl(tmp);
1158
1159 switch (opcode) {
1160 case REORIGINATE_THIS_LSA:
1161 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA)
1162 ospf_opaque_lsa_reoriginate_schedule(
1163 (void *)ai->area, OSPF_OPAQUE_AREA_LSA,
1164 OPAQUE_TYPE_ROUTER_INFORMATION_LSA);
1165 else
1166 ospf_opaque_lsa_reoriginate_schedule(
1167 (void *)top, OSPF_OPAQUE_AS_LSA,
1168 OPAQUE_TYPE_ROUTER_INFORMATION_LSA);
1169 break;
1170 case REFRESH_THIS_LSA:
1171 ospf_opaque_lsa_refresh_schedule(&lsa);
1172 break;
1173 case FLUSH_THIS_LSA:
1174 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA)
1175 UNSET_FLAG(ai->flags, RIFLG_LSA_ENGAGED);
1176 else
1177 UNSET_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED);
1178 ospf_opaque_lsa_flush_schedule(&lsa);
1179 break;
1180 }
1181
1182 return;
1183 }
1184
1185 /* Callback to handle Segment Routing information */
1186 static int ospf_router_info_lsa_update(struct ospf_lsa *lsa)
1187 {
1188
1189 /* Sanity Check */
1190 if (lsa == NULL) {
1191 flog_warn(EC_OSPF_LSA, "RI (%s): Abort! LSA is NULL",
1192 __func__);
1193 return -1;
1194 }
1195
1196 /* Process only Opaque LSA */
1197 if ((lsa->data->type != OSPF_OPAQUE_AREA_LSA)
1198 && (lsa->data->type != OSPF_OPAQUE_AS_LSA))
1199 return 0;
1200
1201 /* Process only Router Information LSA */
1202 if (GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr))
1203 != OPAQUE_TYPE_ROUTER_INFORMATION_LSA)
1204 return 0;
1205
1206 /* Check if it is not my LSA */
1207 if (IS_LSA_SELF(lsa))
1208 return 0;
1209
1210 /* Check if Router Info & Segment Routing are enable */
1211 if (!OspfRI.enabled || !OspfRI.sr_info.enabled)
1212 return 0;
1213
1214 /* Call Segment Routing LSA update or deletion */
1215 if (!IS_LSA_MAXAGE(lsa))
1216 ospf_sr_ri_lsa_update(lsa);
1217 else
1218 ospf_sr_ri_lsa_delete(lsa);
1219
1220 return 0;
1221 }
1222
1223 /*------------------------------------------------------------------------*
1224 * Followings are vty session control functions.
1225 *------------------------------------------------------------------------*/
1226
1227 #define check_tlv_size(size, msg) \
1228 do { \
1229 if (ntohs(tlvh->length) > size) { \
1230 if (vty != NULL) \
1231 vty_out(vty, " Wrong %s TLV size: %d(%d)\n", \
1232 msg, ntohs(tlvh->length), size); \
1233 else \
1234 zlog_debug(" Wrong %s TLV size: %d(%d)", \
1235 msg, ntohs(tlvh->length), size); \
1236 return size + TLV_HDR_SIZE; \
1237 } \
1238 } while (0)
1239
1240 static uint16_t show_vty_router_cap(struct vty *vty, struct tlv_header *tlvh)
1241 {
1242 struct ri_tlv_router_cap *top = (struct ri_tlv_router_cap *)tlvh;
1243
1244 check_tlv_size(RI_TLV_CAPABILITIES_SIZE, "Router Capabilities");
1245
1246 if (vty != NULL)
1247 vty_out(vty, " Router Capabilities: 0x%x\n",
1248 ntohl(top->value));
1249 else
1250 zlog_debug(" Router Capabilities: 0x%x", ntohl(top->value));
1251
1252 return TLV_SIZE(tlvh);
1253 }
1254
1255 static uint16_t show_vty_pce_subtlv_address(struct vty *vty,
1256 struct tlv_header *tlvh)
1257 {
1258 struct ri_pce_subtlv_address *top =
1259 (struct ri_pce_subtlv_address *)tlvh;
1260
1261 if (ntohs(top->address.type) == PCE_ADDRESS_IPV4) {
1262 check_tlv_size(PCE_ADDRESS_IPV4_SIZE, "PCE Address");
1263 if (vty != NULL)
1264 vty_out(vty, " PCE Address: %pI4\n",
1265 &top->address.value);
1266 else
1267 zlog_debug(" PCE Address: %pI4",
1268 &top->address.value);
1269 } else if (ntohs(top->address.type) == PCE_ADDRESS_IPV6) {
1270 /* TODO: Add support to IPv6 with inet_ntop() */
1271 check_tlv_size(PCE_ADDRESS_IPV6_SIZE, "PCE Address");
1272 if (vty != NULL)
1273 vty_out(vty, " PCE Address: 0x%x\n",
1274 ntohl(top->address.value.s_addr));
1275 else
1276 zlog_debug(" PCE Address: 0x%x",
1277 ntohl(top->address.value.s_addr));
1278 } else {
1279 if (vty != NULL)
1280 vty_out(vty, " Wrong PCE Address type: 0x%x\n",
1281 ntohl(top->address.type));
1282 else
1283 zlog_debug(" Wrong PCE Address type: 0x%x",
1284 ntohl(top->address.type));
1285 }
1286
1287 return TLV_SIZE(tlvh);
1288 }
1289
1290 static uint16_t show_vty_pce_subtlv_path_scope(struct vty *vty,
1291 struct tlv_header *tlvh)
1292 {
1293 struct ri_pce_subtlv_path_scope *top =
1294 (struct ri_pce_subtlv_path_scope *)tlvh;
1295
1296 check_tlv_size(RI_PCE_SUBTLV_PATH_SCOPE_SIZE, "PCE Path Scope");
1297
1298 if (vty != NULL)
1299 vty_out(vty, " PCE Path Scope: 0x%x\n", ntohl(top->value));
1300 else
1301 zlog_debug(" PCE Path Scope: 0x%x", ntohl(top->value));
1302
1303 return TLV_SIZE(tlvh);
1304 }
1305
1306 static uint16_t show_vty_pce_subtlv_domain(struct vty *vty,
1307 struct tlv_header *tlvh)
1308 {
1309 struct ri_pce_subtlv_domain *top = (struct ri_pce_subtlv_domain *)tlvh;
1310 struct in_addr tmp;
1311
1312 check_tlv_size(RI_PCE_SUBTLV_DOMAIN_SIZE, "PCE Domain");
1313
1314 if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) {
1315 tmp.s_addr = top->value;
1316 if (vty != NULL)
1317 vty_out(vty, " PCE Domain Area: %pI4\n", &tmp);
1318 else
1319 zlog_debug(" PCE Domain Area: %pI4", &tmp);
1320 } else if (ntohs(top->type) == PCE_DOMAIN_TYPE_AS) {
1321 if (vty != NULL)
1322 vty_out(vty, " PCE Domain AS: %d\n",
1323 ntohl(top->value));
1324 else
1325 zlog_debug(" PCE Domain AS: %d", ntohl(top->value));
1326 } else {
1327 if (vty != NULL)
1328 vty_out(vty, " Wrong PCE Domain type: %d\n",
1329 ntohl(top->type));
1330 else
1331 zlog_debug(" Wrong PCE Domain type: %d",
1332 ntohl(top->type));
1333 }
1334
1335 return TLV_SIZE(tlvh);
1336 }
1337
1338 static uint16_t show_vty_pce_subtlv_neighbor(struct vty *vty,
1339 struct tlv_header *tlvh)
1340 {
1341
1342 struct ri_pce_subtlv_neighbor *top =
1343 (struct ri_pce_subtlv_neighbor *)tlvh;
1344 struct in_addr tmp;
1345
1346 check_tlv_size(RI_PCE_SUBTLV_NEIGHBOR_SIZE, "PCE Neighbor");
1347
1348 if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) {
1349 tmp.s_addr = top->value;
1350 if (vty != NULL)
1351 vty_out(vty, " PCE Neighbor Area: %pI4\n", &tmp);
1352 else
1353 zlog_debug(" PCE Neighbor Area: %pI4", &tmp);
1354 } else if (ntohs(top->type) == PCE_DOMAIN_TYPE_AS) {
1355 if (vty != NULL)
1356 vty_out(vty, " PCE Neighbor AS: %d\n",
1357 ntohl(top->value));
1358 else
1359 zlog_debug(" PCE Neighbor AS: %d",
1360 ntohl(top->value));
1361 } else {
1362 if (vty != NULL)
1363 vty_out(vty, " Wrong PCE Neighbor type: %d\n",
1364 ntohl(top->type));
1365 else
1366 zlog_debug(" Wrong PCE Neighbor type: %d",
1367 ntohl(top->type));
1368 }
1369
1370 return TLV_SIZE(tlvh);
1371 }
1372
1373 static uint16_t show_vty_pce_subtlv_cap_flag(struct vty *vty,
1374 struct tlv_header *tlvh)
1375 {
1376 struct ri_pce_subtlv_cap_flag *top =
1377 (struct ri_pce_subtlv_cap_flag *)tlvh;
1378
1379 check_tlv_size(RI_PCE_SUBTLV_CAP_FLAG_SIZE, "PCE Capabilities");
1380
1381 if (vty != NULL)
1382 vty_out(vty, " PCE Capabilities Flag: 0x%x\n",
1383 ntohl(top->value));
1384 else
1385 zlog_debug(" PCE Capabilities Flag: 0x%x",
1386 ntohl(top->value));
1387
1388 return TLV_SIZE(tlvh);
1389 }
1390
1391 static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh,
1392 size_t buf_size)
1393 {
1394 if (TLV_SIZE(tlvh) > buf_size) {
1395 if (vty != NULL)
1396 vty_out(vty,
1397 " TLV size %d exceeds buffer size. Abort!",
1398 TLV_SIZE(tlvh));
1399 else
1400 zlog_debug(
1401 " TLV size %d exceeds buffer size. Abort!",
1402 TLV_SIZE(tlvh));
1403 return buf_size;
1404 }
1405
1406 if (vty != NULL)
1407 vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
1408 ntohs(tlvh->type), ntohs(tlvh->length));
1409 else
1410 zlog_debug(" Unknown TLV: [type(0x%x), length(0x%x)]",
1411 ntohs(tlvh->type), ntohs(tlvh->length));
1412
1413 return TLV_SIZE(tlvh);
1414 }
1415
1416 static uint16_t show_vty_pce_info(struct vty *vty, struct tlv_header *ri,
1417 size_t buf_size)
1418 {
1419 struct tlv_header *tlvh;
1420 uint16_t length = ntohs(ri->length);
1421 uint16_t sum = 0;
1422
1423 /* Verify that TLV length is valid against remaining buffer size */
1424 if (length > buf_size) {
1425 vty_out(vty,
1426 " PCE Info TLV size %d exceeds buffer size. Abort!\n",
1427 length);
1428 return buf_size;
1429 }
1430
1431 for (tlvh = ri; sum < length; tlvh = TLV_HDR_NEXT(tlvh)) {
1432 switch (ntohs(tlvh->type)) {
1433 case RI_PCE_SUBTLV_ADDRESS:
1434 sum += show_vty_pce_subtlv_address(vty, tlvh);
1435 break;
1436 case RI_PCE_SUBTLV_PATH_SCOPE:
1437 sum += show_vty_pce_subtlv_path_scope(vty, tlvh);
1438 break;
1439 case RI_PCE_SUBTLV_DOMAIN:
1440 sum += show_vty_pce_subtlv_domain(vty, tlvh);
1441 break;
1442 case RI_PCE_SUBTLV_NEIGHBOR:
1443 sum += show_vty_pce_subtlv_neighbor(vty, tlvh);
1444 break;
1445 case RI_PCE_SUBTLV_CAP_FLAG:
1446 sum += show_vty_pce_subtlv_cap_flag(vty, tlvh);
1447 break;
1448 default:
1449 sum += show_vty_unknown_tlv(vty, tlvh, length - sum);
1450 break;
1451 }
1452 }
1453 return sum;
1454 }
1455
1456 /* Display Segment Routing Algorithm TLV information */
1457 static uint16_t show_vty_sr_algorithm(struct vty *vty, struct tlv_header *tlvh)
1458 {
1459 struct ri_sr_tlv_sr_algorithm *algo =
1460 (struct ri_sr_tlv_sr_algorithm *)tlvh;
1461 int i;
1462
1463 check_tlv_size(ALGORITHM_COUNT, "Segment Routing Algorithm");
1464
1465 if (vty != NULL) {
1466 vty_out(vty, " Segment Routing Algorithm TLV:\n");
1467 for (i = 0; i < ntohs(algo->header.length); i++) {
1468 switch (algo->value[i]) {
1469 case 0:
1470 vty_out(vty, " Algorithm %d: SPF\n", i);
1471 break;
1472 case 1:
1473 vty_out(vty, " Algorithm %d: Strict SPF\n",
1474 i);
1475 break;
1476 default:
1477 vty_out(vty,
1478 " Algorithm %d: Unknown value %d\n", i,
1479 algo->value[i]);
1480 break;
1481 }
1482 }
1483 } else {
1484 zlog_debug(" Segment Routing Algorithm TLV:");
1485 for (i = 0; i < ntohs(algo->header.length); i++)
1486 switch (algo->value[i]) {
1487 case 0:
1488 zlog_debug(" Algorithm %d: SPF", i);
1489 break;
1490 case 1:
1491 zlog_debug(" Algorithm %d: Strict SPF", i);
1492 break;
1493 default:
1494 zlog_debug(" Algorithm %d: Unknown value %d",
1495 i, algo->value[i]);
1496 break;
1497 }
1498 }
1499
1500 return TLV_SIZE(tlvh);
1501 }
1502
1503 /* Display Segment Routing SID/Label Range TLV information */
1504 static uint16_t show_vty_sr_range(struct vty *vty, struct tlv_header *tlvh)
1505 {
1506 struct ri_sr_tlv_sid_label_range *range =
1507 (struct ri_sr_tlv_sid_label_range *)tlvh;
1508
1509 check_tlv_size(RI_SR_TLV_LABEL_RANGE_SIZE, "SR Label Range");
1510
1511 if (vty != NULL) {
1512 vty_out(vty,
1513 " Segment Routing %s Range TLV:\n"
1514 " Range Size = %d\n"
1515 " SID Label = %d\n\n",
1516 ntohs(range->header.type) == RI_SR_TLV_SRGB_LABEL_RANGE
1517 ? "Global"
1518 : "Local",
1519 GET_RANGE_SIZE(ntohl(range->size)),
1520 GET_LABEL(ntohl(range->lower.value)));
1521 } else {
1522 zlog_debug(
1523 " Segment Routing %s Range TLV: Range Size = %d SID Label = %d",
1524 ntohs(range->header.type) == RI_SR_TLV_SRGB_LABEL_RANGE
1525 ? "Global"
1526 : "Local",
1527 GET_RANGE_SIZE(ntohl(range->size)),
1528 GET_LABEL(ntohl(range->lower.value)));
1529 }
1530
1531 return TLV_SIZE(tlvh);
1532 }
1533
1534 /* Display Segment Routing Maximum Stack Depth TLV information */
1535 static uint16_t show_vty_sr_msd(struct vty *vty, struct tlv_header *tlvh)
1536 {
1537 struct ri_sr_tlv_node_msd *msd = (struct ri_sr_tlv_node_msd *)tlvh;
1538
1539 check_tlv_size(RI_SR_TLV_NODE_MSD_SIZE, "Node Maximum Stack Depth");
1540
1541 if (vty != NULL) {
1542 vty_out(vty,
1543 " Segment Routing MSD TLV:\n"
1544 " Node Maximum Stack Depth = %d\n",
1545 msd->value);
1546 } else {
1547 zlog_debug(
1548 " Segment Routing MSD TLV: Node Maximum Stack Depth = %d",
1549 msd->value);
1550 }
1551
1552 return TLV_SIZE(tlvh);
1553 }
1554
1555 static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa)
1556 {
1557 struct lsa_header *lsah = lsa->data;
1558 struct tlv_header *tlvh;
1559 uint16_t length = 0, sum = 0;
1560
1561 /* Initialize TLV browsing */
1562 length = lsa->size - OSPF_LSA_HEADER_SIZE;
1563
1564 for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh;
1565 tlvh = TLV_HDR_NEXT(tlvh)) {
1566 switch (ntohs(tlvh->type)) {
1567 case RI_TLV_CAPABILITIES:
1568 sum += show_vty_router_cap(vty, tlvh);
1569 break;
1570 case RI_TLV_PCE:
1571 tlvh++;
1572 sum += TLV_HDR_SIZE;
1573 sum += show_vty_pce_info(vty, tlvh, length - sum);
1574 break;
1575 case RI_SR_TLV_SR_ALGORITHM:
1576 sum += show_vty_sr_algorithm(vty, tlvh);
1577 break;
1578 case RI_SR_TLV_SRGB_LABEL_RANGE:
1579 case RI_SR_TLV_SRLB_LABEL_RANGE:
1580 sum += show_vty_sr_range(vty, tlvh);
1581 break;
1582 case RI_SR_TLV_NODE_MSD:
1583 sum += show_vty_sr_msd(vty, tlvh);
1584 break;
1585
1586 default:
1587 sum += show_vty_unknown_tlv(vty, tlvh, length);
1588 break;
1589 }
1590 }
1591
1592 return;
1593 }
1594
1595 static void ospf_router_info_config_write_router(struct vty *vty)
1596 {
1597 struct ospf_pce_info *pce = &OspfRI.pce_info;
1598 struct listnode *node;
1599 struct ri_pce_subtlv_domain *domain;
1600 struct ri_pce_subtlv_neighbor *neighbor;
1601 struct in_addr tmp;
1602
1603 if (!OspfRI.enabled)
1604 return;
1605
1606 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
1607 vty_out(vty, " router-info as\n");
1608 else
1609 vty_out(vty, " router-info area\n");
1610
1611 if (OspfRI.pce_info.enabled) {
1612
1613 if (pce->pce_address.header.type != 0)
1614 vty_out(vty, " pce address %pI4\n",
1615 &pce->pce_address.address.value);
1616
1617 if (pce->pce_cap_flag.header.type != 0)
1618 vty_out(vty, " pce flag 0x%x\n",
1619 ntohl(pce->pce_cap_flag.value));
1620
1621 for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
1622 if (domain->header.type != 0) {
1623 if (domain->type == PCE_DOMAIN_TYPE_AREA) {
1624 tmp.s_addr = domain->value;
1625 vty_out(vty, " pce domain area %pI4\n",
1626 &tmp);
1627 } else {
1628 vty_out(vty, " pce domain as %d\n",
1629 ntohl(domain->value));
1630 }
1631 }
1632 }
1633
1634 for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
1635 if (neighbor->header.type != 0) {
1636 if (neighbor->type == PCE_DOMAIN_TYPE_AREA) {
1637 tmp.s_addr = neighbor->value;
1638 vty_out(vty,
1639 " pce neighbor area %pI4\n",
1640 &tmp);
1641 } else {
1642 vty_out(vty, " pce neighbor as %d\n",
1643 ntohl(neighbor->value));
1644 }
1645 }
1646 }
1647
1648 if (pce->pce_scope.header.type != 0)
1649 vty_out(vty, " pce scope 0x%x\n",
1650 ntohl(OspfRI.pce_info.pce_scope.value));
1651 }
1652 return;
1653 }
1654
1655 /*------------------------------------------------------------------------*
1656 * Followings are vty command functions.
1657 *------------------------------------------------------------------------*/
1658 /* Simple wrapper schedule RI LSA action in function of the scope */
1659 static void ospf_router_info_schedule(enum lsa_opcode opcode)
1660 {
1661 struct listnode *node, *nnode;
1662 struct ospf_ri_area_info *ai;
1663
1664 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
1665 if (CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED))
1666 ospf_router_info_lsa_schedule(NULL, opcode);
1667 else if (opcode == REORIGINATE_THIS_LSA)
1668 ospf_router_info_lsa_schedule(NULL, opcode);
1669 } else {
1670 for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai)) {
1671 if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED))
1672 ospf_router_info_lsa_schedule(ai, opcode);
1673 }
1674 }
1675 }
1676
1677 DEFUN (router_info,
1678 router_info_area_cmd,
1679 "router-info <as|area [A.B.C.D]>",
1680 OSPF_RI_STR
1681 "Enable the Router Information functionality with AS flooding scope\n"
1682 "Enable the Router Information functionality with Area flooding scope\n"
1683 "OSPF area ID in IP format (deprecated)\n")
1684 {
1685 int idx_mode = 1;
1686 uint8_t scope;
1687
1688 if (OspfRI.enabled)
1689 return CMD_SUCCESS;
1690
1691 /* Check and get Area value if present */
1692 if (strncmp(argv[idx_mode]->arg, "as", 2) == 0)
1693 scope = OSPF_OPAQUE_AS_LSA;
1694 else
1695 scope = OSPF_OPAQUE_AREA_LSA;
1696
1697 /* First start to register Router Information callbacks */
1698 if (!OspfRI.registered && (ospf_router_info_register(scope)) != 0) {
1699 vty_out(vty,
1700 "%% Unable to register Router Information callbacks.");
1701 flog_err(
1702 EC_OSPF_INIT_FAIL,
1703 "RI (%s): Unable to register Router Information callbacks. Abort!",
1704 __func__);
1705 return CMD_WARNING_CONFIG_FAILED;
1706 }
1707
1708 OspfRI.enabled = true;
1709
1710 if (IS_DEBUG_OSPF_EVENT)
1711 zlog_debug("RI-> Router Information (%s flooding): OFF -> ON",
1712 OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area"
1713 : "AS");
1714
1715 /*
1716 * Following code is intended to handle two cases;
1717 *
1718 * 1) Router Information was disabled at startup time, but now become
1719 * enabled.
1720 * 2) Router Information was once enabled then disabled, and now enabled
1721 * again.
1722 */
1723
1724 initialize_params(&OspfRI);
1725
1726 /* Originate or Refresh RI LSA if already engaged */
1727 ospf_router_info_schedule(REORIGINATE_THIS_LSA);
1728 return CMD_SUCCESS;
1729 }
1730
1731
1732 DEFUN (no_router_info,
1733 no_router_info_cmd,
1734 "no router-info",
1735 NO_STR
1736 "Disable the Router Information functionality\n")
1737 {
1738
1739 if (!OspfRI.enabled)
1740 return CMD_SUCCESS;
1741
1742 if (IS_DEBUG_OSPF_EVENT)
1743 zlog_debug("RI-> Router Information: ON -> OFF");
1744
1745 ospf_router_info_schedule(FLUSH_THIS_LSA);
1746
1747 OspfRI.enabled = false;
1748
1749 return CMD_SUCCESS;
1750 }
1751
1752 static int ospf_ri_enabled(struct vty *vty)
1753 {
1754 if (OspfRI.enabled)
1755 return 1;
1756
1757 if (vty)
1758 vty_out(vty, "%% OSPF RI is not turned on\n");
1759
1760 return 0;
1761 }
1762
1763 DEFUN (pce_address,
1764 pce_address_cmd,
1765 "pce address A.B.C.D",
1766 PCE_STR
1767 "Stable IP address of the PCE\n"
1768 "PCE address in IPv4 address format\n")
1769 {
1770 int idx_ipv4 = 2;
1771 struct in_addr value;
1772 struct ospf_pce_info *pi = &OspfRI.pce_info;
1773
1774 if (!ospf_ri_enabled(vty))
1775 return CMD_WARNING_CONFIG_FAILED;
1776
1777 if (!inet_aton(argv[idx_ipv4]->arg, &value)) {
1778 vty_out(vty, "Please specify PCE Address by A.B.C.D\n");
1779 return CMD_WARNING_CONFIG_FAILED;
1780 }
1781
1782 if (ntohs(pi->pce_address.header.type) == 0
1783 || ntohl(pi->pce_address.address.value.s_addr)
1784 != ntohl(value.s_addr)) {
1785
1786 set_pce_address(value, pi);
1787
1788 /* Refresh RI LSA if already engaged */
1789 ospf_router_info_schedule(REFRESH_THIS_LSA);
1790 }
1791
1792 return CMD_SUCCESS;
1793 }
1794
1795 DEFUN (no_pce_address,
1796 no_pce_address_cmd,
1797 "no pce address [A.B.C.D]",
1798 NO_STR
1799 PCE_STR
1800 "Disable PCE address\n"
1801 "PCE address in IPv4 address format\n")
1802 {
1803
1804 unset_param(&OspfRI.pce_info.pce_address);
1805
1806 /* Refresh RI LSA if already engaged */
1807 ospf_router_info_schedule(REFRESH_THIS_LSA);
1808
1809 return CMD_SUCCESS;
1810 }
1811
1812 DEFUN (pce_path_scope,
1813 pce_path_scope_cmd,
1814 "pce scope BITPATTERN",
1815 PCE_STR
1816 "Path scope visibilities of the PCE for path computation\n"
1817 "32-bit Hexadecimal value\n")
1818 {
1819 int idx_bitpattern = 2;
1820 uint32_t scope;
1821 struct ospf_pce_info *pi = &OspfRI.pce_info;
1822
1823 if (!ospf_ri_enabled(vty))
1824 return CMD_WARNING_CONFIG_FAILED;
1825
1826 if (sscanf(argv[idx_bitpattern]->arg, "0x%x", &scope) != 1) {
1827 vty_out(vty, "pce_path_scope: fscanf: %s\n",
1828 safe_strerror(errno));
1829 return CMD_WARNING_CONFIG_FAILED;
1830 }
1831
1832 if (ntohl(pi->pce_scope.header.type) == 0
1833 || scope != pi->pce_scope.value) {
1834 set_pce_path_scope(scope, pi);
1835
1836 /* Refresh RI LSA if already engaged */
1837 ospf_router_info_schedule(REFRESH_THIS_LSA);
1838 }
1839
1840 return CMD_SUCCESS;
1841 }
1842
1843 DEFUN (no_pce_path_scope,
1844 no_pce_path_scope_cmd,
1845 "no pce scope [BITPATTERN]",
1846 NO_STR
1847 PCE_STR
1848 "Disable PCE path scope\n"
1849 "32-bit Hexadecimal value\n")
1850 {
1851
1852 unset_param(&OspfRI.pce_info.pce_address);
1853
1854 /* Refresh RI LSA if already engaged */
1855 ospf_router_info_schedule(REFRESH_THIS_LSA);
1856
1857 return CMD_SUCCESS;
1858 }
1859
1860 DEFUN (pce_domain,
1861 pce_domain_cmd,
1862 "pce domain as (0-65535)",
1863 PCE_STR
1864 "Configure PCE domain AS number\n"
1865 "AS number where the PCE as visibilities for path computation\n"
1866 "AS number in decimal <0-65535>\n")
1867 {
1868 int idx_number = 3;
1869
1870 uint32_t as;
1871 struct ospf_pce_info *pce = &OspfRI.pce_info;
1872 struct listnode *node;
1873 struct ri_pce_subtlv_domain *domain;
1874
1875 if (!ospf_ri_enabled(vty))
1876 return CMD_WARNING_CONFIG_FAILED;
1877
1878 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
1879 vty_out(vty, "pce_domain: fscanf: %s\n", safe_strerror(errno));
1880 return CMD_WARNING_CONFIG_FAILED;
1881 }
1882
1883 /* Check if the domain is not already in the domain list */
1884 for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
1885 if (ntohl(domain->header.type) == 0 && as == domain->value)
1886 return CMD_SUCCESS;
1887 }
1888
1889 /* Create new domain if not found */
1890 set_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce);
1891
1892 /* Refresh RI LSA if already engaged */
1893 ospf_router_info_schedule(REFRESH_THIS_LSA);
1894
1895 return CMD_SUCCESS;
1896 }
1897
1898 DEFUN (no_pce_domain,
1899 no_pce_domain_cmd,
1900 "no pce domain as (0-65535)",
1901 NO_STR
1902 PCE_STR
1903 "Disable PCE domain AS number\n"
1904 "AS number where the PCE as visibilities for path computation\n"
1905 "AS number in decimal <0-65535>\n")
1906 {
1907 int idx_number = 4;
1908
1909 uint32_t as;
1910 struct ospf_pce_info *pce = &OspfRI.pce_info;
1911
1912 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
1913 vty_out(vty, "no_pce_domain: fscanf: %s\n",
1914 safe_strerror(errno));
1915 return CMD_WARNING_CONFIG_FAILED;
1916 }
1917
1918 /* Unset corresponding PCE domain */
1919 unset_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce);
1920
1921 /* Refresh RI LSA if already engaged */
1922 ospf_router_info_schedule(REFRESH_THIS_LSA);
1923
1924 return CMD_SUCCESS;
1925 }
1926
1927 DEFUN (pce_neigbhor,
1928 pce_neighbor_cmd,
1929 "pce neighbor as (0-65535)",
1930 PCE_STR
1931 "Configure PCE neighbor domain AS number\n"
1932 "AS number of PCE neighbors\n"
1933 "AS number in decimal <0-65535>\n")
1934 {
1935 int idx_number = 3;
1936
1937 uint32_t as;
1938 struct ospf_pce_info *pce = &OspfRI.pce_info;
1939 struct listnode *node;
1940 struct ri_pce_subtlv_neighbor *neighbor;
1941
1942 if (!ospf_ri_enabled(vty))
1943 return CMD_WARNING_CONFIG_FAILED;
1944
1945 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
1946 vty_out(vty, "pce_neighbor: fscanf: %s\n",
1947 safe_strerror(errno));
1948 return CMD_WARNING_CONFIG_FAILED;
1949 }
1950
1951 /* Check if the domain is not already in the domain list */
1952 for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
1953 if (ntohl(neighbor->header.type) == 0 && as == neighbor->value)
1954 return CMD_SUCCESS;
1955 }
1956
1957 /* Create new domain if not found */
1958 set_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce);
1959
1960 /* Refresh RI LSA if already engaged */
1961 ospf_router_info_schedule(REFRESH_THIS_LSA);
1962
1963 return CMD_SUCCESS;
1964 }
1965
1966 DEFUN (no_pce_neighbor,
1967 no_pce_neighbor_cmd,
1968 "no pce neighbor as (0-65535)",
1969 NO_STR
1970 PCE_STR
1971 "Disable PCE neighbor AS number\n"
1972 "AS number of PCE neighbor\n"
1973 "AS number in decimal <0-65535>\n")
1974 {
1975 int idx_number = 4;
1976
1977 uint32_t as;
1978 struct ospf_pce_info *pce = &OspfRI.pce_info;
1979
1980 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
1981 vty_out(vty, "no_pce_neighbor: fscanf: %s\n",
1982 safe_strerror(errno));
1983 return CMD_WARNING_CONFIG_FAILED;
1984 }
1985
1986 /* Unset corresponding PCE domain */
1987 unset_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce);
1988
1989 /* Refresh RI LSA if already engaged */
1990 ospf_router_info_schedule(REFRESH_THIS_LSA);
1991
1992 return CMD_SUCCESS;
1993 }
1994
1995 DEFUN (pce_cap_flag,
1996 pce_cap_flag_cmd,
1997 "pce flag BITPATTERN",
1998 PCE_STR
1999 "Capabilities of the PCE for path computation\n"
2000 "32-bit Hexadecimal value\n")
2001 {
2002 int idx_bitpattern = 2;
2003
2004 uint32_t cap;
2005 struct ospf_pce_info *pce = &OspfRI.pce_info;
2006
2007 if (!ospf_ri_enabled(vty))
2008 return CMD_WARNING_CONFIG_FAILED;
2009
2010 if (sscanf(argv[idx_bitpattern]->arg, "0x%x", &cap) != 1) {
2011 vty_out(vty, "pce_cap_flag: fscanf: %s\n",
2012 safe_strerror(errno));
2013 return CMD_WARNING_CONFIG_FAILED;
2014 }
2015
2016 if (ntohl(pce->pce_cap_flag.header.type) == 0
2017 || cap != pce->pce_cap_flag.value) {
2018 set_pce_cap_flag(cap, pce);
2019
2020 /* Refresh RI LSA if already engaged */
2021 ospf_router_info_schedule(REFRESH_THIS_LSA);
2022 }
2023
2024 return CMD_SUCCESS;
2025 }
2026
2027 DEFUN (no_pce_cap_flag,
2028 no_pce_cap_flag_cmd,
2029 "no pce flag",
2030 NO_STR
2031 PCE_STR
2032 "Disable PCE capabilities\n")
2033 {
2034
2035 unset_param(&OspfRI.pce_info.pce_cap_flag);
2036
2037 /* Refresh RI LSA if already engaged */
2038 ospf_router_info_schedule(REFRESH_THIS_LSA);
2039
2040 return CMD_SUCCESS;
2041 }
2042
2043 DEFUN (show_ip_ospf_router_info,
2044 show_ip_ospf_router_info_cmd,
2045 "show ip ospf router-info",
2046 SHOW_STR
2047 IP_STR
2048 OSPF_STR
2049 "Router Information\n")
2050 {
2051
2052 if (OspfRI.enabled) {
2053 vty_out(vty, "--- Router Information parameters ---\n");
2054 show_vty_router_cap(vty, &OspfRI.router_cap.header);
2055 } else {
2056 if (vty != NULL)
2057 vty_out(vty,
2058 " Router Information is disabled on this router\n");
2059 }
2060 return CMD_SUCCESS;
2061 }
2062
2063 DEFUN (show_ip_opsf_router_info_pce,
2064 show_ip_ospf_router_info_pce_cmd,
2065 "show ip ospf router-info pce",
2066 SHOW_STR
2067 IP_STR
2068 OSPF_STR
2069 "Router Information\n"
2070 "PCE information\n")
2071 {
2072
2073 struct ospf_pce_info *pce = &OspfRI.pce_info;
2074 struct listnode *node;
2075 struct ri_pce_subtlv_domain *domain;
2076 struct ri_pce_subtlv_neighbor *neighbor;
2077
2078 if ((OspfRI.enabled) && (OspfRI.pce_info.enabled)) {
2079 vty_out(vty, "--- PCE parameters ---\n");
2080
2081 if (pce->pce_address.header.type != 0)
2082 show_vty_pce_subtlv_address(vty,
2083 &pce->pce_address.header);
2084
2085 if (pce->pce_scope.header.type != 0)
2086 show_vty_pce_subtlv_path_scope(vty,
2087 &pce->pce_scope.header);
2088
2089 for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
2090 if (domain->header.type != 0)
2091 show_vty_pce_subtlv_domain(vty,
2092 &domain->header);
2093 }
2094
2095 for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
2096 if (neighbor->header.type != 0)
2097 show_vty_pce_subtlv_neighbor(vty,
2098 &neighbor->header);
2099 }
2100
2101 if (pce->pce_cap_flag.header.type != 0)
2102 show_vty_pce_subtlv_cap_flag(vty,
2103 &pce->pce_cap_flag.header);
2104
2105 } else {
2106 vty_out(vty, " PCE info is disabled on this router\n");
2107 }
2108
2109 return CMD_SUCCESS;
2110 }
2111
2112 /* Install new CLI commands */
2113 static void ospf_router_info_register_vty(void)
2114 {
2115 install_element(VIEW_NODE, &show_ip_ospf_router_info_cmd);
2116 install_element(VIEW_NODE, &show_ip_ospf_router_info_pce_cmd);
2117
2118 install_element(OSPF_NODE, &router_info_area_cmd);
2119 install_element(OSPF_NODE, &no_router_info_cmd);
2120 install_element(OSPF_NODE, &pce_address_cmd);
2121 install_element(OSPF_NODE, &no_pce_address_cmd);
2122 install_element(OSPF_NODE, &pce_path_scope_cmd);
2123 install_element(OSPF_NODE, &no_pce_path_scope_cmd);
2124 install_element(OSPF_NODE, &pce_domain_cmd);
2125 install_element(OSPF_NODE, &no_pce_domain_cmd);
2126 install_element(OSPF_NODE, &pce_neighbor_cmd);
2127 install_element(OSPF_NODE, &no_pce_neighbor_cmd);
2128 install_element(OSPF_NODE, &pce_cap_flag_cmd);
2129 install_element(OSPF_NODE, &no_pce_cap_flag_cmd);
2130
2131 return;
2132 }