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 * Following 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
,
77 struct json_object
*json
,
78 struct ospf_lsa
*lsa
);
79 static int ospf_router_info_lsa_originate(void *arg
);
80 static struct ospf_lsa
*ospf_router_info_lsa_refresh(struct ospf_lsa
*lsa
);
81 static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info
*ai
,
82 enum lsa_opcode opcode
);
83 static void ospf_router_info_register_vty(void);
84 static int ospf_router_info_lsa_update(struct ospf_lsa
*lsa
);
85 static void del_area_info(void *val
);
86 static void del_pce_info(void *val
);
88 int ospf_router_info_init(void)
91 zlog_info("RI (%s): Initialize Router Information", __func__
);
93 memset(&OspfRI
, 0, sizeof(OspfRI
));
94 OspfRI
.enabled
= false;
95 OspfRI
.registered
= 0;
96 OspfRI
.scope
= OSPF_OPAQUE_AS_LSA
;
97 OspfRI
.as_flags
= RIFLG_LSA_INACTIVE
;
98 OspfRI
.area_info
= list_new();
99 OspfRI
.area_info
->del
= del_area_info
;
101 /* Initialize pce domain and neighbor list */
102 OspfRI
.pce_info
.enabled
= false;
103 OspfRI
.pce_info
.pce_domain
= list_new();
104 OspfRI
.pce_info
.pce_domain
->del
= del_pce_info
;
105 OspfRI
.pce_info
.pce_neighbor
= list_new();
106 OspfRI
.pce_info
.pce_neighbor
->del
= del_pce_info
;
108 /* Initialize Segment Routing information structure */
109 OspfRI
.sr_info
.enabled
= false;
111 ospf_router_info_register_vty();
116 static int ospf_router_info_register(uint8_t scope
)
120 if (OspfRI
.registered
)
123 zlog_info("RI (%s): Register Router Information with scope %s(%d)",
125 scope
== OSPF_OPAQUE_AREA_LSA
? "Area" : "AS", scope
);
126 rc
= ospf_register_opaque_functab(
127 scope
, OPAQUE_TYPE_ROUTER_INFORMATION_LSA
,
128 NULL
, /* new interface */
129 NULL
, /* del interface */
130 ospf_router_info_ism_change
,
131 NULL
, /* NSM change */
132 ospf_router_info_config_write_router
,
133 NULL
, /* Config. write interface */
134 NULL
, /* Config. write debug */
135 ospf_router_info_show_info
, ospf_router_info_lsa_originate
,
136 ospf_router_info_lsa_refresh
, ospf_router_info_lsa_update
,
137 NULL
); /* del_lsa_hook */
141 EC_OSPF_OPAQUE_REGISTRATION
,
142 "RI (%s): Failed to register functions", __func__
);
146 OspfRI
.registered
= 1;
147 OspfRI
.scope
= scope
;
151 static int ospf_router_info_unregister(void)
154 if ((OspfRI
.scope
!= OSPF_OPAQUE_AS_LSA
)
155 && (OspfRI
.scope
!= OSPF_OPAQUE_AREA_LSA
)) {
156 assert("Unable to unregister Router Info functions: Wrong scope!"
161 ospf_delete_opaque_functab(OspfRI
.scope
,
162 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
164 OspfRI
.registered
= 0;
168 void ospf_router_info_term(void)
171 list_delete(&OspfRI
.pce_info
.pce_domain
);
172 list_delete(&OspfRI
.pce_info
.pce_neighbor
);
174 OspfRI
.enabled
= false;
176 ospf_router_info_unregister();
181 void ospf_router_info_finish(void)
183 struct listnode
*node
, *nnode
;
184 struct ospf_ri_area_info
*ai
;
186 /* Flush Router Info LSA */
187 for (ALL_LIST_ELEMENTS(OspfRI
.area_info
, node
, nnode
, ai
))
188 if (CHECK_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
))
189 ospf_router_info_lsa_schedule(ai
, FLUSH_THIS_LSA
);
191 list_delete_all_node(OspfRI
.pce_info
.pce_domain
);
192 list_delete_all_node(OspfRI
.pce_info
.pce_neighbor
);
194 OspfRI
.enabled
= false;
197 static void del_area_info(void *val
)
199 XFREE(MTYPE_OSPF_ROUTER_INFO
, val
);
202 static void del_pce_info(void *val
)
204 XFREE(MTYPE_OSPF_PCE_PARAMS
, val
);
207 /* Catch RI LSA flooding Scope for ospf_ext.[h,c] code */
208 struct scope_info
ospf_router_info_get_flooding_scope(void)
210 struct scope_info flooding_scope
;
212 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
) {
213 flooding_scope
.scope
= OSPF_OPAQUE_AS_LSA
;
214 flooding_scope
.areas
= NULL
;
215 return flooding_scope
;
217 flooding_scope
.scope
= OSPF_OPAQUE_AREA_LSA
;
218 flooding_scope
.areas
= OspfRI
.area_info
;
219 return flooding_scope
;
222 static struct ospf_ri_area_info
*lookup_by_area(struct ospf_area
*area
)
224 struct listnode
*node
, *nnode
;
225 struct ospf_ri_area_info
*ai
;
227 for (ALL_LIST_ELEMENTS(OspfRI
.area_info
, node
, nnode
, ai
))
228 if (ai
->area
== area
)
234 /*------------------------------------------------------------------------*
235 * Following are control functions for ROUTER INFORMATION parameters
237 *------------------------------------------------------------------------*/
239 static void set_router_info_capabilities(struct ri_tlv_router_cap
*ric
,
242 ric
->header
.type
= htons(RI_TLV_CAPABILITIES
);
243 ric
->header
.length
= htons(RI_TLV_LENGTH
);
244 ric
->value
= htonl(cap
);
248 static int set_pce_header(struct ospf_pce_info
*pce
)
251 struct listnode
*node
;
252 struct ri_pce_subtlv_domain
*domain
;
253 struct ri_pce_subtlv_neighbor
*neighbor
;
256 if (ntohs(pce
->pce_address
.header
.type
) != 0)
257 length
+= TLV_SIZE(&pce
->pce_address
.header
);
260 if (ntohs(pce
->pce_scope
.header
.type
) != 0)
261 length
+= TLV_SIZE(&pce
->pce_scope
.header
);
264 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
265 if (ntohs(domain
->header
.type
) != 0)
266 length
+= TLV_SIZE(&domain
->header
);
270 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
271 if (ntohs(neighbor
->header
.type
) != 0)
272 length
+= TLV_SIZE(&neighbor
->header
);
275 /* PCE Capabilities */
276 if (ntohs(pce
->pce_cap_flag
.header
.type
) != 0)
277 length
+= TLV_SIZE(&pce
->pce_cap_flag
.header
);
280 pce
->pce_header
.header
.type
= htons(RI_TLV_PCE
);
281 pce
->pce_header
.header
.length
= htons(length
);
284 pce
->pce_header
.header
.type
= 0;
285 pce
->pce_header
.header
.length
= 0;
286 pce
->enabled
= false;
292 static void set_pce_address(struct in_addr ipv4
, struct ospf_pce_info
*pce
)
295 /* Enable PCE Info */
296 pce
->pce_header
.header
.type
= htons(RI_TLV_PCE
);
297 /* Set PCE Address */
298 pce
->pce_address
.header
.type
= htons(RI_PCE_SUBTLV_ADDRESS
);
299 pce
->pce_address
.header
.length
= htons(PCE_ADDRESS_IPV4_SIZE
);
300 pce
->pce_address
.address
.type
= htons(PCE_ADDRESS_IPV4
);
301 pce
->pce_address
.address
.value
= ipv4
;
306 static void set_pce_path_scope(uint32_t scope
, struct ospf_pce_info
*pce
)
310 pce
->pce_scope
.header
.type
= htons(RI_PCE_SUBTLV_PATH_SCOPE
);
311 pce
->pce_scope
.header
.length
= htons(RI_TLV_LENGTH
);
312 pce
->pce_scope
.value
= htonl(scope
);
317 static void set_pce_domain(uint16_t type
, uint32_t domain
,
318 struct ospf_pce_info
*pce
)
321 struct ri_pce_subtlv_domain
*new;
323 /* Create new domain info */
324 new = XCALLOC(MTYPE_OSPF_PCE_PARAMS
,
325 sizeof(struct ri_pce_subtlv_domain
));
327 new->header
.type
= htons(RI_PCE_SUBTLV_DOMAIN
);
328 new->header
.length
= htons(PCE_ADDRESS_IPV4_SIZE
);
329 new->type
= htons(type
);
330 new->value
= htonl(domain
);
332 /* Add new domain to the list */
333 listnode_add(pce
->pce_domain
, new);
338 static void unset_pce_domain(uint16_t type
, uint32_t domain
,
339 struct ospf_pce_info
*pce
)
341 struct listnode
*node
;
342 struct ri_pce_subtlv_domain
*old
= NULL
;
345 /* Search the corresponding node */
346 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, old
)) {
347 if ((old
->type
== htons(type
))
348 && (old
->value
== htonl(domain
))) {
354 /* if found remove it */
356 listnode_delete(pce
->pce_domain
, old
);
358 /* Finally free the old domain */
359 XFREE(MTYPE_OSPF_PCE_PARAMS
, old
);
363 static void set_pce_neighbor(uint16_t type
, uint32_t domain
,
364 struct ospf_pce_info
*pce
)
367 struct ri_pce_subtlv_neighbor
*new;
369 /* Create new neighbor info */
370 new = XCALLOC(MTYPE_OSPF_PCE_PARAMS
,
371 sizeof(struct ri_pce_subtlv_neighbor
));
373 new->header
.type
= htons(RI_PCE_SUBTLV_NEIGHBOR
);
374 new->header
.length
= htons(PCE_ADDRESS_IPV4_SIZE
);
375 new->type
= htons(type
);
376 new->value
= htonl(domain
);
378 /* Add new domain to the list */
379 listnode_add(pce
->pce_neighbor
, new);
384 static void unset_pce_neighbor(uint16_t type
, uint32_t domain
,
385 struct ospf_pce_info
*pce
)
387 struct listnode
*node
;
388 struct ri_pce_subtlv_neighbor
*old
= NULL
;
391 /* Search the corresponding node */
392 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, old
)) {
393 if ((old
->type
== htons(type
))
394 && (old
->value
== htonl(domain
))) {
400 /* if found remove it */
402 listnode_delete(pce
->pce_neighbor
, old
);
404 /* Finally free the old domain */
405 XFREE(MTYPE_OSPF_PCE_PARAMS
, old
);
409 static void set_pce_cap_flag(uint32_t cap
, struct ospf_pce_info
*pce
)
412 /* Set PCE Capabilities flag */
413 pce
->pce_cap_flag
.header
.type
= htons(RI_PCE_SUBTLV_CAP_FLAG
);
414 pce
->pce_cap_flag
.header
.length
= htons(RI_TLV_LENGTH
);
415 pce
->pce_cap_flag
.value
= htonl(cap
);
420 /* Segment Routing TLV setter */
422 /* Algorithm SubTLV - section 3.1 */
423 static void set_sr_algorithm(uint8_t algo
)
426 OspfRI
.sr_info
.algo
.value
[0] = algo
;
427 for (int i
= 1; i
< ALGORITHM_COUNT
; i
++)
428 OspfRI
.sr_info
.algo
.value
[i
] = SR_ALGORITHM_UNSET
;
430 /* Set TLV type and length == only 1 Algorithm */
431 TLV_TYPE(OspfRI
.sr_info
.algo
) = htons(RI_SR_TLV_SR_ALGORITHM
);
432 TLV_LEN(OspfRI
.sr_info
.algo
) = htons(sizeof(uint8_t));
435 /* unset Aglogithm SubTLV */
436 static void unset_sr_algorithm(uint8_t algo
)
439 for (int i
= 0; i
< ALGORITHM_COUNT
; i
++)
440 OspfRI
.sr_info
.algo
.value
[i
] = SR_ALGORITHM_UNSET
;
442 /* Unset TLV type and length */
443 TLV_TYPE(OspfRI
.sr_info
.algo
) = htons(0);
444 TLV_LEN(OspfRI
.sr_info
.algo
) = htons(0);
447 /* Set Segment Routing Global Block SubTLV - section 3.2 */
448 static void set_sr_global_label_range(struct sr_block srgb
)
451 TLV_TYPE(OspfRI
.sr_info
.srgb
) = htons(RI_SR_TLV_SRGB_LABEL_RANGE
);
452 TLV_LEN(OspfRI
.sr_info
.srgb
) = htons(RI_SR_TLV_LABEL_RANGE_SIZE
);
454 OspfRI
.sr_info
.srgb
.size
= htonl(SET_RANGE_SIZE(srgb
.range_size
));
455 /* Set Lower bound label SubTLV */
456 TLV_TYPE(OspfRI
.sr_info
.srgb
.lower
) = htons(SUBTLV_SID_LABEL
);
457 TLV_LEN(OspfRI
.sr_info
.srgb
.lower
) = htons(SID_RANGE_LABEL_LENGTH
);
458 OspfRI
.sr_info
.srgb
.lower
.value
= htonl(SET_LABEL(srgb
.lower_bound
));
461 /* Unset Segment Routing Global Block SubTLV */
462 static void unset_sr_global_label_range(void)
464 TLV_TYPE(OspfRI
.sr_info
.srgb
) = htons(0);
465 TLV_LEN(OspfRI
.sr_info
.srgb
) = htons(0);
466 TLV_TYPE(OspfRI
.sr_info
.srgb
.lower
) = htons(0);
467 TLV_LEN(OspfRI
.sr_info
.srgb
.lower
) = htons(0);
470 /* Set Segment Routing Local Block SubTLV - section 3.2 */
471 static void set_sr_local_label_range(struct sr_block srlb
)
474 TLV_TYPE(OspfRI
.sr_info
.srlb
) = htons(RI_SR_TLV_SRLB_LABEL_RANGE
);
475 TLV_LEN(OspfRI
.sr_info
.srlb
) = htons(RI_SR_TLV_LABEL_RANGE_SIZE
);
477 OspfRI
.sr_info
.srlb
.size
= htonl(SET_RANGE_SIZE(srlb
.range_size
));
478 /* Set Lower bound label SubTLV */
479 TLV_TYPE(OspfRI
.sr_info
.srlb
.lower
) = htons(SUBTLV_SID_LABEL
);
480 TLV_LEN(OspfRI
.sr_info
.srlb
.lower
) = htons(SID_RANGE_LABEL_LENGTH
);
481 OspfRI
.sr_info
.srlb
.lower
.value
= htonl(SET_LABEL(srlb
.lower_bound
));
484 /* Unset Segment Routing Local Block SubTLV */
485 static void unset_sr_local_label_range(void)
487 TLV_TYPE(OspfRI
.sr_info
.srlb
) = htons(0);
488 TLV_LEN(OspfRI
.sr_info
.srlb
) = htons(0);
489 TLV_TYPE(OspfRI
.sr_info
.srlb
.lower
) = htons(0);
490 TLV_LEN(OspfRI
.sr_info
.srlb
.lower
) = htons(0);
493 /* Set Maximum Stack Depth for this router */
494 static void set_sr_node_msd(uint8_t msd
)
496 TLV_TYPE(OspfRI
.sr_info
.msd
) = htons(RI_SR_TLV_NODE_MSD
);
497 TLV_LEN(OspfRI
.sr_info
.msd
) = htons(sizeof(uint32_t));
498 OspfRI
.sr_info
.msd
.value
= msd
;
501 /* Unset this router MSD */
502 static void unset_sr_node_msd(void)
504 TLV_TYPE(OspfRI
.sr_info
.msd
) = htons(0);
505 TLV_LEN(OspfRI
.sr_info
.msd
) = htons(0);
508 static void unset_param(void *tlv_buffer
)
510 struct tlv_header
*tlv
= (struct tlv_header
*)tlv_buffer
;
513 /* Fill the Value to 0 */
514 memset(TLV_DATA(tlv_buffer
), 0, TLV_BODY_SIZE(tlv
));
520 static void initialize_params(struct ospf_router_info
*ori
)
524 struct listnode
*node
, *nnode
;
525 struct ospf_area
*area
;
526 struct ospf_ri_area_info
*new;
529 * Initialize default Router Information Capabilities.
533 set_router_info_capabilities(&ori
->router_cap
, cap
);
535 /* If Area address is not null and exist, retrieve corresponding
537 top
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
538 zlog_info("RI (%s): Initialize Router Info for %s scope", __func__
,
539 OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
? "Area" : "AS");
541 /* Try to get available Area's context from ospf at this step.
542 * Do it latter if not available */
543 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) {
544 if (!list_isempty(OspfRI
.area_info
))
545 list_delete_all_node(OspfRI
.area_info
);
546 for (ALL_LIST_ELEMENTS(top
->areas
, node
, nnode
, area
)) {
547 zlog_debug("RI (%s): Add area %pI4 to Router Information",
548 __func__
, &area
->area_id
);
549 new = XCALLOC(MTYPE_OSPF_ROUTER_INFO
,
550 sizeof(struct ospf_ri_area_info
));
552 new->flags
= RIFLG_LSA_INACTIVE
;
553 listnode_add(OspfRI
.area_info
, new);
558 * Initialize default PCE Information values
560 /* PCE address == OSPF Router ID */
561 set_pce_address(top
->router_id
, &ori
->pce_info
);
564 cap
= 7; /* Set L, R and Rd bits to one = intra & inter-area path
566 set_pce_path_scope(cap
, &ori
->pce_info
);
568 /* PCE Capabilities */
569 cap
= PCE_CAP_BIDIRECTIONAL
| PCE_CAP_DIVERSE_PATH
| PCE_CAP_OBJECTIVES
570 | PCE_CAP_ADDITIVE
| PCE_CAP_MULTIPLE_REQ
;
571 set_pce_cap_flag(cap
, &ori
->pce_info
);
576 static int is_mandated_params_set(struct ospf_router_info
*ori
)
583 if (ntohs(ori
->router_cap
.header
.type
) == 0)
586 if ((ntohs(ori
->pce_info
.pce_header
.header
.type
) == RI_TLV_PCE
)
587 && (ntohs(ori
->pce_info
.pce_address
.header
.type
) == 0)
588 && (ntohs(ori
->pce_info
.pce_cap_flag
.header
.type
) == 0))
591 if ((ori
->sr_info
.enabled
) && (ntohs(TLV_TYPE(ori
->sr_info
.algo
)) == 0)
592 && (ntohs(TLV_TYPE(ori
->sr_info
.srgb
)) == 0))
601 * Used by Segment Routing to set new TLVs and Sub-TLVs values
603 * @param enable To activate or not Segment Routing router Information flooding
604 * @param srn Self Segment Routing node
608 void ospf_router_info_update_sr(bool enable
, struct sr_node
*srn
)
610 struct listnode
*node
, *nnode
;
611 struct ospf_ri_area_info
*ai
;
613 /* First, check if Router Information is registered or not */
614 if (!OspfRI
.registered
)
615 ospf_router_info_register(OSPF_OPAQUE_AREA_LSA
);
617 /* Verify that scope is AREA */
618 if (OspfRI
.scope
!= OSPF_OPAQUE_AREA_LSA
) {
620 "RI (%s): Router Info is %s flooding: Change scope to Area flooding for Segment Routing",
622 OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
? "Area" : "AS");
626 /* Then, activate and initialize Router Information if necessary */
627 if (!OspfRI
.enabled
) {
628 OspfRI
.enabled
= true;
629 initialize_params(&OspfRI
);
632 /* Check that SR node is valid */
636 if (IS_DEBUG_OSPF_SR
)
637 zlog_debug("RI (%s): %s Routing Information for Segment Routing",
638 __func__
, enable
? "Enable" : "Disable");
640 /* Unset or Set SR parameters */
642 unset_sr_algorithm(SR_ALGORITHM_SPF
);
643 unset_sr_global_label_range();
644 unset_sr_local_label_range();
646 OspfRI
.sr_info
.enabled
= false;
648 // Only SR_ALGORITHM_SPF is supported
649 set_sr_algorithm(SR_ALGORITHM_SPF
);
650 set_sr_global_label_range(srn
->srgb
);
651 set_sr_local_label_range(srn
->srlb
);
653 set_sr_node_msd(srn
->msd
);
656 OspfRI
.sr_info
.enabled
= true;
659 /* Refresh if already engaged or originate RI LSA */
660 for (ALL_LIST_ELEMENTS(OspfRI
.area_info
, node
, nnode
, ai
)) {
661 if (CHECK_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
))
662 ospf_router_info_lsa_schedule(ai
, REFRESH_THIS_LSA
);
664 ospf_router_info_lsa_schedule(ai
,
665 REORIGINATE_THIS_LSA
);
670 /*------------------------------------------------------------------------*
671 * Following are callback functions against generic Opaque-LSAs handling.
672 *------------------------------------------------------------------------*/
673 static void ospf_router_info_ism_change(struct ospf_interface
*oi
,
677 struct ospf_ri_area_info
*ai
;
679 /* Collect area information */
680 ai
= lookup_by_area(oi
->area
);
682 /* Check if area is not yet registered */
686 /* Add this new area to the list */
687 ai
= XCALLOC(MTYPE_OSPF_ROUTER_INFO
, sizeof(struct ospf_ri_area_info
));
689 ai
->flags
= RIFLG_LSA_INACTIVE
;
690 listnode_add(OspfRI
.area_info
, ai
);
695 /*------------------------------------------------------------------------*
696 * Following are OSPF protocol processing functions for ROUTER INFORMATION
697 *------------------------------------------------------------------------*/
699 static void build_tlv_header(struct stream
*s
, struct tlv_header
*tlvh
)
702 stream_put(s
, tlvh
, sizeof(struct tlv_header
));
706 static void build_tlv(struct stream
*s
, struct tlv_header
*tlvh
)
709 if (ntohs(tlvh
->type
) != 0) {
710 build_tlv_header(s
, tlvh
);
711 stream_put(s
, TLV_DATA(tlvh
), TLV_BODY_SIZE(tlvh
));
716 static void ospf_router_info_lsa_body_set(struct stream
*s
)
719 struct listnode
*node
;
720 struct ri_pce_subtlv_domain
*domain
;
721 struct ri_pce_subtlv_neighbor
*neighbor
;
723 /* Build Router Information TLV */
724 build_tlv(s
, &OspfRI
.router_cap
.header
);
726 /* Build Segment Routing TLVs if enabled */
727 if (OspfRI
.sr_info
.enabled
) {
728 /* Build Algorithm TLV */
729 build_tlv(s
, &TLV_HDR(OspfRI
.sr_info
.algo
));
731 build_tlv(s
, &TLV_HDR(OspfRI
.sr_info
.srgb
));
733 build_tlv(s
, &TLV_HDR(OspfRI
.sr_info
.srlb
));
735 build_tlv(s
, &TLV_HDR(OspfRI
.sr_info
.msd
));
738 /* Add RI PCE TLV if it is set */
739 if (OspfRI
.pce_info
.enabled
) {
741 /* Compute PCE Info header first */
742 set_pce_header(&OspfRI
.pce_info
);
745 build_tlv_header(s
, &OspfRI
.pce_info
.pce_header
.header
);
747 /* Build PCE address sub-tlv */
748 build_tlv(s
, &OspfRI
.pce_info
.pce_address
.header
);
750 /* Build PCE path scope sub-tlv */
751 build_tlv(s
, &OspfRI
.pce_info
.pce_scope
.header
);
753 /* Build PCE domain sub-tlv */
754 for (ALL_LIST_ELEMENTS_RO(OspfRI
.pce_info
.pce_domain
, node
,
756 build_tlv(s
, &domain
->header
);
758 /* Build PCE neighbor sub-tlv */
759 for (ALL_LIST_ELEMENTS_RO(OspfRI
.pce_info
.pce_neighbor
, node
,
761 build_tlv(s
, &neighbor
->header
);
763 /* Build PCE cap flag sub-tlv */
764 build_tlv(s
, &OspfRI
.pce_info
.pce_cap_flag
.header
);
770 /* Create new opaque-LSA. */
771 static struct ospf_lsa
*ospf_router_info_lsa_new(struct ospf_area
*area
)
775 struct lsa_header
*lsah
;
776 struct ospf_lsa
*new = NULL
;
777 uint8_t options
, lsa_type
;
778 struct in_addr lsa_id
;
782 /* Create a stream for LSA. */
783 s
= stream_new(OSPF_MAX_LSA_SIZE
);
785 lsah
= (struct lsa_header
*)STREAM_DATA(s
);
787 options
= OSPF_OPTION_E
; /* Enable AS external as we flood RI with
789 options
|= OSPF_OPTION_O
; /* Don't forget this :-) */
791 lsa_type
= OspfRI
.scope
;
792 /* LSA ID == 0 for Router Information see RFC 4970 */
793 tmp
= SET_OPAQUE_LSID(OPAQUE_TYPE_ROUTER_INFORMATION_LSA
, 0);
794 lsa_id
.s_addr
= htonl(tmp
);
796 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
))
798 "LSA[Type%d:%pI4]: Create an Opaque-LSA/ROUTER INFORMATION instance",
801 top
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
803 /* Set opaque-LSA header fields. */
804 lsa_header_set(s
, options
, lsa_type
, lsa_id
, top
->router_id
);
806 /* Set opaque-LSA body fields. */
807 ospf_router_info_lsa_body_set(s
);
810 length
= stream_get_endp(s
);
811 lsah
->length
= htons(length
);
813 /* Now, create an OSPF LSA instance. */
814 new = ospf_lsa_new_and_data(length
);
818 if (new->area
&& new->area
->ospf
)
819 new->vrf_id
= new->area
->ospf
->vrf_id
;
821 new->vrf_id
= VRF_DEFAULT
;
823 SET_FLAG(new->flags
, OSPF_LSA_SELF
);
824 memcpy(new->data
, lsah
, length
);
830 static int ospf_router_info_lsa_originate_as(void *arg
)
832 struct ospf_lsa
*new;
835 vrf_id_t vrf_id
= VRF_DEFAULT
;
838 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) {
840 EC_OSPF_LSA_INSTALL_FAILURE
,
841 "RI (%s): wrong flooding scope AREA instead of AS ?",
846 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
847 new = ospf_router_info_lsa_new(NULL
);
848 new->vrf_id
= VRF_DEFAULT
;
849 top
= (struct ospf
*)arg
;
851 /* Check ospf info */
853 zlog_debug("RI (%s): ospf instance not found for vrf id %u",
855 ospf_lsa_unlock(&new);
859 /* Install this LSA into LSDB. */
860 if (ospf_lsa_install(top
, NULL
/*oi */, new) == NULL
) {
862 EC_OSPF_LSA_INSTALL_FAILURE
,
863 "RI (%s): ospf_lsa_install() ?", __func__
);
864 ospf_lsa_unlock(&new);
868 /* Update new LSA origination count. */
869 top
->lsa_originate_count
++;
871 /* Flood new LSA through AREA or AS. */
872 SET_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
);
873 ospf_flood_through_as(top
, NULL
/*nbr */, new);
875 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
877 "LSA[Type%d:%pI4]: Originate Opaque-LSA/ROUTER INFORMATION",
878 new->data
->type
, &new->data
->id
);
879 ospf_lsa_header_dump(new->data
);
886 static int ospf_router_info_lsa_originate_area(void *arg
)
888 struct ospf_lsa
*new;
890 struct ospf_ri_area_info
*ai
= NULL
;
892 vrf_id_t vrf_id
= VRF_DEFAULT
;
895 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
) {
897 EC_OSPF_LSA_INSTALL_FAILURE
,
898 "RI (%s): wrong flooding scope AS instead of AREA ?",
903 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
904 ai
= lookup_by_area((struct ospf_area
*)arg
);
907 "RI (%s): There is no context for this Router Information. Stop processing",
911 if (ai
->area
->ospf
) {
912 vrf_id
= ai
->area
->ospf
->vrf_id
;
913 top
= ai
->area
->ospf
;
915 top
= ospf_lookup_by_vrf_id(vrf_id
);
917 new = ospf_router_info_lsa_new(ai
->area
);
918 new->vrf_id
= vrf_id
;
920 /* Check ospf info */
922 zlog_debug("RI (%s): ospf instance not found for vrf id %u",
924 ospf_lsa_unlock(&new);
928 /* Install this LSA into LSDB. */
929 if (ospf_lsa_install(top
, NULL
/*oi */, new) == NULL
) {
931 EC_OSPF_LSA_INSTALL_FAILURE
,
932 "RI (%s): ospf_lsa_install() ?", __func__
);
933 ospf_lsa_unlock(&new);
937 /* Update new LSA origination count. */
938 top
->lsa_originate_count
++;
940 /* Flood new LSA through AREA or AS. */
941 SET_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
);
942 ospf_flood_through_area(ai
->area
, NULL
/*nbr */, new);
944 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
946 "LSA[Type%d:%pI4]: Originate Opaque-LSA/ROUTER INFORMATION",
947 new->data
->type
, &new->data
->id
);
948 ospf_lsa_header_dump(new->data
);
955 static int ospf_router_info_lsa_originate(void *arg
)
958 struct ospf_ri_area_info
*ai
;
961 if (!OspfRI
.enabled
) {
962 zlog_info("RI (%s): ROUTER INFORMATION is disabled now.",
964 rc
= 0; /* This is not an error case. */
968 /* Check if Router Information LSA is already engaged */
969 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
) {
970 if ((CHECK_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
))
971 && (CHECK_FLAG(OspfRI
.as_flags
,
972 RIFLG_LSA_FORCED_REFRESH
))) {
973 UNSET_FLAG(OspfRI
.as_flags
, RIFLG_LSA_FORCED_REFRESH
);
974 ospf_router_info_lsa_schedule(NULL
, REFRESH_THIS_LSA
);
979 ai
= lookup_by_area((struct ospf_area
*)arg
);
983 "RI (%s): Missing area information", __func__
);
986 if ((CHECK_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
))
987 && (CHECK_FLAG(ai
->flags
, RIFLG_LSA_FORCED_REFRESH
))) {
988 UNSET_FLAG(ai
->flags
, RIFLG_LSA_FORCED_REFRESH
);
989 ospf_router_info_lsa_schedule(ai
, REFRESH_THIS_LSA
);
995 /* Router Information is not yet Engaged, check parameters */
996 if (!is_mandated_params_set(&OspfRI
))
999 "RI (%s): lacks mandated ROUTER INFORMATION parameters",
1002 /* Ok, let's try to originate an LSA */
1003 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
)
1004 rc
= ospf_router_info_lsa_originate_as(arg
);
1006 rc
= ospf_router_info_lsa_originate_area(arg
);
1011 static struct ospf_lsa
*ospf_router_info_lsa_refresh(struct ospf_lsa
*lsa
)
1013 struct ospf_ri_area_info
*ai
= NULL
;
1014 struct ospf_lsa
*new = NULL
;
1017 if (!OspfRI
.enabled
) {
1019 * This LSA must have flushed before due to ROUTER INFORMATION
1021 * It seems a slip among routers in the routing domain.
1023 zlog_info("RI (%s): ROUTER INFORMATION is disabled now.",
1026 htons(OSPF_LSA_MAXAGE
); /* Flush it anyway. */
1029 /* Verify that the Router Information ID is supported */
1030 if (GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)) != 0) {
1033 "RI (%s): Unsupported Router Information ID",
1038 /* Process LSA depending of the flooding scope */
1039 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) {
1040 /* Get context AREA context */
1041 ai
= lookup_by_area(lsa
->area
);
1045 "RI (%s): No associated Area", __func__
);
1048 /* Flush LSA, if the lsa's age reached to MaxAge. */
1049 if (IS_LSA_MAXAGE(lsa
)) {
1050 UNSET_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
);
1051 ospf_opaque_lsa_flush_schedule(lsa
);
1054 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
1055 new = ospf_router_info_lsa_new(ai
->area
);
1056 new->data
->ls_seqnum
= lsa_seqnum_increment(lsa
);
1057 new->vrf_id
= lsa
->vrf_id
;
1058 /* Install this LSA into LSDB. */
1059 /* Given "lsa" will be freed in the next function. */
1060 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
1061 if (ospf_lsa_install(top
, NULL
/*oi */, new) == NULL
) {
1062 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE
,
1063 "RI (%s): ospf_lsa_install() ?", __func__
);
1064 ospf_lsa_unlock(&new);
1067 /* Flood updated LSA through AREA */
1068 ospf_flood_through_area(ai
->area
, NULL
/*nbr */, new);
1070 } else { /* AS Flooding scope */
1071 /* Flush LSA, if the lsa's age reached to MaxAge. */
1072 if (IS_LSA_MAXAGE(lsa
)) {
1073 UNSET_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
);
1074 ospf_opaque_lsa_flush_schedule(lsa
);
1077 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
1078 new = ospf_router_info_lsa_new(NULL
);
1079 new->data
->ls_seqnum
= lsa_seqnum_increment(lsa
);
1080 new->vrf_id
= lsa
->vrf_id
;
1081 /* Install this LSA into LSDB. */
1082 /* Given "lsa" will be freed in the next function. */
1083 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
1084 if (ospf_lsa_install(top
, NULL
/*oi */, new) == NULL
) {
1085 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE
,
1086 "RI (%s): ospf_lsa_install() ?", __func__
);
1087 ospf_lsa_unlock(&new);
1090 /* Flood updated LSA through AS */
1091 ospf_flood_through_as(top
, NULL
/*nbr */, new);
1094 /* Debug logging. */
1095 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
1097 "LSA[Type%d:%pI4]: Refresh Opaque-LSA/ROUTER INFORMATION",
1098 new->data
->type
, &new->data
->id
);
1099 ospf_lsa_header_dump(new->data
);
1105 static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info
*ai
,
1106 enum lsa_opcode opcode
)
1108 struct ospf_lsa lsa
;
1109 struct lsa_header lsah
;
1113 memset(&lsa
, 0, sizeof(lsa
));
1114 memset(&lsah
, 0, sizeof(lsah
));
1116 zlog_debug("RI (%s): LSA schedule %s%s%s", __func__
,
1117 opcode
== REORIGINATE_THIS_LSA
? "Re-Originate" : "",
1118 opcode
== REFRESH_THIS_LSA
? "Refresh" : "",
1119 opcode
== FLUSH_THIS_LSA
? "Flush" : "");
1121 /* Check LSA flags state coherence and collect area information */
1122 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) {
1123 if ((ai
== NULL
) || (ai
->area
== NULL
)) {
1126 "RI (%s): Router Info is Area scope flooding but area is not set",
1131 if (!CHECK_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
)
1132 && (opcode
!= REORIGINATE_THIS_LSA
))
1135 if (CHECK_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
)
1136 && (opcode
== REORIGINATE_THIS_LSA
))
1137 opcode
= REFRESH_THIS_LSA
;
1139 lsa
.area
= ai
->area
;
1140 top
= ai
->area
->ospf
;
1142 if (!CHECK_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
)
1143 && (opcode
!= REORIGINATE_THIS_LSA
))
1146 if (CHECK_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
)
1147 && (opcode
== REORIGINATE_THIS_LSA
))
1148 opcode
= REFRESH_THIS_LSA
;
1150 top
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1155 lsah
.type
= OspfRI
.scope
;
1157 /* LSA ID is set to 0 for the Router Information. See RFC 4970 */
1158 tmp
= SET_OPAQUE_LSID(OPAQUE_TYPE_ROUTER_INFORMATION_LSA
, 0);
1159 lsah
.id
.s_addr
= htonl(tmp
);
1162 case REORIGINATE_THIS_LSA
:
1163 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
)
1164 ospf_opaque_lsa_reoriginate_schedule(
1165 (void *)ai
->area
, OSPF_OPAQUE_AREA_LSA
,
1166 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
1168 ospf_opaque_lsa_reoriginate_schedule(
1169 (void *)top
, OSPF_OPAQUE_AS_LSA
,
1170 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
1172 case REFRESH_THIS_LSA
:
1173 ospf_opaque_lsa_refresh_schedule(&lsa
);
1175 case FLUSH_THIS_LSA
:
1176 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
)
1177 UNSET_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
);
1179 UNSET_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
);
1180 ospf_opaque_lsa_flush_schedule(&lsa
);
1187 /* Callback to handle Segment Routing information */
1188 static int ospf_router_info_lsa_update(struct ospf_lsa
*lsa
)
1193 flog_warn(EC_OSPF_LSA
, "RI (%s): Abort! LSA is NULL",
1198 /* Process only Opaque LSA */
1199 if ((lsa
->data
->type
!= OSPF_OPAQUE_AREA_LSA
)
1200 && (lsa
->data
->type
!= OSPF_OPAQUE_AS_LSA
))
1203 /* Process only Router Information LSA */
1204 if (GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
))
1205 != OPAQUE_TYPE_ROUTER_INFORMATION_LSA
)
1208 /* Check if it is not my LSA */
1209 if (IS_LSA_SELF(lsa
))
1212 /* Check if Router Info & Segment Routing are enable */
1213 if (!OspfRI
.enabled
|| !OspfRI
.sr_info
.enabled
)
1216 /* Call Segment Routing LSA update or deletion */
1217 if (!IS_LSA_MAXAGE(lsa
))
1218 ospf_sr_ri_lsa_update(lsa
);
1220 ospf_sr_ri_lsa_delete(lsa
);
1225 /*------------------------------------------------------------------------*
1226 * Following are vty session control functions.
1227 *------------------------------------------------------------------------*/
1229 #define check_tlv_size(size, msg) \
1231 if (ntohs(tlvh->length) > size) { \
1233 vty_out(vty, " Wrong %s TLV size: %d(%d)\n", \
1234 msg, ntohs(tlvh->length), size); \
1236 zlog_debug(" Wrong %s TLV size: %d(%d)", \
1237 msg, ntohs(tlvh->length), size); \
1238 return size + TLV_HDR_SIZE; \
1242 static uint16_t show_vty_router_cap(struct vty
*vty
, struct tlv_header
*tlvh
)
1244 struct ri_tlv_router_cap
*top
= (struct ri_tlv_router_cap
*)tlvh
;
1246 check_tlv_size(RI_TLV_CAPABILITIES_SIZE
, "Router Capabilities");
1249 vty_out(vty
, " Router Capabilities: 0x%x\n",
1252 zlog_debug(" Router Capabilities: 0x%x", ntohl(top
->value
));
1254 return TLV_SIZE(tlvh
);
1257 static uint16_t show_vty_pce_subtlv_address(struct vty
*vty
,
1258 struct tlv_header
*tlvh
)
1260 struct ri_pce_subtlv_address
*top
=
1261 (struct ri_pce_subtlv_address
*)tlvh
;
1263 if (ntohs(top
->address
.type
) == PCE_ADDRESS_IPV4
) {
1264 check_tlv_size(PCE_ADDRESS_IPV4_SIZE
, "PCE Address");
1266 vty_out(vty
, " PCE Address: %pI4\n",
1267 &top
->address
.value
);
1269 zlog_debug(" PCE Address: %pI4",
1270 &top
->address
.value
);
1271 } else if (ntohs(top
->address
.type
) == PCE_ADDRESS_IPV6
) {
1272 /* TODO: Add support to IPv6 with inet_ntop() */
1273 check_tlv_size(PCE_ADDRESS_IPV6_SIZE
, "PCE Address");
1275 vty_out(vty
, " PCE Address: 0x%x\n",
1276 ntohl(top
->address
.value
.s_addr
));
1278 zlog_debug(" PCE Address: 0x%x",
1279 ntohl(top
->address
.value
.s_addr
));
1282 vty_out(vty
, " Wrong PCE Address type: 0x%x\n",
1283 ntohl(top
->address
.type
));
1285 zlog_debug(" Wrong PCE Address type: 0x%x",
1286 ntohl(top
->address
.type
));
1289 return TLV_SIZE(tlvh
);
1292 static uint16_t show_vty_pce_subtlv_path_scope(struct vty
*vty
,
1293 struct tlv_header
*tlvh
)
1295 struct ri_pce_subtlv_path_scope
*top
=
1296 (struct ri_pce_subtlv_path_scope
*)tlvh
;
1298 check_tlv_size(RI_PCE_SUBTLV_PATH_SCOPE_SIZE
, "PCE Path Scope");
1301 vty_out(vty
, " PCE Path Scope: 0x%x\n", ntohl(top
->value
));
1303 zlog_debug(" PCE Path Scope: 0x%x", ntohl(top
->value
));
1305 return TLV_SIZE(tlvh
);
1308 static uint16_t show_vty_pce_subtlv_domain(struct vty
*vty
,
1309 struct tlv_header
*tlvh
)
1311 struct ri_pce_subtlv_domain
*top
= (struct ri_pce_subtlv_domain
*)tlvh
;
1314 check_tlv_size(RI_PCE_SUBTLV_DOMAIN_SIZE
, "PCE Domain");
1316 if (ntohs(top
->type
) == PCE_DOMAIN_TYPE_AREA
) {
1317 tmp
.s_addr
= top
->value
;
1319 vty_out(vty
, " PCE Domain Area: %pI4\n", &tmp
);
1321 zlog_debug(" PCE Domain Area: %pI4", &tmp
);
1322 } else if (ntohs(top
->type
) == PCE_DOMAIN_TYPE_AS
) {
1324 vty_out(vty
, " PCE Domain AS: %d\n",
1327 zlog_debug(" PCE Domain AS: %d", ntohl(top
->value
));
1330 vty_out(vty
, " Wrong PCE Domain type: %d\n",
1333 zlog_debug(" Wrong PCE Domain type: %d",
1337 return TLV_SIZE(tlvh
);
1340 static uint16_t show_vty_pce_subtlv_neighbor(struct vty
*vty
,
1341 struct tlv_header
*tlvh
)
1344 struct ri_pce_subtlv_neighbor
*top
=
1345 (struct ri_pce_subtlv_neighbor
*)tlvh
;
1348 check_tlv_size(RI_PCE_SUBTLV_NEIGHBOR_SIZE
, "PCE Neighbor");
1350 if (ntohs(top
->type
) == PCE_DOMAIN_TYPE_AREA
) {
1351 tmp
.s_addr
= top
->value
;
1353 vty_out(vty
, " PCE Neighbor Area: %pI4\n", &tmp
);
1355 zlog_debug(" PCE Neighbor Area: %pI4", &tmp
);
1356 } else if (ntohs(top
->type
) == PCE_DOMAIN_TYPE_AS
) {
1358 vty_out(vty
, " PCE Neighbor AS: %d\n",
1361 zlog_debug(" PCE Neighbor AS: %d",
1365 vty_out(vty
, " Wrong PCE Neighbor type: %d\n",
1368 zlog_debug(" Wrong PCE Neighbor type: %d",
1372 return TLV_SIZE(tlvh
);
1375 static uint16_t show_vty_pce_subtlv_cap_flag(struct vty
*vty
,
1376 struct tlv_header
*tlvh
)
1378 struct ri_pce_subtlv_cap_flag
*top
=
1379 (struct ri_pce_subtlv_cap_flag
*)tlvh
;
1381 check_tlv_size(RI_PCE_SUBTLV_CAP_FLAG_SIZE
, "PCE Capabilities");
1384 vty_out(vty
, " PCE Capabilities Flag: 0x%x\n",
1387 zlog_debug(" PCE Capabilities Flag: 0x%x",
1390 return TLV_SIZE(tlvh
);
1393 static uint16_t show_vty_unknown_tlv(struct vty
*vty
, struct tlv_header
*tlvh
,
1396 if (TLV_SIZE(tlvh
) > buf_size
) {
1399 " TLV size %d exceeds buffer size. Abort!",
1403 " TLV size %d exceeds buffer size. Abort!",
1409 vty_out(vty
, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
1410 ntohs(tlvh
->type
), ntohs(tlvh
->length
));
1412 zlog_debug(" Unknown TLV: [type(0x%x), length(0x%x)]",
1413 ntohs(tlvh
->type
), ntohs(tlvh
->length
));
1415 return TLV_SIZE(tlvh
);
1418 static uint16_t show_vty_pce_info(struct vty
*vty
, struct tlv_header
*ri
,
1421 struct tlv_header
*tlvh
;
1422 uint16_t length
= ntohs(ri
->length
);
1425 /* Verify that TLV length is valid against remaining buffer size */
1426 if (length
> buf_size
) {
1428 " PCE Info TLV size %d exceeds buffer size. Abort!\n",
1433 for (tlvh
= ri
; sum
< length
; tlvh
= TLV_HDR_NEXT(tlvh
)) {
1434 switch (ntohs(tlvh
->type
)) {
1435 case RI_PCE_SUBTLV_ADDRESS
:
1436 sum
+= show_vty_pce_subtlv_address(vty
, tlvh
);
1438 case RI_PCE_SUBTLV_PATH_SCOPE
:
1439 sum
+= show_vty_pce_subtlv_path_scope(vty
, tlvh
);
1441 case RI_PCE_SUBTLV_DOMAIN
:
1442 sum
+= show_vty_pce_subtlv_domain(vty
, tlvh
);
1444 case RI_PCE_SUBTLV_NEIGHBOR
:
1445 sum
+= show_vty_pce_subtlv_neighbor(vty
, tlvh
);
1447 case RI_PCE_SUBTLV_CAP_FLAG
:
1448 sum
+= show_vty_pce_subtlv_cap_flag(vty
, tlvh
);
1451 sum
+= show_vty_unknown_tlv(vty
, tlvh
, length
- sum
);
1458 /* Display Segment Routing Algorithm TLV information */
1459 static uint16_t show_vty_sr_algorithm(struct vty
*vty
, struct tlv_header
*tlvh
)
1461 struct ri_sr_tlv_sr_algorithm
*algo
=
1462 (struct ri_sr_tlv_sr_algorithm
*)tlvh
;
1465 check_tlv_size(ALGORITHM_COUNT
, "Segment Routing Algorithm");
1468 vty_out(vty
, " Segment Routing Algorithm TLV:\n");
1469 for (i
= 0; i
< ntohs(algo
->header
.length
); i
++) {
1470 switch (algo
->value
[i
]) {
1472 vty_out(vty
, " Algorithm %d: SPF\n", i
);
1475 vty_out(vty
, " Algorithm %d: Strict SPF\n",
1480 " Algorithm %d: Unknown value %d\n", i
,
1486 zlog_debug(" Segment Routing Algorithm TLV:");
1487 for (i
= 0; i
< ntohs(algo
->header
.length
); i
++)
1488 switch (algo
->value
[i
]) {
1490 zlog_debug(" Algorithm %d: SPF", i
);
1493 zlog_debug(" Algorithm %d: Strict SPF", i
);
1496 zlog_debug(" Algorithm %d: Unknown value %d",
1502 return TLV_SIZE(tlvh
);
1505 /* Display Segment Routing SID/Label Range TLV information */
1506 static uint16_t show_vty_sr_range(struct vty
*vty
, struct tlv_header
*tlvh
)
1508 struct ri_sr_tlv_sid_label_range
*range
=
1509 (struct ri_sr_tlv_sid_label_range
*)tlvh
;
1511 check_tlv_size(RI_SR_TLV_LABEL_RANGE_SIZE
, "SR Label Range");
1515 " Segment Routing %s Range TLV:\n"
1516 " Range Size = %d\n"
1517 " SID Label = %d\n\n",
1518 ntohs(range
->header
.type
) == RI_SR_TLV_SRGB_LABEL_RANGE
1521 GET_RANGE_SIZE(ntohl(range
->size
)),
1522 GET_LABEL(ntohl(range
->lower
.value
)));
1525 " Segment Routing %s Range TLV: Range Size = %d SID Label = %d",
1526 ntohs(range
->header
.type
) == RI_SR_TLV_SRGB_LABEL_RANGE
1529 GET_RANGE_SIZE(ntohl(range
->size
)),
1530 GET_LABEL(ntohl(range
->lower
.value
)));
1533 return TLV_SIZE(tlvh
);
1536 /* Display Segment Routing Maximum Stack Depth TLV information */
1537 static uint16_t show_vty_sr_msd(struct vty
*vty
, struct tlv_header
*tlvh
)
1539 struct ri_sr_tlv_node_msd
*msd
= (struct ri_sr_tlv_node_msd
*)tlvh
;
1541 check_tlv_size(RI_SR_TLV_NODE_MSD_SIZE
, "Node Maximum Stack Depth");
1545 " Segment Routing MSD TLV:\n"
1546 " Node Maximum Stack Depth = %d\n",
1550 " Segment Routing MSD TLV: Node Maximum Stack Depth = %d",
1554 return TLV_SIZE(tlvh
);
1557 static void ospf_router_info_show_info(struct vty
*vty
,
1558 struct json_object
*json
,
1559 struct ospf_lsa
*lsa
)
1561 struct lsa_header
*lsah
= lsa
->data
;
1562 struct tlv_header
*tlvh
;
1563 uint16_t length
= 0, sum
= 0;
1568 /* Initialize TLV browsing */
1569 length
= lsa
->size
- OSPF_LSA_HEADER_SIZE
;
1571 for (tlvh
= TLV_HDR_TOP(lsah
); sum
< length
&& tlvh
;
1572 tlvh
= TLV_HDR_NEXT(tlvh
)) {
1573 switch (ntohs(tlvh
->type
)) {
1574 case RI_TLV_CAPABILITIES
:
1575 sum
+= show_vty_router_cap(vty
, tlvh
);
1579 sum
+= TLV_HDR_SIZE
;
1580 sum
+= show_vty_pce_info(vty
, tlvh
, length
- sum
);
1582 case RI_SR_TLV_SR_ALGORITHM
:
1583 sum
+= show_vty_sr_algorithm(vty
, tlvh
);
1585 case RI_SR_TLV_SRGB_LABEL_RANGE
:
1586 case RI_SR_TLV_SRLB_LABEL_RANGE
:
1587 sum
+= show_vty_sr_range(vty
, tlvh
);
1589 case RI_SR_TLV_NODE_MSD
:
1590 sum
+= show_vty_sr_msd(vty
, tlvh
);
1594 sum
+= show_vty_unknown_tlv(vty
, tlvh
, length
);
1602 static void ospf_router_info_config_write_router(struct vty
*vty
)
1604 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1605 struct listnode
*node
;
1606 struct ri_pce_subtlv_domain
*domain
;
1607 struct ri_pce_subtlv_neighbor
*neighbor
;
1610 if (!OspfRI
.enabled
)
1613 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
)
1614 vty_out(vty
, " router-info as\n");
1616 vty_out(vty
, " router-info area\n");
1618 if (OspfRI
.pce_info
.enabled
) {
1620 if (pce
->pce_address
.header
.type
!= 0)
1621 vty_out(vty
, " pce address %pI4\n",
1622 &pce
->pce_address
.address
.value
);
1624 if (pce
->pce_cap_flag
.header
.type
!= 0)
1625 vty_out(vty
, " pce flag 0x%x\n",
1626 ntohl(pce
->pce_cap_flag
.value
));
1628 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
1629 if (domain
->header
.type
!= 0) {
1630 if (domain
->type
== PCE_DOMAIN_TYPE_AREA
) {
1631 tmp
.s_addr
= domain
->value
;
1632 vty_out(vty
, " pce domain area %pI4\n",
1635 vty_out(vty
, " pce domain as %d\n",
1636 ntohl(domain
->value
));
1641 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
1642 if (neighbor
->header
.type
!= 0) {
1643 if (neighbor
->type
== PCE_DOMAIN_TYPE_AREA
) {
1644 tmp
.s_addr
= neighbor
->value
;
1646 " pce neighbor area %pI4\n",
1649 vty_out(vty
, " pce neighbor as %d\n",
1650 ntohl(neighbor
->value
));
1655 if (pce
->pce_scope
.header
.type
!= 0)
1656 vty_out(vty
, " pce scope 0x%x\n",
1657 ntohl(OspfRI
.pce_info
.pce_scope
.value
));
1662 /*------------------------------------------------------------------------*
1663 * Following are vty command functions.
1664 *------------------------------------------------------------------------*/
1665 /* Simple wrapper schedule RI LSA action in function of the scope */
1666 static void ospf_router_info_schedule(enum lsa_opcode opcode
)
1668 struct listnode
*node
, *nnode
;
1669 struct ospf_ri_area_info
*ai
;
1671 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
) {
1672 if (CHECK_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
))
1673 ospf_router_info_lsa_schedule(NULL
, opcode
);
1674 else if (opcode
== REORIGINATE_THIS_LSA
)
1675 ospf_router_info_lsa_schedule(NULL
, opcode
);
1677 for (ALL_LIST_ELEMENTS(OspfRI
.area_info
, node
, nnode
, ai
)) {
1678 if (CHECK_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
))
1679 ospf_router_info_lsa_schedule(ai
, opcode
);
1685 router_info_area_cmd
,
1686 "router-info <as|area [A.B.C.D]>",
1688 "Enable the Router Information functionality with AS flooding scope\n"
1689 "Enable the Router Information functionality with Area flooding scope\n"
1690 "OSPF area ID in IP format (deprecated)\n")
1698 /* Check and get Area value if present */
1699 if (strncmp(argv
[idx_mode
]->arg
, "as", 2) == 0)
1700 scope
= OSPF_OPAQUE_AS_LSA
;
1702 scope
= OSPF_OPAQUE_AREA_LSA
;
1704 /* First start to register Router Information callbacks */
1705 if (!OspfRI
.registered
&& (ospf_router_info_register(scope
)) != 0) {
1707 "%% Unable to register Router Information callbacks.");
1710 "RI (%s): Unable to register Router Information callbacks. Abort!",
1712 return CMD_WARNING_CONFIG_FAILED
;
1715 OspfRI
.enabled
= true;
1717 if (IS_DEBUG_OSPF_EVENT
)
1718 zlog_debug("RI-> Router Information (%s flooding): OFF -> ON",
1719 OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
? "Area"
1723 * Following code is intended to handle two cases;
1725 * 1) Router Information was disabled at startup time, but now become
1727 * 2) Router Information was once enabled then disabled, and now enabled
1731 initialize_params(&OspfRI
);
1733 /* Originate or Refresh RI LSA if already engaged */
1734 ospf_router_info_schedule(REORIGINATE_THIS_LSA
);
1739 DEFUN (no_router_info
,
1743 "Disable the Router Information functionality\n")
1746 if (!OspfRI
.enabled
)
1749 if (IS_DEBUG_OSPF_EVENT
)
1750 zlog_debug("RI-> Router Information: ON -> OFF");
1752 ospf_router_info_schedule(FLUSH_THIS_LSA
);
1754 OspfRI
.enabled
= false;
1759 static int ospf_ri_enabled(struct vty
*vty
)
1765 vty_out(vty
, "%% OSPF RI is not turned on\n");
1772 "pce address A.B.C.D",
1774 "Stable IP address of the PCE\n"
1775 "PCE address in IPv4 address format\n")
1778 struct in_addr value
;
1779 struct ospf_pce_info
*pi
= &OspfRI
.pce_info
;
1781 if (!ospf_ri_enabled(vty
))
1782 return CMD_WARNING_CONFIG_FAILED
;
1784 if (!inet_aton(argv
[idx_ipv4
]->arg
, &value
)) {
1785 vty_out(vty
, "Please specify PCE Address by A.B.C.D\n");
1786 return CMD_WARNING_CONFIG_FAILED
;
1789 if (ntohs(pi
->pce_address
.header
.type
) == 0
1790 || ntohl(pi
->pce_address
.address
.value
.s_addr
)
1791 != ntohl(value
.s_addr
)) {
1793 set_pce_address(value
, pi
);
1795 /* Refresh RI LSA if already engaged */
1796 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1802 DEFUN (no_pce_address
,
1804 "no pce address [A.B.C.D]",
1807 "Disable PCE address\n"
1808 "PCE address in IPv4 address format\n")
1811 unset_param(&OspfRI
.pce_info
.pce_address
);
1813 /* Refresh RI LSA if already engaged */
1814 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1819 DEFUN (pce_path_scope
,
1821 "pce scope BITPATTERN",
1823 "Path scope visibilities of the PCE for path computation\n"
1824 "32-bit Hexadecimal value\n")
1826 int idx_bitpattern
= 2;
1828 struct ospf_pce_info
*pi
= &OspfRI
.pce_info
;
1830 if (!ospf_ri_enabled(vty
))
1831 return CMD_WARNING_CONFIG_FAILED
;
1833 if (sscanf(argv
[idx_bitpattern
]->arg
, "0x%x", &scope
) != 1) {
1834 vty_out(vty
, "pce_path_scope: fscanf: %s\n",
1835 safe_strerror(errno
));
1836 return CMD_WARNING_CONFIG_FAILED
;
1839 if (ntohl(pi
->pce_scope
.header
.type
) == 0
1840 || scope
!= pi
->pce_scope
.value
) {
1841 set_pce_path_scope(scope
, pi
);
1843 /* Refresh RI LSA if already engaged */
1844 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1850 DEFUN (no_pce_path_scope
,
1851 no_pce_path_scope_cmd
,
1852 "no pce scope [BITPATTERN]",
1855 "Disable PCE path scope\n"
1856 "32-bit Hexadecimal value\n")
1859 unset_param(&OspfRI
.pce_info
.pce_address
);
1861 /* Refresh RI LSA if already engaged */
1862 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1869 "pce domain as (0-65535)",
1871 "Configure PCE domain AS number\n"
1872 "AS number where the PCE as visibilities for path computation\n"
1873 "AS number in decimal <0-65535>\n")
1878 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1879 struct listnode
*node
;
1880 struct ri_pce_subtlv_domain
*domain
;
1882 if (!ospf_ri_enabled(vty
))
1883 return CMD_WARNING_CONFIG_FAILED
;
1885 if (sscanf(argv
[idx_number
]->arg
, "%" SCNu32
, &as
) != 1) {
1886 vty_out(vty
, "pce_domain: fscanf: %s\n", safe_strerror(errno
));
1887 return CMD_WARNING_CONFIG_FAILED
;
1890 /* Check if the domain is not already in the domain list */
1891 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
1892 if (ntohl(domain
->header
.type
) == 0 && as
== domain
->value
)
1896 /* Create new domain if not found */
1897 set_pce_domain(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1899 /* Refresh RI LSA if already engaged */
1900 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1905 DEFUN (no_pce_domain
,
1907 "no pce domain as (0-65535)",
1910 "Disable PCE domain AS number\n"
1911 "AS number where the PCE as visibilities for path computation\n"
1912 "AS number in decimal <0-65535>\n")
1917 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1919 if (sscanf(argv
[idx_number
]->arg
, "%" SCNu32
, &as
) != 1) {
1920 vty_out(vty
, "no_pce_domain: fscanf: %s\n",
1921 safe_strerror(errno
));
1922 return CMD_WARNING_CONFIG_FAILED
;
1925 /* Unset corresponding PCE domain */
1926 unset_pce_domain(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1928 /* Refresh RI LSA if already engaged */
1929 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1934 DEFUN (pce_neigbhor
,
1936 "pce neighbor as (0-65535)",
1938 "Configure PCE neighbor domain AS number\n"
1939 "AS number of PCE neighbors\n"
1940 "AS number in decimal <0-65535>\n")
1945 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1946 struct listnode
*node
;
1947 struct ri_pce_subtlv_neighbor
*neighbor
;
1949 if (!ospf_ri_enabled(vty
))
1950 return CMD_WARNING_CONFIG_FAILED
;
1952 if (sscanf(argv
[idx_number
]->arg
, "%" SCNu32
, &as
) != 1) {
1953 vty_out(vty
, "pce_neighbor: fscanf: %s\n",
1954 safe_strerror(errno
));
1955 return CMD_WARNING_CONFIG_FAILED
;
1958 /* Check if the domain is not already in the domain list */
1959 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
1960 if (ntohl(neighbor
->header
.type
) == 0 && as
== neighbor
->value
)
1964 /* Create new domain if not found */
1965 set_pce_neighbor(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1967 /* Refresh RI LSA if already engaged */
1968 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1973 DEFUN (no_pce_neighbor
,
1974 no_pce_neighbor_cmd
,
1975 "no pce neighbor as (0-65535)",
1978 "Disable PCE neighbor AS number\n"
1979 "AS number of PCE neighbor\n"
1980 "AS number in decimal <0-65535>\n")
1985 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1987 if (sscanf(argv
[idx_number
]->arg
, "%" SCNu32
, &as
) != 1) {
1988 vty_out(vty
, "no_pce_neighbor: fscanf: %s\n",
1989 safe_strerror(errno
));
1990 return CMD_WARNING_CONFIG_FAILED
;
1993 /* Unset corresponding PCE domain */
1994 unset_pce_neighbor(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1996 /* Refresh RI LSA if already engaged */
1997 ospf_router_info_schedule(REFRESH_THIS_LSA
);
2002 DEFUN (pce_cap_flag
,
2004 "pce flag BITPATTERN",
2006 "Capabilities of the PCE for path computation\n"
2007 "32-bit Hexadecimal value\n")
2009 int idx_bitpattern
= 2;
2012 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
2014 if (!ospf_ri_enabled(vty
))
2015 return CMD_WARNING_CONFIG_FAILED
;
2017 if (sscanf(argv
[idx_bitpattern
]->arg
, "0x%x", &cap
) != 1) {
2018 vty_out(vty
, "pce_cap_flag: fscanf: %s\n",
2019 safe_strerror(errno
));
2020 return CMD_WARNING_CONFIG_FAILED
;
2023 if (ntohl(pce
->pce_cap_flag
.header
.type
) == 0
2024 || cap
!= pce
->pce_cap_flag
.value
) {
2025 set_pce_cap_flag(cap
, pce
);
2027 /* Refresh RI LSA if already engaged */
2028 ospf_router_info_schedule(REFRESH_THIS_LSA
);
2034 DEFUN (no_pce_cap_flag
,
2035 no_pce_cap_flag_cmd
,
2039 "Disable PCE capabilities\n")
2042 unset_param(&OspfRI
.pce_info
.pce_cap_flag
);
2044 /* Refresh RI LSA if already engaged */
2045 ospf_router_info_schedule(REFRESH_THIS_LSA
);
2050 DEFUN (show_ip_ospf_router_info
,
2051 show_ip_ospf_router_info_cmd
,
2052 "show ip ospf router-info",
2056 "Router Information\n")
2059 if (OspfRI
.enabled
) {
2060 vty_out(vty
, "--- Router Information parameters ---\n");
2061 show_vty_router_cap(vty
, &OspfRI
.router_cap
.header
);
2065 " Router Information is disabled on this router\n");
2070 DEFUN (show_ip_opsf_router_info_pce
,
2071 show_ip_ospf_router_info_pce_cmd
,
2072 "show ip ospf router-info pce",
2076 "Router Information\n"
2077 "PCE information\n")
2080 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
2081 struct listnode
*node
;
2082 struct ri_pce_subtlv_domain
*domain
;
2083 struct ri_pce_subtlv_neighbor
*neighbor
;
2085 if ((OspfRI
.enabled
) && (OspfRI
.pce_info
.enabled
)) {
2086 vty_out(vty
, "--- PCE parameters ---\n");
2088 if (pce
->pce_address
.header
.type
!= 0)
2089 show_vty_pce_subtlv_address(vty
,
2090 &pce
->pce_address
.header
);
2092 if (pce
->pce_scope
.header
.type
!= 0)
2093 show_vty_pce_subtlv_path_scope(vty
,
2094 &pce
->pce_scope
.header
);
2096 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
2097 if (domain
->header
.type
!= 0)
2098 show_vty_pce_subtlv_domain(vty
,
2102 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
2103 if (neighbor
->header
.type
!= 0)
2104 show_vty_pce_subtlv_neighbor(vty
,
2108 if (pce
->pce_cap_flag
.header
.type
!= 0)
2109 show_vty_pce_subtlv_cap_flag(vty
,
2110 &pce
->pce_cap_flag
.header
);
2113 vty_out(vty
, " PCE info is disabled on this router\n");
2119 /* Install new CLI commands */
2120 static void ospf_router_info_register_vty(void)
2122 install_element(VIEW_NODE
, &show_ip_ospf_router_info_cmd
);
2123 install_element(VIEW_NODE
, &show_ip_ospf_router_info_pce_cmd
);
2125 install_element(OSPF_NODE
, &router_info_area_cmd
);
2126 install_element(OSPF_NODE
, &no_router_info_cmd
);
2127 install_element(OSPF_NODE
, &pce_address_cmd
);
2128 install_element(OSPF_NODE
, &no_pce_address_cmd
);
2129 install_element(OSPF_NODE
, &pce_path_scope_cmd
);
2130 install_element(OSPF_NODE
, &no_pce_path_scope_cmd
);
2131 install_element(OSPF_NODE
, &pce_domain_cmd
);
2132 install_element(OSPF_NODE
, &no_pce_domain_cmd
);
2133 install_element(OSPF_NODE
, &pce_neighbor_cmd
);
2134 install_element(OSPF_NODE
, &no_pce_neighbor_cmd
);
2135 install_element(OSPF_NODE
, &pce_cap_flag_cmd
);
2136 install_element(OSPF_NODE
, &no_pce_cap_flag_cmd
);