2 * This is an implementation of draft-katz-yeung-ospf-traffic-06.txt
3 * Copyright (C) 2001 KDD R&D Laboratories, Inc.
4 * http://www.kddlabs.co.jp/
6 * This file is part of GNU Zebra.
8 * GNU Zebra is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
13 * GNU Zebra is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with GNU Zebra; see the file COPYING. If not, write to the Free
20 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
24 /***** MTYPE definition is not reflected to "memory.h" yet. *****/
25 #define MTYPE_OSPF_MPLS_TE_LINKPARAMS 0
30 #ifndef HAVE_OPAQUE_LSA
31 #error "Wrong configure option"
32 #endif /* HAVE_OPAQUE_LSA */
46 #include "sockunion.h" /* for inet_aton() */
48 #include "ospfd/ospfd.h"
49 #include "ospfd/ospf_interface.h"
50 #include "ospfd/ospf_ism.h"
51 #include "ospfd/ospf_asbr.h"
52 #include "ospfd/ospf_lsa.h"
53 #include "ospfd/ospf_lsdb.h"
54 #include "ospfd/ospf_neighbor.h"
55 #include "ospfd/ospf_nsm.h"
56 #include "ospfd/ospf_flood.h"
57 #include "ospfd/ospf_packet.h"
58 #include "ospfd/ospf_spf.h"
59 #include "ospfd/ospf_dump.h"
60 #include "ospfd/ospf_route.h"
61 #include "ospfd/ospf_ase.h"
62 #include "ospfd/ospf_zebra.h"
63 #include "ospfd/ospf_te.h"
65 /* Following structure are internal use only. */
68 enum { disabled
, enabled
} status
;
70 /* List elements are zebra-interfaces (ifp), not ospf-interfaces (oi). */
73 /* Store Router-TLV in network byte order. */
74 struct te_tlv_router_addr router_addr
;
80 * According to MPLS-TE (draft) specification, 24-bit Opaque-ID field
81 * is subdivided into 8-bit "unused" field and 16-bit "instance" field.
82 * In this implementation, each Link-TLV has its own instance.
86 /* Reference pointer to a Zebra-interface. */
87 struct interface
*ifp
;
89 /* Area info in which this MPLS-TE link belongs to. */
90 struct ospf_area
*area
;
92 /* Flags to manage this link parameters. */
94 #define LPFLG_LOOKUP_DONE 0x1
95 #define LPFLG_LSA_ENGAGED 0x2
96 #define LPFLG_LSA_FORCED_REFRESH 0x4
98 /* Store Link-TLV in network byte order. */
99 struct te_tlv_link link_header
;
100 struct te_link_subtlv_link_type link_type
;
101 struct te_link_subtlv_link_id link_id
;
102 struct te_link_subtlv_lclif_ipaddr
*lclif_ipaddr
;
103 struct te_link_subtlv_rmtif_ipaddr
*rmtif_ipaddr
;
104 struct te_link_subtlv_te_metric te_metric
;
105 struct te_link_subtlv_max_bw max_bw
;
106 struct te_link_subtlv_max_rsv_bw max_rsv_bw
;
107 struct te_link_subtlv_unrsv_bw unrsv_bw
;
108 struct te_link_subtlv_rsc_clsclr rsc_clsclr
;
112 * Global variable to manage Opaque-LSA/MPLS-TE on this node.
113 * Note that all parameter values are stored in network byte order.
115 static struct ospf_mpls_te OspfMplsTE
;
118 OI_ANY
, OI_DOWN
, OI_UP
122 REORIGINATE_PER_AREA
, REFRESH_THIS_LSA
, FLUSH_THIS_LSA
125 /*------------------------------------------------------------------------*
126 * Followings are initialize/terminate functions for MPLS-TE handling.
127 *------------------------------------------------------------------------*/
129 static int ospf_mpls_te_new_if (struct interface
*ifp
);
130 static int ospf_mpls_te_del_if (struct interface
*ifp
);
131 static void ospf_mpls_te_ism_change (struct ospf_interface
*oi
, int old_status
);
132 static void ospf_mpls_te_nsm_change (struct ospf_neighbor
*nbr
, int old_status
);
133 static void ospf_mpls_te_config_write_router (struct vty
*vty
);
134 static void ospf_mpls_te_config_write_if (struct vty
*vty
, struct interface
*ifp
);
135 static void ospf_mpls_te_show_info (struct vty
*vty
, struct ospf_lsa
*lsa
);
136 static int ospf_mpls_te_lsa_originate (void *arg
);
137 static struct ospf_lsa
*ospf_mpls_te_lsa_refresh (struct ospf_lsa
*lsa
);
138 static void ospf_mpls_te_lsa_schedule (struct mpls_te_link
*lp
, enum sched_opcode
);
140 static void del_mpls_te_link (void *val
);
141 static void ospf_mpls_te_register_vty (void);
144 ospf_mpls_te_init (void)
148 rc
= ospf_register_opaque_functab (
149 OSPF_OPAQUE_AREA_LSA
,
150 OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA
,
153 ospf_mpls_te_ism_change
,
154 ospf_mpls_te_nsm_change
,
155 ospf_mpls_te_config_write_router
,
156 ospf_mpls_te_config_write_if
,
157 NULL
,/* ospf_mpls_te_config_write_debug */
158 ospf_mpls_te_show_info
,
159 ospf_mpls_te_lsa_originate
,
160 ospf_mpls_te_lsa_refresh
,
161 NULL
,/* ospf_mpls_te_new_lsa_hook */
162 NULL
/* ospf_mpls_te_del_lsa_hook */);
165 zlog_warn ("ospf_mpls_te_init: Failed to register functions");
169 memset (&OspfMplsTE
, 0, sizeof (struct ospf_mpls_te
));
170 OspfMplsTE
.status
= disabled
;
171 OspfMplsTE
.iflist
= list_new ();
172 OspfMplsTE
.iflist
->del
= del_mpls_te_link
;
174 ospf_mpls_te_register_vty ();
181 ospf_mpls_te_term (void)
183 list_delete (OspfMplsTE
.iflist
);
185 OspfMplsTE
.iflist
= NULL
;
186 OspfMplsTE
.status
= disabled
;
188 ospf_delete_opaque_functab (OSPF_OPAQUE_AREA_LSA
,
189 OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA
);
193 /*------------------------------------------------------------------------*
194 * Followings are control functions for MPLS-TE parameters management.
195 *------------------------------------------------------------------------*/
198 del_mpls_te_link (void *val
)
200 XFREE (MTYPE_OSPF_MPLS_TE_LINKPARAMS
, val
);
205 get_mpls_te_instance_value (void)
207 static u_int32_t seqno
= 0;
209 if (seqno
< MAX_LEGAL_TE_INSTANCE_NUM
)
212 seqno
= 1; /* Avoid zero. */
217 static struct ospf_interface
*
218 lookup_oi_by_ifp (struct interface
*ifp
,
219 struct ospf_area
*area
, enum oifstate oifstate
)
221 struct ospf_interface
*oi
= NULL
;
222 struct route_node
*rn
;
224 for (rn
= route_top (IF_OIFS (ifp
)); rn
; rn
= route_next (rn
))
226 if ((oi
= rn
->info
) == NULL
)
234 if (ospf_if_is_enable (oi
))
238 if (! ospf_if_is_enable (oi
))
242 zlog_warn ("lookup_oi_by_ifp: Unknown oifstate: %x", oifstate
);
246 if (area
== NULL
|| oi
->area
== area
)
253 static struct mpls_te_link
*
254 lookup_linkparams_by_ifp (struct interface
*ifp
)
256 struct listnode
*node
, *nnode
;
257 struct mpls_te_link
*lp
;
259 for (ALL_LIST_ELEMENTS (OspfMplsTE
.iflist
, node
, nnode
, lp
))
266 static struct mpls_te_link
*
267 lookup_linkparams_by_instance (struct ospf_lsa
*lsa
)
269 struct listnode
*node
;
270 struct mpls_te_link
*lp
;
271 unsigned int key
= GET_OPAQUE_ID (ntohl (lsa
->data
->id
.s_addr
));
273 for (ALL_LIST_ELEMENTS_RO (OspfMplsTE
.iflist
, node
, lp
))
274 if (lp
->instance
== key
)
277 zlog_warn ("lookup_linkparams_by_instance: Entry not found: key(%x)", key
);
282 ospf_mpls_te_foreach_area (
283 void (*func
)(struct mpls_te_link
*lp
, enum sched_opcode
),
284 enum sched_opcode sched_opcode
)
286 struct listnode
*node
, *nnode
;
287 struct listnode
*node2
;
288 struct mpls_te_link
*lp
;
289 struct ospf_area
*area
;
291 for (ALL_LIST_ELEMENTS (OspfMplsTE
.iflist
, node
, nnode
, lp
))
293 if ((area
= lp
->area
) == NULL
)
295 if (lp
->flags
& LPFLG_LOOKUP_DONE
)
299 (* func
)(lp
, sched_opcode
);
301 for (node2
= listnextnode (node
); node2
; node2
= listnextnode (node2
))
302 if ((lp
= listgetdata (node2
)) != NULL
)
303 if (lp
->area
!= NULL
)
304 if (IPV4_ADDR_SAME (&lp
->area
->area_id
, &area
->area_id
))
305 lp
->flags
|= LPFLG_LOOKUP_DONE
;
308 for (ALL_LIST_ELEMENTS_RO (OspfMplsTE
.iflist
, node
, lp
))
309 if (lp
->area
!= NULL
)
310 lp
->flags
&= ~LPFLG_LOOKUP_DONE
;
316 set_mpls_te_router_addr (struct in_addr ipv4
)
318 OspfMplsTE
.router_addr
.header
.type
= htons (TE_TLV_ROUTER_ADDR
);
319 OspfMplsTE
.router_addr
.header
.length
= htons (sizeof (ipv4
));
320 OspfMplsTE
.router_addr
.value
= ipv4
;
325 set_linkparams_link_header (struct mpls_te_link
*lp
)
327 struct te_tlv_header
*tlvh
;
328 u_int16_t length
= 0;
330 /* TE_LINK_SUBTLV_LINK_TYPE */
331 if (ntohs (lp
->link_type
.header
.type
) != 0)
332 length
+= TLV_SIZE (&lp
->link_type
.header
);
334 /* TE_LINK_SUBTLV_LINK_ID */
335 if (ntohs (lp
->link_id
.header
.type
) != 0)
336 length
+= TLV_SIZE (&lp
->link_id
.header
);
338 /* TE_LINK_SUBTLV_LCLIF_IPADDR */
339 if ((tlvh
= (struct te_tlv_header
*) lp
->lclif_ipaddr
) != NULL
340 && ntohs (tlvh
->type
) != 0)
341 length
+= TLV_SIZE (tlvh
);
343 /* TE_LINK_SUBTLV_RMTIF_IPADDR */
344 if ((tlvh
= (struct te_tlv_header
*) lp
->rmtif_ipaddr
) != NULL
345 && ntohs (tlvh
->type
) != 0)
346 length
+= TLV_SIZE (tlvh
);
348 /* TE_LINK_SUBTLV_TE_METRIC */
349 if (ntohs (lp
->te_metric
.header
.type
) != 0)
350 length
+= TLV_SIZE (&lp
->te_metric
.header
);
352 /* TE_LINK_SUBTLV_MAX_BW */
353 if (ntohs (lp
->max_bw
.header
.type
) != 0)
354 length
+= TLV_SIZE (&lp
->max_bw
.header
);
356 /* TE_LINK_SUBTLV_MAX_RSV_BW */
357 if (ntohs (lp
->max_rsv_bw
.header
.type
) != 0)
358 length
+= TLV_SIZE (&lp
->max_rsv_bw
.header
);
360 /* TE_LINK_SUBTLV_UNRSV_BW */
361 if (ntohs (lp
->unrsv_bw
.header
.type
) != 0)
362 length
+= TLV_SIZE (&lp
->unrsv_bw
.header
);
364 /* TE_LINK_SUBTLV_RSC_CLSCLR */
365 if (ntohs (lp
->rsc_clsclr
.header
.type
) != 0)
366 length
+= TLV_SIZE (&lp
->rsc_clsclr
.header
);
368 lp
->link_header
.header
.type
= htons (TE_TLV_LINK
);
369 lp
->link_header
.header
.length
= htons (length
);
375 set_linkparams_link_type (struct ospf_interface
*oi
, struct mpls_te_link
*lp
)
377 lp
->link_type
.header
.type
= htons (TE_LINK_SUBTLV_LINK_TYPE
);
378 lp
->link_type
.header
.length
= htons (sizeof (lp
->link_type
.link_type
.value
));
382 case OSPF_IFTYPE_POINTOPOINT
:
383 lp
->link_type
.link_type
.value
= LINK_TYPE_SUBTLV_VALUE_PTP
;
385 case OSPF_IFTYPE_BROADCAST
:
386 case OSPF_IFTYPE_NBMA
:
387 lp
->link_type
.link_type
.value
= LINK_TYPE_SUBTLV_VALUE_MA
;
390 /* Not supported yet. *//* XXX */
391 lp
->link_type
.header
.type
= htons (0);
398 set_linkparams_link_id (struct ospf_interface
*oi
, struct mpls_te_link
*lp
)
400 struct ospf_neighbor
*nbr
;
403 lp
->link_id
.header
.type
= htons (TE_LINK_SUBTLV_LINK_ID
);
404 lp
->link_id
.header
.length
= htons (sizeof (lp
->link_id
.value
));
407 * The Link ID is identical to the contents of the Link ID field
408 * in the Router LSA for these link types.
412 case OSPF_IFTYPE_POINTOPOINT
:
413 /* Take the router ID of the neighbor. */
414 if ((nbr
= ospf_nbr_lookup_ptop (oi
))
415 && nbr
->state
== NSM_Full
)
417 lp
->link_id
.value
= nbr
->router_id
;
421 case OSPF_IFTYPE_BROADCAST
:
422 case OSPF_IFTYPE_NBMA
:
423 /* Take the interface address of the designated router. */
424 if ((nbr
= ospf_nbr_lookup_by_addr (oi
->nbrs
, &DR (oi
))) == NULL
)
427 if (nbr
->state
== NSM_Full
428 || (IPV4_ADDR_SAME (&oi
->address
->u
.prefix4
, &DR (oi
))
429 && ospf_nbr_count (oi
, NSM_Full
) > 0))
431 lp
->link_id
.value
= DR (oi
);
436 /* Not supported yet. *//* XXX */
437 lp
->link_id
.header
.type
= htons (0);
444 masklen2ip (oi
->address
->prefixlen
, &mask
);
445 lp
->link_id
.value
.s_addr
= oi
->address
->u
.prefix4
.s_addr
& mask
.s_addr
;
451 set_linkparams_te_metric (struct mpls_te_link
*lp
, u_int32_t te_metric
)
453 lp
->te_metric
.header
.type
= htons (TE_LINK_SUBTLV_TE_METRIC
);
454 lp
->te_metric
.header
.length
= htons (sizeof (lp
->te_metric
.value
));
455 lp
->te_metric
.value
= htonl (te_metric
);
460 set_linkparams_max_bw (struct mpls_te_link
*lp
, float *fp
)
462 lp
->max_bw
.header
.type
= htons (TE_LINK_SUBTLV_MAX_BW
);
463 lp
->max_bw
.header
.length
= htons (sizeof (lp
->max_bw
.value
));
464 htonf (fp
, &lp
->max_bw
.value
);
469 set_linkparams_max_rsv_bw (struct mpls_te_link
*lp
, float *fp
)
471 lp
->max_rsv_bw
.header
.type
= htons (TE_LINK_SUBTLV_MAX_RSV_BW
);
472 lp
->max_rsv_bw
.header
.length
= htons (sizeof (lp
->max_rsv_bw
.value
));
473 htonf (fp
, &lp
->max_rsv_bw
.value
);
478 set_linkparams_unrsv_bw (struct mpls_te_link
*lp
, int priority
, float *fp
)
480 /* Note that TLV-length field is the size of array. */
481 lp
->unrsv_bw
.header
.type
= htons (TE_LINK_SUBTLV_UNRSV_BW
);
482 lp
->unrsv_bw
.header
.length
= htons (sizeof (lp
->unrsv_bw
.value
));
483 htonf (fp
, &lp
->unrsv_bw
.value
[priority
]);
488 set_linkparams_rsc_clsclr (struct mpls_te_link
*lp
, u_int32_t classcolor
)
490 lp
->rsc_clsclr
.header
.type
= htons (TE_LINK_SUBTLV_RSC_CLSCLR
);
491 lp
->rsc_clsclr
.header
.length
= htons (sizeof (lp
->rsc_clsclr
.value
));
492 lp
->rsc_clsclr
.value
= htonl (classcolor
);
497 initialize_linkparams (struct mpls_te_link
*lp
)
499 struct interface
*ifp
= lp
->ifp
;
500 struct ospf_interface
*oi
;
504 if ((oi
= lookup_oi_by_ifp (ifp
, NULL
, OI_ANY
)) == NULL
)
508 * Try to set initial values those can be derived from
509 * zebra-interface information.
511 set_linkparams_link_type (oi
, lp
);
514 * Linux and *BSD kernel holds bandwidth parameter as an "int" type.
515 * We may have to reconsider, if "ifp->bandwidth" type changes to float.
517 fval
= (float)((ifp
->bandwidth
? ifp
->bandwidth
518 : OSPF_DEFAULT_BANDWIDTH
) * 1000 / 8);
520 set_linkparams_max_bw (lp
, &fval
);
521 set_linkparams_max_rsv_bw (lp
, &fval
);
523 for (i
= 0; i
< 8; i
++)
524 set_linkparams_unrsv_bw (lp
, i
, &fval
);
530 is_mandated_params_set (struct mpls_te_link
*lp
)
534 if (ntohs (OspfMplsTE
.router_addr
.header
.type
) == 0)
537 if (ntohs (lp
->link_type
.header
.type
) == 0)
540 if (ntohs (lp
->link_id
.header
.type
) == 0)
548 /*------------------------------------------------------------------------*
549 * Followings are callback functions against generic Opaque-LSAs handling.
550 *------------------------------------------------------------------------*/
553 ospf_mpls_te_new_if (struct interface
*ifp
)
555 struct mpls_te_link
*new;
558 if (lookup_linkparams_by_ifp (ifp
) != NULL
)
560 zlog_warn ("ospf_mpls_te_new_if: ifp(%p) already in use?", (void *)ifp
);
561 rc
= 0; /* Do nothing here. */
565 new = XCALLOC (MTYPE_OSPF_MPLS_TE_LINKPARAMS
,
566 sizeof (struct mpls_te_link
));
569 zlog_warn ("ospf_mpls_te_new_if: XMALLOC: %s", safe_strerror (errno
));
575 new->instance
= get_mpls_te_instance_value ();
578 initialize_linkparams (new);
580 listnode_add (OspfMplsTE
.iflist
, new);
582 /* Schedule Opaque-LSA refresh. *//* XXX */
590 ospf_mpls_te_del_if (struct interface
*ifp
)
592 struct mpls_te_link
*lp
;
595 if ((lp
= lookup_linkparams_by_ifp (ifp
)) != NULL
)
597 struct list
*iflist
= OspfMplsTE
.iflist
;
599 /* Dequeue listnode entry from the list. */
600 listnode_delete (iflist
, lp
);
602 /* Avoid misjudgement in the next lookup. */
603 if (listcount (iflist
) == 0)
604 iflist
->head
= iflist
->tail
= NULL
;
606 XFREE (MTYPE_OSPF_MPLS_TE_LINKPARAMS
, lp
);
609 /* Schedule Opaque-LSA refresh. *//* XXX */
617 ospf_mpls_te_ism_change (struct ospf_interface
*oi
, int old_state
)
619 struct te_link_subtlv_link_type old_type
;
620 struct te_link_subtlv_link_id old_id
;
621 struct mpls_te_link
*lp
;
623 if ((lp
= lookup_linkparams_by_ifp (oi
->ifp
)) == NULL
)
625 zlog_warn ("ospf_mpls_te_ism_change: Cannot get linkparams from OI(%s)?", IF_NAME (oi
));
628 if (oi
->area
== NULL
|| oi
->area
->ospf
== NULL
)
630 zlog_warn ("ospf_mpls_te_ism_change: Cannot refer to OSPF from OI(%s)?",
635 if ((lp
->area
!= NULL
636 && ! IPV4_ADDR_SAME (&lp
->area
->area_id
, &oi
->area
->area_id
))
637 || (lp
->area
!= NULL
&& oi
->area
== NULL
))
639 /* How should we consider this case? */
640 zlog_warn ("MPLS-TE: Area for OI(%s) has changed to [%s], flush previous LSAs", IF_NAME (oi
), oi
->area
? inet_ntoa (oi
->area
->area_id
) : "N/A");
641 ospf_mpls_te_lsa_schedule (lp
, FLUSH_THIS_LSA
);
644 /* Keep Area information in conbination with linkparams. */
649 case ISM_PointToPoint
:
653 old_type
= lp
->link_type
;
654 old_id
= lp
->link_id
;
656 set_linkparams_link_type (oi
, lp
);
657 set_linkparams_link_id (oi
, lp
);
659 if ((ntohs (old_type
.header
.type
) != ntohs (lp
->link_type
.header
.type
)
660 || old_type
.link_type
.value
!= lp
->link_type
.link_type
.value
)
661 || (ntohs (old_id
.header
.type
) != ntohs (lp
->link_id
.header
.type
)
662 || ntohl (old_id
.value
.s_addr
) != ntohl (lp
->link_id
.value
.s_addr
)))
664 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
665 ospf_mpls_te_lsa_schedule (lp
, REFRESH_THIS_LSA
);
667 ospf_mpls_te_lsa_schedule (lp
, REORIGINATE_PER_AREA
);
671 lp
->link_type
.header
.type
= htons (0);
672 lp
->link_id
.header
.type
= htons (0);
674 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
675 ospf_mpls_te_lsa_schedule (lp
, FLUSH_THIS_LSA
);
684 ospf_mpls_te_nsm_change (struct ospf_neighbor
*nbr
, int old_state
)
686 /* So far, nothing to do here. */
690 /*------------------------------------------------------------------------*
691 * Followings are OSPF protocol processing functions for MPLS-TE.
692 *------------------------------------------------------------------------*/
695 build_tlv_header (struct stream
*s
, struct te_tlv_header
*tlvh
)
697 stream_put (s
, tlvh
, sizeof (struct te_tlv_header
));
702 build_router_tlv (struct stream
*s
)
704 struct te_tlv_header
*tlvh
= &OspfMplsTE
.router_addr
.header
;
705 if (ntohs (tlvh
->type
) != 0)
707 build_tlv_header (s
, tlvh
);
708 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
714 build_link_subtlv_link_type (struct stream
*s
, struct mpls_te_link
*lp
)
716 struct te_tlv_header
*tlvh
= &lp
->link_type
.header
;
717 if (ntohs (tlvh
->type
) != 0)
719 build_tlv_header (s
, tlvh
);
720 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
726 build_link_subtlv_link_id (struct stream
*s
, struct mpls_te_link
*lp
)
728 struct te_tlv_header
*tlvh
= &lp
->link_id
.header
;
729 if (ntohs (tlvh
->type
) != 0)
731 build_tlv_header (s
, tlvh
);
732 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
738 build_link_subtlv_lclif_ipaddr (struct stream
*s
, struct mpls_te_link
*lp
)
740 struct te_tlv_header
*tlvh
= (struct te_tlv_header
*) lp
->lclif_ipaddr
;
741 if (tlvh
!= NULL
&& ntohs (tlvh
->type
) != 0)
743 build_tlv_header (s
, tlvh
);
744 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
750 build_link_subtlv_rmtif_ipaddr (struct stream
*s
, struct mpls_te_link
*lp
)
752 struct te_tlv_header
*tlvh
= (struct te_tlv_header
*) lp
->rmtif_ipaddr
;
753 if (tlvh
!= NULL
&& ntohs (tlvh
->type
) != 0)
755 build_tlv_header (s
, tlvh
);
756 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
762 build_link_subtlv_te_metric (struct stream
*s
, struct mpls_te_link
*lp
)
764 struct te_tlv_header
*tlvh
= &lp
->te_metric
.header
;
765 if (ntohs (tlvh
->type
) != 0)
767 build_tlv_header (s
, tlvh
);
768 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
774 build_link_subtlv_max_bw (struct stream
*s
, struct mpls_te_link
*lp
)
776 struct te_tlv_header
*tlvh
= &lp
->max_bw
.header
;
777 if (ntohs (tlvh
->type
) != 0)
779 build_tlv_header (s
, tlvh
);
780 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
786 build_link_subtlv_max_rsv_bw (struct stream
*s
, struct mpls_te_link
*lp
)
788 struct te_tlv_header
*tlvh
= &lp
->max_rsv_bw
.header
;
789 if (ntohs (tlvh
->type
) != 0)
791 build_tlv_header (s
, tlvh
);
792 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
798 build_link_subtlv_unrsv_bw (struct stream
*s
, struct mpls_te_link
*lp
)
800 struct te_tlv_header
*tlvh
= &lp
->unrsv_bw
.header
;
801 if (ntohs (tlvh
->type
) != 0)
803 build_tlv_header (s
, tlvh
);
804 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
810 build_link_subtlv_rsc_clsclr (struct stream
*s
, struct mpls_te_link
*lp
)
812 struct te_tlv_header
*tlvh
= &lp
->rsc_clsclr
.header
;
813 if (ntohs (tlvh
->type
) != 0)
815 build_tlv_header (s
, tlvh
);
816 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
822 build_link_tlv (struct stream
*s
, struct mpls_te_link
*lp
)
824 set_linkparams_link_header (lp
);
825 build_tlv_header (s
, &lp
->link_header
.header
);
827 build_link_subtlv_link_type (s
, lp
);
828 build_link_subtlv_link_id (s
, lp
);
829 build_link_subtlv_lclif_ipaddr (s
, lp
);
830 build_link_subtlv_rmtif_ipaddr (s
, lp
);
831 build_link_subtlv_te_metric (s
, lp
);
832 build_link_subtlv_max_bw (s
, lp
);
833 build_link_subtlv_max_rsv_bw (s
, lp
);
834 build_link_subtlv_unrsv_bw (s
, lp
);
835 build_link_subtlv_rsc_clsclr (s
, lp
);
840 ospf_mpls_te_lsa_body_set (struct stream
*s
, struct mpls_te_link
*lp
)
843 * The router address TLV is type 1, and ...
844 * It must appear in exactly one
845 * Traffic Engineering LSA originated by a router.
847 build_router_tlv (s
);
850 * Only one Link TLV shall be carried in each LSA, allowing for fine
851 * granularity changes in topology.
853 build_link_tlv (s
, lp
);
857 /* Create new opaque-LSA. */
858 static struct ospf_lsa
*
859 ospf_mpls_te_lsa_new (struct ospf_area
*area
, struct mpls_te_link
*lp
)
862 struct lsa_header
*lsah
;
863 struct ospf_lsa
*new = NULL
;
864 u_char options
, lsa_type
;
865 struct in_addr lsa_id
;
869 /* Create a stream for LSA. */
870 if ((s
= stream_new (OSPF_MAX_LSA_SIZE
)) == NULL
)
872 zlog_warn ("ospf_mpls_te_lsa_new: stream_new() ?");
875 lsah
= (struct lsa_header
*) STREAM_DATA (s
);
877 options
= LSA_OPTIONS_GET (area
);
878 options
|= LSA_OPTIONS_NSSA_GET (area
);
879 options
|= OSPF_OPTION_O
; /* Don't forget this :-) */
881 lsa_type
= OSPF_OPAQUE_AREA_LSA
;
882 tmp
= SET_OPAQUE_LSID (OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA
, lp
->instance
);
883 lsa_id
.s_addr
= htonl (tmp
);
885 if (IS_DEBUG_OSPF (lsa
, LSA_GENERATE
))
886 zlog_debug ("LSA[Type%d:%s]: Create an Opaque-LSA/MPLS-TE instance", lsa_type
, inet_ntoa (lsa_id
));
888 /* Set opaque-LSA header fields. */
889 lsa_header_set (s
, options
, lsa_type
, lsa_id
, area
->ospf
->router_id
);
891 /* Set opaque-LSA body fields. */
892 ospf_mpls_te_lsa_body_set (s
, lp
);
895 length
= stream_get_endp (s
);
896 lsah
->length
= htons (length
);
898 /* Now, create an OSPF LSA instance. */
899 if ((new = ospf_lsa_new ()) == NULL
)
901 zlog_warn ("ospf_mpls_te_lsa_new: ospf_lsa_new() ?");
905 if ((new->data
= ospf_lsa_data_new (length
)) == NULL
)
907 zlog_warn ("ospf_mpls_te_lsa_new: ospf_lsa_data_new() ?");
908 ospf_lsa_unlock (&new);
915 SET_FLAG (new->flags
, OSPF_LSA_SELF
);
916 memcpy (new->data
, lsah
, length
);
924 ospf_mpls_te_lsa_originate1 (struct ospf_area
*area
, struct mpls_te_link
*lp
)
926 struct ospf_lsa
*new;
929 /* Create new Opaque-LSA/MPLS-TE instance. */
930 if ((new = ospf_mpls_te_lsa_new (area
, lp
)) == NULL
)
932 zlog_warn ("ospf_mpls_te_lsa_originate1: ospf_mpls_te_lsa_new() ?");
936 /* Install this LSA into LSDB. */
937 if (ospf_lsa_install (area
->ospf
, NULL
/*oi*/, new) == NULL
)
939 zlog_warn ("ospf_mpls_te_lsa_originate1: ospf_lsa_install() ?");
940 ospf_lsa_unlock (&new);
944 /* Now this linkparameter entry has associated LSA. */
945 lp
->flags
|= LPFLG_LSA_ENGAGED
;
947 /* Update new LSA origination count. */
948 area
->ospf
->lsa_originate_count
++;
950 /* Flood new LSA through area. */
951 ospf_flood_through_area (area
, NULL
/*nbr*/, new);
953 if (IS_DEBUG_OSPF (lsa
, LSA_GENERATE
))
955 char area_id
[INET_ADDRSTRLEN
];
956 strcpy (area_id
, inet_ntoa (area
->area_id
));
957 zlog_debug ("LSA[Type%d:%s]: Originate Opaque-LSA/MPLS-TE: Area(%s), Link(%s)", new->data
->type
, inet_ntoa (new->data
->id
), area_id
, lp
->ifp
->name
);
958 ospf_lsa_header_dump (new->data
);
967 ospf_mpls_te_lsa_originate (void *arg
)
969 struct ospf_area
*area
= (struct ospf_area
*) arg
;
970 struct listnode
*node
, *nnode
;
971 struct mpls_te_link
*lp
;
974 if (OspfMplsTE
.status
== disabled
)
976 zlog_info ("ospf_mpls_te_lsa_originate: MPLS-TE is disabled now.");
977 rc
= 0; /* This is not an error case. */
981 for (ALL_LIST_ELEMENTS (OspfMplsTE
.iflist
, node
, nnode
, lp
))
983 if (lp
->area
== NULL
)
985 if (! IPV4_ADDR_SAME (&lp
->area
->area_id
, &area
->area_id
))
988 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
990 if (lp
->flags
& LPFLG_LSA_FORCED_REFRESH
)
992 lp
->flags
&= ~LPFLG_LSA_FORCED_REFRESH
;
993 ospf_mpls_te_lsa_schedule (lp
, REFRESH_THIS_LSA
);
997 if (! is_mandated_params_set (lp
))
999 zlog_warn ("ospf_mpls_te_lsa_originate: Link(%s) lacks some mandated MPLS-TE parameters.", lp
->ifp
? lp
->ifp
->name
: "?");
1003 /* Ok, let's try to originate an LSA for this area and Link. */
1004 if (ospf_mpls_te_lsa_originate1 (area
, lp
) != 0)
1013 static struct ospf_lsa
*
1014 ospf_mpls_te_lsa_refresh (struct ospf_lsa
*lsa
)
1016 struct mpls_te_link
*lp
;
1017 struct ospf_area
*area
= lsa
->area
;
1018 struct ospf_lsa
*new = NULL
;
1020 if (OspfMplsTE
.status
== disabled
)
1023 * This LSA must have flushed before due to MPLS-TE status change.
1024 * It seems a slip among routers in the routing domain.
1026 zlog_info ("ospf_mpls_te_lsa_refresh: MPLS-TE is disabled now.");
1027 lsa
->data
->ls_age
= htons (OSPF_LSA_MAXAGE
); /* Flush it anyway. */
1030 /* At first, resolve lsa/lp relationship. */
1031 if ((lp
= lookup_linkparams_by_instance (lsa
)) == NULL
)
1033 zlog_warn ("ospf_mpls_te_lsa_refresh: Invalid parameter?");
1034 lsa
->data
->ls_age
= htons (OSPF_LSA_MAXAGE
); /* Flush it anyway. */
1037 /* If the lsa's age reached to MaxAge, start flushing procedure. */
1038 if (IS_LSA_MAXAGE (lsa
))
1041 lp
->flags
&= ~LPFLG_LSA_ENGAGED
;
1042 ospf_opaque_lsa_flush_schedule (lsa
);
1046 /* Create new Opaque-LSA/MPLS-TE instance. */
1047 if ((new = ospf_mpls_te_lsa_new (area
, lp
)) == NULL
)
1049 zlog_warn ("ospf_mpls_te_lsa_refresh: ospf_mpls_te_lsa_new() ?");
1052 new->data
->ls_seqnum
= lsa_seqnum_increment (lsa
);
1054 /* Install this LSA into LSDB. */
1055 /* Given "lsa" will be freed in the next function. */
1056 if (ospf_lsa_install (area
->ospf
, NULL
/*oi*/, new) == NULL
)
1058 zlog_warn ("ospf_mpls_te_lsa_refresh: ospf_lsa_install() ?");
1059 ospf_lsa_unlock (&new);
1063 /* Flood updated LSA through area. */
1064 ospf_flood_through_area (area
, NULL
/*nbr*/, new);
1066 /* Debug logging. */
1067 if (IS_DEBUG_OSPF (lsa
, LSA_GENERATE
))
1069 zlog_debug ("LSA[Type%d:%s]: Refresh Opaque-LSA/MPLS-TE",
1070 new->data
->type
, inet_ntoa (new->data
->id
));
1071 ospf_lsa_header_dump (new->data
);
1079 ospf_mpls_te_lsa_schedule (struct mpls_te_link
*lp
,
1080 enum sched_opcode opcode
)
1082 struct ospf_lsa lsa
;
1083 struct lsa_header lsah
;
1086 memset (&lsa
, 0, sizeof (lsa
));
1087 memset (&lsah
, 0, sizeof (lsah
));
1089 lsa
.area
= lp
->area
;
1091 lsah
.type
= OSPF_OPAQUE_AREA_LSA
;
1092 tmp
= SET_OPAQUE_LSID (OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA
, lp
->instance
);
1093 lsah
.id
.s_addr
= htonl (tmp
);
1097 case REORIGINATE_PER_AREA
:
1098 ospf_opaque_lsa_reoriginate_schedule ((void *) lp
->area
,
1099 OSPF_OPAQUE_AREA_LSA
, OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA
);
1101 case REFRESH_THIS_LSA
:
1102 ospf_opaque_lsa_refresh_schedule (&lsa
);
1104 case FLUSH_THIS_LSA
:
1105 lp
->flags
&= ~LPFLG_LSA_ENGAGED
;
1106 ospf_opaque_lsa_flush_schedule (&lsa
);
1109 zlog_warn ("ospf_mpls_te_lsa_schedule: Unknown opcode (%u)", opcode
);
1116 /*------------------------------------------------------------------------*
1117 * Followings are vty session control functions.
1118 *------------------------------------------------------------------------*/
1121 show_vty_router_addr (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1123 struct te_tlv_router_addr
*top
= (struct te_tlv_router_addr
*) tlvh
;
1126 vty_out (vty
, " Router-Address: %s%s", inet_ntoa (top
->value
), VTY_NEWLINE
);
1128 zlog_debug (" Router-Address: %s", inet_ntoa (top
->value
));
1130 return TLV_SIZE (tlvh
);
1134 show_vty_link_header (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1136 struct te_tlv_link
*top
= (struct te_tlv_link
*) tlvh
;
1139 vty_out (vty
, " Link: %u octets of data%s", ntohs (top
->header
.length
), VTY_NEWLINE
);
1141 zlog_debug (" Link: %u octets of data", ntohs (top
->header
.length
));
1143 return TLV_HDR_SIZE
; /* Here is special, not "TLV_SIZE". */
1147 show_vty_link_subtlv_link_type (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1149 struct te_link_subtlv_link_type
*top
;
1150 const char *cp
= "Unknown";
1152 top
= (struct te_link_subtlv_link_type
*) tlvh
;
1153 switch (top
->link_type
.value
)
1155 case LINK_TYPE_SUBTLV_VALUE_PTP
:
1156 cp
= "Point-to-point";
1158 case LINK_TYPE_SUBTLV_VALUE_MA
:
1166 vty_out (vty
, " Link-Type: %s (%u)%s", cp
, top
->link_type
.value
, VTY_NEWLINE
);
1168 zlog_debug (" Link-Type: %s (%u)", cp
, top
->link_type
.value
);
1170 return TLV_SIZE (tlvh
);
1174 show_vty_link_subtlv_link_id (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1176 struct te_link_subtlv_link_id
*top
;
1178 top
= (struct te_link_subtlv_link_id
*) tlvh
;
1180 vty_out (vty
, " Link-ID: %s%s", inet_ntoa (top
->value
), VTY_NEWLINE
);
1182 zlog_debug (" Link-ID: %s", inet_ntoa (top
->value
));
1184 return TLV_SIZE (tlvh
);
1188 show_vty_link_subtlv_lclif_ipaddr (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1190 struct te_link_subtlv_lclif_ipaddr
*top
;
1193 top
= (struct te_link_subtlv_lclif_ipaddr
*) tlvh
;
1194 n
= ntohs (tlvh
->length
) / sizeof (top
->value
[0]);
1197 vty_out (vty
, " Local Interface IP Address(es): %d%s", n
, VTY_NEWLINE
);
1199 zlog_debug (" Local Interface IP Address(es): %d", n
);
1201 for (i
= 0; i
< n
; i
++)
1204 vty_out (vty
, " #%d: %s%s", i
, inet_ntoa (top
->value
[i
]), VTY_NEWLINE
);
1206 zlog_debug (" #%d: %s", i
, inet_ntoa (top
->value
[i
]));
1208 return TLV_SIZE (tlvh
);
1212 show_vty_link_subtlv_rmtif_ipaddr (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1214 struct te_link_subtlv_rmtif_ipaddr
*top
;
1217 top
= (struct te_link_subtlv_rmtif_ipaddr
*) tlvh
;
1218 n
= ntohs (tlvh
->length
) / sizeof (top
->value
[0]);
1220 vty_out (vty
, " Remote Interface IP Address(es): %d%s", n
, VTY_NEWLINE
);
1222 zlog_debug (" Remote Interface IP Address(es): %d", n
);
1224 for (i
= 0; i
< n
; i
++)
1227 vty_out (vty
, " #%d: %s%s", i
, inet_ntoa (top
->value
[i
]), VTY_NEWLINE
);
1229 zlog_debug (" #%d: %s", i
, inet_ntoa (top
->value
[i
]));
1231 return TLV_SIZE (tlvh
);
1235 show_vty_link_subtlv_te_metric (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1237 struct te_link_subtlv_te_metric
*top
;
1239 top
= (struct te_link_subtlv_te_metric
*) tlvh
;
1241 vty_out (vty
, " Traffic Engineering Metric: %u%s", (u_int32_t
) ntohl (top
->value
), VTY_NEWLINE
);
1243 zlog_debug (" Traffic Engineering Metric: %u", (u_int32_t
) ntohl (top
->value
));
1245 return TLV_SIZE (tlvh
);
1249 show_vty_link_subtlv_max_bw (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1251 struct te_link_subtlv_max_bw
*top
;
1254 top
= (struct te_link_subtlv_max_bw
*) tlvh
;
1255 ntohf (&top
->value
, &fval
);
1258 vty_out (vty
, " Maximum Bandwidth: %g (Bytes/sec)%s", fval
, VTY_NEWLINE
);
1260 zlog_debug (" Maximum Bandwidth: %g (Bytes/sec)", fval
);
1262 return TLV_SIZE (tlvh
);
1266 show_vty_link_subtlv_max_rsv_bw (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1268 struct te_link_subtlv_max_rsv_bw
*top
;
1271 top
= (struct te_link_subtlv_max_rsv_bw
*) tlvh
;
1272 ntohf (&top
->value
, &fval
);
1275 vty_out (vty
, " Maximum Reservable Bandwidth: %g (Bytes/sec)%s", fval
, VTY_NEWLINE
);
1277 zlog_debug (" Maximum Reservable Bandwidth: %g (Bytes/sec)", fval
);
1279 return TLV_SIZE (tlvh
);
1283 show_vty_link_subtlv_unrsv_bw (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1285 struct te_link_subtlv_unrsv_bw
*top
;
1289 top
= (struct te_link_subtlv_unrsv_bw
*) tlvh
;
1290 for (i
= 0; i
< 8; i
++)
1292 ntohf (&top
->value
[i
], &fval
);
1294 vty_out (vty
, " Unreserved Bandwidth (pri %d): %g (Bytes/sec)%s", i
, fval
, VTY_NEWLINE
);
1296 zlog_debug (" Unreserved Bandwidth (pri %d): %g (Bytes/sec)", i
, fval
);
1299 return TLV_SIZE (tlvh
);
1303 show_vty_link_subtlv_rsc_clsclr (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1305 struct te_link_subtlv_rsc_clsclr
*top
;
1307 top
= (struct te_link_subtlv_rsc_clsclr
*) tlvh
;
1309 vty_out (vty
, " Resource class/color: 0x%x%s", (u_int32_t
) ntohl (top
->value
), VTY_NEWLINE
);
1311 zlog_debug (" Resource Class/Color: 0x%x", (u_int32_t
) ntohl (top
->value
));
1313 return TLV_SIZE (tlvh
);
1317 show_vty_unknown_tlv (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1320 vty_out (vty
, " Unknown TLV: [type(0x%x), length(0x%x)]%s", ntohs (tlvh
->type
), ntohs (tlvh
->length
), VTY_NEWLINE
);
1322 zlog_debug (" Unknown TLV: [type(0x%x), length(0x%x)]", ntohs (tlvh
->type
), ntohs (tlvh
->length
));
1324 return TLV_SIZE (tlvh
);
1328 ospf_mpls_te_show_link_subtlv (struct vty
*vty
, struct te_tlv_header
*tlvh0
,
1329 u_int16_t subtotal
, u_int16_t total
)
1331 struct te_tlv_header
*tlvh
, *next
;
1332 u_int16_t sum
= subtotal
;
1334 for (tlvh
= tlvh0
; sum
< total
; tlvh
= (next
? next
: TLV_HDR_NEXT (tlvh
)))
1337 switch (ntohs (tlvh
->type
))
1339 case TE_LINK_SUBTLV_LINK_TYPE
:
1340 sum
+= show_vty_link_subtlv_link_type (vty
, tlvh
);
1342 case TE_LINK_SUBTLV_LINK_ID
:
1343 sum
+= show_vty_link_subtlv_link_id (vty
, tlvh
);
1345 case TE_LINK_SUBTLV_LCLIF_IPADDR
:
1346 sum
+= show_vty_link_subtlv_lclif_ipaddr (vty
, tlvh
);
1348 case TE_LINK_SUBTLV_RMTIF_IPADDR
:
1349 sum
+= show_vty_link_subtlv_rmtif_ipaddr (vty
, tlvh
);
1351 case TE_LINK_SUBTLV_TE_METRIC
:
1352 sum
+= show_vty_link_subtlv_te_metric (vty
, tlvh
);
1354 case TE_LINK_SUBTLV_MAX_BW
:
1355 sum
+= show_vty_link_subtlv_max_bw (vty
, tlvh
);
1357 case TE_LINK_SUBTLV_MAX_RSV_BW
:
1358 sum
+= show_vty_link_subtlv_max_rsv_bw (vty
, tlvh
);
1360 case TE_LINK_SUBTLV_UNRSV_BW
:
1361 sum
+= show_vty_link_subtlv_unrsv_bw (vty
, tlvh
);
1363 case TE_LINK_SUBTLV_RSC_CLSCLR
:
1364 sum
+= show_vty_link_subtlv_rsc_clsclr (vty
, tlvh
);
1367 sum
+= show_vty_unknown_tlv (vty
, tlvh
);
1375 ospf_mpls_te_show_info (struct vty
*vty
, struct ospf_lsa
*lsa
)
1377 struct lsa_header
*lsah
= (struct lsa_header
*) lsa
->data
;
1378 struct te_tlv_header
*tlvh
, *next
;
1379 u_int16_t sum
, total
;
1380 u_int16_t (* subfunc
)(struct vty
*vty
, struct te_tlv_header
*tlvh
,
1381 u_int16_t subtotal
, u_int16_t total
) = NULL
;
1384 total
= ntohs (lsah
->length
) - OSPF_LSA_HEADER_SIZE
;
1386 for (tlvh
= TLV_HDR_TOP (lsah
); sum
< total
;
1387 tlvh
= (next
? next
: TLV_HDR_NEXT (tlvh
)))
1389 if (subfunc
!= NULL
)
1391 sum
= (* subfunc
)(vty
, tlvh
, sum
, total
);
1392 next
= (struct te_tlv_header
*)((char *) tlvh
+ sum
);
1398 switch (ntohs (tlvh
->type
))
1400 case TE_TLV_ROUTER_ADDR
:
1401 sum
+= show_vty_router_addr (vty
, tlvh
);
1404 sum
+= show_vty_link_header (vty
, tlvh
);
1405 subfunc
= ospf_mpls_te_show_link_subtlv
;
1409 sum
+= show_vty_unknown_tlv (vty
, tlvh
);
1417 ospf_mpls_te_config_write_router (struct vty
*vty
)
1419 if (OspfMplsTE
.status
== enabled
)
1421 vty_out (vty
, " mpls-te%s", VTY_NEWLINE
);
1422 vty_out (vty
, " mpls-te router-address %s%s",
1423 inet_ntoa (OspfMplsTE
.router_addr
.value
), VTY_NEWLINE
);
1429 ospf_mpls_te_config_write_if (struct vty
*vty
, struct interface
*ifp
)
1431 struct mpls_te_link
*lp
;
1433 if ((OspfMplsTE
.status
== enabled
)
1434 && (! if_is_loopback (ifp
) && if_is_up (ifp
) && ospf_oi_count (ifp
) > 0)
1435 && ((lp
= lookup_linkparams_by_ifp (ifp
)) != NULL
))
1440 vty_out (vty
, " mpls-te link metric %u%s",
1441 (u_int32_t
) ntohl (lp
->te_metric
.value
), VTY_NEWLINE
);
1443 ntohf (&lp
->max_bw
.value
, &fval
);
1444 if (fval
>= MPLS_TE_MINIMUM_BANDWIDTH
)
1445 vty_out (vty
, " mpls-te link max-bw %g%s", fval
, VTY_NEWLINE
);
1447 ntohf (&lp
->max_rsv_bw
.value
, &fval
);
1448 if (fval
>= MPLS_TE_MINIMUM_BANDWIDTH
)
1449 vty_out (vty
, " mpls-te link max-rsv-bw %g%s", fval
, VTY_NEWLINE
);
1451 for (i
= 0; i
< 8; i
++)
1453 ntohf (&lp
->unrsv_bw
.value
[i
], &fval
);
1454 if (fval
>= MPLS_TE_MINIMUM_BANDWIDTH
)
1455 vty_out (vty
, " mpls-te link unrsv-bw %d %g%s",
1456 i
, fval
, VTY_NEWLINE
);
1459 vty_out (vty
, " mpls-te link rsc-clsclr 0x%x%s",
1460 (u_int32_t
) ntohl (lp
->rsc_clsclr
.value
), VTY_NEWLINE
);
1465 /*------------------------------------------------------------------------*
1466 * Followings are vty command functions.
1467 *------------------------------------------------------------------------*/
1472 "Configure MPLS-TE parameters\n"
1473 "Enable the MPLS-TE functionality\n")
1475 struct listnode
*node
, *nnode
;
1476 struct mpls_te_link
*lp
;
1477 struct ospf
*ospf
= vty
->index
;
1482 if (OspfMplsTE
.status
== enabled
)
1485 if (IS_DEBUG_OSPF_EVENT
)
1486 zlog_debug ("MPLS-TE: OFF -> ON");
1488 OspfMplsTE
.status
= enabled
;
1491 * Following code is intended to handle two cases;
1493 * 1) MPLS-TE was disabled at startup time, but now become enabled.
1494 * 2) MPLS-TE was once enabled then disabled, and now enabled again.
1496 for (ALL_LIST_ELEMENTS (OspfMplsTE
.iflist
, node
, nnode
, lp
))
1497 initialize_linkparams (lp
);
1499 ospf_mpls_te_foreach_area (ospf_mpls_te_lsa_schedule
, REORIGINATE_PER_AREA
);
1507 "Configure MPLS-TE parameters\n"
1508 "Enable the MPLS-TE functionality\n")
1514 "Configure MPLS-TE parameters\n"
1515 "Disable the MPLS-TE functionality\n")
1517 struct listnode
*node
, *nnode
;
1518 struct mpls_te_link
*lp
;
1519 struct ospf
*ospf
= vty
->index
;
1524 if (OspfMplsTE
.status
== disabled
)
1527 if (IS_DEBUG_OSPF_EVENT
)
1528 zlog_debug ("MPLS-TE: ON -> OFF");
1530 OspfMplsTE
.status
= disabled
;
1532 for (ALL_LIST_ELEMENTS (OspfMplsTE
.iflist
, node
, nnode
, lp
))
1533 if (lp
->area
!= NULL
)
1534 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
1535 ospf_mpls_te_lsa_schedule (lp
, FLUSH_THIS_LSA
);
1544 "Configure MPLS-TE parameters\n"
1545 "Disable the MPLS-TE functionality\n")
1547 DEFUN (mpls_te_router_addr
,
1548 mpls_te_router_addr_cmd
,
1549 "mpls-te router-address A.B.C.D",
1550 "MPLS-TE specific commands\n"
1551 "Stable IP address of the advertising router\n"
1552 "MPLS-TE router address in IPv4 address format\n")
1554 struct te_tlv_router_addr
*ra
= &OspfMplsTE
.router_addr
;
1555 struct in_addr value
;
1556 struct ospf
*ospf
= vty
->index
;
1561 if (! inet_aton (argv
[0], &value
))
1563 vty_out (vty
, "Please specify Router-Addr by A.B.C.D%s", VTY_NEWLINE
);
1567 if (ntohs (ra
->header
.type
) == 0
1568 || ntohl (ra
->value
.s_addr
) != ntohl (value
.s_addr
))
1570 struct listnode
*node
, *nnode
;
1571 struct mpls_te_link
*lp
;
1572 int need_to_reoriginate
= 0;
1574 set_mpls_te_router_addr (value
);
1576 if (OspfMplsTE
.status
== disabled
)
1579 for (ALL_LIST_ELEMENTS (OspfMplsTE
.iflist
, node
, nnode
, lp
))
1581 if (lp
->area
== NULL
)
1584 if ((lp
->flags
& LPFLG_LSA_ENGAGED
) == 0)
1586 need_to_reoriginate
= 1;
1591 for (ALL_LIST_ELEMENTS (OspfMplsTE
.iflist
, node
, nnode
, lp
))
1593 if (lp
->area
== NULL
)
1596 if (need_to_reoriginate
)
1597 lp
->flags
|= LPFLG_LSA_FORCED_REFRESH
;
1599 ospf_mpls_te_lsa_schedule (lp
, REFRESH_THIS_LSA
);
1602 if (need_to_reoriginate
)
1603 ospf_mpls_te_foreach_area (
1604 ospf_mpls_te_lsa_schedule
, REORIGINATE_PER_AREA
);
1610 DEFUN (mpls_te_link_metric
,
1611 mpls_te_link_metric_cmd
,
1612 "mpls-te link metric <0-4294967295>",
1613 "MPLS-TE specific commands\n"
1614 "Configure MPLS-TE link parameters\n"
1615 "Link metric for MPLS-TE purpose\n"
1618 struct interface
*ifp
= (struct interface
*) vty
->index
;
1619 struct mpls_te_link
*lp
;
1622 if ((lp
= lookup_linkparams_by_ifp (ifp
)) == NULL
)
1624 vty_out (vty
, "mpls_te_link_metric: Something wrong!%s", VTY_NEWLINE
);
1628 value
= strtoul (argv
[0], NULL
, 10);
1630 if (ntohs (lp
->te_metric
.header
.type
) == 0
1631 || ntohl (lp
->te_metric
.value
) != value
)
1633 set_linkparams_te_metric (lp
, value
);
1635 if (OspfMplsTE
.status
== enabled
)
1636 if (lp
->area
!= NULL
)
1638 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
1639 ospf_mpls_te_lsa_schedule (lp
, REFRESH_THIS_LSA
);
1641 ospf_mpls_te_lsa_schedule (lp
, REORIGINATE_PER_AREA
);
1647 DEFUN (mpls_te_link_maxbw
,
1648 mpls_te_link_maxbw_cmd
,
1649 "mpls-te link max-bw BANDWIDTH",
1650 "MPLS-TE specific commands\n"
1651 "Configure MPLS-TE link parameters\n"
1652 "Maximum bandwidth that can be used\n"
1653 "Bytes/second (IEEE floating point format)\n")
1655 struct interface
*ifp
= (struct interface
*) vty
->index
;
1656 struct mpls_te_link
*lp
;
1659 if ((lp
= lookup_linkparams_by_ifp (ifp
)) == NULL
)
1661 vty_out (vty
, "mpls_te_link_maxbw: Something wrong!%s", VTY_NEWLINE
);
1665 ntohf (&lp
->max_bw
.value
, &f1
);
1666 if (sscanf (argv
[0], "%g", &f2
) != 1)
1668 vty_out (vty
, "mpls_te_link_maxbw: fscanf: %s%s", safe_strerror (errno
), VTY_NEWLINE
);
1672 if (ntohs (lp
->max_bw
.header
.type
) == 0
1675 set_linkparams_max_bw (lp
, &f2
);
1677 if (OspfMplsTE
.status
== enabled
)
1678 if (lp
->area
!= NULL
)
1680 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
1681 ospf_mpls_te_lsa_schedule (lp
, REFRESH_THIS_LSA
);
1683 ospf_mpls_te_lsa_schedule (lp
, REORIGINATE_PER_AREA
);
1689 DEFUN (mpls_te_link_max_rsv_bw
,
1690 mpls_te_link_max_rsv_bw_cmd
,
1691 "mpls-te link max-rsv-bw BANDWIDTH",
1692 "MPLS-TE specific commands\n"
1693 "Configure MPLS-TE link parameters\n"
1694 "Maximum bandwidth that may be reserved\n"
1695 "Bytes/second (IEEE floating point format)\n")
1697 struct interface
*ifp
= (struct interface
*) vty
->index
;
1698 struct mpls_te_link
*lp
;
1701 if ((lp
= lookup_linkparams_by_ifp (ifp
)) == NULL
)
1703 vty_out (vty
, "mpls_te_link_max_rsv_bw: Something wrong!%s", VTY_NEWLINE
);
1707 ntohf (&lp
->max_rsv_bw
.value
, &f1
);
1708 if (sscanf (argv
[0], "%g", &f2
) != 1)
1710 vty_out (vty
, "mpls_te_link_max_rsv_bw: fscanf: %s%s", safe_strerror (errno
), VTY_NEWLINE
);
1714 if (ntohs (lp
->max_rsv_bw
.header
.type
) == 0
1717 set_linkparams_max_rsv_bw (lp
, &f2
);
1719 if (OspfMplsTE
.status
== enabled
)
1720 if (lp
->area
!= NULL
)
1722 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
1723 ospf_mpls_te_lsa_schedule (lp
, REFRESH_THIS_LSA
);
1725 ospf_mpls_te_lsa_schedule (lp
, REORIGINATE_PER_AREA
);
1731 DEFUN (mpls_te_link_unrsv_bw
,
1732 mpls_te_link_unrsv_bw_cmd
,
1733 "mpls-te link unrsv-bw <0-7> BANDWIDTH",
1734 "MPLS-TE specific commands\n"
1735 "Configure MPLS-TE link parameters\n"
1736 "Unreserved bandwidth at each priority level\n"
1738 "Bytes/second (IEEE floating point format)\n")
1740 struct interface
*ifp
= (struct interface
*) vty
->index
;
1741 struct mpls_te_link
*lp
;
1745 if ((lp
= lookup_linkparams_by_ifp (ifp
)) == NULL
)
1747 vty_out (vty
, "mpls_te_link_unrsv_bw: Something wrong!%s", VTY_NEWLINE
);
1751 /* We don't have to consider about range check here. */
1752 if (sscanf (argv
[0], "%d", &priority
) != 1)
1754 vty_out (vty
, "mpls_te_link_unrsv_bw: fscanf: %s%s", safe_strerror (errno
), VTY_NEWLINE
);
1758 ntohf (&lp
->unrsv_bw
.value
[priority
], &f1
);
1759 if (sscanf (argv
[1], "%g", &f2
) != 1)
1761 vty_out (vty
, "mpls_te_link_unrsv_bw: fscanf: %s%s", safe_strerror (errno
), VTY_NEWLINE
);
1765 if (ntohs (lp
->unrsv_bw
.header
.type
) == 0
1768 set_linkparams_unrsv_bw (lp
, priority
, &f2
);
1770 if (OspfMplsTE
.status
== enabled
)
1771 if (lp
->area
!= NULL
)
1773 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
1774 ospf_mpls_te_lsa_schedule (lp
, REFRESH_THIS_LSA
);
1776 ospf_mpls_te_lsa_schedule (lp
, REORIGINATE_PER_AREA
);
1782 DEFUN (mpls_te_link_rsc_clsclr
,
1783 mpls_te_link_rsc_clsclr_cmd
,
1784 "mpls-te link rsc-clsclr BITPATTERN",
1785 "MPLS-TE specific commands\n"
1786 "Configure MPLS-TE link parameters\n"
1787 "Administrative group membership\n"
1788 "32-bit Hexadecimal value (ex. 0xa1)\n")
1790 struct interface
*ifp
= (struct interface
*) vty
->index
;
1791 struct mpls_te_link
*lp
;
1792 unsigned long value
;
1794 if ((lp
= lookup_linkparams_by_ifp (ifp
)) == NULL
)
1796 vty_out (vty
, "mpls_te_link_rsc_clsclr: Something wrong!%s", VTY_NEWLINE
);
1800 if (sscanf (argv
[0], "0x%lx", &value
) != 1)
1802 vty_out (vty
, "mpls_te_link_rsc_clsclr: fscanf: %s%s", safe_strerror (errno
), VTY_NEWLINE
);
1806 if (ntohs (lp
->rsc_clsclr
.header
.type
) == 0
1807 || ntohl (lp
->rsc_clsclr
.value
) != value
)
1809 set_linkparams_rsc_clsclr (lp
, value
);
1811 if (OspfMplsTE
.status
== enabled
)
1812 if (lp
->area
!= NULL
)
1814 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
1815 ospf_mpls_te_lsa_schedule (lp
, REFRESH_THIS_LSA
);
1817 ospf_mpls_te_lsa_schedule (lp
, REORIGINATE_PER_AREA
);
1823 DEFUN (show_mpls_te_router
,
1824 show_mpls_te_router_cmd
,
1825 "show mpls-te router",
1827 "MPLS-TE information\n"
1828 "Router information\n")
1830 if (OspfMplsTE
.status
== enabled
)
1832 vty_out (vty
, "--- MPLS-TE router parameters ---%s",
1835 if (ntohs (OspfMplsTE
.router_addr
.header
.type
) != 0)
1836 show_vty_router_addr (vty
, &OspfMplsTE
.router_addr
.header
);
1837 else if (vty
!= NULL
)
1838 vty_out (vty
, " N/A%s", VTY_NEWLINE
);
1844 show_mpls_te_link_sub (struct vty
*vty
, struct interface
*ifp
)
1846 struct mpls_te_link
*lp
;
1847 struct te_tlv_header
*tlvh
;
1849 if ((OspfMplsTE
.status
== enabled
)
1850 && (! if_is_loopback (ifp
) && if_is_up (ifp
) && ospf_oi_count (ifp
) > 0)
1851 && ((lp
= lookup_linkparams_by_ifp (ifp
)) != NULL
))
1853 vty_out (vty
, "-- MPLS-TE link parameters for %s --%s",
1854 ifp
->name
, VTY_NEWLINE
);
1856 show_vty_link_subtlv_link_type (vty
, &lp
->link_type
.header
);
1857 show_vty_link_subtlv_link_id (vty
, &lp
->link_id
.header
);
1859 if ((tlvh
= (struct te_tlv_header
*) lp
->lclif_ipaddr
) != NULL
)
1860 show_vty_link_subtlv_lclif_ipaddr (vty
, tlvh
);
1861 if ((tlvh
= (struct te_tlv_header
*) lp
->rmtif_ipaddr
) != NULL
)
1862 show_vty_link_subtlv_rmtif_ipaddr (vty
, tlvh
);
1864 show_vty_link_subtlv_te_metric (vty
, &lp
->te_metric
.header
);
1866 show_vty_link_subtlv_max_bw (vty
, &lp
->max_bw
.header
);
1867 show_vty_link_subtlv_max_rsv_bw (vty
, &lp
->max_rsv_bw
.header
);
1868 show_vty_link_subtlv_unrsv_bw (vty
, &lp
->unrsv_bw
.header
);
1869 show_vty_link_subtlv_rsc_clsclr (vty
, &lp
->rsc_clsclr
.header
);
1873 vty_out (vty
, " %s: MPLS-TE is disabled on this interface%s",
1874 ifp
->name
, VTY_NEWLINE
);
1880 DEFUN (show_mpls_te_link
,
1881 show_mpls_te_link_cmd
,
1882 "show mpls-te interface [INTERFACE]",
1884 "MPLS-TE information\n"
1885 "Interface information\n"
1888 struct interface
*ifp
;
1889 struct listnode
*node
, *nnode
;
1891 /* Show All Interfaces. */
1894 for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT
), node
, nnode
, ifp
))
1895 show_mpls_te_link_sub (vty
, ifp
);
1897 /* Interface name is specified. */
1900 if ((ifp
= if_lookup_by_name (argv
[0])) == NULL
)
1901 vty_out (vty
, "No such interface name%s", VTY_NEWLINE
);
1903 show_mpls_te_link_sub (vty
, ifp
);
1910 ospf_mpls_te_register_vty (void)
1912 install_element (VIEW_NODE
, &show_mpls_te_router_cmd
);
1913 install_element (VIEW_NODE
, &show_mpls_te_link_cmd
);
1914 install_element (ENABLE_NODE
, &show_mpls_te_router_cmd
);
1915 install_element (ENABLE_NODE
, &show_mpls_te_link_cmd
);
1917 install_element (OSPF_NODE
, &mpls_te_cmd
);
1918 install_element (OSPF_NODE
, &no_mpls_te_cmd
);
1919 install_element (OSPF_NODE
, &no_mpls_te_val_cmd
);
1920 install_element (OSPF_NODE
, &mpls_te_on_cmd
);
1921 install_element (OSPF_NODE
, &mpls_te_router_addr_cmd
);
1923 install_element (INTERFACE_NODE
, &mpls_te_link_metric_cmd
);
1924 install_element (INTERFACE_NODE
, &mpls_te_link_maxbw_cmd
);
1925 install_element (INTERFACE_NODE
, &mpls_te_link_max_rsv_bw_cmd
);
1926 install_element (INTERFACE_NODE
, &mpls_te_link_unrsv_bw_cmd
);
1927 install_element (INTERFACE_NODE
, &mpls_te_link_rsc_clsclr_cmd
);
1932 #endif /* HAVE_OSPF_TE */