1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * This is an implementation of RFC4970 Router Information
4 * with support of RFC5088 PCE Capabilites announcement
6 * Module name: Router Information
7 * Author: Olivier Dugeon <olivier.dugeon@orange.com>
8 * Copyright (C) 2012 - 2017 Orange Labs http://www.orange.com/
25 #include "sockunion.h" /* for inet_aton() */
28 #include "ospfd/ospfd.h"
29 #include "ospfd/ospf_interface.h"
30 #include "ospfd/ospf_ism.h"
31 #include "ospfd/ospf_asbr.h"
32 #include "ospfd/ospf_lsa.h"
33 #include "ospfd/ospf_lsdb.h"
34 #include "ospfd/ospf_neighbor.h"
35 #include "ospfd/ospf_nsm.h"
36 #include "ospfd/ospf_flood.h"
37 #include "ospfd/ospf_packet.h"
38 #include "ospfd/ospf_spf.h"
39 #include "ospfd/ospf_dump.h"
40 #include "ospfd/ospf_route.h"
41 #include "ospfd/ospf_ase.h"
42 #include "ospfd/ospf_zebra.h"
43 #include "ospfd/ospf_sr.h"
44 #include "ospfd/ospf_ri.h"
45 #include "ospfd/ospf_errors.h"
48 * Global variable to manage Opaque-LSA/Router Information on this node.
49 * Note that all parameter values are stored in network byte order.
51 static struct ospf_router_info OspfRI
;
53 /*------------------------------------------------------------------------------*
54 * Following are initialize/terminate functions for Router Information
56 *------------------------------------------------------------------------------*/
58 static void ospf_router_info_ism_change(struct ospf_interface
*oi
,
60 static void ospf_router_info_config_write_router(struct vty
*vty
);
61 static void ospf_router_info_show_info(struct vty
*vty
,
62 struct json_object
*json
,
63 struct ospf_lsa
*lsa
);
64 static int ospf_router_info_lsa_originate(void *arg
);
65 static struct ospf_lsa
*ospf_router_info_lsa_refresh(struct ospf_lsa
*lsa
);
66 static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info
*ai
,
67 enum lsa_opcode opcode
);
68 static void ospf_router_info_register_vty(void);
69 static int ospf_router_info_lsa_update(struct ospf_lsa
*lsa
);
70 static void del_area_info(void *val
);
71 static void del_pce_info(void *val
);
73 int ospf_router_info_init(void)
76 zlog_info("RI (%s): Initialize Router Information", __func__
);
78 memset(&OspfRI
, 0, sizeof(OspfRI
));
79 OspfRI
.enabled
= false;
80 OspfRI
.registered
= 0;
81 OspfRI
.scope
= OSPF_OPAQUE_AS_LSA
;
82 OspfRI
.as_flags
= RIFLG_LSA_INACTIVE
;
83 OspfRI
.area_info
= list_new();
84 OspfRI
.area_info
->del
= del_area_info
;
86 /* Initialize pce domain and neighbor list */
87 OspfRI
.pce_info
.enabled
= false;
88 OspfRI
.pce_info
.pce_domain
= list_new();
89 OspfRI
.pce_info
.pce_domain
->del
= del_pce_info
;
90 OspfRI
.pce_info
.pce_neighbor
= list_new();
91 OspfRI
.pce_info
.pce_neighbor
->del
= del_pce_info
;
93 /* Initialize Segment Routing information structure */
94 OspfRI
.sr_info
.enabled
= false;
96 ospf_router_info_register_vty();
101 static int ospf_router_info_register(uint8_t scope
)
105 if (OspfRI
.registered
)
108 zlog_info("RI (%s): Register Router Information with scope %s(%d)",
110 scope
== OSPF_OPAQUE_AREA_LSA
? "Area" : "AS", scope
);
111 rc
= ospf_register_opaque_functab(
112 scope
, OPAQUE_TYPE_ROUTER_INFORMATION_LSA
,
113 NULL
, /* new interface */
114 NULL
, /* del interface */
115 ospf_router_info_ism_change
,
116 NULL
, /* NSM change */
117 ospf_router_info_config_write_router
,
118 NULL
, /* Config. write interface */
119 NULL
, /* Config. write debug */
120 ospf_router_info_show_info
, ospf_router_info_lsa_originate
,
121 ospf_router_info_lsa_refresh
, ospf_router_info_lsa_update
,
122 NULL
); /* del_lsa_hook */
126 EC_OSPF_OPAQUE_REGISTRATION
,
127 "RI (%s): Failed to register functions", __func__
);
131 OspfRI
.registered
= 1;
132 OspfRI
.scope
= scope
;
136 static int ospf_router_info_unregister(void)
139 if ((OspfRI
.scope
!= OSPF_OPAQUE_AS_LSA
)
140 && (OspfRI
.scope
!= OSPF_OPAQUE_AREA_LSA
)) {
141 assert("Unable to unregister Router Info functions: Wrong scope!"
146 ospf_delete_opaque_functab(OspfRI
.scope
,
147 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
149 OspfRI
.registered
= 0;
153 void ospf_router_info_term(void)
156 list_delete(&OspfRI
.pce_info
.pce_domain
);
157 list_delete(&OspfRI
.pce_info
.pce_neighbor
);
159 OspfRI
.enabled
= false;
161 ospf_router_info_unregister();
166 void ospf_router_info_finish(void)
168 struct listnode
*node
, *nnode
;
169 struct ospf_ri_area_info
*ai
;
171 /* Flush Router Info LSA */
172 for (ALL_LIST_ELEMENTS(OspfRI
.area_info
, node
, nnode
, ai
))
173 if (CHECK_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
))
174 ospf_router_info_lsa_schedule(ai
, FLUSH_THIS_LSA
);
176 list_delete_all_node(OspfRI
.pce_info
.pce_domain
);
177 list_delete_all_node(OspfRI
.pce_info
.pce_neighbor
);
179 OspfRI
.enabled
= false;
182 static void del_area_info(void *val
)
184 XFREE(MTYPE_OSPF_ROUTER_INFO
, val
);
187 static void del_pce_info(void *val
)
189 XFREE(MTYPE_OSPF_PCE_PARAMS
, val
);
192 /* Catch RI LSA flooding Scope for ospf_ext.[h,c] code */
193 struct scope_info
ospf_router_info_get_flooding_scope(void)
195 struct scope_info flooding_scope
;
197 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
) {
198 flooding_scope
.scope
= OSPF_OPAQUE_AS_LSA
;
199 flooding_scope
.areas
= NULL
;
200 return flooding_scope
;
202 flooding_scope
.scope
= OSPF_OPAQUE_AREA_LSA
;
203 flooding_scope
.areas
= OspfRI
.area_info
;
204 return flooding_scope
;
207 static struct ospf_ri_area_info
*lookup_by_area(struct ospf_area
*area
)
209 struct listnode
*node
, *nnode
;
210 struct ospf_ri_area_info
*ai
;
212 for (ALL_LIST_ELEMENTS(OspfRI
.area_info
, node
, nnode
, ai
))
213 if (ai
->area
== area
)
219 /*------------------------------------------------------------------------*
220 * Following are control functions for ROUTER INFORMATION parameters
222 *------------------------------------------------------------------------*/
224 static void set_router_info_capabilities(struct ri_tlv_router_cap
*ric
,
227 ric
->header
.type
= htons(RI_TLV_CAPABILITIES
);
228 ric
->header
.length
= htons(RI_TLV_LENGTH
);
229 ric
->value
= htonl(cap
);
233 static int set_pce_header(struct ospf_pce_info
*pce
)
236 struct listnode
*node
;
237 struct ri_pce_subtlv_domain
*domain
;
238 struct ri_pce_subtlv_neighbor
*neighbor
;
241 if (ntohs(pce
->pce_address
.header
.type
) != 0)
242 length
+= TLV_SIZE(&pce
->pce_address
.header
);
245 if (ntohs(pce
->pce_scope
.header
.type
) != 0)
246 length
+= TLV_SIZE(&pce
->pce_scope
.header
);
249 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
250 if (ntohs(domain
->header
.type
) != 0)
251 length
+= TLV_SIZE(&domain
->header
);
255 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
256 if (ntohs(neighbor
->header
.type
) != 0)
257 length
+= TLV_SIZE(&neighbor
->header
);
260 /* PCE Capabilities */
261 if (ntohs(pce
->pce_cap_flag
.header
.type
) != 0)
262 length
+= TLV_SIZE(&pce
->pce_cap_flag
.header
);
265 pce
->pce_header
.header
.type
= htons(RI_TLV_PCE
);
266 pce
->pce_header
.header
.length
= htons(length
);
269 pce
->pce_header
.header
.type
= 0;
270 pce
->pce_header
.header
.length
= 0;
271 pce
->enabled
= false;
277 static void set_pce_address(struct in_addr ipv4
, struct ospf_pce_info
*pce
)
280 /* Enable PCE Info */
281 pce
->pce_header
.header
.type
= htons(RI_TLV_PCE
);
282 /* Set PCE Address */
283 pce
->pce_address
.header
.type
= htons(RI_PCE_SUBTLV_ADDRESS
);
284 pce
->pce_address
.header
.length
= htons(PCE_ADDRESS_IPV4_SIZE
);
285 pce
->pce_address
.address
.type
= htons(PCE_ADDRESS_IPV4
);
286 pce
->pce_address
.address
.value
= ipv4
;
291 static void set_pce_path_scope(uint32_t scope
, struct ospf_pce_info
*pce
)
295 pce
->pce_scope
.header
.type
= htons(RI_PCE_SUBTLV_PATH_SCOPE
);
296 pce
->pce_scope
.header
.length
= htons(RI_TLV_LENGTH
);
297 pce
->pce_scope
.value
= htonl(scope
);
302 static void set_pce_domain(uint16_t type
, uint32_t domain
,
303 struct ospf_pce_info
*pce
)
306 struct ri_pce_subtlv_domain
*new;
308 /* Create new domain info */
309 new = XCALLOC(MTYPE_OSPF_PCE_PARAMS
,
310 sizeof(struct ri_pce_subtlv_domain
));
312 new->header
.type
= htons(RI_PCE_SUBTLV_DOMAIN
);
313 new->header
.length
= htons(PCE_ADDRESS_IPV4_SIZE
);
314 new->type
= htons(type
);
315 new->value
= htonl(domain
);
317 /* Add new domain to the list */
318 listnode_add(pce
->pce_domain
, new);
323 static void unset_pce_domain(uint16_t type
, uint32_t domain
,
324 struct ospf_pce_info
*pce
)
326 struct listnode
*node
;
327 struct ri_pce_subtlv_domain
*old
= NULL
;
330 /* Search the corresponding node */
331 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, old
)) {
332 if ((old
->type
== htons(type
))
333 && (old
->value
== htonl(domain
))) {
339 /* if found remove it */
341 listnode_delete(pce
->pce_domain
, old
);
343 /* Finally free the old domain */
344 XFREE(MTYPE_OSPF_PCE_PARAMS
, old
);
348 static void set_pce_neighbor(uint16_t type
, uint32_t domain
,
349 struct ospf_pce_info
*pce
)
352 struct ri_pce_subtlv_neighbor
*new;
354 /* Create new neighbor info */
355 new = XCALLOC(MTYPE_OSPF_PCE_PARAMS
,
356 sizeof(struct ri_pce_subtlv_neighbor
));
358 new->header
.type
= htons(RI_PCE_SUBTLV_NEIGHBOR
);
359 new->header
.length
= htons(PCE_ADDRESS_IPV4_SIZE
);
360 new->type
= htons(type
);
361 new->value
= htonl(domain
);
363 /* Add new domain to the list */
364 listnode_add(pce
->pce_neighbor
, new);
369 static void unset_pce_neighbor(uint16_t type
, uint32_t domain
,
370 struct ospf_pce_info
*pce
)
372 struct listnode
*node
;
373 struct ri_pce_subtlv_neighbor
*old
= NULL
;
376 /* Search the corresponding node */
377 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, old
)) {
378 if ((old
->type
== htons(type
))
379 && (old
->value
== htonl(domain
))) {
385 /* if found remove it */
387 listnode_delete(pce
->pce_neighbor
, old
);
389 /* Finally free the old domain */
390 XFREE(MTYPE_OSPF_PCE_PARAMS
, old
);
394 static void set_pce_cap_flag(uint32_t cap
, struct ospf_pce_info
*pce
)
397 /* Set PCE Capabilities flag */
398 pce
->pce_cap_flag
.header
.type
= htons(RI_PCE_SUBTLV_CAP_FLAG
);
399 pce
->pce_cap_flag
.header
.length
= htons(RI_TLV_LENGTH
);
400 pce
->pce_cap_flag
.value
= htonl(cap
);
405 /* Segment Routing TLV setter */
407 /* Algorithm SubTLV - section 3.1 */
408 static void set_sr_algorithm(uint8_t algo
)
411 OspfRI
.sr_info
.algo
.value
[0] = algo
;
412 for (int i
= 1; i
< ALGORITHM_COUNT
; i
++)
413 OspfRI
.sr_info
.algo
.value
[i
] = SR_ALGORITHM_UNSET
;
415 /* Set TLV type and length == only 1 Algorithm */
416 TLV_TYPE(OspfRI
.sr_info
.algo
) = htons(RI_SR_TLV_SR_ALGORITHM
);
417 TLV_LEN(OspfRI
.sr_info
.algo
) = htons(sizeof(uint8_t));
420 /* unset Aglogithm SubTLV */
421 static void unset_sr_algorithm(uint8_t algo
)
424 for (int i
= 0; i
< ALGORITHM_COUNT
; i
++)
425 OspfRI
.sr_info
.algo
.value
[i
] = SR_ALGORITHM_UNSET
;
427 /* Unset TLV type and length */
428 TLV_TYPE(OspfRI
.sr_info
.algo
) = htons(0);
429 TLV_LEN(OspfRI
.sr_info
.algo
) = htons(0);
432 /* Set Segment Routing Global Block SubTLV - section 3.2 */
433 static void set_sr_global_label_range(struct sr_block srgb
)
436 TLV_TYPE(OspfRI
.sr_info
.srgb
) = htons(RI_SR_TLV_SRGB_LABEL_RANGE
);
437 TLV_LEN(OspfRI
.sr_info
.srgb
) = htons(RI_SR_TLV_LABEL_RANGE_SIZE
);
439 OspfRI
.sr_info
.srgb
.size
= htonl(SET_RANGE_SIZE(srgb
.range_size
));
440 /* Set Lower bound label SubTLV */
441 TLV_TYPE(OspfRI
.sr_info
.srgb
.lower
) = htons(SUBTLV_SID_LABEL
);
442 TLV_LEN(OspfRI
.sr_info
.srgb
.lower
) = htons(SID_RANGE_LABEL_LENGTH
);
443 OspfRI
.sr_info
.srgb
.lower
.value
= htonl(SET_LABEL(srgb
.lower_bound
));
446 /* Unset Segment Routing Global Block SubTLV */
447 static void unset_sr_global_label_range(void)
449 TLV_TYPE(OspfRI
.sr_info
.srgb
) = htons(0);
450 TLV_LEN(OspfRI
.sr_info
.srgb
) = htons(0);
451 TLV_TYPE(OspfRI
.sr_info
.srgb
.lower
) = htons(0);
452 TLV_LEN(OspfRI
.sr_info
.srgb
.lower
) = htons(0);
455 /* Set Segment Routing Local Block SubTLV - section 3.2 */
456 static void set_sr_local_label_range(struct sr_block srlb
)
459 TLV_TYPE(OspfRI
.sr_info
.srlb
) = htons(RI_SR_TLV_SRLB_LABEL_RANGE
);
460 TLV_LEN(OspfRI
.sr_info
.srlb
) = htons(RI_SR_TLV_LABEL_RANGE_SIZE
);
462 OspfRI
.sr_info
.srlb
.size
= htonl(SET_RANGE_SIZE(srlb
.range_size
));
463 /* Set Lower bound label SubTLV */
464 TLV_TYPE(OspfRI
.sr_info
.srlb
.lower
) = htons(SUBTLV_SID_LABEL
);
465 TLV_LEN(OspfRI
.sr_info
.srlb
.lower
) = htons(SID_RANGE_LABEL_LENGTH
);
466 OspfRI
.sr_info
.srlb
.lower
.value
= htonl(SET_LABEL(srlb
.lower_bound
));
469 /* Unset Segment Routing Local Block SubTLV */
470 static void unset_sr_local_label_range(void)
472 TLV_TYPE(OspfRI
.sr_info
.srlb
) = htons(0);
473 TLV_LEN(OspfRI
.sr_info
.srlb
) = htons(0);
474 TLV_TYPE(OspfRI
.sr_info
.srlb
.lower
) = htons(0);
475 TLV_LEN(OspfRI
.sr_info
.srlb
.lower
) = htons(0);
478 /* Set Maximum Stack Depth for this router */
479 static void set_sr_node_msd(uint8_t msd
)
481 TLV_TYPE(OspfRI
.sr_info
.msd
) = htons(RI_SR_TLV_NODE_MSD
);
482 TLV_LEN(OspfRI
.sr_info
.msd
) = htons(sizeof(uint32_t));
483 OspfRI
.sr_info
.msd
.value
= msd
;
486 /* Unset this router MSD */
487 static void unset_sr_node_msd(void)
489 TLV_TYPE(OspfRI
.sr_info
.msd
) = htons(0);
490 TLV_LEN(OspfRI
.sr_info
.msd
) = htons(0);
493 static void unset_param(void *tlv_buffer
)
495 struct tlv_header
*tlv
= (struct tlv_header
*)tlv_buffer
;
498 /* Fill the Value to 0 */
499 memset(TLV_DATA(tlv_buffer
), 0, TLV_BODY_SIZE(tlv
));
505 static void initialize_params(struct ospf_router_info
*ori
)
509 struct listnode
*node
, *nnode
;
510 struct ospf_area
*area
;
511 struct ospf_ri_area_info
*new;
514 * Initialize default Router Information Capabilities.
518 set_router_info_capabilities(&ori
->router_cap
, cap
);
520 /* If Area address is not null and exist, retrieve corresponding
522 top
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
523 zlog_info("RI (%s): Initialize Router Info for %s scope", __func__
,
524 OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
? "Area" : "AS");
526 /* Try to get available Area's context from ospf at this step.
527 * Do it latter if not available */
528 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) {
529 if (!list_isempty(OspfRI
.area_info
))
530 list_delete_all_node(OspfRI
.area_info
);
531 for (ALL_LIST_ELEMENTS(top
->areas
, node
, nnode
, area
)) {
532 zlog_debug("RI (%s): Add area %pI4 to Router Information",
533 __func__
, &area
->area_id
);
534 new = XCALLOC(MTYPE_OSPF_ROUTER_INFO
,
535 sizeof(struct ospf_ri_area_info
));
537 new->flags
= RIFLG_LSA_INACTIVE
;
538 listnode_add(OspfRI
.area_info
, new);
543 * Initialize default PCE Information values
545 /* PCE address == OSPF Router ID */
546 set_pce_address(top
->router_id
, &ori
->pce_info
);
549 cap
= 7; /* Set L, R and Rd bits to one = intra & inter-area path
551 set_pce_path_scope(cap
, &ori
->pce_info
);
553 /* PCE Capabilities */
554 cap
= PCE_CAP_BIDIRECTIONAL
| PCE_CAP_DIVERSE_PATH
| PCE_CAP_OBJECTIVES
555 | PCE_CAP_ADDITIVE
| PCE_CAP_MULTIPLE_REQ
;
556 set_pce_cap_flag(cap
, &ori
->pce_info
);
561 static int is_mandated_params_set(struct ospf_router_info
*ori
)
568 if (ntohs(ori
->router_cap
.header
.type
) == 0)
571 if ((ntohs(ori
->pce_info
.pce_header
.header
.type
) == RI_TLV_PCE
)
572 && (ntohs(ori
->pce_info
.pce_address
.header
.type
) == 0)
573 && (ntohs(ori
->pce_info
.pce_cap_flag
.header
.type
) == 0))
576 if ((ori
->sr_info
.enabled
) && (ntohs(TLV_TYPE(ori
->sr_info
.algo
)) == 0)
577 && (ntohs(TLV_TYPE(ori
->sr_info
.srgb
)) == 0))
586 * Used by Segment Routing to set new TLVs and Sub-TLVs values
588 * @param enable To activate or not Segment Routing router Information flooding
589 * @param srn Self Segment Routing node
593 void ospf_router_info_update_sr(bool enable
, struct sr_node
*srn
)
595 struct listnode
*node
, *nnode
;
596 struct ospf_ri_area_info
*ai
;
598 /* First, check if Router Information is registered or not */
599 if (!OspfRI
.registered
)
600 ospf_router_info_register(OSPF_OPAQUE_AREA_LSA
);
602 /* Verify that scope is AREA */
603 if (OspfRI
.scope
!= OSPF_OPAQUE_AREA_LSA
) {
605 "RI (%s): Router Info is %s flooding: Change scope to Area flooding for Segment Routing",
607 OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
? "Area" : "AS");
611 /* Then, activate and initialize Router Information if necessary */
612 if (!OspfRI
.enabled
) {
613 OspfRI
.enabled
= true;
614 initialize_params(&OspfRI
);
617 /* Check that SR node is valid */
621 if (IS_DEBUG_OSPF_SR
)
622 zlog_debug("RI (%s): %s Routing Information for Segment Routing",
623 __func__
, enable
? "Enable" : "Disable");
625 /* Unset or Set SR parameters */
627 unset_sr_algorithm(SR_ALGORITHM_SPF
);
628 unset_sr_global_label_range();
629 unset_sr_local_label_range();
631 OspfRI
.sr_info
.enabled
= false;
633 // Only SR_ALGORITHM_SPF is supported
634 set_sr_algorithm(SR_ALGORITHM_SPF
);
635 set_sr_global_label_range(srn
->srgb
);
636 set_sr_local_label_range(srn
->srlb
);
638 set_sr_node_msd(srn
->msd
);
641 OspfRI
.sr_info
.enabled
= true;
644 /* Refresh if already engaged or originate RI LSA */
645 for (ALL_LIST_ELEMENTS(OspfRI
.area_info
, node
, nnode
, ai
)) {
646 if (CHECK_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
))
647 ospf_router_info_lsa_schedule(ai
, REFRESH_THIS_LSA
);
649 ospf_router_info_lsa_schedule(ai
,
650 REORIGINATE_THIS_LSA
);
655 /*------------------------------------------------------------------------*
656 * Following are callback functions against generic Opaque-LSAs handling.
657 *------------------------------------------------------------------------*/
658 static void ospf_router_info_ism_change(struct ospf_interface
*oi
,
662 struct ospf_ri_area_info
*ai
;
664 /* Collect area information */
665 ai
= lookup_by_area(oi
->area
);
667 /* Check if area is not yet registered */
671 /* Add this new area to the list */
672 ai
= XCALLOC(MTYPE_OSPF_ROUTER_INFO
, sizeof(struct ospf_ri_area_info
));
674 ai
->flags
= RIFLG_LSA_INACTIVE
;
675 listnode_add(OspfRI
.area_info
, ai
);
680 /*------------------------------------------------------------------------*
681 * Following are OSPF protocol processing functions for ROUTER INFORMATION
682 *------------------------------------------------------------------------*/
684 static void build_tlv_header(struct stream
*s
, struct tlv_header
*tlvh
)
687 stream_put(s
, tlvh
, sizeof(struct tlv_header
));
691 static void build_tlv(struct stream
*s
, struct tlv_header
*tlvh
)
694 if (ntohs(tlvh
->type
) != 0) {
695 build_tlv_header(s
, tlvh
);
696 stream_put(s
, TLV_DATA(tlvh
), TLV_BODY_SIZE(tlvh
));
701 static void ospf_router_info_lsa_body_set(struct stream
*s
)
704 struct listnode
*node
;
705 struct ri_pce_subtlv_domain
*domain
;
706 struct ri_pce_subtlv_neighbor
*neighbor
;
708 /* Build Router Information TLV */
709 build_tlv(s
, &OspfRI
.router_cap
.header
);
711 /* Build Segment Routing TLVs if enabled */
712 if (OspfRI
.sr_info
.enabled
) {
713 /* Build Algorithm TLV */
714 build_tlv(s
, &TLV_HDR(OspfRI
.sr_info
.algo
));
716 build_tlv(s
, &TLV_HDR(OspfRI
.sr_info
.srgb
));
718 build_tlv(s
, &TLV_HDR(OspfRI
.sr_info
.srlb
));
720 build_tlv(s
, &TLV_HDR(OspfRI
.sr_info
.msd
));
723 /* Add RI PCE TLV if it is set */
724 if (OspfRI
.pce_info
.enabled
) {
726 /* Compute PCE Info header first */
727 set_pce_header(&OspfRI
.pce_info
);
730 build_tlv_header(s
, &OspfRI
.pce_info
.pce_header
.header
);
732 /* Build PCE address sub-tlv */
733 build_tlv(s
, &OspfRI
.pce_info
.pce_address
.header
);
735 /* Build PCE path scope sub-tlv */
736 build_tlv(s
, &OspfRI
.pce_info
.pce_scope
.header
);
738 /* Build PCE domain sub-tlv */
739 for (ALL_LIST_ELEMENTS_RO(OspfRI
.pce_info
.pce_domain
, node
,
741 build_tlv(s
, &domain
->header
);
743 /* Build PCE neighbor sub-tlv */
744 for (ALL_LIST_ELEMENTS_RO(OspfRI
.pce_info
.pce_neighbor
, node
,
746 build_tlv(s
, &neighbor
->header
);
748 /* Build PCE cap flag sub-tlv */
749 build_tlv(s
, &OspfRI
.pce_info
.pce_cap_flag
.header
);
755 /* Create new opaque-LSA. */
756 static struct ospf_lsa
*ospf_router_info_lsa_new(struct ospf_area
*area
)
760 struct lsa_header
*lsah
;
761 struct ospf_lsa
*new = NULL
;
762 uint8_t options
, lsa_type
;
763 struct in_addr lsa_id
;
767 /* Create a stream for LSA. */
768 s
= stream_new(OSPF_MAX_LSA_SIZE
);
770 lsah
= (struct lsa_header
*)STREAM_DATA(s
);
772 options
= OSPF_OPTION_E
; /* Enable AS external as we flood RI with
774 options
|= OSPF_OPTION_O
; /* Don't forget this :-) */
776 lsa_type
= OspfRI
.scope
;
777 /* LSA ID == 0 for Router Information see RFC 4970 */
778 tmp
= SET_OPAQUE_LSID(OPAQUE_TYPE_ROUTER_INFORMATION_LSA
, 0);
779 lsa_id
.s_addr
= htonl(tmp
);
781 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
))
783 "LSA[Type%d:%pI4]: Create an Opaque-LSA/ROUTER INFORMATION instance",
786 top
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
788 /* Set opaque-LSA header fields. */
789 lsa_header_set(s
, options
, lsa_type
, lsa_id
, top
->router_id
);
791 /* Set opaque-LSA body fields. */
792 ospf_router_info_lsa_body_set(s
);
795 length
= stream_get_endp(s
);
796 lsah
->length
= htons(length
);
798 /* Now, create an OSPF LSA instance. */
799 new = ospf_lsa_new_and_data(length
);
803 if (new->area
&& new->area
->ospf
)
804 new->vrf_id
= new->area
->ospf
->vrf_id
;
806 new->vrf_id
= VRF_DEFAULT
;
808 SET_FLAG(new->flags
, OSPF_LSA_SELF
);
809 memcpy(new->data
, lsah
, length
);
815 static int ospf_router_info_lsa_originate_as(void *arg
)
817 struct ospf_lsa
*new;
820 vrf_id_t vrf_id
= VRF_DEFAULT
;
823 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) {
825 EC_OSPF_LSA_INSTALL_FAILURE
,
826 "RI (%s): wrong flooding scope AREA instead of AS ?",
831 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
832 new = ospf_router_info_lsa_new(NULL
);
833 new->vrf_id
= VRF_DEFAULT
;
834 top
= (struct ospf
*)arg
;
836 /* Check ospf info */
838 zlog_debug("RI (%s): ospf instance not found for vrf id %u",
840 ospf_lsa_unlock(&new);
844 /* Install this LSA into LSDB. */
845 if (ospf_lsa_install(top
, NULL
/*oi */, new) == NULL
) {
847 EC_OSPF_LSA_INSTALL_FAILURE
,
848 "RI (%s): ospf_lsa_install() ?", __func__
);
849 ospf_lsa_unlock(&new);
853 /* Update new LSA origination count. */
854 top
->lsa_originate_count
++;
856 /* Flood new LSA through AREA or AS. */
857 SET_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
);
858 ospf_flood_through_as(top
, NULL
/*nbr */, new);
860 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
862 "LSA[Type%d:%pI4]: Originate Opaque-LSA/ROUTER INFORMATION",
863 new->data
->type
, &new->data
->id
);
864 ospf_lsa_header_dump(new->data
);
871 static int ospf_router_info_lsa_originate_area(void *arg
)
873 struct ospf_lsa
*new;
875 struct ospf_ri_area_info
*ai
= NULL
;
877 vrf_id_t vrf_id
= VRF_DEFAULT
;
880 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
) {
882 EC_OSPF_LSA_INSTALL_FAILURE
,
883 "RI (%s): wrong flooding scope AS instead of AREA ?",
888 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
889 ai
= lookup_by_area((struct ospf_area
*)arg
);
892 "RI (%s): There is no context for this Router Information. Stop processing",
896 if (ai
->area
->ospf
) {
897 vrf_id
= ai
->area
->ospf
->vrf_id
;
898 top
= ai
->area
->ospf
;
900 top
= ospf_lookup_by_vrf_id(vrf_id
);
902 new = ospf_router_info_lsa_new(ai
->area
);
903 new->vrf_id
= vrf_id
;
905 /* Check ospf info */
907 zlog_debug("RI (%s): ospf instance not found for vrf id %u",
909 ospf_lsa_unlock(&new);
913 /* Install this LSA into LSDB. */
914 if (ospf_lsa_install(top
, NULL
/*oi */, new) == NULL
) {
916 EC_OSPF_LSA_INSTALL_FAILURE
,
917 "RI (%s): ospf_lsa_install() ?", __func__
);
918 ospf_lsa_unlock(&new);
922 /* Update new LSA origination count. */
923 top
->lsa_originate_count
++;
925 /* Flood new LSA through AREA or AS. */
926 SET_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
);
927 ospf_flood_through_area(ai
->area
, NULL
/*nbr */, new);
929 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
931 "LSA[Type%d:%pI4]: Originate Opaque-LSA/ROUTER INFORMATION",
932 new->data
->type
, &new->data
->id
);
933 ospf_lsa_header_dump(new->data
);
940 static int ospf_router_info_lsa_originate(void *arg
)
943 struct ospf_ri_area_info
*ai
;
946 if (!OspfRI
.enabled
) {
947 zlog_info("RI (%s): ROUTER INFORMATION is disabled now.",
949 rc
= 0; /* This is not an error case. */
953 /* Check if Router Information LSA is already engaged */
954 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
) {
955 if ((CHECK_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
))
956 && (CHECK_FLAG(OspfRI
.as_flags
,
957 RIFLG_LSA_FORCED_REFRESH
))) {
958 UNSET_FLAG(OspfRI
.as_flags
, RIFLG_LSA_FORCED_REFRESH
);
959 ospf_router_info_lsa_schedule(NULL
, REFRESH_THIS_LSA
);
964 ai
= lookup_by_area((struct ospf_area
*)arg
);
968 "RI (%s): Missing area information", __func__
);
971 if ((CHECK_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
))
972 && (CHECK_FLAG(ai
->flags
, RIFLG_LSA_FORCED_REFRESH
))) {
973 UNSET_FLAG(ai
->flags
, RIFLG_LSA_FORCED_REFRESH
);
974 ospf_router_info_lsa_schedule(ai
, REFRESH_THIS_LSA
);
980 /* Router Information is not yet Engaged, check parameters */
981 if (!is_mandated_params_set(&OspfRI
))
984 "RI (%s): lacks mandated ROUTER INFORMATION parameters",
987 /* Ok, let's try to originate an LSA */
988 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
)
989 rc
= ospf_router_info_lsa_originate_as(arg
);
991 rc
= ospf_router_info_lsa_originate_area(arg
);
996 static struct ospf_lsa
*ospf_router_info_lsa_refresh(struct ospf_lsa
*lsa
)
998 struct ospf_ri_area_info
*ai
= NULL
;
999 struct ospf_lsa
*new = NULL
;
1002 if (!OspfRI
.enabled
) {
1004 * This LSA must have flushed before due to ROUTER INFORMATION
1006 * It seems a slip among routers in the routing domain.
1008 zlog_info("RI (%s): ROUTER INFORMATION is disabled now.",
1011 htons(OSPF_LSA_MAXAGE
); /* Flush it anyway. */
1014 /* Verify that the Router Information ID is supported */
1015 if (GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)) != 0) {
1018 "RI (%s): Unsupported Router Information ID",
1023 /* Process LSA depending of the flooding scope */
1024 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) {
1025 /* Get context AREA context */
1026 ai
= lookup_by_area(lsa
->area
);
1030 "RI (%s): No associated Area", __func__
);
1033 /* Flush LSA, if the lsa's age reached to MaxAge. */
1034 if (IS_LSA_MAXAGE(lsa
)) {
1035 UNSET_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
);
1036 ospf_opaque_lsa_flush_schedule(lsa
);
1039 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
1040 new = ospf_router_info_lsa_new(ai
->area
);
1041 new->data
->ls_seqnum
= lsa_seqnum_increment(lsa
);
1042 new->vrf_id
= lsa
->vrf_id
;
1043 /* Install this LSA into LSDB. */
1044 /* Given "lsa" will be freed in the next function. */
1045 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
1046 if (ospf_lsa_install(top
, NULL
/*oi */, new) == NULL
) {
1047 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE
,
1048 "RI (%s): ospf_lsa_install() ?", __func__
);
1049 ospf_lsa_unlock(&new);
1052 /* Flood updated LSA through AREA */
1053 ospf_flood_through_area(ai
->area
, NULL
/*nbr */, new);
1055 } else { /* AS Flooding scope */
1056 /* Flush LSA, if the lsa's age reached to MaxAge. */
1057 if (IS_LSA_MAXAGE(lsa
)) {
1058 UNSET_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
);
1059 ospf_opaque_lsa_flush_schedule(lsa
);
1062 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
1063 new = ospf_router_info_lsa_new(NULL
);
1064 new->data
->ls_seqnum
= lsa_seqnum_increment(lsa
);
1065 new->vrf_id
= lsa
->vrf_id
;
1066 /* Install this LSA into LSDB. */
1067 /* Given "lsa" will be freed in the next function. */
1068 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
1069 if (ospf_lsa_install(top
, NULL
/*oi */, new) == NULL
) {
1070 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE
,
1071 "RI (%s): ospf_lsa_install() ?", __func__
);
1072 ospf_lsa_unlock(&new);
1075 /* Flood updated LSA through AS */
1076 ospf_flood_through_as(top
, NULL
/*nbr */, new);
1079 /* Debug logging. */
1080 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
1082 "LSA[Type%d:%pI4]: Refresh Opaque-LSA/ROUTER INFORMATION",
1083 new->data
->type
, &new->data
->id
);
1084 ospf_lsa_header_dump(new->data
);
1090 static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info
*ai
,
1091 enum lsa_opcode opcode
)
1093 struct ospf_lsa lsa
;
1094 struct lsa_header lsah
;
1098 memset(&lsa
, 0, sizeof(lsa
));
1099 memset(&lsah
, 0, sizeof(lsah
));
1101 zlog_debug("RI (%s): LSA schedule %s%s%s", __func__
,
1102 opcode
== REORIGINATE_THIS_LSA
? "Re-Originate" : "",
1103 opcode
== REFRESH_THIS_LSA
? "Refresh" : "",
1104 opcode
== FLUSH_THIS_LSA
? "Flush" : "");
1106 /* Check LSA flags state coherence and collect area information */
1107 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) {
1108 if ((ai
== NULL
) || (ai
->area
== NULL
)) {
1111 "RI (%s): Router Info is Area scope flooding but area is not set",
1116 if (!CHECK_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
)
1117 && (opcode
!= REORIGINATE_THIS_LSA
))
1120 if (CHECK_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
)
1121 && (opcode
== REORIGINATE_THIS_LSA
))
1122 opcode
= REFRESH_THIS_LSA
;
1124 lsa
.area
= ai
->area
;
1125 top
= ai
->area
->ospf
;
1127 if (!CHECK_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
)
1128 && (opcode
!= REORIGINATE_THIS_LSA
))
1131 if (CHECK_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
)
1132 && (opcode
== REORIGINATE_THIS_LSA
))
1133 opcode
= REFRESH_THIS_LSA
;
1135 top
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1140 lsah
.type
= OspfRI
.scope
;
1142 /* LSA ID is set to 0 for the Router Information. See RFC 4970 */
1143 tmp
= SET_OPAQUE_LSID(OPAQUE_TYPE_ROUTER_INFORMATION_LSA
, 0);
1144 lsah
.id
.s_addr
= htonl(tmp
);
1147 case REORIGINATE_THIS_LSA
:
1148 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
)
1149 ospf_opaque_lsa_reoriginate_schedule(
1150 (void *)ai
->area
, OSPF_OPAQUE_AREA_LSA
,
1151 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
1153 ospf_opaque_lsa_reoriginate_schedule(
1154 (void *)top
, OSPF_OPAQUE_AS_LSA
,
1155 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
1157 case REFRESH_THIS_LSA
:
1158 ospf_opaque_lsa_refresh_schedule(&lsa
);
1160 case FLUSH_THIS_LSA
:
1161 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
)
1162 UNSET_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
);
1164 UNSET_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
);
1165 ospf_opaque_lsa_flush_schedule(&lsa
);
1172 /* Callback to handle Segment Routing information */
1173 static int ospf_router_info_lsa_update(struct ospf_lsa
*lsa
)
1178 flog_warn(EC_OSPF_LSA
, "RI (%s): Abort! LSA is NULL",
1183 /* Process only Opaque LSA */
1184 if ((lsa
->data
->type
!= OSPF_OPAQUE_AREA_LSA
)
1185 && (lsa
->data
->type
!= OSPF_OPAQUE_AS_LSA
))
1188 /* Process only Router Information LSA */
1189 if (GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
))
1190 != OPAQUE_TYPE_ROUTER_INFORMATION_LSA
)
1193 /* Check if it is not my LSA */
1194 if (IS_LSA_SELF(lsa
))
1197 /* Check if Router Info & Segment Routing are enable */
1198 if (!OspfRI
.enabled
|| !OspfRI
.sr_info
.enabled
)
1201 /* Call Segment Routing LSA update or deletion */
1202 if (!IS_LSA_MAXAGE(lsa
))
1203 ospf_sr_ri_lsa_update(lsa
);
1205 ospf_sr_ri_lsa_delete(lsa
);
1210 /*------------------------------------------------------------------------*
1211 * Following are vty session control functions.
1212 *------------------------------------------------------------------------*/
1214 #define check_tlv_size(size, msg) \
1216 if (ntohs(tlvh->length) > size) { \
1218 vty_out(vty, " Wrong %s TLV size: %d(%d)\n", \
1219 msg, ntohs(tlvh->length), size); \
1221 zlog_debug(" Wrong %s TLV size: %d(%d)", \
1222 msg, ntohs(tlvh->length), size); \
1223 return size + TLV_HDR_SIZE; \
1227 static uint16_t show_vty_router_cap(struct vty
*vty
, struct tlv_header
*tlvh
)
1229 struct ri_tlv_router_cap
*top
= (struct ri_tlv_router_cap
*)tlvh
;
1231 check_tlv_size(RI_TLV_CAPABILITIES_SIZE
, "Router Capabilities");
1234 vty_out(vty
, " Router Capabilities: 0x%x\n",
1237 zlog_debug(" Router Capabilities: 0x%x", ntohl(top
->value
));
1239 return TLV_SIZE(tlvh
);
1242 static uint16_t show_vty_pce_subtlv_address(struct vty
*vty
,
1243 struct tlv_header
*tlvh
)
1245 struct ri_pce_subtlv_address
*top
=
1246 (struct ri_pce_subtlv_address
*)tlvh
;
1248 if (ntohs(top
->address
.type
) == PCE_ADDRESS_IPV4
) {
1249 check_tlv_size(PCE_ADDRESS_IPV4_SIZE
, "PCE Address");
1251 vty_out(vty
, " PCE Address: %pI4\n",
1252 &top
->address
.value
);
1254 zlog_debug(" PCE Address: %pI4",
1255 &top
->address
.value
);
1256 } else if (ntohs(top
->address
.type
) == PCE_ADDRESS_IPV6
) {
1257 /* TODO: Add support to IPv6 with inet_ntop() */
1258 check_tlv_size(PCE_ADDRESS_IPV6_SIZE
, "PCE Address");
1260 vty_out(vty
, " PCE Address: 0x%x\n",
1261 ntohl(top
->address
.value
.s_addr
));
1263 zlog_debug(" PCE Address: 0x%x",
1264 ntohl(top
->address
.value
.s_addr
));
1267 vty_out(vty
, " Wrong PCE Address type: 0x%x\n",
1268 ntohl(top
->address
.type
));
1270 zlog_debug(" Wrong PCE Address type: 0x%x",
1271 ntohl(top
->address
.type
));
1274 return TLV_SIZE(tlvh
);
1277 static uint16_t show_vty_pce_subtlv_path_scope(struct vty
*vty
,
1278 struct tlv_header
*tlvh
)
1280 struct ri_pce_subtlv_path_scope
*top
=
1281 (struct ri_pce_subtlv_path_scope
*)tlvh
;
1283 check_tlv_size(RI_PCE_SUBTLV_PATH_SCOPE_SIZE
, "PCE Path Scope");
1286 vty_out(vty
, " PCE Path Scope: 0x%x\n", ntohl(top
->value
));
1288 zlog_debug(" PCE Path Scope: 0x%x", ntohl(top
->value
));
1290 return TLV_SIZE(tlvh
);
1293 static uint16_t show_vty_pce_subtlv_domain(struct vty
*vty
,
1294 struct tlv_header
*tlvh
)
1296 struct ri_pce_subtlv_domain
*top
= (struct ri_pce_subtlv_domain
*)tlvh
;
1299 check_tlv_size(RI_PCE_SUBTLV_DOMAIN_SIZE
, "PCE Domain");
1301 if (ntohs(top
->type
) == PCE_DOMAIN_TYPE_AREA
) {
1302 tmp
.s_addr
= top
->value
;
1304 vty_out(vty
, " PCE Domain Area: %pI4\n", &tmp
);
1306 zlog_debug(" PCE Domain Area: %pI4", &tmp
);
1307 } else if (ntohs(top
->type
) == PCE_DOMAIN_TYPE_AS
) {
1309 vty_out(vty
, " PCE Domain AS: %d\n",
1312 zlog_debug(" PCE Domain AS: %d", ntohl(top
->value
));
1315 vty_out(vty
, " Wrong PCE Domain type: %d\n",
1318 zlog_debug(" Wrong PCE Domain type: %d",
1322 return TLV_SIZE(tlvh
);
1325 static uint16_t show_vty_pce_subtlv_neighbor(struct vty
*vty
,
1326 struct tlv_header
*tlvh
)
1329 struct ri_pce_subtlv_neighbor
*top
=
1330 (struct ri_pce_subtlv_neighbor
*)tlvh
;
1333 check_tlv_size(RI_PCE_SUBTLV_NEIGHBOR_SIZE
, "PCE Neighbor");
1335 if (ntohs(top
->type
) == PCE_DOMAIN_TYPE_AREA
) {
1336 tmp
.s_addr
= top
->value
;
1338 vty_out(vty
, " PCE Neighbor Area: %pI4\n", &tmp
);
1340 zlog_debug(" PCE Neighbor Area: %pI4", &tmp
);
1341 } else if (ntohs(top
->type
) == PCE_DOMAIN_TYPE_AS
) {
1343 vty_out(vty
, " PCE Neighbor AS: %d\n",
1346 zlog_debug(" PCE Neighbor AS: %d",
1350 vty_out(vty
, " Wrong PCE Neighbor type: %d\n",
1353 zlog_debug(" Wrong PCE Neighbor type: %d",
1357 return TLV_SIZE(tlvh
);
1360 static uint16_t show_vty_pce_subtlv_cap_flag(struct vty
*vty
,
1361 struct tlv_header
*tlvh
)
1363 struct ri_pce_subtlv_cap_flag
*top
=
1364 (struct ri_pce_subtlv_cap_flag
*)tlvh
;
1366 check_tlv_size(RI_PCE_SUBTLV_CAP_FLAG_SIZE
, "PCE Capabilities");
1369 vty_out(vty
, " PCE Capabilities Flag: 0x%x\n",
1372 zlog_debug(" PCE Capabilities Flag: 0x%x",
1375 return TLV_SIZE(tlvh
);
1378 static uint16_t show_vty_unknown_tlv(struct vty
*vty
, struct tlv_header
*tlvh
,
1381 if (TLV_SIZE(tlvh
) > buf_size
) {
1384 " TLV size %d exceeds buffer size. Abort!",
1388 " TLV size %d exceeds buffer size. Abort!",
1394 vty_out(vty
, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
1395 ntohs(tlvh
->type
), ntohs(tlvh
->length
));
1397 zlog_debug(" Unknown TLV: [type(0x%x), length(0x%x)]",
1398 ntohs(tlvh
->type
), ntohs(tlvh
->length
));
1400 return TLV_SIZE(tlvh
);
1403 static uint16_t show_vty_pce_info(struct vty
*vty
, struct tlv_header
*ri
,
1406 struct tlv_header
*tlvh
;
1407 uint16_t length
= ntohs(ri
->length
);
1410 /* Verify that TLV length is valid against remaining buffer size */
1411 if (length
> buf_size
) {
1413 " PCE Info TLV size %d exceeds buffer size. Abort!\n",
1418 for (tlvh
= ri
; sum
< length
; tlvh
= TLV_HDR_NEXT(tlvh
)) {
1419 switch (ntohs(tlvh
->type
)) {
1420 case RI_PCE_SUBTLV_ADDRESS
:
1421 sum
+= show_vty_pce_subtlv_address(vty
, tlvh
);
1423 case RI_PCE_SUBTLV_PATH_SCOPE
:
1424 sum
+= show_vty_pce_subtlv_path_scope(vty
, tlvh
);
1426 case RI_PCE_SUBTLV_DOMAIN
:
1427 sum
+= show_vty_pce_subtlv_domain(vty
, tlvh
);
1429 case RI_PCE_SUBTLV_NEIGHBOR
:
1430 sum
+= show_vty_pce_subtlv_neighbor(vty
, tlvh
);
1432 case RI_PCE_SUBTLV_CAP_FLAG
:
1433 sum
+= show_vty_pce_subtlv_cap_flag(vty
, tlvh
);
1436 sum
+= show_vty_unknown_tlv(vty
, tlvh
, length
- sum
);
1443 /* Display Segment Routing Algorithm TLV information */
1444 static uint16_t show_vty_sr_algorithm(struct vty
*vty
, struct tlv_header
*tlvh
)
1446 struct ri_sr_tlv_sr_algorithm
*algo
=
1447 (struct ri_sr_tlv_sr_algorithm
*)tlvh
;
1450 check_tlv_size(ALGORITHM_COUNT
, "Segment Routing Algorithm");
1453 vty_out(vty
, " Segment Routing Algorithm TLV:\n");
1454 for (i
= 0; i
< ntohs(algo
->header
.length
); i
++) {
1455 switch (algo
->value
[i
]) {
1457 vty_out(vty
, " Algorithm %d: SPF\n", i
);
1460 vty_out(vty
, " Algorithm %d: Strict SPF\n",
1465 " Algorithm %d: Unknown value %d\n", i
,
1471 zlog_debug(" Segment Routing Algorithm TLV:");
1472 for (i
= 0; i
< ntohs(algo
->header
.length
); i
++)
1473 switch (algo
->value
[i
]) {
1475 zlog_debug(" Algorithm %d: SPF", i
);
1478 zlog_debug(" Algorithm %d: Strict SPF", i
);
1481 zlog_debug(" Algorithm %d: Unknown value %d",
1487 return TLV_SIZE(tlvh
);
1490 /* Display Segment Routing SID/Label Range TLV information */
1491 static uint16_t show_vty_sr_range(struct vty
*vty
, struct tlv_header
*tlvh
)
1493 struct ri_sr_tlv_sid_label_range
*range
=
1494 (struct ri_sr_tlv_sid_label_range
*)tlvh
;
1496 check_tlv_size(RI_SR_TLV_LABEL_RANGE_SIZE
, "SR Label Range");
1500 " Segment Routing %s Range TLV:\n"
1501 " Range Size = %d\n"
1502 " SID Label = %d\n\n",
1503 ntohs(range
->header
.type
) == RI_SR_TLV_SRGB_LABEL_RANGE
1506 GET_RANGE_SIZE(ntohl(range
->size
)),
1507 GET_LABEL(ntohl(range
->lower
.value
)));
1510 " Segment Routing %s Range TLV: Range Size = %d SID Label = %d",
1511 ntohs(range
->header
.type
) == RI_SR_TLV_SRGB_LABEL_RANGE
1514 GET_RANGE_SIZE(ntohl(range
->size
)),
1515 GET_LABEL(ntohl(range
->lower
.value
)));
1518 return TLV_SIZE(tlvh
);
1521 /* Display Segment Routing Maximum Stack Depth TLV information */
1522 static uint16_t show_vty_sr_msd(struct vty
*vty
, struct tlv_header
*tlvh
)
1524 struct ri_sr_tlv_node_msd
*msd
= (struct ri_sr_tlv_node_msd
*)tlvh
;
1526 check_tlv_size(RI_SR_TLV_NODE_MSD_SIZE
, "Node Maximum Stack Depth");
1530 " Segment Routing MSD TLV:\n"
1531 " Node Maximum Stack Depth = %d\n",
1535 " Segment Routing MSD TLV: Node Maximum Stack Depth = %d",
1539 return TLV_SIZE(tlvh
);
1542 static void ospf_router_info_show_info(struct vty
*vty
,
1543 struct json_object
*json
,
1544 struct ospf_lsa
*lsa
)
1546 struct lsa_header
*lsah
= lsa
->data
;
1547 struct tlv_header
*tlvh
;
1548 uint16_t length
= 0, sum
= 0;
1553 /* Initialize TLV browsing */
1554 length
= lsa
->size
- OSPF_LSA_HEADER_SIZE
;
1556 for (tlvh
= TLV_HDR_TOP(lsah
); sum
< length
&& tlvh
;
1557 tlvh
= TLV_HDR_NEXT(tlvh
)) {
1558 switch (ntohs(tlvh
->type
)) {
1559 case RI_TLV_CAPABILITIES
:
1560 sum
+= show_vty_router_cap(vty
, tlvh
);
1564 sum
+= TLV_HDR_SIZE
;
1565 sum
+= show_vty_pce_info(vty
, tlvh
, length
- sum
);
1567 case RI_SR_TLV_SR_ALGORITHM
:
1568 sum
+= show_vty_sr_algorithm(vty
, tlvh
);
1570 case RI_SR_TLV_SRGB_LABEL_RANGE
:
1571 case RI_SR_TLV_SRLB_LABEL_RANGE
:
1572 sum
+= show_vty_sr_range(vty
, tlvh
);
1574 case RI_SR_TLV_NODE_MSD
:
1575 sum
+= show_vty_sr_msd(vty
, tlvh
);
1579 sum
+= show_vty_unknown_tlv(vty
, tlvh
, length
);
1587 static void ospf_router_info_config_write_router(struct vty
*vty
)
1589 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1590 struct listnode
*node
;
1591 struct ri_pce_subtlv_domain
*domain
;
1592 struct ri_pce_subtlv_neighbor
*neighbor
;
1595 if (!OspfRI
.enabled
)
1598 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
)
1599 vty_out(vty
, " router-info as\n");
1601 vty_out(vty
, " router-info area\n");
1603 if (OspfRI
.pce_info
.enabled
) {
1605 if (pce
->pce_address
.header
.type
!= 0)
1606 vty_out(vty
, " pce address %pI4\n",
1607 &pce
->pce_address
.address
.value
);
1609 if (pce
->pce_cap_flag
.header
.type
!= 0)
1610 vty_out(vty
, " pce flag 0x%x\n",
1611 ntohl(pce
->pce_cap_flag
.value
));
1613 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
1614 if (domain
->header
.type
!= 0) {
1615 if (domain
->type
== PCE_DOMAIN_TYPE_AREA
) {
1616 tmp
.s_addr
= domain
->value
;
1617 vty_out(vty
, " pce domain area %pI4\n",
1620 vty_out(vty
, " pce domain as %d\n",
1621 ntohl(domain
->value
));
1626 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
1627 if (neighbor
->header
.type
!= 0) {
1628 if (neighbor
->type
== PCE_DOMAIN_TYPE_AREA
) {
1629 tmp
.s_addr
= neighbor
->value
;
1631 " pce neighbor area %pI4\n",
1634 vty_out(vty
, " pce neighbor as %d\n",
1635 ntohl(neighbor
->value
));
1640 if (pce
->pce_scope
.header
.type
!= 0)
1641 vty_out(vty
, " pce scope 0x%x\n",
1642 ntohl(OspfRI
.pce_info
.pce_scope
.value
));
1647 /*------------------------------------------------------------------------*
1648 * Following are vty command functions.
1649 *------------------------------------------------------------------------*/
1650 /* Simple wrapper schedule RI LSA action in function of the scope */
1651 static void ospf_router_info_schedule(enum lsa_opcode opcode
)
1653 struct listnode
*node
, *nnode
;
1654 struct ospf_ri_area_info
*ai
;
1656 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
) {
1657 if (CHECK_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
))
1658 ospf_router_info_lsa_schedule(NULL
, opcode
);
1659 else if (opcode
== REORIGINATE_THIS_LSA
)
1660 ospf_router_info_lsa_schedule(NULL
, opcode
);
1662 for (ALL_LIST_ELEMENTS(OspfRI
.area_info
, node
, nnode
, ai
)) {
1663 if (CHECK_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
))
1664 ospf_router_info_lsa_schedule(ai
, opcode
);
1670 router_info_area_cmd
,
1671 "router-info <as|area [A.B.C.D]>",
1673 "Enable the Router Information functionality with AS flooding scope\n"
1674 "Enable the Router Information functionality with Area flooding scope\n"
1675 "OSPF area ID in IP format (deprecated)\n")
1683 /* Check and get Area value if present */
1684 if (strncmp(argv
[idx_mode
]->arg
, "as", 2) == 0)
1685 scope
= OSPF_OPAQUE_AS_LSA
;
1687 scope
= OSPF_OPAQUE_AREA_LSA
;
1689 /* First start to register Router Information callbacks */
1690 if (!OspfRI
.registered
&& (ospf_router_info_register(scope
)) != 0) {
1692 "%% Unable to register Router Information callbacks.");
1695 "RI (%s): Unable to register Router Information callbacks. Abort!",
1697 return CMD_WARNING_CONFIG_FAILED
;
1700 OspfRI
.enabled
= true;
1702 if (IS_DEBUG_OSPF_EVENT
)
1703 zlog_debug("RI-> Router Information (%s flooding): OFF -> ON",
1704 OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
? "Area"
1708 * Following code is intended to handle two cases;
1710 * 1) Router Information was disabled at startup time, but now become
1712 * 2) Router Information was once enabled then disabled, and now enabled
1716 initialize_params(&OspfRI
);
1718 /* Originate or Refresh RI LSA if already engaged */
1719 ospf_router_info_schedule(REORIGINATE_THIS_LSA
);
1724 DEFUN (no_router_info
,
1728 "Disable the Router Information functionality\n")
1731 if (!OspfRI
.enabled
)
1734 if (IS_DEBUG_OSPF_EVENT
)
1735 zlog_debug("RI-> Router Information: ON -> OFF");
1737 ospf_router_info_schedule(FLUSH_THIS_LSA
);
1739 OspfRI
.enabled
= false;
1744 static int ospf_ri_enabled(struct vty
*vty
)
1750 vty_out(vty
, "%% OSPF RI is not turned on\n");
1757 "pce address A.B.C.D",
1759 "Stable IP address of the PCE\n"
1760 "PCE address in IPv4 address format\n")
1763 struct in_addr value
;
1764 struct ospf_pce_info
*pi
= &OspfRI
.pce_info
;
1766 if (!ospf_ri_enabled(vty
))
1767 return CMD_WARNING_CONFIG_FAILED
;
1769 if (!inet_aton(argv
[idx_ipv4
]->arg
, &value
)) {
1770 vty_out(vty
, "Please specify PCE Address by A.B.C.D\n");
1771 return CMD_WARNING_CONFIG_FAILED
;
1774 if (ntohs(pi
->pce_address
.header
.type
) == 0
1775 || ntohl(pi
->pce_address
.address
.value
.s_addr
)
1776 != ntohl(value
.s_addr
)) {
1778 set_pce_address(value
, pi
);
1780 /* Refresh RI LSA if already engaged */
1781 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1787 DEFUN (no_pce_address
,
1789 "no pce address [A.B.C.D]",
1792 "Disable PCE address\n"
1793 "PCE address in IPv4 address format\n")
1796 unset_param(&OspfRI
.pce_info
.pce_address
);
1798 /* Refresh RI LSA if already engaged */
1799 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1804 DEFUN (pce_path_scope
,
1806 "pce scope BITPATTERN",
1808 "Path scope visibilities of the PCE for path computation\n"
1809 "32-bit Hexadecimal value\n")
1811 int idx_bitpattern
= 2;
1813 struct ospf_pce_info
*pi
= &OspfRI
.pce_info
;
1815 if (!ospf_ri_enabled(vty
))
1816 return CMD_WARNING_CONFIG_FAILED
;
1818 if (sscanf(argv
[idx_bitpattern
]->arg
, "0x%x", &scope
) != 1) {
1819 vty_out(vty
, "pce_path_scope: fscanf: %s\n",
1820 safe_strerror(errno
));
1821 return CMD_WARNING_CONFIG_FAILED
;
1824 if (ntohl(pi
->pce_scope
.header
.type
) == 0
1825 || scope
!= pi
->pce_scope
.value
) {
1826 set_pce_path_scope(scope
, pi
);
1828 /* Refresh RI LSA if already engaged */
1829 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1835 DEFUN (no_pce_path_scope
,
1836 no_pce_path_scope_cmd
,
1837 "no pce scope [BITPATTERN]",
1840 "Disable PCE path scope\n"
1841 "32-bit Hexadecimal value\n")
1844 unset_param(&OspfRI
.pce_info
.pce_address
);
1846 /* Refresh RI LSA if already engaged */
1847 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1854 "pce domain as (0-65535)",
1856 "Configure PCE domain AS number\n"
1857 "AS number where the PCE as visibilities for path computation\n"
1858 "AS number in decimal <0-65535>\n")
1863 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1864 struct listnode
*node
;
1865 struct ri_pce_subtlv_domain
*domain
;
1867 if (!ospf_ri_enabled(vty
))
1868 return CMD_WARNING_CONFIG_FAILED
;
1870 if (sscanf(argv
[idx_number
]->arg
, "%" SCNu32
, &as
) != 1) {
1871 vty_out(vty
, "pce_domain: fscanf: %s\n", safe_strerror(errno
));
1872 return CMD_WARNING_CONFIG_FAILED
;
1875 /* Check if the domain is not already in the domain list */
1876 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
1877 if (ntohl(domain
->header
.type
) == 0 && as
== domain
->value
)
1881 /* Create new domain if not found */
1882 set_pce_domain(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1884 /* Refresh RI LSA if already engaged */
1885 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1890 DEFUN (no_pce_domain
,
1892 "no pce domain as (0-65535)",
1895 "Disable PCE domain AS number\n"
1896 "AS number where the PCE as visibilities for path computation\n"
1897 "AS number in decimal <0-65535>\n")
1902 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1904 if (sscanf(argv
[idx_number
]->arg
, "%" SCNu32
, &as
) != 1) {
1905 vty_out(vty
, "no_pce_domain: fscanf: %s\n",
1906 safe_strerror(errno
));
1907 return CMD_WARNING_CONFIG_FAILED
;
1910 /* Unset corresponding PCE domain */
1911 unset_pce_domain(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1913 /* Refresh RI LSA if already engaged */
1914 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1919 DEFUN (pce_neigbhor
,
1921 "pce neighbor as (0-65535)",
1923 "Configure PCE neighbor domain AS number\n"
1924 "AS number of PCE neighbors\n"
1925 "AS number in decimal <0-65535>\n")
1930 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1931 struct listnode
*node
;
1932 struct ri_pce_subtlv_neighbor
*neighbor
;
1934 if (!ospf_ri_enabled(vty
))
1935 return CMD_WARNING_CONFIG_FAILED
;
1937 if (sscanf(argv
[idx_number
]->arg
, "%" SCNu32
, &as
) != 1) {
1938 vty_out(vty
, "pce_neighbor: fscanf: %s\n",
1939 safe_strerror(errno
));
1940 return CMD_WARNING_CONFIG_FAILED
;
1943 /* Check if the domain is not already in the domain list */
1944 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
1945 if (ntohl(neighbor
->header
.type
) == 0 && as
== neighbor
->value
)
1949 /* Create new domain if not found */
1950 set_pce_neighbor(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1952 /* Refresh RI LSA if already engaged */
1953 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1958 DEFUN (no_pce_neighbor
,
1959 no_pce_neighbor_cmd
,
1960 "no pce neighbor as (0-65535)",
1963 "Disable PCE neighbor AS number\n"
1964 "AS number of PCE neighbor\n"
1965 "AS number in decimal <0-65535>\n")
1970 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1972 if (sscanf(argv
[idx_number
]->arg
, "%" SCNu32
, &as
) != 1) {
1973 vty_out(vty
, "no_pce_neighbor: fscanf: %s\n",
1974 safe_strerror(errno
));
1975 return CMD_WARNING_CONFIG_FAILED
;
1978 /* Unset corresponding PCE domain */
1979 unset_pce_neighbor(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1981 /* Refresh RI LSA if already engaged */
1982 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1987 DEFUN (pce_cap_flag
,
1989 "pce flag BITPATTERN",
1991 "Capabilities of the PCE for path computation\n"
1992 "32-bit Hexadecimal value\n")
1994 int idx_bitpattern
= 2;
1997 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1999 if (!ospf_ri_enabled(vty
))
2000 return CMD_WARNING_CONFIG_FAILED
;
2002 if (sscanf(argv
[idx_bitpattern
]->arg
, "0x%x", &cap
) != 1) {
2003 vty_out(vty
, "pce_cap_flag: fscanf: %s\n",
2004 safe_strerror(errno
));
2005 return CMD_WARNING_CONFIG_FAILED
;
2008 if (ntohl(pce
->pce_cap_flag
.header
.type
) == 0
2009 || cap
!= pce
->pce_cap_flag
.value
) {
2010 set_pce_cap_flag(cap
, pce
);
2012 /* Refresh RI LSA if already engaged */
2013 ospf_router_info_schedule(REFRESH_THIS_LSA
);
2019 DEFUN (no_pce_cap_flag
,
2020 no_pce_cap_flag_cmd
,
2024 "Disable PCE capabilities\n")
2027 unset_param(&OspfRI
.pce_info
.pce_cap_flag
);
2029 /* Refresh RI LSA if already engaged */
2030 ospf_router_info_schedule(REFRESH_THIS_LSA
);
2035 DEFUN (show_ip_ospf_router_info
,
2036 show_ip_ospf_router_info_cmd
,
2037 "show ip ospf router-info",
2041 "Router Information\n")
2044 if (OspfRI
.enabled
) {
2045 vty_out(vty
, "--- Router Information parameters ---\n");
2046 show_vty_router_cap(vty
, &OspfRI
.router_cap
.header
);
2050 " Router Information is disabled on this router\n");
2055 DEFUN (show_ip_opsf_router_info_pce
,
2056 show_ip_ospf_router_info_pce_cmd
,
2057 "show ip ospf router-info pce",
2061 "Router Information\n"
2062 "PCE information\n")
2065 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
2066 struct listnode
*node
;
2067 struct ri_pce_subtlv_domain
*domain
;
2068 struct ri_pce_subtlv_neighbor
*neighbor
;
2070 if ((OspfRI
.enabled
) && (OspfRI
.pce_info
.enabled
)) {
2071 vty_out(vty
, "--- PCE parameters ---\n");
2073 if (pce
->pce_address
.header
.type
!= 0)
2074 show_vty_pce_subtlv_address(vty
,
2075 &pce
->pce_address
.header
);
2077 if (pce
->pce_scope
.header
.type
!= 0)
2078 show_vty_pce_subtlv_path_scope(vty
,
2079 &pce
->pce_scope
.header
);
2081 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
2082 if (domain
->header
.type
!= 0)
2083 show_vty_pce_subtlv_domain(vty
,
2087 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
2088 if (neighbor
->header
.type
!= 0)
2089 show_vty_pce_subtlv_neighbor(vty
,
2093 if (pce
->pce_cap_flag
.header
.type
!= 0)
2094 show_vty_pce_subtlv_cap_flag(vty
,
2095 &pce
->pce_cap_flag
.header
);
2098 vty_out(vty
, " PCE info is disabled on this router\n");
2104 /* Install new CLI commands */
2105 static void ospf_router_info_register_vty(void)
2107 install_element(VIEW_NODE
, &show_ip_ospf_router_info_cmd
);
2108 install_element(VIEW_NODE
, &show_ip_ospf_router_info_pce_cmd
);
2110 install_element(OSPF_NODE
, &router_info_area_cmd
);
2111 install_element(OSPF_NODE
, &no_router_info_cmd
);
2112 install_element(OSPF_NODE
, &pce_address_cmd
);
2113 install_element(OSPF_NODE
, &no_pce_address_cmd
);
2114 install_element(OSPF_NODE
, &pce_path_scope_cmd
);
2115 install_element(OSPF_NODE
, &no_pce_path_scope_cmd
);
2116 install_element(OSPF_NODE
, &pce_domain_cmd
);
2117 install_element(OSPF_NODE
, &no_pce_domain_cmd
);
2118 install_element(OSPF_NODE
, &pce_neighbor_cmd
);
2119 install_element(OSPF_NODE
, &no_pce_neighbor_cmd
);
2120 install_element(OSPF_NODE
, &pce_cap_flag_cmd
);
2121 install_element(OSPF_NODE
, &no_pce_cap_flag_cmd
);