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