2 * This is an implementation of RFC4970 Router Information
3 * with support of RFC5088 PCE Capabilites announcement
5 * Module name: Router Information
6 * Author: Olivier Dugeon <olivier.dugeon@orange.com>
7 * Copyright (C) 2012 - 2017 Orange Labs http://www.orange.com/
9 * This file is part of GNU Quagga.
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
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.
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
40 #include "sockunion.h" /* for inet_aton() */
43 #include "ospfd/ospfd.h"
44 #include "ospfd/ospf_interface.h"
45 #include "ospfd/ospf_ism.h"
46 #include "ospfd/ospf_asbr.h"
47 #include "ospfd/ospf_lsa.h"
48 #include "ospfd/ospf_lsdb.h"
49 #include "ospfd/ospf_neighbor.h"
50 #include "ospfd/ospf_nsm.h"
51 #include "ospfd/ospf_flood.h"
52 #include "ospfd/ospf_packet.h"
53 #include "ospfd/ospf_spf.h"
54 #include "ospfd/ospf_dump.h"
55 #include "ospfd/ospf_route.h"
56 #include "ospfd/ospf_ase.h"
57 #include "ospfd/ospf_zebra.h"
58 #include "ospfd/ospf_sr.h"
59 #include "ospfd/ospf_ri.h"
60 #include "ospfd/ospf_errors.h"
63 * Global variable to manage Opaque-LSA/Router Information on this node.
64 * Note that all parameter values are stored in network byte order.
66 static struct ospf_router_info OspfRI
;
68 /*------------------------------------------------------------------------------*
69 * Followings are initialize/terminate functions for Router Information
71 *------------------------------------------------------------------------------*/
73 static void ospf_router_info_ism_change(struct ospf_interface
*oi
,
75 static void ospf_router_info_config_write_router(struct vty
*vty
);
76 static void ospf_router_info_show_info(struct vty
*vty
, struct ospf_lsa
*lsa
);
77 static int ospf_router_info_lsa_originate(void *arg
);
78 static struct ospf_lsa
*ospf_router_info_lsa_refresh(struct ospf_lsa
*lsa
);
79 static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info
*ai
,
80 enum lsa_opcode opcode
);
81 static void ospf_router_info_register_vty(void);
82 static int ospf_router_info_lsa_update(struct ospf_lsa
*lsa
);
83 static void del_area_info(void *val
);
84 static void del_pce_info(void *val
);
86 int ospf_router_info_init(void)
89 zlog_info("RI (%s): Initialize Router Information", __func__
);
91 memset(&OspfRI
, 0, sizeof(struct ospf_router_info
));
92 OspfRI
.enabled
= false;
93 OspfRI
.registered
= 0;
94 OspfRI
.scope
= OSPF_OPAQUE_AS_LSA
;
95 OspfRI
.as_flags
= RIFLG_LSA_INACTIVE
;
96 OspfRI
.area_info
= list_new();
97 OspfRI
.area_info
->del
= del_area_info
;
99 /* Initialize pce domain and neighbor list */
100 OspfRI
.pce_info
.enabled
= false;
101 OspfRI
.pce_info
.pce_domain
= list_new();
102 OspfRI
.pce_info
.pce_domain
->del
= del_pce_info
;
103 OspfRI
.pce_info
.pce_neighbor
= list_new();
104 OspfRI
.pce_info
.pce_neighbor
->del
= del_pce_info
;
106 /* Initialize Segment Routing information structure */
107 OspfRI
.sr_info
.enabled
= false;
109 ospf_router_info_register_vty();
114 static int ospf_router_info_register(uint8_t scope
)
118 if (OspfRI
.registered
)
121 zlog_info("RI (%s): Register Router Information with scope %s(%d)",
123 scope
== OSPF_OPAQUE_AREA_LSA
? "Area" : "AS", scope
);
124 rc
= ospf_register_opaque_functab(
125 scope
, OPAQUE_TYPE_ROUTER_INFORMATION_LSA
,
126 NULL
, /* new interface */
127 NULL
, /* del interface */
128 ospf_router_info_ism_change
,
129 NULL
, /* NSM change */
130 ospf_router_info_config_write_router
,
131 NULL
, /* Config. write interface */
132 NULL
, /* Config. write debug */
133 ospf_router_info_show_info
, ospf_router_info_lsa_originate
,
134 ospf_router_info_lsa_refresh
, ospf_router_info_lsa_update
,
135 NULL
); /* del_lsa_hook */
139 EC_OSPF_OPAQUE_REGISTRATION
,
140 "RI (%s): Failed to register functions", __func__
);
144 OspfRI
.registered
= 1;
145 OspfRI
.scope
= scope
;
149 static int ospf_router_info_unregister(void)
152 if ((OspfRI
.scope
!= OSPF_OPAQUE_AS_LSA
)
153 && (OspfRI
.scope
!= OSPF_OPAQUE_AREA_LSA
)) {
154 assert("Unable to unregister Router Info functions: Wrong scope!"
159 ospf_delete_opaque_functab(OspfRI
.scope
,
160 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
162 OspfRI
.registered
= 0;
166 void ospf_router_info_term(void)
169 list_delete(&OspfRI
.pce_info
.pce_domain
);
170 list_delete(&OspfRI
.pce_info
.pce_neighbor
);
172 OspfRI
.enabled
= false;
174 ospf_router_info_unregister();
179 void ospf_router_info_finish(void)
181 struct listnode
*node
, *nnode
;
182 struct ospf_ri_area_info
*ai
;
184 /* Flush Router Info LSA */
185 for (ALL_LIST_ELEMENTS(OspfRI
.area_info
, node
, nnode
, ai
))
186 if (CHECK_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
))
187 ospf_router_info_lsa_schedule(ai
, FLUSH_THIS_LSA
);
189 list_delete_all_node(OspfRI
.pce_info
.pce_domain
);
190 list_delete_all_node(OspfRI
.pce_info
.pce_neighbor
);
192 OspfRI
.enabled
= false;
195 static void del_area_info(void *val
)
197 XFREE(MTYPE_OSPF_ROUTER_INFO
, val
);
200 static void del_pce_info(void *val
)
202 XFREE(MTYPE_OSPF_PCE_PARAMS
, val
);
205 /* Catch RI LSA flooding Scope for ospf_ext.[h,c] code */
206 struct scope_info
ospf_router_info_get_flooding_scope(void)
208 struct scope_info flooding_scope
;
210 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
) {
211 flooding_scope
.scope
= OSPF_OPAQUE_AS_LSA
;
212 flooding_scope
.areas
= NULL
;
213 return flooding_scope
;
215 flooding_scope
.scope
= OSPF_OPAQUE_AREA_LSA
;
216 flooding_scope
.areas
= OspfRI
.area_info
;
217 return flooding_scope
;
220 static struct ospf_ri_area_info
*lookup_by_area(struct ospf_area
*area
)
222 struct listnode
*node
, *nnode
;
223 struct ospf_ri_area_info
*ai
;
225 for (ALL_LIST_ELEMENTS(OspfRI
.area_info
, node
, nnode
, ai
))
226 if (ai
->area
== area
)
232 /*------------------------------------------------------------------------*
233 * Followings are control functions for ROUTER INFORMATION parameters
235 *------------------------------------------------------------------------*/
237 static void set_router_info_capabilities(struct ri_tlv_router_cap
*ric
,
240 ric
->header
.type
= htons(RI_TLV_CAPABILITIES
);
241 ric
->header
.length
= htons(RI_TLV_LENGTH
);
242 ric
->value
= htonl(cap
);
246 static int set_pce_header(struct ospf_pce_info
*pce
)
249 struct listnode
*node
;
250 struct ri_pce_subtlv_domain
*domain
;
251 struct ri_pce_subtlv_neighbor
*neighbor
;
254 if (ntohs(pce
->pce_address
.header
.type
) != 0)
255 length
+= TLV_SIZE(&pce
->pce_address
.header
);
258 if (ntohs(pce
->pce_scope
.header
.type
) != 0)
259 length
+= TLV_SIZE(&pce
->pce_scope
.header
);
262 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
263 if (ntohs(domain
->header
.type
) != 0)
264 length
+= TLV_SIZE(&domain
->header
);
268 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
269 if (ntohs(neighbor
->header
.type
) != 0)
270 length
+= TLV_SIZE(&neighbor
->header
);
273 /* PCE Capabilities */
274 if (ntohs(pce
->pce_cap_flag
.header
.type
) != 0)
275 length
+= TLV_SIZE(&pce
->pce_cap_flag
.header
);
278 pce
->pce_header
.header
.type
= htons(RI_TLV_PCE
);
279 pce
->pce_header
.header
.length
= htons(length
);
282 pce
->pce_header
.header
.type
= 0;
283 pce
->pce_header
.header
.length
= 0;
284 pce
->enabled
= false;
290 static void set_pce_address(struct in_addr ipv4
, struct ospf_pce_info
*pce
)
293 /* Enable PCE Info */
294 pce
->pce_header
.header
.type
= htons(RI_TLV_PCE
);
295 /* Set PCE Address */
296 pce
->pce_address
.header
.type
= htons(RI_PCE_SUBTLV_ADDRESS
);
297 pce
->pce_address
.header
.length
= htons(PCE_ADDRESS_IPV4_SIZE
);
298 pce
->pce_address
.address
.type
= htons(PCE_ADDRESS_IPV4
);
299 pce
->pce_address
.address
.value
= ipv4
;
304 static void set_pce_path_scope(uint32_t scope
, struct ospf_pce_info
*pce
)
308 pce
->pce_scope
.header
.type
= htons(RI_PCE_SUBTLV_PATH_SCOPE
);
309 pce
->pce_scope
.header
.length
= htons(RI_TLV_LENGTH
);
310 pce
->pce_scope
.value
= htonl(scope
);
315 static void set_pce_domain(uint16_t type
, uint32_t domain
,
316 struct ospf_pce_info
*pce
)
319 struct ri_pce_subtlv_domain
*new;
321 /* Create new domain info */
322 new = XCALLOC(MTYPE_OSPF_PCE_PARAMS
,
323 sizeof(struct ri_pce_subtlv_domain
));
325 new->header
.type
= htons(RI_PCE_SUBTLV_DOMAIN
);
326 new->header
.length
= htons(PCE_ADDRESS_IPV4_SIZE
);
327 new->type
= htons(type
);
328 new->value
= htonl(domain
);
330 /* Add new domain to the list */
331 listnode_add(pce
->pce_domain
, new);
336 static void unset_pce_domain(uint16_t type
, uint32_t domain
,
337 struct ospf_pce_info
*pce
)
339 struct listnode
*node
;
340 struct ri_pce_subtlv_domain
*old
= NULL
;
343 /* Search the corresponding node */
344 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, old
)) {
345 if ((old
->type
== htons(type
))
346 && (old
->value
== htonl(domain
))) {
352 /* if found remove it */
354 listnode_delete(pce
->pce_domain
, old
);
356 /* Finally free the old domain */
357 XFREE(MTYPE_OSPF_PCE_PARAMS
, old
);
361 static void set_pce_neighbor(uint16_t type
, uint32_t domain
,
362 struct ospf_pce_info
*pce
)
365 struct ri_pce_subtlv_neighbor
*new;
367 /* Create new neighbor info */
368 new = XCALLOC(MTYPE_OSPF_PCE_PARAMS
,
369 sizeof(struct ri_pce_subtlv_neighbor
));
371 new->header
.type
= htons(RI_PCE_SUBTLV_NEIGHBOR
);
372 new->header
.length
= htons(PCE_ADDRESS_IPV4_SIZE
);
373 new->type
= htons(type
);
374 new->value
= htonl(domain
);
376 /* Add new domain to the list */
377 listnode_add(pce
->pce_neighbor
, new);
382 static void unset_pce_neighbor(uint16_t type
, uint32_t domain
,
383 struct ospf_pce_info
*pce
)
385 struct listnode
*node
;
386 struct ri_pce_subtlv_neighbor
*old
= NULL
;
389 /* Search the corresponding node */
390 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, old
)) {
391 if ((old
->type
== htons(type
))
392 && (old
->value
== htonl(domain
))) {
398 /* if found remove it */
400 listnode_delete(pce
->pce_neighbor
, old
);
402 /* Finally free the old domain */
403 XFREE(MTYPE_OSPF_PCE_PARAMS
, old
);
407 static void set_pce_cap_flag(uint32_t cap
, struct ospf_pce_info
*pce
)
410 /* Set PCE Capabilities flag */
411 pce
->pce_cap_flag
.header
.type
= htons(RI_PCE_SUBTLV_CAP_FLAG
);
412 pce
->pce_cap_flag
.header
.length
= htons(RI_TLV_LENGTH
);
413 pce
->pce_cap_flag
.value
= htonl(cap
);
418 /* Segment Routing TLV setter */
420 /* Algorithm SubTLV - section 3.1 */
421 static void set_sr_algorithm(uint8_t algo
)
424 OspfRI
.sr_info
.algo
.value
[0] = algo
;
425 for (int i
= 1; i
< ALGORITHM_COUNT
; i
++)
426 OspfRI
.sr_info
.algo
.value
[i
] = SR_ALGORITHM_UNSET
;
428 /* Set TLV type and length == only 1 Algorithm */
429 TLV_TYPE(OspfRI
.sr_info
.algo
) = htons(RI_SR_TLV_SR_ALGORITHM
);
430 TLV_LEN(OspfRI
.sr_info
.algo
) = htons(sizeof(uint8_t));
433 /* unset Aglogithm SubTLV */
434 static void unset_sr_algorithm(uint8_t algo
)
437 for (int i
= 0; i
< ALGORITHM_COUNT
; i
++)
438 OspfRI
.sr_info
.algo
.value
[i
] = SR_ALGORITHM_UNSET
;
440 /* Unset TLV type and length */
441 TLV_TYPE(OspfRI
.sr_info
.algo
) = htons(0);
442 TLV_LEN(OspfRI
.sr_info
.algo
) = htons(0);
445 /* Set Segment Routing Global Block SubTLV - section 3.2 */
446 static void set_sr_global_label_range(struct sr_block srgb
)
449 TLV_TYPE(OspfRI
.sr_info
.srgb
) = htons(RI_SR_TLV_SRGB_LABEL_RANGE
);
450 TLV_LEN(OspfRI
.sr_info
.srgb
) = htons(RI_SR_TLV_LABEL_RANGE_SIZE
);
452 OspfRI
.sr_info
.srgb
.size
= htonl(SET_RANGE_SIZE(srgb
.range_size
));
453 /* Set Lower bound label SubTLV */
454 TLV_TYPE(OspfRI
.sr_info
.srgb
.lower
) = htons(SUBTLV_SID_LABEL
);
455 TLV_LEN(OspfRI
.sr_info
.srgb
.lower
) = htons(SID_RANGE_LABEL_LENGTH
);
456 OspfRI
.sr_info
.srgb
.lower
.value
= htonl(SET_LABEL(srgb
.lower_bound
));
459 /* Unset Segment Routing Global Block SubTLV */
460 static void unset_sr_global_label_range(void)
462 TLV_TYPE(OspfRI
.sr_info
.srgb
) = htons(0);
463 TLV_LEN(OspfRI
.sr_info
.srgb
) = htons(0);
464 TLV_TYPE(OspfRI
.sr_info
.srgb
.lower
) = htons(0);
465 TLV_LEN(OspfRI
.sr_info
.srgb
.lower
) = htons(0);
468 /* Set Segment Routing Local Block SubTLV - section 3.2 */
469 static void set_sr_local_label_range(struct sr_block srlb
)
472 TLV_TYPE(OspfRI
.sr_info
.srlb
) = htons(RI_SR_TLV_SRLB_LABEL_RANGE
);
473 TLV_LEN(OspfRI
.sr_info
.srlb
) = htons(RI_SR_TLV_LABEL_RANGE_SIZE
);
475 OspfRI
.sr_info
.srlb
.size
= htonl(SET_RANGE_SIZE(srlb
.range_size
));
476 /* Set Lower bound label SubTLV */
477 TLV_TYPE(OspfRI
.sr_info
.srlb
.lower
) = htons(SUBTLV_SID_LABEL
);
478 TLV_LEN(OspfRI
.sr_info
.srlb
.lower
) = htons(SID_RANGE_LABEL_LENGTH
);
479 OspfRI
.sr_info
.srlb
.lower
.value
= htonl(SET_LABEL(srlb
.lower_bound
));
482 /* Unset Segment Routing Local Block SubTLV */
483 static void unset_sr_local_label_range(void)
485 TLV_TYPE(OspfRI
.sr_info
.srlb
) = htons(0);
486 TLV_LEN(OspfRI
.sr_info
.srlb
) = htons(0);
487 TLV_TYPE(OspfRI
.sr_info
.srlb
.lower
) = htons(0);
488 TLV_LEN(OspfRI
.sr_info
.srlb
.lower
) = htons(0);
491 /* Set Maximum Stack Depth for this router */
492 static void set_sr_node_msd(uint8_t msd
)
494 TLV_TYPE(OspfRI
.sr_info
.msd
) = htons(RI_SR_TLV_NODE_MSD
);
495 TLV_LEN(OspfRI
.sr_info
.msd
) = htons(sizeof(uint32_t));
496 OspfRI
.sr_info
.msd
.value
= msd
;
499 /* Unset this router MSD */
500 static void unset_sr_node_msd(void)
502 TLV_TYPE(OspfRI
.sr_info
.msd
) = htons(0);
503 TLV_LEN(OspfRI
.sr_info
.msd
) = htons(0);
506 static void unset_param(void *tlv_buffer
)
508 struct tlv_header
*tlv
= (struct tlv_header
*)tlv_buffer
;
511 /* Fill the Value to 0 */
512 memset(TLV_DATA(tlv_buffer
), 0, TLV_BODY_SIZE(tlv
));
518 static void initialize_params(struct ospf_router_info
*ori
)
522 struct listnode
*node
, *nnode
;
523 struct ospf_area
*area
;
524 struct ospf_ri_area_info
*new;
527 * Initialize default Router Information Capabilities.
531 set_router_info_capabilities(&ori
->router_cap
, cap
);
533 /* If Area address is not null and exist, retrieve corresponding
535 top
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
536 zlog_info("RI (%s): Initialize Router Info for %s scope", __func__
,
537 OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
? "Area" : "AS");
539 /* Try to get available Area's context from ospf at this step.
540 * Do it latter if not available */
541 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) {
542 if (!list_isempty(OspfRI
.area_info
))
543 list_delete_all_node(OspfRI
.area_info
);
544 for (ALL_LIST_ELEMENTS(top
->areas
, node
, nnode
, area
)) {
545 zlog_debug("RI (%s): Add area %pI4 to Router Information",
546 __func__
, &area
->area_id
);
547 new = XCALLOC(MTYPE_OSPF_ROUTER_INFO
,
548 sizeof(struct ospf_ri_area_info
));
550 new->flags
= RIFLG_LSA_INACTIVE
;
551 listnode_add(OspfRI
.area_info
, new);
556 * Initialize default PCE Information values
558 /* PCE address == OSPF Router ID */
559 set_pce_address(top
->router_id
, &ori
->pce_info
);
562 cap
= 7; /* Set L, R and Rd bits to one = intra & inter-area path
564 set_pce_path_scope(cap
, &ori
->pce_info
);
566 /* PCE Capabilities */
567 cap
= PCE_CAP_BIDIRECTIONAL
| PCE_CAP_DIVERSE_PATH
| PCE_CAP_OBJECTIVES
568 | PCE_CAP_ADDITIVE
| PCE_CAP_MULTIPLE_REQ
;
569 set_pce_cap_flag(cap
, &ori
->pce_info
);
574 static int is_mandated_params_set(struct ospf_router_info
*ori
)
581 if (ntohs(ori
->router_cap
.header
.type
) == 0)
584 if ((ntohs(ori
->pce_info
.pce_header
.header
.type
) == RI_TLV_PCE
)
585 && (ntohs(ori
->pce_info
.pce_address
.header
.type
) == 0)
586 && (ntohs(ori
->pce_info
.pce_cap_flag
.header
.type
) == 0))
589 if ((ori
->sr_info
.enabled
) && (ntohs(TLV_TYPE(ori
->sr_info
.algo
)) == 0)
590 && (ntohs(TLV_TYPE(ori
->sr_info
.srgb
)) == 0))
599 * Used by Segment Routing to set new TLVs and Sub-TLVs values
601 * @param enable To activate or not Segment Routing router Information flooding
602 * @param srn Self Segment Routing node
606 void ospf_router_info_update_sr(bool enable
, struct sr_node
*srn
)
608 struct listnode
*node
, *nnode
;
609 struct ospf_ri_area_info
*ai
;
611 /* First, check if Router Information is registered or not */
612 if (!OspfRI
.registered
)
613 ospf_router_info_register(OSPF_OPAQUE_AREA_LSA
);
615 /* Verify that scope is AREA */
616 if (OspfRI
.scope
!= OSPF_OPAQUE_AREA_LSA
) {
618 "RI (%s): Router Info is %s flooding: Change scope to Area flooding for Segment Routing",
620 OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
? "Area" : "AS");
624 /* Then, activate and initialize Router Information if necessary */
625 if (!OspfRI
.enabled
) {
626 OspfRI
.enabled
= true;
627 initialize_params(&OspfRI
);
630 /* Check that SR node is valid */
634 if (IS_DEBUG_OSPF_SR
)
635 zlog_debug("RI (%s): %s Routing Information for Segment Routing",
636 __func__
, enable
? "Enable" : "Disable");
638 /* Unset or Set SR parameters */
640 unset_sr_algorithm(SR_ALGORITHM_SPF
);
641 unset_sr_global_label_range();
642 unset_sr_local_label_range();
644 OspfRI
.sr_info
.enabled
= false;
646 // Only SR_ALGORITHM_SPF is supported
647 set_sr_algorithm(SR_ALGORITHM_SPF
);
648 set_sr_global_label_range(srn
->srgb
);
649 set_sr_local_label_range(srn
->srlb
);
651 set_sr_node_msd(srn
->msd
);
654 OspfRI
.sr_info
.enabled
= true;
657 /* Refresh if already engaged or originate RI LSA */
658 for (ALL_LIST_ELEMENTS(OspfRI
.area_info
, node
, nnode
, ai
)) {
659 if (CHECK_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
))
660 ospf_router_info_lsa_schedule(ai
, REFRESH_THIS_LSA
);
662 ospf_router_info_lsa_schedule(ai
,
663 REORIGINATE_THIS_LSA
);
668 /*------------------------------------------------------------------------*
669 * Followings are callback functions against generic Opaque-LSAs handling.
670 *------------------------------------------------------------------------*/
671 static void ospf_router_info_ism_change(struct ospf_interface
*oi
,
675 struct ospf_ri_area_info
*ai
;
677 /* Collect area information */
678 ai
= lookup_by_area(oi
->area
);
680 /* Check if area is not yet registered */
684 /* Add this new area to the list */
685 ai
= XCALLOC(MTYPE_OSPF_ROUTER_INFO
, sizeof(struct ospf_ri_area_info
));
687 ai
->flags
= RIFLG_LSA_INACTIVE
;
688 listnode_add(OspfRI
.area_info
, ai
);
693 /*------------------------------------------------------------------------*
694 * Followings are OSPF protocol processing functions for ROUTER INFORMATION
695 *------------------------------------------------------------------------*/
697 static void build_tlv_header(struct stream
*s
, struct tlv_header
*tlvh
)
700 stream_put(s
, tlvh
, sizeof(struct tlv_header
));
704 static void build_tlv(struct stream
*s
, struct tlv_header
*tlvh
)
707 if (ntohs(tlvh
->type
) != 0) {
708 build_tlv_header(s
, tlvh
);
709 stream_put(s
, TLV_DATA(tlvh
), TLV_BODY_SIZE(tlvh
));
714 static void ospf_router_info_lsa_body_set(struct stream
*s
)
717 struct listnode
*node
;
718 struct ri_pce_subtlv_domain
*domain
;
719 struct ri_pce_subtlv_neighbor
*neighbor
;
721 /* Build Router Information TLV */
722 build_tlv(s
, &OspfRI
.router_cap
.header
);
724 /* Build Segment Routing TLVs if enabled */
725 if (OspfRI
.sr_info
.enabled
) {
726 /* Build Algorithm TLV */
727 build_tlv(s
, &TLV_HDR(OspfRI
.sr_info
.algo
));
729 build_tlv(s
, &TLV_HDR(OspfRI
.sr_info
.srgb
));
731 build_tlv(s
, &TLV_HDR(OspfRI
.sr_info
.srlb
));
733 build_tlv(s
, &TLV_HDR(OspfRI
.sr_info
.msd
));
736 /* Add RI PCE TLV if it is set */
737 if (OspfRI
.pce_info
.enabled
) {
739 /* Compute PCE Info header first */
740 set_pce_header(&OspfRI
.pce_info
);
743 build_tlv_header(s
, &OspfRI
.pce_info
.pce_header
.header
);
745 /* Build PCE address sub-tlv */
746 build_tlv(s
, &OspfRI
.pce_info
.pce_address
.header
);
748 /* Build PCE path scope sub-tlv */
749 build_tlv(s
, &OspfRI
.pce_info
.pce_scope
.header
);
751 /* Build PCE domain sub-tlv */
752 for (ALL_LIST_ELEMENTS_RO(OspfRI
.pce_info
.pce_domain
, node
,
754 build_tlv(s
, &domain
->header
);
756 /* Build PCE neighbor sub-tlv */
757 for (ALL_LIST_ELEMENTS_RO(OspfRI
.pce_info
.pce_neighbor
, node
,
759 build_tlv(s
, &neighbor
->header
);
761 /* Build PCE cap flag sub-tlv */
762 build_tlv(s
, &OspfRI
.pce_info
.pce_cap_flag
.header
);
768 /* Create new opaque-LSA. */
769 static struct ospf_lsa
*ospf_router_info_lsa_new(struct ospf_area
*area
)
773 struct lsa_header
*lsah
;
774 struct ospf_lsa
*new = NULL
;
775 uint8_t options
, lsa_type
;
776 struct in_addr lsa_id
;
780 /* Create a stream for LSA. */
781 s
= stream_new(OSPF_MAX_LSA_SIZE
);
783 lsah
= (struct lsa_header
*)STREAM_DATA(s
);
785 options
= OSPF_OPTION_E
; /* Enable AS external as we flood RI with
787 options
|= OSPF_OPTION_O
; /* Don't forget this :-) */
789 lsa_type
= OspfRI
.scope
;
790 /* LSA ID == 0 for Router Information see RFC 4970 */
791 tmp
= SET_OPAQUE_LSID(OPAQUE_TYPE_ROUTER_INFORMATION_LSA
, 0);
792 lsa_id
.s_addr
= htonl(tmp
);
794 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
))
796 "LSA[Type%d:%pI4]: Create an Opaque-LSA/ROUTER INFORMATION instance",
799 top
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
801 /* Set opaque-LSA header fields. */
802 lsa_header_set(s
, options
, lsa_type
, lsa_id
, top
->router_id
);
804 /* Set opaque-LSA body fields. */
805 ospf_router_info_lsa_body_set(s
);
808 length
= stream_get_endp(s
);
809 lsah
->length
= htons(length
);
811 /* Now, create an OSPF LSA instance. */
812 new = ospf_lsa_new_and_data(length
);
816 if (new->area
&& new->area
->ospf
)
817 new->vrf_id
= new->area
->ospf
->vrf_id
;
819 new->vrf_id
= VRF_DEFAULT
;
821 SET_FLAG(new->flags
, OSPF_LSA_SELF
);
822 memcpy(new->data
, lsah
, length
);
828 static int ospf_router_info_lsa_originate_as(void *arg
)
830 struct ospf_lsa
*new;
833 vrf_id_t vrf_id
= VRF_DEFAULT
;
836 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) {
838 EC_OSPF_LSA_INSTALL_FAILURE
,
839 "RI (%s): wrong flooding scope AREA instead of AS ?",
844 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
845 new = ospf_router_info_lsa_new(NULL
);
846 new->vrf_id
= VRF_DEFAULT
;
847 top
= (struct ospf
*)arg
;
849 /* Check ospf info */
851 zlog_debug("RI (%s): ospf instance not found for vrf id %u",
853 ospf_lsa_unlock(&new);
857 /* Install this LSA into LSDB. */
858 if (ospf_lsa_install(top
, NULL
/*oi */, new) == NULL
) {
860 EC_OSPF_LSA_INSTALL_FAILURE
,
861 "RI (%s): ospf_lsa_install() ?", __func__
);
862 ospf_lsa_unlock(&new);
866 /* Update new LSA origination count. */
867 top
->lsa_originate_count
++;
869 /* Flood new LSA through AREA or AS. */
870 SET_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
);
871 ospf_flood_through_as(top
, NULL
/*nbr */, new);
873 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
875 "LSA[Type%d:%pI4]: Originate Opaque-LSA/ROUTER INFORMATION",
876 new->data
->type
, &new->data
->id
);
877 ospf_lsa_header_dump(new->data
);
884 static int ospf_router_info_lsa_originate_area(void *arg
)
886 struct ospf_lsa
*new;
888 struct ospf_ri_area_info
*ai
= NULL
;
890 vrf_id_t vrf_id
= VRF_DEFAULT
;
893 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
) {
895 EC_OSPF_LSA_INSTALL_FAILURE
,
896 "RI (%s): wrong flooding scope AS instead of AREA ?",
901 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
902 ai
= lookup_by_area((struct ospf_area
*)arg
);
905 "RI (%s): There is no context for this Router Information. Stop processing",
909 if (ai
->area
->ospf
) {
910 vrf_id
= ai
->area
->ospf
->vrf_id
;
911 top
= ai
->area
->ospf
;
913 top
= ospf_lookup_by_vrf_id(vrf_id
);
915 new = ospf_router_info_lsa_new(ai
->area
);
916 new->vrf_id
= vrf_id
;
918 /* Check ospf info */
920 zlog_debug("RI (%s): ospf instance not found for vrf id %u",
922 ospf_lsa_unlock(&new);
926 /* Install this LSA into LSDB. */
927 if (ospf_lsa_install(top
, NULL
/*oi */, new) == NULL
) {
929 EC_OSPF_LSA_INSTALL_FAILURE
,
930 "RI (%s): ospf_lsa_install() ?", __func__
);
931 ospf_lsa_unlock(&new);
935 /* Update new LSA origination count. */
936 top
->lsa_originate_count
++;
938 /* Flood new LSA through AREA or AS. */
939 SET_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
);
940 ospf_flood_through_area(ai
->area
, NULL
/*nbr */, new);
942 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
944 "LSA[Type%d:%pI4]: Originate Opaque-LSA/ROUTER INFORMATION",
945 new->data
->type
, &new->data
->id
);
946 ospf_lsa_header_dump(new->data
);
953 static int ospf_router_info_lsa_originate(void *arg
)
956 struct ospf_ri_area_info
*ai
;
959 if (!OspfRI
.enabled
) {
960 zlog_info("RI (%s): ROUTER INFORMATION is disabled now.",
962 rc
= 0; /* This is not an error case. */
966 /* Check if Router Information LSA is already engaged */
967 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
) {
968 if ((CHECK_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
))
969 && (CHECK_FLAG(OspfRI
.as_flags
,
970 RIFLG_LSA_FORCED_REFRESH
))) {
971 UNSET_FLAG(OspfRI
.as_flags
, RIFLG_LSA_FORCED_REFRESH
);
972 ospf_router_info_lsa_schedule(NULL
, REFRESH_THIS_LSA
);
977 ai
= lookup_by_area((struct ospf_area
*)arg
);
981 "RI (%s): Missing area information", __func__
);
984 if ((CHECK_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
))
985 && (CHECK_FLAG(ai
->flags
, RIFLG_LSA_FORCED_REFRESH
))) {
986 UNSET_FLAG(ai
->flags
, RIFLG_LSA_FORCED_REFRESH
);
987 ospf_router_info_lsa_schedule(ai
, REFRESH_THIS_LSA
);
993 /* Router Information is not yet Engaged, check parameters */
994 if (!is_mandated_params_set(&OspfRI
))
997 "RI (%s): lacks mandated ROUTER INFORMATION parameters",
1000 /* Ok, let's try to originate an LSA */
1001 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
)
1002 rc
= ospf_router_info_lsa_originate_as(arg
);
1004 rc
= ospf_router_info_lsa_originate_area(arg
);
1009 static struct ospf_lsa
*ospf_router_info_lsa_refresh(struct ospf_lsa
*lsa
)
1011 struct ospf_ri_area_info
*ai
= NULL
;
1012 struct ospf_lsa
*new = NULL
;
1015 if (!OspfRI
.enabled
) {
1017 * This LSA must have flushed before due to ROUTER INFORMATION
1019 * It seems a slip among routers in the routing domain.
1021 zlog_info("RI (%s): ROUTER INFORMATION is disabled now.",
1024 htons(OSPF_LSA_MAXAGE
); /* Flush it anyway. */
1027 /* Verify that the Router Information ID is supported */
1028 if (GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)) != 0) {
1031 "RI (%s): Unsupported Router Information ID",
1036 /* Process LSA depending of the flooding scope */
1037 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) {
1038 /* Get context AREA context */
1039 ai
= lookup_by_area(lsa
->area
);
1043 "RI (%s): No associated Area", __func__
);
1046 /* Flush LSA, if the lsa's age reached to MaxAge. */
1047 if (IS_LSA_MAXAGE(lsa
)) {
1048 UNSET_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
);
1049 ospf_opaque_lsa_flush_schedule(lsa
);
1052 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
1053 new = ospf_router_info_lsa_new(ai
->area
);
1054 new->data
->ls_seqnum
= lsa_seqnum_increment(lsa
);
1055 new->vrf_id
= lsa
->vrf_id
;
1056 /* Install this LSA into LSDB. */
1057 /* Given "lsa" will be freed in the next function. */
1058 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
1059 if (ospf_lsa_install(top
, NULL
/*oi */, new) == NULL
) {
1060 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE
,
1061 "RI (%s): ospf_lsa_install() ?", __func__
);
1062 ospf_lsa_unlock(&new);
1065 /* Flood updated LSA through AREA */
1066 ospf_flood_through_area(ai
->area
, NULL
/*nbr */, new);
1068 } else { /* AS Flooding scope */
1069 /* Flush LSA, if the lsa's age reached to MaxAge. */
1070 if (IS_LSA_MAXAGE(lsa
)) {
1071 UNSET_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
);
1072 ospf_opaque_lsa_flush_schedule(lsa
);
1075 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
1076 new = ospf_router_info_lsa_new(NULL
);
1077 new->data
->ls_seqnum
= lsa_seqnum_increment(lsa
);
1078 new->vrf_id
= lsa
->vrf_id
;
1079 /* Install this LSA into LSDB. */
1080 /* Given "lsa" will be freed in the next function. */
1081 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
1082 if (ospf_lsa_install(top
, NULL
/*oi */, new) == NULL
) {
1083 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE
,
1084 "RI (%s): ospf_lsa_install() ?", __func__
);
1085 ospf_lsa_unlock(&new);
1088 /* Flood updated LSA through AS */
1089 ospf_flood_through_as(top
, NULL
/*nbr */, new);
1092 /* Debug logging. */
1093 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
1095 "LSA[Type%d:%pI4]: Refresh Opaque-LSA/ROUTER INFORMATION",
1096 new->data
->type
, &new->data
->id
);
1097 ospf_lsa_header_dump(new->data
);
1103 static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info
*ai
,
1104 enum lsa_opcode opcode
)
1106 struct ospf_lsa lsa
;
1107 struct lsa_header lsah
;
1111 memset(&lsa
, 0, sizeof(lsa
));
1112 memset(&lsah
, 0, sizeof(lsah
));
1114 zlog_debug("RI (%s): LSA schedule %s%s%s", __func__
,
1115 opcode
== REORIGINATE_THIS_LSA
? "Re-Originate" : "",
1116 opcode
== REFRESH_THIS_LSA
? "Refresh" : "",
1117 opcode
== FLUSH_THIS_LSA
? "Flush" : "");
1119 /* Check LSA flags state coherence and collect area information */
1120 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) {
1121 if ((ai
== NULL
) || (ai
->area
== NULL
)) {
1124 "RI (%s): Router Info is Area scope flooding but area is not set",
1129 if (!CHECK_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
)
1130 && (opcode
!= REORIGINATE_THIS_LSA
))
1133 if (CHECK_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
)
1134 && (opcode
== REORIGINATE_THIS_LSA
))
1135 opcode
= REFRESH_THIS_LSA
;
1137 lsa
.area
= ai
->area
;
1138 top
= ai
->area
->ospf
;
1140 if (!CHECK_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
)
1141 && (opcode
!= REORIGINATE_THIS_LSA
))
1144 if (CHECK_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
)
1145 && (opcode
== REORIGINATE_THIS_LSA
))
1146 opcode
= REFRESH_THIS_LSA
;
1148 top
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1153 lsah
.type
= OspfRI
.scope
;
1155 /* LSA ID is set to 0 for the Router Information. See RFC 4970 */
1156 tmp
= SET_OPAQUE_LSID(OPAQUE_TYPE_ROUTER_INFORMATION_LSA
, 0);
1157 lsah
.id
.s_addr
= htonl(tmp
);
1160 case REORIGINATE_THIS_LSA
:
1161 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
)
1162 ospf_opaque_lsa_reoriginate_schedule(
1163 (void *)ai
->area
, OSPF_OPAQUE_AREA_LSA
,
1164 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
1166 ospf_opaque_lsa_reoriginate_schedule(
1167 (void *)top
, OSPF_OPAQUE_AS_LSA
,
1168 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
1170 case REFRESH_THIS_LSA
:
1171 ospf_opaque_lsa_refresh_schedule(&lsa
);
1173 case FLUSH_THIS_LSA
:
1174 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
)
1175 UNSET_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
);
1177 UNSET_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
);
1178 ospf_opaque_lsa_flush_schedule(&lsa
);
1185 /* Callback to handle Segment Routing information */
1186 static int ospf_router_info_lsa_update(struct ospf_lsa
*lsa
)
1191 flog_warn(EC_OSPF_LSA
, "RI (%s): Abort! LSA is NULL",
1196 /* Process only Opaque LSA */
1197 if ((lsa
->data
->type
!= OSPF_OPAQUE_AREA_LSA
)
1198 && (lsa
->data
->type
!= OSPF_OPAQUE_AS_LSA
))
1201 /* Process only Router Information LSA */
1202 if (GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
))
1203 != OPAQUE_TYPE_ROUTER_INFORMATION_LSA
)
1206 /* Check if it is not my LSA */
1207 if (IS_LSA_SELF(lsa
))
1210 /* Check if Router Info & Segment Routing are enable */
1211 if (!OspfRI
.enabled
|| !OspfRI
.sr_info
.enabled
)
1214 /* Call Segment Routing LSA update or deletion */
1215 if (!IS_LSA_MAXAGE(lsa
))
1216 ospf_sr_ri_lsa_update(lsa
);
1218 ospf_sr_ri_lsa_delete(lsa
);
1223 /*------------------------------------------------------------------------*
1224 * Followings are vty session control functions.
1225 *------------------------------------------------------------------------*/
1227 #define check_tlv_size(size, msg) \
1229 if (ntohs(tlvh->length) > size) { \
1231 vty_out(vty, " Wrong %s TLV size: %d(%d)\n", \
1232 msg, ntohs(tlvh->length), size); \
1234 zlog_debug(" Wrong %s TLV size: %d(%d)", \
1235 msg, ntohs(tlvh->length), size); \
1236 return size + TLV_HDR_SIZE; \
1240 static uint16_t show_vty_router_cap(struct vty
*vty
, struct tlv_header
*tlvh
)
1242 struct ri_tlv_router_cap
*top
= (struct ri_tlv_router_cap
*)tlvh
;
1244 check_tlv_size(RI_TLV_CAPABILITIES_SIZE
, "Router Capabilities");
1247 vty_out(vty
, " Router Capabilities: 0x%x\n",
1250 zlog_debug(" Router Capabilities: 0x%x", ntohl(top
->value
));
1252 return TLV_SIZE(tlvh
);
1255 static uint16_t show_vty_pce_subtlv_address(struct vty
*vty
,
1256 struct tlv_header
*tlvh
)
1258 struct ri_pce_subtlv_address
*top
=
1259 (struct ri_pce_subtlv_address
*)tlvh
;
1261 if (ntohs(top
->address
.type
) == PCE_ADDRESS_IPV4
) {
1262 check_tlv_size(PCE_ADDRESS_IPV4_SIZE
, "PCE Address");
1264 vty_out(vty
, " PCE Address: %pI4\n",
1265 &top
->address
.value
);
1267 zlog_debug(" PCE Address: %pI4",
1268 &top
->address
.value
);
1269 } else if (ntohs(top
->address
.type
) == PCE_ADDRESS_IPV6
) {
1270 /* TODO: Add support to IPv6 with inet_ntop() */
1271 check_tlv_size(PCE_ADDRESS_IPV6_SIZE
, "PCE Address");
1273 vty_out(vty
, " PCE Address: 0x%x\n",
1274 ntohl(top
->address
.value
.s_addr
));
1276 zlog_debug(" PCE Address: 0x%x",
1277 ntohl(top
->address
.value
.s_addr
));
1280 vty_out(vty
, " Wrong PCE Address type: 0x%x\n",
1281 ntohl(top
->address
.type
));
1283 zlog_debug(" Wrong PCE Address type: 0x%x",
1284 ntohl(top
->address
.type
));
1287 return TLV_SIZE(tlvh
);
1290 static uint16_t show_vty_pce_subtlv_path_scope(struct vty
*vty
,
1291 struct tlv_header
*tlvh
)
1293 struct ri_pce_subtlv_path_scope
*top
=
1294 (struct ri_pce_subtlv_path_scope
*)tlvh
;
1296 check_tlv_size(RI_PCE_SUBTLV_PATH_SCOPE_SIZE
, "PCE Path Scope");
1299 vty_out(vty
, " PCE Path Scope: 0x%x\n", ntohl(top
->value
));
1301 zlog_debug(" PCE Path Scope: 0x%x", ntohl(top
->value
));
1303 return TLV_SIZE(tlvh
);
1306 static uint16_t show_vty_pce_subtlv_domain(struct vty
*vty
,
1307 struct tlv_header
*tlvh
)
1309 struct ri_pce_subtlv_domain
*top
= (struct ri_pce_subtlv_domain
*)tlvh
;
1312 check_tlv_size(RI_PCE_SUBTLV_DOMAIN_SIZE
, "PCE Domain");
1314 if (ntohs(top
->type
) == PCE_DOMAIN_TYPE_AREA
) {
1315 tmp
.s_addr
= top
->value
;
1317 vty_out(vty
, " PCE Domain Area: %pI4\n", &tmp
);
1319 zlog_debug(" PCE Domain Area: %pI4", &tmp
);
1320 } else if (ntohs(top
->type
) == PCE_DOMAIN_TYPE_AS
) {
1322 vty_out(vty
, " PCE Domain AS: %d\n",
1325 zlog_debug(" PCE Domain AS: %d", ntohl(top
->value
));
1328 vty_out(vty
, " Wrong PCE Domain type: %d\n",
1331 zlog_debug(" Wrong PCE Domain type: %d",
1335 return TLV_SIZE(tlvh
);
1338 static uint16_t show_vty_pce_subtlv_neighbor(struct vty
*vty
,
1339 struct tlv_header
*tlvh
)
1342 struct ri_pce_subtlv_neighbor
*top
=
1343 (struct ri_pce_subtlv_neighbor
*)tlvh
;
1346 check_tlv_size(RI_PCE_SUBTLV_NEIGHBOR_SIZE
, "PCE Neighbor");
1348 if (ntohs(top
->type
) == PCE_DOMAIN_TYPE_AREA
) {
1349 tmp
.s_addr
= top
->value
;
1351 vty_out(vty
, " PCE Neighbor Area: %pI4\n", &tmp
);
1353 zlog_debug(" PCE Neighbor Area: %pI4", &tmp
);
1354 } else if (ntohs(top
->type
) == PCE_DOMAIN_TYPE_AS
) {
1356 vty_out(vty
, " PCE Neighbor AS: %d\n",
1359 zlog_debug(" PCE Neighbor AS: %d",
1363 vty_out(vty
, " Wrong PCE Neighbor type: %d\n",
1366 zlog_debug(" Wrong PCE Neighbor type: %d",
1370 return TLV_SIZE(tlvh
);
1373 static uint16_t show_vty_pce_subtlv_cap_flag(struct vty
*vty
,
1374 struct tlv_header
*tlvh
)
1376 struct ri_pce_subtlv_cap_flag
*top
=
1377 (struct ri_pce_subtlv_cap_flag
*)tlvh
;
1379 check_tlv_size(RI_PCE_SUBTLV_CAP_FLAG_SIZE
, "PCE Capabilities");
1382 vty_out(vty
, " PCE Capabilities Flag: 0x%x\n",
1385 zlog_debug(" PCE Capabilities Flag: 0x%x",
1388 return TLV_SIZE(tlvh
);
1391 static uint16_t show_vty_unknown_tlv(struct vty
*vty
, struct tlv_header
*tlvh
,
1394 if (TLV_SIZE(tlvh
) > buf_size
) {
1397 " TLV size %d exceeds buffer size. Abort!",
1401 " TLV size %d exceeds buffer size. Abort!",
1407 vty_out(vty
, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
1408 ntohs(tlvh
->type
), ntohs(tlvh
->length
));
1410 zlog_debug(" Unknown TLV: [type(0x%x), length(0x%x)]",
1411 ntohs(tlvh
->type
), ntohs(tlvh
->length
));
1413 return TLV_SIZE(tlvh
);
1416 static uint16_t show_vty_pce_info(struct vty
*vty
, struct tlv_header
*ri
,
1419 struct tlv_header
*tlvh
;
1420 uint16_t length
= ntohs(ri
->length
);
1423 /* Verify that TLV length is valid against remaining buffer size */
1424 if (length
> buf_size
) {
1426 " PCE Info TLV size %d exceeds buffer size. Abort!\n",
1431 for (tlvh
= ri
; sum
< length
; tlvh
= TLV_HDR_NEXT(tlvh
)) {
1432 switch (ntohs(tlvh
->type
)) {
1433 case RI_PCE_SUBTLV_ADDRESS
:
1434 sum
+= show_vty_pce_subtlv_address(vty
, tlvh
);
1436 case RI_PCE_SUBTLV_PATH_SCOPE
:
1437 sum
+= show_vty_pce_subtlv_path_scope(vty
, tlvh
);
1439 case RI_PCE_SUBTLV_DOMAIN
:
1440 sum
+= show_vty_pce_subtlv_domain(vty
, tlvh
);
1442 case RI_PCE_SUBTLV_NEIGHBOR
:
1443 sum
+= show_vty_pce_subtlv_neighbor(vty
, tlvh
);
1445 case RI_PCE_SUBTLV_CAP_FLAG
:
1446 sum
+= show_vty_pce_subtlv_cap_flag(vty
, tlvh
);
1449 sum
+= show_vty_unknown_tlv(vty
, tlvh
, length
- sum
);
1456 /* Display Segment Routing Algorithm TLV information */
1457 static uint16_t show_vty_sr_algorithm(struct vty
*vty
, struct tlv_header
*tlvh
)
1459 struct ri_sr_tlv_sr_algorithm
*algo
=
1460 (struct ri_sr_tlv_sr_algorithm
*)tlvh
;
1463 check_tlv_size(ALGORITHM_COUNT
, "Segment Routing Algorithm");
1466 vty_out(vty
, " Segment Routing Algorithm TLV:\n");
1467 for (i
= 0; i
< ntohs(algo
->header
.length
); i
++) {
1468 switch (algo
->value
[i
]) {
1470 vty_out(vty
, " Algorithm %d: SPF\n", i
);
1473 vty_out(vty
, " Algorithm %d: Strict SPF\n",
1478 " Algorithm %d: Unknown value %d\n", i
,
1484 zlog_debug(" Segment Routing Algorithm TLV:");
1485 for (i
= 0; i
< ntohs(algo
->header
.length
); i
++)
1486 switch (algo
->value
[i
]) {
1488 zlog_debug(" Algorithm %d: SPF", i
);
1491 zlog_debug(" Algorithm %d: Strict SPF", i
);
1494 zlog_debug(" Algorithm %d: Unknown value %d",
1500 return TLV_SIZE(tlvh
);
1503 /* Display Segment Routing SID/Label Range TLV information */
1504 static uint16_t show_vty_sr_range(struct vty
*vty
, struct tlv_header
*tlvh
)
1506 struct ri_sr_tlv_sid_label_range
*range
=
1507 (struct ri_sr_tlv_sid_label_range
*)tlvh
;
1509 check_tlv_size(RI_SR_TLV_LABEL_RANGE_SIZE
, "SR Label Range");
1513 " Segment Routing %s Range TLV:\n"
1514 " Range Size = %d\n"
1515 " SID Label = %d\n\n",
1516 ntohs(range
->header
.type
) == RI_SR_TLV_SRGB_LABEL_RANGE
1519 GET_RANGE_SIZE(ntohl(range
->size
)),
1520 GET_LABEL(ntohl(range
->lower
.value
)));
1523 " Segment Routing %s Range TLV: Range Size = %d SID Label = %d",
1524 ntohs(range
->header
.type
) == RI_SR_TLV_SRGB_LABEL_RANGE
1527 GET_RANGE_SIZE(ntohl(range
->size
)),
1528 GET_LABEL(ntohl(range
->lower
.value
)));
1531 return TLV_SIZE(tlvh
);
1534 /* Display Segment Routing Maximum Stack Depth TLV information */
1535 static uint16_t show_vty_sr_msd(struct vty
*vty
, struct tlv_header
*tlvh
)
1537 struct ri_sr_tlv_node_msd
*msd
= (struct ri_sr_tlv_node_msd
*)tlvh
;
1539 check_tlv_size(RI_SR_TLV_NODE_MSD_SIZE
, "Node Maximum Stack Depth");
1543 " Segment Routing MSD TLV:\n"
1544 " Node Maximum Stack Depth = %d\n",
1548 " Segment Routing MSD TLV: Node Maximum Stack Depth = %d",
1552 return TLV_SIZE(tlvh
);
1555 static void ospf_router_info_show_info(struct vty
*vty
, struct ospf_lsa
*lsa
)
1557 struct lsa_header
*lsah
= lsa
->data
;
1558 struct tlv_header
*tlvh
;
1559 uint16_t length
= 0, sum
= 0;
1561 /* Initialize TLV browsing */
1562 length
= lsa
->size
- OSPF_LSA_HEADER_SIZE
;
1564 for (tlvh
= TLV_HDR_TOP(lsah
); sum
< length
&& tlvh
;
1565 tlvh
= TLV_HDR_NEXT(tlvh
)) {
1566 switch (ntohs(tlvh
->type
)) {
1567 case RI_TLV_CAPABILITIES
:
1568 sum
+= show_vty_router_cap(vty
, tlvh
);
1572 sum
+= TLV_HDR_SIZE
;
1573 sum
+= show_vty_pce_info(vty
, tlvh
, length
- sum
);
1575 case RI_SR_TLV_SR_ALGORITHM
:
1576 sum
+= show_vty_sr_algorithm(vty
, tlvh
);
1578 case RI_SR_TLV_SRGB_LABEL_RANGE
:
1579 case RI_SR_TLV_SRLB_LABEL_RANGE
:
1580 sum
+= show_vty_sr_range(vty
, tlvh
);
1582 case RI_SR_TLV_NODE_MSD
:
1583 sum
+= show_vty_sr_msd(vty
, tlvh
);
1587 sum
+= show_vty_unknown_tlv(vty
, tlvh
, length
);
1595 static void ospf_router_info_config_write_router(struct vty
*vty
)
1597 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1598 struct listnode
*node
;
1599 struct ri_pce_subtlv_domain
*domain
;
1600 struct ri_pce_subtlv_neighbor
*neighbor
;
1603 if (!OspfRI
.enabled
)
1606 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
)
1607 vty_out(vty
, " router-info as\n");
1609 vty_out(vty
, " router-info area\n");
1611 if (OspfRI
.pce_info
.enabled
) {
1613 if (pce
->pce_address
.header
.type
!= 0)
1614 vty_out(vty
, " pce address %pI4\n",
1615 &pce
->pce_address
.address
.value
);
1617 if (pce
->pce_cap_flag
.header
.type
!= 0)
1618 vty_out(vty
, " pce flag 0x%x\n",
1619 ntohl(pce
->pce_cap_flag
.value
));
1621 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
1622 if (domain
->header
.type
!= 0) {
1623 if (domain
->type
== PCE_DOMAIN_TYPE_AREA
) {
1624 tmp
.s_addr
= domain
->value
;
1625 vty_out(vty
, " pce domain area %pI4\n",
1628 vty_out(vty
, " pce domain as %d\n",
1629 ntohl(domain
->value
));
1634 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
1635 if (neighbor
->header
.type
!= 0) {
1636 if (neighbor
->type
== PCE_DOMAIN_TYPE_AREA
) {
1637 tmp
.s_addr
= neighbor
->value
;
1639 " pce neighbor area %pI4\n",
1642 vty_out(vty
, " pce neighbor as %d\n",
1643 ntohl(neighbor
->value
));
1648 if (pce
->pce_scope
.header
.type
!= 0)
1649 vty_out(vty
, " pce scope 0x%x\n",
1650 ntohl(OspfRI
.pce_info
.pce_scope
.value
));
1655 /*------------------------------------------------------------------------*
1656 * Followings are vty command functions.
1657 *------------------------------------------------------------------------*/
1658 /* Simple wrapper schedule RI LSA action in function of the scope */
1659 static void ospf_router_info_schedule(enum lsa_opcode opcode
)
1661 struct listnode
*node
, *nnode
;
1662 struct ospf_ri_area_info
*ai
;
1664 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
) {
1665 if (CHECK_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
))
1666 ospf_router_info_lsa_schedule(NULL
, opcode
);
1667 else if (opcode
== REORIGINATE_THIS_LSA
)
1668 ospf_router_info_lsa_schedule(NULL
, opcode
);
1670 for (ALL_LIST_ELEMENTS(OspfRI
.area_info
, node
, nnode
, ai
)) {
1671 if (CHECK_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
))
1672 ospf_router_info_lsa_schedule(ai
, opcode
);
1678 router_info_area_cmd
,
1679 "router-info <as|area [A.B.C.D]>",
1681 "Enable the Router Information functionality with AS flooding scope\n"
1682 "Enable the Router Information functionality with Area flooding scope\n"
1683 "OSPF area ID in IP format (deprecated)\n")
1691 /* Check and get Area value if present */
1692 if (strncmp(argv
[idx_mode
]->arg
, "as", 2) == 0)
1693 scope
= OSPF_OPAQUE_AS_LSA
;
1695 scope
= OSPF_OPAQUE_AREA_LSA
;
1697 /* First start to register Router Information callbacks */
1698 if (!OspfRI
.registered
&& (ospf_router_info_register(scope
)) != 0) {
1700 "%% Unable to register Router Information callbacks.");
1703 "RI (%s): Unable to register Router Information callbacks. Abort!",
1705 return CMD_WARNING_CONFIG_FAILED
;
1708 OspfRI
.enabled
= true;
1710 if (IS_DEBUG_OSPF_EVENT
)
1711 zlog_debug("RI-> Router Information (%s flooding): OFF -> ON",
1712 OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
? "Area"
1716 * Following code is intended to handle two cases;
1718 * 1) Router Information was disabled at startup time, but now become
1720 * 2) Router Information was once enabled then disabled, and now enabled
1724 initialize_params(&OspfRI
);
1726 /* Originate or Refresh RI LSA if already engaged */
1727 ospf_router_info_schedule(REORIGINATE_THIS_LSA
);
1732 DEFUN (no_router_info
,
1736 "Disable the Router Information functionality\n")
1739 if (!OspfRI
.enabled
)
1742 if (IS_DEBUG_OSPF_EVENT
)
1743 zlog_debug("RI-> Router Information: ON -> OFF");
1745 ospf_router_info_schedule(FLUSH_THIS_LSA
);
1747 OspfRI
.enabled
= false;
1752 static int ospf_ri_enabled(struct vty
*vty
)
1758 vty_out(vty
, "%% OSPF RI is not turned on\n");
1765 "pce address A.B.C.D",
1767 "Stable IP address of the PCE\n"
1768 "PCE address in IPv4 address format\n")
1771 struct in_addr value
;
1772 struct ospf_pce_info
*pi
= &OspfRI
.pce_info
;
1774 if (!ospf_ri_enabled(vty
))
1775 return CMD_WARNING_CONFIG_FAILED
;
1777 if (!inet_aton(argv
[idx_ipv4
]->arg
, &value
)) {
1778 vty_out(vty
, "Please specify PCE Address by A.B.C.D\n");
1779 return CMD_WARNING_CONFIG_FAILED
;
1782 if (ntohs(pi
->pce_address
.header
.type
) == 0
1783 || ntohl(pi
->pce_address
.address
.value
.s_addr
)
1784 != ntohl(value
.s_addr
)) {
1786 set_pce_address(value
, pi
);
1788 /* Refresh RI LSA if already engaged */
1789 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1795 DEFUN (no_pce_address
,
1797 "no pce address [A.B.C.D]",
1800 "Disable PCE address\n"
1801 "PCE address in IPv4 address format\n")
1804 unset_param(&OspfRI
.pce_info
.pce_address
);
1806 /* Refresh RI LSA if already engaged */
1807 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1812 DEFUN (pce_path_scope
,
1814 "pce scope BITPATTERN",
1816 "Path scope visibilities of the PCE for path computation\n"
1817 "32-bit Hexadecimal value\n")
1819 int idx_bitpattern
= 2;
1821 struct ospf_pce_info
*pi
= &OspfRI
.pce_info
;
1823 if (!ospf_ri_enabled(vty
))
1824 return CMD_WARNING_CONFIG_FAILED
;
1826 if (sscanf(argv
[idx_bitpattern
]->arg
, "0x%x", &scope
) != 1) {
1827 vty_out(vty
, "pce_path_scope: fscanf: %s\n",
1828 safe_strerror(errno
));
1829 return CMD_WARNING_CONFIG_FAILED
;
1832 if (ntohl(pi
->pce_scope
.header
.type
) == 0
1833 || scope
!= pi
->pce_scope
.value
) {
1834 set_pce_path_scope(scope
, pi
);
1836 /* Refresh RI LSA if already engaged */
1837 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1843 DEFUN (no_pce_path_scope
,
1844 no_pce_path_scope_cmd
,
1845 "no pce scope [BITPATTERN]",
1848 "Disable PCE path scope\n"
1849 "32-bit Hexadecimal value\n")
1852 unset_param(&OspfRI
.pce_info
.pce_address
);
1854 /* Refresh RI LSA if already engaged */
1855 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1862 "pce domain as (0-65535)",
1864 "Configure PCE domain AS number\n"
1865 "AS number where the PCE as visibilities for path computation\n"
1866 "AS number in decimal <0-65535>\n")
1871 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1872 struct listnode
*node
;
1873 struct ri_pce_subtlv_domain
*domain
;
1875 if (!ospf_ri_enabled(vty
))
1876 return CMD_WARNING_CONFIG_FAILED
;
1878 if (sscanf(argv
[idx_number
]->arg
, "%" SCNu32
, &as
) != 1) {
1879 vty_out(vty
, "pce_domain: fscanf: %s\n", safe_strerror(errno
));
1880 return CMD_WARNING_CONFIG_FAILED
;
1883 /* Check if the domain is not already in the domain list */
1884 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
1885 if (ntohl(domain
->header
.type
) == 0 && as
== domain
->value
)
1889 /* Create new domain if not found */
1890 set_pce_domain(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1892 /* Refresh RI LSA if already engaged */
1893 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1898 DEFUN (no_pce_domain
,
1900 "no pce domain as (0-65535)",
1903 "Disable PCE domain AS number\n"
1904 "AS number where the PCE as visibilities for path computation\n"
1905 "AS number in decimal <0-65535>\n")
1910 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1912 if (sscanf(argv
[idx_number
]->arg
, "%" SCNu32
, &as
) != 1) {
1913 vty_out(vty
, "no_pce_domain: fscanf: %s\n",
1914 safe_strerror(errno
));
1915 return CMD_WARNING_CONFIG_FAILED
;
1918 /* Unset corresponding PCE domain */
1919 unset_pce_domain(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1921 /* Refresh RI LSA if already engaged */
1922 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1927 DEFUN (pce_neigbhor
,
1929 "pce neighbor as (0-65535)",
1931 "Configure PCE neighbor domain AS number\n"
1932 "AS number of PCE neighbors\n"
1933 "AS number in decimal <0-65535>\n")
1938 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1939 struct listnode
*node
;
1940 struct ri_pce_subtlv_neighbor
*neighbor
;
1942 if (!ospf_ri_enabled(vty
))
1943 return CMD_WARNING_CONFIG_FAILED
;
1945 if (sscanf(argv
[idx_number
]->arg
, "%" SCNu32
, &as
) != 1) {
1946 vty_out(vty
, "pce_neighbor: fscanf: %s\n",
1947 safe_strerror(errno
));
1948 return CMD_WARNING_CONFIG_FAILED
;
1951 /* Check if the domain is not already in the domain list */
1952 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
1953 if (ntohl(neighbor
->header
.type
) == 0 && as
== neighbor
->value
)
1957 /* Create new domain if not found */
1958 set_pce_neighbor(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1960 /* Refresh RI LSA if already engaged */
1961 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1966 DEFUN (no_pce_neighbor
,
1967 no_pce_neighbor_cmd
,
1968 "no pce neighbor as (0-65535)",
1971 "Disable PCE neighbor AS number\n"
1972 "AS number of PCE neighbor\n"
1973 "AS number in decimal <0-65535>\n")
1978 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1980 if (sscanf(argv
[idx_number
]->arg
, "%" SCNu32
, &as
) != 1) {
1981 vty_out(vty
, "no_pce_neighbor: fscanf: %s\n",
1982 safe_strerror(errno
));
1983 return CMD_WARNING_CONFIG_FAILED
;
1986 /* Unset corresponding PCE domain */
1987 unset_pce_neighbor(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1989 /* Refresh RI LSA if already engaged */
1990 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1995 DEFUN (pce_cap_flag
,
1997 "pce flag BITPATTERN",
1999 "Capabilities of the PCE for path computation\n"
2000 "32-bit Hexadecimal value\n")
2002 int idx_bitpattern
= 2;
2005 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
2007 if (!ospf_ri_enabled(vty
))
2008 return CMD_WARNING_CONFIG_FAILED
;
2010 if (sscanf(argv
[idx_bitpattern
]->arg
, "0x%x", &cap
) != 1) {
2011 vty_out(vty
, "pce_cap_flag: fscanf: %s\n",
2012 safe_strerror(errno
));
2013 return CMD_WARNING_CONFIG_FAILED
;
2016 if (ntohl(pce
->pce_cap_flag
.header
.type
) == 0
2017 || cap
!= pce
->pce_cap_flag
.value
) {
2018 set_pce_cap_flag(cap
, pce
);
2020 /* Refresh RI LSA if already engaged */
2021 ospf_router_info_schedule(REFRESH_THIS_LSA
);
2027 DEFUN (no_pce_cap_flag
,
2028 no_pce_cap_flag_cmd
,
2032 "Disable PCE capabilities\n")
2035 unset_param(&OspfRI
.pce_info
.pce_cap_flag
);
2037 /* Refresh RI LSA if already engaged */
2038 ospf_router_info_schedule(REFRESH_THIS_LSA
);
2043 DEFUN (show_ip_ospf_router_info
,
2044 show_ip_ospf_router_info_cmd
,
2045 "show ip ospf router-info",
2049 "Router Information\n")
2052 if (OspfRI
.enabled
) {
2053 vty_out(vty
, "--- Router Information parameters ---\n");
2054 show_vty_router_cap(vty
, &OspfRI
.router_cap
.header
);
2058 " Router Information is disabled on this router\n");
2063 DEFUN (show_ip_opsf_router_info_pce
,
2064 show_ip_ospf_router_info_pce_cmd
,
2065 "show ip ospf router-info pce",
2069 "Router Information\n"
2070 "PCE information\n")
2073 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
2074 struct listnode
*node
;
2075 struct ri_pce_subtlv_domain
*domain
;
2076 struct ri_pce_subtlv_neighbor
*neighbor
;
2078 if ((OspfRI
.enabled
) && (OspfRI
.pce_info
.enabled
)) {
2079 vty_out(vty
, "--- PCE parameters ---\n");
2081 if (pce
->pce_address
.header
.type
!= 0)
2082 show_vty_pce_subtlv_address(vty
,
2083 &pce
->pce_address
.header
);
2085 if (pce
->pce_scope
.header
.type
!= 0)
2086 show_vty_pce_subtlv_path_scope(vty
,
2087 &pce
->pce_scope
.header
);
2089 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
2090 if (domain
->header
.type
!= 0)
2091 show_vty_pce_subtlv_domain(vty
,
2095 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
2096 if (neighbor
->header
.type
!= 0)
2097 show_vty_pce_subtlv_neighbor(vty
,
2101 if (pce
->pce_cap_flag
.header
.type
!= 0)
2102 show_vty_pce_subtlv_cap_flag(vty
,
2103 &pce
->pce_cap_flag
.header
);
2106 vty_out(vty
, " PCE info is disabled on this router\n");
2112 /* Install new CLI commands */
2113 static void ospf_router_info_register_vty(void)
2115 install_element(VIEW_NODE
, &show_ip_ospf_router_info_cmd
);
2116 install_element(VIEW_NODE
, &show_ip_ospf_router_info_pce_cmd
);
2118 install_element(OSPF_NODE
, &router_info_area_cmd
);
2119 install_element(OSPF_NODE
, &no_router_info_cmd
);
2120 install_element(OSPF_NODE
, &pce_address_cmd
);
2121 install_element(OSPF_NODE
, &no_pce_address_cmd
);
2122 install_element(OSPF_NODE
, &pce_path_scope_cmd
);
2123 install_element(OSPF_NODE
, &no_pce_path_scope_cmd
);
2124 install_element(OSPF_NODE
, &pce_domain_cmd
);
2125 install_element(OSPF_NODE
, &no_pce_domain_cmd
);
2126 install_element(OSPF_NODE
, &pce_neighbor_cmd
);
2127 install_element(OSPF_NODE
, &no_pce_neighbor_cmd
);
2128 install_element(OSPF_NODE
, &pce_cap_flag_cmd
);
2129 install_element(OSPF_NODE
, &no_pce_cap_flag_cmd
);