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
;
72 /* Store Router Information Segment Routing TLV and SubTLV in network byte order. */
73 struct ospf_ri_sr_info
{
75 /* Algorithms supported by the node */
76 struct ri_sr_tlv_sr_algorithm algo
;
78 * Segment Routing Global Block i.e. label range
79 * Only one range supported in this code
81 struct ri_sr_tlv_sid_label_range range
;
82 /* Maximum SID Depth supported by the node */
83 struct ri_sr_tlv_node_msd msd
;
86 /* Following structure are internal use only. */
87 struct ospf_router_info
{
93 /* Flags to manage this router information. */
94 #define RIFLG_LSA_ENGAGED 0x1
95 #define RIFLG_LSA_FORCED_REFRESH 0x2
98 /* area pointer if flooding is Type 10 Null if flooding is AS scope */
99 struct ospf_area
*area
;
100 struct in_addr area_id
;
102 /* Store Router Information Capabilities LSA */
103 struct ri_tlv_router_cap router_cap
;
105 /* Store PCE capability LSA */
106 struct ospf_pce_info pce_info
;
108 /* Store SR capability LSA */
109 struct ospf_ri_sr_info sr_info
;
113 * Global variable to manage Opaque-LSA/Router Information on this node.
114 * Note that all parameter values are stored in network byte order.
116 static struct ospf_router_info OspfRI
;
118 /*------------------------------------------------------------------------------*
119 * Followings are initialize/terminate functions for Router Information
121 *------------------------------------------------------------------------------*/
123 static void ospf_router_info_ism_change(struct ospf_interface
*oi
,
125 static void ospf_router_info_nsm_change(struct ospf_neighbor
*nbr
,
127 static void ospf_router_info_config_write_router(struct vty
*vty
);
128 static void ospf_router_info_show_info(struct vty
*vty
, struct ospf_lsa
*lsa
);
129 static int ospf_router_info_lsa_originate(void *arg
);
130 static struct ospf_lsa
*ospf_router_info_lsa_refresh(struct ospf_lsa
*lsa
);
131 static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode
);
132 static void ospf_router_info_register_vty(void);
133 static int ospf_router_info_lsa_update(struct ospf_lsa
*lsa
);
134 static void del_pce_info(void *val
);
136 int ospf_router_info_init(void)
139 zlog_info("RI -> Initialize Router Information");
141 memset(&OspfRI
, 0, sizeof(struct ospf_router_info
));
142 OspfRI
.enabled
= false;
143 OspfRI
.registered
= 0;
144 OspfRI
.scope
= OSPF_OPAQUE_AS_LSA
;
145 OspfRI
.area_id
.s_addr
= 0;
148 /* Initialize pce domain and neighbor list */
149 OspfRI
.pce_info
.enabled
= false;
150 OspfRI
.pce_info
.pce_domain
= list_new();
151 OspfRI
.pce_info
.pce_domain
->del
= del_pce_info
;
152 OspfRI
.pce_info
.pce_neighbor
= list_new();
153 OspfRI
.pce_info
.pce_neighbor
->del
= del_pce_info
;
155 /* Initialize Segment Routing information structure */
156 OspfRI
.sr_info
.enabled
= false;
158 ospf_router_info_register_vty();
163 static int ospf_router_info_register(u_int8_t scope
)
167 if (OspfRI
.registered
)
170 zlog_info("RI -> Register Router Information with scope %s(%d)",
171 scope
== OSPF_OPAQUE_AREA_LSA
? "Area" : "AS", scope
);
172 rc
= ospf_register_opaque_functab(
173 scope
, OPAQUE_TYPE_ROUTER_INFORMATION_LSA
,
174 NULL
, /* new interface */
175 NULL
, /* del interface */
176 ospf_router_info_ism_change
,
177 ospf_router_info_nsm_change
,
178 ospf_router_info_config_write_router
,
179 NULL
, /* Config. write interface */
180 NULL
, /* Config. write debug */
181 ospf_router_info_show_info
,
182 ospf_router_info_lsa_originate
,
183 ospf_router_info_lsa_refresh
,
184 ospf_router_info_lsa_update
,
185 NULL
); /* del_lsa_hook */
189 "ospf_router_info_init: Failed to register functions");
193 OspfRI
.registered
= 1;
194 OspfRI
.scope
= scope
;
198 static int ospf_router_info_unregister()
201 if ((OspfRI
.scope
!= OSPF_OPAQUE_AS_LSA
)
202 && (OspfRI
.scope
!= OSPF_OPAQUE_AREA_LSA
)) {
204 "Unable to unregister Router Info functions: Wrong scope!");
208 ospf_delete_opaque_functab(OspfRI
.scope
,
209 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
211 OspfRI
.registered
= 0;
215 void ospf_router_info_term(void)
218 list_delete_and_null(&OspfRI
.pce_info
.pce_domain
);
219 list_delete_and_null(&OspfRI
.pce_info
.pce_neighbor
);
221 OspfRI
.enabled
= false;
223 ospf_router_info_unregister();
228 static void del_pce_info(void *val
)
230 XFREE(MTYPE_OSPF_PCE_PARAMS
, val
);
234 /* Catch RI LSA flooding Scope for ospf_ext.[h,c] code */
235 struct scope_info
ospf_router_info_get_flooding_scope(void)
237 struct scope_info flooding_scope
;
238 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
) {
239 flooding_scope
.scope
= OSPF_OPAQUE_AS_LSA
;
240 flooding_scope
.area_id
.s_addr
= 0;
241 return flooding_scope
;
243 flooding_scope
.scope
= OSPF_OPAQUE_AREA_LSA
;
244 flooding_scope
.area_id
.s_addr
= OspfRI
.area_id
.s_addr
;
245 return flooding_scope
;
248 /*------------------------------------------------------------------------*
249 * Followings are control functions for ROUTER INFORMATION parameters
251 *------------------------------------------------------------------------*/
253 static void set_router_info_capabilities(struct ri_tlv_router_cap
*ric
,
256 ric
->header
.type
= htons(RI_TLV_CAPABILITIES
);
257 ric
->header
.length
= htons(RI_TLV_LENGTH
);
258 ric
->value
= htonl(cap
);
262 static int set_pce_header(struct ospf_pce_info
*pce
)
264 u_int16_t length
= 0;
265 struct listnode
*node
;
266 struct ri_pce_subtlv_domain
*domain
;
267 struct ri_pce_subtlv_neighbor
*neighbor
;
270 if (ntohs(pce
->pce_address
.header
.type
) != 0)
271 length
+= TLV_SIZE(&pce
->pce_address
.header
);
274 if (ntohs(pce
->pce_scope
.header
.type
) != 0)
275 length
+= TLV_SIZE(&pce
->pce_scope
.header
);
278 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
279 if (ntohs(domain
->header
.type
) != 0)
280 length
+= TLV_SIZE(&domain
->header
);
284 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
285 if (ntohs(neighbor
->header
.type
) != 0)
286 length
+= TLV_SIZE(&neighbor
->header
);
289 /* PCE Capabilities */
290 if (ntohs(pce
->pce_cap_flag
.header
.type
) != 0)
291 length
+= TLV_SIZE(&pce
->pce_cap_flag
.header
);
294 pce
->pce_header
.header
.type
= htons(RI_TLV_PCE
);
295 pce
->pce_header
.header
.length
= htons(length
);
298 pce
->pce_header
.header
.type
= 0;
299 pce
->pce_header
.header
.length
= 0;
300 pce
->enabled
= false;
306 static void set_pce_address(struct in_addr ipv4
, struct ospf_pce_info
*pce
)
309 /* Enable PCE Info */
310 pce
->pce_header
.header
.type
= htons(RI_TLV_PCE
);
311 /* Set PCE Address */
312 pce
->pce_address
.header
.type
= htons(RI_PCE_SUBTLV_ADDRESS
);
313 pce
->pce_address
.header
.length
= htons(PCE_ADDRESS_LENGTH_IPV4
);
314 pce
->pce_address
.address
.type
= htons(PCE_ADDRESS_TYPE_IPV4
);
315 pce
->pce_address
.address
.value
= ipv4
;
320 static void set_pce_path_scope(u_int32_t scope
, struct ospf_pce_info
*pce
)
324 pce
->pce_scope
.header
.type
= htons(RI_PCE_SUBTLV_PATH_SCOPE
);
325 pce
->pce_scope
.header
.length
= htons(RI_TLV_LENGTH
);
326 pce
->pce_scope
.value
= htonl(scope
);
331 static void set_pce_domain(u_int16_t type
, u_int32_t domain
,
332 struct ospf_pce_info
*pce
)
335 struct ri_pce_subtlv_domain
*new;
337 /* Create new domain info */
338 new = XCALLOC(MTYPE_OSPF_PCE_PARAMS
,
339 sizeof(struct ri_pce_subtlv_domain
));
341 new->header
.type
= htons(RI_PCE_SUBTLV_DOMAIN
);
342 new->header
.length
= htons(PCE_ADDRESS_LENGTH_IPV4
);
343 new->type
= htons(type
);
344 new->value
= htonl(domain
);
346 /* Add new domain to the list */
347 listnode_add(pce
->pce_domain
, new);
352 static void unset_pce_domain(u_int16_t type
, u_int32_t domain
,
353 struct ospf_pce_info
*pce
)
355 struct listnode
*node
;
356 struct ri_pce_subtlv_domain
*old
= NULL
;
359 /* Search the corresponding node */
360 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, old
)) {
361 if ((old
->type
== htons(type
))
362 && (old
->value
== htonl(domain
))) {
368 /* if found remove it */
370 listnode_delete(pce
->pce_domain
, old
);
372 /* Avoid misjudgement in the next lookup. */
373 if (listcount(pce
->pce_domain
) == 0)
374 pce
->pce_domain
->head
= pce
->pce_domain
->tail
= NULL
;
376 /* Finally free the old domain */
377 XFREE(MTYPE_OSPF_PCE_PARAMS
, old
);
381 static void set_pce_neighbor(u_int16_t type
, u_int32_t domain
,
382 struct ospf_pce_info
*pce
)
385 struct ri_pce_subtlv_neighbor
*new;
387 /* Create new neighbor info */
388 new = XCALLOC(MTYPE_OSPF_PCE_PARAMS
,
389 sizeof(struct ri_pce_subtlv_neighbor
));
391 new->header
.type
= htons(RI_PCE_SUBTLV_NEIGHBOR
);
392 new->header
.length
= htons(PCE_ADDRESS_LENGTH_IPV4
);
393 new->type
= htons(type
);
394 new->value
= htonl(domain
);
396 /* Add new domain to the list */
397 listnode_add(pce
->pce_neighbor
, new);
402 static void unset_pce_neighbor(u_int16_t type
, u_int32_t domain
,
403 struct ospf_pce_info
*pce
)
405 struct listnode
*node
;
406 struct ri_pce_subtlv_neighbor
*old
= NULL
;
409 /* Search the corresponding node */
410 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, old
)) {
411 if ((old
->type
== htons(type
))
412 && (old
->value
== htonl(domain
))) {
418 /* if found remove it */
420 listnode_delete(pce
->pce_neighbor
, old
);
422 /* Avoid misjudgement in the next lookup. */
423 if (listcount(pce
->pce_neighbor
) == 0)
424 pce
->pce_neighbor
->head
= pce
->pce_neighbor
->tail
=
427 /* Finally free the old domain */
428 XFREE(MTYPE_OSPF_PCE_PARAMS
, old
);
432 static void set_pce_cap_flag(u_int32_t cap
, struct ospf_pce_info
*pce
)
435 /* Set PCE Capabilities flag */
436 pce
->pce_cap_flag
.header
.type
= htons(RI_PCE_SUBTLV_CAP_FLAG
);
437 pce
->pce_cap_flag
.header
.length
= htons(RI_TLV_LENGTH
);
438 pce
->pce_cap_flag
.value
= htonl(cap
);
443 /* Segment Routing TLV setter */
445 /* Algorithm SubTLV - section 3.1 */
446 static void set_sr_algorithm(uint8_t algo
)
449 OspfRI
.sr_info
.algo
.value
[0] = algo
;
450 for (int i
= 1; i
< ALGORITHM_COUNT
; i
++)
451 OspfRI
.sr_info
.algo
.value
[i
] = SR_ALGORITHM_UNSET
;
453 /* Set TLV type and length == only 1 Algorithm */
454 TLV_TYPE(OspfRI
.sr_info
.algo
) = htons(RI_SR_TLV_SR_ALGORITHM
);
455 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);
474 /* Segment Routing Global Block SubTLV - section 3.2 */
475 static void set_sr_sid_label_range(struct sr_srgb srgb
)
478 TLV_TYPE(OspfRI
.sr_info
.range
) = htons(RI_SR_TLV_SID_LABEL_RANGE
);
479 TLV_LEN(OspfRI
.sr_info
.range
) =
480 htons(SUBTLV_SID_LABEL_SIZE
+ sizeof(uint32_t));
482 OspfRI
.sr_info
.range
.size
= htonl(SET_RANGE_SIZE(srgb
.range_size
));
483 /* Set Lower bound label SubTLV */
484 TLV_TYPE(OspfRI
.sr_info
.range
.lower
) = htons(SUBTLV_SID_LABEL
);
485 TLV_LEN(OspfRI
.sr_info
.range
.lower
) = htons(SID_RANGE_LABEL_LENGTH
);
486 OspfRI
.sr_info
.range
.lower
.value
= htonl(SET_LABEL(srgb
.lower_bound
));
491 /* Unset this SRGB SubTLV */
492 static void unset_sr_sid_label_range()
495 TLV_TYPE(OspfRI
.sr_info
.range
) = htons(0);
496 TLV_LEN(OspfRI
.sr_info
.range
) = htons(0);
497 TLV_TYPE(OspfRI
.sr_info
.range
.lower
) = htons(0);
498 TLV_LEN(OspfRI
.sr_info
.range
.lower
) = htons(0);
503 /* Set Maximum Stack Depth for this router */
504 static void set_sr_node_msd(uint8_t msd
)
506 TLV_TYPE(OspfRI
.sr_info
.msd
) = htons(RI_SR_TLV_NODE_MSD
);
507 TLV_LEN(OspfRI
.sr_info
.msd
) = htons(sizeof(uint32_t));
508 OspfRI
.sr_info
.msd
.value
= msd
;
513 /* Unset this router MSD */
514 static void unset_sr_node_msd()
516 TLV_TYPE(OspfRI
.sr_info
.msd
) = htons(0);
517 TLV_LEN(OspfRI
.sr_info
.msd
) = htons(0);
522 static void unset_param(struct tlv_header
*tlv
)
526 /* Fill the Value to 0 */
527 memset(TLV_DATA(tlv
), 0, TLV_BODY_SIZE(tlv
));
533 static void initialize_params(struct ospf_router_info
*ori
)
539 * Initialize default Router Information Capabilities.
543 set_router_info_capabilities(&ori
->router_cap
, cap
);
545 /* If Area address is not null and exist, retrieve corresponding
547 top
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
548 zlog_info("RI-> Initialize Router Info for %s scope within area %s",
549 OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
? "Area" : "AS",
550 inet_ntoa(OspfRI
.area_id
));
552 /* Try to get the Area context at this step. Do it latter if not
554 if ((OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) && (OspfRI
.area
== NULL
))
555 OspfRI
.area
= ospf_area_lookup_by_area_id(top
, OspfRI
.area_id
);
558 * Initialize default PCE Information values
560 /* PCE address == OSPF Router ID */
561 set_pce_address(top
->router_id
, &ori
->pce_info
);
564 cap
= 7; /* Set L, R and Rd bits to one = intra & inter-area path
566 set_pce_path_scope(cap
, &ori
->pce_info
);
568 /* PCE Capabilities */
569 cap
= PCE_CAP_BIDIRECTIONAL
| PCE_CAP_DIVERSE_PATH
| PCE_CAP_OBJECTIVES
570 | PCE_CAP_ADDITIVE
| PCE_CAP_MULTIPLE_REQ
;
571 set_pce_cap_flag(cap
, &ori
->pce_info
);
576 static int is_mandated_params_set(struct ospf_router_info ori
)
580 if (ntohs(ori
.router_cap
.header
.type
) == 0)
583 if ((ntohs(ori
.pce_info
.pce_header
.header
.type
) == RI_TLV_PCE
)
584 && (ntohs(ori
.pce_info
.pce_address
.header
.type
) == 0)
585 && (ntohs(ori
.pce_info
.pce_cap_flag
.header
.type
) == 0))
588 if ((ori
.sr_info
.enabled
) && (ntohs(TLV_TYPE(ori
.sr_info
.algo
)) == 0)
589 && (ntohs(TLV_TYPE(ori
.sr_info
.range
)) == 0))
598 * Used by Segment Routing to set new TLVs and Sub-TLVs values
600 * @param enable To activate or not Segment Routing router Information flooding
601 * @param size Size of Label Range i.e. SRGB size
602 * @param lower Lower bound of the Label Range i.e. SRGB first label
603 * @param msd Maximum label Stack Depth suported by the router
607 void ospf_router_info_update_sr(bool enable
, struct sr_srgb srgb
, uint8_t msd
)
610 /* First activate and initialize Router Information is necessary */
611 if (!OspfRI
.enabled
) {
612 OspfRI
.enabled
= true;
613 initialize_params(&OspfRI
);
616 if (IS_DEBUG_OSPF_SR
)
617 zlog_debug("RI-> %s Routing Information for Segment Routing",
618 enable
? "Enable" : "Disable");
620 /* Unset or Set SR parameters */
622 unset_sr_algorithm(SR_ALGORITHM_SPF
);
623 unset_sr_sid_label_range();
625 OspfRI
.sr_info
.enabled
= false;
627 // Only SR_ALGORITHM_SPF is supported
628 set_sr_algorithm(SR_ALGORITHM_SPF
);
629 set_sr_sid_label_range(srgb
);
631 set_sr_node_msd(msd
);
634 OspfRI
.sr_info
.enabled
= true;
637 /* Refresh if already engaged or originate RI LSA */
638 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
639 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
641 ospf_router_info_lsa_schedule(REORIGINATE_THIS_LSA
);
644 /*------------------------------------------------------------------------*
645 * Followings are callback functions against generic Opaque-LSAs handling.
646 *------------------------------------------------------------------------*/
647 static void ospf_router_info_ism_change(struct ospf_interface
*oi
,
650 /* So far, nothing to do here. */
654 static void ospf_router_info_nsm_change(struct ospf_neighbor
*nbr
,
657 /* So far, nothing to do here. */
661 /*------------------------------------------------------------------------*
662 * Followings are OSPF protocol processing functions for ROUTER INFORMATION
663 *------------------------------------------------------------------------*/
665 static void build_tlv_header(struct stream
*s
, struct tlv_header
*tlvh
)
668 stream_put(s
, tlvh
, sizeof(struct tlv_header
));
672 static void build_tlv(struct stream
*s
, struct tlv_header
*tlvh
)
675 if (ntohs(tlvh
->type
) != 0) {
676 build_tlv_header(s
, tlvh
);
677 stream_put(s
, TLV_DATA(tlvh
), TLV_BODY_SIZE(tlvh
));
682 static void ospf_router_info_lsa_body_set(struct stream
*s
)
685 struct listnode
*node
;
686 struct ri_pce_subtlv_domain
*domain
;
687 struct ri_pce_subtlv_neighbor
*neighbor
;
689 /* Build Router Information TLV */
690 build_tlv(s
, &OspfRI
.router_cap
.header
);
692 /* Build Segment Routing TLVs if enabled */
693 if (OspfRI
.sr_info
.enabled
) {
694 /* Build Algorithm TLV */
695 build_tlv(s
, &TLV_HDR(OspfRI
.sr_info
.algo
));
697 build_tlv(s
, &TLV_HDR(OspfRI
.sr_info
.range
));
699 build_tlv(s
, &TLV_HDR(OspfRI
.sr_info
.msd
));
702 /* Add RI PCE TLV if it is set */
703 if (OspfRI
.pce_info
.enabled
) {
705 /* Compute PCE Info header first */
706 set_pce_header (&OspfRI
.pce_info
);
709 build_tlv_header(s
, &OspfRI
.pce_info
.pce_header
.header
);
711 /* Build PCE address sub-tlv */
712 build_tlv(s
, &OspfRI
.pce_info
.pce_address
.header
);
714 /* Build PCE path scope sub-tlv */
715 build_tlv(s
, &OspfRI
.pce_info
.pce_scope
.header
);
717 /* Build PCE domain sub-tlv */
718 for (ALL_LIST_ELEMENTS_RO(OspfRI
.pce_info
.pce_domain
, node
,
720 build_tlv(s
, &domain
->header
);
722 /* Build PCE neighbor sub-tlv */
723 for (ALL_LIST_ELEMENTS_RO(OspfRI
.pce_info
.pce_neighbor
, node
,
725 build_tlv(s
, &neighbor
->header
);
727 /* Build PCE cap flag sub-tlv */
728 build_tlv(s
, &OspfRI
.pce_info
.pce_cap_flag
.header
);
734 /* Create new opaque-LSA. */
735 static struct ospf_lsa
*ospf_router_info_lsa_new()
739 struct lsa_header
*lsah
;
740 struct ospf_lsa
*new = NULL
;
741 u_char options
, lsa_type
;
742 struct in_addr lsa_id
;
746 /* Create a stream for LSA. */
747 if ((s
= stream_new(OSPF_MAX_LSA_SIZE
)) == NULL
) {
748 zlog_warn("ospf_router_info_lsa_new: stream_new() ?");
751 lsah
= (struct lsa_header
*)STREAM_DATA(s
);
753 options
= OSPF_OPTION_E
; /* Enable AS external as we flood RI with
755 options
|= OSPF_OPTION_O
; /* Don't forget this :-) */
757 lsa_type
= OspfRI
.scope
;
758 /* LSA ID == 0 for Router Information see RFC 4970 */
759 tmp
= SET_OPAQUE_LSID(OPAQUE_TYPE_ROUTER_INFORMATION_LSA
, 0);
760 lsa_id
.s_addr
= htonl(tmp
);
762 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
))
764 "LSA[Type%d:%s]: Create an Opaque-LSA/ROUTER INFORMATION instance",
765 lsa_type
, inet_ntoa(lsa_id
));
767 top
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
769 /* Set opaque-LSA header fields. */
770 lsa_header_set(s
, options
, lsa_type
, lsa_id
, top
->router_id
);
772 /* Set opaque-LSA body fields. */
773 ospf_router_info_lsa_body_set(s
);
776 length
= stream_get_endp(s
);
777 lsah
->length
= htons(length
);
779 /* Now, create an OSPF LSA instance. */
780 if ((new = ospf_lsa_new()) == NULL
) {
781 zlog_warn("ospf_router_info_lsa_new: ospf_lsa_new() ?");
785 if ((new->data
= ospf_lsa_data_new(length
)) == NULL
) {
786 zlog_warn("ospf_router_info_lsa_new: ospf_lsa_data_new() ?");
787 ospf_lsa_unlock(&new);
793 new->area
= OspfRI
.area
; /* Area must be null if the Opaque type is AS
794 scope, fulfill otherwise */
796 if (new->area
&& new->area
->ospf
)
797 new->vrf_id
= new->area
->ospf
->vrf_id
;
799 new->vrf_id
= VRF_DEFAULT
;
801 SET_FLAG(new->flags
, OSPF_LSA_SELF
);
802 memcpy(new->data
, lsah
, length
);
808 static int ospf_router_info_lsa_originate1(void *arg
)
810 struct ospf_lsa
*new;
812 struct ospf_area
*area
;
814 vrf_id_t vrf_id
= VRF_DEFAULT
;
816 /* First check if the area is known if flooding scope is Area */
817 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) {
818 area
= (struct ospf_area
*)arg
;
819 if (area
->area_id
.s_addr
!= OspfRI
.area_id
.s_addr
) {
821 "RI -> This is not the Router Information Area. Stop processing");
826 vrf_id
= area
->ospf
->vrf_id
;
829 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
830 if ((new = ospf_router_info_lsa_new()) == NULL
) {
832 "ospf_router_info_lsa_originate1: ospf_router_info_lsa_new() ?");
835 new->vrf_id
= vrf_id
;
838 top
= ospf_lookup_by_vrf_id(vrf_id
);
840 zlog_debug("%s: ospf instance not found for vrf id %u",
841 __PRETTY_FUNCTION__
, vrf_id
);
842 ospf_lsa_unlock(&new);
846 /* Install this LSA into LSDB. */
847 if (ospf_lsa_install(top
, NULL
/*oi */, new) == NULL
) {
849 "ospf_router_info_lsa_originate1: ospf_lsa_install() ?");
850 ospf_lsa_unlock(&new);
854 /* Now this Router Info parameter entry has associated LSA. */
855 SET_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
);
857 /* Update new LSA origination count. */
858 top
->lsa_originate_count
++;
860 /* Flood new LSA through AS. */
861 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
)
862 ospf_flood_through_as(top
, NULL
/*nbr */, new);
864 ospf_flood_through_area(OspfRI
.area
, NULL
/*nbr */, new);
866 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
868 "LSA[Type%d:%s]: Originate Opaque-LSA/ROUTER INFORMATION",
869 new->data
->type
, inet_ntoa(new->data
->id
));
870 ospf_lsa_header_dump(new->data
);
877 static int ospf_router_info_lsa_originate(void *arg
)
882 if (!OspfRI
.enabled
) {
884 "ospf_router_info_lsa_originate: ROUTER INFORMATION is disabled now.");
885 rc
= 0; /* This is not an error case. */
889 /* Check if Router Information LSA is already engaged */
890 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
)) {
891 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_FORCED_REFRESH
)) {
892 UNSET_FLAG(OspfRI
.flags
, RIFLG_LSA_FORCED_REFRESH
);
893 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
896 if (!is_mandated_params_set(OspfRI
))
898 "ospf_router_info_lsa_originate: lacks mandated ROUTER INFORMATION parameters");
900 /* Ok, let's try to originate an LSA */
901 if (ospf_router_info_lsa_originate1(arg
) != 0)
909 static struct ospf_lsa
*ospf_router_info_lsa_refresh(struct ospf_lsa
*lsa
)
911 struct ospf_lsa
*new = NULL
;
914 if (!OspfRI
.enabled
) {
916 * This LSA must have flushed before due to ROUTER INFORMATION
918 * It seems a slip among routers in the routing domain.
921 "ospf_router_info_lsa_refresh: ROUTER INFORMATION is disabled now.");
923 htons(OSPF_LSA_MAXAGE
); /* Flush it anyway. */
926 /* Verify that the Router Information ID is supported */
927 if (GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)) != 0) {
929 "ospf_router_info_lsa_refresh: Unsupported Router Information ID");
933 /* If the lsa's age reached to MaxAge, start flushing procedure. */
934 if (IS_LSA_MAXAGE(lsa
)) {
935 UNSET_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
);
936 ospf_opaque_lsa_flush_schedule(lsa
);
940 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
941 if ((new = ospf_router_info_lsa_new()) == NULL
) {
943 "ospf_router_info_lsa_refresh: ospf_router_info_lsa_new() ?");
946 new->data
->ls_seqnum
= lsa_seqnum_increment(lsa
);
947 new->vrf_id
= lsa
->vrf_id
;
949 /* Install this LSA into LSDB. */
950 /* Given "lsa" will be freed in the next function. */
951 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
952 if (ospf_lsa_install(top
, NULL
/*oi */, new) == NULL
) {
953 zlog_warn("ospf_router_info_lsa_refresh: ospf_lsa_install() ?");
954 ospf_lsa_unlock(&new);
958 /* Flood updated LSA through AS or AREA depending of OspfRI.scope. */
959 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
)
960 ospf_flood_through_as(top
, NULL
/*nbr */, new);
962 ospf_flood_through_area(OspfRI
.area
, NULL
/*nbr */, new);
965 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
967 "LSA[Type%d:%s]: Refresh Opaque-LSA/ROUTER INFORMATION",
968 new->data
->type
, inet_ntoa(new->data
->id
));
969 ospf_lsa_header_dump(new->data
);
975 static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode
)
978 struct lsa_header lsah
;
982 memset(&lsa
, 0, sizeof(lsa
));
983 memset(&lsah
, 0, sizeof(lsah
));
985 zlog_debug("RI-> LSA schedule %s%s%s",
986 opcode
== REORIGINATE_THIS_LSA
? "Re-Originate" : "",
987 opcode
== REFRESH_THIS_LSA
? "Refresh" : "",
988 opcode
== FLUSH_THIS_LSA
? "Flush" : "");
990 /* Check LSA flags state coherence */
991 if (!CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
) && (opcode
!= REORIGINATE_THIS_LSA
))
994 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
) && (opcode
== REORIGINATE_THIS_LSA
))
995 opcode
= REFRESH_THIS_LSA
;
997 top
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
998 if ((OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) && (OspfRI
.area
== NULL
)) {
1000 "ospf_router_info_lsa_schedule(): Router Info is Area scope flooding but area is not set");
1001 OspfRI
.area
= ospf_area_lookup_by_area_id(top
, OspfRI
.area_id
);
1003 lsa
.area
= OspfRI
.area
;
1005 lsah
.type
= OspfRI
.scope
;
1007 /* LSA ID is set to 0 for the Router Information. See RFC 4970 */
1008 tmp
= SET_OPAQUE_LSID(OPAQUE_TYPE_ROUTER_INFORMATION_LSA
, 0);
1009 lsah
.id
.s_addr
= htonl(tmp
);
1012 case REORIGINATE_THIS_LSA
:
1013 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
)
1014 ospf_opaque_lsa_reoriginate_schedule(
1015 (void *)OspfRI
.area
, OSPF_OPAQUE_AREA_LSA
,
1016 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
1018 ospf_opaque_lsa_reoriginate_schedule(
1019 (void *)top
, OSPF_OPAQUE_AS_LSA
,
1020 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
1022 case REFRESH_THIS_LSA
:
1023 ospf_opaque_lsa_refresh_schedule(&lsa
);
1025 case FLUSH_THIS_LSA
:
1026 UNSET_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
);
1027 ospf_opaque_lsa_flush_schedule(&lsa
);
1030 zlog_warn("ospf_router_info_lsa_schedule: Unknown opcode (%u)",
1038 /* Callback to handle Segment Routing information */
1039 static int ospf_router_info_lsa_update(struct ospf_lsa
*lsa
)
1044 zlog_warn("OSPF-RI (ospf_router_info_lsa_update): Abort! LSA is NULL");
1048 /* Check if it is not my LSA */
1049 if (IS_LSA_SELF(lsa
))
1052 /* Process only Router Information LSA */
1053 if (GET_OPAQUE_TYPE(
1054 ntohl(lsa
->data
->id
.s_addr
)) != OPAQUE_TYPE_ROUTER_INFORMATION_LSA
)
1057 /* Check if Router Info & Segment Routing are enable */
1058 if (!OspfRI
.enabled
|| !OspfRI
.sr_info
.enabled
)
1061 /* Call Segment Routing LSA update or deletion */
1062 if (!IS_LSA_MAXAGE(lsa
))
1063 ospf_sr_ri_lsa_update(lsa
);
1065 ospf_sr_ri_lsa_delete(lsa
);
1070 /*------------------------------------------------------------------------*
1071 * Followings are vty session control functions.
1072 *------------------------------------------------------------------------*/
1074 static u_int16_t
show_vty_router_cap(struct vty
*vty
,
1075 struct tlv_header
*tlvh
)
1077 struct ri_tlv_router_cap
*top
= (struct ri_tlv_router_cap
*)tlvh
;
1080 vty_out(vty
, " Router Capabilities: 0x%x\n",
1083 zlog_debug(" Router Capabilities: 0x%x", ntohl(top
->value
));
1085 return TLV_SIZE(tlvh
);
1088 static u_int16_t
show_vty_pce_subtlv_address(struct vty
*vty
,
1089 struct tlv_header
*tlvh
)
1091 struct ri_pce_subtlv_address
*top
=
1092 (struct ri_pce_subtlv_address
*)tlvh
;
1094 if (ntohs(top
->address
.type
) == PCE_ADDRESS_TYPE_IPV4
) {
1096 vty_out(vty
, " PCE Address: %s\n",
1097 inet_ntoa(top
->address
.value
));
1099 zlog_debug(" PCE Address: %s",
1100 inet_ntoa(top
->address
.value
));
1102 /* TODO: Add support to IPv6 with inet_ntop() */
1104 vty_out(vty
, " PCE Address: 0x%x\n",
1105 ntohl(top
->address
.value
.s_addr
));
1107 zlog_debug(" PCE Address: 0x%x",
1108 ntohl(top
->address
.value
.s_addr
));
1111 return TLV_SIZE(tlvh
);
1114 static u_int16_t
show_vty_pce_subtlv_path_scope(struct vty
*vty
,
1115 struct tlv_header
*tlvh
)
1117 struct ri_pce_subtlv_path_scope
*top
=
1118 (struct ri_pce_subtlv_path_scope
*)tlvh
;
1121 vty_out(vty
, " PCE Path Scope: 0x%x\n", ntohl(top
->value
));
1123 zlog_debug(" PCE Path Scope: 0x%x", ntohl(top
->value
));
1125 return TLV_SIZE(tlvh
);
1128 static u_int16_t
show_vty_pce_subtlv_domain(struct vty
*vty
,
1129 struct tlv_header
*tlvh
)
1131 struct ri_pce_subtlv_domain
*top
= (struct ri_pce_subtlv_domain
*)tlvh
;
1134 if (ntohs(top
->type
) == PCE_DOMAIN_TYPE_AREA
) {
1135 tmp
.s_addr
= top
->value
;
1137 vty_out(vty
, " PCE domain Area: %s\n", inet_ntoa(tmp
));
1139 zlog_debug(" PCE domain Area: %s", inet_ntoa(tmp
));
1142 vty_out(vty
, " PCE domain AS: %d\n",
1145 zlog_debug(" PCE domain AS: %d", ntohl(top
->value
));
1147 return TLV_SIZE(tlvh
);
1150 static u_int16_t
show_vty_pce_subtlv_neighbor(struct vty
*vty
,
1151 struct tlv_header
*tlvh
)
1154 struct ri_pce_subtlv_neighbor
*top
=
1155 (struct ri_pce_subtlv_neighbor
*)tlvh
;
1158 if (ntohs(top
->type
) == PCE_DOMAIN_TYPE_AREA
) {
1159 tmp
.s_addr
= top
->value
;
1161 vty_out(vty
, " PCE neighbor Area: %s\n",
1164 zlog_debug(" PCE neighbor Area: %s", inet_ntoa(tmp
));
1167 vty_out(vty
, " PCE neighbor AS: %d\n",
1170 zlog_debug(" PCE neighbor AS: %d",
1173 return TLV_SIZE(tlvh
);
1176 static u_int16_t
show_vty_pce_subtlv_cap_flag(struct vty
*vty
,
1177 struct tlv_header
*tlvh
)
1179 struct ri_pce_subtlv_cap_flag
*top
=
1180 (struct ri_pce_subtlv_cap_flag
*)tlvh
;
1183 vty_out(vty
, " PCE Capabilities Flag: 0x%x\n",
1186 zlog_debug(" PCE Capabilities Flag: 0x%x",
1189 return TLV_SIZE(tlvh
);
1192 static u_int16_t
show_vty_unknown_tlv(struct vty
*vty
,
1193 struct tlv_header
*tlvh
)
1196 vty_out(vty
, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
1197 ntohs(tlvh
->type
), ntohs(tlvh
->length
));
1199 zlog_debug(" Unknown TLV: [type(0x%x), length(0x%x)]",
1200 ntohs(tlvh
->type
), ntohs(tlvh
->length
));
1202 return TLV_SIZE(tlvh
);
1205 static u_int16_t
show_vty_pce_info(struct vty
*vty
, struct tlv_header
*ri
,
1208 struct tlv_header
*tlvh
;
1211 for (tlvh
= ri
; sum
< total
; tlvh
= TLV_HDR_NEXT(tlvh
)) {
1212 switch (ntohs(tlvh
->type
)) {
1213 case RI_PCE_SUBTLV_ADDRESS
:
1214 sum
+= show_vty_pce_subtlv_address(vty
, tlvh
);
1216 case RI_PCE_SUBTLV_PATH_SCOPE
:
1217 sum
+= show_vty_pce_subtlv_path_scope(vty
, tlvh
);
1219 case RI_PCE_SUBTLV_DOMAIN
:
1220 sum
+= show_vty_pce_subtlv_domain(vty
, tlvh
);
1222 case RI_PCE_SUBTLV_NEIGHBOR
:
1223 sum
+= show_vty_pce_subtlv_neighbor(vty
, tlvh
);
1225 case RI_PCE_SUBTLV_CAP_FLAG
:
1226 sum
+= show_vty_pce_subtlv_cap_flag(vty
, tlvh
);
1229 sum
+= show_vty_unknown_tlv(vty
, tlvh
);
1236 /* Display Segment Routing Algorithm TLV information */
1237 static uint16_t show_vty_sr_algorithm(struct vty
*vty
, struct tlv_header
*tlvh
)
1239 struct ri_sr_tlv_sr_algorithm
*algo
=
1240 (struct ri_sr_tlv_sr_algorithm
*)tlvh
;
1243 vty_out(vty
, " Segment Routing Algorithm TLV:\n");
1244 for (i
= 0; i
< ntohs(algo
->header
.length
); i
++) {
1245 switch (algo
->value
[i
]) {
1247 vty_out(vty
, " Algorithm %d: SPF\n", i
);
1250 vty_out(vty
, " Algorithm %d: Strict SPF\n",
1255 " Algorithm %d: Unknown value %d\n", i
,
1263 zlog_debug(" Segment Routing Algorithm TLV:\n");
1264 for (i
= 0; i
< ntohs(algo
->header
.length
); i
++)
1265 switch (algo
->value
[i
]) {
1267 zlog_debug(" Algorithm %d: SPF\n", i
);
1270 zlog_debug(" Algorithm %d: Strict SPF\n", i
);
1274 " Algorithm %d: Unknown value %d\n",
1280 return TLV_SIZE(tlvh
);
1283 /* Display Segment Routing SID/Label Range TLV information */
1284 static uint16_t show_vty_sr_range(struct vty
*vty
, struct tlv_header
*tlvh
)
1286 struct ri_sr_tlv_sid_label_range
*range
=
1287 (struct ri_sr_tlv_sid_label_range
*)tlvh
;
1291 " Segment Routing Range TLV:\n"
1292 " Range Size = %d\n"
1293 " SID Label = %d\n\n",
1294 GET_RANGE_SIZE(ntohl(range
->size
)),
1295 GET_LABEL(ntohl(range
->lower
.value
)));
1298 " Segment Routing Range TLV:\n"
1299 " Range Size = %d\n"
1300 " SID Label = %d\n\n",
1301 GET_RANGE_SIZE(ntohl(range
->size
)),
1302 GET_LABEL(ntohl(range
->lower
.value
)));
1305 return TLV_SIZE(tlvh
);
1308 /* Display Segment Routing Maximum Stack Depth TLV information */
1309 static uint16_t show_vty_sr_msd(struct vty
*vty
, struct tlv_header
*tlvh
)
1311 struct ri_sr_tlv_node_msd
*msd
= (struct ri_sr_tlv_node_msd
*)tlvh
;
1315 " Segment Routing MSD TLV:\n"
1316 " Node Maximum Stack Depth = %d\n",
1320 " Segment Routing MSD TLV:\n"
1321 " Node Maximum Stack Depth = %d\n",
1325 return TLV_SIZE(tlvh
);
1328 static void ospf_router_info_show_info(struct vty
*vty
, struct ospf_lsa
*lsa
)
1330 struct lsa_header
*lsah
= (struct lsa_header
*)lsa
->data
;
1331 struct tlv_header
*tlvh
;
1332 u_int16_t length
= 0, sum
= 0;
1334 /* Initialize TLV browsing */
1335 length
= ntohs(lsah
->length
) - OSPF_LSA_HEADER_SIZE
;
1337 for (tlvh
= TLV_HDR_TOP(lsah
); sum
< length
;
1338 tlvh
= TLV_HDR_NEXT(tlvh
)) {
1339 switch (ntohs(tlvh
->type
)) {
1340 case RI_TLV_CAPABILITIES
:
1341 sum
+= show_vty_router_cap(vty
, tlvh
);
1345 sum
+= TLV_HDR_SIZE
;
1346 sum
+= show_vty_pce_info(vty
, tlvh
, length
- sum
);
1348 case RI_SR_TLV_SR_ALGORITHM
:
1349 sum
+= show_vty_sr_algorithm(vty
, tlvh
);
1351 case RI_SR_TLV_SID_LABEL_RANGE
:
1352 sum
+= show_vty_sr_range(vty
, tlvh
);
1354 case RI_SR_TLV_NODE_MSD
:
1355 sum
+= show_vty_sr_msd(vty
, tlvh
);
1359 sum
+= show_vty_unknown_tlv(vty
, tlvh
);
1367 static void ospf_router_info_config_write_router(struct vty
*vty
)
1369 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1370 struct listnode
*node
;
1371 struct ri_pce_subtlv_domain
*domain
;
1372 struct ri_pce_subtlv_neighbor
*neighbor
;
1375 if (!OspfRI
.enabled
)
1378 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
)
1379 vty_out(vty
, " router-info as\n");
1381 vty_out(vty
, " router-info area %s\n",
1382 inet_ntoa(OspfRI
.area_id
));
1384 if (OspfRI
.pce_info
.enabled
) {
1386 if (pce
->pce_address
.header
.type
!= 0)
1387 vty_out(vty
, " pce address %s\n",
1388 inet_ntoa(pce
->pce_address
.address
.value
));
1390 if (pce
->pce_cap_flag
.header
.type
!= 0)
1391 vty_out(vty
, " pce flag 0x%x\n",
1392 ntohl(pce
->pce_cap_flag
.value
));
1394 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
1395 if (domain
->header
.type
!= 0) {
1396 if (domain
->type
== PCE_DOMAIN_TYPE_AREA
) {
1397 tmp
.s_addr
= domain
->value
;
1398 vty_out(vty
, " pce domain area %s\n",
1401 vty_out(vty
, " pce domain as %d\n",
1402 ntohl(domain
->value
));
1407 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
1408 if (neighbor
->header
.type
!= 0) {
1409 if (neighbor
->type
== PCE_DOMAIN_TYPE_AREA
) {
1410 tmp
.s_addr
= neighbor
->value
;
1411 vty_out(vty
, " pce neighbor area %s\n",
1414 vty_out(vty
, " pce neighbor as %d\n",
1415 ntohl(neighbor
->value
));
1420 if (pce
->pce_scope
.header
.type
!= 0)
1421 vty_out(vty
, " pce scope 0x%x\n",
1422 ntohl(OspfRI
.pce_info
.pce_scope
.value
));
1427 /*------------------------------------------------------------------------*
1428 * Followings are vty command functions.
1429 *------------------------------------------------------------------------*/
1432 router_info_area_cmd
,
1433 "router-info <as|area A.B.C.D>",
1435 "Enable the Router Information functionality with AS flooding scope\n"
1436 "Enable the Router Information functionality with Area flooding scope\n"
1437 "OSPF area ID in IP format\n")
1440 char *area
= (argc
== 3) ? argv
[idx_ipv4
]->arg
: NULL
;
1447 /* Check and get Area value if present */
1449 if (!inet_aton(area
, &OspfRI
.area_id
)) {
1450 vty_out(vty
, "%% specified Area ID %s is invalid\n",
1452 return CMD_WARNING_CONFIG_FAILED
;
1454 scope
= OSPF_OPAQUE_AREA_LSA
;
1456 OspfRI
.area_id
.s_addr
= 0;
1457 scope
= OSPF_OPAQUE_AS_LSA
;
1460 /* First start to register Router Information callbacks */
1461 if ((ospf_router_info_register(scope
)) != 0) {
1463 "Unable to register Router Information callbacks. Abort!");
1464 return CMD_WARNING_CONFIG_FAILED
;
1467 OspfRI
.enabled
= true;
1469 if (IS_DEBUG_OSPF_EVENT
)
1470 zlog_debug("RI-> Router Information (%s flooding): OFF -> ON",
1471 OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
? "Area"
1475 * Following code is intended to handle two cases;
1477 * 1) Router Information was disabled at startup time, but now become
1479 * 2) Router Information was once enabled then disabled, and now enabled
1483 initialize_params(&OspfRI
);
1485 /* Refresh RI LSA if already engaged */
1486 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
)) {
1487 zlog_debug ("RI-> Refresh LSA following configuration");
1488 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA
);
1490 zlog_debug("RI-> Initial origination following configuration");
1491 ospf_router_info_lsa_schedule(REORIGINATE_THIS_LSA
);
1497 DEFUN (no_router_info
,
1501 "Disable the Router Information functionality\n")
1504 if (!OspfRI
.enabled
)
1507 if (IS_DEBUG_OSPF_EVENT
)
1508 zlog_debug("RI-> Router Information: ON -> OFF");
1510 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1511 ospf_router_info_lsa_schedule(FLUSH_THIS_LSA
);
1513 /* Unregister the callbacks */
1514 ospf_router_info_unregister();
1516 OspfRI
.enabled
= false;
1521 static int ospf_ri_enabled(struct vty
*vty
)
1527 vty_out(vty
, "%% OSPF RI is not turned on\n");
1534 "pce address A.B.C.D",
1536 "Stable IP address of the PCE\n"
1537 "PCE address in IPv4 address format\n")
1540 struct in_addr value
;
1541 struct ospf_pce_info
*pi
= &OspfRI
.pce_info
;
1543 if (!ospf_ri_enabled(vty
))
1544 return CMD_WARNING_CONFIG_FAILED
;
1546 if (!inet_aton(argv
[idx_ipv4
]->arg
, &value
)) {
1547 vty_out(vty
, "Please specify PCE Address by A.B.C.D\n");
1548 return CMD_WARNING_CONFIG_FAILED
;
1551 if (ntohs(pi
->pce_address
.header
.type
) == 0
1552 || ntohl(pi
->pce_address
.address
.value
.s_addr
)
1553 != ntohl(value
.s_addr
)) {
1555 set_pce_address(value
, pi
);
1557 /* Refresh RI LSA if already engaged */
1558 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1559 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1565 DEFUN (no_pce_address
,
1567 "no pce address [A.B.C.D]",
1570 "Disable PCE address\n"
1571 "PCE address in IPv4 address format\n")
1574 unset_param(&OspfRI
.pce_info
.pce_address
.header
);
1576 /* Refresh RI LSA if already engaged */
1577 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1578 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1583 DEFUN (pce_path_scope
,
1585 "pce scope BITPATTERN",
1587 "Path scope visibilities of the PCE for path computation\n"
1588 "32-bit Hexadecimal value\n")
1590 int idx_bitpattern
= 2;
1592 struct ospf_pce_info
*pi
= &OspfRI
.pce_info
;
1594 if (!ospf_ri_enabled(vty
))
1595 return CMD_WARNING_CONFIG_FAILED
;
1597 if (sscanf(argv
[idx_bitpattern
]->arg
, "0x%x", &scope
) != 1) {
1598 vty_out(vty
, "pce_path_scope: fscanf: %s\n",
1599 safe_strerror(errno
));
1600 return CMD_WARNING_CONFIG_FAILED
;
1603 if (ntohl(pi
->pce_scope
.header
.type
) == 0
1604 || scope
!= pi
->pce_scope
.value
) {
1605 set_pce_path_scope(scope
, pi
);
1607 /* Refresh RI LSA if already engaged */
1608 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1609 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1615 DEFUN (no_pce_path_scope
,
1616 no_pce_path_scope_cmd
,
1617 "no pce scope [BITPATTERN]",
1620 "Disable PCE path scope\n"
1621 "32-bit Hexadecimal value\n")
1624 unset_param(&OspfRI
.pce_info
.pce_address
.header
);
1626 /* Refresh RI LSA if already engaged */
1627 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1628 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1635 "pce domain as (0-65535)",
1637 "Configure PCE domain AS number\n"
1638 "AS number where the PCE as visibilities for path computation\n"
1639 "AS number in decimal <0-65535>\n")
1644 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1645 struct listnode
*node
;
1646 struct ri_pce_subtlv_domain
*domain
;
1648 if (!ospf_ri_enabled(vty
))
1649 return CMD_WARNING_CONFIG_FAILED
;
1651 if (sscanf(argv
[idx_number
]->arg
, "%d", &as
) != 1) {
1652 vty_out(vty
, "pce_domain: fscanf: %s\n", safe_strerror(errno
));
1653 return CMD_WARNING_CONFIG_FAILED
;
1656 /* Check if the domain is not already in the domain list */
1657 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
1658 if (ntohl(domain
->header
.type
) == 0 && as
== domain
->value
)
1662 /* Create new domain if not found */
1663 set_pce_domain(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1665 /* Refresh RI LSA if already engaged */
1666 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1667 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1672 DEFUN (no_pce_domain
,
1674 "no pce domain as (0-65535)",
1677 "Disable PCE domain AS number\n"
1678 "AS number where the PCE as visibilities for path computation\n"
1679 "AS number in decimal <0-65535>\n")
1684 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1686 if (sscanf(argv
[idx_number
]->arg
, "%d", &as
) != 1) {
1687 vty_out(vty
, "no_pce_domain: fscanf: %s\n",
1688 safe_strerror(errno
));
1689 return CMD_WARNING_CONFIG_FAILED
;
1692 /* Unset corresponding PCE domain */
1693 unset_pce_domain(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1695 /* Refresh RI LSA if already engaged */
1696 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1697 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1702 DEFUN (pce_neigbhor
,
1704 "pce neighbor as (0-65535)",
1706 "Configure PCE neighbor domain AS number\n"
1707 "AS number of PCE neighbors\n"
1708 "AS number in decimal <0-65535>\n")
1713 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1714 struct listnode
*node
;
1715 struct ri_pce_subtlv_neighbor
*neighbor
;
1717 if (!ospf_ri_enabled(vty
))
1718 return CMD_WARNING_CONFIG_FAILED
;
1720 if (sscanf(argv
[idx_number
]->arg
, "%d", &as
) != 1) {
1721 vty_out(vty
, "pce_neighbor: fscanf: %s\n",
1722 safe_strerror(errno
));
1723 return CMD_WARNING_CONFIG_FAILED
;
1726 /* Check if the domain is not already in the domain list */
1727 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
1728 if (ntohl(neighbor
->header
.type
) == 0 && as
== neighbor
->value
)
1732 /* Create new domain if not found */
1733 set_pce_neighbor(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1735 /* Refresh RI LSA if already engaged */
1736 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1737 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1742 DEFUN (no_pce_neighbor
,
1743 no_pce_neighbor_cmd
,
1744 "no pce neighbor as (0-65535)",
1747 "Disable PCE neighbor AS number\n"
1748 "AS number of PCE neighbor\n"
1749 "AS number in decimal <0-65535>\n")
1754 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1756 if (sscanf(argv
[idx_number
]->arg
, "%d", &as
) != 1) {
1757 vty_out(vty
, "no_pce_neighbor: fscanf: %s\n",
1758 safe_strerror(errno
));
1759 return CMD_WARNING_CONFIG_FAILED
;
1762 /* Unset corresponding PCE domain */
1763 unset_pce_neighbor(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1765 /* Refresh RI LSA if already engaged */
1766 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1767 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1772 DEFUN (pce_cap_flag
,
1774 "pce flag BITPATTERN",
1776 "Capabilities of the PCE for path computation\n"
1777 "32-bit Hexadecimal value\n")
1779 int idx_bitpattern
= 2;
1782 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1784 if (!ospf_ri_enabled(vty
))
1785 return CMD_WARNING_CONFIG_FAILED
;
1787 if (sscanf(argv
[idx_bitpattern
]->arg
, "0x%x", &cap
) != 1) {
1788 vty_out(vty
, "pce_cap_flag: fscanf: %s\n",
1789 safe_strerror(errno
));
1790 return CMD_WARNING_CONFIG_FAILED
;
1793 if (ntohl(pce
->pce_cap_flag
.header
.type
) == 0
1794 || cap
!= pce
->pce_cap_flag
.value
) {
1795 set_pce_cap_flag(cap
, pce
);
1797 /* Refresh RI LSA if already engaged */
1798 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1799 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1805 DEFUN (no_pce_cap_flag
,
1806 no_pce_cap_flag_cmd
,
1810 "Disable PCE capabilities\n")
1813 unset_param(&OspfRI
.pce_info
.pce_cap_flag
.header
);
1815 /* Refresh RI LSA if already engaged */
1816 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1817 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1822 DEFUN (show_ip_ospf_router_info
,
1823 show_ip_ospf_router_info_cmd
,
1824 "show ip ospf router-info",
1828 "Router Information\n")
1831 if (OspfRI
.enabled
) {
1832 vty_out(vty
, "--- Router Information parameters ---\n");
1833 show_vty_router_cap(vty
, &OspfRI
.router_cap
.header
);
1837 " Router Information is disabled on this router\n");
1842 DEFUN (show_ip_opsf_router_info_pce
,
1843 show_ip_ospf_router_info_pce_cmd
,
1844 "show ip ospf router-info pce",
1848 "Router Information\n"
1849 "PCE information\n")
1852 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1853 struct listnode
*node
;
1854 struct ri_pce_subtlv_domain
*domain
;
1855 struct ri_pce_subtlv_neighbor
*neighbor
;
1857 if ((OspfRI
.enabled
) && (OspfRI
.pce_info
.enabled
)) {
1858 vty_out(vty
, "--- PCE parameters ---\n");
1860 if (pce
->pce_address
.header
.type
!= 0)
1861 show_vty_pce_subtlv_address(vty
,
1862 &pce
->pce_address
.header
);
1864 if (pce
->pce_scope
.header
.type
!= 0)
1865 show_vty_pce_subtlv_path_scope(vty
,
1866 &pce
->pce_scope
.header
);
1868 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
1869 if (domain
->header
.type
!= 0)
1870 show_vty_pce_subtlv_domain(vty
,
1874 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
1875 if (neighbor
->header
.type
!= 0)
1876 show_vty_pce_subtlv_neighbor(vty
,
1880 if (pce
->pce_cap_flag
.header
.type
!= 0)
1881 show_vty_pce_subtlv_cap_flag(vty
,
1882 &pce
->pce_cap_flag
.header
);
1886 " PCE info is disabled on this router\n");
1892 /* Install new CLI commands */
1893 static void ospf_router_info_register_vty(void)
1895 install_element(VIEW_NODE
, &show_ip_ospf_router_info_cmd
);
1896 install_element(VIEW_NODE
, &show_ip_ospf_router_info_pce_cmd
);
1898 install_element(OSPF_NODE
, &router_info_area_cmd
);
1899 install_element(OSPF_NODE
, &no_router_info_cmd
);
1900 install_element(OSPF_NODE
, &pce_address_cmd
);
1901 install_element(OSPF_NODE
, &no_pce_address_cmd
);
1902 install_element(OSPF_NODE
, &pce_path_scope_cmd
);
1903 install_element(OSPF_NODE
, &no_pce_path_scope_cmd
);
1904 install_element(OSPF_NODE
, &pce_domain_cmd
);
1905 install_element(OSPF_NODE
, &no_pce_domain_cmd
);
1906 install_element(OSPF_NODE
, &pce_neighbor_cmd
);
1907 install_element(OSPF_NODE
, &no_pce_neighbor_cmd
);
1908 install_element(OSPF_NODE
, &pce_cap_flag_cmd
);
1909 install_element(OSPF_NODE
, &no_pce_cap_flag_cmd
);