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"
62 /* Store Router Information PCE TLV and SubTLV in network byte order. */
63 struct ospf_pce_info
{
65 struct ri_tlv_pce pce_header
;
66 struct ri_pce_subtlv_address pce_address
;
67 struct ri_pce_subtlv_path_scope pce_scope
;
68 struct list
*pce_domain
;
69 struct list
*pce_neighbor
;
70 struct ri_pce_subtlv_cap_flag pce_cap_flag
;
74 * Store Router Information Segment Routing TLV and SubTLV
75 * in network byte order
77 struct ospf_ri_sr_info
{
79 /* Algorithms supported by the node */
80 struct ri_sr_tlv_sr_algorithm algo
;
82 * Segment Routing Global Block i.e. label range
83 * Only one range supported in this code
85 struct ri_sr_tlv_sid_label_range range
;
86 /* Maximum SID Depth supported by the node */
87 struct ri_sr_tlv_node_msd msd
;
90 /* Following structure are internal use only. */
91 struct ospf_router_info
{
97 /* Flags to manage this router information. */
98 #define RIFLG_LSA_ENGAGED 0x1
99 #define RIFLG_LSA_FORCED_REFRESH 0x2
102 /* area pointer if flooding is Type 10 Null if flooding is AS scope */
103 struct ospf_area
*area
;
104 struct in_addr area_id
;
106 /* Store Router Information Capabilities LSA */
107 struct ri_tlv_router_cap router_cap
;
109 /* Store PCE capability LSA */
110 struct ospf_pce_info pce_info
;
112 /* Store SR capability LSA */
113 struct ospf_ri_sr_info sr_info
;
117 * Global variable to manage Opaque-LSA/Router Information on this node.
118 * Note that all parameter values are stored in network byte order.
120 static struct ospf_router_info OspfRI
;
122 /*------------------------------------------------------------------------------*
123 * Followings are initialize/terminate functions for Router Information
125 *------------------------------------------------------------------------------*/
127 static void ospf_router_info_ism_change(struct ospf_interface
*oi
,
129 static void ospf_router_info_nsm_change(struct ospf_neighbor
*nbr
,
131 static void ospf_router_info_config_write_router(struct vty
*vty
);
132 static void ospf_router_info_show_info(struct vty
*vty
, struct ospf_lsa
*lsa
);
133 static int ospf_router_info_lsa_originate(void *arg
);
134 static struct ospf_lsa
*ospf_router_info_lsa_refresh(struct ospf_lsa
*lsa
);
135 static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode
);
136 static void ospf_router_info_register_vty(void);
137 static int ospf_router_info_lsa_update(struct ospf_lsa
*lsa
);
138 static void del_pce_info(void *val
);
140 int ospf_router_info_init(void)
143 zlog_info("RI -> Initialize Router Information");
145 memset(&OspfRI
, 0, sizeof(struct ospf_router_info
));
146 OspfRI
.enabled
= false;
147 OspfRI
.registered
= 0;
148 OspfRI
.scope
= OSPF_OPAQUE_AS_LSA
;
149 OspfRI
.area_id
.s_addr
= 0;
152 /* Initialize pce domain and neighbor list */
153 OspfRI
.pce_info
.enabled
= false;
154 OspfRI
.pce_info
.pce_domain
= list_new();
155 OspfRI
.pce_info
.pce_domain
->del
= del_pce_info
;
156 OspfRI
.pce_info
.pce_neighbor
= list_new();
157 OspfRI
.pce_info
.pce_neighbor
->del
= del_pce_info
;
159 /* Initialize Segment Routing information structure */
160 OspfRI
.sr_info
.enabled
= false;
162 ospf_router_info_register_vty();
167 static int ospf_router_info_register(uint8_t scope
)
171 if (OspfRI
.registered
)
174 zlog_info("RI -> Register Router Information with scope %s(%d)",
175 scope
== OSPF_OPAQUE_AREA_LSA
? "Area" : "AS", scope
);
176 rc
= ospf_register_opaque_functab(
177 scope
, OPAQUE_TYPE_ROUTER_INFORMATION_LSA
,
178 NULL
, /* new interface */
179 NULL
, /* del interface */
180 ospf_router_info_ism_change
, ospf_router_info_nsm_change
,
181 ospf_router_info_config_write_router
,
182 NULL
, /* Config. write interface */
183 NULL
, /* Config. write debug */
184 ospf_router_info_show_info
, ospf_router_info_lsa_originate
,
185 ospf_router_info_lsa_refresh
, ospf_router_info_lsa_update
,
186 NULL
); /* del_lsa_hook */
190 EC_OSPF_OPAQUE_REGISTRATION
,
191 "ospf_router_info_init: Failed to register functions");
195 OspfRI
.registered
= 1;
196 OspfRI
.scope
= scope
;
200 static int ospf_router_info_unregister()
203 if ((OspfRI
.scope
!= OSPF_OPAQUE_AS_LSA
)
204 && (OspfRI
.scope
!= OSPF_OPAQUE_AREA_LSA
)) {
205 assert("Unable to unregister Router Info functions: Wrong scope!"
210 ospf_delete_opaque_functab(OspfRI
.scope
,
211 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
213 OspfRI
.registered
= 0;
217 void ospf_router_info_term(void)
220 list_delete(&OspfRI
.pce_info
.pce_domain
);
221 list_delete(&OspfRI
.pce_info
.pce_neighbor
);
223 OspfRI
.enabled
= false;
225 ospf_router_info_unregister();
230 void ospf_router_info_finish(void)
232 list_delete_all_node(OspfRI
.pce_info
.pce_domain
);
233 list_delete_all_node(OspfRI
.pce_info
.pce_neighbor
);
235 OspfRI
.enabled
= false;
238 static void del_pce_info(void *val
)
240 XFREE(MTYPE_OSPF_PCE_PARAMS
, val
);
244 /* Catch RI LSA flooding Scope for ospf_ext.[h,c] code */
245 struct scope_info
ospf_router_info_get_flooding_scope(void)
247 struct scope_info flooding_scope
;
249 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
) {
250 flooding_scope
.scope
= OSPF_OPAQUE_AS_LSA
;
251 flooding_scope
.area_id
.s_addr
= 0;
252 return flooding_scope
;
254 flooding_scope
.scope
= OSPF_OPAQUE_AREA_LSA
;
255 flooding_scope
.area_id
.s_addr
= OspfRI
.area_id
.s_addr
;
256 return flooding_scope
;
259 /*------------------------------------------------------------------------*
260 * Followings are control functions for ROUTER INFORMATION parameters
262 *------------------------------------------------------------------------*/
264 static void set_router_info_capabilities(struct ri_tlv_router_cap
*ric
,
267 ric
->header
.type
= htons(RI_TLV_CAPABILITIES
);
268 ric
->header
.length
= htons(RI_TLV_LENGTH
);
269 ric
->value
= htonl(cap
);
273 static int set_pce_header(struct ospf_pce_info
*pce
)
276 struct listnode
*node
;
277 struct ri_pce_subtlv_domain
*domain
;
278 struct ri_pce_subtlv_neighbor
*neighbor
;
281 if (ntohs(pce
->pce_address
.header
.type
) != 0)
282 length
+= TLV_SIZE(&pce
->pce_address
.header
);
285 if (ntohs(pce
->pce_scope
.header
.type
) != 0)
286 length
+= TLV_SIZE(&pce
->pce_scope
.header
);
289 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
290 if (ntohs(domain
->header
.type
) != 0)
291 length
+= TLV_SIZE(&domain
->header
);
295 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
296 if (ntohs(neighbor
->header
.type
) != 0)
297 length
+= TLV_SIZE(&neighbor
->header
);
300 /* PCE Capabilities */
301 if (ntohs(pce
->pce_cap_flag
.header
.type
) != 0)
302 length
+= TLV_SIZE(&pce
->pce_cap_flag
.header
);
305 pce
->pce_header
.header
.type
= htons(RI_TLV_PCE
);
306 pce
->pce_header
.header
.length
= htons(length
);
309 pce
->pce_header
.header
.type
= 0;
310 pce
->pce_header
.header
.length
= 0;
311 pce
->enabled
= false;
317 static void set_pce_address(struct in_addr ipv4
, struct ospf_pce_info
*pce
)
320 /* Enable PCE Info */
321 pce
->pce_header
.header
.type
= htons(RI_TLV_PCE
);
322 /* Set PCE Address */
323 pce
->pce_address
.header
.type
= htons(RI_PCE_SUBTLV_ADDRESS
);
324 pce
->pce_address
.header
.length
= htons(PCE_ADDRESS_LENGTH_IPV4
);
325 pce
->pce_address
.address
.type
= htons(PCE_ADDRESS_TYPE_IPV4
);
326 pce
->pce_address
.address
.value
= ipv4
;
331 static void set_pce_path_scope(uint32_t scope
, struct ospf_pce_info
*pce
)
335 pce
->pce_scope
.header
.type
= htons(RI_PCE_SUBTLV_PATH_SCOPE
);
336 pce
->pce_scope
.header
.length
= htons(RI_TLV_LENGTH
);
337 pce
->pce_scope
.value
= htonl(scope
);
342 static void set_pce_domain(uint16_t type
, uint32_t domain
,
343 struct ospf_pce_info
*pce
)
346 struct ri_pce_subtlv_domain
*new;
348 /* Create new domain info */
349 new = XCALLOC(MTYPE_OSPF_PCE_PARAMS
,
350 sizeof(struct ri_pce_subtlv_domain
));
352 new->header
.type
= htons(RI_PCE_SUBTLV_DOMAIN
);
353 new->header
.length
= htons(PCE_ADDRESS_LENGTH_IPV4
);
354 new->type
= htons(type
);
355 new->value
= htonl(domain
);
357 /* Add new domain to the list */
358 listnode_add(pce
->pce_domain
, new);
363 static void unset_pce_domain(uint16_t type
, uint32_t domain
,
364 struct ospf_pce_info
*pce
)
366 struct listnode
*node
;
367 struct ri_pce_subtlv_domain
*old
= NULL
;
370 /* Search the corresponding node */
371 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, old
)) {
372 if ((old
->type
== htons(type
))
373 && (old
->value
== htonl(domain
))) {
379 /* if found remove it */
381 listnode_delete(pce
->pce_domain
, old
);
383 /* Finally free the old domain */
384 XFREE(MTYPE_OSPF_PCE_PARAMS
, old
);
388 static void set_pce_neighbor(uint16_t type
, uint32_t domain
,
389 struct ospf_pce_info
*pce
)
392 struct ri_pce_subtlv_neighbor
*new;
394 /* Create new neighbor info */
395 new = XCALLOC(MTYPE_OSPF_PCE_PARAMS
,
396 sizeof(struct ri_pce_subtlv_neighbor
));
398 new->header
.type
= htons(RI_PCE_SUBTLV_NEIGHBOR
);
399 new->header
.length
= htons(PCE_ADDRESS_LENGTH_IPV4
);
400 new->type
= htons(type
);
401 new->value
= htonl(domain
);
403 /* Add new domain to the list */
404 listnode_add(pce
->pce_neighbor
, new);
409 static void unset_pce_neighbor(uint16_t type
, uint32_t domain
,
410 struct ospf_pce_info
*pce
)
412 struct listnode
*node
;
413 struct ri_pce_subtlv_neighbor
*old
= NULL
;
416 /* Search the corresponding node */
417 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, old
)) {
418 if ((old
->type
== htons(type
))
419 && (old
->value
== htonl(domain
))) {
425 /* if found remove it */
427 listnode_delete(pce
->pce_neighbor
, old
);
429 /* Finally free the old domain */
430 XFREE(MTYPE_OSPF_PCE_PARAMS
, old
);
434 static void set_pce_cap_flag(uint32_t cap
, struct ospf_pce_info
*pce
)
437 /* Set PCE Capabilities flag */
438 pce
->pce_cap_flag
.header
.type
= htons(RI_PCE_SUBTLV_CAP_FLAG
);
439 pce
->pce_cap_flag
.header
.length
= htons(RI_TLV_LENGTH
);
440 pce
->pce_cap_flag
.value
= htonl(cap
);
445 /* Segment Routing TLV setter */
447 /* Algorithm SubTLV - section 3.1 */
448 static void set_sr_algorithm(uint8_t algo
)
451 OspfRI
.sr_info
.algo
.value
[0] = algo
;
452 for (int i
= 1; i
< ALGORITHM_COUNT
; i
++)
453 OspfRI
.sr_info
.algo
.value
[i
] = SR_ALGORITHM_UNSET
;
455 /* Set TLV type and length == only 1 Algorithm */
456 TLV_TYPE(OspfRI
.sr_info
.algo
) = htons(RI_SR_TLV_SR_ALGORITHM
);
457 TLV_LEN(OspfRI
.sr_info
.algo
) = htons(sizeof(uint8_t));
460 /* unset Aglogithm SubTLV */
461 static void unset_sr_algorithm(uint8_t algo
)
464 for (int i
= 0; i
< ALGORITHM_COUNT
; i
++)
465 OspfRI
.sr_info
.algo
.value
[i
] = SR_ALGORITHM_UNSET
;
467 /* Unset TLV type and length */
468 TLV_TYPE(OspfRI
.sr_info
.algo
) = htons(0);
469 TLV_LEN(OspfRI
.sr_info
.algo
) = htons(0);
472 /* Segment Routing Global Block SubTLV - section 3.2 */
473 static void set_sr_sid_label_range(struct sr_srgb srgb
)
476 TLV_TYPE(OspfRI
.sr_info
.range
) = htons(RI_SR_TLV_SID_LABEL_RANGE
);
477 TLV_LEN(OspfRI
.sr_info
.range
) =
478 htons(SUBTLV_SID_LABEL_SIZE
+ sizeof(uint32_t));
480 OspfRI
.sr_info
.range
.size
= htonl(SET_RANGE_SIZE(srgb
.range_size
));
481 /* Set Lower bound label SubTLV */
482 TLV_TYPE(OspfRI
.sr_info
.range
.lower
) = htons(SUBTLV_SID_LABEL
);
483 TLV_LEN(OspfRI
.sr_info
.range
.lower
) = htons(SID_RANGE_LABEL_LENGTH
);
484 OspfRI
.sr_info
.range
.lower
.value
= htonl(SET_LABEL(srgb
.lower_bound
));
487 /* Unset this SRGB SubTLV */
488 static void unset_sr_sid_label_range(void)
491 TLV_TYPE(OspfRI
.sr_info
.range
) = htons(0);
492 TLV_LEN(OspfRI
.sr_info
.range
) = htons(0);
493 TLV_TYPE(OspfRI
.sr_info
.range
.lower
) = htons(0);
494 TLV_LEN(OspfRI
.sr_info
.range
.lower
) = htons(0);
497 /* Set Maximum Stack Depth for this router */
498 static void set_sr_node_msd(uint8_t msd
)
500 TLV_TYPE(OspfRI
.sr_info
.msd
) = htons(RI_SR_TLV_NODE_MSD
);
501 TLV_LEN(OspfRI
.sr_info
.msd
) = htons(sizeof(uint32_t));
502 OspfRI
.sr_info
.msd
.value
= msd
;
505 /* Unset this router MSD */
506 static void unset_sr_node_msd(void)
508 TLV_TYPE(OspfRI
.sr_info
.msd
) = htons(0);
509 TLV_LEN(OspfRI
.sr_info
.msd
) = htons(0);
512 static void unset_param(void *tlv_buffer
)
514 struct tlv_header
*tlv
= (struct tlv_header
*)tlv_buffer
;
517 /* Fill the Value to 0 */
518 memset(TLV_DATA(tlv_buffer
), 0, TLV_BODY_SIZE(tlv
));
524 static void initialize_params(struct ospf_router_info
*ori
)
530 * Initialize default Router Information Capabilities.
534 set_router_info_capabilities(&ori
->router_cap
, cap
);
536 /* If Area address is not null and exist, retrieve corresponding
538 top
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
539 zlog_info("RI-> Initialize Router Info for %s scope within area %s",
540 OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
? "Area" : "AS",
541 inet_ntoa(OspfRI
.area_id
));
543 /* Try to get the Area context at this step. Do it latter if not
545 if ((OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) && (OspfRI
.area
== NULL
))
546 OspfRI
.area
= ospf_area_lookup_by_area_id(top
, OspfRI
.area_id
);
549 * Initialize default PCE Information values
551 /* PCE address == OSPF Router ID */
552 set_pce_address(top
->router_id
, &ori
->pce_info
);
555 cap
= 7; /* Set L, R and Rd bits to one = intra & inter-area path
557 set_pce_path_scope(cap
, &ori
->pce_info
);
559 /* PCE Capabilities */
560 cap
= PCE_CAP_BIDIRECTIONAL
| PCE_CAP_DIVERSE_PATH
| PCE_CAP_OBJECTIVES
561 | PCE_CAP_ADDITIVE
| PCE_CAP_MULTIPLE_REQ
;
562 set_pce_cap_flag(cap
, &ori
->pce_info
);
567 static int is_mandated_params_set(struct ospf_router_info ori
)
571 if (ntohs(ori
.router_cap
.header
.type
) == 0)
574 if ((ntohs(ori
.pce_info
.pce_header
.header
.type
) == RI_TLV_PCE
)
575 && (ntohs(ori
.pce_info
.pce_address
.header
.type
) == 0)
576 && (ntohs(ori
.pce_info
.pce_cap_flag
.header
.type
) == 0))
579 if ((ori
.sr_info
.enabled
) && (ntohs(TLV_TYPE(ori
.sr_info
.algo
)) == 0)
580 && (ntohs(TLV_TYPE(ori
.sr_info
.range
)) == 0))
589 * Used by Segment Routing to set new TLVs and Sub-TLVs values
591 * @param enable To activate or not Segment Routing router Information flooding
592 * @param size Size of Label Range i.e. SRGB size
593 * @param lower Lower bound of the Label Range i.e. SRGB first label
594 * @param msd Maximum label Stack Depth suported by the router
598 void ospf_router_info_update_sr(bool enable
, struct sr_srgb srgb
, uint8_t msd
)
601 /* First activate and initialize Router Information is necessary */
602 if (!OspfRI
.enabled
) {
603 OspfRI
.enabled
= true;
604 initialize_params(&OspfRI
);
607 if (IS_DEBUG_OSPF_SR
)
608 zlog_debug("RI-> %s Routing Information for Segment Routing",
609 enable
? "Enable" : "Disable");
611 /* Unset or Set SR parameters */
613 unset_sr_algorithm(SR_ALGORITHM_SPF
);
614 unset_sr_sid_label_range();
616 OspfRI
.sr_info
.enabled
= false;
618 // Only SR_ALGORITHM_SPF is supported
619 set_sr_algorithm(SR_ALGORITHM_SPF
);
620 set_sr_sid_label_range(srgb
);
622 set_sr_node_msd(msd
);
625 OspfRI
.sr_info
.enabled
= true;
628 /* Refresh if already engaged or originate RI LSA */
629 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
630 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
632 ospf_router_info_lsa_schedule(REORIGINATE_THIS_LSA
);
635 /*------------------------------------------------------------------------*
636 * Followings are callback functions against generic Opaque-LSAs handling.
637 *------------------------------------------------------------------------*/
638 static void ospf_router_info_ism_change(struct ospf_interface
*oi
,
641 /* So far, nothing to do here. */
645 static void ospf_router_info_nsm_change(struct ospf_neighbor
*nbr
,
648 /* So far, nothing to do here. */
652 /*------------------------------------------------------------------------*
653 * Followings are OSPF protocol processing functions for ROUTER INFORMATION
654 *------------------------------------------------------------------------*/
656 static void build_tlv_header(struct stream
*s
, struct tlv_header
*tlvh
)
659 stream_put(s
, tlvh
, sizeof(struct tlv_header
));
663 static void build_tlv(struct stream
*s
, struct tlv_header
*tlvh
)
666 if (ntohs(tlvh
->type
) != 0) {
667 build_tlv_header(s
, tlvh
);
668 stream_put(s
, TLV_DATA(tlvh
), TLV_BODY_SIZE(tlvh
));
673 static void ospf_router_info_lsa_body_set(struct stream
*s
)
676 struct listnode
*node
;
677 struct ri_pce_subtlv_domain
*domain
;
678 struct ri_pce_subtlv_neighbor
*neighbor
;
680 /* Build Router Information TLV */
681 build_tlv(s
, &OspfRI
.router_cap
.header
);
683 /* Build Segment Routing TLVs if enabled */
684 if (OspfRI
.sr_info
.enabled
) {
685 /* Build Algorithm TLV */
686 build_tlv(s
, &TLV_HDR(OspfRI
.sr_info
.algo
));
688 build_tlv(s
, &TLV_HDR(OspfRI
.sr_info
.range
));
690 build_tlv(s
, &TLV_HDR(OspfRI
.sr_info
.msd
));
693 /* Add RI PCE TLV if it is set */
694 if (OspfRI
.pce_info
.enabled
) {
696 /* Compute PCE Info header first */
697 set_pce_header(&OspfRI
.pce_info
);
700 build_tlv_header(s
, &OspfRI
.pce_info
.pce_header
.header
);
702 /* Build PCE address sub-tlv */
703 build_tlv(s
, &OspfRI
.pce_info
.pce_address
.header
);
705 /* Build PCE path scope sub-tlv */
706 build_tlv(s
, &OspfRI
.pce_info
.pce_scope
.header
);
708 /* Build PCE domain sub-tlv */
709 for (ALL_LIST_ELEMENTS_RO(OspfRI
.pce_info
.pce_domain
, node
,
711 build_tlv(s
, &domain
->header
);
713 /* Build PCE neighbor sub-tlv */
714 for (ALL_LIST_ELEMENTS_RO(OspfRI
.pce_info
.pce_neighbor
, node
,
716 build_tlv(s
, &neighbor
->header
);
718 /* Build PCE cap flag sub-tlv */
719 build_tlv(s
, &OspfRI
.pce_info
.pce_cap_flag
.header
);
725 /* Create new opaque-LSA. */
726 static struct ospf_lsa
*ospf_router_info_lsa_new()
730 struct lsa_header
*lsah
;
731 struct ospf_lsa
*new = NULL
;
732 uint8_t options
, lsa_type
;
733 struct in_addr lsa_id
;
737 /* Create a stream for LSA. */
738 s
= stream_new(OSPF_MAX_LSA_SIZE
);
740 lsah
= (struct lsa_header
*)STREAM_DATA(s
);
742 options
= OSPF_OPTION_E
; /* Enable AS external as we flood RI with
744 options
|= OSPF_OPTION_O
; /* Don't forget this :-) */
746 lsa_type
= OspfRI
.scope
;
747 /* LSA ID == 0 for Router Information see RFC 4970 */
748 tmp
= SET_OPAQUE_LSID(OPAQUE_TYPE_ROUTER_INFORMATION_LSA
, 0);
749 lsa_id
.s_addr
= htonl(tmp
);
751 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
))
753 "LSA[Type%d:%s]: Create an Opaque-LSA/ROUTER INFORMATION instance",
754 lsa_type
, inet_ntoa(lsa_id
));
756 top
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
758 /* Set opaque-LSA header fields. */
759 lsa_header_set(s
, options
, lsa_type
, lsa_id
, top
->router_id
);
761 /* Set opaque-LSA body fields. */
762 ospf_router_info_lsa_body_set(s
);
765 length
= stream_get_endp(s
);
766 lsah
->length
= htons(length
);
768 /* Now, create an OSPF LSA instance. */
769 new = ospf_lsa_new_and_data(length
);
771 new->area
= OspfRI
.area
; /* Area must be null if the Opaque type is AS
772 scope, fulfill otherwise */
774 if (new->area
&& new->area
->ospf
)
775 new->vrf_id
= new->area
->ospf
->vrf_id
;
777 new->vrf_id
= VRF_DEFAULT
;
779 SET_FLAG(new->flags
, OSPF_LSA_SELF
);
780 memcpy(new->data
, lsah
, length
);
786 static int ospf_router_info_lsa_originate1(void *arg
)
788 struct ospf_lsa
*new;
790 struct ospf_area
*area
;
792 vrf_id_t vrf_id
= VRF_DEFAULT
;
794 /* First check if the area is known if flooding scope is Area */
795 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) {
796 area
= (struct ospf_area
*)arg
;
797 if (area
->area_id
.s_addr
!= OspfRI
.area_id
.s_addr
) {
799 "RI -> This is not the Router Information Area. Stop processing");
804 vrf_id
= area
->ospf
->vrf_id
;
807 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
808 new = ospf_router_info_lsa_new();
809 new->vrf_id
= vrf_id
;
812 top
= ospf_lookup_by_vrf_id(vrf_id
);
814 zlog_debug("%s: ospf instance not found for vrf id %u",
815 __PRETTY_FUNCTION__
, vrf_id
);
816 ospf_lsa_unlock(&new);
820 /* Install this LSA into LSDB. */
821 if (ospf_lsa_install(top
, NULL
/*oi */, new) == NULL
) {
823 EC_OSPF_LSA_INSTALL_FAILURE
,
824 "ospf_router_info_lsa_originate1: ospf_lsa_install() ?");
825 ospf_lsa_unlock(&new);
829 /* Now this Router Info parameter entry has associated LSA. */
830 SET_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
);
832 /* Update new LSA origination count. */
833 top
->lsa_originate_count
++;
835 /* Flood new LSA through AS. */
836 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
)
837 ospf_flood_through_as(top
, NULL
/*nbr */, new);
839 ospf_flood_through_area(OspfRI
.area
, NULL
/*nbr */, new);
841 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
843 "LSA[Type%d:%s]: Originate Opaque-LSA/ROUTER INFORMATION",
844 new->data
->type
, inet_ntoa(new->data
->id
));
845 ospf_lsa_header_dump(new->data
);
852 static int ospf_router_info_lsa_originate(void *arg
)
857 if (!OspfRI
.enabled
) {
859 "ospf_router_info_lsa_originate: ROUTER INFORMATION is disabled now.");
860 rc
= 0; /* This is not an error case. */
864 /* Check if Router Information LSA is already engaged */
865 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
)) {
866 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_FORCED_REFRESH
)) {
867 UNSET_FLAG(OspfRI
.flags
, RIFLG_LSA_FORCED_REFRESH
);
868 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
871 if (!is_mandated_params_set(OspfRI
))
874 "ospf_router_info_lsa_originate: lacks mandated ROUTER INFORMATION parameters");
876 /* Ok, let's try to originate an LSA */
877 if (ospf_router_info_lsa_originate1(arg
) != 0)
885 static struct ospf_lsa
*ospf_router_info_lsa_refresh(struct ospf_lsa
*lsa
)
887 struct ospf_lsa
*new = NULL
;
890 if (!OspfRI
.enabled
) {
892 * This LSA must have flushed before due to ROUTER INFORMATION
894 * It seems a slip among routers in the routing domain.
897 "ospf_router_info_lsa_refresh: ROUTER INFORMATION is disabled now.");
899 htons(OSPF_LSA_MAXAGE
); /* Flush it anyway. */
902 /* Verify that the Router Information ID is supported */
903 if (GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)) != 0) {
906 "ospf_router_info_lsa_refresh: Unsupported Router Information ID");
910 /* If the lsa's age reached to MaxAge, start flushing procedure. */
911 if (IS_LSA_MAXAGE(lsa
)) {
912 UNSET_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
);
913 ospf_opaque_lsa_flush_schedule(lsa
);
917 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
918 new = ospf_router_info_lsa_new();
919 new->data
->ls_seqnum
= lsa_seqnum_increment(lsa
);
920 new->vrf_id
= lsa
->vrf_id
;
922 /* Install this LSA into LSDB. */
923 /* Given "lsa" will be freed in the next function. */
924 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
925 if (ospf_lsa_install(top
, NULL
/*oi */, new) == NULL
) {
926 flog_warn(EC_OSPF_LSA_INSTALL_FAILURE
,
927 "ospf_router_info_lsa_refresh: ospf_lsa_install() ?");
928 ospf_lsa_unlock(&new);
932 /* Flood updated LSA through AS or AREA depending of OspfRI.scope. */
933 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
)
934 ospf_flood_through_as(top
, NULL
/*nbr */, new);
936 ospf_flood_through_area(OspfRI
.area
, NULL
/*nbr */, new);
939 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
941 "LSA[Type%d:%s]: Refresh Opaque-LSA/ROUTER INFORMATION",
942 new->data
->type
, inet_ntoa(new->data
->id
));
943 ospf_lsa_header_dump(new->data
);
949 static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode
)
952 struct lsa_header lsah
;
956 memset(&lsa
, 0, sizeof(lsa
));
957 memset(&lsah
, 0, sizeof(lsah
));
959 zlog_debug("RI-> LSA schedule %s%s%s",
960 opcode
== REORIGINATE_THIS_LSA
? "Re-Originate" : "",
961 opcode
== REFRESH_THIS_LSA
? "Refresh" : "",
962 opcode
== FLUSH_THIS_LSA
? "Flush" : "");
964 /* Check LSA flags state coherence */
965 if (!CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
)
966 && (opcode
!= REORIGINATE_THIS_LSA
))
969 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
)
970 && (opcode
== REORIGINATE_THIS_LSA
))
971 opcode
= REFRESH_THIS_LSA
;
973 top
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
974 if ((OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) && (OspfRI
.area
== NULL
)) {
977 "ospf_router_info_lsa_schedule(): Router Info is Area scope flooding but area is not set");
978 OspfRI
.area
= ospf_area_lookup_by_area_id(top
, OspfRI
.area_id
);
980 lsa
.area
= OspfRI
.area
;
982 lsah
.type
= OspfRI
.scope
;
984 /* LSA ID is set to 0 for the Router Information. See RFC 4970 */
985 tmp
= SET_OPAQUE_LSID(OPAQUE_TYPE_ROUTER_INFORMATION_LSA
, 0);
986 lsah
.id
.s_addr
= htonl(tmp
);
989 case REORIGINATE_THIS_LSA
:
990 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
)
991 ospf_opaque_lsa_reoriginate_schedule(
992 (void *)OspfRI
.area
, OSPF_OPAQUE_AREA_LSA
,
993 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
995 ospf_opaque_lsa_reoriginate_schedule(
996 (void *)top
, OSPF_OPAQUE_AS_LSA
,
997 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
999 case REFRESH_THIS_LSA
:
1000 ospf_opaque_lsa_refresh_schedule(&lsa
);
1002 case FLUSH_THIS_LSA
:
1003 UNSET_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
);
1004 ospf_opaque_lsa_flush_schedule(&lsa
);
1011 /* Callback to handle Segment Routing information */
1012 static int ospf_router_info_lsa_update(struct ospf_lsa
*lsa
)
1017 flog_warn(EC_OSPF_LSA
, "OSPF-RI (%s): Abort! LSA is NULL",
1022 /* Process only Opaque LSA */
1023 if ((lsa
->data
->type
!= OSPF_OPAQUE_AREA_LSA
)
1024 && (lsa
->data
->type
!= OSPF_OPAQUE_AS_LSA
))
1027 /* Process only Router Information LSA */
1028 if (GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
))
1029 != OPAQUE_TYPE_ROUTER_INFORMATION_LSA
)
1032 /* Check if it is not my LSA */
1033 if (IS_LSA_SELF(lsa
))
1036 /* Check if Router Info & Segment Routing are enable */
1037 if (!OspfRI
.enabled
|| !OspfRI
.sr_info
.enabled
)
1040 /* Call Segment Routing LSA update or deletion */
1041 if (!IS_LSA_MAXAGE(lsa
))
1042 ospf_sr_ri_lsa_update(lsa
);
1044 ospf_sr_ri_lsa_delete(lsa
);
1049 /*------------------------------------------------------------------------*
1050 * Followings are vty session control functions.
1051 *------------------------------------------------------------------------*/
1053 static uint16_t show_vty_router_cap(struct vty
*vty
, struct tlv_header
*tlvh
)
1055 struct ri_tlv_router_cap
*top
= (struct ri_tlv_router_cap
*)tlvh
;
1058 vty_out(vty
, " Router Capabilities: 0x%x\n",
1061 zlog_debug(" Router Capabilities: 0x%x", ntohl(top
->value
));
1063 return TLV_SIZE(tlvh
);
1066 static uint16_t show_vty_pce_subtlv_address(struct vty
*vty
,
1067 struct tlv_header
*tlvh
)
1069 struct ri_pce_subtlv_address
*top
=
1070 (struct ri_pce_subtlv_address
*)tlvh
;
1072 if (ntohs(top
->address
.type
) == PCE_ADDRESS_TYPE_IPV4
) {
1074 vty_out(vty
, " PCE Address: %s\n",
1075 inet_ntoa(top
->address
.value
));
1077 zlog_debug(" PCE Address: %s",
1078 inet_ntoa(top
->address
.value
));
1080 /* TODO: Add support to IPv6 with inet_ntop() */
1082 vty_out(vty
, " PCE Address: 0x%x\n",
1083 ntohl(top
->address
.value
.s_addr
));
1085 zlog_debug(" PCE Address: 0x%x",
1086 ntohl(top
->address
.value
.s_addr
));
1089 return TLV_SIZE(tlvh
);
1092 static uint16_t show_vty_pce_subtlv_path_scope(struct vty
*vty
,
1093 struct tlv_header
*tlvh
)
1095 struct ri_pce_subtlv_path_scope
*top
=
1096 (struct ri_pce_subtlv_path_scope
*)tlvh
;
1099 vty_out(vty
, " PCE Path Scope: 0x%x\n", ntohl(top
->value
));
1101 zlog_debug(" PCE Path Scope: 0x%x", ntohl(top
->value
));
1103 return TLV_SIZE(tlvh
);
1106 static uint16_t show_vty_pce_subtlv_domain(struct vty
*vty
,
1107 struct tlv_header
*tlvh
)
1109 struct ri_pce_subtlv_domain
*top
= (struct ri_pce_subtlv_domain
*)tlvh
;
1112 if (ntohs(top
->type
) == PCE_DOMAIN_TYPE_AREA
) {
1113 tmp
.s_addr
= top
->value
;
1115 vty_out(vty
, " PCE domain Area: %s\n", inet_ntoa(tmp
));
1117 zlog_debug(" PCE domain Area: %s", inet_ntoa(tmp
));
1120 vty_out(vty
, " PCE domain AS: %d\n",
1123 zlog_debug(" PCE domain AS: %d", ntohl(top
->value
));
1125 return TLV_SIZE(tlvh
);
1128 static uint16_t show_vty_pce_subtlv_neighbor(struct vty
*vty
,
1129 struct tlv_header
*tlvh
)
1132 struct ri_pce_subtlv_neighbor
*top
=
1133 (struct ri_pce_subtlv_neighbor
*)tlvh
;
1136 if (ntohs(top
->type
) == PCE_DOMAIN_TYPE_AREA
) {
1137 tmp
.s_addr
= top
->value
;
1139 vty_out(vty
, " PCE neighbor Area: %s\n",
1142 zlog_debug(" PCE neighbor Area: %s", inet_ntoa(tmp
));
1145 vty_out(vty
, " PCE neighbor AS: %d\n",
1148 zlog_debug(" PCE neighbor AS: %d",
1151 return TLV_SIZE(tlvh
);
1154 static uint16_t show_vty_pce_subtlv_cap_flag(struct vty
*vty
,
1155 struct tlv_header
*tlvh
)
1157 struct ri_pce_subtlv_cap_flag
*top
=
1158 (struct ri_pce_subtlv_cap_flag
*)tlvh
;
1161 vty_out(vty
, " PCE Capabilities Flag: 0x%x\n",
1164 zlog_debug(" PCE Capabilities Flag: 0x%x",
1167 return TLV_SIZE(tlvh
);
1170 static uint16_t show_vty_unknown_tlv(struct vty
*vty
, struct tlv_header
*tlvh
)
1173 vty_out(vty
, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
1174 ntohs(tlvh
->type
), ntohs(tlvh
->length
));
1176 zlog_debug(" Unknown TLV: [type(0x%x), length(0x%x)]",
1177 ntohs(tlvh
->type
), ntohs(tlvh
->length
));
1179 return TLV_SIZE(tlvh
);
1182 static uint16_t show_vty_pce_info(struct vty
*vty
, struct tlv_header
*ri
,
1185 struct tlv_header
*tlvh
;
1188 for (tlvh
= ri
; sum
< total
; tlvh
= TLV_HDR_NEXT(tlvh
)) {
1189 switch (ntohs(tlvh
->type
)) {
1190 case RI_PCE_SUBTLV_ADDRESS
:
1191 sum
+= show_vty_pce_subtlv_address(vty
, tlvh
);
1193 case RI_PCE_SUBTLV_PATH_SCOPE
:
1194 sum
+= show_vty_pce_subtlv_path_scope(vty
, tlvh
);
1196 case RI_PCE_SUBTLV_DOMAIN
:
1197 sum
+= show_vty_pce_subtlv_domain(vty
, tlvh
);
1199 case RI_PCE_SUBTLV_NEIGHBOR
:
1200 sum
+= show_vty_pce_subtlv_neighbor(vty
, tlvh
);
1202 case RI_PCE_SUBTLV_CAP_FLAG
:
1203 sum
+= show_vty_pce_subtlv_cap_flag(vty
, tlvh
);
1206 sum
+= show_vty_unknown_tlv(vty
, tlvh
);
1213 /* Display Segment Routing Algorithm TLV information */
1214 static uint16_t show_vty_sr_algorithm(struct vty
*vty
, struct tlv_header
*tlvh
)
1216 struct ri_sr_tlv_sr_algorithm
*algo
=
1217 (struct ri_sr_tlv_sr_algorithm
*)tlvh
;
1221 vty_out(vty
, " Segment Routing Algorithm TLV:\n");
1222 for (i
= 0; i
< ntohs(algo
->header
.length
); i
++) {
1223 switch (algo
->value
[i
]) {
1225 vty_out(vty
, " Algorithm %d: SPF\n", i
);
1228 vty_out(vty
, " Algorithm %d: Strict SPF\n",
1233 " Algorithm %d: Unknown value %d\n", i
,
1241 zlog_debug(" Segment Routing Algorithm TLV:\n");
1242 for (i
= 0; i
< ntohs(algo
->header
.length
); i
++)
1243 switch (algo
->value
[i
]) {
1245 zlog_debug(" Algorithm %d: SPF\n", i
);
1248 zlog_debug(" Algorithm %d: Strict SPF\n", i
);
1252 " Algorithm %d: Unknown value %d\n",
1258 return TLV_SIZE(tlvh
);
1261 /* Display Segment Routing SID/Label Range TLV information */
1262 static uint16_t show_vty_sr_range(struct vty
*vty
, struct tlv_header
*tlvh
)
1264 struct ri_sr_tlv_sid_label_range
*range
=
1265 (struct ri_sr_tlv_sid_label_range
*)tlvh
;
1269 " Segment Routing Range TLV:\n"
1270 " Range Size = %d\n"
1271 " SID Label = %d\n\n",
1272 GET_RANGE_SIZE(ntohl(range
->size
)),
1273 GET_LABEL(ntohl(range
->lower
.value
)));
1276 " Segment Routing Range TLV:\n"
1277 " Range Size = %d\n"
1278 " SID Label = %d\n\n",
1279 GET_RANGE_SIZE(ntohl(range
->size
)),
1280 GET_LABEL(ntohl(range
->lower
.value
)));
1283 return TLV_SIZE(tlvh
);
1286 /* Display Segment Routing Maximum Stack Depth TLV information */
1287 static uint16_t show_vty_sr_msd(struct vty
*vty
, struct tlv_header
*tlvh
)
1289 struct ri_sr_tlv_node_msd
*msd
= (struct ri_sr_tlv_node_msd
*)tlvh
;
1293 " Segment Routing MSD TLV:\n"
1294 " Node Maximum Stack Depth = %d\n",
1298 " Segment Routing MSD TLV:\n"
1299 " Node Maximum Stack Depth = %d\n",
1303 return TLV_SIZE(tlvh
);
1306 static void ospf_router_info_show_info(struct vty
*vty
, struct ospf_lsa
*lsa
)
1308 struct lsa_header
*lsah
= (struct lsa_header
*)lsa
->data
;
1309 struct tlv_header
*tlvh
;
1310 uint16_t length
= 0, sum
= 0;
1312 /* Initialize TLV browsing */
1313 length
= ntohs(lsah
->length
) - OSPF_LSA_HEADER_SIZE
;
1315 for (tlvh
= TLV_HDR_TOP(lsah
); sum
< length
;
1316 tlvh
= TLV_HDR_NEXT(tlvh
)) {
1317 switch (ntohs(tlvh
->type
)) {
1318 case RI_TLV_CAPABILITIES
:
1319 sum
+= show_vty_router_cap(vty
, tlvh
);
1323 sum
+= TLV_HDR_SIZE
;
1324 sum
+= show_vty_pce_info(vty
, tlvh
, length
- sum
);
1326 case RI_SR_TLV_SR_ALGORITHM
:
1327 sum
+= show_vty_sr_algorithm(vty
, tlvh
);
1329 case RI_SR_TLV_SID_LABEL_RANGE
:
1330 sum
+= show_vty_sr_range(vty
, tlvh
);
1332 case RI_SR_TLV_NODE_MSD
:
1333 sum
+= show_vty_sr_msd(vty
, tlvh
);
1337 sum
+= show_vty_unknown_tlv(vty
, tlvh
);
1345 static void ospf_router_info_config_write_router(struct vty
*vty
)
1347 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1348 struct listnode
*node
;
1349 struct ri_pce_subtlv_domain
*domain
;
1350 struct ri_pce_subtlv_neighbor
*neighbor
;
1353 if (!OspfRI
.enabled
)
1356 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
)
1357 vty_out(vty
, " router-info as\n");
1359 vty_out(vty
, " router-info area %s\n",
1360 inet_ntoa(OspfRI
.area_id
));
1362 if (OspfRI
.pce_info
.enabled
) {
1364 if (pce
->pce_address
.header
.type
!= 0)
1365 vty_out(vty
, " pce address %s\n",
1366 inet_ntoa(pce
->pce_address
.address
.value
));
1368 if (pce
->pce_cap_flag
.header
.type
!= 0)
1369 vty_out(vty
, " pce flag 0x%x\n",
1370 ntohl(pce
->pce_cap_flag
.value
));
1372 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
1373 if (domain
->header
.type
!= 0) {
1374 if (domain
->type
== PCE_DOMAIN_TYPE_AREA
) {
1375 tmp
.s_addr
= domain
->value
;
1376 vty_out(vty
, " pce domain area %s\n",
1379 vty_out(vty
, " pce domain as %d\n",
1380 ntohl(domain
->value
));
1385 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
1386 if (neighbor
->header
.type
!= 0) {
1387 if (neighbor
->type
== PCE_DOMAIN_TYPE_AREA
) {
1388 tmp
.s_addr
= neighbor
->value
;
1389 vty_out(vty
, " pce neighbor area %s\n",
1392 vty_out(vty
, " pce neighbor as %d\n",
1393 ntohl(neighbor
->value
));
1398 if (pce
->pce_scope
.header
.type
!= 0)
1399 vty_out(vty
, " pce scope 0x%x\n",
1400 ntohl(OspfRI
.pce_info
.pce_scope
.value
));
1405 /*------------------------------------------------------------------------*
1406 * Followings are vty command functions.
1407 *------------------------------------------------------------------------*/
1410 router_info_area_cmd
,
1411 "router-info <as|area A.B.C.D>",
1413 "Enable the Router Information functionality with AS flooding scope\n"
1414 "Enable the Router Information functionality with Area flooding scope\n"
1415 "OSPF area ID in IP format\n")
1418 char *area
= (argc
== 3) ? argv
[idx_ipv4
]->arg
: NULL
;
1425 /* Check and get Area value if present */
1427 if (!inet_aton(area
, &OspfRI
.area_id
)) {
1428 vty_out(vty
, "%% specified Area ID %s is invalid\n",
1430 return CMD_WARNING_CONFIG_FAILED
;
1432 scope
= OSPF_OPAQUE_AREA_LSA
;
1434 OspfRI
.area_id
.s_addr
= 0;
1435 scope
= OSPF_OPAQUE_AS_LSA
;
1438 /* First start to register Router Information callbacks */
1439 if ((ospf_router_info_register(scope
)) != 0) {
1441 "%% Unable to register Router Information callbacks.");
1444 "Unable to register Router Information callbacks. Abort!");
1445 return CMD_WARNING_CONFIG_FAILED
;
1448 OspfRI
.enabled
= true;
1450 if (IS_DEBUG_OSPF_EVENT
)
1451 zlog_debug("RI-> Router Information (%s flooding): OFF -> ON",
1452 OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
? "Area"
1456 * Following code is intended to handle two cases;
1458 * 1) Router Information was disabled at startup time, but now become
1460 * 2) Router Information was once enabled then disabled, and now enabled
1464 initialize_params(&OspfRI
);
1466 /* Refresh RI LSA if already engaged */
1467 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
)) {
1468 zlog_debug("RI-> Refresh LSA following configuration");
1469 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1471 zlog_debug("RI-> Initial origination following configuration");
1472 ospf_router_info_lsa_schedule(REORIGINATE_THIS_LSA
);
1478 DEFUN (no_router_info
,
1482 "Disable the Router Information functionality\n")
1485 if (!OspfRI
.enabled
)
1488 if (IS_DEBUG_OSPF_EVENT
)
1489 zlog_debug("RI-> Router Information: ON -> OFF");
1491 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1492 ospf_router_info_lsa_schedule(FLUSH_THIS_LSA
);
1494 OspfRI
.enabled
= false;
1499 static int ospf_ri_enabled(struct vty
*vty
)
1505 vty_out(vty
, "%% OSPF RI is not turned on\n");
1512 "pce address A.B.C.D",
1514 "Stable IP address of the PCE\n"
1515 "PCE address in IPv4 address format\n")
1518 struct in_addr value
;
1519 struct ospf_pce_info
*pi
= &OspfRI
.pce_info
;
1521 if (!ospf_ri_enabled(vty
))
1522 return CMD_WARNING_CONFIG_FAILED
;
1524 if (!inet_aton(argv
[idx_ipv4
]->arg
, &value
)) {
1525 vty_out(vty
, "Please specify PCE Address by A.B.C.D\n");
1526 return CMD_WARNING_CONFIG_FAILED
;
1529 if (ntohs(pi
->pce_address
.header
.type
) == 0
1530 || ntohl(pi
->pce_address
.address
.value
.s_addr
)
1531 != ntohl(value
.s_addr
)) {
1533 set_pce_address(value
, pi
);
1535 /* Refresh RI LSA if already engaged */
1536 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1537 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1543 DEFUN (no_pce_address
,
1545 "no pce address [A.B.C.D]",
1548 "Disable PCE address\n"
1549 "PCE address in IPv4 address format\n")
1552 unset_param(&OspfRI
.pce_info
.pce_address
);
1554 /* Refresh RI LSA if already engaged */
1555 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1556 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1561 DEFUN (pce_path_scope
,
1563 "pce scope BITPATTERN",
1565 "Path scope visibilities of the PCE for path computation\n"
1566 "32-bit Hexadecimal value\n")
1568 int idx_bitpattern
= 2;
1570 struct ospf_pce_info
*pi
= &OspfRI
.pce_info
;
1572 if (!ospf_ri_enabled(vty
))
1573 return CMD_WARNING_CONFIG_FAILED
;
1575 if (sscanf(argv
[idx_bitpattern
]->arg
, "0x%x", &scope
) != 1) {
1576 vty_out(vty
, "pce_path_scope: fscanf: %s\n",
1577 safe_strerror(errno
));
1578 return CMD_WARNING_CONFIG_FAILED
;
1581 if (ntohl(pi
->pce_scope
.header
.type
) == 0
1582 || scope
!= pi
->pce_scope
.value
) {
1583 set_pce_path_scope(scope
, pi
);
1585 /* Refresh RI LSA if already engaged */
1586 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1587 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1593 DEFUN (no_pce_path_scope
,
1594 no_pce_path_scope_cmd
,
1595 "no pce scope [BITPATTERN]",
1598 "Disable PCE path scope\n"
1599 "32-bit Hexadecimal value\n")
1602 unset_param(&OspfRI
.pce_info
.pce_address
);
1604 /* Refresh RI LSA if already engaged */
1605 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1606 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1613 "pce domain as (0-65535)",
1615 "Configure PCE domain AS number\n"
1616 "AS number where the PCE as visibilities for path computation\n"
1617 "AS number in decimal <0-65535>\n")
1622 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1623 struct listnode
*node
;
1624 struct ri_pce_subtlv_domain
*domain
;
1626 if (!ospf_ri_enabled(vty
))
1627 return CMD_WARNING_CONFIG_FAILED
;
1629 if (sscanf(argv
[idx_number
]->arg
, "%" SCNu32
, &as
) != 1) {
1630 vty_out(vty
, "pce_domain: fscanf: %s\n", safe_strerror(errno
));
1631 return CMD_WARNING_CONFIG_FAILED
;
1634 /* Check if the domain is not already in the domain list */
1635 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
1636 if (ntohl(domain
->header
.type
) == 0 && as
== domain
->value
)
1640 /* Create new domain if not found */
1641 set_pce_domain(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1643 /* Refresh RI LSA if already engaged */
1644 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1645 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1650 DEFUN (no_pce_domain
,
1652 "no pce domain as (0-65535)",
1655 "Disable PCE domain AS number\n"
1656 "AS number where the PCE as visibilities for path computation\n"
1657 "AS number in decimal <0-65535>\n")
1662 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1664 if (sscanf(argv
[idx_number
]->arg
, "%" SCNu32
, &as
) != 1) {
1665 vty_out(vty
, "no_pce_domain: fscanf: %s\n",
1666 safe_strerror(errno
));
1667 return CMD_WARNING_CONFIG_FAILED
;
1670 /* Unset corresponding PCE domain */
1671 unset_pce_domain(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1673 /* Refresh RI LSA if already engaged */
1674 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1675 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1680 DEFUN (pce_neigbhor
,
1682 "pce neighbor as (0-65535)",
1684 "Configure PCE neighbor domain AS number\n"
1685 "AS number of PCE neighbors\n"
1686 "AS number in decimal <0-65535>\n")
1691 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1692 struct listnode
*node
;
1693 struct ri_pce_subtlv_neighbor
*neighbor
;
1695 if (!ospf_ri_enabled(vty
))
1696 return CMD_WARNING_CONFIG_FAILED
;
1698 if (sscanf(argv
[idx_number
]->arg
, "%" SCNu32
, &as
) != 1) {
1699 vty_out(vty
, "pce_neighbor: fscanf: %s\n",
1700 safe_strerror(errno
));
1701 return CMD_WARNING_CONFIG_FAILED
;
1704 /* Check if the domain is not already in the domain list */
1705 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
1706 if (ntohl(neighbor
->header
.type
) == 0 && as
== neighbor
->value
)
1710 /* Create new domain if not found */
1711 set_pce_neighbor(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1713 /* Refresh RI LSA if already engaged */
1714 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1715 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1720 DEFUN (no_pce_neighbor
,
1721 no_pce_neighbor_cmd
,
1722 "no pce neighbor as (0-65535)",
1725 "Disable PCE neighbor AS number\n"
1726 "AS number of PCE neighbor\n"
1727 "AS number in decimal <0-65535>\n")
1732 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1734 if (sscanf(argv
[idx_number
]->arg
, "%" SCNu32
, &as
) != 1) {
1735 vty_out(vty
, "no_pce_neighbor: fscanf: %s\n",
1736 safe_strerror(errno
));
1737 return CMD_WARNING_CONFIG_FAILED
;
1740 /* Unset corresponding PCE domain */
1741 unset_pce_neighbor(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1743 /* Refresh RI LSA if already engaged */
1744 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1745 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1750 DEFUN (pce_cap_flag
,
1752 "pce flag BITPATTERN",
1754 "Capabilities of the PCE for path computation\n"
1755 "32-bit Hexadecimal value\n")
1757 int idx_bitpattern
= 2;
1760 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1762 if (!ospf_ri_enabled(vty
))
1763 return CMD_WARNING_CONFIG_FAILED
;
1765 if (sscanf(argv
[idx_bitpattern
]->arg
, "0x%x", &cap
) != 1) {
1766 vty_out(vty
, "pce_cap_flag: fscanf: %s\n",
1767 safe_strerror(errno
));
1768 return CMD_WARNING_CONFIG_FAILED
;
1771 if (ntohl(pce
->pce_cap_flag
.header
.type
) == 0
1772 || cap
!= pce
->pce_cap_flag
.value
) {
1773 set_pce_cap_flag(cap
, pce
);
1775 /* Refresh RI LSA if already engaged */
1776 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1777 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1783 DEFUN (no_pce_cap_flag
,
1784 no_pce_cap_flag_cmd
,
1788 "Disable PCE capabilities\n")
1791 unset_param(&OspfRI
.pce_info
.pce_cap_flag
);
1793 /* Refresh RI LSA if already engaged */
1794 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1795 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1800 DEFUN (show_ip_ospf_router_info
,
1801 show_ip_ospf_router_info_cmd
,
1802 "show ip ospf router-info",
1806 "Router Information\n")
1809 if (OspfRI
.enabled
) {
1810 vty_out(vty
, "--- Router Information parameters ---\n");
1811 show_vty_router_cap(vty
, &OspfRI
.router_cap
.header
);
1815 " Router Information is disabled on this router\n");
1820 DEFUN (show_ip_opsf_router_info_pce
,
1821 show_ip_ospf_router_info_pce_cmd
,
1822 "show ip ospf router-info pce",
1826 "Router Information\n"
1827 "PCE information\n")
1830 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1831 struct listnode
*node
;
1832 struct ri_pce_subtlv_domain
*domain
;
1833 struct ri_pce_subtlv_neighbor
*neighbor
;
1835 if ((OspfRI
.enabled
) && (OspfRI
.pce_info
.enabled
)) {
1836 vty_out(vty
, "--- PCE parameters ---\n");
1838 if (pce
->pce_address
.header
.type
!= 0)
1839 show_vty_pce_subtlv_address(vty
,
1840 &pce
->pce_address
.header
);
1842 if (pce
->pce_scope
.header
.type
!= 0)
1843 show_vty_pce_subtlv_path_scope(vty
,
1844 &pce
->pce_scope
.header
);
1846 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
1847 if (domain
->header
.type
!= 0)
1848 show_vty_pce_subtlv_domain(vty
,
1852 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
1853 if (neighbor
->header
.type
!= 0)
1854 show_vty_pce_subtlv_neighbor(vty
,
1858 if (pce
->pce_cap_flag
.header
.type
!= 0)
1859 show_vty_pce_subtlv_cap_flag(vty
,
1860 &pce
->pce_cap_flag
.header
);
1863 vty_out(vty
, " PCE info is disabled on this router\n");
1869 /* Install new CLI commands */
1870 static void ospf_router_info_register_vty(void)
1872 install_element(VIEW_NODE
, &show_ip_ospf_router_info_cmd
);
1873 install_element(VIEW_NODE
, &show_ip_ospf_router_info_pce_cmd
);
1875 install_element(OSPF_NODE
, &router_info_area_cmd
);
1876 install_element(OSPF_NODE
, &no_router_info_cmd
);
1877 install_element(OSPF_NODE
, &pce_address_cmd
);
1878 install_element(OSPF_NODE
, &no_pce_address_cmd
);
1879 install_element(OSPF_NODE
, &pce_path_scope_cmd
);
1880 install_element(OSPF_NODE
, &no_pce_path_scope_cmd
);
1881 install_element(OSPF_NODE
, &pce_domain_cmd
);
1882 install_element(OSPF_NODE
, &no_pce_domain_cmd
);
1883 install_element(OSPF_NODE
, &pce_neighbor_cmd
);
1884 install_element(OSPF_NODE
, &no_pce_neighbor_cmd
);
1885 install_element(OSPF_NODE
, &pce_cap_flag_cmd
);
1886 install_element(OSPF_NODE
, &no_pce_cap_flag_cmd
);