2 * This is an implementation of RFC4970 Router Information
3 * with support of RFC5088 PCE Capabilites announcement
5 * Module name: Router Information
6 * Author: Olivier Dugeon <olivier.dugeon@orange.com>
7 * Copyright (C) 2012 - 2017 Orange Labs http://www.orange.com/
9 * This file is part of GNU Quagga.
11 * GNU Zebra is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2, or (at your option) any
16 * GNU Quagga is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with this program; see the file COPYING; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
40 #include "sockunion.h" /* for inet_aton() */
43 #include "ospfd/ospfd.h"
44 #include "ospfd/ospf_interface.h"
45 #include "ospfd/ospf_ism.h"
46 #include "ospfd/ospf_asbr.h"
47 #include "ospfd/ospf_lsa.h"
48 #include "ospfd/ospf_lsdb.h"
49 #include "ospfd/ospf_neighbor.h"
50 #include "ospfd/ospf_nsm.h"
51 #include "ospfd/ospf_flood.h"
52 #include "ospfd/ospf_packet.h"
53 #include "ospfd/ospf_spf.h"
54 #include "ospfd/ospf_dump.h"
55 #include "ospfd/ospf_route.h"
56 #include "ospfd/ospf_ase.h"
57 #include "ospfd/ospf_zebra.h"
58 #include "ospfd/ospf_sr.h"
59 #include "ospfd/ospf_ri.h"
60 #include "ospfd/ospf_errors.h"
63 * Global variable to manage Opaque-LSA/Router Information on this node.
64 * Note that all parameter values are stored in network byte order.
66 static struct ospf_router_info OspfRI
;
68 /*------------------------------------------------------------------------------*
69 * Followings are initialize/terminate functions for Router Information
71 *------------------------------------------------------------------------------*/
73 static void ospf_router_info_ism_change(struct ospf_interface
*oi
,
75 static void ospf_router_info_config_write_router(struct vty
*vty
);
76 static void ospf_router_info_show_info(struct vty
*vty
, struct ospf_lsa
*lsa
);
77 static int ospf_router_info_lsa_originate(void *arg
);
78 static struct ospf_lsa
*ospf_router_info_lsa_refresh(struct ospf_lsa
*lsa
);
79 static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info
*ai
,
80 enum lsa_opcode opcode
);
81 static void ospf_router_info_register_vty(void);
82 static int ospf_router_info_lsa_update(struct ospf_lsa
*lsa
);
83 static void del_area_info(void *val
);
84 static void del_pce_info(void *val
);
86 int ospf_router_info_init(void)
89 zlog_info("RI (%s): Initialize Router Information", __func__
);
91 memset(&OspfRI
, 0, sizeof(struct ospf_router_info
));
92 OspfRI
.enabled
= false;
93 OspfRI
.registered
= 0;
94 OspfRI
.scope
= OSPF_OPAQUE_AS_LSA
;
95 OspfRI
.as_flags
= RIFLG_LSA_INACTIVE
;
96 OspfRI
.area_info
= list_new();
97 OspfRI
.area_info
->del
= del_area_info
;
99 /* Initialize pce domain and neighbor list */
100 OspfRI
.pce_info
.enabled
= false;
101 OspfRI
.pce_info
.pce_domain
= list_new();
102 OspfRI
.pce_info
.pce_domain
->del
= del_pce_info
;
103 OspfRI
.pce_info
.pce_neighbor
= list_new();
104 OspfRI
.pce_info
.pce_neighbor
->del
= del_pce_info
;
106 /* Initialize Segment Routing information structure */
107 OspfRI
.sr_info
.enabled
= false;
109 ospf_router_info_register_vty();
114 static int ospf_router_info_register(uint8_t scope
)
118 if (OspfRI
.registered
)
121 zlog_info("RI (%s): Register Router Information with scope %s(%d)",
123 scope
== OSPF_OPAQUE_AREA_LSA
? "Area" : "AS", scope
);
124 rc
= ospf_register_opaque_functab(
125 scope
, OPAQUE_TYPE_ROUTER_INFORMATION_LSA
,
126 NULL
, /* new interface */
127 NULL
, /* del interface */
128 ospf_router_info_ism_change
,
129 NULL
, /* NSM change */
130 ospf_router_info_config_write_router
,
131 NULL
, /* Config. write interface */
132 NULL
, /* Config. write debug */
133 ospf_router_info_show_info
, ospf_router_info_lsa_originate
,
134 ospf_router_info_lsa_refresh
, ospf_router_info_lsa_update
,
135 NULL
); /* del_lsa_hook */
139 EC_OSPF_OPAQUE_REGISTRATION
,
140 "RI (%s): Failed to register functions", __func__
);
144 OspfRI
.registered
= 1;
145 OspfRI
.scope
= scope
;
149 static int ospf_router_info_unregister(void)
152 if ((OspfRI
.scope
!= OSPF_OPAQUE_AS_LSA
)
153 && (OspfRI
.scope
!= OSPF_OPAQUE_AREA_LSA
)) {
154 assert("Unable to unregister Router Info functions: Wrong scope!"
159 ospf_delete_opaque_functab(OspfRI
.scope
,
160 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
162 OspfRI
.registered
= 0;
166 void ospf_router_info_term(void)
169 list_delete(&OspfRI
.pce_info
.pce_domain
);
170 list_delete(&OspfRI
.pce_info
.pce_neighbor
);
172 OspfRI
.enabled
= false;
174 ospf_router_info_unregister();
179 void ospf_router_info_finish(void)
181 list_delete_all_node(OspfRI
.pce_info
.pce_domain
);
182 list_delete_all_node(OspfRI
.pce_info
.pce_neighbor
);
184 OspfRI
.enabled
= false;
187 static void del_area_info(void *val
)
189 XFREE(MTYPE_OSPF_ROUTER_INFO
, val
);
192 static void del_pce_info(void *val
)
194 XFREE(MTYPE_OSPF_PCE_PARAMS
, val
);
197 /* Catch RI LSA flooding Scope for ospf_ext.[h,c] code */
198 struct scope_info
ospf_router_info_get_flooding_scope(void)
200 struct scope_info flooding_scope
;
202 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
) {
203 flooding_scope
.scope
= OSPF_OPAQUE_AS_LSA
;
204 flooding_scope
.areas
= NULL
;
205 return flooding_scope
;
207 flooding_scope
.scope
= OSPF_OPAQUE_AREA_LSA
;
208 flooding_scope
.areas
= OspfRI
.area_info
;
209 return flooding_scope
;
212 static struct ospf_ri_area_info
*lookup_by_area(struct ospf_area
*area
)
214 struct listnode
*node
, *nnode
;
215 struct ospf_ri_area_info
*ai
;
217 for (ALL_LIST_ELEMENTS(OspfRI
.area_info
, node
, nnode
, ai
))
218 if (ai
->area
== area
)
224 /*------------------------------------------------------------------------*
225 * Followings are control functions for ROUTER INFORMATION parameters
227 *------------------------------------------------------------------------*/
229 static void set_router_info_capabilities(struct ri_tlv_router_cap
*ric
,
232 ric
->header
.type
= htons(RI_TLV_CAPABILITIES
);
233 ric
->header
.length
= htons(RI_TLV_LENGTH
);
234 ric
->value
= htonl(cap
);
238 static int set_pce_header(struct ospf_pce_info
*pce
)
241 struct listnode
*node
;
242 struct ri_pce_subtlv_domain
*domain
;
243 struct ri_pce_subtlv_neighbor
*neighbor
;
246 if (ntohs(pce
->pce_address
.header
.type
) != 0)
247 length
+= TLV_SIZE(&pce
->pce_address
.header
);
250 if (ntohs(pce
->pce_scope
.header
.type
) != 0)
251 length
+= TLV_SIZE(&pce
->pce_scope
.header
);
254 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
255 if (ntohs(domain
->header
.type
) != 0)
256 length
+= TLV_SIZE(&domain
->header
);
260 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
261 if (ntohs(neighbor
->header
.type
) != 0)
262 length
+= TLV_SIZE(&neighbor
->header
);
265 /* PCE Capabilities */
266 if (ntohs(pce
->pce_cap_flag
.header
.type
) != 0)
267 length
+= TLV_SIZE(&pce
->pce_cap_flag
.header
);
270 pce
->pce_header
.header
.type
= htons(RI_TLV_PCE
);
271 pce
->pce_header
.header
.length
= htons(length
);
274 pce
->pce_header
.header
.type
= 0;
275 pce
->pce_header
.header
.length
= 0;
276 pce
->enabled
= false;
282 static void set_pce_address(struct in_addr ipv4
, struct ospf_pce_info
*pce
)
285 /* Enable PCE Info */
286 pce
->pce_header
.header
.type
= htons(RI_TLV_PCE
);
287 /* Set PCE Address */
288 pce
->pce_address
.header
.type
= htons(RI_PCE_SUBTLV_ADDRESS
);
289 pce
->pce_address
.header
.length
= htons(PCE_ADDRESS_LENGTH_IPV4
);
290 pce
->pce_address
.address
.type
= htons(PCE_ADDRESS_TYPE_IPV4
);
291 pce
->pce_address
.address
.value
= ipv4
;
296 static void set_pce_path_scope(uint32_t scope
, struct ospf_pce_info
*pce
)
300 pce
->pce_scope
.header
.type
= htons(RI_PCE_SUBTLV_PATH_SCOPE
);
301 pce
->pce_scope
.header
.length
= htons(RI_TLV_LENGTH
);
302 pce
->pce_scope
.value
= htonl(scope
);
307 static void set_pce_domain(uint16_t type
, uint32_t domain
,
308 struct ospf_pce_info
*pce
)
311 struct ri_pce_subtlv_domain
*new;
313 /* Create new domain info */
314 new = XCALLOC(MTYPE_OSPF_PCE_PARAMS
,
315 sizeof(struct ri_pce_subtlv_domain
));
317 new->header
.type
= htons(RI_PCE_SUBTLV_DOMAIN
);
318 new->header
.length
= htons(PCE_ADDRESS_LENGTH_IPV4
);
319 new->type
= htons(type
);
320 new->value
= htonl(domain
);
322 /* Add new domain to the list */
323 listnode_add(pce
->pce_domain
, new);
328 static void unset_pce_domain(uint16_t type
, uint32_t domain
,
329 struct ospf_pce_info
*pce
)
331 struct listnode
*node
;
332 struct ri_pce_subtlv_domain
*old
= NULL
;
335 /* Search the corresponding node */
336 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, old
)) {
337 if ((old
->type
== htons(type
))
338 && (old
->value
== htonl(domain
))) {
344 /* if found remove it */
346 listnode_delete(pce
->pce_domain
, old
);
348 /* Finally free the old domain */
349 XFREE(MTYPE_OSPF_PCE_PARAMS
, old
);
353 static void set_pce_neighbor(uint16_t type
, uint32_t domain
,
354 struct ospf_pce_info
*pce
)
357 struct ri_pce_subtlv_neighbor
*new;
359 /* Create new neighbor info */
360 new = XCALLOC(MTYPE_OSPF_PCE_PARAMS
,
361 sizeof(struct ri_pce_subtlv_neighbor
));
363 new->header
.type
= htons(RI_PCE_SUBTLV_NEIGHBOR
);
364 new->header
.length
= htons(PCE_ADDRESS_LENGTH_IPV4
);
365 new->type
= htons(type
);
366 new->value
= htonl(domain
);
368 /* Add new domain to the list */
369 listnode_add(pce
->pce_neighbor
, new);
374 static void unset_pce_neighbor(uint16_t type
, uint32_t domain
,
375 struct ospf_pce_info
*pce
)
377 struct listnode
*node
;
378 struct ri_pce_subtlv_neighbor
*old
= NULL
;
381 /* Search the corresponding node */
382 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, old
)) {
383 if ((old
->type
== htons(type
))
384 && (old
->value
== htonl(domain
))) {
390 /* if found remove it */
392 listnode_delete(pce
->pce_neighbor
, old
);
394 /* Finally free the old domain */
395 XFREE(MTYPE_OSPF_PCE_PARAMS
, old
);
399 static void set_pce_cap_flag(uint32_t cap
, struct ospf_pce_info
*pce
)
402 /* Set PCE Capabilities flag */
403 pce
->pce_cap_flag
.header
.type
= htons(RI_PCE_SUBTLV_CAP_FLAG
);
404 pce
->pce_cap_flag
.header
.length
= htons(RI_TLV_LENGTH
);
405 pce
->pce_cap_flag
.value
= htonl(cap
);
410 /* Segment Routing TLV setter */
412 /* Algorithm SubTLV - section 3.1 */
413 static void set_sr_algorithm(uint8_t algo
)
416 OspfRI
.sr_info
.algo
.value
[0] = algo
;
417 for (int i
= 1; i
< ALGORITHM_COUNT
; i
++)
418 OspfRI
.sr_info
.algo
.value
[i
] = SR_ALGORITHM_UNSET
;
420 /* Set TLV type and length == only 1 Algorithm */
421 TLV_TYPE(OspfRI
.sr_info
.algo
) = htons(RI_SR_TLV_SR_ALGORITHM
);
422 TLV_LEN(OspfRI
.sr_info
.algo
) = htons(sizeof(uint8_t));
425 /* unset Aglogithm SubTLV */
426 static void unset_sr_algorithm(uint8_t algo
)
429 for (int i
= 0; i
< ALGORITHM_COUNT
; i
++)
430 OspfRI
.sr_info
.algo
.value
[i
] = SR_ALGORITHM_UNSET
;
432 /* Unset TLV type and length */
433 TLV_TYPE(OspfRI
.sr_info
.algo
) = htons(0);
434 TLV_LEN(OspfRI
.sr_info
.algo
) = htons(0);
437 /* Segment Routing Global Block SubTLV - section 3.2 */
438 static void set_sr_sid_label_range(struct sr_srgb srgb
)
441 TLV_TYPE(OspfRI
.sr_info
.range
) = htons(RI_SR_TLV_SID_LABEL_RANGE
);
442 TLV_LEN(OspfRI
.sr_info
.range
) =
443 htons(SUBTLV_SID_LABEL_SIZE
+ sizeof(uint32_t));
445 OspfRI
.sr_info
.range
.size
= htonl(SET_RANGE_SIZE(srgb
.range_size
));
446 /* Set Lower bound label SubTLV */
447 TLV_TYPE(OspfRI
.sr_info
.range
.lower
) = htons(SUBTLV_SID_LABEL
);
448 TLV_LEN(OspfRI
.sr_info
.range
.lower
) = htons(SID_RANGE_LABEL_LENGTH
);
449 OspfRI
.sr_info
.range
.lower
.value
= htonl(SET_LABEL(srgb
.lower_bound
));
452 /* Unset this SRGB SubTLV */
453 static void unset_sr_sid_label_range(void)
456 TLV_TYPE(OspfRI
.sr_info
.range
) = htons(0);
457 TLV_LEN(OspfRI
.sr_info
.range
) = htons(0);
458 TLV_TYPE(OspfRI
.sr_info
.range
.lower
) = htons(0);
459 TLV_LEN(OspfRI
.sr_info
.range
.lower
) = htons(0);
462 /* Set Maximum Stack Depth for this router */
463 static void set_sr_node_msd(uint8_t msd
)
465 TLV_TYPE(OspfRI
.sr_info
.msd
) = htons(RI_SR_TLV_NODE_MSD
);
466 TLV_LEN(OspfRI
.sr_info
.msd
) = htons(sizeof(uint32_t));
467 OspfRI
.sr_info
.msd
.value
= msd
;
470 /* Unset this router MSD */
471 static void unset_sr_node_msd(void)
473 TLV_TYPE(OspfRI
.sr_info
.msd
) = htons(0);
474 TLV_LEN(OspfRI
.sr_info
.msd
) = htons(0);
477 static void unset_param(void *tlv_buffer
)
479 struct tlv_header
*tlv
= (struct tlv_header
*)tlv_buffer
;
482 /* Fill the Value to 0 */
483 memset(TLV_DATA(tlv_buffer
), 0, TLV_BODY_SIZE(tlv
));
489 static void initialize_params(struct ospf_router_info
*ori
)
493 struct listnode
*node
, *nnode
;
494 struct ospf_area
*area
;
495 struct ospf_ri_area_info
*new;
498 * Initialize default Router Information Capabilities.
502 set_router_info_capabilities(&ori
->router_cap
, cap
);
504 /* If Area address is not null and exist, retrieve corresponding
506 top
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
507 zlog_info("RI (%s): Initialize Router Info for %s scope", __func__
,
508 OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
? "Area" : "AS");
510 /* Try to get available Area's context from ospf at this step.
511 * Do it latter if not available */
512 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) {
513 for (ALL_LIST_ELEMENTS(top
->areas
, node
, nnode
, area
)) {
514 zlog_debug("RI (%s): Add area %s to Router Information",
515 __func__
, inet_ntoa(area
->area_id
));
516 new = XCALLOC(MTYPE_OSPF_ROUTER_INFO
,
517 sizeof(struct ospf_ri_area_info
));
519 new->flags
= RIFLG_LSA_INACTIVE
;
520 listnode_add(OspfRI
.area_info
, new);
525 * Initialize default PCE Information values
527 /* PCE address == OSPF Router ID */
528 set_pce_address(top
->router_id
, &ori
->pce_info
);
531 cap
= 7; /* Set L, R and Rd bits to one = intra & inter-area path
533 set_pce_path_scope(cap
, &ori
->pce_info
);
535 /* PCE Capabilities */
536 cap
= PCE_CAP_BIDIRECTIONAL
| PCE_CAP_DIVERSE_PATH
| PCE_CAP_OBJECTIVES
537 | PCE_CAP_ADDITIVE
| PCE_CAP_MULTIPLE_REQ
;
538 set_pce_cap_flag(cap
, &ori
->pce_info
);
543 static int is_mandated_params_set(struct ospf_router_info ori
)
547 if (ntohs(ori
.router_cap
.header
.type
) == 0)
550 if ((ntohs(ori
.pce_info
.pce_header
.header
.type
) == RI_TLV_PCE
)
551 && (ntohs(ori
.pce_info
.pce_address
.header
.type
) == 0)
552 && (ntohs(ori
.pce_info
.pce_cap_flag
.header
.type
) == 0))
555 if ((ori
.sr_info
.enabled
) && (ntohs(TLV_TYPE(ori
.sr_info
.algo
)) == 0)
556 && (ntohs(TLV_TYPE(ori
.sr_info
.range
)) == 0))
565 * Used by Segment Routing to set new TLVs and Sub-TLVs values
567 * @param enable To activate or not Segment Routing router Information flooding
568 * @param size Size of Label Range i.e. SRGB size
569 * @param lower Lower bound of the Label Range i.e. SRGB first label
570 * @param msd Maximum label Stack Depth supported by the router
574 void ospf_router_info_update_sr(bool enable
, struct sr_srgb srgb
, uint8_t msd
)
576 struct listnode
*node
, *nnode
;
577 struct ospf_ri_area_info
*ai
;
579 /* First, check if Router Information is registered or not */
580 if (!OspfRI
.registered
)
581 ospf_router_info_register(OSPF_OPAQUE_AREA_LSA
);
583 /* Verify that scope is AREA */
584 if (OspfRI
.scope
!= OSPF_OPAQUE_AREA_LSA
) {
586 "RI (%s): Router Info is %s flooding: Change scope to Area flooding for Segment Routing",
588 OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
? "Area" : "AS");
592 /* Then, activate and initialize Router Information if necessary */
593 if (!OspfRI
.enabled
) {
594 OspfRI
.enabled
= true;
595 initialize_params(&OspfRI
);
598 if (IS_DEBUG_OSPF_SR
)
599 zlog_debug("RI (%s): %s Routing Information for Segment Routing",
600 __func__
, enable
? "Enable" : "Disable");
602 /* Unset or Set SR parameters */
604 unset_sr_algorithm(SR_ALGORITHM_SPF
);
605 unset_sr_sid_label_range();
607 OspfRI
.sr_info
.enabled
= false;
609 // Only SR_ALGORITHM_SPF is supported
610 set_sr_algorithm(SR_ALGORITHM_SPF
);
611 set_sr_sid_label_range(srgb
);
613 set_sr_node_msd(msd
);
616 OspfRI
.sr_info
.enabled
= true;
619 /* Refresh if already engaged or originate RI LSA */
620 for (ALL_LIST_ELEMENTS(OspfRI
.area_info
, node
, nnode
, ai
)) {
621 if (CHECK_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
))
622 ospf_router_info_lsa_schedule(ai
, REFRESH_THIS_LSA
);
624 ospf_router_info_lsa_schedule(ai
,
625 REORIGINATE_THIS_LSA
);
630 /*------------------------------------------------------------------------*
631 * Followings are callback functions against generic Opaque-LSAs handling.
632 *------------------------------------------------------------------------*/
633 static void ospf_router_info_ism_change(struct ospf_interface
*oi
,
637 struct ospf_ri_area_info
*ai
;
639 /* Collect area information */
640 ai
= lookup_by_area(oi
->area
);
642 /* Check if area is not yet registered */
646 /* Add this new area to the list */
647 ai
= XCALLOC(MTYPE_OSPF_ROUTER_INFO
, sizeof(struct ospf_ri_area_info
));
649 ai
->flags
= RIFLG_LSA_INACTIVE
;
650 listnode_add(OspfRI
.area_info
, ai
);
655 /*------------------------------------------------------------------------*
656 * Followings are OSPF protocol processing functions for ROUTER INFORMATION
657 *------------------------------------------------------------------------*/
659 static void build_tlv_header(struct stream
*s
, struct tlv_header
*tlvh
)
662 stream_put(s
, tlvh
, sizeof(struct tlv_header
));
666 static void build_tlv(struct stream
*s
, struct tlv_header
*tlvh
)
669 if (ntohs(tlvh
->type
) != 0) {
670 build_tlv_header(s
, tlvh
);
671 stream_put(s
, TLV_DATA(tlvh
), TLV_BODY_SIZE(tlvh
));
676 static void ospf_router_info_lsa_body_set(struct stream
*s
)
679 struct listnode
*node
;
680 struct ri_pce_subtlv_domain
*domain
;
681 struct ri_pce_subtlv_neighbor
*neighbor
;
683 /* Build Router Information TLV */
684 build_tlv(s
, &OspfRI
.router_cap
.header
);
686 /* Build Segment Routing TLVs if enabled */
687 if (OspfRI
.sr_info
.enabled
) {
688 /* Build Algorithm TLV */
689 build_tlv(s
, &TLV_HDR(OspfRI
.sr_info
.algo
));
691 build_tlv(s
, &TLV_HDR(OspfRI
.sr_info
.range
));
693 build_tlv(s
, &TLV_HDR(OspfRI
.sr_info
.msd
));
696 /* Add RI PCE TLV if it is set */
697 if (OspfRI
.pce_info
.enabled
) {
699 /* Compute PCE Info header first */
700 set_pce_header(&OspfRI
.pce_info
);
703 build_tlv_header(s
, &OspfRI
.pce_info
.pce_header
.header
);
705 /* Build PCE address sub-tlv */
706 build_tlv(s
, &OspfRI
.pce_info
.pce_address
.header
);
708 /* Build PCE path scope sub-tlv */
709 build_tlv(s
, &OspfRI
.pce_info
.pce_scope
.header
);
711 /* Build PCE domain sub-tlv */
712 for (ALL_LIST_ELEMENTS_RO(OspfRI
.pce_info
.pce_domain
, node
,
714 build_tlv(s
, &domain
->header
);
716 /* Build PCE neighbor sub-tlv */
717 for (ALL_LIST_ELEMENTS_RO(OspfRI
.pce_info
.pce_neighbor
, node
,
719 build_tlv(s
, &neighbor
->header
);
721 /* Build PCE cap flag sub-tlv */
722 build_tlv(s
, &OspfRI
.pce_info
.pce_cap_flag
.header
);
728 /* Create new opaque-LSA. */
729 static struct ospf_lsa
*ospf_router_info_lsa_new(struct ospf_area
*area
)
733 struct lsa_header
*lsah
;
734 struct ospf_lsa
*new = NULL
;
735 uint8_t options
, lsa_type
;
736 struct in_addr lsa_id
;
740 /* Create a stream for LSA. */
741 s
= stream_new(OSPF_MAX_LSA_SIZE
);
743 lsah
= (struct lsa_header
*)STREAM_DATA(s
);
745 options
= OSPF_OPTION_E
; /* Enable AS external as we flood RI with
747 options
|= OSPF_OPTION_O
; /* Don't forget this :-) */
749 lsa_type
= OspfRI
.scope
;
750 /* LSA ID == 0 for Router Information see RFC 4970 */
751 tmp
= SET_OPAQUE_LSID(OPAQUE_TYPE_ROUTER_INFORMATION_LSA
, 0);
752 lsa_id
.s_addr
= htonl(tmp
);
754 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
))
756 "LSA[Type%d:%s]: Create an Opaque-LSA/ROUTER INFORMATION instance",
757 lsa_type
, inet_ntoa(lsa_id
));
759 top
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
761 /* Set opaque-LSA header fields. */
762 lsa_header_set(s
, options
, lsa_type
, lsa_id
, top
->router_id
);
764 /* Set opaque-LSA body fields. */
765 ospf_router_info_lsa_body_set(s
);
768 length
= stream_get_endp(s
);
769 lsah
->length
= htons(length
);
771 /* Now, create an OSPF LSA instance. */
772 new = ospf_lsa_new_and_data(length
);
776 if (new->area
&& new->area
->ospf
)
777 new->vrf_id
= new->area
->ospf
->vrf_id
;
779 new->vrf_id
= VRF_DEFAULT
;
781 SET_FLAG(new->flags
, OSPF_LSA_SELF
);
782 memcpy(new->data
, lsah
, length
);
788 static int ospf_router_info_lsa_originate_as(void *arg
)
790 struct ospf_lsa
*new;
793 vrf_id_t vrf_id
= VRF_DEFAULT
;
796 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) {
798 EC_OSPF_LSA_INSTALL_FAILURE
,
799 "RI (%s): wrong flooding scope AREA instead of AS ?",
804 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
805 new = ospf_router_info_lsa_new(NULL
);
806 new->vrf_id
= VRF_DEFAULT
;
807 top
= (struct ospf
*)arg
;
809 /* Check ospf info */
811 zlog_debug("RI (%s): ospf instance not found for vrf id %u",
813 ospf_lsa_unlock(&new);
817 /* Install this LSA into LSDB. */
818 if (ospf_lsa_install(top
, NULL
/*oi */, new) == NULL
) {
820 EC_OSPF_LSA_INSTALL_FAILURE
,
821 "RI (%s): ospf_lsa_install() ?", __func__
);
822 ospf_lsa_unlock(&new);
826 /* Update new LSA origination count. */
827 top
->lsa_originate_count
++;
829 /* Flood new LSA through AREA or AS. */
830 SET_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
);
831 ospf_flood_through_as(top
, NULL
/*nbr */, new);
833 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
835 "LSA[Type%d:%s]: Originate Opaque-LSA/ROUTER INFORMATION",
836 new->data
->type
, inet_ntoa(new->data
->id
));
837 ospf_lsa_header_dump(new->data
);
844 static int ospf_router_info_lsa_originate_area(void *arg
)
846 struct ospf_lsa
*new;
848 struct ospf_ri_area_info
*ai
= NULL
;
850 vrf_id_t vrf_id
= VRF_DEFAULT
;
853 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
) {
855 EC_OSPF_LSA_INSTALL_FAILURE
,
856 "RI (%s): wrong flooding scope AS instead of AREA ?",
861 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
862 ai
= lookup_by_area((struct ospf_area
*)arg
);
865 "RI (%s): There is no context for this Router Information. Stop processing",
869 if (ai
->area
->ospf
) {
870 vrf_id
= ai
->area
->ospf
->vrf_id
;
871 top
= ai
->area
->ospf
;
873 top
= ospf_lookup_by_vrf_id(vrf_id
);
875 new = ospf_router_info_lsa_new(ai
->area
);
876 new->vrf_id
= vrf_id
;
878 /* Check ospf info */
880 zlog_debug("RI (%s): ospf instance not found for vrf id %u",
882 ospf_lsa_unlock(&new);
886 /* Install this LSA into LSDB. */
887 if (ospf_lsa_install(top
, NULL
/*oi */, new) == NULL
) {
889 EC_OSPF_LSA_INSTALL_FAILURE
,
890 "RI (%s): ospf_lsa_install() ?", __func__
);
891 ospf_lsa_unlock(&new);
895 /* Update new LSA origination count. */
896 top
->lsa_originate_count
++;
898 /* Flood new LSA through AREA or AS. */
899 SET_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
);
900 ospf_flood_through_area(ai
->area
, NULL
/*nbr */, new);
902 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
904 "LSA[Type%d:%s]: Originate Opaque-LSA/ROUTER INFORMATION",
905 new->data
->type
, inet_ntoa(new->data
->id
));
906 ospf_lsa_header_dump(new->data
);
913 static int ospf_router_info_lsa_originate(void *arg
)
916 struct ospf_ri_area_info
*ai
;
919 if (!OspfRI
.enabled
) {
920 zlog_info("RI (%s): ROUTER INFORMATION is disabled now.",
922 rc
= 0; /* This is not an error case. */
926 /* Check if Router Information LSA is already engaged */
927 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
) {
928 if ((CHECK_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
))
929 && (CHECK_FLAG(OspfRI
.as_flags
,
930 RIFLG_LSA_FORCED_REFRESH
))) {
931 UNSET_FLAG(OspfRI
.as_flags
, RIFLG_LSA_FORCED_REFRESH
);
932 ospf_router_info_lsa_schedule(NULL
, REFRESH_THIS_LSA
);
937 ai
= lookup_by_area((struct ospf_area
*)arg
);
941 "RI (%s): Missing area information", __func__
);
944 if ((CHECK_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
))
945 && (CHECK_FLAG(ai
->flags
, RIFLG_LSA_FORCED_REFRESH
))) {
946 UNSET_FLAG(ai
->flags
, RIFLG_LSA_FORCED_REFRESH
);
947 ospf_router_info_lsa_schedule(ai
, REFRESH_THIS_LSA
);
953 /* Router Information is not yet Engaged, check parameters */
954 if (!is_mandated_params_set(OspfRI
))
957 "RI (%s): lacks mandated ROUTER INFORMATION parameters",
960 /* Ok, let's try to originate an LSA */
961 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
)
962 rc
= ospf_router_info_lsa_originate_as(arg
);
964 rc
= ospf_router_info_lsa_originate_area(arg
);
969 static struct ospf_lsa
*ospf_router_info_lsa_refresh(struct ospf_lsa
*lsa
)
971 struct ospf_ri_area_info
*ai
= NULL
;
972 struct ospf_lsa
*new = NULL
;
975 if (!OspfRI
.enabled
) {
977 * This LSA must have flushed before due to ROUTER INFORMATION
979 * It seems a slip among routers in the routing domain.
981 zlog_info("RI (%s): ROUTER INFORMATION is disabled now.",
984 htons(OSPF_LSA_MAXAGE
); /* Flush it anyway. */
987 /* Verify that the Router Information ID is supported */
988 if (GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)) != 0) {
991 "RI (%s): Unsupported Router Information ID",
996 /* Process LSA depending of the flooding scope */
997 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) {
998 /* Get context AREA context */
999 ai
= lookup_by_area(lsa
->area
);
1003 "RI (%s): No associated Area", __func__
);
1006 /* Flush LSA, if the lsa's age reached to MaxAge. */
1007 if (IS_LSA_MAXAGE(lsa
)) {
1008 UNSET_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
);
1009 ospf_opaque_lsa_flush_schedule(lsa
);
1012 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
1013 new = ospf_router_info_lsa_new(ai
->area
);
1014 new->data
->ls_seqnum
= lsa_seqnum_increment(lsa
);
1015 new->vrf_id
= lsa
->vrf_id
;
1016 /* Install this LSA into LSDB. */
1017 /* Given "lsa" will be freed in the next function. */
1018 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
1019 if (ospf_lsa_install(top
, NULL
/*oi */, new) == NULL
) {
1020 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE
,
1021 "RI (%s): ospf_lsa_install() ?", __func__
);
1022 ospf_lsa_unlock(&new);
1025 /* Flood updated LSA through AREA */
1026 ospf_flood_through_area(ai
->area
, NULL
/*nbr */, new);
1028 } else { /* AS Flooding scope */
1029 /* Flush LSA, if the lsa's age reached to MaxAge. */
1030 if (IS_LSA_MAXAGE(lsa
)) {
1031 UNSET_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
);
1032 ospf_opaque_lsa_flush_schedule(lsa
);
1035 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
1036 new = ospf_router_info_lsa_new(NULL
);
1037 new->data
->ls_seqnum
= lsa_seqnum_increment(lsa
);
1038 new->vrf_id
= lsa
->vrf_id
;
1039 /* Install this LSA into LSDB. */
1040 /* Given "lsa" will be freed in the next function. */
1041 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
1042 if (ospf_lsa_install(top
, NULL
/*oi */, new) == NULL
) {
1043 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE
,
1044 "RI (%s): ospf_lsa_install() ?", __func__
);
1045 ospf_lsa_unlock(&new);
1048 /* Flood updated LSA through AS */
1049 ospf_flood_through_as(top
, NULL
/*nbr */, new);
1052 /* Debug logging. */
1053 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
1055 "LSA[Type%d:%s]: Refresh Opaque-LSA/ROUTER INFORMATION",
1056 new->data
->type
, inet_ntoa(new->data
->id
));
1057 ospf_lsa_header_dump(new->data
);
1063 static void ospf_router_info_lsa_schedule(struct ospf_ri_area_info
*ai
,
1064 enum lsa_opcode opcode
)
1066 struct ospf_lsa lsa
;
1067 struct lsa_header lsah
;
1071 memset(&lsa
, 0, sizeof(lsa
));
1072 memset(&lsah
, 0, sizeof(lsah
));
1074 zlog_debug("RI (%s): LSA schedule %s%s%s", __func__
,
1075 opcode
== REORIGINATE_THIS_LSA
? "Re-Originate" : "",
1076 opcode
== REFRESH_THIS_LSA
? "Refresh" : "",
1077 opcode
== FLUSH_THIS_LSA
? "Flush" : "");
1079 /* Check LSA flags state coherence and collect area information */
1080 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) {
1081 if ((ai
== NULL
) || (ai
->area
== NULL
)) {
1084 "RI (%s): Router Info is Area scope flooding but area is not set",
1089 if (!CHECK_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
)
1090 && (opcode
!= REORIGINATE_THIS_LSA
))
1093 if (CHECK_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
)
1094 && (opcode
== REORIGINATE_THIS_LSA
))
1095 opcode
= REFRESH_THIS_LSA
;
1097 lsa
.area
= ai
->area
;
1098 top
= ai
->area
->ospf
;
1100 if (!CHECK_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
)
1101 && (opcode
!= REORIGINATE_THIS_LSA
))
1104 if (CHECK_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
)
1105 && (opcode
== REORIGINATE_THIS_LSA
))
1106 opcode
= REFRESH_THIS_LSA
;
1108 top
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1113 lsah
.type
= OspfRI
.scope
;
1115 /* LSA ID is set to 0 for the Router Information. See RFC 4970 */
1116 tmp
= SET_OPAQUE_LSID(OPAQUE_TYPE_ROUTER_INFORMATION_LSA
, 0);
1117 lsah
.id
.s_addr
= htonl(tmp
);
1120 case REORIGINATE_THIS_LSA
:
1121 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
)
1122 ospf_opaque_lsa_reoriginate_schedule(
1123 (void *)ai
->area
, OSPF_OPAQUE_AREA_LSA
,
1124 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
1126 ospf_opaque_lsa_reoriginate_schedule(
1127 (void *)top
, OSPF_OPAQUE_AS_LSA
,
1128 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
1130 case REFRESH_THIS_LSA
:
1131 ospf_opaque_lsa_refresh_schedule(&lsa
);
1133 case FLUSH_THIS_LSA
:
1134 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
)
1135 UNSET_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
);
1137 UNSET_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
);
1138 ospf_opaque_lsa_flush_schedule(&lsa
);
1145 /* Callback to handle Segment Routing information */
1146 static int ospf_router_info_lsa_update(struct ospf_lsa
*lsa
)
1151 flog_warn(EC_OSPF_LSA
, "RI (%s): Abort! LSA is NULL",
1156 /* Process only Opaque LSA */
1157 if ((lsa
->data
->type
!= OSPF_OPAQUE_AREA_LSA
)
1158 && (lsa
->data
->type
!= OSPF_OPAQUE_AS_LSA
))
1161 /* Process only Router Information LSA */
1162 if (GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
))
1163 != OPAQUE_TYPE_ROUTER_INFORMATION_LSA
)
1166 /* Check if it is not my LSA */
1167 if (IS_LSA_SELF(lsa
))
1170 /* Check if Router Info & Segment Routing are enable */
1171 if (!OspfRI
.enabled
|| !OspfRI
.sr_info
.enabled
)
1174 /* Call Segment Routing LSA update or deletion */
1175 if (!IS_LSA_MAXAGE(lsa
))
1176 ospf_sr_ri_lsa_update(lsa
);
1178 ospf_sr_ri_lsa_delete(lsa
);
1183 /*------------------------------------------------------------------------*
1184 * Followings are vty session control functions.
1185 *------------------------------------------------------------------------*/
1187 static uint16_t show_vty_router_cap(struct vty
*vty
, struct tlv_header
*tlvh
)
1189 struct ri_tlv_router_cap
*top
= (struct ri_tlv_router_cap
*)tlvh
;
1192 vty_out(vty
, " Router Capabilities: 0x%x\n",
1195 zlog_debug(" Router Capabilities: 0x%x", ntohl(top
->value
));
1197 return TLV_SIZE(tlvh
);
1200 static uint16_t show_vty_pce_subtlv_address(struct vty
*vty
,
1201 struct tlv_header
*tlvh
)
1203 struct ri_pce_subtlv_address
*top
=
1204 (struct ri_pce_subtlv_address
*)tlvh
;
1206 if (ntohs(top
->address
.type
) == PCE_ADDRESS_TYPE_IPV4
) {
1208 vty_out(vty
, " PCE Address: %s\n",
1209 inet_ntoa(top
->address
.value
));
1211 zlog_debug(" PCE Address: %s",
1212 inet_ntoa(top
->address
.value
));
1214 /* TODO: Add support to IPv6 with inet_ntop() */
1216 vty_out(vty
, " PCE Address: 0x%x\n",
1217 ntohl(top
->address
.value
.s_addr
));
1219 zlog_debug(" PCE Address: 0x%x",
1220 ntohl(top
->address
.value
.s_addr
));
1223 return TLV_SIZE(tlvh
);
1226 static uint16_t show_vty_pce_subtlv_path_scope(struct vty
*vty
,
1227 struct tlv_header
*tlvh
)
1229 struct ri_pce_subtlv_path_scope
*top
=
1230 (struct ri_pce_subtlv_path_scope
*)tlvh
;
1233 vty_out(vty
, " PCE Path Scope: 0x%x\n", ntohl(top
->value
));
1235 zlog_debug(" PCE Path Scope: 0x%x", ntohl(top
->value
));
1237 return TLV_SIZE(tlvh
);
1240 static uint16_t show_vty_pce_subtlv_domain(struct vty
*vty
,
1241 struct tlv_header
*tlvh
)
1243 struct ri_pce_subtlv_domain
*top
= (struct ri_pce_subtlv_domain
*)tlvh
;
1246 if (ntohs(top
->type
) == PCE_DOMAIN_TYPE_AREA
) {
1247 tmp
.s_addr
= top
->value
;
1249 vty_out(vty
, " PCE domain Area: %s\n", inet_ntoa(tmp
));
1251 zlog_debug(" PCE domain Area: %s", inet_ntoa(tmp
));
1254 vty_out(vty
, " PCE domain AS: %d\n",
1257 zlog_debug(" PCE domain AS: %d", ntohl(top
->value
));
1259 return TLV_SIZE(tlvh
);
1262 static uint16_t show_vty_pce_subtlv_neighbor(struct vty
*vty
,
1263 struct tlv_header
*tlvh
)
1266 struct ri_pce_subtlv_neighbor
*top
=
1267 (struct ri_pce_subtlv_neighbor
*)tlvh
;
1270 if (ntohs(top
->type
) == PCE_DOMAIN_TYPE_AREA
) {
1271 tmp
.s_addr
= top
->value
;
1273 vty_out(vty
, " PCE neighbor Area: %s\n",
1276 zlog_debug(" PCE neighbor Area: %s", inet_ntoa(tmp
));
1279 vty_out(vty
, " PCE neighbor AS: %d\n",
1282 zlog_debug(" PCE neighbor AS: %d",
1285 return TLV_SIZE(tlvh
);
1288 static uint16_t show_vty_pce_subtlv_cap_flag(struct vty
*vty
,
1289 struct tlv_header
*tlvh
)
1291 struct ri_pce_subtlv_cap_flag
*top
=
1292 (struct ri_pce_subtlv_cap_flag
*)tlvh
;
1295 vty_out(vty
, " PCE Capabilities Flag: 0x%x\n",
1298 zlog_debug(" PCE Capabilities Flag: 0x%x",
1301 return TLV_SIZE(tlvh
);
1304 static uint16_t show_vty_unknown_tlv(struct vty
*vty
, struct tlv_header
*tlvh
)
1307 vty_out(vty
, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
1308 ntohs(tlvh
->type
), ntohs(tlvh
->length
));
1310 zlog_debug(" Unknown TLV: [type(0x%x), length(0x%x)]",
1311 ntohs(tlvh
->type
), ntohs(tlvh
->length
));
1313 return TLV_SIZE(tlvh
);
1316 static uint16_t show_vty_pce_info(struct vty
*vty
, struct tlv_header
*ri
,
1319 struct tlv_header
*tlvh
;
1322 for (tlvh
= ri
; sum
< total
; tlvh
= TLV_HDR_NEXT(tlvh
)) {
1323 switch (ntohs(tlvh
->type
)) {
1324 case RI_PCE_SUBTLV_ADDRESS
:
1325 sum
+= show_vty_pce_subtlv_address(vty
, tlvh
);
1327 case RI_PCE_SUBTLV_PATH_SCOPE
:
1328 sum
+= show_vty_pce_subtlv_path_scope(vty
, tlvh
);
1330 case RI_PCE_SUBTLV_DOMAIN
:
1331 sum
+= show_vty_pce_subtlv_domain(vty
, tlvh
);
1333 case RI_PCE_SUBTLV_NEIGHBOR
:
1334 sum
+= show_vty_pce_subtlv_neighbor(vty
, tlvh
);
1336 case RI_PCE_SUBTLV_CAP_FLAG
:
1337 sum
+= show_vty_pce_subtlv_cap_flag(vty
, tlvh
);
1340 sum
+= show_vty_unknown_tlv(vty
, tlvh
);
1347 /* Display Segment Routing Algorithm TLV information */
1348 static uint16_t show_vty_sr_algorithm(struct vty
*vty
, struct tlv_header
*tlvh
)
1350 struct ri_sr_tlv_sr_algorithm
*algo
=
1351 (struct ri_sr_tlv_sr_algorithm
*)tlvh
;
1355 vty_out(vty
, " Segment Routing Algorithm TLV:\n");
1356 for (i
= 0; i
< ntohs(algo
->header
.length
); i
++) {
1357 switch (algo
->value
[i
]) {
1359 vty_out(vty
, " Algorithm %d: SPF\n", i
);
1362 vty_out(vty
, " Algorithm %d: Strict SPF\n",
1367 " Algorithm %d: Unknown value %d\n", i
,
1375 zlog_debug(" Segment Routing Algorithm TLV:");
1376 for (i
= 0; i
< ntohs(algo
->header
.length
); i
++)
1377 switch (algo
->value
[i
]) {
1379 zlog_debug(" Algorithm %d: SPF", i
);
1382 zlog_debug(" Algorithm %d: Strict SPF", i
);
1386 " Algorithm %d: Unknown value %d\n",
1392 return TLV_SIZE(tlvh
);
1395 /* Display Segment Routing SID/Label Range TLV information */
1396 static uint16_t show_vty_sr_range(struct vty
*vty
, struct tlv_header
*tlvh
)
1398 struct ri_sr_tlv_sid_label_range
*range
=
1399 (struct ri_sr_tlv_sid_label_range
*)tlvh
;
1403 " Segment Routing Range TLV:\n"
1404 " Range Size = %d\n"
1405 " SID Label = %d\n\n",
1406 GET_RANGE_SIZE(ntohl(range
->size
)),
1407 GET_LABEL(ntohl(range
->lower
.value
)));
1410 " Segment Routing Range TLV:\n"
1411 " Range Size = %d\n"
1412 " SID Label = %d\n\n",
1413 GET_RANGE_SIZE(ntohl(range
->size
)),
1414 GET_LABEL(ntohl(range
->lower
.value
)));
1417 return TLV_SIZE(tlvh
);
1420 /* Display Segment Routing Maximum Stack Depth TLV information */
1421 static uint16_t show_vty_sr_msd(struct vty
*vty
, struct tlv_header
*tlvh
)
1423 struct ri_sr_tlv_node_msd
*msd
= (struct ri_sr_tlv_node_msd
*)tlvh
;
1427 " Segment Routing MSD TLV:\n"
1428 " Node Maximum Stack Depth = %d\n",
1432 " Segment Routing MSD TLV:\n"
1433 " Node Maximum Stack Depth = %d\n",
1437 return TLV_SIZE(tlvh
);
1440 static void ospf_router_info_show_info(struct vty
*vty
, struct ospf_lsa
*lsa
)
1442 struct lsa_header
*lsah
= (struct lsa_header
*)lsa
->data
;
1443 struct tlv_header
*tlvh
;
1444 uint16_t length
= 0, sum
= 0;
1446 /* Initialize TLV browsing */
1447 length
= ntohs(lsah
->length
) - OSPF_LSA_HEADER_SIZE
;
1449 for (tlvh
= TLV_HDR_TOP(lsah
); sum
< length
;
1450 tlvh
= TLV_HDR_NEXT(tlvh
)) {
1451 switch (ntohs(tlvh
->type
)) {
1452 case RI_TLV_CAPABILITIES
:
1453 sum
+= show_vty_router_cap(vty
, tlvh
);
1457 sum
+= TLV_HDR_SIZE
;
1458 sum
+= show_vty_pce_info(vty
, tlvh
, length
- sum
);
1460 case RI_SR_TLV_SR_ALGORITHM
:
1461 sum
+= show_vty_sr_algorithm(vty
, tlvh
);
1463 case RI_SR_TLV_SID_LABEL_RANGE
:
1464 sum
+= show_vty_sr_range(vty
, tlvh
);
1466 case RI_SR_TLV_NODE_MSD
:
1467 sum
+= show_vty_sr_msd(vty
, tlvh
);
1471 sum
+= show_vty_unknown_tlv(vty
, tlvh
);
1479 static void ospf_router_info_config_write_router(struct vty
*vty
)
1481 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1482 struct listnode
*node
;
1483 struct ri_pce_subtlv_domain
*domain
;
1484 struct ri_pce_subtlv_neighbor
*neighbor
;
1487 if (!OspfRI
.enabled
)
1490 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
)
1491 vty_out(vty
, " router-info as\n");
1493 vty_out(vty
, " router-info area\n");
1495 if (OspfRI
.pce_info
.enabled
) {
1497 if (pce
->pce_address
.header
.type
!= 0)
1498 vty_out(vty
, " pce address %s\n",
1499 inet_ntoa(pce
->pce_address
.address
.value
));
1501 if (pce
->pce_cap_flag
.header
.type
!= 0)
1502 vty_out(vty
, " pce flag 0x%x\n",
1503 ntohl(pce
->pce_cap_flag
.value
));
1505 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
1506 if (domain
->header
.type
!= 0) {
1507 if (domain
->type
== PCE_DOMAIN_TYPE_AREA
) {
1508 tmp
.s_addr
= domain
->value
;
1509 vty_out(vty
, " pce domain area %s\n",
1512 vty_out(vty
, " pce domain as %d\n",
1513 ntohl(domain
->value
));
1518 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
1519 if (neighbor
->header
.type
!= 0) {
1520 if (neighbor
->type
== PCE_DOMAIN_TYPE_AREA
) {
1521 tmp
.s_addr
= neighbor
->value
;
1522 vty_out(vty
, " pce neighbor area %s\n",
1525 vty_out(vty
, " pce neighbor as %d\n",
1526 ntohl(neighbor
->value
));
1531 if (pce
->pce_scope
.header
.type
!= 0)
1532 vty_out(vty
, " pce scope 0x%x\n",
1533 ntohl(OspfRI
.pce_info
.pce_scope
.value
));
1538 /*------------------------------------------------------------------------*
1539 * Followings are vty command functions.
1540 *------------------------------------------------------------------------*/
1541 /* Simple wrapper schedule RI LSA action in function of the scope */
1542 static void ospf_router_info_schedule(enum lsa_opcode opcode
)
1544 struct listnode
*node
, *nnode
;
1545 struct ospf_ri_area_info
*ai
;
1547 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
) {
1548 if (CHECK_FLAG(OspfRI
.as_flags
, RIFLG_LSA_ENGAGED
))
1549 ospf_router_info_lsa_schedule(NULL
, opcode
);
1550 else if (opcode
== REORIGINATE_THIS_LSA
)
1551 ospf_router_info_lsa_schedule(NULL
, opcode
);
1553 for (ALL_LIST_ELEMENTS(OspfRI
.area_info
, node
, nnode
, ai
)) {
1554 if (CHECK_FLAG(ai
->flags
, RIFLG_LSA_ENGAGED
))
1555 ospf_router_info_lsa_schedule(ai
, opcode
);
1561 router_info_area_cmd
,
1562 "router-info <as|area [A.B.C.D]>",
1564 "Enable the Router Information functionality with AS flooding scope\n"
1565 "Enable the Router Information functionality with Area flooding scope\n"
1566 "OSPF area ID in IP format (deprecated)\n")
1574 /* Check and get Area value if present */
1575 if (strncmp(argv
[idx_mode
]->arg
, "as", 2) == 0)
1576 scope
= OSPF_OPAQUE_AS_LSA
;
1578 scope
= OSPF_OPAQUE_AREA_LSA
;
1580 /* First start to register Router Information callbacks */
1581 if (!OspfRI
.registered
&& (ospf_router_info_register(scope
)) != 0) {
1583 "%% Unable to register Router Information callbacks.");
1586 "RI (%s): Unable to register Router Information callbacks. Abort!",
1588 return CMD_WARNING_CONFIG_FAILED
;
1591 OspfRI
.enabled
= true;
1593 if (IS_DEBUG_OSPF_EVENT
)
1594 zlog_debug("RI-> Router Information (%s flooding): OFF -> ON",
1595 OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
? "Area"
1599 * Following code is intended to handle two cases;
1601 * 1) Router Information was disabled at startup time, but now become
1603 * 2) Router Information was once enabled then disabled, and now enabled
1607 initialize_params(&OspfRI
);
1609 /* Originate or Refresh RI LSA if already engaged */
1610 ospf_router_info_schedule(REORIGINATE_THIS_LSA
);
1615 DEFUN (no_router_info
,
1619 "Disable the Router Information functionality\n")
1622 if (!OspfRI
.enabled
)
1625 if (IS_DEBUG_OSPF_EVENT
)
1626 zlog_debug("RI-> Router Information: ON -> OFF");
1628 ospf_router_info_schedule(FLUSH_THIS_LSA
);
1630 OspfRI
.enabled
= false;
1635 static int ospf_ri_enabled(struct vty
*vty
)
1641 vty_out(vty
, "%% OSPF RI is not turned on\n");
1648 "pce address A.B.C.D",
1650 "Stable IP address of the PCE\n"
1651 "PCE address in IPv4 address format\n")
1654 struct in_addr value
;
1655 struct ospf_pce_info
*pi
= &OspfRI
.pce_info
;
1657 if (!ospf_ri_enabled(vty
))
1658 return CMD_WARNING_CONFIG_FAILED
;
1660 if (!inet_aton(argv
[idx_ipv4
]->arg
, &value
)) {
1661 vty_out(vty
, "Please specify PCE Address by A.B.C.D\n");
1662 return CMD_WARNING_CONFIG_FAILED
;
1665 if (ntohs(pi
->pce_address
.header
.type
) == 0
1666 || ntohl(pi
->pce_address
.address
.value
.s_addr
)
1667 != ntohl(value
.s_addr
)) {
1669 set_pce_address(value
, pi
);
1671 /* Refresh RI LSA if already engaged */
1672 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1678 DEFUN (no_pce_address
,
1680 "no pce address [A.B.C.D]",
1683 "Disable PCE address\n"
1684 "PCE address in IPv4 address format\n")
1687 unset_param(&OspfRI
.pce_info
.pce_address
);
1689 /* Refresh RI LSA if already engaged */
1690 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1695 DEFUN (pce_path_scope
,
1697 "pce scope BITPATTERN",
1699 "Path scope visibilities of the PCE for path computation\n"
1700 "32-bit Hexadecimal value\n")
1702 int idx_bitpattern
= 2;
1704 struct ospf_pce_info
*pi
= &OspfRI
.pce_info
;
1706 if (!ospf_ri_enabled(vty
))
1707 return CMD_WARNING_CONFIG_FAILED
;
1709 if (sscanf(argv
[idx_bitpattern
]->arg
, "0x%x", &scope
) != 1) {
1710 vty_out(vty
, "pce_path_scope: fscanf: %s\n",
1711 safe_strerror(errno
));
1712 return CMD_WARNING_CONFIG_FAILED
;
1715 if (ntohl(pi
->pce_scope
.header
.type
) == 0
1716 || scope
!= pi
->pce_scope
.value
) {
1717 set_pce_path_scope(scope
, pi
);
1719 /* Refresh RI LSA if already engaged */
1720 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1726 DEFUN (no_pce_path_scope
,
1727 no_pce_path_scope_cmd
,
1728 "no pce scope [BITPATTERN]",
1731 "Disable PCE path scope\n"
1732 "32-bit Hexadecimal value\n")
1735 unset_param(&OspfRI
.pce_info
.pce_address
);
1737 /* Refresh RI LSA if already engaged */
1738 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1745 "pce domain as (0-65535)",
1747 "Configure PCE domain AS number\n"
1748 "AS number where the PCE as visibilities for path computation\n"
1749 "AS number in decimal <0-65535>\n")
1754 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1755 struct listnode
*node
;
1756 struct ri_pce_subtlv_domain
*domain
;
1758 if (!ospf_ri_enabled(vty
))
1759 return CMD_WARNING_CONFIG_FAILED
;
1761 if (sscanf(argv
[idx_number
]->arg
, "%" SCNu32
, &as
) != 1) {
1762 vty_out(vty
, "pce_domain: fscanf: %s\n", safe_strerror(errno
));
1763 return CMD_WARNING_CONFIG_FAILED
;
1766 /* Check if the domain is not already in the domain list */
1767 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
1768 if (ntohl(domain
->header
.type
) == 0 && as
== domain
->value
)
1772 /* Create new domain if not found */
1773 set_pce_domain(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1775 /* Refresh RI LSA if already engaged */
1776 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1781 DEFUN (no_pce_domain
,
1783 "no pce domain as (0-65535)",
1786 "Disable PCE domain AS number\n"
1787 "AS number where the PCE as visibilities for path computation\n"
1788 "AS number in decimal <0-65535>\n")
1793 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1795 if (sscanf(argv
[idx_number
]->arg
, "%" SCNu32
, &as
) != 1) {
1796 vty_out(vty
, "no_pce_domain: fscanf: %s\n",
1797 safe_strerror(errno
));
1798 return CMD_WARNING_CONFIG_FAILED
;
1801 /* Unset corresponding PCE domain */
1802 unset_pce_domain(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1804 /* Refresh RI LSA if already engaged */
1805 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1810 DEFUN (pce_neigbhor
,
1812 "pce neighbor as (0-65535)",
1814 "Configure PCE neighbor domain AS number\n"
1815 "AS number of PCE neighbors\n"
1816 "AS number in decimal <0-65535>\n")
1821 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1822 struct listnode
*node
;
1823 struct ri_pce_subtlv_neighbor
*neighbor
;
1825 if (!ospf_ri_enabled(vty
))
1826 return CMD_WARNING_CONFIG_FAILED
;
1828 if (sscanf(argv
[idx_number
]->arg
, "%" SCNu32
, &as
) != 1) {
1829 vty_out(vty
, "pce_neighbor: fscanf: %s\n",
1830 safe_strerror(errno
));
1831 return CMD_WARNING_CONFIG_FAILED
;
1834 /* Check if the domain is not already in the domain list */
1835 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
1836 if (ntohl(neighbor
->header
.type
) == 0 && as
== neighbor
->value
)
1840 /* Create new domain if not found */
1841 set_pce_neighbor(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1843 /* Refresh RI LSA if already engaged */
1844 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1849 DEFUN (no_pce_neighbor
,
1850 no_pce_neighbor_cmd
,
1851 "no pce neighbor as (0-65535)",
1854 "Disable PCE neighbor AS number\n"
1855 "AS number of PCE neighbor\n"
1856 "AS number in decimal <0-65535>\n")
1861 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1863 if (sscanf(argv
[idx_number
]->arg
, "%" SCNu32
, &as
) != 1) {
1864 vty_out(vty
, "no_pce_neighbor: fscanf: %s\n",
1865 safe_strerror(errno
));
1866 return CMD_WARNING_CONFIG_FAILED
;
1869 /* Unset corresponding PCE domain */
1870 unset_pce_neighbor(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1872 /* Refresh RI LSA if already engaged */
1873 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1878 DEFUN (pce_cap_flag
,
1880 "pce flag BITPATTERN",
1882 "Capabilities of the PCE for path computation\n"
1883 "32-bit Hexadecimal value\n")
1885 int idx_bitpattern
= 2;
1888 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1890 if (!ospf_ri_enabled(vty
))
1891 return CMD_WARNING_CONFIG_FAILED
;
1893 if (sscanf(argv
[idx_bitpattern
]->arg
, "0x%x", &cap
) != 1) {
1894 vty_out(vty
, "pce_cap_flag: fscanf: %s\n",
1895 safe_strerror(errno
));
1896 return CMD_WARNING_CONFIG_FAILED
;
1899 if (ntohl(pce
->pce_cap_flag
.header
.type
) == 0
1900 || cap
!= pce
->pce_cap_flag
.value
) {
1901 set_pce_cap_flag(cap
, pce
);
1903 /* Refresh RI LSA if already engaged */
1904 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1910 DEFUN (no_pce_cap_flag
,
1911 no_pce_cap_flag_cmd
,
1915 "Disable PCE capabilities\n")
1918 unset_param(&OspfRI
.pce_info
.pce_cap_flag
);
1920 /* Refresh RI LSA if already engaged */
1921 ospf_router_info_schedule(REFRESH_THIS_LSA
);
1926 DEFUN (show_ip_ospf_router_info
,
1927 show_ip_ospf_router_info_cmd
,
1928 "show ip ospf router-info",
1932 "Router Information\n")
1935 if (OspfRI
.enabled
) {
1936 vty_out(vty
, "--- Router Information parameters ---\n");
1937 show_vty_router_cap(vty
, &OspfRI
.router_cap
.header
);
1941 " Router Information is disabled on this router\n");
1946 DEFUN (show_ip_opsf_router_info_pce
,
1947 show_ip_ospf_router_info_pce_cmd
,
1948 "show ip ospf router-info pce",
1952 "Router Information\n"
1953 "PCE information\n")
1956 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1957 struct listnode
*node
;
1958 struct ri_pce_subtlv_domain
*domain
;
1959 struct ri_pce_subtlv_neighbor
*neighbor
;
1961 if ((OspfRI
.enabled
) && (OspfRI
.pce_info
.enabled
)) {
1962 vty_out(vty
, "--- PCE parameters ---\n");
1964 if (pce
->pce_address
.header
.type
!= 0)
1965 show_vty_pce_subtlv_address(vty
,
1966 &pce
->pce_address
.header
);
1968 if (pce
->pce_scope
.header
.type
!= 0)
1969 show_vty_pce_subtlv_path_scope(vty
,
1970 &pce
->pce_scope
.header
);
1972 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
1973 if (domain
->header
.type
!= 0)
1974 show_vty_pce_subtlv_domain(vty
,
1978 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
1979 if (neighbor
->header
.type
!= 0)
1980 show_vty_pce_subtlv_neighbor(vty
,
1984 if (pce
->pce_cap_flag
.header
.type
!= 0)
1985 show_vty_pce_subtlv_cap_flag(vty
,
1986 &pce
->pce_cap_flag
.header
);
1989 vty_out(vty
, " PCE info is disabled on this router\n");
1995 /* Install new CLI commands */
1996 static void ospf_router_info_register_vty(void)
1998 install_element(VIEW_NODE
, &show_ip_ospf_router_info_cmd
);
1999 install_element(VIEW_NODE
, &show_ip_ospf_router_info_pce_cmd
);
2001 install_element(OSPF_NODE
, &router_info_area_cmd
);
2002 install_element(OSPF_NODE
, &no_router_info_cmd
);
2003 install_element(OSPF_NODE
, &pce_address_cmd
);
2004 install_element(OSPF_NODE
, &no_pce_address_cmd
);
2005 install_element(OSPF_NODE
, &pce_path_scope_cmd
);
2006 install_element(OSPF_NODE
, &no_pce_path_scope_cmd
);
2007 install_element(OSPF_NODE
, &pce_domain_cmd
);
2008 install_element(OSPF_NODE
, &no_pce_domain_cmd
);
2009 install_element(OSPF_NODE
, &pce_neighbor_cmd
);
2010 install_element(OSPF_NODE
, &no_pce_neighbor_cmd
);
2011 install_element(OSPF_NODE
, &pce_cap_flag_cmd
);
2012 install_element(OSPF_NODE
, &no_pce_cap_flag_cmd
);