2 * This is an implementation of RFC4970 Router Information
3 * with support of RFC5088 PCE Capabilites announcement
5 * Module name: Router Information
7 * Created: 2012-02-01 by Olivier Dugeon
8 * Copyright (C) 2012 Orange Labs http://www.orange.com/
10 * This file is part of GNU Quagga.
12 * GNU Zebra is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2, or (at your option) any
17 * GNU Quagga is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
22 * You should have received a copy of the GNU General Public License along
23 * with this program; see the file COPYING; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
41 #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_ri.h"
59 #include "ospfd/ospf_te.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 /* Following structure are internal use only. */
73 struct ospf_router_info
{
79 /* Flags to manage this router information. */
80 #define RIFLG_LSA_ENGAGED 0x1
81 #define RIFLG_LSA_FORCED_REFRESH 0x2
84 /* area pointer if flooding is Type 10 Null if flooding is AS scope */
85 struct ospf_area
*area
;
86 struct in_addr area_id
;
88 /* Store Router Information Capabilities LSA */
89 struct ri_tlv_router_cap router_cap
;
91 /* Store PCE capability LSA */
92 struct ospf_pce_info pce_info
;
96 * Global variable to manage Opaque-LSA/Router Information on this node.
97 * Note that all parameter values are stored in network byte order.
99 static struct ospf_router_info OspfRI
;
101 /*------------------------------------------------------------------------------*
102 * Followings are initialize/terminate functions for Router Information
104 *------------------------------------------------------------------------------*/
106 static void ospf_router_info_ism_change(struct ospf_interface
*oi
,
108 static void ospf_router_info_nsm_change(struct ospf_neighbor
*nbr
,
110 static void ospf_router_info_config_write_router(struct vty
*vty
);
111 static void ospf_router_info_show_info(struct vty
*vty
, struct ospf_lsa
*lsa
);
112 static int ospf_router_info_lsa_originate(void *arg
);
113 static struct ospf_lsa
*ospf_router_info_lsa_refresh(struct ospf_lsa
*lsa
);
114 static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode
);
115 static void ospf_router_info_register_vty(void);
116 static void del_pce_info(void *val
);
118 int ospf_router_info_init(void)
121 memset(&OspfRI
, 0, sizeof(struct ospf_router_info
));
122 OspfRI
.enabled
= false;
123 OspfRI
.registered
= 0;
124 OspfRI
.scope
= OSPF_OPAQUE_AS_LSA
;
127 /* Initialize pce domain and neighbor list */
128 OspfRI
.pce_info
.enabled
= false;
129 OspfRI
.pce_info
.pce_domain
= list_new();
130 OspfRI
.pce_info
.pce_domain
->del
= del_pce_info
;
131 OspfRI
.pce_info
.pce_neighbor
= list_new();
132 OspfRI
.pce_info
.pce_neighbor
->del
= del_pce_info
;
134 ospf_router_info_register_vty();
139 static int ospf_router_info_register(u_int8_t scope
)
143 if (OspfRI
.registered
)
146 zlog_info("Register Router Information with scope %s(%d)",
147 scope
== OSPF_OPAQUE_AREA_LSA
? "Area" : "AS", scope
);
148 rc
= ospf_register_opaque_functab(
149 scope
, OPAQUE_TYPE_ROUTER_INFORMATION_LSA
,
150 NULL
, /* new interface */
151 NULL
, /* del interface */
152 ospf_router_info_ism_change
, ospf_router_info_nsm_change
,
153 ospf_router_info_config_write_router
,
154 NULL
, /* Config. write interface */
155 NULL
, /* Config. write debug */
156 ospf_router_info_show_info
, ospf_router_info_lsa_originate
,
157 ospf_router_info_lsa_refresh
, NULL
, /* new_lsa_hook */
158 NULL
); /* del_lsa_hook */
162 "ospf_router_info_init: Failed to register functions");
166 OspfRI
.registered
= 1;
167 OspfRI
.scope
= scope
;
171 static int ospf_router_info_unregister()
174 if ((OspfRI
.scope
!= OSPF_OPAQUE_AS_LSA
)
175 && (OspfRI
.scope
!= OSPF_OPAQUE_AREA_LSA
)) {
177 "Unable to unregister Router Info functions: Wrong scope!");
181 ospf_delete_opaque_functab(OspfRI
.scope
,
182 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
184 OspfRI
.registered
= 0;
188 void ospf_router_info_term(void)
191 list_delete_and_null(&OspfRI
.pce_info
.pce_domain
);
192 list_delete_and_null(&OspfRI
.pce_info
.pce_neighbor
);
194 OspfRI
.enabled
= false;
196 ospf_router_info_unregister();
201 static void del_pce_info(void *val
)
203 XFREE(MTYPE_OSPF_PCE_PARAMS
, val
);
207 /*------------------------------------------------------------------------*
208 * Followings are control functions for ROUTER INFORMATION parameters
210 *------------------------------------------------------------------------*/
212 static void set_router_info_capabilities(struct ri_tlv_router_cap
*ric
,
215 ric
->header
.type
= htons(RI_TLV_CAPABILITIES
);
216 ric
->header
.length
= htons(RI_TLV_LENGTH
);
217 ric
->value
= htonl(cap
);
221 static int set_pce_header(struct ospf_pce_info
*pce
)
223 u_int16_t length
= 0;
224 struct listnode
*node
;
225 struct ri_pce_subtlv_domain
*domain
;
226 struct ri_pce_subtlv_neighbor
*neighbor
;
229 if (ntohs(pce
->pce_address
.header
.type
) != 0)
230 length
+= TLV_SIZE(&pce
->pce_address
.header
);
233 if (ntohs(pce
->pce_scope
.header
.type
) != 0)
234 length
+= TLV_SIZE(&pce
->pce_scope
.header
);
237 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
238 if (ntohs(domain
->header
.type
) != 0)
239 length
+= TLV_SIZE(&domain
->header
);
243 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
244 if (ntohs(neighbor
->header
.type
) != 0)
245 length
+= TLV_SIZE(&neighbor
->header
);
248 /* PCE Capabilities */
249 if (ntohs(pce
->pce_cap_flag
.header
.type
) != 0)
250 length
+= TLV_SIZE(&pce
->pce_cap_flag
.header
);
253 pce
->pce_header
.header
.type
= htons(RI_TLV_PCE
);
254 pce
->pce_header
.header
.length
= htons(length
);
257 pce
->pce_header
.header
.type
= 0;
258 pce
->pce_header
.header
.length
= 0;
259 pce
->enabled
= false;
265 static void set_pce_address(struct in_addr ipv4
, struct ospf_pce_info
*pce
)
268 /* Enable PCE Info */
269 pce
->pce_header
.header
.type
= htons(RI_TLV_PCE
);
270 /* Set PCE Address */
271 pce
->pce_address
.header
.type
= htons(RI_PCE_SUBTLV_ADDRESS
);
272 pce
->pce_address
.header
.length
= htons(PCE_ADDRESS_LENGTH_IPV4
);
273 pce
->pce_address
.address
.type
= htons(PCE_ADDRESS_TYPE_IPV4
);
274 pce
->pce_address
.address
.value
= ipv4
;
279 static void set_pce_path_scope(u_int32_t scope
, struct ospf_pce_info
*pce
)
283 pce
->pce_scope
.header
.type
= htons(RI_PCE_SUBTLV_PATH_SCOPE
);
284 pce
->pce_scope
.header
.length
= htons(RI_TLV_LENGTH
);
285 pce
->pce_scope
.value
= htonl(scope
);
290 static void set_pce_domain(u_int16_t type
, u_int32_t domain
,
291 struct ospf_pce_info
*pce
)
294 struct ri_pce_subtlv_domain
*new;
296 /* Create new domain info */
297 new = XCALLOC(MTYPE_OSPF_PCE_PARAMS
,
298 sizeof(struct ri_pce_subtlv_domain
));
300 new->header
.type
= htons(RI_PCE_SUBTLV_DOMAIN
);
301 new->header
.length
= htons(PCE_ADDRESS_LENGTH_IPV4
);
302 new->type
= htons(type
);
303 new->value
= htonl(domain
);
305 /* Add new domain to the list */
306 listnode_add(pce
->pce_domain
, new);
311 static void unset_pce_domain(u_int16_t type
, u_int32_t domain
,
312 struct ospf_pce_info
*pce
)
314 struct listnode
*node
;
315 struct ri_pce_subtlv_domain
*old
= NULL
;
318 /* Search the corresponding node */
319 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, old
)) {
320 if ((old
->type
== htons(type
))
321 && (old
->value
== htonl(domain
))) {
327 /* if found remove it */
329 listnode_delete(pce
->pce_domain
, old
);
331 /* Avoid misjudgement in the next lookup. */
332 if (listcount(pce
->pce_domain
) == 0)
333 pce
->pce_domain
->head
= pce
->pce_domain
->tail
= NULL
;
335 /* Finally free the old domain */
336 XFREE(MTYPE_OSPF_PCE_PARAMS
, old
);
340 static void set_pce_neighbor(u_int16_t type
, u_int32_t domain
,
341 struct ospf_pce_info
*pce
)
344 struct ri_pce_subtlv_neighbor
*new;
346 /* Create new neighbor info */
347 new = XCALLOC(MTYPE_OSPF_PCE_PARAMS
,
348 sizeof(struct ri_pce_subtlv_neighbor
));
350 new->header
.type
= htons(RI_PCE_SUBTLV_NEIGHBOR
);
351 new->header
.length
= htons(PCE_ADDRESS_LENGTH_IPV4
);
352 new->type
= htons(type
);
353 new->value
= htonl(domain
);
355 /* Add new domain to the list */
356 listnode_add(pce
->pce_neighbor
, new);
361 static void unset_pce_neighbor(u_int16_t type
, u_int32_t domain
,
362 struct ospf_pce_info
*pce
)
364 struct listnode
*node
;
365 struct ri_pce_subtlv_neighbor
*old
= NULL
;
368 /* Search the corresponding node */
369 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, old
)) {
370 if ((old
->type
== htons(type
))
371 && (old
->value
== htonl(domain
))) {
377 /* if found remove it */
379 listnode_delete(pce
->pce_neighbor
, old
);
381 /* Avoid misjudgement in the next lookup. */
382 if (listcount(pce
->pce_neighbor
) == 0)
383 pce
->pce_neighbor
->head
= pce
->pce_neighbor
->tail
=
386 /* Finally free the old domain */
387 XFREE(MTYPE_OSPF_PCE_PARAMS
, old
);
391 static void set_pce_cap_flag(u_int32_t cap
, struct ospf_pce_info
*pce
)
394 /* Set PCE Capabilities flag */
395 pce
->pce_cap_flag
.header
.type
= htons(RI_PCE_SUBTLV_CAP_FLAG
);
396 pce
->pce_cap_flag
.header
.length
= htons(RI_TLV_LENGTH
);
397 pce
->pce_cap_flag
.value
= htonl(cap
);
403 static void unset_param(struct tlv_header
*tlv
)
407 /* Fill the Value to 0 */
408 memset(TLV_DATA(tlv
), 0, TLV_BODY_SIZE(tlv
));
414 static void initialize_params(struct ospf_router_info
*ori
)
420 * Initialize default Router Information Capabilities.
424 set_router_info_capabilities(&ori
->router_cap
, cap
);
426 /* If Area address is not null and exist, retrieve corresponding
428 top
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
429 zlog_info("RI-> Initialize Router Info for %s scope within area %s",
430 OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
? "Area" : "AS",
431 inet_ntoa(OspfRI
.area_id
));
433 /* Try to get the Area context at this step. Do it latter if not
435 if ((OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) && (OspfRI
.area
== NULL
))
436 OspfRI
.area
= ospf_area_lookup_by_area_id(top
, OspfRI
.area_id
);
439 * Initialize default PCE Information values
441 /* PCE address == OSPF Router ID */
442 set_pce_address(top
->router_id
, &ori
->pce_info
);
445 cap
= 7; /* Set L, R and Rd bits to one = intra & inter-area path
447 set_pce_path_scope(cap
, &ori
->pce_info
);
449 /* PCE Capabilities */
450 cap
= PCE_CAP_BIDIRECTIONAL
| PCE_CAP_DIVERSE_PATH
| PCE_CAP_OBJECTIVES
451 | PCE_CAP_ADDITIVE
| PCE_CAP_MULTIPLE_REQ
;
452 set_pce_cap_flag(cap
, &ori
->pce_info
);
457 static int is_mandated_params_set(struct ospf_router_info ori
)
461 if (ntohs(ori
.router_cap
.header
.type
) == 0)
464 if ((ntohs(ori
.pce_info
.pce_header
.header
.type
) == RI_TLV_PCE
)
465 && (ntohs(ori
.pce_info
.pce_address
.header
.type
) == 0)
466 && (ntohs(ori
.pce_info
.pce_cap_flag
.header
.type
) == 0))
474 /*------------------------------------------------------------------------*
475 * Followings are callback functions against generic Opaque-LSAs handling.
476 *------------------------------------------------------------------------*/
477 static void ospf_router_info_ism_change(struct ospf_interface
*oi
,
480 /* So far, nothing to do here. */
484 static void ospf_router_info_nsm_change(struct ospf_neighbor
*nbr
,
487 /* So far, nothing to do here. */
491 /*------------------------------------------------------------------------*
492 * Followings are OSPF protocol processing functions for ROUTER INFORMATION
493 *------------------------------------------------------------------------*/
495 static void build_tlv_header(struct stream
*s
, struct tlv_header
*tlvh
)
498 stream_put(s
, tlvh
, sizeof(struct tlv_header
));
502 static void build_tlv(struct stream
*s
, struct tlv_header
*tlvh
)
505 if (ntohs(tlvh
->type
) != 0) {
506 build_tlv_header(s
, tlvh
);
507 stream_put(s
, TLV_DATA(tlvh
), TLV_BODY_SIZE(tlvh
));
512 static void ospf_router_info_lsa_body_set(struct stream
*s
)
515 struct listnode
*node
;
516 struct ri_pce_subtlv_domain
*domain
;
517 struct ri_pce_subtlv_neighbor
*neighbor
;
519 /* Build Router Information TLV */
520 build_tlv(s
, &OspfRI
.router_cap
.header
);
522 /* Compute PCE Info header first */
523 set_pce_header (&OspfRI
.pce_info
);
525 /* Add RI PCE TLV if it is set */
526 if (OspfRI
.pce_info
.enabled
) {
529 build_tlv_header(s
, &OspfRI
.pce_info
.pce_header
.header
);
531 /* Build PCE address sub-tlv */
532 build_tlv(s
, &OspfRI
.pce_info
.pce_address
.header
);
534 /* Build PCE path scope sub-tlv */
535 build_tlv(s
, &OspfRI
.pce_info
.pce_scope
.header
);
537 /* Build PCE domain sub-tlv */
538 for (ALL_LIST_ELEMENTS_RO(OspfRI
.pce_info
.pce_domain
, node
,
540 build_tlv(s
, &domain
->header
);
542 /* Build PCE neighbor sub-tlv */
543 for (ALL_LIST_ELEMENTS_RO(OspfRI
.pce_info
.pce_neighbor
, node
,
545 build_tlv(s
, &neighbor
->header
);
547 /* Build PCE cap flag sub-tlv */
548 build_tlv(s
, &OspfRI
.pce_info
.pce_cap_flag
.header
);
554 /* Create new opaque-LSA. */
555 static struct ospf_lsa
*ospf_router_info_lsa_new()
559 struct lsa_header
*lsah
;
560 struct ospf_lsa
*new = NULL
;
561 u_char options
, lsa_type
;
562 struct in_addr lsa_id
;
566 /* Create a stream for LSA. */
567 if ((s
= stream_new(OSPF_MAX_LSA_SIZE
)) == NULL
) {
568 zlog_warn("ospf_router_info_lsa_new: stream_new() ?");
571 lsah
= (struct lsa_header
*)STREAM_DATA(s
);
573 options
= OSPF_OPTION_E
; /* Enable AS external as we flood RI with
575 options
|= OSPF_OPTION_O
; /* Don't forget this :-) */
577 lsa_type
= OspfRI
.scope
;
578 /* LSA ID == 0 for Router Information see RFC 4970 */
579 tmp
= SET_OPAQUE_LSID(OPAQUE_TYPE_ROUTER_INFORMATION_LSA
, 0);
580 lsa_id
.s_addr
= htonl(tmp
);
582 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
))
584 "LSA[Type%d:%s]: Create an Opaque-LSA/ROUTER INFORMATION instance",
585 lsa_type
, inet_ntoa(lsa_id
));
587 top
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
589 /* Set opaque-LSA header fields. */
590 lsa_header_set(s
, options
, lsa_type
, lsa_id
, top
->router_id
);
592 /* Set opaque-LSA body fields. */
593 ospf_router_info_lsa_body_set(s
);
596 length
= stream_get_endp(s
);
597 lsah
->length
= htons(length
);
599 /* Now, create an OSPF LSA instance. */
600 if ((new = ospf_lsa_new()) == NULL
) {
601 zlog_warn("ospf_router_info_lsa_new: ospf_lsa_new() ?");
605 if ((new->data
= ospf_lsa_data_new(length
)) == NULL
) {
606 zlog_warn("ospf_router_info_lsa_new: ospf_lsa_data_new() ?");
607 ospf_lsa_unlock(&new);
613 new->area
= OspfRI
.area
; /* Area must be null if the Opaque type is AS
614 scope, fulfill otherwise */
616 if (new->area
&& new->area
->ospf
)
617 new->vrf_id
= new->area
->ospf
->vrf_id
;
619 new->vrf_id
= VRF_DEFAULT
;
621 SET_FLAG(new->flags
, OSPF_LSA_SELF
);
622 memcpy(new->data
, lsah
, length
);
628 static int ospf_router_info_lsa_originate1(void *arg
)
630 struct ospf_lsa
*new;
632 struct ospf_area
*area
;
634 vrf_id_t vrf_id
= VRF_DEFAULT
;
636 /* First check if the area is known if flooding scope is Area */
637 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) {
638 area
= (struct ospf_area
*)arg
;
639 if (area
->area_id
.s_addr
!= OspfRI
.area_id
.s_addr
) {
641 "RI -> This is not the Router Information Area. Stop processing");
646 vrf_id
= area
->ospf
->vrf_id
;
649 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
650 if ((new = ospf_router_info_lsa_new()) == NULL
) {
652 "ospf_router_info_lsa_originate1: ospf_router_info_lsa_new() ?");
655 new->vrf_id
= vrf_id
;
658 top
= ospf_lookup_by_vrf_id(vrf_id
);
660 zlog_debug("%s: ospf instance not found for vrf id %u",
661 __PRETTY_FUNCTION__
, vrf_id
);
662 ospf_lsa_unlock(&new);
666 /* Install this LSA into LSDB. */
667 if (ospf_lsa_install(top
, NULL
/*oi */, new) == NULL
) {
669 "ospf_router_info_lsa_originate1: ospf_lsa_install() ?");
670 ospf_lsa_unlock(&new);
674 /* Now this Router Info parameter entry has associated LSA. */
675 SET_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
);
677 /* Update new LSA origination count. */
678 top
->lsa_originate_count
++;
680 /* Flood new LSA through AS. */
681 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
)
682 ospf_flood_through_as(top
, NULL
/*nbr */, new);
684 ospf_flood_through_area(OspfRI
.area
, NULL
/*nbr */, new);
686 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
688 "LSA[Type%d:%s]: Originate Opaque-LSA/ROUTER INFORMATION",
689 new->data
->type
, inet_ntoa(new->data
->id
));
690 ospf_lsa_header_dump(new->data
);
697 static int ospf_router_info_lsa_originate(void *arg
)
702 if (!OspfRI
.enabled
) {
704 "ospf_router_info_lsa_originate: ROUTER INFORMATION is disabled now.");
705 rc
= 0; /* This is not an error case. */
709 /* Check if Router Information LSA is already engaged */
710 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
)) {
711 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_FORCED_REFRESH
)) {
712 UNSET_FLAG(OspfRI
.flags
, RIFLG_LSA_FORCED_REFRESH
);
713 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
716 if (!is_mandated_params_set(OspfRI
))
718 "ospf_router_info_lsa_originate: lacks mandated ROUTER INFORMATION parameters");
720 /* Ok, let's try to originate an LSA */
721 if (ospf_router_info_lsa_originate1(arg
) != 0)
729 static struct ospf_lsa
*ospf_router_info_lsa_refresh(struct ospf_lsa
*lsa
)
731 struct ospf_lsa
*new = NULL
;
734 if (!OspfRI
.enabled
) {
736 * This LSA must have flushed before due to ROUTER INFORMATION
738 * It seems a slip among routers in the routing domain.
741 "ospf_router_info_lsa_refresh: ROUTER INFORMATION is disabled now.");
743 htons(OSPF_LSA_MAXAGE
); /* Flush it anyway. */
746 /* Verify that the Router Information ID is supported */
747 if (GET_OPAQUE_ID(ntohl(lsa
->data
->id
.s_addr
)) != 0) {
749 "ospf_router_info_lsa_refresh: Unsupported Router Information ID");
753 /* If the lsa's age reached to MaxAge, start flushing procedure. */
754 if (IS_LSA_MAXAGE(lsa
)) {
755 UNSET_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
);
756 ospf_opaque_lsa_flush_schedule(lsa
);
760 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
761 if ((new = ospf_router_info_lsa_new()) == NULL
) {
763 "ospf_router_info_lsa_refresh: ospf_router_info_lsa_new() ?");
766 new->data
->ls_seqnum
= lsa_seqnum_increment(lsa
);
767 new->vrf_id
= lsa
->vrf_id
;
769 /* Install this LSA into LSDB. */
770 /* Given "lsa" will be freed in the next function. */
771 top
= ospf_lookup_by_vrf_id(lsa
->vrf_id
);
772 if (ospf_lsa_install(top
, NULL
/*oi */, new) == NULL
) {
773 zlog_warn("ospf_router_info_lsa_refresh: ospf_lsa_install() ?");
774 ospf_lsa_unlock(&new);
778 /* Flood updated LSA through AS or AREA depending of OspfRI.scope. */
779 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
)
780 ospf_flood_through_as(top
, NULL
/*nbr */, new);
782 ospf_flood_through_area(OspfRI
.area
, NULL
/*nbr */, new);
785 if (IS_DEBUG_OSPF(lsa
, LSA_GENERATE
)) {
787 "LSA[Type%d:%s]: Refresh Opaque-LSA/ROUTER INFORMATION",
788 new->data
->type
, inet_ntoa(new->data
->id
));
789 ospf_lsa_header_dump(new->data
);
795 static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode
)
798 struct lsa_header lsah
;
802 memset(&lsa
, 0, sizeof(lsa
));
803 memset(&lsah
, 0, sizeof(lsah
));
805 zlog_debug("RI-> LSA schedule %s%s%s",
806 opcode
== REORIGINATE_THIS_LSA
? "Re-Originate" : "",
807 opcode
== REFRESH_THIS_LSA
? "Refresh" : "",
808 opcode
== FLUSH_THIS_LSA
? "Flush" : "");
810 /* Check LSA flags state coherence */
811 if (!CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
) && (opcode
!= REORIGINATE_THIS_LSA
))
814 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
) && (opcode
== REORIGINATE_THIS_LSA
))
815 opcode
= REFRESH_THIS_LSA
;
817 top
= ospf_lookup_by_vrf_id(VRF_DEFAULT
);
818 if ((OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) && (OspfRI
.area
== NULL
)) {
820 "ospf_router_info_lsa_schedule(): Router Info is Area scope flooding but area is not set");
821 OspfRI
.area
= ospf_area_lookup_by_area_id(top
, OspfRI
.area_id
);
823 lsa
.area
= OspfRI
.area
;
825 lsah
.type
= OspfRI
.scope
;
827 /* LSA ID is set to 0 for the Router Information. See RFC 4970 */
828 tmp
= SET_OPAQUE_LSID(OPAQUE_TYPE_ROUTER_INFORMATION_LSA
, 0);
829 lsah
.id
.s_addr
= htonl(tmp
);
832 case REORIGINATE_THIS_LSA
:
833 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
)
834 ospf_opaque_lsa_reoriginate_schedule(
835 (void *)OspfRI
.area
, OSPF_OPAQUE_AREA_LSA
,
836 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
838 ospf_opaque_lsa_reoriginate_schedule(
839 (void *)top
, OSPF_OPAQUE_AS_LSA
,
840 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
842 case REFRESH_THIS_LSA
:
843 ospf_opaque_lsa_refresh_schedule(&lsa
);
846 UNSET_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
);
847 ospf_opaque_lsa_flush_schedule(&lsa
);
850 zlog_warn("ospf_router_info_lsa_schedule: Unknown opcode (%u)",
858 /*------------------------------------------------------------------------*
859 * Followings are vty session control functions.
860 *------------------------------------------------------------------------*/
862 static u_int16_t
show_vty_router_cap(struct vty
*vty
,
863 struct tlv_header
*tlvh
)
865 struct ri_tlv_router_cap
*top
= (struct ri_tlv_router_cap
*)tlvh
;
868 vty_out(vty
, " Router Capabilities: 0x%x\n",
871 zlog_debug(" Router Capabilities: 0x%x", ntohl(top
->value
));
873 return TLV_SIZE(tlvh
);
876 static u_int16_t
show_vty_pce_subtlv_address(struct vty
*vty
,
877 struct tlv_header
*tlvh
)
879 struct ri_pce_subtlv_address
*top
=
880 (struct ri_pce_subtlv_address
*)tlvh
;
882 if (ntohs(top
->address
.type
) == PCE_ADDRESS_TYPE_IPV4
) {
884 vty_out(vty
, " PCE Address: %s\n",
885 inet_ntoa(top
->address
.value
));
887 zlog_debug(" PCE Address: %s",
888 inet_ntoa(top
->address
.value
));
890 /* TODO: Add support to IPv6 with inet_ntop() */
892 vty_out(vty
, " PCE Address: 0x%x\n",
893 ntohl(top
->address
.value
.s_addr
));
895 zlog_debug(" PCE Address: 0x%x",
896 ntohl(top
->address
.value
.s_addr
));
899 return TLV_SIZE(tlvh
);
902 static u_int16_t
show_vty_pce_subtlv_path_scope(struct vty
*vty
,
903 struct tlv_header
*tlvh
)
905 struct ri_pce_subtlv_path_scope
*top
=
906 (struct ri_pce_subtlv_path_scope
*)tlvh
;
909 vty_out(vty
, " PCE Path Scope: 0x%x\n", ntohl(top
->value
));
911 zlog_debug(" PCE Path Scope: 0x%x", ntohl(top
->value
));
913 return TLV_SIZE(tlvh
);
916 static u_int16_t
show_vty_pce_subtlv_domain(struct vty
*vty
,
917 struct tlv_header
*tlvh
)
919 struct ri_pce_subtlv_domain
*top
= (struct ri_pce_subtlv_domain
*)tlvh
;
922 if (ntohs(top
->type
) == PCE_DOMAIN_TYPE_AREA
) {
923 tmp
.s_addr
= top
->value
;
925 vty_out(vty
, " PCE domain Area: %s\n", inet_ntoa(tmp
));
927 zlog_debug(" PCE domain Area: %s", inet_ntoa(tmp
));
930 vty_out(vty
, " PCE domain AS: %d\n",
933 zlog_debug(" PCE domain AS: %d", ntohl(top
->value
));
935 return TLV_SIZE(tlvh
);
938 static u_int16_t
show_vty_pce_subtlv_neighbor(struct vty
*vty
,
939 struct tlv_header
*tlvh
)
942 struct ri_pce_subtlv_neighbor
*top
=
943 (struct ri_pce_subtlv_neighbor
*)tlvh
;
946 if (ntohs(top
->type
) == PCE_DOMAIN_TYPE_AREA
) {
947 tmp
.s_addr
= top
->value
;
949 vty_out(vty
, " PCE neighbor Area: %s\n",
952 zlog_debug(" PCE neighbor Area: %s", inet_ntoa(tmp
));
955 vty_out(vty
, " PCE neighbor AS: %d\n",
958 zlog_debug(" PCE neighbor AS: %d",
961 return TLV_SIZE(tlvh
);
964 static u_int16_t
show_vty_pce_subtlv_cap_flag(struct vty
*vty
,
965 struct tlv_header
*tlvh
)
967 struct ri_pce_subtlv_cap_flag
*top
=
968 (struct ri_pce_subtlv_cap_flag
*)tlvh
;
971 vty_out(vty
, " PCE Capabilities Flag: 0x%x\n",
974 zlog_debug(" PCE Capabilities Flag: 0x%x",
977 return TLV_SIZE(tlvh
);
980 static u_int16_t
show_vty_unknown_tlv(struct vty
*vty
,
981 struct tlv_header
*tlvh
)
984 vty_out(vty
, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
985 ntohs(tlvh
->type
), ntohs(tlvh
->length
));
987 zlog_debug(" Unknown TLV: [type(0x%x), length(0x%x)]",
988 ntohs(tlvh
->type
), ntohs(tlvh
->length
));
990 return TLV_SIZE(tlvh
);
993 static u_int16_t
show_vty_pce_info(struct vty
*vty
, struct tlv_header
*ri
,
996 struct tlv_header
*tlvh
;
999 for (tlvh
= ri
; sum
< total
; tlvh
= TLV_HDR_NEXT(tlvh
)) {
1000 switch (ntohs(tlvh
->type
)) {
1001 case RI_PCE_SUBTLV_ADDRESS
:
1002 sum
+= show_vty_pce_subtlv_address(vty
, tlvh
);
1004 case RI_PCE_SUBTLV_PATH_SCOPE
:
1005 sum
+= show_vty_pce_subtlv_path_scope(vty
, tlvh
);
1007 case RI_PCE_SUBTLV_DOMAIN
:
1008 sum
+= show_vty_pce_subtlv_domain(vty
, tlvh
);
1010 case RI_PCE_SUBTLV_NEIGHBOR
:
1011 sum
+= show_vty_pce_subtlv_neighbor(vty
, tlvh
);
1013 case RI_PCE_SUBTLV_CAP_FLAG
:
1014 sum
+= show_vty_pce_subtlv_cap_flag(vty
, tlvh
);
1017 sum
+= show_vty_unknown_tlv(vty
, tlvh
);
1024 static void ospf_router_info_show_info(struct vty
*vty
, struct ospf_lsa
*lsa
)
1026 struct lsa_header
*lsah
= (struct lsa_header
*)lsa
->data
;
1027 struct tlv_header
*tlvh
;
1028 u_int16_t length
= 0, sum
= 0;
1030 /* Initialize TLV browsing */
1031 length
= ntohs(lsah
->length
) - OSPF_LSA_HEADER_SIZE
;
1033 for (tlvh
= TLV_HDR_TOP(lsah
); sum
< length
;
1034 tlvh
= TLV_HDR_NEXT(tlvh
)) {
1035 switch (ntohs(tlvh
->type
)) {
1036 case RI_TLV_CAPABILITIES
:
1037 sum
+= show_vty_router_cap(vty
, tlvh
);
1041 sum
+= TLV_HDR_SIZE
;
1042 sum
+= show_vty_pce_info(vty
, tlvh
, length
- sum
);
1045 sum
+= show_vty_unknown_tlv(vty
, tlvh
);
1053 static void ospf_router_info_config_write_router(struct vty
*vty
)
1055 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1056 struct listnode
*node
;
1057 struct ri_pce_subtlv_domain
*domain
;
1058 struct ri_pce_subtlv_neighbor
*neighbor
;
1061 if (OspfRI
.enabled
) {
1062 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
)
1063 vty_out(vty
, " router-info as\n");
1065 vty_out(vty
, " router-info area %s\n",
1066 inet_ntoa(OspfRI
.area_id
));
1068 if (OspfRI
.pce_info
.enabled
) {
1070 if (pce
->pce_address
.header
.type
!= 0)
1071 vty_out(vty
, " pce address %s\n",
1072 inet_ntoa(pce
->pce_address
.address
.value
));
1074 if (pce
->pce_cap_flag
.header
.type
!= 0)
1075 vty_out(vty
, " pce flag 0x%x\n",
1076 ntohl(pce
->pce_cap_flag
.value
));
1078 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
1079 if (domain
->header
.type
!= 0) {
1080 if (domain
->type
== PCE_DOMAIN_TYPE_AREA
) {
1081 tmp
.s_addr
= domain
->value
;
1082 vty_out(vty
, " pce domain area %s\n",
1085 vty_out(vty
, " pce domain as %d\n",
1086 ntohl(domain
->value
));
1091 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
1092 if (neighbor
->header
.type
!= 0) {
1093 if (neighbor
->type
== PCE_DOMAIN_TYPE_AREA
) {
1094 tmp
.s_addr
= neighbor
->value
;
1095 vty_out(vty
, " pce neighbor area %s\n",
1098 vty_out(vty
, " pce neighbor as %d\n",
1099 ntohl(neighbor
->value
));
1104 if (pce
->pce_scope
.header
.type
!= 0)
1105 vty_out(vty
, " pce scope 0x%x\n",
1106 ntohl(OspfRI
.pce_info
.pce_scope
.value
));
1112 /*------------------------------------------------------------------------*
1113 * Followings are vty command functions.
1114 *------------------------------------------------------------------------*/
1117 router_info_area_cmd
,
1118 "router-info <as|area A.B.C.D>",
1120 "Enable the Router Information functionality with AS flooding scope\n"
1121 "Enable the Router Information functionality with Area flooding scope\n"
1122 "OSPF area ID in IP format\n")
1125 char *area
= (argc
== 3) ? argv
[idx_ipv4
]->arg
: NULL
;
1132 /* Check and get Area value if present */
1134 if (!inet_aton(area
, &OspfRI
.area_id
)) {
1135 vty_out(vty
, "%% specified Area ID %s is invalid\n",
1137 return CMD_WARNING_CONFIG_FAILED
;
1139 scope
= OSPF_OPAQUE_AREA_LSA
;
1141 OspfRI
.area_id
.s_addr
= 0;
1142 scope
= OSPF_OPAQUE_AS_LSA
;
1145 /* First start to register Router Information callbacks */
1146 if ((ospf_router_info_register(scope
)) != 0) {
1148 "Unable to register Router Information callbacks. Abort!");
1149 return CMD_WARNING_CONFIG_FAILED
;
1152 OspfRI
.enabled
= true;
1154 if (IS_DEBUG_OSPF_EVENT
)
1155 zlog_debug("RI-> Router Information (%s flooding): OFF -> ON",
1156 OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
? "Area"
1160 * Following code is intended to handle two cases;
1162 * 1) Router Information was disabled at startup time, but now become
1164 * 2) Router Information was once enabled then disabled, and now enabled
1168 initialize_params(&OspfRI
);
1170 /* Refresh RI LSA if already engaged */
1171 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
)) {
1172 zlog_debug ("RI-> Refresh LSA following configuration");
1173 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA
);
1175 zlog_debug("RI-> Initial origination following configuration");
1176 ospf_router_info_lsa_schedule(REORIGINATE_THIS_LSA
);
1182 DEFUN (no_router_info
,
1186 "Disable the Router Information functionality\n")
1189 if (!OspfRI
.enabled
)
1192 if (IS_DEBUG_OSPF_EVENT
)
1193 zlog_debug("RI-> Router Information: ON -> OFF");
1195 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1196 ospf_router_info_lsa_schedule(FLUSH_THIS_LSA
);
1198 /* Unregister the callbacks */
1199 ospf_router_info_unregister();
1201 OspfRI
.enabled
= false;
1206 static int ospf_ri_enabled(struct vty
*vty
)
1212 vty_out(vty
, "%% OSPF RI is not turned on\n");
1219 "pce address A.B.C.D",
1221 "Stable IP address of the PCE\n"
1222 "PCE address in IPv4 address format\n")
1225 struct in_addr value
;
1226 struct ospf_pce_info
*pi
= &OspfRI
.pce_info
;
1228 if (!ospf_ri_enabled(vty
))
1229 return CMD_WARNING_CONFIG_FAILED
;
1231 if (!inet_aton(argv
[idx_ipv4
]->arg
, &value
)) {
1232 vty_out(vty
, "Please specify PCE Address by A.B.C.D\n");
1233 return CMD_WARNING_CONFIG_FAILED
;
1236 if (ntohs(pi
->pce_address
.header
.type
) == 0
1237 || ntohl(pi
->pce_address
.address
.value
.s_addr
)
1238 != ntohl(value
.s_addr
)) {
1240 set_pce_address(value
, pi
);
1242 /* Refresh RI LSA if already engaged */
1243 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1244 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1250 DEFUN (no_pce_address
,
1252 "no pce address [A.B.C.D]",
1255 "Disable PCE address\n"
1256 "PCE address in IPv4 address format\n")
1259 unset_param(&OspfRI
.pce_info
.pce_address
.header
);
1261 /* Refresh RI LSA if already engaged */
1262 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1263 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1268 DEFUN (pce_path_scope
,
1270 "pce scope BITPATTERN",
1272 "Path scope visibilities of the PCE for path computation\n"
1273 "32-bit Hexadecimal value\n")
1275 int idx_bitpattern
= 2;
1277 struct ospf_pce_info
*pi
= &OspfRI
.pce_info
;
1279 if (!ospf_ri_enabled(vty
))
1280 return CMD_WARNING_CONFIG_FAILED
;
1282 if (sscanf(argv
[idx_bitpattern
]->arg
, "0x%x", &scope
) != 1) {
1283 vty_out(vty
, "pce_path_scope: fscanf: %s\n",
1284 safe_strerror(errno
));
1285 return CMD_WARNING_CONFIG_FAILED
;
1288 if (ntohl(pi
->pce_scope
.header
.type
) == 0
1289 || scope
!= pi
->pce_scope
.value
) {
1290 set_pce_path_scope(scope
, pi
);
1292 /* Refresh RI LSA if already engaged */
1293 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1294 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1300 DEFUN (no_pce_path_scope
,
1301 no_pce_path_scope_cmd
,
1302 "no pce scope [BITPATTERN]",
1305 "Disable PCE path scope\n"
1306 "32-bit Hexadecimal value\n")
1309 unset_param(&OspfRI
.pce_info
.pce_address
.header
);
1311 /* Refresh RI LSA if already engaged */
1312 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1313 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1320 "pce domain as (0-65535)",
1322 "Configure PCE domain AS number\n"
1323 "AS number where the PCE as visibilities for path computation\n"
1324 "AS number in decimal <0-65535>\n")
1329 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1330 struct listnode
*node
;
1331 struct ri_pce_subtlv_domain
*domain
;
1333 if (!ospf_ri_enabled(vty
))
1334 return CMD_WARNING_CONFIG_FAILED
;
1336 if (sscanf(argv
[idx_number
]->arg
, "%d", &as
) != 1) {
1337 vty_out(vty
, "pce_domain: fscanf: %s\n", safe_strerror(errno
));
1338 return CMD_WARNING_CONFIG_FAILED
;
1341 /* Check if the domain is not already in the domain list */
1342 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
1343 if (ntohl(domain
->header
.type
) == 0 && as
== domain
->value
)
1347 /* Create new domain if not found */
1348 set_pce_domain(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1350 /* Refresh RI LSA if already engaged */
1351 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1352 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1357 DEFUN (no_pce_domain
,
1359 "no pce domain as (0-65535)",
1362 "Disable PCE domain AS number\n"
1363 "AS number where the PCE as visibilities for path computation\n"
1364 "AS number in decimal <0-65535>\n")
1369 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1371 if (sscanf(argv
[idx_number
]->arg
, "%d", &as
) != 1) {
1372 vty_out(vty
, "no_pce_domain: fscanf: %s\n",
1373 safe_strerror(errno
));
1374 return CMD_WARNING_CONFIG_FAILED
;
1377 /* Unset corresponding PCE domain */
1378 unset_pce_domain(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1380 /* Refresh RI LSA if already engaged */
1381 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1382 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1387 DEFUN (pce_neigbhor
,
1389 "pce neighbor as (0-65535)",
1391 "Configure PCE neighbor domain AS number\n"
1392 "AS number of PCE neighbors\n"
1393 "AS number in decimal <0-65535>\n")
1398 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1399 struct listnode
*node
;
1400 struct ri_pce_subtlv_neighbor
*neighbor
;
1402 if (!ospf_ri_enabled(vty
))
1403 return CMD_WARNING_CONFIG_FAILED
;
1405 if (sscanf(argv
[idx_number
]->arg
, "%d", &as
) != 1) {
1406 vty_out(vty
, "pce_neighbor: fscanf: %s\n",
1407 safe_strerror(errno
));
1408 return CMD_WARNING_CONFIG_FAILED
;
1411 /* Check if the domain is not already in the domain list */
1412 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
1413 if (ntohl(neighbor
->header
.type
) == 0 && as
== neighbor
->value
)
1417 /* Create new domain if not found */
1418 set_pce_neighbor(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1420 /* Refresh RI LSA if already engaged */
1421 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1422 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1427 DEFUN (no_pce_neighbor
,
1428 no_pce_neighbor_cmd
,
1429 "no pce neighbor as (0-65535)",
1432 "Disable PCE neighbor AS number\n"
1433 "AS number of PCE neighbor\n"
1434 "AS number in decimal <0-65535>\n")
1439 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1441 if (sscanf(argv
[idx_number
]->arg
, "%d", &as
) != 1) {
1442 vty_out(vty
, "no_pce_neighbor: fscanf: %s\n",
1443 safe_strerror(errno
));
1444 return CMD_WARNING_CONFIG_FAILED
;
1447 /* Unset corresponding PCE domain */
1448 unset_pce_neighbor(PCE_DOMAIN_TYPE_AS
, as
, pce
);
1450 /* Refresh RI LSA if already engaged */
1451 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1452 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1457 DEFUN (pce_cap_flag
,
1459 "pce flag BITPATTERN",
1461 "Capabilities of the PCE for path computation\n"
1462 "32-bit Hexadecimal value\n")
1464 int idx_bitpattern
= 2;
1467 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1469 if (!ospf_ri_enabled(vty
))
1470 return CMD_WARNING_CONFIG_FAILED
;
1472 if (sscanf(argv
[idx_bitpattern
]->arg
, "0x%x", &cap
) != 1) {
1473 vty_out(vty
, "pce_cap_flag: fscanf: %s\n",
1474 safe_strerror(errno
));
1475 return CMD_WARNING_CONFIG_FAILED
;
1478 if (ntohl(pce
->pce_cap_flag
.header
.type
) == 0
1479 || cap
!= pce
->pce_cap_flag
.value
) {
1480 set_pce_cap_flag(cap
, pce
);
1482 /* Refresh RI LSA if already engaged */
1483 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1484 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1490 DEFUN (no_pce_cap_flag
,
1491 no_pce_cap_flag_cmd
,
1495 "Disable PCE capabilities\n")
1498 unset_param(&OspfRI
.pce_info
.pce_cap_flag
.header
);
1500 /* Refresh RI LSA if already engaged */
1501 if (CHECK_FLAG(OspfRI
.flags
, RIFLG_LSA_ENGAGED
))
1502 ospf_router_info_lsa_schedule(REFRESH_THIS_LSA
);
1507 DEFUN (show_ip_ospf_router_info
,
1508 show_ip_ospf_router_info_cmd
,
1509 "show ip ospf router-info",
1513 "Router Information\n")
1516 if (OspfRI
.enabled
) {
1517 vty_out(vty
, "--- Router Information parameters ---\n");
1518 show_vty_router_cap(vty
, &OspfRI
.router_cap
.header
);
1522 " Router Information is disabled on this router\n");
1527 DEFUN (show_ip_opsf_router_info_pce
,
1528 show_ip_ospf_router_info_pce_cmd
,
1529 "show ip ospf router-info pce",
1533 "Router Information\n"
1534 "PCE information\n")
1537 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1538 struct listnode
*node
;
1539 struct ri_pce_subtlv_domain
*domain
;
1540 struct ri_pce_subtlv_neighbor
*neighbor
;
1542 if (OspfRI
.enabled
) {
1543 vty_out(vty
, "--- PCE parameters ---\n");
1545 if (pce
->pce_address
.header
.type
!= 0)
1546 show_vty_pce_subtlv_address(vty
,
1547 &pce
->pce_address
.header
);
1549 if (pce
->pce_scope
.header
.type
!= 0)
1550 show_vty_pce_subtlv_path_scope(vty
,
1551 &pce
->pce_scope
.header
);
1553 for (ALL_LIST_ELEMENTS_RO(pce
->pce_domain
, node
, domain
)) {
1554 if (domain
->header
.type
!= 0)
1555 show_vty_pce_subtlv_domain(vty
,
1559 for (ALL_LIST_ELEMENTS_RO(pce
->pce_neighbor
, node
, neighbor
)) {
1560 if (neighbor
->header
.type
!= 0)
1561 show_vty_pce_subtlv_neighbor(vty
,
1565 if (pce
->pce_cap_flag
.header
.type
!= 0)
1566 show_vty_pce_subtlv_cap_flag(vty
,
1567 &pce
->pce_cap_flag
.header
);
1571 " Router Information is disabled on this router\n");
1577 /* Install new CLI commands */
1578 static void ospf_router_info_register_vty(void)
1580 install_element(VIEW_NODE
, &show_ip_ospf_router_info_cmd
);
1581 install_element(VIEW_NODE
, &show_ip_ospf_router_info_pce_cmd
);
1583 install_element(OSPF_NODE
, &router_info_area_cmd
);
1584 install_element(OSPF_NODE
, &no_router_info_cmd
);
1585 install_element(OSPF_NODE
, &pce_address_cmd
);
1586 install_element(OSPF_NODE
, &no_pce_address_cmd
);
1587 install_element(OSPF_NODE
, &pce_path_scope_cmd
);
1588 install_element(OSPF_NODE
, &no_pce_path_scope_cmd
);
1589 install_element(OSPF_NODE
, &pce_domain_cmd
);
1590 install_element(OSPF_NODE
, &no_pce_domain_cmd
);
1591 install_element(OSPF_NODE
, &pce_neighbor_cmd
);
1592 install_element(OSPF_NODE
, &no_pce_neighbor_cmd
);
1593 install_element(OSPF_NODE
, &pce_cap_flag_cmd
);
1594 install_element(OSPF_NODE
, &no_pce_cap_flag_cmd
);