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