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"
61 /* Store Router Information PCE TLV and SubTLV in network byte order. */
62 struct ospf_pce_info
{
64 struct ri_tlv_pce pce_header
;
65 struct ri_pce_subtlv_address pce_address
;
66 struct ri_pce_subtlv_path_scope pce_scope
;
67 struct list
*pce_domain
;
68 struct list
*pce_neighbor
;
69 struct ri_pce_subtlv_cap_flag pce_cap_flag
;
73 * Store Router Information Segment Routing TLV and SubTLV
74 * in network byte order
76 struct ospf_ri_sr_info
{
78 /* Algorithms supported by the node */
79 struct ri_sr_tlv_sr_algorithm algo
;
81 * Segment Routing Global Block i.e. label range
82 * Only one range supported in this code
84 struct ri_sr_tlv_sid_label_range range
;
85 /* Maximum SID Depth supported by the node */
86 struct ri_sr_tlv_node_msd msd
;
89 /* Following structure are internal use only. */
90 struct ospf_router_info
{
96 /* Flags to manage this router information. */
97 #define RIFLG_LSA_ENGAGED 0x1
98 #define RIFLG_LSA_FORCED_REFRESH 0x2
101 /* area pointer if flooding is Type 10 Null if flooding is AS scope */
102 struct ospf_area
*area
;
103 struct in_addr area_id
;
105 /* Store Router Information Capabilities LSA */
106 struct ri_tlv_router_cap router_cap
;
108 /* Store PCE capability LSA */
109 struct ospf_pce_info pce_info
;
111 /* Store SR capability LSA */
112 struct ospf_ri_sr_info sr_info
;
116 * Global variable to manage Opaque-LSA/Router Information on this node.
117 * Note that all parameter values are stored in network byte order.
119 static struct ospf_router_info OspfRI
;
121 /*------------------------------------------------------------------------------*
122 * Followings are initialize/terminate functions for Router Information
124 *------------------------------------------------------------------------------*/
126 static void ospf_router_info_ism_change(struct ospf_interface
*oi
,
128 static void ospf_router_info_nsm_change(struct ospf_neighbor
*nbr
,
130 static void ospf_router_info_config_write_router(struct vty
*vty
);
131 static void ospf_router_info_show_info(struct vty
*vty
, struct ospf_lsa
*lsa
);
132 static int ospf_router_info_lsa_originate(void *arg
);
133 static struct ospf_lsa
*ospf_router_info_lsa_refresh(struct ospf_lsa
*lsa
);
134 static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode
);
135 static void ospf_router_info_register_vty(void);
136 static int ospf_router_info_lsa_update(struct ospf_lsa
*lsa
);
137 static void del_pce_info(void *val
);
139 int ospf_router_info_init(void)
142 zlog_info("RI -> Initialize Router Information");
144 memset(&OspfRI
, 0, sizeof(struct ospf_router_info
));
145 OspfRI
.enabled
= false;
146 OspfRI
.registered
= 0;
147 OspfRI
.scope
= OSPF_OPAQUE_AS_LSA
;
148 OspfRI
.area_id
.s_addr
= 0;
151 /* Initialize pce domain and neighbor list */
152 OspfRI
.pce_info
.enabled
= false;
153 OspfRI
.pce_info
.pce_domain
= list_new();
154 OspfRI
.pce_info
.pce_domain
->del
= del_pce_info
;
155 OspfRI
.pce_info
.pce_neighbor
= list_new();
156 OspfRI
.pce_info
.pce_neighbor
->del
= del_pce_info
;
158 /* Initialize Segment Routing information structure */
159 OspfRI
.sr_info
.enabled
= false;
161 ospf_router_info_register_vty();
166 static int ospf_router_info_register(u_int8_t scope
)
170 if (OspfRI
.registered
)
173 zlog_info("RI -> Register Router Information with scope %s(%d)",
174 scope
== OSPF_OPAQUE_AREA_LSA
? "Area" : "AS", scope
);
175 rc
= ospf_register_opaque_functab(
176 scope
, OPAQUE_TYPE_ROUTER_INFORMATION_LSA
,
177 NULL
, /* new interface */
178 NULL
, /* del interface */
179 ospf_router_info_ism_change
,
180 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
,
185 ospf_router_info_lsa_originate
,
186 ospf_router_info_lsa_refresh
,
187 ospf_router_info_lsa_update
,
188 NULL
); /* del_lsa_hook */
192 "ospf_router_info_init: Failed to register functions");
196 OspfRI
.registered
= 1;
197 OspfRI
.scope
= scope
;
201 static int ospf_router_info_unregister()
204 if ((OspfRI
.scope
!= OSPF_OPAQUE_AS_LSA
)
205 && (OspfRI
.scope
!= OSPF_OPAQUE_AREA_LSA
)) {
207 "Unable to unregister Router Info functions: Wrong scope!");
211 ospf_delete_opaque_functab(OspfRI
.scope
,
212 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
214 OspfRI
.registered
= 0;
218 void ospf_router_info_term(void)
221 list_delete_and_null(&OspfRI
.pce_info
.pce_domain
);
222 list_delete_and_null(&OspfRI
.pce_info
.pce_neighbor
);
224 OspfRI
.enabled
= false;
226 ospf_router_info_unregister();
231 void ospf_router_info_finish(void)
233 list_delete_all_node(OspfRI
.pce_info
.pce_domain
);
234 list_delete_all_node(OspfRI
.pce_info
.pce_neighbor
);
236 OspfRI
.enabled
= false;
239 static void del_pce_info(void *val
)
241 XFREE(MTYPE_OSPF_PCE_PARAMS
, val
);
245 /* Catch RI LSA flooding Scope for ospf_ext.[h,c] code */
246 struct scope_info
ospf_router_info_get_flooding_scope(void)
248 struct scope_info flooding_scope
;
250 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
) {
251 flooding_scope
.scope
= OSPF_OPAQUE_AS_LSA
;
252 flooding_scope
.area_id
.s_addr
= 0;
253 return flooding_scope
;
255 flooding_scope
.scope
= OSPF_OPAQUE_AREA_LSA
;
256 flooding_scope
.area_id
.s_addr
= OspfRI
.area_id
.s_addr
;
257 return flooding_scope
;
260 /*------------------------------------------------------------------------*
261 * Followings are control functions for ROUTER INFORMATION parameters
263 *------------------------------------------------------------------------*/
265 static void set_router_info_capabilities(struct ri_tlv_router_cap
*ric
,
268 ric
->header
.type
= htons(RI_TLV_CAPABILITIES
);
269 ric
->header
.length
= htons(RI_TLV_LENGTH
);
270 ric
->value
= htonl(cap
);
274 static int set_pce_header(struct ospf_pce_info
*pce
)
276 u_int16_t length
= 0;
277 struct listnode
*node
;
278 struct ri_pce_subtlv_domain
*domain
;
279 struct ri_pce_subtlv_neighbor
*neighbor
;
282 if (ntohs(pce
->pce_address
.header
.type
) != 0)
283 length
+= TLV_SIZE(&pce
->pce_address
.header
);
286 if (ntohs(pce
->pce_scope
.header
.type
) != 0)
287 length
+= TLV_SIZE(&pce
->pce_scope
.header
);
290 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
291 if (ntohs(domain
->header
.type
) != 0)
292 length
+= TLV_SIZE(&domain
->header
);
296 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
297 if (ntohs(neighbor
->header
.type
) != 0)
298 length
+= TLV_SIZE(&neighbor
->header
);
301 /* PCE Capabilities */
302 if (ntohs(pce
->pce_cap_flag
.header
.type
) != 0)
303 length
+= TLV_SIZE(&pce
->pce_cap_flag
.header
);
306 pce
->pce_header
.header
.type
= htons(RI_TLV_PCE
);
307 pce
->pce_header
.header
.length
= htons(length
);
310 pce
->pce_header
.header
.type
= 0;
311 pce
->pce_header
.header
.length
= 0;
312 pce
->enabled
= false;
318 static void set_pce_address(struct in_addr ipv4
, struct ospf_pce_info
*pce
)
321 /* Enable PCE Info */
322 pce
->pce_header
.header
.type
= htons(RI_TLV_PCE
);
323 /* Set PCE Address */
324 pce
->pce_address
.header
.type
= htons(RI_PCE_SUBTLV_ADDRESS
);
325 pce
->pce_address
.header
.length
= htons(PCE_ADDRESS_LENGTH_IPV4
);
326 pce
->pce_address
.address
.type
= htons(PCE_ADDRESS_TYPE_IPV4
);
327 pce
->pce_address
.address
.value
= ipv4
;
332 static void set_pce_path_scope(u_int32_t scope
, struct ospf_pce_info
*pce
)
336 pce
->pce_scope
.header
.type
= htons(RI_PCE_SUBTLV_PATH_SCOPE
);
337 pce
->pce_scope
.header
.length
= htons(RI_TLV_LENGTH
);
338 pce
->pce_scope
.value
= htonl(scope
);
343 static void set_pce_domain(u_int16_t type
, u_int32_t domain
,
344 struct ospf_pce_info
*pce
)
347 struct ri_pce_subtlv_domain
*new;
349 /* Create new domain info */
350 new = XCALLOC(MTYPE_OSPF_PCE_PARAMS
,
351 sizeof(struct ri_pce_subtlv_domain
));
353 new->header
.type
= htons(RI_PCE_SUBTLV_DOMAIN
);
354 new->header
.length
= htons(PCE_ADDRESS_LENGTH_IPV4
);
355 new->type
= htons(type
);
356 new->value
= htonl(domain
);
358 /* Add new domain to the list */
359 listnode_add(pce
->pce_domain
, new);
364 static void unset_pce_domain(u_int16_t type
, u_int32_t domain
,
365 struct ospf_pce_info
*pce
)
367 struct listnode
*node
;
368 struct ri_pce_subtlv_domain
*old
= NULL
;
371 /* Search the corresponding node */
372 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, old
)) {
373 if ((old
->type
== htons(type
))
374 && (old
->value
== htonl(domain
))) {
380 /* if found remove it */
382 listnode_delete(pce
->pce_domain
, old
);
384 /* Avoid misjudgement in the next lookup. */
385 if (listcount(pce
->pce_domain
) == 0)
386 pce
->pce_domain
->head
= pce
->pce_domain
->tail
= NULL
;
388 /* Finally free the old domain */
389 XFREE(MTYPE_OSPF_PCE_PARAMS
, old
);
393 static void set_pce_neighbor(u_int16_t type
, u_int32_t domain
,
394 struct ospf_pce_info
*pce
)
397 struct ri_pce_subtlv_neighbor
*new;
399 /* Create new neighbor info */
400 new = XCALLOC(MTYPE_OSPF_PCE_PARAMS
,
401 sizeof(struct ri_pce_subtlv_neighbor
));
403 new->header
.type
= htons(RI_PCE_SUBTLV_NEIGHBOR
);
404 new->header
.length
= htons(PCE_ADDRESS_LENGTH_IPV4
);
405 new->type
= htons(type
);
406 new->value
= htonl(domain
);
408 /* Add new domain to the list */
409 listnode_add(pce
->pce_neighbor
, new);
414 static void unset_pce_neighbor(u_int16_t type
, u_int32_t domain
,
415 struct ospf_pce_info
*pce
)
417 struct listnode
*node
;
418 struct ri_pce_subtlv_neighbor
*old
= NULL
;
421 /* Search the corresponding node */
422 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, old
)) {
423 if ((old
->type
== htons(type
))
424 && (old
->value
== htonl(domain
))) {
430 /* if found remove it */
432 listnode_delete(pce
->pce_neighbor
, old
);
434 /* Avoid misjudgement in the next lookup. */
435 if (listcount(pce
->pce_neighbor
) == 0)
436 pce
->pce_neighbor
->head
= pce
->pce_neighbor
->tail
=
439 /* Finally free the old domain */
440 XFREE(MTYPE_OSPF_PCE_PARAMS
, old
);
444 static void set_pce_cap_flag(u_int32_t cap
, struct ospf_pce_info
*pce
)
447 /* Set PCE Capabilities flag */
448 pce
->pce_cap_flag
.header
.type
= htons(RI_PCE_SUBTLV_CAP_FLAG
);
449 pce
->pce_cap_flag
.header
.length
= htons(RI_TLV_LENGTH
);
450 pce
->pce_cap_flag
.value
= htonl(cap
);
455 /* Segment Routing TLV setter */
457 /* Algorithm SubTLV - section 3.1 */
458 static void set_sr_algorithm(uint8_t algo
)
461 OspfRI
.sr_info
.algo
.value
[0] = algo
;
462 for (int i
= 1; i
< ALGORITHM_COUNT
; i
++)
463 OspfRI
.sr_info
.algo
.value
[i
] = SR_ALGORITHM_UNSET
;
465 /* Set TLV type and length == only 1 Algorithm */
466 TLV_TYPE(OspfRI
.sr_info
.algo
) = htons(RI_SR_TLV_SR_ALGORITHM
);
467 TLV_LEN(OspfRI
.sr_info
.algo
) = htons(sizeof(uint8_t));
471 /* unset Aglogithm SubTLV */
472 static void unset_sr_algorithm(uint8_t algo
)
475 for (int i
= 0; i
< ALGORITHM_COUNT
; i
++)
476 OspfRI
.sr_info
.algo
.value
[i
] = SR_ALGORITHM_UNSET
;
478 /* Unset TLV type and length */
479 TLV_TYPE(OspfRI
.sr_info
.algo
) = htons(0);
480 TLV_LEN(OspfRI
.sr_info
.algo
) = htons(0);
484 /* Segment Routing Global Block SubTLV - section 3.2 */
485 static void set_sr_sid_label_range(struct sr_srgb srgb
)
488 TLV_TYPE(OspfRI
.sr_info
.range
) = htons(RI_SR_TLV_SID_LABEL_RANGE
);
489 TLV_LEN(OspfRI
.sr_info
.range
) =
490 htons(SUBTLV_SID_LABEL_SIZE
+ sizeof(uint32_t));
492 OspfRI
.sr_info
.range
.size
= htonl(SET_RANGE_SIZE(srgb
.range_size
));
493 /* Set Lower bound label SubTLV */
494 TLV_TYPE(OspfRI
.sr_info
.range
.lower
) = htons(SUBTLV_SID_LABEL
);
495 TLV_LEN(OspfRI
.sr_info
.range
.lower
) = htons(SID_RANGE_LABEL_LENGTH
);
496 OspfRI
.sr_info
.range
.lower
.value
= htonl(SET_LABEL(srgb
.lower_bound
));
500 /* Unset this SRGB SubTLV */
501 static void unset_sr_sid_label_range(void)
504 TLV_TYPE(OspfRI
.sr_info
.range
) = htons(0);
505 TLV_LEN(OspfRI
.sr_info
.range
) = htons(0);
506 TLV_TYPE(OspfRI
.sr_info
.range
.lower
) = htons(0);
507 TLV_LEN(OspfRI
.sr_info
.range
.lower
) = htons(0);
511 /* Set Maximum Stack Depth for this router */
512 static void set_sr_node_msd(uint8_t msd
)
514 TLV_TYPE(OspfRI
.sr_info
.msd
) = htons(RI_SR_TLV_NODE_MSD
);
515 TLV_LEN(OspfRI
.sr_info
.msd
) = htons(sizeof(uint32_t));
516 OspfRI
.sr_info
.msd
.value
= msd
;
520 /* Unset this router MSD */
521 static void unset_sr_node_msd(void)
523 TLV_TYPE(OspfRI
.sr_info
.msd
) = htons(0);
524 TLV_LEN(OspfRI
.sr_info
.msd
) = htons(0);
528 static void unset_param(struct tlv_header
*tlv
)
532 /* Fill the Value to 0 */
533 memset(TLV_DATA(tlv
), 0, TLV_BODY_SIZE(tlv
));
539 static void initialize_params(struct ospf_router_info
*ori
)
545 * Initialize default Router Information Capabilities.
549 set_router_info_capabilities(&ori
->router_cap
, cap
);
551 /* If Area address is not null and exist, retrieve corresponding
553 top
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
554 zlog_info("RI-> Initialize Router Info for %s scope within area %s",
555 OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
? "Area" : "AS",
556 inet_ntoa(OspfRI
.area_id
));
558 /* Try to get the Area context at this step. Do it latter if not
560 if ((OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) && (OspfRI
.area
== NULL
))
561 OspfRI
.area
= ospf_area_lookup_by_area_id(top
, OspfRI
.area_id
);
564 * Initialize default PCE Information values
566 /* PCE address == OSPF Router ID */
567 set_pce_address(top
->router_id
, &ori
->pce_info
);
570 cap
= 7; /* Set L, R and Rd bits to one = intra & inter-area path
572 set_pce_path_scope(cap
, &ori
->pce_info
);
574 /* PCE Capabilities */
575 cap
= PCE_CAP_BIDIRECTIONAL
| PCE_CAP_DIVERSE_PATH
| PCE_CAP_OBJECTIVES
576 | PCE_CAP_ADDITIVE
| PCE_CAP_MULTIPLE_REQ
;
577 set_pce_cap_flag(cap
, &ori
->pce_info
);
582 static int is_mandated_params_set(struct ospf_router_info ori
)
586 if (ntohs(ori
.router_cap
.header
.type
) == 0)
589 if ((ntohs(ori
.pce_info
.pce_header
.header
.type
) == RI_TLV_PCE
)
590 && (ntohs(ori
.pce_info
.pce_address
.header
.type
) == 0)
591 && (ntohs(ori
.pce_info
.pce_cap_flag
.header
.type
) == 0))
594 if ((ori
.sr_info
.enabled
) && (ntohs(TLV_TYPE(ori
.sr_info
.algo
)) == 0)
595 && (ntohs(TLV_TYPE(ori
.sr_info
.range
)) == 0))
604 * Used by Segment Routing to set new TLVs and Sub-TLVs values
606 * @param enable To activate or not Segment Routing router Information flooding
607 * @param size Size of Label Range i.e. SRGB size
608 * @param lower Lower bound of the Label Range i.e. SRGB first label
609 * @param msd Maximum label Stack Depth suported by the router
613 void ospf_router_info_update_sr(bool enable
, struct sr_srgb srgb
, uint8_t msd
)
616 /* First activate and initialize Router Information is necessary */
617 if (!OspfRI
.enabled
) {
618 OspfRI
.enabled
= true;
619 initialize_params(&OspfRI
);
622 if (IS_DEBUG_OSPF_SR
)
623 zlog_debug("RI-> %s Routing Information for Segment Routing",
624 enable
? "Enable" : "Disable");
626 /* Unset or Set SR parameters */
628 unset_sr_algorithm(SR_ALGORITHM_SPF
);
629 unset_sr_sid_label_range();
631 OspfRI
.sr_info
.enabled
= false;
633 // Only SR_ALGORITHM_SPF is supported
634 set_sr_algorithm(SR_ALGORITHM_SPF
);
635 set_sr_sid_label_range(srgb
);
637 set_sr_node_msd(msd
);
640 OspfRI
.sr_info
.enabled
= true;
643 /* Refresh if already engaged or originate RI LSA */
644 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
645 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
647 ospf_router_info_lsa_schedule(REORIGINATE_THIS_LSA
);
650 /*------------------------------------------------------------------------*
651 * Followings are callback functions against generic Opaque-LSAs handling.
652 *------------------------------------------------------------------------*/
653 static void ospf_router_info_ism_change(struct ospf_interface
*oi
,
656 /* So far, nothing to do here. */
660 static void ospf_router_info_nsm_change(struct ospf_neighbor
*nbr
,
663 /* So far, nothing to do here. */
667 /*------------------------------------------------------------------------*
668 * Followings are OSPF protocol processing functions for ROUTER INFORMATION
669 *------------------------------------------------------------------------*/
671 static void build_tlv_header(struct stream
*s
, struct tlv_header
*tlvh
)
674 stream_put(s
, tlvh
, sizeof(struct tlv_header
));
678 static void build_tlv(struct stream
*s
, struct tlv_header
*tlvh
)
681 if (ntohs(tlvh
->type
) != 0) {
682 build_tlv_header(s
, tlvh
);
683 stream_put(s
, TLV_DATA(tlvh
), TLV_BODY_SIZE(tlvh
));
688 static void ospf_router_info_lsa_body_set(struct stream
*s
)
691 struct listnode
*node
;
692 struct ri_pce_subtlv_domain
*domain
;
693 struct ri_pce_subtlv_neighbor
*neighbor
;
695 /* Build Router Information TLV */
696 build_tlv(s
, &OspfRI
.router_cap
.header
);
698 /* Build Segment Routing TLVs if enabled */
699 if (OspfRI
.sr_info
.enabled
) {
700 /* Build Algorithm TLV */
701 build_tlv(s
, &TLV_HDR(OspfRI
.sr_info
.algo
));
703 build_tlv(s
, &TLV_HDR(OspfRI
.sr_info
.range
));
705 build_tlv(s
, &TLV_HDR(OspfRI
.sr_info
.msd
));
708 /* Add RI PCE TLV if it is set */
709 if (OspfRI
.pce_info
.enabled
) {
711 /* Compute PCE Info header first */
712 set_pce_header (&OspfRI
.pce_info
);
715 build_tlv_header(s
, &OspfRI
.pce_info
.pce_header
.header
);
717 /* Build PCE address sub-tlv */
718 build_tlv(s
, &OspfRI
.pce_info
.pce_address
.header
);
720 /* Build PCE path scope sub-tlv */
721 build_tlv(s
, &OspfRI
.pce_info
.pce_scope
.header
);
723 /* Build PCE domain sub-tlv */
724 for (ALL_LIST_ELEMENTS_RO(OspfRI
.pce_info
.pce_domain
, node
,
726 build_tlv(s
, &domain
->header
);
728 /* Build PCE neighbor sub-tlv */
729 for (ALL_LIST_ELEMENTS_RO(OspfRI
.pce_info
.pce_neighbor
, node
,
731 build_tlv(s
, &neighbor
->header
);
733 /* Build PCE cap flag sub-tlv */
734 build_tlv(s
, &OspfRI
.pce_info
.pce_cap_flag
.header
);
740 /* Create new opaque-LSA. */
741 static struct ospf_lsa
*ospf_router_info_lsa_new()
745 struct lsa_header
*lsah
;
746 struct ospf_lsa
*new = NULL
;
747 u_char options
, lsa_type
;
748 struct in_addr lsa_id
;
752 /* Create a stream for LSA. */
753 if ((s
= stream_new(OSPF_MAX_LSA_SIZE
)) == NULL
) {
754 zlog_warn("ospf_router_info_lsa_new: stream_new() ?");
757 lsah
= (struct lsa_header
*)STREAM_DATA(s
);
759 options
= OSPF_OPTION_E
; /* Enable AS external as we flood RI with
761 options
|= OSPF_OPTION_O
; /* Don't forget this :-) */
763 lsa_type
= OspfRI
.scope
;
764 /* LSA ID == 0 for Router Information see RFC 4970 */
765 tmp
= SET_OPAQUE_LSID(OPAQUE_TYPE_ROUTER_INFORMATION_LSA
, 0);
766 lsa_id
.s_addr
= htonl(tmp
);
768 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
))
770 "LSA[Type%d:%s]: Create an Opaque-LSA/ROUTER INFORMATION instance",
771 lsa_type
, inet_ntoa(lsa_id
));
773 top
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
775 /* Set opaque-LSA header fields. */
776 lsa_header_set(s
, options
, lsa_type
, lsa_id
, top
->router_id
);
778 /* Set opaque-LSA body fields. */
779 ospf_router_info_lsa_body_set(s
);
782 length
= stream_get_endp(s
);
783 lsah
->length
= htons(length
);
785 /* Now, create an OSPF LSA instance. */
786 if ((new = ospf_lsa_new()) == NULL
) {
787 zlog_warn("ospf_router_info_lsa_new: ospf_lsa_new() ?");
791 if ((new->data
= ospf_lsa_data_new(length
)) == NULL
) {
792 zlog_warn("ospf_router_info_lsa_new: ospf_lsa_data_new() ?");
793 ospf_lsa_unlock(&new);
799 new->area
= OspfRI
.area
; /* Area must be null if the Opaque type is AS
800 scope, fulfill otherwise */
802 if (new->area
&& new->area
->ospf
)
803 new->vrf_id
= new->area
->ospf
->vrf_id
;
805 new->vrf_id
= VRF_DEFAULT
;
807 SET_FLAG(new->flags
, OSPF_LSA_SELF
);
808 memcpy(new->data
, lsah
, length
);
814 static int ospf_router_info_lsa_originate1(void *arg
)
816 struct ospf_lsa
*new;
818 struct ospf_area
*area
;
820 vrf_id_t vrf_id
= VRF_DEFAULT
;
822 /* First check if the area is known if flooding scope is Area */
823 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) {
824 area
= (struct ospf_area
*)arg
;
825 if (area
->area_id
.s_addr
!= OspfRI
.area_id
.s_addr
) {
827 "RI -> This is not the Router Information Area. Stop processing");
832 vrf_id
= area
->ospf
->vrf_id
;
835 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
836 if ((new = ospf_router_info_lsa_new()) == NULL
) {
838 "ospf_router_info_lsa_originate1: ospf_router_info_lsa_new() ?");
841 new->vrf_id
= vrf_id
;
844 top
= ospf_lookup_by_vrf_id(vrf_id
);
846 zlog_debug("%s: ospf instance not found for vrf id %u",
847 __PRETTY_FUNCTION__
, vrf_id
);
848 ospf_lsa_unlock(&new);
852 /* Install this LSA into LSDB. */
853 if (ospf_lsa_install(top
, NULL
/*oi */, new) == NULL
) {
855 "ospf_router_info_lsa_originate1: ospf_lsa_install() ?");
856 ospf_lsa_unlock(&new);
860 /* Now this Router Info parameter entry has associated LSA. */
861 SET_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
);
863 /* Update new LSA origination count. */
864 top
->lsa_originate_count
++;
866 /* Flood new LSA through AS. */
867 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
)
868 ospf_flood_through_as(top
, NULL
/*nbr */, new);
870 ospf_flood_through_area(OspfRI
.area
, NULL
/*nbr */, new);
872 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
874 "LSA[Type%d:%s]: Originate Opaque-LSA/ROUTER INFORMATION",
875 new->data
->type
, inet_ntoa(new->data
->id
));
876 ospf_lsa_header_dump(new->data
);
883 static int ospf_router_info_lsa_originate(void *arg
)
888 if (!OspfRI
.enabled
) {
890 "ospf_router_info_lsa_originate: ROUTER INFORMATION is disabled now.");
891 rc
= 0; /* This is not an error case. */
895 /* Check if Router Information LSA is already engaged */
896 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
)) {
897 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_FORCED_REFRESH
)) {
898 UNSET_FLAG(OspfRI
.flags
, RIFLG_LSA_FORCED_REFRESH
);
899 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
902 if (!is_mandated_params_set(OspfRI
))
904 "ospf_router_info_lsa_originate: lacks mandated ROUTER INFORMATION parameters");
906 /* Ok, let's try to originate an LSA */
907 if (ospf_router_info_lsa_originate1(arg
) != 0)
915 static struct ospf_lsa
*ospf_router_info_lsa_refresh(struct ospf_lsa
*lsa
)
917 struct ospf_lsa
*new = NULL
;
920 if (!OspfRI
.enabled
) {
922 * This LSA must have flushed before due to ROUTER INFORMATION
924 * It seems a slip among routers in the routing domain.
927 "ospf_router_info_lsa_refresh: ROUTER INFORMATION is disabled now.");
929 htons(OSPF_LSA_MAXAGE
); /* Flush it anyway. */
932 /* Verify that the Router Information ID is supported */
933 if (GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)) != 0) {
935 "ospf_router_info_lsa_refresh: Unsupported Router Information ID");
939 /* If the lsa's age reached to MaxAge, start flushing procedure. */
940 if (IS_LSA_MAXAGE(lsa
)) {
941 UNSET_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
);
942 ospf_opaque_lsa_flush_schedule(lsa
);
946 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
947 if ((new = ospf_router_info_lsa_new()) == NULL
) {
949 "ospf_router_info_lsa_refresh: ospf_router_info_lsa_new() ?");
952 new->data
->ls_seqnum
= lsa_seqnum_increment(lsa
);
953 new->vrf_id
= lsa
->vrf_id
;
955 /* Install this LSA into LSDB. */
956 /* Given "lsa" will be freed in the next function. */
957 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
958 if (ospf_lsa_install(top
, NULL
/*oi */, new) == NULL
) {
959 zlog_warn("ospf_router_info_lsa_refresh: ospf_lsa_install() ?");
960 ospf_lsa_unlock(&new);
964 /* Flood updated LSA through AS or AREA depending of OspfRI.scope. */
965 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
)
966 ospf_flood_through_as(top
, NULL
/*nbr */, new);
968 ospf_flood_through_area(OspfRI
.area
, NULL
/*nbr */, new);
971 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
973 "LSA[Type%d:%s]: Refresh Opaque-LSA/ROUTER INFORMATION",
974 new->data
->type
, inet_ntoa(new->data
->id
));
975 ospf_lsa_header_dump(new->data
);
981 static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode
)
984 struct lsa_header lsah
;
988 memset(&lsa
, 0, sizeof(lsa
));
989 memset(&lsah
, 0, sizeof(lsah
));
991 zlog_debug("RI-> LSA schedule %s%s%s",
992 opcode
== REORIGINATE_THIS_LSA
? "Re-Originate" : "",
993 opcode
== REFRESH_THIS_LSA
? "Refresh" : "",
994 opcode
== FLUSH_THIS_LSA
? "Flush" : "");
996 /* Check LSA flags state coherence */
997 if (!CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
) && (opcode
!= REORIGINATE_THIS_LSA
))
1000 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
) && (opcode
== REORIGINATE_THIS_LSA
))
1001 opcode
= REFRESH_THIS_LSA
;
1003 top
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
1004 if ((OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) && (OspfRI
.area
== NULL
)) {
1006 "ospf_router_info_lsa_schedule(): Router Info is Area scope flooding but area is not set");
1007 OspfRI
.area
= ospf_area_lookup_by_area_id(top
, OspfRI
.area_id
);
1009 lsa
.area
= OspfRI
.area
;
1011 lsah
.type
= OspfRI
.scope
;
1013 /* LSA ID is set to 0 for the Router Information. See RFC 4970 */
1014 tmp
= SET_OPAQUE_LSID(OPAQUE_TYPE_ROUTER_INFORMATION_LSA
, 0);
1015 lsah
.id
.s_addr
= htonl(tmp
);
1018 case REORIGINATE_THIS_LSA
:
1019 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
)
1020 ospf_opaque_lsa_reoriginate_schedule(
1021 (void *)OspfRI
.area
, OSPF_OPAQUE_AREA_LSA
,
1022 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
1024 ospf_opaque_lsa_reoriginate_schedule(
1025 (void *)top
, OSPF_OPAQUE_AS_LSA
,
1026 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
1028 case REFRESH_THIS_LSA
:
1029 ospf_opaque_lsa_refresh_schedule(&lsa
);
1031 case FLUSH_THIS_LSA
:
1032 UNSET_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
);
1033 ospf_opaque_lsa_flush_schedule(&lsa
);
1036 zlog_warn("ospf_router_info_lsa_schedule: Unknown opcode (%u)",
1044 /* Callback to handle Segment Routing information */
1045 static int ospf_router_info_lsa_update(struct ospf_lsa
*lsa
)
1050 zlog_warn("OSPF-RI (%s): Abort! LSA is NULL", __func__
);
1054 /* Process only Opaque LSA */
1055 if ((lsa
->data
->type
!= OSPF_OPAQUE_AREA_LSA
)
1056 && (lsa
->data
->type
!= OSPF_OPAQUE_AS_LSA
))
1059 /* Process only Router Information LSA */
1060 if (GET_OPAQUE_TYPE(ntohl(lsa
->data
->id
.s_addr
)) !=
1061 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
)
1064 /* Check if it is not my LSA */
1065 if (IS_LSA_SELF(lsa
))
1068 /* Check if Router Info & Segment Routing are enable */
1069 if (!OspfRI
.enabled
|| !OspfRI
.sr_info
.enabled
)
1072 /* Call Segment Routing LSA update or deletion */
1073 if (!IS_LSA_MAXAGE(lsa
))
1074 ospf_sr_ri_lsa_update(lsa
);
1076 ospf_sr_ri_lsa_delete(lsa
);
1081 /*------------------------------------------------------------------------*
1082 * Followings are vty session control functions.
1083 *------------------------------------------------------------------------*/
1085 static u_int16_t
show_vty_router_cap(struct vty
*vty
,
1086 struct tlv_header
*tlvh
)
1088 struct ri_tlv_router_cap
*top
= (struct ri_tlv_router_cap
*)tlvh
;
1091 vty_out(vty
, " Router Capabilities: 0x%x\n",
1094 zlog_debug(" Router Capabilities: 0x%x", ntohl(top
->value
));
1096 return TLV_SIZE(tlvh
);
1099 static u_int16_t
show_vty_pce_subtlv_address(struct vty
*vty
,
1100 struct tlv_header
*tlvh
)
1102 struct ri_pce_subtlv_address
*top
=
1103 (struct ri_pce_subtlv_address
*)tlvh
;
1105 if (ntohs(top
->address
.type
) == PCE_ADDRESS_TYPE_IPV4
) {
1107 vty_out(vty
, " PCE Address: %s\n",
1108 inet_ntoa(top
->address
.value
));
1110 zlog_debug(" PCE Address: %s",
1111 inet_ntoa(top
->address
.value
));
1113 /* TODO: Add support to IPv6 with inet_ntop() */
1115 vty_out(vty
, " PCE Address: 0x%x\n",
1116 ntohl(top
->address
.value
.s_addr
));
1118 zlog_debug(" PCE Address: 0x%x",
1119 ntohl(top
->address
.value
.s_addr
));
1122 return TLV_SIZE(tlvh
);
1125 static u_int16_t
show_vty_pce_subtlv_path_scope(struct vty
*vty
,
1126 struct tlv_header
*tlvh
)
1128 struct ri_pce_subtlv_path_scope
*top
=
1129 (struct ri_pce_subtlv_path_scope
*)tlvh
;
1132 vty_out(vty
, " PCE Path Scope: 0x%x\n", ntohl(top
->value
));
1134 zlog_debug(" PCE Path Scope: 0x%x", ntohl(top
->value
));
1136 return TLV_SIZE(tlvh
);
1139 static u_int16_t
show_vty_pce_subtlv_domain(struct vty
*vty
,
1140 struct tlv_header
*tlvh
)
1142 struct ri_pce_subtlv_domain
*top
= (struct ri_pce_subtlv_domain
*)tlvh
;
1145 if (ntohs(top
->type
) == PCE_DOMAIN_TYPE_AREA
) {
1146 tmp
.s_addr
= top
->value
;
1148 vty_out(vty
, " PCE domain Area: %s\n", inet_ntoa(tmp
));
1150 zlog_debug(" PCE domain Area: %s", inet_ntoa(tmp
));
1153 vty_out(vty
, " PCE domain AS: %d\n",
1156 zlog_debug(" PCE domain AS: %d", ntohl(top
->value
));
1158 return TLV_SIZE(tlvh
);
1161 static u_int16_t
show_vty_pce_subtlv_neighbor(struct vty
*vty
,
1162 struct tlv_header
*tlvh
)
1165 struct ri_pce_subtlv_neighbor
*top
=
1166 (struct ri_pce_subtlv_neighbor
*)tlvh
;
1169 if (ntohs(top
->type
) == PCE_DOMAIN_TYPE_AREA
) {
1170 tmp
.s_addr
= top
->value
;
1172 vty_out(vty
, " PCE neighbor Area: %s\n",
1175 zlog_debug(" PCE neighbor Area: %s", inet_ntoa(tmp
));
1178 vty_out(vty
, " PCE neighbor AS: %d\n",
1181 zlog_debug(" PCE neighbor AS: %d",
1184 return TLV_SIZE(tlvh
);
1187 static u_int16_t
show_vty_pce_subtlv_cap_flag(struct vty
*vty
,
1188 struct tlv_header
*tlvh
)
1190 struct ri_pce_subtlv_cap_flag
*top
=
1191 (struct ri_pce_subtlv_cap_flag
*)tlvh
;
1194 vty_out(vty
, " PCE Capabilities Flag: 0x%x\n",
1197 zlog_debug(" PCE Capabilities Flag: 0x%x",
1200 return TLV_SIZE(tlvh
);
1203 static u_int16_t
show_vty_unknown_tlv(struct vty
*vty
,
1204 struct tlv_header
*tlvh
)
1207 vty_out(vty
, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
1208 ntohs(tlvh
->type
), ntohs(tlvh
->length
));
1210 zlog_debug(" Unknown TLV: [type(0x%x), length(0x%x)]",
1211 ntohs(tlvh
->type
), ntohs(tlvh
->length
));
1213 return TLV_SIZE(tlvh
);
1216 static u_int16_t
show_vty_pce_info(struct vty
*vty
, struct tlv_header
*ri
,
1219 struct tlv_header
*tlvh
;
1222 for (tlvh
= ri
; sum
< total
; tlvh
= TLV_HDR_NEXT(tlvh
)) {
1223 switch (ntohs(tlvh
->type
)) {
1224 case RI_PCE_SUBTLV_ADDRESS
:
1225 sum
+= show_vty_pce_subtlv_address(vty
, tlvh
);
1227 case RI_PCE_SUBTLV_PATH_SCOPE
:
1228 sum
+= show_vty_pce_subtlv_path_scope(vty
, tlvh
);
1230 case RI_PCE_SUBTLV_DOMAIN
:
1231 sum
+= show_vty_pce_subtlv_domain(vty
, tlvh
);
1233 case RI_PCE_SUBTLV_NEIGHBOR
:
1234 sum
+= show_vty_pce_subtlv_neighbor(vty
, tlvh
);
1236 case RI_PCE_SUBTLV_CAP_FLAG
:
1237 sum
+= show_vty_pce_subtlv_cap_flag(vty
, tlvh
);
1240 sum
+= show_vty_unknown_tlv(vty
, tlvh
);
1247 /* Display Segment Routing Algorithm TLV information */
1248 static uint16_t show_vty_sr_algorithm(struct vty
*vty
, struct tlv_header
*tlvh
)
1250 struct ri_sr_tlv_sr_algorithm
*algo
=
1251 (struct ri_sr_tlv_sr_algorithm
*)tlvh
;
1255 vty_out(vty
, " Segment Routing Algorithm TLV:\n");
1256 for (i
= 0; i
< ntohs(algo
->header
.length
); i
++) {
1257 switch (algo
->value
[i
]) {
1259 vty_out(vty
, " Algorithm %d: SPF\n", i
);
1262 vty_out(vty
, " Algorithm %d: Strict SPF\n",
1267 " Algorithm %d: Unknown value %d\n", i
,
1275 zlog_debug(" Segment Routing Algorithm TLV:\n");
1276 for (i
= 0; i
< ntohs(algo
->header
.length
); i
++)
1277 switch (algo
->value
[i
]) {
1279 zlog_debug(" Algorithm %d: SPF\n", i
);
1282 zlog_debug(" Algorithm %d: Strict SPF\n", i
);
1286 " Algorithm %d: Unknown value %d\n",
1292 return TLV_SIZE(tlvh
);
1295 /* Display Segment Routing SID/Label Range TLV information */
1296 static uint16_t show_vty_sr_range(struct vty
*vty
, struct tlv_header
*tlvh
)
1298 struct ri_sr_tlv_sid_label_range
*range
=
1299 (struct ri_sr_tlv_sid_label_range
*)tlvh
;
1303 " Segment Routing Range TLV:\n"
1304 " Range Size = %d\n"
1305 " SID Label = %d\n\n",
1306 GET_RANGE_SIZE(ntohl(range
->size
)),
1307 GET_LABEL(ntohl(range
->lower
.value
)));
1310 " Segment Routing Range TLV:\n"
1311 " Range Size = %d\n"
1312 " SID Label = %d\n\n",
1313 GET_RANGE_SIZE(ntohl(range
->size
)),
1314 GET_LABEL(ntohl(range
->lower
.value
)));
1317 return TLV_SIZE(tlvh
);
1320 /* Display Segment Routing Maximum Stack Depth TLV information */
1321 static uint16_t show_vty_sr_msd(struct vty
*vty
, struct tlv_header
*tlvh
)
1323 struct ri_sr_tlv_node_msd
*msd
= (struct ri_sr_tlv_node_msd
*)tlvh
;
1327 " Segment Routing MSD TLV:\n"
1328 " Node Maximum Stack Depth = %d\n",
1332 " Segment Routing MSD TLV:\n"
1333 " Node Maximum Stack Depth = %d\n",
1337 return TLV_SIZE(tlvh
);
1340 static void ospf_router_info_show_info(struct vty
*vty
, struct ospf_lsa
*lsa
)
1342 struct lsa_header
*lsah
= (struct lsa_header
*)lsa
->data
;
1343 struct tlv_header
*tlvh
;
1344 u_int16_t length
= 0, sum
= 0;
1346 /* Initialize TLV browsing */
1347 length
= ntohs(lsah
->length
) - OSPF_LSA_HEADER_SIZE
;
1349 for (tlvh
= TLV_HDR_TOP(lsah
); sum
< length
;
1350 tlvh
= TLV_HDR_NEXT(tlvh
)) {
1351 switch (ntohs(tlvh
->type
)) {
1352 case RI_TLV_CAPABILITIES
:
1353 sum
+= show_vty_router_cap(vty
, tlvh
);
1357 sum
+= TLV_HDR_SIZE
;
1358 sum
+= show_vty_pce_info(vty
, tlvh
, length
- sum
);
1360 case RI_SR_TLV_SR_ALGORITHM
:
1361 sum
+= show_vty_sr_algorithm(vty
, tlvh
);
1363 case RI_SR_TLV_SID_LABEL_RANGE
:
1364 sum
+= show_vty_sr_range(vty
, tlvh
);
1366 case RI_SR_TLV_NODE_MSD
:
1367 sum
+= show_vty_sr_msd(vty
, tlvh
);
1371 sum
+= show_vty_unknown_tlv(vty
, tlvh
);
1379 static void ospf_router_info_config_write_router(struct vty
*vty
)
1381 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1382 struct listnode
*node
;
1383 struct ri_pce_subtlv_domain
*domain
;
1384 struct ri_pce_subtlv_neighbor
*neighbor
;
1387 if (!OspfRI
.enabled
)
1390 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
)
1391 vty_out(vty
, " router-info as\n");
1393 vty_out(vty
, " router-info area %s\n",
1394 inet_ntoa(OspfRI
.area_id
));
1396 if (OspfRI
.pce_info
.enabled
) {
1398 if (pce
->pce_address
.header
.type
!= 0)
1399 vty_out(vty
, " pce address %s\n",
1400 inet_ntoa(pce
->pce_address
.address
.value
));
1402 if (pce
->pce_cap_flag
.header
.type
!= 0)
1403 vty_out(vty
, " pce flag 0x%x\n",
1404 ntohl(pce
->pce_cap_flag
.value
));
1406 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
1407 if (domain
->header
.type
!= 0) {
1408 if (domain
->type
== PCE_DOMAIN_TYPE_AREA
) {
1409 tmp
.s_addr
= domain
->value
;
1410 vty_out(vty
, " pce domain area %s\n",
1413 vty_out(vty
, " pce domain as %d\n",
1414 ntohl(domain
->value
));
1419 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
1420 if (neighbor
->header
.type
!= 0) {
1421 if (neighbor
->type
== PCE_DOMAIN_TYPE_AREA
) {
1422 tmp
.s_addr
= neighbor
->value
;
1423 vty_out(vty
, " pce neighbor area %s\n",
1426 vty_out(vty
, " pce neighbor as %d\n",
1427 ntohl(neighbor
->value
));
1432 if (pce
->pce_scope
.header
.type
!= 0)
1433 vty_out(vty
, " pce scope 0x%x\n",
1434 ntohl(OspfRI
.pce_info
.pce_scope
.value
));
1439 /*------------------------------------------------------------------------*
1440 * Followings are vty command functions.
1441 *------------------------------------------------------------------------*/
1444 router_info_area_cmd
,
1445 "router-info <as|area A.B.C.D>",
1447 "Enable the Router Information functionality with AS flooding scope\n"
1448 "Enable the Router Information functionality with Area flooding scope\n"
1449 "OSPF area ID in IP format\n")
1452 char *area
= (argc
== 3) ? argv
[idx_ipv4
]->arg
: NULL
;
1459 /* Check and get Area value if present */
1461 if (!inet_aton(area
, &OspfRI
.area_id
)) {
1462 vty_out(vty
, "%% specified Area ID %s is invalid\n",
1464 return CMD_WARNING_CONFIG_FAILED
;
1466 scope
= OSPF_OPAQUE_AREA_LSA
;
1468 OspfRI
.area_id
.s_addr
= 0;
1469 scope
= OSPF_OPAQUE_AS_LSA
;
1472 /* First start to register Router Information callbacks */
1473 if ((ospf_router_info_register(scope
)) != 0) {
1475 "Unable to register Router Information callbacks. Abort!");
1476 return CMD_WARNING_CONFIG_FAILED
;
1479 OspfRI
.enabled
= true;
1481 if (IS_DEBUG_OSPF_EVENT
)
1482 zlog_debug("RI-> Router Information (%s flooding): OFF -> ON",
1483 OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
? "Area"
1487 * Following code is intended to handle two cases;
1489 * 1) Router Information was disabled at startup time, but now become
1491 * 2) Router Information was once enabled then disabled, and now enabled
1495 initialize_params(&OspfRI
);
1497 /* Refresh RI LSA if already engaged */
1498 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
)) {
1499 zlog_debug ("RI-> Refresh LSA following configuration");
1500 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA
);
1502 zlog_debug("RI-> Initial origination following configuration");
1503 ospf_router_info_lsa_schedule(REORIGINATE_THIS_LSA
);
1509 DEFUN (no_router_info
,
1513 "Disable the Router Information functionality\n")
1516 if (!OspfRI
.enabled
)
1519 if (IS_DEBUG_OSPF_EVENT
)
1520 zlog_debug("RI-> Router Information: ON -> OFF");
1522 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1523 ospf_router_info_lsa_schedule(FLUSH_THIS_LSA
);
1525 OspfRI
.enabled
= false;
1530 static int ospf_ri_enabled(struct vty
*vty
)
1536 vty_out(vty
, "%% OSPF RI is not turned on\n");
1543 "pce address A.B.C.D",
1545 "Stable IP address of the PCE\n"
1546 "PCE address in IPv4 address format\n")
1549 struct in_addr value
;
1550 struct ospf_pce_info
*pi
= &OspfRI
.pce_info
;
1552 if (!ospf_ri_enabled(vty
))
1553 return CMD_WARNING_CONFIG_FAILED
;
1555 if (!inet_aton(argv
[idx_ipv4
]->arg
, &value
)) {
1556 vty_out(vty
, "Please specify PCE Address by A.B.C.D\n");
1557 return CMD_WARNING_CONFIG_FAILED
;
1560 if (ntohs(pi
->pce_address
.header
.type
) == 0
1561 || ntohl(pi
->pce_address
.address
.value
.s_addr
)
1562 != ntohl(value
.s_addr
)) {
1564 set_pce_address(value
, pi
);
1566 /* Refresh RI LSA if already engaged */
1567 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1568 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1574 DEFUN (no_pce_address
,
1576 "no pce address [A.B.C.D]",
1579 "Disable PCE address\n"
1580 "PCE address in IPv4 address format\n")
1583 unset_param(&OspfRI
.pce_info
.pce_address
.header
);
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
);
1592 DEFUN (pce_path_scope
,
1594 "pce scope BITPATTERN",
1596 "Path scope visibilities of the PCE for path computation\n"
1597 "32-bit Hexadecimal value\n")
1599 int idx_bitpattern
= 2;
1601 struct ospf_pce_info
*pi
= &OspfRI
.pce_info
;
1603 if (!ospf_ri_enabled(vty
))
1604 return CMD_WARNING_CONFIG_FAILED
;
1606 if (sscanf(argv
[idx_bitpattern
]->arg
, "0x%x", &scope
) != 1) {
1607 vty_out(vty
, "pce_path_scope: fscanf: %s\n",
1608 safe_strerror(errno
));
1609 return CMD_WARNING_CONFIG_FAILED
;
1612 if (ntohl(pi
->pce_scope
.header
.type
) == 0
1613 || scope
!= pi
->pce_scope
.value
) {
1614 set_pce_path_scope(scope
, pi
);
1616 /* Refresh RI LSA if already engaged */
1617 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1618 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1624 DEFUN (no_pce_path_scope
,
1625 no_pce_path_scope_cmd
,
1626 "no pce scope [BITPATTERN]",
1629 "Disable PCE path scope\n"
1630 "32-bit Hexadecimal value\n")
1633 unset_param(&OspfRI
.pce_info
.pce_address
.header
);
1635 /* Refresh RI LSA if already engaged */
1636 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1637 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1644 "pce domain as (0-65535)",
1646 "Configure PCE domain AS number\n"
1647 "AS number where the PCE as visibilities for path computation\n"
1648 "AS number in decimal <0-65535>\n")
1653 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1654 struct listnode
*node
;
1655 struct ri_pce_subtlv_domain
*domain
;
1657 if (!ospf_ri_enabled(vty
))
1658 return CMD_WARNING_CONFIG_FAILED
;
1660 if (sscanf(argv
[idx_number
]->arg
, "%d", &as
) != 1) {
1661 vty_out(vty
, "pce_domain: fscanf: %s\n", safe_strerror(errno
));
1662 return CMD_WARNING_CONFIG_FAILED
;
1665 /* Check if the domain is not already in the domain list */
1666 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
1667 if (ntohl(domain
->header
.type
) == 0 && as
== domain
->value
)
1671 /* Create new domain if not found */
1672 set_pce_domain(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1674 /* Refresh RI LSA if already engaged */
1675 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1676 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1681 DEFUN (no_pce_domain
,
1683 "no pce domain as (0-65535)",
1686 "Disable PCE domain AS number\n"
1687 "AS number where the PCE as visibilities for path computation\n"
1688 "AS number in decimal <0-65535>\n")
1693 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1695 if (sscanf(argv
[idx_number
]->arg
, "%d", &as
) != 1) {
1696 vty_out(vty
, "no_pce_domain: fscanf: %s\n",
1697 safe_strerror(errno
));
1698 return CMD_WARNING_CONFIG_FAILED
;
1701 /* Unset corresponding PCE domain */
1702 unset_pce_domain(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1704 /* Refresh RI LSA if already engaged */
1705 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1706 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1711 DEFUN (pce_neigbhor
,
1713 "pce neighbor as (0-65535)",
1715 "Configure PCE neighbor domain AS number\n"
1716 "AS number of PCE neighbors\n"
1717 "AS number in decimal <0-65535>\n")
1722 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1723 struct listnode
*node
;
1724 struct ri_pce_subtlv_neighbor
*neighbor
;
1726 if (!ospf_ri_enabled(vty
))
1727 return CMD_WARNING_CONFIG_FAILED
;
1729 if (sscanf(argv
[idx_number
]->arg
, "%d", &as
) != 1) {
1730 vty_out(vty
, "pce_neighbor: fscanf: %s\n",
1731 safe_strerror(errno
));
1732 return CMD_WARNING_CONFIG_FAILED
;
1735 /* Check if the domain is not already in the domain list */
1736 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
1737 if (ntohl(neighbor
->header
.type
) == 0 && as
== neighbor
->value
)
1741 /* Create new domain if not found */
1742 set_pce_neighbor(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1744 /* Refresh RI LSA if already engaged */
1745 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1746 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1751 DEFUN (no_pce_neighbor
,
1752 no_pce_neighbor_cmd
,
1753 "no pce neighbor as (0-65535)",
1756 "Disable PCE neighbor AS number\n"
1757 "AS number of PCE neighbor\n"
1758 "AS number in decimal <0-65535>\n")
1763 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1765 if (sscanf(argv
[idx_number
]->arg
, "%d", &as
) != 1) {
1766 vty_out(vty
, "no_pce_neighbor: fscanf: %s\n",
1767 safe_strerror(errno
));
1768 return CMD_WARNING_CONFIG_FAILED
;
1771 /* Unset corresponding PCE domain */
1772 unset_pce_neighbor(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1774 /* Refresh RI LSA if already engaged */
1775 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1776 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1781 DEFUN (pce_cap_flag
,
1783 "pce flag BITPATTERN",
1785 "Capabilities of the PCE for path computation\n"
1786 "32-bit Hexadecimal value\n")
1788 int idx_bitpattern
= 2;
1791 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1793 if (!ospf_ri_enabled(vty
))
1794 return CMD_WARNING_CONFIG_FAILED
;
1796 if (sscanf(argv
[idx_bitpattern
]->arg
, "0x%x", &cap
) != 1) {
1797 vty_out(vty
, "pce_cap_flag: fscanf: %s\n",
1798 safe_strerror(errno
));
1799 return CMD_WARNING_CONFIG_FAILED
;
1802 if (ntohl(pce
->pce_cap_flag
.header
.type
) == 0
1803 || cap
!= pce
->pce_cap_flag
.value
) {
1804 set_pce_cap_flag(cap
, pce
);
1806 /* Refresh RI LSA if already engaged */
1807 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1808 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1814 DEFUN (no_pce_cap_flag
,
1815 no_pce_cap_flag_cmd
,
1819 "Disable PCE capabilities\n")
1822 unset_param(&OspfRI
.pce_info
.pce_cap_flag
.header
);
1824 /* Refresh RI LSA if already engaged */
1825 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1826 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1831 DEFUN (show_ip_ospf_router_info
,
1832 show_ip_ospf_router_info_cmd
,
1833 "show ip ospf router-info",
1837 "Router Information\n")
1840 if (OspfRI
.enabled
) {
1841 vty_out(vty
, "--- Router Information parameters ---\n");
1842 show_vty_router_cap(vty
, &OspfRI
.router_cap
.header
);
1846 " Router Information is disabled on this router\n");
1851 DEFUN (show_ip_opsf_router_info_pce
,
1852 show_ip_ospf_router_info_pce_cmd
,
1853 "show ip ospf router-info pce",
1857 "Router Information\n"
1858 "PCE information\n")
1861 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1862 struct listnode
*node
;
1863 struct ri_pce_subtlv_domain
*domain
;
1864 struct ri_pce_subtlv_neighbor
*neighbor
;
1866 if ((OspfRI
.enabled
) && (OspfRI
.pce_info
.enabled
)) {
1867 vty_out(vty
, "--- PCE parameters ---\n");
1869 if (pce
->pce_address
.header
.type
!= 0)
1870 show_vty_pce_subtlv_address(vty
,
1871 &pce
->pce_address
.header
);
1873 if (pce
->pce_scope
.header
.type
!= 0)
1874 show_vty_pce_subtlv_path_scope(vty
,
1875 &pce
->pce_scope
.header
);
1877 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
1878 if (domain
->header
.type
!= 0)
1879 show_vty_pce_subtlv_domain(vty
,
1883 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
1884 if (neighbor
->header
.type
!= 0)
1885 show_vty_pce_subtlv_neighbor(vty
,
1889 if (pce
->pce_cap_flag
.header
.type
!= 0)
1890 show_vty_pce_subtlv_cap_flag(vty
,
1891 &pce
->pce_cap_flag
.header
);
1895 " PCE info is disabled on this router\n");
1901 /* Install new CLI commands */
1902 static void ospf_router_info_register_vty(void)
1904 install_element(VIEW_NODE
, &show_ip_ospf_router_info_cmd
);
1905 install_element(VIEW_NODE
, &show_ip_ospf_router_info_pce_cmd
);
1907 install_element(OSPF_NODE
, &router_info_area_cmd
);
1908 install_element(OSPF_NODE
, &no_router_info_cmd
);
1909 install_element(OSPF_NODE
, &pce_address_cmd
);
1910 install_element(OSPF_NODE
, &no_pce_address_cmd
);
1911 install_element(OSPF_NODE
, &pce_path_scope_cmd
);
1912 install_element(OSPF_NODE
, &no_pce_path_scope_cmd
);
1913 install_element(OSPF_NODE
, &pce_domain_cmd
);
1914 install_element(OSPF_NODE
, &no_pce_domain_cmd
);
1915 install_element(OSPF_NODE
, &pce_neighbor_cmd
);
1916 install_element(OSPF_NODE
, &no_pce_neighbor_cmd
);
1917 install_element(OSPF_NODE
, &pce_cap_flag_cmd
);
1918 install_element(OSPF_NODE
, &no_pce_cap_flag_cmd
);