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
ospf_router_info_init(void)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
ospf_router_info_register(uint8_t scope)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
ospf_router_info_unregister(void)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
ospf_router_info_term(void)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
ospf_router_info_finish(void)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
del_area_info(void * val)195 static void del_area_info(void *val)
196 {
197 XFREE(MTYPE_OSPF_ROUTER_INFO, val);
198 }
199
del_pce_info(void * val)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 */
ospf_router_info_get_flooding_scope(void)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
lookup_by_area(struct ospf_area * area)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
set_router_info_capabilities(struct ri_tlv_router_cap * ric,uint32_t cap)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
set_pce_header(struct ospf_pce_info * pce)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
set_pce_address(struct in_addr ipv4,struct ospf_pce_info * pce)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
set_pce_path_scope(uint32_t scope,struct ospf_pce_info * pce)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
set_pce_domain(uint16_t type,uint32_t domain,struct ospf_pce_info * pce)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
unset_pce_domain(uint16_t type,uint32_t domain,struct ospf_pce_info * pce)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
set_pce_neighbor(uint16_t type,uint32_t domain,struct ospf_pce_info * pce)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
unset_pce_neighbor(uint16_t type,uint32_t domain,struct ospf_pce_info * pce)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
set_pce_cap_flag(uint32_t cap,struct ospf_pce_info * pce)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 */
set_sr_algorithm(uint8_t algo)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 */
unset_sr_algorithm(uint8_t algo)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 */
set_sr_global_label_range(struct sr_block srgb)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 */
unset_sr_global_label_range(void)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 */
set_sr_local_label_range(struct sr_block srlb)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 */
unset_sr_local_label_range(void)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 */
set_sr_node_msd(uint8_t msd)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 */
unset_sr_node_msd(void)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
unset_param(void * tlv_buffer)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
initialize_params(struct ospf_router_info * ori)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 %s to Router Information",
548 __func__, inet_ntoa(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
is_mandated_params_set(struct ospf_router_info * ori)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 */
ospf_router_info_update_sr(bool enable,struct sr_node * srn)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 *------------------------------------------------------------------------*/
ospf_router_info_ism_change(struct ospf_interface * oi,int old_state)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
build_tlv_header(struct stream * s,struct tlv_header * tlvh)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
build_tlv(struct stream * s,struct tlv_header * tlvh)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
ospf_router_info_lsa_body_set(struct stream * s)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. */
ospf_router_info_lsa_new(struct ospf_area * area)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:%s]: Create an Opaque-LSA/ROUTER INFORMATION instance",
799 lsa_type, inet_ntoa(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
ospf_router_info_lsa_originate_as(void * arg)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:%s]: Originate Opaque-LSA/ROUTER INFORMATION",
878 new->data->type, inet_ntoa(new->data->id));
879 ospf_lsa_header_dump(new->data);
880 }
881
882 rc = 0;
883 return rc;
884 }
885
ospf_router_info_lsa_originate_area(void * arg)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:%s]: Originate Opaque-LSA/ROUTER INFORMATION",
947 new->data->type, inet_ntoa(new->data->id));
948 ospf_lsa_header_dump(new->data);
949 }
950
951 rc = 0;
952 return rc;
953 }
954
ospf_router_info_lsa_originate(void * arg)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
ospf_router_info_lsa_refresh(struct ospf_lsa * lsa)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:%s]: Refresh Opaque-LSA/ROUTER INFORMATION",
1098 new->data->type, inet_ntoa(new->data->id));
1099 ospf_lsa_header_dump(new->data);
1100 }
1101
1102 return new;
1103 }
1104
ospf_router_info_lsa_schedule(struct ospf_ri_area_info * ai,enum lsa_opcode opcode)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 */
ospf_router_info_lsa_update(struct ospf_lsa * lsa)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
show_vty_router_cap(struct vty * vty,struct tlv_header * tlvh)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
show_vty_pce_subtlv_address(struct vty * vty,struct tlv_header * tlvh)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: %s\n",
1251 inet_ntoa(top->address.value));
1252 else
1253 zlog_debug(" PCE Address: %s",
1254 inet_ntoa(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
show_vty_pce_subtlv_path_scope(struct vty * vty,struct tlv_header * tlvh)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
show_vty_pce_subtlv_domain(struct vty * vty,struct tlv_header * tlvh)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: %s\n", inet_ntoa(tmp));
1292 else
1293 zlog_debug(" PCE domain Area: %s", inet_ntoa(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
show_vty_pce_subtlv_neighbor(struct vty * vty,struct tlv_header * tlvh)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: %s\n",
1316 inet_ntoa(tmp));
1317 else
1318 zlog_debug(" PCE neighbor Area: %s", inet_ntoa(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
show_vty_pce_subtlv_cap_flag(struct vty * vty,struct tlv_header * tlvh)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
show_vty_unknown_tlv(struct vty * vty,struct tlv_header * tlvh)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
show_vty_pce_info(struct vty * vty,struct tlv_header * ri,uint32_t total)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 */
show_vty_sr_algorithm(struct vty * vty,struct tlv_header * tlvh)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 */
show_vty_sr_range(struct vty * vty,struct tlv_header * tlvh)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:\n"
1455 " Range Size = %d\n"
1456 " SID Label = %d\n\n",
1457 ntohs(range->header.type) == RI_SR_TLV_SRGB_LABEL_RANGE
1458 ? "Global"
1459 : "Local",
1460 GET_RANGE_SIZE(ntohl(range->size)),
1461 GET_LABEL(ntohl(range->lower.value)));
1462 }
1463
1464 return TLV_SIZE(tlvh);
1465 }
1466
1467 /* Display Segment Routing Maximum Stack Depth TLV information */
show_vty_sr_msd(struct vty * vty,struct tlv_header * tlvh)1468 static uint16_t show_vty_sr_msd(struct vty *vty, struct tlv_header *tlvh)
1469 {
1470 struct ri_sr_tlv_node_msd *msd = (struct ri_sr_tlv_node_msd *)tlvh;
1471
1472 if (vty != NULL) {
1473 vty_out(vty,
1474 " Segment Routing MSD TLV:\n"
1475 " Node Maximum Stack Depth = %d\n",
1476 msd->value);
1477 } else {
1478 zlog_debug(
1479 " Segment Routing MSD TLV:\n"
1480 " Node Maximum Stack Depth = %d\n",
1481 msd->value);
1482 }
1483
1484 return TLV_SIZE(tlvh);
1485 }
1486
ospf_router_info_show_info(struct vty * vty,struct ospf_lsa * lsa)1487 static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa)
1488 {
1489 struct lsa_header *lsah = lsa->data;
1490 struct tlv_header *tlvh;
1491 uint16_t length = 0, sum = 0;
1492
1493 /* Initialize TLV browsing */
1494 length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
1495
1496 for (tlvh = TLV_HDR_TOP(lsah); sum < length;
1497 tlvh = TLV_HDR_NEXT(tlvh)) {
1498 switch (ntohs(tlvh->type)) {
1499 case RI_TLV_CAPABILITIES:
1500 sum += show_vty_router_cap(vty, tlvh);
1501 break;
1502 case RI_TLV_PCE:
1503 tlvh++;
1504 sum += TLV_HDR_SIZE;
1505 sum += show_vty_pce_info(vty, tlvh, length - sum);
1506 break;
1507 case RI_SR_TLV_SR_ALGORITHM:
1508 sum += show_vty_sr_algorithm(vty, tlvh);
1509 break;
1510 case RI_SR_TLV_SRGB_LABEL_RANGE:
1511 case RI_SR_TLV_SRLB_LABEL_RANGE:
1512 sum += show_vty_sr_range(vty, tlvh);
1513 break;
1514 case RI_SR_TLV_NODE_MSD:
1515 sum += show_vty_sr_msd(vty, tlvh);
1516 break;
1517
1518 default:
1519 sum += show_vty_unknown_tlv(vty, tlvh);
1520 break;
1521 }
1522 }
1523
1524 return;
1525 }
1526
ospf_router_info_config_write_router(struct vty * vty)1527 static void ospf_router_info_config_write_router(struct vty *vty)
1528 {
1529 struct ospf_pce_info *pce = &OspfRI.pce_info;
1530 struct listnode *node;
1531 struct ri_pce_subtlv_domain *domain;
1532 struct ri_pce_subtlv_neighbor *neighbor;
1533 struct in_addr tmp;
1534
1535 if (!OspfRI.enabled)
1536 return;
1537
1538 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
1539 vty_out(vty, " router-info as\n");
1540 else
1541 vty_out(vty, " router-info area\n");
1542
1543 if (OspfRI.pce_info.enabled) {
1544
1545 if (pce->pce_address.header.type != 0)
1546 vty_out(vty, " pce address %s\n",
1547 inet_ntoa(pce->pce_address.address.value));
1548
1549 if (pce->pce_cap_flag.header.type != 0)
1550 vty_out(vty, " pce flag 0x%x\n",
1551 ntohl(pce->pce_cap_flag.value));
1552
1553 for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
1554 if (domain->header.type != 0) {
1555 if (domain->type == PCE_DOMAIN_TYPE_AREA) {
1556 tmp.s_addr = domain->value;
1557 vty_out(vty, " pce domain area %s\n",
1558 inet_ntoa(tmp));
1559 } else {
1560 vty_out(vty, " pce domain as %d\n",
1561 ntohl(domain->value));
1562 }
1563 }
1564 }
1565
1566 for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
1567 if (neighbor->header.type != 0) {
1568 if (neighbor->type == PCE_DOMAIN_TYPE_AREA) {
1569 tmp.s_addr = neighbor->value;
1570 vty_out(vty, " pce neighbor area %s\n",
1571 inet_ntoa(tmp));
1572 } else {
1573 vty_out(vty, " pce neighbor as %d\n",
1574 ntohl(neighbor->value));
1575 }
1576 }
1577 }
1578
1579 if (pce->pce_scope.header.type != 0)
1580 vty_out(vty, " pce scope 0x%x\n",
1581 ntohl(OspfRI.pce_info.pce_scope.value));
1582 }
1583 return;
1584 }
1585
1586 /*------------------------------------------------------------------------*
1587 * Followings are vty command functions.
1588 *------------------------------------------------------------------------*/
1589 /* Simple wrapper schedule RI LSA action in function of the scope */
ospf_router_info_schedule(enum lsa_opcode opcode)1590 static void ospf_router_info_schedule(enum lsa_opcode opcode)
1591 {
1592 struct listnode *node, *nnode;
1593 struct ospf_ri_area_info *ai;
1594
1595 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
1596 if (CHECK_FLAG(OspfRI.as_flags, RIFLG_LSA_ENGAGED))
1597 ospf_router_info_lsa_schedule(NULL, opcode);
1598 else if (opcode == REORIGINATE_THIS_LSA)
1599 ospf_router_info_lsa_schedule(NULL, opcode);
1600 } else {
1601 for (ALL_LIST_ELEMENTS(OspfRI.area_info, node, nnode, ai)) {
1602 if (CHECK_FLAG(ai->flags, RIFLG_LSA_ENGAGED))
1603 ospf_router_info_lsa_schedule(ai, opcode);
1604 }
1605 }
1606 }
1607
1608 DEFUN (router_info,
1609 router_info_area_cmd,
1610 "router-info <as|area [A.B.C.D]>",
1611 OSPF_RI_STR
1612 "Enable the Router Information functionality with AS flooding scope\n"
1613 "Enable the Router Information functionality with Area flooding scope\n"
1614 "OSPF area ID in IP format (deprecated)\n")
1615 {
1616 int idx_mode = 1;
1617 uint8_t scope;
1618
1619 if (OspfRI.enabled)
1620 return CMD_SUCCESS;
1621
1622 /* Check and get Area value if present */
1623 if (strncmp(argv[idx_mode]->arg, "as", 2) == 0)
1624 scope = OSPF_OPAQUE_AS_LSA;
1625 else
1626 scope = OSPF_OPAQUE_AREA_LSA;
1627
1628 /* First start to register Router Information callbacks */
1629 if (!OspfRI.registered && (ospf_router_info_register(scope)) != 0) {
1630 vty_out(vty,
1631 "%% Unable to register Router Information callbacks.");
1632 flog_err(
1633 EC_OSPF_INIT_FAIL,
1634 "RI (%s): Unable to register Router Information callbacks. Abort!",
1635 __func__);
1636 return CMD_WARNING_CONFIG_FAILED;
1637 }
1638
1639 OspfRI.enabled = true;
1640
1641 if (IS_DEBUG_OSPF_EVENT)
1642 zlog_debug("RI-> Router Information (%s flooding): OFF -> ON",
1643 OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area"
1644 : "AS");
1645
1646 /*
1647 * Following code is intended to handle two cases;
1648 *
1649 * 1) Router Information was disabled at startup time, but now become
1650 * enabled.
1651 * 2) Router Information was once enabled then disabled, and now enabled
1652 * again.
1653 */
1654
1655 initialize_params(&OspfRI);
1656
1657 /* Originate or Refresh RI LSA if already engaged */
1658 ospf_router_info_schedule(REORIGINATE_THIS_LSA);
1659 return CMD_SUCCESS;
1660 }
1661
1662
1663 DEFUN (no_router_info,
1664 no_router_info_cmd,
1665 "no router-info",
1666 NO_STR
1667 "Disable the Router Information functionality\n")
1668 {
1669
1670 if (!OspfRI.enabled)
1671 return CMD_SUCCESS;
1672
1673 if (IS_DEBUG_OSPF_EVENT)
1674 zlog_debug("RI-> Router Information: ON -> OFF");
1675
1676 ospf_router_info_schedule(FLUSH_THIS_LSA);
1677
1678 OspfRI.enabled = false;
1679
1680 return CMD_SUCCESS;
1681 }
1682
ospf_ri_enabled(struct vty * vty)1683 static int ospf_ri_enabled(struct vty *vty)
1684 {
1685 if (OspfRI.enabled)
1686 return 1;
1687
1688 if (vty)
1689 vty_out(vty, "%% OSPF RI is not turned on\n");
1690
1691 return 0;
1692 }
1693
1694 DEFUN (pce_address,
1695 pce_address_cmd,
1696 "pce address A.B.C.D",
1697 PCE_STR
1698 "Stable IP address of the PCE\n"
1699 "PCE address in IPv4 address format\n")
1700 {
1701 int idx_ipv4 = 2;
1702 struct in_addr value;
1703 struct ospf_pce_info *pi = &OspfRI.pce_info;
1704
1705 if (!ospf_ri_enabled(vty))
1706 return CMD_WARNING_CONFIG_FAILED;
1707
1708 if (!inet_aton(argv[idx_ipv4]->arg, &value)) {
1709 vty_out(vty, "Please specify PCE Address by A.B.C.D\n");
1710 return CMD_WARNING_CONFIG_FAILED;
1711 }
1712
1713 if (ntohs(pi->pce_address.header.type) == 0
1714 || ntohl(pi->pce_address.address.value.s_addr)
1715 != ntohl(value.s_addr)) {
1716
1717 set_pce_address(value, pi);
1718
1719 /* Refresh RI LSA if already engaged */
1720 ospf_router_info_schedule(REFRESH_THIS_LSA);
1721 }
1722
1723 return CMD_SUCCESS;
1724 }
1725
1726 DEFUN (no_pce_address,
1727 no_pce_address_cmd,
1728 "no pce address [A.B.C.D]",
1729 NO_STR
1730 PCE_STR
1731 "Disable PCE address\n"
1732 "PCE address in IPv4 address format\n")
1733 {
1734
1735 unset_param(&OspfRI.pce_info.pce_address);
1736
1737 /* Refresh RI LSA if already engaged */
1738 ospf_router_info_schedule(REFRESH_THIS_LSA);
1739
1740 return CMD_SUCCESS;
1741 }
1742
1743 DEFUN (pce_path_scope,
1744 pce_path_scope_cmd,
1745 "pce scope BITPATTERN",
1746 PCE_STR
1747 "Path scope visibilities of the PCE for path computation\n"
1748 "32-bit Hexadecimal value\n")
1749 {
1750 int idx_bitpattern = 2;
1751 uint32_t scope;
1752 struct ospf_pce_info *pi = &OspfRI.pce_info;
1753
1754 if (!ospf_ri_enabled(vty))
1755 return CMD_WARNING_CONFIG_FAILED;
1756
1757 if (sscanf(argv[idx_bitpattern]->arg, "0x%x", &scope) != 1) {
1758 vty_out(vty, "pce_path_scope: fscanf: %s\n",
1759 safe_strerror(errno));
1760 return CMD_WARNING_CONFIG_FAILED;
1761 }
1762
1763 if (ntohl(pi->pce_scope.header.type) == 0
1764 || scope != pi->pce_scope.value) {
1765 set_pce_path_scope(scope, pi);
1766
1767 /* Refresh RI LSA if already engaged */
1768 ospf_router_info_schedule(REFRESH_THIS_LSA);
1769 }
1770
1771 return CMD_SUCCESS;
1772 }
1773
1774 DEFUN (no_pce_path_scope,
1775 no_pce_path_scope_cmd,
1776 "no pce scope [BITPATTERN]",
1777 NO_STR
1778 PCE_STR
1779 "Disable PCE path scope\n"
1780 "32-bit Hexadecimal value\n")
1781 {
1782
1783 unset_param(&OspfRI.pce_info.pce_address);
1784
1785 /* Refresh RI LSA if already engaged */
1786 ospf_router_info_schedule(REFRESH_THIS_LSA);
1787
1788 return CMD_SUCCESS;
1789 }
1790
1791 DEFUN (pce_domain,
1792 pce_domain_cmd,
1793 "pce domain as (0-65535)",
1794 PCE_STR
1795 "Configure PCE domain AS number\n"
1796 "AS number where the PCE as visibilities for path computation\n"
1797 "AS number in decimal <0-65535>\n")
1798 {
1799 int idx_number = 3;
1800
1801 uint32_t as;
1802 struct ospf_pce_info *pce = &OspfRI.pce_info;
1803 struct listnode *node;
1804 struct ri_pce_subtlv_domain *domain;
1805
1806 if (!ospf_ri_enabled(vty))
1807 return CMD_WARNING_CONFIG_FAILED;
1808
1809 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
1810 vty_out(vty, "pce_domain: fscanf: %s\n", safe_strerror(errno));
1811 return CMD_WARNING_CONFIG_FAILED;
1812 }
1813
1814 /* Check if the domain is not already in the domain list */
1815 for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
1816 if (ntohl(domain->header.type) == 0 && as == domain->value)
1817 return CMD_SUCCESS;
1818 }
1819
1820 /* Create new domain if not found */
1821 set_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce);
1822
1823 /* Refresh RI LSA if already engaged */
1824 ospf_router_info_schedule(REFRESH_THIS_LSA);
1825
1826 return CMD_SUCCESS;
1827 }
1828
1829 DEFUN (no_pce_domain,
1830 no_pce_domain_cmd,
1831 "no pce domain as (0-65535)",
1832 NO_STR
1833 PCE_STR
1834 "Disable PCE domain AS number\n"
1835 "AS number where the PCE as visibilities for path computation\n"
1836 "AS number in decimal <0-65535>\n")
1837 {
1838 int idx_number = 4;
1839
1840 uint32_t as;
1841 struct ospf_pce_info *pce = &OspfRI.pce_info;
1842
1843 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
1844 vty_out(vty, "no_pce_domain: fscanf: %s\n",
1845 safe_strerror(errno));
1846 return CMD_WARNING_CONFIG_FAILED;
1847 }
1848
1849 /* Unset corresponding PCE domain */
1850 unset_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce);
1851
1852 /* Refresh RI LSA if already engaged */
1853 ospf_router_info_schedule(REFRESH_THIS_LSA);
1854
1855 return CMD_SUCCESS;
1856 }
1857
1858 DEFUN (pce_neigbhor,
1859 pce_neighbor_cmd,
1860 "pce neighbor as (0-65535)",
1861 PCE_STR
1862 "Configure PCE neighbor domain AS number\n"
1863 "AS number of PCE neighbors\n"
1864 "AS number in decimal <0-65535>\n")
1865 {
1866 int idx_number = 3;
1867
1868 uint32_t as;
1869 struct ospf_pce_info *pce = &OspfRI.pce_info;
1870 struct listnode *node;
1871 struct ri_pce_subtlv_neighbor *neighbor;
1872
1873 if (!ospf_ri_enabled(vty))
1874 return CMD_WARNING_CONFIG_FAILED;
1875
1876 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
1877 vty_out(vty, "pce_neighbor: fscanf: %s\n",
1878 safe_strerror(errno));
1879 return CMD_WARNING_CONFIG_FAILED;
1880 }
1881
1882 /* Check if the domain is not already in the domain list */
1883 for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
1884 if (ntohl(neighbor->header.type) == 0 && as == neighbor->value)
1885 return CMD_SUCCESS;
1886 }
1887
1888 /* Create new domain if not found */
1889 set_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce);
1890
1891 /* Refresh RI LSA if already engaged */
1892 ospf_router_info_schedule(REFRESH_THIS_LSA);
1893
1894 return CMD_SUCCESS;
1895 }
1896
1897 DEFUN (no_pce_neighbor,
1898 no_pce_neighbor_cmd,
1899 "no pce neighbor as (0-65535)",
1900 NO_STR
1901 PCE_STR
1902 "Disable PCE neighbor AS number\n"
1903 "AS number of PCE neighbor\n"
1904 "AS number in decimal <0-65535>\n")
1905 {
1906 int idx_number = 4;
1907
1908 uint32_t as;
1909 struct ospf_pce_info *pce = &OspfRI.pce_info;
1910
1911 if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
1912 vty_out(vty, "no_pce_neighbor: fscanf: %s\n",
1913 safe_strerror(errno));
1914 return CMD_WARNING_CONFIG_FAILED;
1915 }
1916
1917 /* Unset corresponding PCE domain */
1918 unset_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce);
1919
1920 /* Refresh RI LSA if already engaged */
1921 ospf_router_info_schedule(REFRESH_THIS_LSA);
1922
1923 return CMD_SUCCESS;
1924 }
1925
1926 DEFUN (pce_cap_flag,
1927 pce_cap_flag_cmd,
1928 "pce flag BITPATTERN",
1929 PCE_STR
1930 "Capabilities of the PCE for path computation\n"
1931 "32-bit Hexadecimal value\n")
1932 {
1933 int idx_bitpattern = 2;
1934
1935 uint32_t cap;
1936 struct ospf_pce_info *pce = &OspfRI.pce_info;
1937
1938 if (!ospf_ri_enabled(vty))
1939 return CMD_WARNING_CONFIG_FAILED;
1940
1941 if (sscanf(argv[idx_bitpattern]->arg, "0x%x", &cap) != 1) {
1942 vty_out(vty, "pce_cap_flag: fscanf: %s\n",
1943 safe_strerror(errno));
1944 return CMD_WARNING_CONFIG_FAILED;
1945 }
1946
1947 if (ntohl(pce->pce_cap_flag.header.type) == 0
1948 || cap != pce->pce_cap_flag.value) {
1949 set_pce_cap_flag(cap, pce);
1950
1951 /* Refresh RI LSA if already engaged */
1952 ospf_router_info_schedule(REFRESH_THIS_LSA);
1953 }
1954
1955 return CMD_SUCCESS;
1956 }
1957
1958 DEFUN (no_pce_cap_flag,
1959 no_pce_cap_flag_cmd,
1960 "no pce flag",
1961 NO_STR
1962 PCE_STR
1963 "Disable PCE capabilities\n")
1964 {
1965
1966 unset_param(&OspfRI.pce_info.pce_cap_flag);
1967
1968 /* Refresh RI LSA if already engaged */
1969 ospf_router_info_schedule(REFRESH_THIS_LSA);
1970
1971 return CMD_SUCCESS;
1972 }
1973
1974 DEFUN (show_ip_ospf_router_info,
1975 show_ip_ospf_router_info_cmd,
1976 "show ip ospf router-info",
1977 SHOW_STR
1978 IP_STR
1979 OSPF_STR
1980 "Router Information\n")
1981 {
1982
1983 if (OspfRI.enabled) {
1984 vty_out(vty, "--- Router Information parameters ---\n");
1985 show_vty_router_cap(vty, &OspfRI.router_cap.header);
1986 } else {
1987 if (vty != NULL)
1988 vty_out(vty,
1989 " Router Information is disabled on this router\n");
1990 }
1991 return CMD_SUCCESS;
1992 }
1993
1994 DEFUN (show_ip_opsf_router_info_pce,
1995 show_ip_ospf_router_info_pce_cmd,
1996 "show ip ospf router-info pce",
1997 SHOW_STR
1998 IP_STR
1999 OSPF_STR
2000 "Router Information\n"
2001 "PCE information\n")
2002 {
2003
2004 struct ospf_pce_info *pce = &OspfRI.pce_info;
2005 struct listnode *node;
2006 struct ri_pce_subtlv_domain *domain;
2007 struct ri_pce_subtlv_neighbor *neighbor;
2008
2009 if ((OspfRI.enabled) && (OspfRI.pce_info.enabled)) {
2010 vty_out(vty, "--- PCE parameters ---\n");
2011
2012 if (pce->pce_address.header.type != 0)
2013 show_vty_pce_subtlv_address(vty,
2014 &pce->pce_address.header);
2015
2016 if (pce->pce_scope.header.type != 0)
2017 show_vty_pce_subtlv_path_scope(vty,
2018 &pce->pce_scope.header);
2019
2020 for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
2021 if (domain->header.type != 0)
2022 show_vty_pce_subtlv_domain(vty,
2023 &domain->header);
2024 }
2025
2026 for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
2027 if (neighbor->header.type != 0)
2028 show_vty_pce_subtlv_neighbor(vty,
2029 &neighbor->header);
2030 }
2031
2032 if (pce->pce_cap_flag.header.type != 0)
2033 show_vty_pce_subtlv_cap_flag(vty,
2034 &pce->pce_cap_flag.header);
2035
2036 } else {
2037 vty_out(vty, " PCE info is disabled on this router\n");
2038 }
2039
2040 return CMD_SUCCESS;
2041 }
2042
2043 /* Install new CLI commands */
ospf_router_info_register_vty(void)2044 static void ospf_router_info_register_vty(void)
2045 {
2046 install_element(VIEW_NODE, &show_ip_ospf_router_info_cmd);
2047 install_element(VIEW_NODE, &show_ip_ospf_router_info_pce_cmd);
2048
2049 install_element(OSPF_NODE, &router_info_area_cmd);
2050 install_element(OSPF_NODE, &no_router_info_cmd);
2051 install_element(OSPF_NODE, &pce_address_cmd);
2052 install_element(OSPF_NODE, &no_pce_address_cmd);
2053 install_element(OSPF_NODE, &pce_path_scope_cmd);
2054 install_element(OSPF_NODE, &no_pce_path_scope_cmd);
2055 install_element(OSPF_NODE, &pce_domain_cmd);
2056 install_element(OSPF_NODE, &no_pce_domain_cmd);
2057 install_element(OSPF_NODE, &pce_neighbor_cmd);
2058 install_element(OSPF_NODE, &no_pce_neighbor_cmd);
2059 install_element(OSPF_NODE, &pce_cap_flag_cmd);
2060 install_element(OSPF_NODE, &no_pce_cap_flag_cmd);
2061
2062 return;
2063 }
2064