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
23 * along with GNU Quagga; see the file COPYING. If not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
42 #include "sockunion.h" /* for inet_aton() */
44 #include "ospfd/ospfd.h"
45 #include "ospfd/ospf_interface.h"
46 #include "ospfd/ospf_ism.h"
47 #include "ospfd/ospf_asbr.h"
48 #include "ospfd/ospf_lsa.h"
49 #include "ospfd/ospf_lsdb.h"
50 #include "ospfd/ospf_neighbor.h"
51 #include "ospfd/ospf_nsm.h"
52 #include "ospfd/ospf_flood.h"
53 #include "ospfd/ospf_packet.h"
54 #include "ospfd/ospf_spf.h"
55 #include "ospfd/ospf_dump.h"
56 #include "ospfd/ospf_route.h"
57 #include "ospfd/ospf_ase.h"
58 #include "ospfd/ospf_zebra.h"
59 #include "ospfd/ospf_ri.h"
60 #include "ospfd/ospf_te.h"
65 /* Store Router Information PCE TLV and SubTLV in network byte order. */
66 struct ri_tlv_pce pce_header;
67 struct ri_pce_subtlv_address pce_address;
68 struct ri_pce_subtlv_path_scope pce_scope;
69 struct list *pce_domain;
70 struct list *pce_neighbor;
71 struct ri_pce_subtlv_cap_flag pce_cap_flag;
74 /* Following structure are internal use only. */
75 struct ospf_router_info
82 /* Flags to manage this router information. */
83 #define RIFLG_LOOKUP_DONE 0x1
84 #define RIFLG_LSA_ENGAGED 0x2
85 #define RIFLG_LSA_FORCED_REFRESH 0x4
88 /* area pointer if flooding is Type 10 Null if flooding is AS scope */
89 struct ospf_area *area;
90 struct in_addr area_id;
92 /* Store Router Information Capabilities LSA */
93 struct ri_tlv_router_cap router_cap;
95 /* Store PCE capability LSA */
96 struct ospf_pce_info pce_info;
100 * Global variable to manage Opaque-LSA/Router Information on this node.
101 * Note that all parameter values are stored in network byte order.
103 static struct ospf_router_info OspfRI;
105 /*------------------------------------------------------------------------------*
106 * Followings are initialize/terminate functions for Router Information handling.
107 *------------------------------------------------------------------------------*/
109 static void ospf_router_info_ism_change (struct ospf_interface *oi,
111 static void ospf_router_info_nsm_change (struct ospf_neighbor *nbr,
113 static void ospf_router_info_config_write_router (struct vty *vty);
114 static void ospf_router_info_show_info (struct vty *vty,
115 struct ospf_lsa *lsa);
116 static int ospf_router_info_lsa_originate (void *arg);
117 static struct ospf_lsa *ospf_router_info_lsa_refresh (struct ospf_lsa *lsa);
118 static void ospf_router_info_lsa_schedule (opcode_t opcode);
119 static void ospf_router_info_register_vty (void);
120 static void del_pce_info (void *val);
123 ospf_router_info_init (void)
126 memset (&OspfRI, 0, sizeof (struct ospf_router_info));
127 OspfRI.status = disabled;
128 OspfRI.registered = 0;
129 OspfRI.scope = OSPF_OPAQUE_AS_LSA;
132 /* Initialize pce domain and neighbor list */
133 OspfRI.pce_info.pce_domain = list_new ();
134 OspfRI.pce_info.pce_domain->del = del_pce_info;
135 OspfRI.pce_info.pce_neighbor = list_new ();
136 OspfRI.pce_info.pce_neighbor->del = del_pce_info;
138 ospf_router_info_register_vty ();
144 ospf_router_info_register (u_int8_t scope)
148 if (OspfRI.registered)
151 zlog_info ("Register Router Information with scope %s(%d)",
152 scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS", scope);
153 rc = ospf_register_opaque_functab (scope,
154 OPAQUE_TYPE_ROUTER_INFORMATION_LSA,
155 NULL, /* new interface */
156 NULL, /* del interface */
157 ospf_router_info_ism_change,
158 ospf_router_info_nsm_change,
159 ospf_router_info_config_write_router,
160 NULL, /* Config. write interface */
161 NULL, /* Config. write debug */
162 ospf_router_info_show_info,
163 ospf_router_info_lsa_originate,
164 ospf_router_info_lsa_refresh,
165 NULL, /* new_lsa_hook */
166 NULL); /* del_lsa_hook */
170 zlog_warn ("ospf_router_info_init: Failed to register functions");
174 OspfRI.registered = 1;
175 OspfRI.scope = scope;
180 ospf_router_info_unregister ()
183 if ((OspfRI.scope != OSPF_OPAQUE_AS_LSA)
184 && (OspfRI.scope != OSPF_OPAQUE_AREA_LSA))
186 zlog_warn ("Unable to unregister Router Info functions: Wrong scope!");
190 ospf_delete_opaque_functab (OspfRI.scope,
191 OPAQUE_TYPE_ROUTER_INFORMATION_LSA);
193 OspfRI.registered = 0;
199 ospf_router_info_term (void)
202 list_delete (OspfRI.pce_info.pce_domain);
203 list_delete (OspfRI.pce_info.pce_neighbor);
205 OspfRI.pce_info.pce_domain = NULL;
206 OspfRI.pce_info.pce_neighbor = NULL;
207 OspfRI.status = disabled;
209 ospf_router_info_unregister (OspfRI.scope);
215 del_pce_info (void *val)
217 XFREE (MTYPE_OSPF_PCE_PARAMS, val);
221 /*------------------------------------------------------------------------*
222 * Followings are control functions for ROUTER INFORMATION parameters management.
223 *------------------------------------------------------------------------*/
226 set_router_info_capabilities (struct ri_tlv_router_cap *ric, u_int32_t cap)
228 ric->header.type = htons (RI_TLV_CAPABILITIES);
229 ric->header.length = htons (RI_TLV_LENGTH);
230 ric->value = htonl (cap);
235 set_pce_header (struct ospf_pce_info *pce)
237 u_int16_t length = 0;
238 struct listnode *node;
239 struct ri_pce_subtlv_domain *domain;
240 struct ri_pce_subtlv_neighbor *neighbor;
243 if (ntohs (pce->pce_address.header.type) != 0)
244 length += RI_TLV_SIZE (&pce->pce_address.header);
247 if (ntohs (pce->pce_scope.header.type) != 0)
248 length += RI_TLV_SIZE (&pce->pce_scope.header);
251 for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain))
253 if (ntohs (domain->header.type) != 0)
254 length += RI_TLV_SIZE (&domain->header);
258 for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor))
260 if (ntohs (neighbor->header.type) != 0)
261 length += RI_TLV_SIZE (&neighbor->header);
264 /* PCE Capabilities */
265 if (ntohs (pce->pce_cap_flag.header.type) != 0)
266 length += RI_TLV_SIZE (&pce->pce_cap_flag.header);
270 pce->pce_header.header.type = htons (RI_TLV_PCE);
271 pce->pce_header.header.length = htons (length);
275 pce->pce_header.header.type = 0;
276 pce->pce_header.header.length = 0;
283 set_pce_address (struct in_addr ipv4, struct ospf_pce_info *pce)
286 /* Enable PCE Info */
287 pce->pce_header.header.type = htons (RI_TLV_PCE);
288 /* Set PCE Address */
289 pce->pce_address.header.type = htons (RI_PCE_SUBTLV_ADDRESS);
290 pce->pce_address.header.length = htons (PCE_ADDRESS_LENGTH_IPV4);
291 pce->pce_address.address.type = htons (PCE_ADDRESS_TYPE_IPV4);
292 pce->pce_address.address.value = ipv4;
298 set_pce_path_scope (u_int32_t scope, struct ospf_pce_info *pce)
301 /* Enable PCE Info */
302 pce->pce_header.header.type = htons (RI_TLV_PCE);
304 pce->pce_scope.header.type = htons (RI_PCE_SUBTLV_PATH_SCOPE);
305 pce->pce_scope.header.length = htons (RI_TLV_LENGTH);
306 pce->pce_scope.value = htonl (scope);
312 set_pce_domain (u_int16_t type, u_int32_t domain, struct ospf_pce_info *pce)
315 struct ri_pce_subtlv_domain *new;
317 /* Enable PCE Info */
318 pce->pce_header.header.type = htons (RI_TLV_PCE);
320 /* Create new domain info */
322 XCALLOC (MTYPE_OSPF_PCE_PARAMS,
323 sizeof (struct ri_pce_subtlv_domain));
325 new->header.type = htons (RI_PCE_SUBTLV_DOMAIN);
326 new->header.length = htons (PCE_ADDRESS_LENGTH_IPV4);
327 new->type = htons (type);
328 new->value = htonl (domain);
330 /* Add new domain to the list */
331 listnode_add (pce->pce_domain, new);
337 unset_pce_domain (u_int16_t type, u_int32_t domain, struct ospf_pce_info *pce)
339 struct listnode *node;
340 struct ri_pce_subtlv_domain *old = NULL;
343 /* Search the corresponding node */
344 for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, old))
346 if ((old->type == htons (type)) && (old->value == htonl (domain)))
353 /* if found remove it */
356 listnode_delete (pce->pce_domain, old);
358 /* Avoid misjudgement in the next lookup. */
359 if (listcount (pce->pce_domain) == 0)
360 pce->pce_domain->head = pce->pce_domain->tail = NULL;
362 /* Finally free the old domain */
363 XFREE (MTYPE_OSPF_PCE_PARAMS, old);
368 set_pce_neighbor (u_int16_t type, u_int32_t domain, struct ospf_pce_info *pce)
371 struct ri_pce_subtlv_neighbor *new;
373 /* Enable PCE Info */
374 pce->pce_header.header.type = htons (RI_TLV_PCE);
376 /* Create new neighbor info */
378 XCALLOC (MTYPE_OSPF_PCE_PARAMS,
379 sizeof (struct ri_pce_subtlv_neighbor));
381 new->header.type = htons (RI_PCE_SUBTLV_NEIGHBOR);
382 new->header.length = htons (PCE_ADDRESS_LENGTH_IPV4);
383 new->type = htons (type);
384 new->value = htonl (domain);
386 /* Add new domain to the list */
387 listnode_add (pce->pce_neighbor, new);
393 unset_pce_neighbor (u_int16_t type, u_int32_t domain,
394 struct ospf_pce_info *pce)
396 struct listnode *node;
397 struct ri_pce_subtlv_neighbor *old = NULL;
400 /* Search the corresponding node */
401 for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, old))
403 if ((old->type == htons (type)) && (old->value == htonl (domain)))
410 /* if found remove it */
413 listnode_delete (pce->pce_neighbor, old);
415 /* Avoid misjudgement in the next lookup. */
416 if (listcount (pce->pce_neighbor) == 0)
417 pce->pce_neighbor->head = pce->pce_neighbor->tail = NULL;
419 /* Finally free the old domain */
420 XFREE (MTYPE_OSPF_PCE_PARAMS, old);
425 set_pce_cap_flag (u_int32_t cap, struct ospf_pce_info *pce)
428 /* Enable PCE Info */
429 pce->pce_header.header.type = htons (RI_TLV_PCE);
430 /* Set PCE Capabilities flag */
431 pce->pce_cap_flag.header.type = htons (RI_PCE_SUBTLV_CAP_FLAG);
432 pce->pce_cap_flag.header.length = htons (RI_TLV_LENGTH);
433 pce->pce_cap_flag.value = htonl (cap);
440 unset_param (struct ri_tlv_header *tlv)
444 /* Fill the Value to 0 */
445 memset ((tlv + RI_TLV_HDR_SIZE), 0, RI_TLV_BODY_SIZE (tlv));
452 initialize_params (struct ospf_router_info *ori)
458 * Initialize default Router Information Capabilities.
461 cap = cap | RI_TE_SUPPORT;
463 set_router_info_capabilities (&ori->router_cap, cap);
465 /* If Area address is not null and exist, retrieve corresponding structure */
466 top = ospf_lookup ();
467 zlog_info ("RI-> Initialize Router Info for %s scope within area %s",
468 OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS",
469 inet_ntoa (OspfRI.area_id));
471 /* Try to get the Area context at this step. Do it latter if not available */
472 if ((OspfRI.scope == OSPF_OPAQUE_AREA_LSA) && (OspfRI.area == NULL))
473 OspfRI.area = ospf_area_lookup_by_area_id (top, OspfRI.area_id);
476 * Initialize default PCE Information values
478 /* PCE address == OSPF Router ID */
479 set_pce_address (top->router_id, &ori->pce_info);
482 cap = 7; /* Set L, R and Rd bits to one = intra & inter-area path computation */
483 set_pce_path_scope (cap, &ori->pce_info);
485 /* PCE Capabilities */
487 PCE_CAP_BIDIRECTIONAL | PCE_CAP_DIVERSE_PATH | PCE_CAP_OBJECTIVES |
488 PCE_CAP_ADDITIVE | PCE_CAP_MULTIPLE_REQ;
489 set_pce_cap_flag (cap, &ori->pce_info);
491 /* Finally compute PCE header */
492 set_pce_header (&ori->pce_info);
498 is_mandated_params_set (struct ospf_router_info ori)
502 if (ntohs (ori.router_cap.header.type) == 0)
505 if ((ntohs (ori.pce_info.pce_header.header.type) == RI_TLV_PCE)
506 && (ntohs (ori.pce_info.pce_address.header.type) == 0)
507 && (ntohs (ori.pce_info.pce_cap_flag.header.type) == 0))
516 /*------------------------------------------------------------------------*
517 * Followings are callback functions against generic Opaque-LSAs handling.
518 *------------------------------------------------------------------------*/
520 ospf_router_info_ism_change (struct ospf_interface *oi, int old_state)
522 /* So far, nothing to do here. */
528 ospf_router_info_nsm_change (struct ospf_neighbor *nbr, int old_state)
531 /* So far, nothing to do here. */
535 /*------------------------------------------------------------------------*
536 * Followings are OSPF protocol processing functions for ROUTER INFORMATION
537 *------------------------------------------------------------------------*/
540 build_tlv_header (struct stream *s, struct ri_tlv_header *tlvh)
543 stream_put (s, tlvh, sizeof (struct ri_tlv_header));
548 build_tlv (struct stream *s, struct ri_tlv_header *tlvh)
551 if (ntohs (tlvh->type) != 0)
553 build_tlv_header (s, tlvh);
554 stream_put (s, tlvh + 1, RI_TLV_BODY_SIZE (tlvh));
560 ospf_router_info_lsa_body_set (struct stream *s)
563 struct listnode *node;
564 struct ri_pce_subtlv_domain *domain;
565 struct ri_pce_subtlv_neighbor *neighbor;
567 /* Build Router Information TLV */
568 build_tlv (s, &OspfRI.router_cap.header);
570 /* Add RI PCE TLV if it is set */
571 /* Compute PCE Info header first */
572 if ((set_pce_header (&OspfRI.pce_info)) != 0)
576 build_tlv_header (s, &OspfRI.pce_info.pce_header.header);
578 /* Build PCE address sub-tlv */
579 build_tlv (s, &OspfRI.pce_info.pce_address.header);
581 /* Build PCE path scope sub-tlv */
582 build_tlv (s, &OspfRI.pce_info.pce_scope.header);
584 /* Build PCE domain sub-tlv */
585 for (ALL_LIST_ELEMENTS_RO (OspfRI.pce_info.pce_domain, node, domain))
586 build_tlv (s, &domain->header);
588 /* Build PCE neighbor sub-tlv */
589 for (ALL_LIST_ELEMENTS_RO
590 (OspfRI.pce_info.pce_neighbor, node, neighbor))
591 build_tlv (s, &neighbor->header);
593 /* Build PCE cap flag sub-tlv */
594 build_tlv (s, &OspfRI.pce_info.pce_cap_flag.header);
600 /* Create new opaque-LSA. */
601 static struct ospf_lsa *
602 ospf_router_info_lsa_new ()
606 struct lsa_header *lsah;
607 struct ospf_lsa *new = NULL;
608 u_char options, lsa_type;
609 struct in_addr lsa_id;
613 /* Create a stream for LSA. */
614 if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL)
616 zlog_warn ("ospf_router_info_lsa_new: stream_new() ?");
619 lsah = (struct lsa_header *) STREAM_DATA (s);
621 options = OSPF_OPTION_E; /* Enable AS external as we flood RI with Opaque Type 11 */
622 options |= OSPF_OPTION_O; /* Don't forget this :-) */
624 lsa_type = OspfRI.scope;
625 /* LSA ID == 0 for Router Information see RFC 4970 */
626 tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_ROUTER_INFORMATION_LSA, 0);
627 lsa_id.s_addr = htonl (tmp);
629 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
631 ("LSA[Type%d:%s]: Create an Opaque-LSA/ROUTER INFORMATION instance",
632 lsa_type, inet_ntoa (lsa_id));
634 top = ospf_lookup ();
636 /* Set opaque-LSA header fields. */
637 lsa_header_set (s, options, lsa_type, lsa_id, top->router_id);
639 /* Set opaque-LSA body fields. */
640 ospf_router_info_lsa_body_set (s);
643 length = stream_get_endp (s);
644 lsah->length = htons (length);
646 /* Now, create an OSPF LSA instance. */
647 if ((new = ospf_lsa_new ()) == NULL)
649 zlog_warn ("ospf_router_info_lsa_new: ospf_lsa_new() ?");
653 if ((new->data = ospf_lsa_data_new (length)) == NULL)
655 zlog_warn ("ospf_router_info_lsa_new: ospf_lsa_data_new() ?");
656 ospf_lsa_unlock (&new);
662 new->area = OspfRI.area; /* Area must be null if the Opaque type is AS scope, fulfill otherwise */
664 SET_FLAG (new->flags, OSPF_LSA_SELF);
665 memcpy (new->data, lsah, length);
672 ospf_router_info_lsa_originate1 (void *arg)
674 struct ospf_lsa *new;
676 struct ospf_area *area;
679 /* First check if the area is known if flooding scope is Area */
680 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA)
682 area = (struct ospf_area *) arg;
683 if (area->area_id.s_addr != OspfRI.area_id.s_addr)
686 ("RI -> This is not the Router Information Area. Stop processing");
692 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
693 if ((new = ospf_router_info_lsa_new ()) == NULL)
696 ("ospf_router_info_lsa_originate1: ospf_router_info_lsa_new() ?");
701 top = ospf_lookup ();
703 /* Install this LSA into LSDB. */
704 if (ospf_lsa_install (top, NULL /*oi */ , new) == NULL)
706 zlog_warn ("ospf_router_info_lsa_originate1: ospf_lsa_install() ?");
707 ospf_lsa_unlock (&new);
711 /* Now this Router Info parameter entry has associated LSA. */
712 SET_FLAG (OspfRI.flags, RIFLG_LSA_ENGAGED);
714 /* Update new LSA origination count. */
715 top->lsa_originate_count++;
717 /* Flood new LSA through AS. */
718 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
719 ospf_flood_through_as (top, NULL /*nbr */ , new);
721 ospf_flood_through_area (OspfRI.area, NULL /*nbr */ , new);
723 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
725 zlog_debug ("LSA[Type%d:%s]: Originate Opaque-LSA/ROUTER INFORMATION",
726 new->data->type, inet_ntoa (new->data->id));
727 ospf_lsa_header_dump (new->data);
735 ospf_router_info_lsa_originate (void *arg)
740 if (OspfRI.status == disabled)
743 ("ospf_router_info_lsa_originate: ROUTER INFORMATION is disabled now.");
744 rc = 0; /* This is not an error case. */
748 /* Check if Router Information LSA is already engaged */
749 if (OspfRI.flags & RIFLG_LSA_ENGAGED)
751 if (OspfRI.flags & RIFLG_LSA_FORCED_REFRESH)
753 OspfRI.flags &= ~RIFLG_LSA_FORCED_REFRESH;
754 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
759 if (!is_mandated_params_set (OspfRI))
761 ("ospf_router_info_lsa_originate: lacks mandated ROUTER INFORMATION parameters");
763 /* Ok, let's try to originate an LSA */
764 if (ospf_router_info_lsa_originate1 (arg) != 0)
772 static struct ospf_lsa *
773 ospf_router_info_lsa_refresh (struct ospf_lsa *lsa)
775 struct ospf_lsa *new = NULL;
778 if (OspfRI.status == disabled)
781 * This LSA must have flushed before due to ROUTER INFORMATION status change.
782 * It seems a slip among routers in the routing domain.
785 ("ospf_router_info_lsa_refresh: ROUTER INFORMATION is disabled now.");
786 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
789 /* Verify that the Router Information ID is supported */
790 if (GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)) != 0)
793 ("ospf_router_info_lsa_refresh: Unsupported Router Information ID");
797 /* If the lsa's age reached to MaxAge, start flushing procedure. */
798 if (IS_LSA_MAXAGE (lsa))
800 OspfRI.flags &= ~RIFLG_LSA_ENGAGED;
801 ospf_opaque_lsa_flush_schedule (lsa);
805 /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
806 if ((new = ospf_router_info_lsa_new ()) == NULL)
809 ("ospf_router_info_lsa_refresh: ospf_router_info_lsa_new() ?");
812 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
814 /* Install this LSA into LSDB. */
815 /* Given "lsa" will be freed in the next function. */
816 top = ospf_lookup ();
817 if (ospf_lsa_install (top, NULL /*oi */ , new) == NULL)
819 zlog_warn ("ospf_router_info_lsa_refresh: ospf_lsa_install() ?");
820 ospf_lsa_unlock (&new);
824 /* Flood updated LSA through AS or AREA depending of OspfRI.scope. */
825 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
826 ospf_flood_through_as (top, NULL /*nbr */ , new);
828 ospf_flood_through_area (OspfRI.area, NULL /*nbr */ , new);
831 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
833 zlog_debug ("LSA[Type%d:%s]: Refresh Opaque-LSA/ROUTER INFORMATION",
834 new->data->type, inet_ntoa (new->data->id));
835 ospf_lsa_header_dump (new->data);
842 ospf_router_info_lsa_schedule (opcode_t opcode)
845 struct lsa_header lsah;
849 memset (&lsa, 0, sizeof (lsa));
850 memset (&lsah, 0, sizeof (lsah));
852 zlog_debug ("RI-> LSA schedule %s%s%s",
853 opcode == REORIGINATE_THIS_LSA ? "Re-Originate" : "",
854 opcode == REFRESH_THIS_LSA ? "Refresh" : "",
855 opcode == FLUSH_THIS_LSA ? "Flush" : "");
857 top = ospf_lookup ();
858 if ((OspfRI.scope == OSPF_OPAQUE_AREA_LSA) && (OspfRI.area == NULL))
861 ("ospf_router_info_lsa_schedule(): Router Info is Area scope flooding but area is not set");
862 OspfRI.area = ospf_area_lookup_by_area_id (top, OspfRI.area_id);
864 lsa.area = OspfRI.area;
866 lsah.type = OspfRI.scope;
868 /* LSA ID is set to 0 for the Router Information. See RFC 4970 */
869 tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_ROUTER_INFORMATION_LSA, 0);
870 lsah.id.s_addr = htonl (tmp);
874 case REORIGINATE_THIS_LSA:
875 if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA)
876 ospf_opaque_lsa_reoriginate_schedule ((void *) OspfRI.area,
877 OSPF_OPAQUE_AREA_LSA,
878 OPAQUE_TYPE_ROUTER_INFORMATION_LSA);
880 ospf_opaque_lsa_reoriginate_schedule ((void *) top,
882 OPAQUE_TYPE_ROUTER_INFORMATION_LSA);
884 case REFRESH_THIS_LSA:
885 ospf_opaque_lsa_refresh_schedule (&lsa);
888 OspfRI.flags &= ~RIFLG_LSA_ENGAGED;
889 ospf_opaque_lsa_flush_schedule (&lsa);
892 zlog_warn ("ospf_router_info_lsa_schedule: Unknown opcode (%u)",
900 /*------------------------------------------------------------------------*
901 * Followings are vty session control functions.
902 *------------------------------------------------------------------------*/
905 show_vty_router_cap (struct vty *vty, struct ri_tlv_header *tlvh)
907 struct ri_tlv_router_cap *top = (struct ri_tlv_router_cap *) tlvh;
910 vty_out (vty, " Router Capabilities: 0x%x%s", ntohl (top->value),
913 zlog_debug (" Router Capabilities: 0x%x", ntohl (top->value));
915 return RI_TLV_SIZE (tlvh);
919 show_vty_pce_subtlv_address (struct vty *vty, struct ri_tlv_header *tlvh)
921 struct ri_pce_subtlv_address *top = (struct ri_pce_subtlv_address *) tlvh;
923 if (ntohs (top->address.type) == PCE_ADDRESS_TYPE_IPV4)
926 vty_out (vty, " PCE Address: %s%s", inet_ntoa (top->address.value),
929 zlog_debug (" PCE Address: %s", inet_ntoa (top->address.value));
933 /* TODO: Add support to IPv6 with inet_ntop() */
935 vty_out (vty, " PCE Address: 0x%x%s",
936 ntohl (top->address.value.s_addr), VTY_NEWLINE);
938 zlog_debug (" PCE Address: 0x%x",
939 ntohl (top->address.value.s_addr));
942 return RI_TLV_SIZE (tlvh);
946 show_vty_pce_subtlv_path_scope (struct vty *vty, struct ri_tlv_header *tlvh)
948 struct ri_pce_subtlv_path_scope *top =
949 (struct ri_pce_subtlv_path_scope *) tlvh;
952 vty_out (vty, " PCE Path Scope: 0x%x%s", ntohl (top->value),
955 zlog_debug (" PCE Path Scope: 0x%x", ntohl (top->value));
957 return RI_TLV_SIZE (tlvh);
961 show_vty_pce_subtlv_domain (struct vty *vty, struct ri_tlv_header *tlvh)
963 struct ri_pce_subtlv_domain *top = (struct ri_pce_subtlv_domain *) tlvh;
966 if (ntohs (top->type) == PCE_DOMAIN_TYPE_AREA)
968 tmp.s_addr = top->value;
970 vty_out (vty, " PCE domain Area: %s%s", inet_ntoa (tmp),
973 zlog_debug (" PCE domain Area: %s", inet_ntoa (tmp));
978 vty_out (vty, " PCE domain AS: %d%s", ntohl (top->value),
981 zlog_debug (" PCE domain AS: %d", ntohl (top->value));
983 return RI_TLV_SIZE (tlvh);
987 show_vty_pce_subtlv_neighbor (struct vty *vty, struct ri_tlv_header *tlvh)
990 struct ri_pce_subtlv_neighbor *top = (struct ri_pce_subtlv_neighbor *) tlvh;
993 if (ntohs (top->type) == PCE_DOMAIN_TYPE_AREA)
995 tmp.s_addr = top->value;
997 vty_out (vty, " PCE neighbor Area: %s%s", inet_ntoa (tmp),
1000 zlog_debug (" PCE neighbor Area: %s", inet_ntoa (tmp));
1005 vty_out (vty, " PCE neighbor AS: %d%s", ntohl (top->value),
1008 zlog_debug (" PCE neighbor AS: %d", ntohl (top->value));
1010 return RI_TLV_SIZE (tlvh);
1014 show_vty_pce_subtlv_cap_flag (struct vty *vty, struct ri_tlv_header *tlvh)
1016 struct ri_pce_subtlv_cap_flag *top = (struct ri_pce_subtlv_cap_flag *) tlvh;
1019 vty_out (vty, " PCE Capabilities Flag: 0x%x%s", ntohl (top->value),
1022 zlog_debug (" PCE Capabilities Flag: 0x%x", ntohl (top->value));
1024 return RI_TLV_SIZE (tlvh);
1028 show_vty_unknown_tlv (struct vty *vty, struct ri_tlv_header *tlvh)
1031 vty_out (vty, " Unknown TLV: [type(0x%x), length(0x%x)]%s",
1032 ntohs (tlvh->type), ntohs (tlvh->length), VTY_NEWLINE);
1034 zlog_debug (" Unknown TLV: [type(0x%x), length(0x%x)]",
1035 ntohs (tlvh->type), ntohs (tlvh->length));
1037 return RI_TLV_SIZE (tlvh);
1041 show_vty_pce_info (struct vty *vty, struct ri_tlv_header *ri, uint32_t total)
1043 struct ri_tlv_header *tlvh;
1046 for (tlvh = ri; sum < total; tlvh = RI_TLV_HDR_NEXT (tlvh))
1048 switch (ntohs (tlvh->type))
1050 case RI_PCE_SUBTLV_ADDRESS:
1051 sum += show_vty_pce_subtlv_address (vty, tlvh);
1053 case RI_PCE_SUBTLV_PATH_SCOPE:
1054 sum += show_vty_pce_subtlv_path_scope (vty, tlvh);
1056 case RI_PCE_SUBTLV_DOMAIN:
1057 sum += show_vty_pce_subtlv_domain (vty, tlvh);
1059 case RI_PCE_SUBTLV_NEIGHBOR:
1060 sum += show_vty_pce_subtlv_neighbor (vty, tlvh);
1062 case RI_PCE_SUBTLV_CAP_FLAG:
1063 sum += show_vty_pce_subtlv_cap_flag (vty, tlvh);
1066 sum += show_vty_unknown_tlv (vty, tlvh);
1074 ospf_router_info_show_info (struct vty *vty, struct ospf_lsa *lsa)
1076 struct lsa_header *lsah = (struct lsa_header *) lsa->data;
1077 struct ri_tlv_header *tlvh;
1078 u_int16_t length = 0, sum = 0;
1080 /* Initialize TLV browsing */
1081 length = ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE;
1083 for (tlvh = RI_TLV_HDR_TOP (lsah); sum < length;
1084 tlvh = RI_TLV_HDR_NEXT (tlvh))
1086 switch (ntohs (tlvh->type))
1088 case RI_TLV_CAPABILITIES:
1089 sum += show_vty_router_cap (vty, tlvh);
1093 sum += RI_TLV_HDR_SIZE;
1094 sum += show_vty_pce_info (vty, tlvh, length - sum);
1097 sum += show_vty_unknown_tlv (vty, tlvh);
1106 ospf_router_info_config_write_router (struct vty *vty)
1108 struct ospf_pce_info *pce = &OspfRI.pce_info;
1109 struct listnode *node;
1110 struct ri_pce_subtlv_domain *domain;
1111 struct ri_pce_subtlv_neighbor *neighbor;
1114 if (OspfRI.status == enabled)
1116 if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
1117 vty_out (vty, " router-info as%s", VTY_NEWLINE);
1119 vty_out (vty, " router-info area %s%s", inet_ntoa (OspfRI.area_id),
1122 if (pce->pce_address.header.type != 0)
1123 vty_out (vty, " pce address %s%s",
1124 inet_ntoa (pce->pce_address.address.value), VTY_NEWLINE);
1126 if (pce->pce_cap_flag.header.type != 0)
1127 vty_out (vty, " pce flag 0x%x%s", ntohl (pce->pce_cap_flag.value),
1130 for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain))
1132 if (domain->header.type != 0)
1134 if (domain->type == PCE_DOMAIN_TYPE_AREA)
1136 tmp.s_addr = domain->value;
1137 vty_out (vty, " pce domain area %s%s", inet_ntoa (tmp),
1142 vty_out (vty, " pce domain as %d%s", ntohl (domain->value),
1148 for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor))
1150 if (neighbor->header.type != 0)
1152 if (neighbor->type == PCE_DOMAIN_TYPE_AREA)
1154 tmp.s_addr = neighbor->value;
1155 vty_out (vty, " pce neighbor area %s%s", inet_ntoa (tmp),
1160 vty_out (vty, " pce neighbor as %d%s",
1161 ntohl (neighbor->value), VTY_NEWLINE);
1166 if (pce->pce_scope.header.type != 0)
1167 vty_out (vty, " pce scope 0x%x%s",
1168 ntohl (OspfRI.pce_info.pce_scope.value), VTY_NEWLINE);
1173 /*------------------------------------------------------------------------*
1174 * Followings are vty command functions.
1175 *------------------------------------------------------------------------*/
1178 router_info_area_cmd,
1179 "router-info area A.B.C.D",
1181 "Enable the Router Information functionality with Area flooding scope\n"
1182 "OSPF area ID in IP format")
1187 if (OspfRI.status == enabled)
1190 /* Check and get Area value if present */
1193 if (!inet_aton (argv[0], &OspfRI.area_id))
1195 vty_out (vty, "Please specify Router Info Area by A.B.C.D%s",
1199 scope = OSPF_OPAQUE_AREA_LSA;
1203 OspfRI.area_id.s_addr = 0;
1204 scope = OSPF_OPAQUE_AS_LSA;
1207 /* First start to register Router Information callbacks */
1208 if ((ospf_router_info_register (scope)) != 0)
1210 zlog_warn ("Enable to register Router Information callbacks. Abort!");
1214 OspfRI.status = enabled;
1216 if (IS_DEBUG_OSPF_EVENT)
1217 zlog_debug ("RI-> Router Information (%s flooding): OFF -> ON",
1218 OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS");
1221 * Following code is intended to handle two cases;
1223 * 1) Router Information was disabled at startup time, but now become enabled.
1224 * 2) Router Information was once enabled then disabled, and now enabled again.
1227 initialize_params (&OspfRI);
1229 /* Refresh RI LSA if already engaged */
1230 if (OspfRI.flags & RIFLG_LSA_ENGAGED)
1232 zlog_debug ("RI-> Initial origination following configuration");
1233 ospf_router_info_lsa_schedule (REORIGINATE_THIS_LSA);
1243 "Enable the Router Information functionality with AS flooding scope\n")
1245 DEFUN (no_router_info,
1249 "Disable the Router Information functionality\n")
1252 if (OspfRI.status == disabled)
1255 if (IS_DEBUG_OSPF_EVENT)
1256 zlog_debug ("RI-> Router Information: ON -> OFF");
1258 if (OspfRI.flags & RIFLG_LSA_ENGAGED)
1259 ospf_router_info_lsa_schedule (FLUSH_THIS_LSA);
1261 /* Unregister the callbacks */
1262 ospf_router_info_unregister ();
1264 OspfRI.status = disabled;
1271 "pce address A.B.C.D",
1273 "Stable IP address of the PCE\n"
1274 "PCE address in IPv4 address format\n")
1276 struct in_addr value;
1277 struct ospf_pce_info *pi = &OspfRI.pce_info;
1279 if (!inet_aton (argv[0], &value))
1281 vty_out (vty, "Please specify PCE Address by A.B.C.D%s", VTY_NEWLINE);
1285 if (ntohs (pi->pce_address.header.type) == 0
1286 || ntohl (pi->pce_address.address.value.s_addr) != ntohl (value.s_addr))
1289 set_pce_address (value, pi);
1291 /* Refresh RI LSA if already engaged */
1292 if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
1293 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1299 DEFUN (no_pce_address,
1304 "Disable PCE address\n")
1307 unset_param (&OspfRI.pce_info.pce_address.header);
1309 /* Refresh RI LSA if already engaged */
1310 if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
1311 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1316 DEFUN (pce_path_scope,
1318 "pce scope BITPATTERN",
1320 "Path scope visibilities of the PCE for path computation\n"
1321 "32-bit Hexadecimal value\n")
1324 struct ospf_pce_info *pi = &OspfRI.pce_info;
1326 if (sscanf (argv[0], "0x%x", &scope) != 1)
1328 vty_out (vty, "pce_path_scope: fscanf: %s%s", safe_strerror (errno),
1333 if (ntohl (pi->pce_scope.header.type) == 0 || scope != pi->pce_scope.value)
1335 set_pce_path_scope (scope, pi);
1337 /* Refresh RI LSA if already engaged */
1338 if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
1339 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1345 DEFUN (no_pce_path_scope,
1346 no_pce_path_scope_cmd,
1350 "Disable PCE path scope\n")
1353 unset_param (&OspfRI.pce_info.pce_address.header);
1355 /* Refresh RI LSA if already engaged */
1356 if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
1357 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1364 "pce domain as <0-65535>",
1366 "Configure PCE domain AS number\n"
1367 "AS number where the PCE as visibilities for path computation\n"
1368 "AS number in decimal <0-65535>\n")
1372 struct ospf_pce_info *pce = &OspfRI.pce_info;
1373 struct listnode *node;
1374 struct ri_pce_subtlv_domain *domain;
1376 if (sscanf (argv[0], "%d", &as) != 1)
1378 vty_out (vty, "pce_domain: fscanf: %s%s", safe_strerror (errno),
1383 /* Check if the domain is not already in the domain list */
1384 for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain))
1386 if (ntohl (domain->header.type) == 0 && as == domain->value)
1390 /* Create new domain if not found */
1391 set_pce_domain (PCE_DOMAIN_TYPE_AS, as, pce);
1393 /* Refresh RI LSA if already engaged */
1394 if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
1395 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1397 out:return CMD_SUCCESS;
1400 DEFUN (no_pce_domain,
1402 "no pce domain as <0-65535>",
1405 "Disable PCE domain AS number\n"
1406 "AS number where the PCE as visibilities for path computation\n"
1407 "AS number in decimal <0-65535>\n")
1411 struct ospf_pce_info *pce = &OspfRI.pce_info;
1413 if (sscanf (argv[0], "%d", &as) != 1)
1415 vty_out (vty, "no_pce_domain: fscanf: %s%s", safe_strerror (errno),
1420 /* Unset corresponding PCE domain */
1421 unset_pce_domain (PCE_DOMAIN_TYPE_AS, as, pce);
1423 /* Refresh RI LSA if already engaged */
1424 if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
1425 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1430 DEFUN (pce_neigbhor,
1432 "pce neighbor as <0-65535>",
1434 "Configure PCE neighbor domain AS number\n"
1435 "AS number of PCE neighbors\n"
1436 "AS number in decimal <0-65535>\n")
1440 struct ospf_pce_info *pce = &OspfRI.pce_info;
1441 struct listnode *node;
1442 struct ri_pce_subtlv_neighbor *neighbor;
1444 if (sscanf (argv[0], "%d", &as) != 1)
1446 vty_out (vty, "pce_neighbor: fscanf: %s%s", safe_strerror (errno),
1451 /* Check if the domain is not already in the domain list */
1452 for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor))
1454 if (ntohl (neighbor->header.type) == 0 && as == neighbor->value)
1458 /* Create new domain if not found */
1459 set_pce_neighbor (PCE_DOMAIN_TYPE_AS, as, pce);
1461 /* Refresh RI LSA if already engaged */
1462 if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
1463 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1465 out:return CMD_SUCCESS;
1468 DEFUN (no_pce_neighbor,
1469 no_pce_neighbor_cmd,
1470 "no pce neighbor as <0-65535>",
1473 "Disable PCE neighbor AS number\n"
1474 "AS number of PCE neighbor\n"
1475 "AS number in decimal <0-65535>\n")
1479 struct ospf_pce_info *pce = &OspfRI.pce_info;
1481 if (sscanf (argv[0], "%d", &as) != 1)
1483 vty_out (vty, "no_pce_neighbor: fscanf: %s%s", safe_strerror (errno),
1488 /* Unset corresponding PCE domain */
1489 unset_pce_neighbor (PCE_DOMAIN_TYPE_AS, as, pce);
1491 /* Refresh RI LSA if already engaged */
1492 if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
1493 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1498 DEFUN (pce_cap_flag,
1500 "pce flag BITPATTERN",
1502 "Capabilities of the PCE for path computation\n"
1503 "32-bit Hexadecimal value\n")
1507 struct ospf_pce_info *pce = &OspfRI.pce_info;
1509 if (sscanf (argv[0], "0x%x", &cap) != 1)
1511 vty_out (vty, "pce_cap_flag: fscanf: %s%s", safe_strerror (errno),
1516 if (ntohl (pce->pce_cap_flag.header.type) == 0
1517 || cap != pce->pce_cap_flag.value)
1519 set_pce_cap_flag (cap, pce);
1521 /* Refresh RI LSA if already engaged */
1522 if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
1523 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1529 DEFUN (no_pce_cap_flag,
1530 no_pce_cap_flag_cmd,
1534 "Disable PCE capabilities\n")
1537 unset_param (&OspfRI.pce_info.pce_cap_flag.header);
1539 /* Refresh RI LSA if already engaged */
1540 if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
1541 ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
1546 DEFUN (show_ip_ospf_router_info,
1547 show_ip_ospf_router_info_cmd,
1548 "show ip ospf router-info",
1552 "Router Information\n")
1555 if (OspfRI.status == enabled)
1557 vty_out (vty, "--- Router Information parameters ---%s", VTY_NEWLINE);
1558 show_vty_router_cap (vty, &OspfRI.router_cap.header);
1563 vty_out (vty, " Router Information is disabled on this router%s", VTY_NEWLINE);
1568 DEFUN (show_ip_opsf_router_info_pce,
1569 show_ip_ospf_router_info_pce_cmd,
1570 "show ip ospf router-info pce",
1574 "Router Information\n"
1575 "PCE information\n")
1578 struct ospf_pce_info *pce = &OspfRI.pce_info;
1579 struct listnode *node;
1580 struct ri_pce_subtlv_domain *domain;
1581 struct ri_pce_subtlv_neighbor *neighbor;
1583 if (OspfRI.status == enabled)
1585 vty_out (vty, "--- PCE parameters ---%s", VTY_NEWLINE);
1587 if (pce->pce_address.header.type != 0)
1588 show_vty_pce_subtlv_address (vty, &pce->pce_address.header);
1590 if (pce->pce_scope.header.type != 0)
1591 show_vty_pce_subtlv_path_scope (vty, &pce->pce_scope.header);
1593 for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain))
1595 if (domain->header.type != 0)
1596 show_vty_pce_subtlv_domain (vty, &domain->header);
1599 for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor))
1601 if (neighbor->header.type != 0)
1602 show_vty_pce_subtlv_neighbor (vty, &neighbor->header);
1605 if (pce->pce_cap_flag.header.type != 0)
1606 show_vty_pce_subtlv_cap_flag (vty, &pce->pce_cap_flag.header);
1611 vty_out (vty, " Router Information is disabled on this router%s",
1618 /* Install new CLI commands */
1620 ospf_router_info_register_vty (void)
1622 install_element (VIEW_NODE, &show_ip_ospf_router_info_cmd);
1623 install_element (VIEW_NODE, &show_ip_ospf_router_info_pce_cmd);
1625 install_element (OSPF_NODE, &router_info_area_cmd);
1626 install_element (OSPF_NODE, &router_info_as_cmd);
1627 install_element (OSPF_NODE, &no_router_info_cmd);
1628 install_element (OSPF_NODE, &pce_address_cmd);
1629 install_element (OSPF_NODE, &pce_path_scope_cmd);
1630 install_element (OSPF_NODE, &pce_domain_cmd);
1631 install_element (OSPF_NODE, &no_pce_domain_cmd);
1632 install_element (OSPF_NODE, &pce_neighbor_cmd);
1633 install_element (OSPF_NODE, &no_pce_neighbor_cmd);
1634 install_element (OSPF_NODE, &pce_cap_flag_cmd);