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"
64 /* Store Router Information PCE TLV and SubTLV in network byte order. */
65 struct ri_tlv_pce pce_header
;
66 struct ri_pce_subtlv_address pce_address
;
67 struct ri_pce_subtlv_path_scope pce_scope
;
68 struct list
*pce_domain
;
69 struct list
*pce_neighbor
;
70 struct ri_pce_subtlv_cap_flag pce_cap_flag
;
73 /* Following structure are internal use only. */
74 struct ospf_router_info
81 /* Flags to manage this router information. */
82 #define RIFLG_LOOKUP_DONE 0x1
83 #define RIFLG_LSA_ENGAGED 0x2
84 #define RIFLG_LSA_FORCED_REFRESH 0x4
87 /* area pointer if flooding is Type 10 Null if flooding is AS scope */
88 struct ospf_area
*area
;
89 struct in_addr area_id
;
91 /* Store Router Information Capabilities LSA */
92 struct ri_tlv_router_cap router_cap
;
94 /* Store PCE capability LSA */
95 struct ospf_pce_info pce_info
;
99 * Global variable to manage Opaque-LSA/Router Information on this node.
100 * Note that all parameter values are stored in network byte order.
102 static struct ospf_router_info OspfRI
;
104 /*------------------------------------------------------------------------------*
105 * Followings are initialize/terminate functions for Router Information handling.
106 *------------------------------------------------------------------------------*/
108 static void ospf_router_info_ism_change (struct ospf_interface
*oi
,
110 static void ospf_router_info_nsm_change (struct ospf_neighbor
*nbr
,
112 static void ospf_router_info_config_write_router (struct vty
*vty
);
113 static void ospf_router_info_show_info (struct vty
*vty
,
114 struct ospf_lsa
*lsa
);
115 static int ospf_router_info_lsa_originate (void *arg
);
116 static struct ospf_lsa
*ospf_router_info_lsa_refresh (struct ospf_lsa
*lsa
);
117 static void ospf_router_info_lsa_schedule (opcode_t opcode
);
118 static void ospf_router_info_register_vty (void);
119 static void del_pce_info (void *val
);
122 ospf_router_info_init (void)
125 memset (&OspfRI
, 0, sizeof (struct ospf_router_info
));
126 OspfRI
.status
= disabled
;
127 OspfRI
.registered
= 0;
128 OspfRI
.scope
= OSPF_OPAQUE_AS_LSA
;
131 /* Initialize pce domain and neighbor list */
132 OspfRI
.pce_info
.pce_domain
= list_new ();
133 OspfRI
.pce_info
.pce_domain
->del
= del_pce_info
;
134 OspfRI
.pce_info
.pce_neighbor
= list_new ();
135 OspfRI
.pce_info
.pce_neighbor
->del
= del_pce_info
;
137 ospf_router_info_register_vty ();
143 ospf_router_info_register (u_int8_t scope
)
147 if (OspfRI
.registered
)
150 zlog_info ("Register Router Information with scope %s(%d)",
151 scope
== OSPF_OPAQUE_AREA_LSA
? "Area" : "AS", scope
);
152 rc
= ospf_register_opaque_functab (scope
,
153 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
,
154 NULL
, /* new interface */
155 NULL
, /* del interface */
156 ospf_router_info_ism_change
,
157 ospf_router_info_nsm_change
,
158 ospf_router_info_config_write_router
,
159 NULL
, /* Config. write interface */
160 NULL
, /* Config. write debug */
161 ospf_router_info_show_info
,
162 ospf_router_info_lsa_originate
,
163 ospf_router_info_lsa_refresh
,
164 NULL
, /* new_lsa_hook */
165 NULL
); /* del_lsa_hook */
169 zlog_warn ("ospf_router_info_init: Failed to register functions");
173 OspfRI
.registered
= 1;
174 OspfRI
.scope
= scope
;
179 ospf_router_info_unregister ()
182 if ((OspfRI
.scope
!= OSPF_OPAQUE_AS_LSA
)
183 && (OspfRI
.scope
!= OSPF_OPAQUE_AREA_LSA
))
185 zlog_warn ("Unable to unregister Router Info functions: Wrong scope!");
189 ospf_delete_opaque_functab (OspfRI
.scope
,
190 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
192 OspfRI
.registered
= 0;
198 ospf_router_info_term (void)
201 list_delete (OspfRI
.pce_info
.pce_domain
);
202 list_delete (OspfRI
.pce_info
.pce_neighbor
);
204 OspfRI
.pce_info
.pce_domain
= NULL
;
205 OspfRI
.pce_info
.pce_neighbor
= NULL
;
206 OspfRI
.status
= disabled
;
208 ospf_router_info_unregister ();
214 del_pce_info (void *val
)
216 XFREE (MTYPE_OSPF_PCE_PARAMS
, val
);
220 /*------------------------------------------------------------------------*
221 * Followings are control functions for ROUTER INFORMATION parameters management.
222 *------------------------------------------------------------------------*/
225 set_router_info_capabilities (struct ri_tlv_router_cap
*ric
, u_int32_t cap
)
227 ric
->header
.type
= htons (RI_TLV_CAPABILITIES
);
228 ric
->header
.length
= htons (RI_TLV_LENGTH
);
229 ric
->value
= htonl (cap
);
234 set_pce_header (struct ospf_pce_info
*pce
)
236 u_int16_t length
= 0;
237 struct listnode
*node
;
238 struct ri_pce_subtlv_domain
*domain
;
239 struct ri_pce_subtlv_neighbor
*neighbor
;
242 if (ntohs (pce
->pce_address
.header
.type
) != 0)
243 length
+= RI_TLV_SIZE (&pce
->pce_address
.header
);
246 if (ntohs (pce
->pce_scope
.header
.type
) != 0)
247 length
+= RI_TLV_SIZE (&pce
->pce_scope
.header
);
250 for (ALL_LIST_ELEMENTS_RO (pce
->pce_domain
, node
, domain
))
252 if (ntohs (domain
->header
.type
) != 0)
253 length
+= RI_TLV_SIZE (&domain
->header
);
257 for (ALL_LIST_ELEMENTS_RO (pce
->pce_neighbor
, node
, neighbor
))
259 if (ntohs (neighbor
->header
.type
) != 0)
260 length
+= RI_TLV_SIZE (&neighbor
->header
);
263 /* PCE Capabilities */
264 if (ntohs (pce
->pce_cap_flag
.header
.type
) != 0)
265 length
+= RI_TLV_SIZE (&pce
->pce_cap_flag
.header
);
269 pce
->pce_header
.header
.type
= htons (RI_TLV_PCE
);
270 pce
->pce_header
.header
.length
= htons (length
);
274 pce
->pce_header
.header
.type
= 0;
275 pce
->pce_header
.header
.length
= 0;
282 set_pce_address (struct in_addr ipv4
, struct ospf_pce_info
*pce
)
285 /* Enable PCE Info */
286 pce
->pce_header
.header
.type
= htons (RI_TLV_PCE
);
287 /* Set PCE Address */
288 pce
->pce_address
.header
.type
= htons (RI_PCE_SUBTLV_ADDRESS
);
289 pce
->pce_address
.header
.length
= htons (PCE_ADDRESS_LENGTH_IPV4
);
290 pce
->pce_address
.address
.type
= htons (PCE_ADDRESS_TYPE_IPV4
);
291 pce
->pce_address
.address
.value
= ipv4
;
297 set_pce_path_scope (u_int32_t scope
, struct ospf_pce_info
*pce
)
300 /* Enable PCE Info */
301 pce
->pce_header
.header
.type
= htons (RI_TLV_PCE
);
303 pce
->pce_scope
.header
.type
= htons (RI_PCE_SUBTLV_PATH_SCOPE
);
304 pce
->pce_scope
.header
.length
= htons (RI_TLV_LENGTH
);
305 pce
->pce_scope
.value
= htonl (scope
);
311 set_pce_domain (u_int16_t type
, u_int32_t domain
, struct ospf_pce_info
*pce
)
314 struct ri_pce_subtlv_domain
*new;
316 /* Enable PCE Info */
317 pce
->pce_header
.header
.type
= htons (RI_TLV_PCE
);
319 /* Create new domain info */
321 XCALLOC (MTYPE_OSPF_PCE_PARAMS
,
322 sizeof (struct ri_pce_subtlv_domain
));
324 new->header
.type
= htons (RI_PCE_SUBTLV_DOMAIN
);
325 new->header
.length
= htons (PCE_ADDRESS_LENGTH_IPV4
);
326 new->type
= htons (type
);
327 new->value
= htonl (domain
);
329 /* Add new domain to the list */
330 listnode_add (pce
->pce_domain
, new);
336 unset_pce_domain (u_int16_t type
, u_int32_t domain
, struct ospf_pce_info
*pce
)
338 struct listnode
*node
;
339 struct ri_pce_subtlv_domain
*old
= NULL
;
342 /* Search the corresponding node */
343 for (ALL_LIST_ELEMENTS_RO (pce
->pce_domain
, node
, old
))
345 if ((old
->type
== htons (type
)) && (old
->value
== htonl (domain
)))
352 /* if found remove it */
355 listnode_delete (pce
->pce_domain
, old
);
357 /* Avoid misjudgement in the next lookup. */
358 if (listcount (pce
->pce_domain
) == 0)
359 pce
->pce_domain
->head
= pce
->pce_domain
->tail
= NULL
;
361 /* Finally free the old domain */
362 XFREE (MTYPE_OSPF_PCE_PARAMS
, old
);
367 set_pce_neighbor (u_int16_t type
, u_int32_t domain
, struct ospf_pce_info
*pce
)
370 struct ri_pce_subtlv_neighbor
*new;
372 /* Enable PCE Info */
373 pce
->pce_header
.header
.type
= htons (RI_TLV_PCE
);
375 /* Create new neighbor info */
377 XCALLOC (MTYPE_OSPF_PCE_PARAMS
,
378 sizeof (struct ri_pce_subtlv_neighbor
));
380 new->header
.type
= htons (RI_PCE_SUBTLV_NEIGHBOR
);
381 new->header
.length
= htons (PCE_ADDRESS_LENGTH_IPV4
);
382 new->type
= htons (type
);
383 new->value
= htonl (domain
);
385 /* Add new domain to the list */
386 listnode_add (pce
->pce_neighbor
, new);
392 unset_pce_neighbor (u_int16_t type
, u_int32_t domain
,
393 struct ospf_pce_info
*pce
)
395 struct listnode
*node
;
396 struct ri_pce_subtlv_neighbor
*old
= NULL
;
399 /* Search the corresponding node */
400 for (ALL_LIST_ELEMENTS_RO (pce
->pce_neighbor
, node
, old
))
402 if ((old
->type
== htons (type
)) && (old
->value
== htonl (domain
)))
409 /* if found remove it */
412 listnode_delete (pce
->pce_neighbor
, old
);
414 /* Avoid misjudgement in the next lookup. */
415 if (listcount (pce
->pce_neighbor
) == 0)
416 pce
->pce_neighbor
->head
= pce
->pce_neighbor
->tail
= NULL
;
418 /* Finally free the old domain */
419 XFREE (MTYPE_OSPF_PCE_PARAMS
, old
);
424 set_pce_cap_flag (u_int32_t cap
, struct ospf_pce_info
*pce
)
427 /* Enable PCE Info */
428 pce
->pce_header
.header
.type
= htons (RI_TLV_PCE
);
429 /* Set PCE Capabilities flag */
430 pce
->pce_cap_flag
.header
.type
= htons (RI_PCE_SUBTLV_CAP_FLAG
);
431 pce
->pce_cap_flag
.header
.length
= htons (RI_TLV_LENGTH
);
432 pce
->pce_cap_flag
.value
= htonl (cap
);
439 unset_param (struct ri_tlv_header
*tlv
)
443 /* Fill the Value to 0 */
444 memset ((tlv
+ RI_TLV_HDR_SIZE
), 0, RI_TLV_BODY_SIZE (tlv
));
451 initialize_params (struct ospf_router_info
*ori
)
457 * Initialize default Router Information Capabilities.
460 cap
= cap
| RI_TE_SUPPORT
;
462 set_router_info_capabilities (&ori
->router_cap
, cap
);
464 /* If Area address is not null and exist, retrieve corresponding structure */
465 top
= ospf_lookup ();
466 zlog_info ("RI-> Initialize Router Info for %s scope within area %s",
467 OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
? "Area" : "AS",
468 inet_ntoa (OspfRI
.area_id
));
470 /* Try to get the Area context at this step. Do it latter if not available */
471 if ((OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) && (OspfRI
.area
== NULL
))
472 OspfRI
.area
= ospf_area_lookup_by_area_id (top
, OspfRI
.area_id
);
475 * Initialize default PCE Information values
477 /* PCE address == OSPF Router ID */
478 set_pce_address (top
->router_id
, &ori
->pce_info
);
481 cap
= 7; /* Set L, R and Rd bits to one = intra & inter-area path computation */
482 set_pce_path_scope (cap
, &ori
->pce_info
);
484 /* PCE Capabilities */
486 PCE_CAP_BIDIRECTIONAL
| PCE_CAP_DIVERSE_PATH
| PCE_CAP_OBJECTIVES
|
487 PCE_CAP_ADDITIVE
| PCE_CAP_MULTIPLE_REQ
;
488 set_pce_cap_flag (cap
, &ori
->pce_info
);
490 /* Finally compute PCE header */
491 set_pce_header (&ori
->pce_info
);
497 is_mandated_params_set (struct ospf_router_info ori
)
501 if (ntohs (ori
.router_cap
.header
.type
) == 0)
504 if ((ntohs (ori
.pce_info
.pce_header
.header
.type
) == RI_TLV_PCE
)
505 && (ntohs (ori
.pce_info
.pce_address
.header
.type
) == 0)
506 && (ntohs (ori
.pce_info
.pce_cap_flag
.header
.type
) == 0))
515 /*------------------------------------------------------------------------*
516 * Followings are callback functions against generic Opaque-LSAs handling.
517 *------------------------------------------------------------------------*/
519 ospf_router_info_ism_change (struct ospf_interface
*oi
, int old_state
)
521 /* So far, nothing to do here. */
527 ospf_router_info_nsm_change (struct ospf_neighbor
*nbr
, int old_state
)
530 /* So far, nothing to do here. */
534 /*------------------------------------------------------------------------*
535 * Followings are OSPF protocol processing functions for ROUTER INFORMATION
536 *------------------------------------------------------------------------*/
539 build_tlv_header (struct stream
*s
, struct ri_tlv_header
*tlvh
)
542 stream_put (s
, tlvh
, sizeof (struct ri_tlv_header
));
547 build_tlv (struct stream
*s
, struct ri_tlv_header
*tlvh
)
550 if (ntohs (tlvh
->type
) != 0)
552 build_tlv_header (s
, tlvh
);
553 stream_put (s
, tlvh
+ 1, RI_TLV_BODY_SIZE (tlvh
));
559 ospf_router_info_lsa_body_set (struct stream
*s
)
562 struct listnode
*node
;
563 struct ri_pce_subtlv_domain
*domain
;
564 struct ri_pce_subtlv_neighbor
*neighbor
;
566 /* Build Router Information TLV */
567 build_tlv (s
, &OspfRI
.router_cap
.header
);
569 /* Add RI PCE TLV if it is set */
570 /* Compute PCE Info header first */
571 if ((set_pce_header (&OspfRI
.pce_info
)) != 0)
575 build_tlv_header (s
, &OspfRI
.pce_info
.pce_header
.header
);
577 /* Build PCE address sub-tlv */
578 build_tlv (s
, &OspfRI
.pce_info
.pce_address
.header
);
580 /* Build PCE path scope sub-tlv */
581 build_tlv (s
, &OspfRI
.pce_info
.pce_scope
.header
);
583 /* Build PCE domain sub-tlv */
584 for (ALL_LIST_ELEMENTS_RO (OspfRI
.pce_info
.pce_domain
, node
, domain
))
585 build_tlv (s
, &domain
->header
);
587 /* Build PCE neighbor sub-tlv */
588 for (ALL_LIST_ELEMENTS_RO
589 (OspfRI
.pce_info
.pce_neighbor
, node
, neighbor
))
590 build_tlv (s
, &neighbor
->header
);
592 /* Build PCE cap flag sub-tlv */
593 build_tlv (s
, &OspfRI
.pce_info
.pce_cap_flag
.header
);
599 /* Create new opaque-LSA. */
600 static struct ospf_lsa
*
601 ospf_router_info_lsa_new ()
605 struct lsa_header
*lsah
;
606 struct ospf_lsa
*new = NULL
;
607 u_char options
, lsa_type
;
608 struct in_addr lsa_id
;
612 /* Create a stream for LSA. */
613 if ((s
= stream_new (OSPF_MAX_LSA_SIZE
)) == NULL
)
615 zlog_warn ("ospf_router_info_lsa_new: stream_new() ?");
618 lsah
= (struct lsa_header
*) STREAM_DATA (s
);
620 options
= OSPF_OPTION_E
; /* Enable AS external as we flood RI with Opaque Type 11 */
621 options
|= OSPF_OPTION_O
; /* Don't forget this :-) */
623 lsa_type
= OspfRI
.scope
;
624 /* LSA ID == 0 for Router Information see RFC 4970 */
625 tmp
= SET_OPAQUE_LSID (OPAQUE_TYPE_ROUTER_INFORMATION_LSA
, 0);
626 lsa_id
.s_addr
= htonl (tmp
);
628 if (IS_DEBUG_OSPF (lsa
, LSA_GENERATE
))
630 ("LSA[Type%d:%s]: Create an Opaque-LSA/ROUTER INFORMATION instance",
631 lsa_type
, inet_ntoa (lsa_id
));
633 top
= ospf_lookup ();
635 /* Set opaque-LSA header fields. */
636 lsa_header_set (s
, options
, lsa_type
, lsa_id
, top
->router_id
);
638 /* Set opaque-LSA body fields. */
639 ospf_router_info_lsa_body_set (s
);
642 length
= stream_get_endp (s
);
643 lsah
->length
= htons (length
);
645 /* Now, create an OSPF LSA instance. */
646 if ((new = ospf_lsa_new ()) == NULL
)
648 zlog_warn ("ospf_router_info_lsa_new: ospf_lsa_new() ?");
652 if ((new->data
= ospf_lsa_data_new (length
)) == NULL
)
654 zlog_warn ("ospf_router_info_lsa_new: ospf_lsa_data_new() ?");
655 ospf_lsa_unlock (&new);
661 new->area
= OspfRI
.area
; /* Area must be null if the Opaque type is AS scope, fulfill otherwise */
663 SET_FLAG (new->flags
, OSPF_LSA_SELF
);
664 memcpy (new->data
, lsah
, length
);
671 ospf_router_info_lsa_originate1 (void *arg
)
673 struct ospf_lsa
*new;
675 struct ospf_area
*area
;
678 /* First check if the area is known if flooding scope is Area */
679 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
)
681 area
= (struct ospf_area
*) arg
;
682 if (area
->area_id
.s_addr
!= OspfRI
.area_id
.s_addr
)
685 ("RI -> This is not the Router Information Area. Stop processing");
691 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
692 if ((new = ospf_router_info_lsa_new ()) == NULL
)
695 ("ospf_router_info_lsa_originate1: ospf_router_info_lsa_new() ?");
700 top
= ospf_lookup ();
702 /* Install this LSA into LSDB. */
703 if (ospf_lsa_install (top
, NULL
/*oi */ , new) == NULL
)
705 zlog_warn ("ospf_router_info_lsa_originate1: ospf_lsa_install() ?");
706 ospf_lsa_unlock (&new);
710 /* Now this Router Info parameter entry has associated LSA. */
711 SET_FLAG (OspfRI
.flags
, RIFLG_LSA_ENGAGED
);
713 /* Update new LSA origination count. */
714 top
->lsa_originate_count
++;
716 /* Flood new LSA through AS. */
717 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
)
718 ospf_flood_through_as (top
, NULL
/*nbr */ , new);
720 ospf_flood_through_area (OspfRI
.area
, NULL
/*nbr */ , new);
722 if (IS_DEBUG_OSPF (lsa
, LSA_GENERATE
))
724 zlog_debug ("LSA[Type%d:%s]: Originate Opaque-LSA/ROUTER INFORMATION",
725 new->data
->type
, inet_ntoa (new->data
->id
));
726 ospf_lsa_header_dump (new->data
);
734 ospf_router_info_lsa_originate (void *arg
)
739 if (OspfRI
.status
== disabled
)
742 ("ospf_router_info_lsa_originate: ROUTER INFORMATION is disabled now.");
743 rc
= 0; /* This is not an error case. */
747 /* Check if Router Information LSA is already engaged */
748 if (OspfRI
.flags
& RIFLG_LSA_ENGAGED
)
750 if (OspfRI
.flags
& RIFLG_LSA_FORCED_REFRESH
)
752 OspfRI
.flags
&= ~RIFLG_LSA_FORCED_REFRESH
;
753 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA
);
758 if (!is_mandated_params_set (OspfRI
))
760 ("ospf_router_info_lsa_originate: lacks mandated ROUTER INFORMATION parameters");
762 /* Ok, let's try to originate an LSA */
763 if (ospf_router_info_lsa_originate1 (arg
) != 0)
771 static struct ospf_lsa
*
772 ospf_router_info_lsa_refresh (struct ospf_lsa
*lsa
)
774 struct ospf_lsa
*new = NULL
;
777 if (OspfRI
.status
== disabled
)
780 * This LSA must have flushed before due to ROUTER INFORMATION status change.
781 * It seems a slip among routers in the routing domain.
784 ("ospf_router_info_lsa_refresh: ROUTER INFORMATION is disabled now.");
785 lsa
->data
->ls_age
= htons (OSPF_LSA_MAXAGE
); /* Flush it anyway. */
788 /* Verify that the Router Information ID is supported */
789 if (GET_OPAQUE_ID (ntohl (lsa
->data
->id
.s_addr
)) != 0)
792 ("ospf_router_info_lsa_refresh: Unsupported Router Information ID");
796 /* If the lsa's age reached to MaxAge, start flushing procedure. */
797 if (IS_LSA_MAXAGE (lsa
))
799 OspfRI
.flags
&= ~RIFLG_LSA_ENGAGED
;
800 ospf_opaque_lsa_flush_schedule (lsa
);
804 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
805 if ((new = ospf_router_info_lsa_new ()) == NULL
)
808 ("ospf_router_info_lsa_refresh: ospf_router_info_lsa_new() ?");
811 new->data
->ls_seqnum
= lsa_seqnum_increment (lsa
);
813 /* Install this LSA into LSDB. */
814 /* Given "lsa" will be freed in the next function. */
815 top
= ospf_lookup ();
816 if (ospf_lsa_install (top
, NULL
/*oi */ , new) == NULL
)
818 zlog_warn ("ospf_router_info_lsa_refresh: ospf_lsa_install() ?");
819 ospf_lsa_unlock (&new);
823 /* Flood updated LSA through AS or AREA depending of OspfRI.scope. */
824 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
)
825 ospf_flood_through_as (top
, NULL
/*nbr */ , new);
827 ospf_flood_through_area (OspfRI
.area
, NULL
/*nbr */ , new);
830 if (IS_DEBUG_OSPF (lsa
, LSA_GENERATE
))
832 zlog_debug ("LSA[Type%d:%s]: Refresh Opaque-LSA/ROUTER INFORMATION",
833 new->data
->type
, inet_ntoa (new->data
->id
));
834 ospf_lsa_header_dump (new->data
);
841 ospf_router_info_lsa_schedule (opcode_t opcode
)
844 struct lsa_header lsah
;
848 memset (&lsa
, 0, sizeof (lsa
));
849 memset (&lsah
, 0, sizeof (lsah
));
851 zlog_debug ("RI-> LSA schedule %s%s%s",
852 opcode
== REORIGINATE_THIS_LSA
? "Re-Originate" : "",
853 opcode
== REFRESH_THIS_LSA
? "Refresh" : "",
854 opcode
== FLUSH_THIS_LSA
? "Flush" : "");
856 top
= ospf_lookup ();
857 if ((OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
) && (OspfRI
.area
== NULL
))
860 ("ospf_router_info_lsa_schedule(): Router Info is Area scope flooding but area is not set");
861 OspfRI
.area
= ospf_area_lookup_by_area_id (top
, OspfRI
.area_id
);
863 lsa
.area
= OspfRI
.area
;
865 lsah
.type
= OspfRI
.scope
;
867 /* LSA ID is set to 0 for the Router Information. See RFC 4970 */
868 tmp
= SET_OPAQUE_LSID (OPAQUE_TYPE_ROUTER_INFORMATION_LSA
, 0);
869 lsah
.id
.s_addr
= htonl (tmp
);
873 case REORIGINATE_THIS_LSA
:
874 if (OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
)
875 ospf_opaque_lsa_reoriginate_schedule ((void *) OspfRI
.area
,
876 OSPF_OPAQUE_AREA_LSA
,
877 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
879 ospf_opaque_lsa_reoriginate_schedule ((void *) top
,
881 OPAQUE_TYPE_ROUTER_INFORMATION_LSA
);
883 case REFRESH_THIS_LSA
:
884 ospf_opaque_lsa_refresh_schedule (&lsa
);
887 OspfRI
.flags
&= ~RIFLG_LSA_ENGAGED
;
888 ospf_opaque_lsa_flush_schedule (&lsa
);
891 zlog_warn ("ospf_router_info_lsa_schedule: Unknown opcode (%u)",
899 /*------------------------------------------------------------------------*
900 * Followings are vty session control functions.
901 *------------------------------------------------------------------------*/
904 show_vty_router_cap (struct vty
*vty
, struct ri_tlv_header
*tlvh
)
906 struct ri_tlv_router_cap
*top
= (struct ri_tlv_router_cap
*) tlvh
;
909 vty_out (vty
, " Router Capabilities: 0x%x%s", ntohl (top
->value
),
912 zlog_debug (" Router Capabilities: 0x%x", ntohl (top
->value
));
914 return RI_TLV_SIZE (tlvh
);
918 show_vty_pce_subtlv_address (struct vty
*vty
, struct ri_tlv_header
*tlvh
)
920 struct ri_pce_subtlv_address
*top
= (struct ri_pce_subtlv_address
*) tlvh
;
922 if (ntohs (top
->address
.type
) == PCE_ADDRESS_TYPE_IPV4
)
925 vty_out (vty
, " PCE Address: %s%s", inet_ntoa (top
->address
.value
),
928 zlog_debug (" PCE Address: %s", inet_ntoa (top
->address
.value
));
932 /* TODO: Add support to IPv6 with inet_ntop() */
934 vty_out (vty
, " PCE Address: 0x%x%s",
935 ntohl (top
->address
.value
.s_addr
), VTY_NEWLINE
);
937 zlog_debug (" PCE Address: 0x%x",
938 ntohl (top
->address
.value
.s_addr
));
941 return RI_TLV_SIZE (tlvh
);
945 show_vty_pce_subtlv_path_scope (struct vty
*vty
, struct ri_tlv_header
*tlvh
)
947 struct ri_pce_subtlv_path_scope
*top
=
948 (struct ri_pce_subtlv_path_scope
*) tlvh
;
951 vty_out (vty
, " PCE Path Scope: 0x%x%s", ntohl (top
->value
),
954 zlog_debug (" PCE Path Scope: 0x%x", ntohl (top
->value
));
956 return RI_TLV_SIZE (tlvh
);
960 show_vty_pce_subtlv_domain (struct vty
*vty
, struct ri_tlv_header
*tlvh
)
962 struct ri_pce_subtlv_domain
*top
= (struct ri_pce_subtlv_domain
*) tlvh
;
965 if (ntohs (top
->type
) == PCE_DOMAIN_TYPE_AREA
)
967 tmp
.s_addr
= top
->value
;
969 vty_out (vty
, " PCE domain Area: %s%s", inet_ntoa (tmp
),
972 zlog_debug (" PCE domain Area: %s", inet_ntoa (tmp
));
977 vty_out (vty
, " PCE domain AS: %d%s", ntohl (top
->value
),
980 zlog_debug (" PCE domain AS: %d", ntohl (top
->value
));
982 return RI_TLV_SIZE (tlvh
);
986 show_vty_pce_subtlv_neighbor (struct vty
*vty
, struct ri_tlv_header
*tlvh
)
989 struct ri_pce_subtlv_neighbor
*top
= (struct ri_pce_subtlv_neighbor
*) tlvh
;
992 if (ntohs (top
->type
) == PCE_DOMAIN_TYPE_AREA
)
994 tmp
.s_addr
= top
->value
;
996 vty_out (vty
, " PCE neighbor Area: %s%s", inet_ntoa (tmp
),
999 zlog_debug (" PCE neighbor Area: %s", inet_ntoa (tmp
));
1004 vty_out (vty
, " PCE neighbor AS: %d%s", ntohl (top
->value
),
1007 zlog_debug (" PCE neighbor AS: %d", ntohl (top
->value
));
1009 return RI_TLV_SIZE (tlvh
);
1013 show_vty_pce_subtlv_cap_flag (struct vty
*vty
, struct ri_tlv_header
*tlvh
)
1015 struct ri_pce_subtlv_cap_flag
*top
= (struct ri_pce_subtlv_cap_flag
*) tlvh
;
1018 vty_out (vty
, " PCE Capabilities Flag: 0x%x%s", ntohl (top
->value
),
1021 zlog_debug (" PCE Capabilities Flag: 0x%x", ntohl (top
->value
));
1023 return RI_TLV_SIZE (tlvh
);
1027 show_vty_unknown_tlv (struct vty
*vty
, struct ri_tlv_header
*tlvh
)
1030 vty_out (vty
, " Unknown TLV: [type(0x%x), length(0x%x)]%s",
1031 ntohs (tlvh
->type
), ntohs (tlvh
->length
), VTY_NEWLINE
);
1033 zlog_debug (" Unknown TLV: [type(0x%x), length(0x%x)]",
1034 ntohs (tlvh
->type
), ntohs (tlvh
->length
));
1036 return RI_TLV_SIZE (tlvh
);
1040 show_vty_pce_info (struct vty
*vty
, struct ri_tlv_header
*ri
, uint32_t total
)
1042 struct ri_tlv_header
*tlvh
;
1045 for (tlvh
= ri
; sum
< total
; tlvh
= RI_TLV_HDR_NEXT (tlvh
))
1047 switch (ntohs (tlvh
->type
))
1049 case RI_PCE_SUBTLV_ADDRESS
:
1050 sum
+= show_vty_pce_subtlv_address (vty
, tlvh
);
1052 case RI_PCE_SUBTLV_PATH_SCOPE
:
1053 sum
+= show_vty_pce_subtlv_path_scope (vty
, tlvh
);
1055 case RI_PCE_SUBTLV_DOMAIN
:
1056 sum
+= show_vty_pce_subtlv_domain (vty
, tlvh
);
1058 case RI_PCE_SUBTLV_NEIGHBOR
:
1059 sum
+= show_vty_pce_subtlv_neighbor (vty
, tlvh
);
1061 case RI_PCE_SUBTLV_CAP_FLAG
:
1062 sum
+= show_vty_pce_subtlv_cap_flag (vty
, tlvh
);
1065 sum
+= show_vty_unknown_tlv (vty
, tlvh
);
1073 ospf_router_info_show_info (struct vty
*vty
, struct ospf_lsa
*lsa
)
1075 struct lsa_header
*lsah
= (struct lsa_header
*) lsa
->data
;
1076 struct ri_tlv_header
*tlvh
;
1077 u_int16_t length
= 0, sum
= 0;
1079 /* Initialize TLV browsing */
1080 length
= ntohs (lsah
->length
) - OSPF_LSA_HEADER_SIZE
;
1082 for (tlvh
= RI_TLV_HDR_TOP (lsah
); sum
< length
;
1083 tlvh
= RI_TLV_HDR_NEXT (tlvh
))
1085 switch (ntohs (tlvh
->type
))
1087 case RI_TLV_CAPABILITIES
:
1088 sum
+= show_vty_router_cap (vty
, tlvh
);
1092 sum
+= RI_TLV_HDR_SIZE
;
1093 sum
+= show_vty_pce_info (vty
, tlvh
, length
- sum
);
1096 sum
+= show_vty_unknown_tlv (vty
, tlvh
);
1105 ospf_router_info_config_write_router (struct vty
*vty
)
1107 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1108 struct listnode
*node
;
1109 struct ri_pce_subtlv_domain
*domain
;
1110 struct ri_pce_subtlv_neighbor
*neighbor
;
1113 if (OspfRI
.status
== enabled
)
1115 if (OspfRI
.scope
== OSPF_OPAQUE_AS_LSA
)
1116 vty_out (vty
, " router-info as%s", VTY_NEWLINE
);
1118 vty_out (vty
, " router-info area %s%s", inet_ntoa (OspfRI
.area_id
),
1121 if (pce
->pce_address
.header
.type
!= 0)
1122 vty_out (vty
, " pce address %s%s",
1123 inet_ntoa (pce
->pce_address
.address
.value
), VTY_NEWLINE
);
1125 if (pce
->pce_cap_flag
.header
.type
!= 0)
1126 vty_out (vty
, " pce flag 0x%x%s", ntohl (pce
->pce_cap_flag
.value
),
1129 for (ALL_LIST_ELEMENTS_RO (pce
->pce_domain
, node
, domain
))
1131 if (domain
->header
.type
!= 0)
1133 if (domain
->type
== PCE_DOMAIN_TYPE_AREA
)
1135 tmp
.s_addr
= domain
->value
;
1136 vty_out (vty
, " pce domain area %s%s", inet_ntoa (tmp
),
1141 vty_out (vty
, " pce domain as %d%s", ntohl (domain
->value
),
1147 for (ALL_LIST_ELEMENTS_RO (pce
->pce_neighbor
, node
, neighbor
))
1149 if (neighbor
->header
.type
!= 0)
1151 if (neighbor
->type
== PCE_DOMAIN_TYPE_AREA
)
1153 tmp
.s_addr
= neighbor
->value
;
1154 vty_out (vty
, " pce neighbor area %s%s", inet_ntoa (tmp
),
1159 vty_out (vty
, " pce neighbor as %d%s",
1160 ntohl (neighbor
->value
), VTY_NEWLINE
);
1165 if (pce
->pce_scope
.header
.type
!= 0)
1166 vty_out (vty
, " pce scope 0x%x%s",
1167 ntohl (OspfRI
.pce_info
.pce_scope
.value
), VTY_NEWLINE
);
1172 /*------------------------------------------------------------------------*
1173 * Followings are vty command functions.
1174 *------------------------------------------------------------------------*/
1177 router_info_area_cmd
,
1178 "router-info <as|area A.B.C.D>",
1180 "Enable the Router Information functionality with AS flooding scope\n"
1181 "Enable the Router Information functionality with Area flooding scope\n"
1182 "OSPF area ID in IP format")
1185 char *area
= (argc
== 3) ? argv
[idx_ipv4
]->arg
: NULL
;
1189 if (OspfRI
.status
== enabled
)
1192 /* Check and get Area value if present */
1195 if (!inet_aton (area
, &OspfRI
.area_id
))
1197 vty_out (vty
, "Please specifya valid Area ID%s", VTY_NEWLINE
);
1200 scope
= OSPF_OPAQUE_AREA_LSA
;
1204 OspfRI
.area_id
.s_addr
= 0;
1205 scope
= OSPF_OPAQUE_AS_LSA
;
1208 /* First start to register Router Information callbacks */
1209 if ((ospf_router_info_register (scope
)) != 0)
1211 zlog_warn ("Enable to register Router Information callbacks. Abort!");
1215 OspfRI
.status
= enabled
;
1217 if (IS_DEBUG_OSPF_EVENT
)
1218 zlog_debug ("RI-> Router Information (%s flooding): OFF -> ON",
1219 OspfRI
.scope
== OSPF_OPAQUE_AREA_LSA
? "Area" : "AS");
1222 * Following code is intended to handle two cases;
1224 * 1) Router Information was disabled at startup time, but now become enabled.
1225 * 2) Router Information was once enabled then disabled, and now enabled again.
1228 initialize_params (&OspfRI
);
1230 /* Refresh RI LSA if already engaged */
1231 if (OspfRI
.flags
& RIFLG_LSA_ENGAGED
)
1233 zlog_debug ("RI-> Initial origination following configuration");
1234 ospf_router_info_lsa_schedule (REORIGINATE_THIS_LSA
);
1241 DEFUN (no_router_info
,
1245 "Disable the Router Information functionality\n")
1248 if (OspfRI
.status
== disabled
)
1251 if (IS_DEBUG_OSPF_EVENT
)
1252 zlog_debug ("RI-> Router Information: ON -> OFF");
1254 if (OspfRI
.flags
& RIFLG_LSA_ENGAGED
)
1255 ospf_router_info_lsa_schedule (FLUSH_THIS_LSA
);
1257 /* Unregister the callbacks */
1258 ospf_router_info_unregister ();
1260 OspfRI
.status
= disabled
;
1266 ospf_ri_enabled (struct vty
*vty
)
1268 if (OspfRI
.status
== enabled
)
1272 vty_out (vty
, "%% OSPF RI is not turned on%s", VTY_NEWLINE
);
1279 "pce address A.B.C.D",
1281 "Stable IP address of the PCE\n"
1282 "PCE address in IPv4 address format\n")
1285 struct in_addr value
;
1286 struct ospf_pce_info
*pi
= &OspfRI
.pce_info
;
1288 if (!ospf_ri_enabled (vty
))
1291 if (!inet_aton (argv
[idx_ipv4
]->arg
, &value
))
1293 vty_out (vty
, "Please specify PCE Address by A.B.C.D%s", VTY_NEWLINE
);
1297 if (ntohs (pi
->pce_address
.header
.type
) == 0
1298 || ntohl (pi
->pce_address
.address
.value
.s_addr
) != ntohl (value
.s_addr
))
1301 set_pce_address (value
, pi
);
1303 /* Refresh RI LSA if already engaged */
1304 if (OspfRI
.flags
& RIFLG_LSA_ENGAGED
)
1305 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA
);
1311 DEFUN (no_pce_address
,
1313 "no pce address [A.B.C.D]",
1316 "Disable PCE address\n"
1317 "PCE address in IPv4 address format\n")
1320 unset_param (&OspfRI
.pce_info
.pce_address
.header
);
1322 /* Refresh RI LSA if already engaged */
1323 if ((OspfRI
.status
== enabled
) && (OspfRI
.flags
& RIFLG_LSA_ENGAGED
))
1324 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA
);
1329 DEFUN (pce_path_scope
,
1331 "pce scope BITPATTERN",
1333 "Path scope visibilities of the PCE for path computation\n"
1334 "32-bit Hexadecimal value\n")
1336 int idx_bitpattern
= 2;
1338 struct ospf_pce_info
*pi
= &OspfRI
.pce_info
;
1340 if (!ospf_ri_enabled (vty
))
1343 if (sscanf (argv
[idx_bitpattern
]->arg
, "0x%x", &scope
) != 1)
1345 vty_out (vty
, "pce_path_scope: fscanf: %s%s", safe_strerror (errno
),
1350 if (ntohl (pi
->pce_scope
.header
.type
) == 0 || scope
!= pi
->pce_scope
.value
)
1352 set_pce_path_scope (scope
, pi
);
1354 /* Refresh RI LSA if already engaged */
1355 if (OspfRI
.flags
& RIFLG_LSA_ENGAGED
)
1356 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA
);
1362 DEFUN (no_pce_path_scope
,
1363 no_pce_path_scope_cmd
,
1364 "no pce scope [BITPATTERN]",
1367 "Disable PCE path scope\n"
1368 "32-bit Hexadecimal value\n")
1371 unset_param (&OspfRI
.pce_info
.pce_address
.header
);
1373 /* Refresh RI LSA if already engaged */
1374 if ((OspfRI
.status
== enabled
) && (OspfRI
.flags
& RIFLG_LSA_ENGAGED
))
1375 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA
);
1382 "pce domain as (0-65535)",
1384 "Configure PCE domain AS number\n"
1385 "AS number where the PCE as visibilities for path computation\n"
1386 "AS number in decimal <0-65535>\n")
1391 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1392 struct listnode
*node
;
1393 struct ri_pce_subtlv_domain
*domain
;
1395 if (!ospf_ri_enabled (vty
))
1398 if (sscanf (argv
[idx_number
]->arg
, "%d", &as
) != 1)
1400 vty_out (vty
, "pce_domain: fscanf: %s%s", safe_strerror (errno
),
1405 /* Check if the domain is not already in the domain list */
1406 for (ALL_LIST_ELEMENTS_RO (pce
->pce_domain
, node
, domain
))
1408 if (ntohl (domain
->header
.type
) == 0 && as
== domain
->value
)
1412 /* Create new domain if not found */
1413 set_pce_domain (PCE_DOMAIN_TYPE_AS
, as
, pce
);
1415 /* Refresh RI LSA if already engaged */
1416 if (OspfRI
.flags
& RIFLG_LSA_ENGAGED
)
1417 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA
);
1422 DEFUN (no_pce_domain
,
1424 "no pce domain as (0-65535)",
1427 "Disable PCE domain AS number\n"
1428 "AS number where the PCE as visibilities for path computation\n"
1429 "AS number in decimal <0-65535>\n")
1434 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1436 if (sscanf (argv
[idx_number
]->arg
, "%d", &as
) != 1)
1438 vty_out (vty
, "no_pce_domain: fscanf: %s%s", safe_strerror (errno
),
1443 /* Unset corresponding PCE domain */
1444 unset_pce_domain (PCE_DOMAIN_TYPE_AS
, as
, pce
);
1446 /* Refresh RI LSA if already engaged */
1447 if ((OspfRI
.status
== enabled
) && (OspfRI
.flags
& RIFLG_LSA_ENGAGED
))
1448 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA
);
1453 DEFUN (pce_neigbhor
,
1455 "pce neighbor as (0-65535)",
1457 "Configure PCE neighbor domain AS number\n"
1458 "AS number of PCE neighbors\n"
1459 "AS number in decimal <0-65535>\n")
1464 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1465 struct listnode
*node
;
1466 struct ri_pce_subtlv_neighbor
*neighbor
;
1468 if (!ospf_ri_enabled (vty
))
1471 if (sscanf (argv
[idx_number
]->arg
, "%d", &as
) != 1)
1473 vty_out (vty
, "pce_neighbor: fscanf: %s%s", safe_strerror (errno
),
1478 /* Check if the domain is not already in the domain list */
1479 for (ALL_LIST_ELEMENTS_RO (pce
->pce_neighbor
, node
, neighbor
))
1481 if (ntohl (neighbor
->header
.type
) == 0 && as
== neighbor
->value
)
1485 /* Create new domain if not found */
1486 set_pce_neighbor (PCE_DOMAIN_TYPE_AS
, as
, pce
);
1488 /* Refresh RI LSA if already engaged */
1489 if (OspfRI
.flags
& RIFLG_LSA_ENGAGED
)
1490 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA
);
1495 DEFUN (no_pce_neighbor
,
1496 no_pce_neighbor_cmd
,
1497 "no pce neighbor as (0-65535)",
1500 "Disable PCE neighbor AS number\n"
1501 "AS number of PCE neighbor\n"
1502 "AS number in decimal <0-65535>\n")
1507 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1509 if (sscanf (argv
[idx_number
]->arg
, "%d", &as
) != 1)
1511 vty_out (vty
, "no_pce_neighbor: fscanf: %s%s", safe_strerror (errno
),
1516 /* Unset corresponding PCE domain */
1517 unset_pce_neighbor (PCE_DOMAIN_TYPE_AS
, as
, pce
);
1519 /* Refresh RI LSA if already engaged */
1520 if ((OspfRI
.status
== enabled
) && (OspfRI
.flags
& RIFLG_LSA_ENGAGED
))
1521 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA
);
1526 DEFUN (pce_cap_flag
,
1528 "pce flag BITPATTERN",
1530 "Capabilities of the PCE for path computation\n"
1531 "32-bit Hexadecimal value\n")
1533 int idx_bitpattern
= 2;
1536 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1538 if (!ospf_ri_enabled (vty
))
1541 if (sscanf (argv
[idx_bitpattern
]->arg
, "0x%x", &cap
) != 1)
1543 vty_out (vty
, "pce_cap_flag: fscanf: %s%s", safe_strerror (errno
),
1548 if (ntohl (pce
->pce_cap_flag
.header
.type
) == 0
1549 || cap
!= pce
->pce_cap_flag
.value
)
1551 set_pce_cap_flag (cap
, pce
);
1553 /* Refresh RI LSA if already engaged */
1554 if (OspfRI
.flags
& RIFLG_LSA_ENGAGED
)
1555 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA
);
1561 DEFUN (no_pce_cap_flag
,
1562 no_pce_cap_flag_cmd
,
1566 "Disable PCE capabilities\n")
1569 unset_param (&OspfRI
.pce_info
.pce_cap_flag
.header
);
1571 /* Refresh RI LSA if already engaged */
1572 if ((OspfRI
.status
== enabled
) && (OspfRI
.flags
& RIFLG_LSA_ENGAGED
))
1573 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA
);
1578 DEFUN (show_ip_ospf_router_info
,
1579 show_ip_ospf_router_info_cmd
,
1580 "show ip ospf router-info",
1584 "Router Information\n")
1587 if (OspfRI
.status
== enabled
)
1589 vty_out (vty
, "--- Router Information parameters ---%s", VTY_NEWLINE
);
1590 show_vty_router_cap (vty
, &OspfRI
.router_cap
.header
);
1595 vty_out (vty
, " Router Information is disabled on this router%s", VTY_NEWLINE
);
1600 DEFUN (show_ip_opsf_router_info_pce
,
1601 show_ip_ospf_router_info_pce_cmd
,
1602 "show ip ospf router-info pce",
1606 "Router Information\n"
1607 "PCE information\n")
1610 struct ospf_pce_info
*pce
= &OspfRI
.pce_info
;
1611 struct listnode
*node
;
1612 struct ri_pce_subtlv_domain
*domain
;
1613 struct ri_pce_subtlv_neighbor
*neighbor
;
1615 if (OspfRI
.status
== enabled
)
1617 vty_out (vty
, "--- PCE parameters ---%s", VTY_NEWLINE
);
1619 if (pce
->pce_address
.header
.type
!= 0)
1620 show_vty_pce_subtlv_address (vty
, &pce
->pce_address
.header
);
1622 if (pce
->pce_scope
.header
.type
!= 0)
1623 show_vty_pce_subtlv_path_scope (vty
, &pce
->pce_scope
.header
);
1625 for (ALL_LIST_ELEMENTS_RO (pce
->pce_domain
, node
, domain
))
1627 if (domain
->header
.type
!= 0)
1628 show_vty_pce_subtlv_domain (vty
, &domain
->header
);
1631 for (ALL_LIST_ELEMENTS_RO (pce
->pce_neighbor
, node
, neighbor
))
1633 if (neighbor
->header
.type
!= 0)
1634 show_vty_pce_subtlv_neighbor (vty
, &neighbor
->header
);
1637 if (pce
->pce_cap_flag
.header
.type
!= 0)
1638 show_vty_pce_subtlv_cap_flag (vty
, &pce
->pce_cap_flag
.header
);
1643 vty_out (vty
, " Router Information is disabled on this router%s",
1650 /* Install new CLI commands */
1652 ospf_router_info_register_vty (void)
1654 install_element (VIEW_NODE
, &show_ip_ospf_router_info_cmd
);
1655 install_element (VIEW_NODE
, &show_ip_ospf_router_info_pce_cmd
);
1657 install_element (OSPF_NODE
, &router_info_area_cmd
);
1658 install_element (OSPF_NODE
, &no_router_info_cmd
);
1659 install_element (OSPF_NODE
, &pce_address_cmd
);
1660 install_element (OSPF_NODE
, &no_pce_address_cmd
);
1661 install_element (OSPF_NODE
, &pce_path_scope_cmd
);
1662 install_element (OSPF_NODE
, &no_pce_path_scope_cmd
);
1663 install_element (OSPF_NODE
, &pce_domain_cmd
);
1664 install_element (OSPF_NODE
, &no_pce_domain_cmd
);
1665 install_element (OSPF_NODE
, &pce_neighbor_cmd
);
1666 install_element (OSPF_NODE
, &no_pce_neighbor_cmd
);
1667 install_element (OSPF_NODE
, &pce_cap_flag_cmd
);
1668 install_element (OSPF_NODE
, &no_pce_cap_flag_cmd
);