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