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 */
45 #include "sockunion.h" /* for inet_aton() */
47 #include "ospfd/ospfd.h"
48 #include "ospfd/ospf_interface.h"
49 #include "ospfd/ospf_ism.h"
50 #include "ospfd/ospf_asbr.h"
51 #include "ospfd/ospf_lsa.h"
52 #include "ospfd/ospf_lsdb.h"
53 #include "ospfd/ospf_neighbor.h"
54 #include "ospfd/ospf_nsm.h"
55 #include "ospfd/ospf_flood.h"
56 #include "ospfd/ospf_packet.h"
57 #include "ospfd/ospf_spf.h"
58 #include "ospfd/ospf_dump.h"
59 #include "ospfd/ospf_route.h"
60 #include "ospfd/ospf_ase.h"
61 #include "ospfd/ospf_zebra.h"
62 #include "ospfd/ospf_te.h"
64 /* Following structure are internal use only. */
67 enum { disabled
, enabled
} status
;
69 /* List elements are zebra-interfaces (ifp), not ospf-interfaces (oi). */
72 /* Store Router-TLV in network byte order. */
73 struct te_tlv_router_addr router_addr
;
79 * According to MPLS-TE (draft) specification, 24-bit Opaque-ID field
80 * is subdivided into 8-bit "unused" field and 16-bit "instance" field.
81 * In this implementation, each Link-TLV has its own instance.
85 /* Reference pointer to a Zebra-interface. */
86 struct interface
*ifp
;
88 /* Area info in which this MPLS-TE link belongs to. */
89 struct ospf_area
*area
;
91 /* Flags to manage this link parameters. */
93 #define LPFLG_LOOKUP_DONE 0x1
94 #define LPFLG_LSA_ENGAGED 0x2
95 #define LPFLG_LSA_FORCED_REFRESH 0x4
97 /* Store Link-TLV in network byte order. */
98 struct te_tlv_link link_header
;
99 struct te_link_subtlv_link_type link_type
;
100 struct te_link_subtlv_link_id link_id
;
101 struct te_link_subtlv_lclif_ipaddr
*lclif_ipaddr
;
102 struct te_link_subtlv_rmtif_ipaddr
*rmtif_ipaddr
;
103 struct te_link_subtlv_te_metric te_metric
;
104 struct te_link_subtlv_max_bw max_bw
;
105 struct te_link_subtlv_max_rsv_bw max_rsv_bw
;
106 struct te_link_subtlv_unrsv_bw unrsv_bw
;
107 struct te_link_subtlv_rsc_clsclr rsc_clsclr
;
111 * Global variable to manage Opaque-LSA/MPLS-TE on this node.
112 * Note that all parameter values are stored in network byte order.
114 static struct ospf_mpls_te OspfMplsTE
;
117 OI_ANY
, OI_DOWN
, OI_UP
121 REORIGINATE_PER_AREA
, REFRESH_THIS_LSA
, FLUSH_THIS_LSA
124 /*------------------------------------------------------------------------*
125 * Followings are initialize/terminate functions for MPLS-TE handling.
126 *------------------------------------------------------------------------*/
128 static int ospf_mpls_te_new_if (struct interface
*ifp
);
129 static int ospf_mpls_te_del_if (struct interface
*ifp
);
130 static void ospf_mpls_te_ism_change (struct ospf_interface
*oi
, int old_status
);
131 static void ospf_mpls_te_nsm_change (struct ospf_neighbor
*nbr
, int old_status
);
132 static void ospf_mpls_te_config_write_router (struct vty
*vty
);
133 static void ospf_mpls_te_config_write_if (struct vty
*vty
, struct interface
*ifp
);
134 static void ospf_mpls_te_show_info (struct vty
*vty
, struct ospf_lsa
*lsa
);
135 static int ospf_mpls_te_lsa_originate (void *arg
);
136 static void ospf_mpls_te_lsa_refresh (struct ospf_lsa
*lsa
);
137 static void ospf_mpls_te_lsa_schedule (struct mpls_te_link
*lp
, enum sched_opcode
);
139 static void del_mpls_te_link (void *val
);
140 static void ospf_mpls_te_register_vty (void);
143 ospf_mpls_te_init (void)
147 rc
= ospf_register_opaque_functab (
148 OSPF_OPAQUE_AREA_LSA
,
149 OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA
,
152 ospf_mpls_te_ism_change
,
153 ospf_mpls_te_nsm_change
,
154 ospf_mpls_te_config_write_router
,
155 ospf_mpls_te_config_write_if
,
156 NULL
,/* ospf_mpls_te_config_write_debug */
157 ospf_mpls_te_show_info
,
158 ospf_mpls_te_lsa_originate
,
159 ospf_mpls_te_lsa_refresh
,
160 NULL
,/* ospf_mpls_te_new_lsa_hook */
161 NULL
/* ospf_mpls_te_del_lsa_hook */);
164 zlog_warn ("ospf_mpls_te_init: Failed to register functions");
168 memset (&OspfMplsTE
, 0, sizeof (struct ospf_mpls_te
));
169 OspfMplsTE
.status
= disabled
;
170 OspfMplsTE
.iflist
= list_new ();
171 OspfMplsTE
.iflist
->del
= del_mpls_te_link
;
173 ospf_mpls_te_register_vty ();
180 ospf_mpls_te_term (void)
182 list_delete (OspfMplsTE
.iflist
);
184 OspfMplsTE
.iflist
= NULL
;
185 OspfMplsTE
.status
= disabled
;
187 ospf_delete_opaque_functab (OSPF_OPAQUE_AREA_LSA
,
188 OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA
);
192 /*------------------------------------------------------------------------*
193 * Followings are control functions for MPLS-TE parameters management.
194 *------------------------------------------------------------------------*/
197 del_mpls_te_link (void *val
)
199 XFREE (MTYPE_OSPF_MPLS_TE_LINKPARAMS
, val
);
204 get_mpls_te_instance_value (void)
206 static u_int32_t seqno
= 0;
208 if (LEGAL_TE_INSTANCE_RANGE (seqno
+ 1))
211 seqno
= 1; /* Avoid zero. */
216 static struct ospf_interface
*
217 lookup_oi_by_ifp (struct interface
*ifp
,
218 struct ospf_area
*area
, enum oifstate oifstate
)
220 struct ospf_interface
*oi
= NULL
;
221 struct route_node
*rn
;
223 for (rn
= route_top (IF_OIFS (ifp
)); rn
; rn
= route_next (rn
))
225 if ((oi
= rn
->info
) == NULL
)
233 if (ospf_if_is_enable (oi
))
237 if (! ospf_if_is_enable (oi
))
241 zlog_warn ("lookup_oi_by_ifp: Unknown oifstate: %x", oifstate
);
245 if (area
== NULL
|| oi
->area
== area
)
252 static struct mpls_te_link
*
253 lookup_linkparams_by_ifp (struct interface
*ifp
)
255 struct listnode
*node
, *nnode
;
256 struct mpls_te_link
*lp
;
258 for (ALL_LIST_ELEMENTS (OspfMplsTE
.iflist
, node
, nnode
, lp
))
265 static struct mpls_te_link
*
266 lookup_linkparams_by_instance (struct ospf_lsa
*lsa
)
268 struct listnode
*node
;
269 struct mpls_te_link
*lp
;
270 unsigned int key
= GET_OPAQUE_ID (ntohl (lsa
->data
->id
.s_addr
));
272 for (ALL_LIST_ELEMENTS_RO (OspfMplsTE
.iflist
, node
, lp
))
273 if (lp
->instance
== key
)
276 zlog_warn ("lookup_linkparams_by_instance: Entry not found: key(%x)", key
);
281 ospf_mpls_te_foreach_area (
282 void (*func
)(struct mpls_te_link
*lp
, enum sched_opcode
),
283 enum sched_opcode sched_opcode
)
285 struct listnode
*node
, *nnode
;
286 struct listnode
*node2
;
287 struct mpls_te_link
*lp
;
288 struct ospf_area
*area
;
290 for (ALL_LIST_ELEMENTS (OspfMplsTE
.iflist
, node
, nnode
, lp
))
292 if ((area
= lp
->area
) == NULL
)
294 if (lp
->flags
& LPFLG_LOOKUP_DONE
)
298 (* func
)(lp
, sched_opcode
);
300 for (node2
= listnextnode (node
); node2
; node2
= listnextnode (node2
))
301 if ((lp
= listgetdata (node2
)) != NULL
)
302 if (lp
->area
!= NULL
)
303 if (IPV4_ADDR_SAME (&lp
->area
->area_id
, &area
->area_id
))
304 lp
->flags
|= LPFLG_LOOKUP_DONE
;
307 for (ALL_LIST_ELEMENTS_RO (OspfMplsTE
.iflist
, node
, lp
))
308 if (lp
->area
!= NULL
)
309 lp
->flags
&= ~LPFLG_LOOKUP_DONE
;
315 set_mpls_te_router_addr (struct in_addr ipv4
)
317 OspfMplsTE
.router_addr
.header
.type
= htons (TE_TLV_ROUTER_ADDR
);
318 OspfMplsTE
.router_addr
.header
.length
= htons (sizeof (ipv4
));
319 OspfMplsTE
.router_addr
.value
= ipv4
;
324 set_linkparams_link_header (struct mpls_te_link
*lp
)
326 struct te_tlv_header
*tlvh
;
327 u_int16_t length
= 0;
329 /* TE_LINK_SUBTLV_LINK_TYPE */
330 if (ntohs (lp
->link_type
.header
.type
) != 0)
331 length
+= TLV_SIZE (&lp
->link_type
.header
);
333 /* TE_LINK_SUBTLV_LINK_ID */
334 if (ntohs (lp
->link_id
.header
.type
) != 0)
335 length
+= TLV_SIZE (&lp
->link_id
.header
);
337 /* TE_LINK_SUBTLV_LCLIF_IPADDR */
338 if ((tlvh
= (struct te_tlv_header
*) lp
->lclif_ipaddr
) != NULL
339 && ntohs (tlvh
->type
) != 0)
340 length
+= TLV_SIZE (tlvh
);
342 /* TE_LINK_SUBTLV_RMTIF_IPADDR */
343 if ((tlvh
= (struct te_tlv_header
*) lp
->rmtif_ipaddr
) != NULL
344 && ntohs (tlvh
->type
) != 0)
345 length
+= TLV_SIZE (tlvh
);
347 /* TE_LINK_SUBTLV_TE_METRIC */
348 if (ntohs (lp
->te_metric
.header
.type
) != 0)
349 length
+= TLV_SIZE (&lp
->te_metric
.header
);
351 /* TE_LINK_SUBTLV_MAX_BW */
352 if (ntohs (lp
->max_bw
.header
.type
) != 0)
353 length
+= TLV_SIZE (&lp
->max_bw
.header
);
355 /* TE_LINK_SUBTLV_MAX_RSV_BW */
356 if (ntohs (lp
->max_rsv_bw
.header
.type
) != 0)
357 length
+= TLV_SIZE (&lp
->max_rsv_bw
.header
);
359 /* TE_LINK_SUBTLV_UNRSV_BW */
360 if (ntohs (lp
->unrsv_bw
.header
.type
) != 0)
361 length
+= TLV_SIZE (&lp
->unrsv_bw
.header
);
363 /* TE_LINK_SUBTLV_RSC_CLSCLR */
364 if (ntohs (lp
->rsc_clsclr
.header
.type
) != 0)
365 length
+= TLV_SIZE (&lp
->rsc_clsclr
.header
);
367 lp
->link_header
.header
.type
= htons (TE_TLV_LINK
);
368 lp
->link_header
.header
.length
= htons (length
);
374 set_linkparams_link_type (struct ospf_interface
*oi
, struct mpls_te_link
*lp
)
376 lp
->link_type
.header
.type
= htons (TE_LINK_SUBTLV_LINK_TYPE
);
377 lp
->link_type
.header
.length
= htons (sizeof (lp
->link_type
.link_type
.value
));
381 case OSPF_IFTYPE_POINTOPOINT
:
382 lp
->link_type
.link_type
.value
= LINK_TYPE_SUBTLV_VALUE_PTP
;
384 case OSPF_IFTYPE_BROADCAST
:
385 case OSPF_IFTYPE_NBMA
:
386 lp
->link_type
.link_type
.value
= LINK_TYPE_SUBTLV_VALUE_MA
;
389 /* Not supported yet. *//* XXX */
390 lp
->link_type
.header
.type
= htons (0);
397 set_linkparams_link_id (struct ospf_interface
*oi
, struct mpls_te_link
*lp
)
399 struct ospf_neighbor
*nbr
;
402 lp
->link_id
.header
.type
= htons (TE_LINK_SUBTLV_LINK_ID
);
403 lp
->link_id
.header
.length
= htons (sizeof (lp
->link_id
.value
));
406 * The Link ID is identical to the contents of the Link ID field
407 * in the Router LSA for these link types.
411 case OSPF_IFTYPE_POINTOPOINT
:
412 /* Take the router ID of the neighbor. */
413 if ((nbr
= ospf_nbr_lookup_ptop (oi
))
414 && nbr
->state
== NSM_Full
)
416 lp
->link_id
.value
= nbr
->router_id
;
420 case OSPF_IFTYPE_BROADCAST
:
421 case OSPF_IFTYPE_NBMA
:
422 /* Take the interface address of the designated router. */
423 if ((nbr
= ospf_nbr_lookup_by_addr (oi
->nbrs
, &DR (oi
))) == NULL
)
426 if (nbr
->state
== NSM_Full
427 || (IPV4_ADDR_SAME (&oi
->address
->u
.prefix4
, &DR (oi
))
428 && ospf_nbr_count (oi
, NSM_Full
) > 0))
430 lp
->link_id
.value
= DR (oi
);
435 /* Not supported yet. *//* XXX */
436 lp
->link_id
.header
.type
= htons (0);
443 masklen2ip (oi
->address
->prefixlen
, &mask
);
444 lp
->link_id
.value
.s_addr
= oi
->address
->u
.prefix4
.s_addr
& mask
.s_addr
;
450 set_linkparams_te_metric (struct mpls_te_link
*lp
, u_int32_t te_metric
)
452 lp
->te_metric
.header
.type
= htons (TE_LINK_SUBTLV_TE_METRIC
);
453 lp
->te_metric
.header
.length
= htons (sizeof (lp
->te_metric
.value
));
454 lp
->te_metric
.value
= htonl (te_metric
);
459 set_linkparams_max_bw (struct mpls_te_link
*lp
, float *fp
)
461 lp
->max_bw
.header
.type
= htons (TE_LINK_SUBTLV_MAX_BW
);
462 lp
->max_bw
.header
.length
= htons (sizeof (lp
->max_bw
.value
));
463 htonf (fp
, &lp
->max_bw
.value
);
468 set_linkparams_max_rsv_bw (struct mpls_te_link
*lp
, float *fp
)
470 lp
->max_rsv_bw
.header
.type
= htons (TE_LINK_SUBTLV_MAX_RSV_BW
);
471 lp
->max_rsv_bw
.header
.length
= htons (sizeof (lp
->max_rsv_bw
.value
));
472 htonf (fp
, &lp
->max_rsv_bw
.value
);
477 set_linkparams_unrsv_bw (struct mpls_te_link
*lp
, int priority
, float *fp
)
479 /* Note that TLV-length field is the size of array. */
480 lp
->unrsv_bw
.header
.type
= htons (TE_LINK_SUBTLV_UNRSV_BW
);
481 lp
->unrsv_bw
.header
.length
= htons (sizeof (lp
->unrsv_bw
.value
));
482 htonf (fp
, &lp
->unrsv_bw
.value
[priority
]);
487 set_linkparams_rsc_clsclr (struct mpls_te_link
*lp
, u_int32_t classcolor
)
489 lp
->rsc_clsclr
.header
.type
= htons (TE_LINK_SUBTLV_RSC_CLSCLR
);
490 lp
->rsc_clsclr
.header
.length
= htons (sizeof (lp
->rsc_clsclr
.value
));
491 lp
->rsc_clsclr
.value
= htonl (classcolor
);
496 initialize_linkparams (struct mpls_te_link
*lp
)
498 struct interface
*ifp
= lp
->ifp
;
499 struct ospf_interface
*oi
;
503 if ((oi
= lookup_oi_by_ifp (ifp
, NULL
, OI_ANY
)) == NULL
)
507 * Try to set initial values those can be derived from
508 * zebra-interface information.
510 set_linkparams_link_type (oi
, lp
);
513 * Linux and *BSD kernel holds bandwidth parameter as an "int" type.
514 * We may have to reconsider, if "ifp->bandwidth" type changes to float.
516 fval
= (float)((ifp
->bandwidth
? ifp
->bandwidth
517 : OSPF_DEFAULT_BANDWIDTH
) * 1000 / 8);
519 set_linkparams_max_bw (lp
, &fval
);
520 set_linkparams_max_rsv_bw (lp
, &fval
);
522 for (i
= 0; i
< 8; i
++)
523 set_linkparams_unrsv_bw (lp
, i
, &fval
);
529 is_mandated_params_set (struct mpls_te_link
*lp
)
533 if (ntohs (OspfMplsTE
.router_addr
.header
.type
) == 0)
536 if (ntohs (lp
->link_type
.header
.type
) == 0)
539 if (ntohs (lp
->link_id
.header
.type
) == 0)
547 /*------------------------------------------------------------------------*
548 * Followings are callback functions against generic Opaque-LSAs handling.
549 *------------------------------------------------------------------------*/
552 ospf_mpls_te_new_if (struct interface
*ifp
)
554 struct mpls_te_link
*new;
557 if (lookup_linkparams_by_ifp (ifp
) != NULL
)
559 zlog_warn ("ospf_mpls_te_new_if: ifp(%p) already in use?", ifp
);
560 rc
= 0; /* Do nothing here. */
564 if ((new = XMALLOC (MTYPE_OSPF_MPLS_TE_LINKPARAMS
,
565 sizeof (struct mpls_te_link
))) == NULL
)
567 zlog_warn ("ospf_mpls_te_new_if: XMALLOC: %s", safe_strerror (errno
));
570 memset (new, 0, sizeof (struct mpls_te_link
));
574 new->instance
= get_mpls_te_instance_value ();
577 initialize_linkparams (new);
579 listnode_add (OspfMplsTE
.iflist
, new);
581 /* Schedule Opaque-LSA refresh. *//* XXX */
589 ospf_mpls_te_del_if (struct interface
*ifp
)
591 struct mpls_te_link
*lp
;
594 if ((lp
= lookup_linkparams_by_ifp (ifp
)) != NULL
)
596 struct list
*iflist
= OspfMplsTE
.iflist
;
598 /* Dequeue listnode entry from the list. */
599 listnode_delete (iflist
, lp
);
601 /* Avoid misjudgement in the next lookup. */
602 if (listcount (iflist
) == 0)
603 iflist
->head
= iflist
->tail
= NULL
;
605 XFREE (MTYPE_OSPF_MPLS_TE_LINKPARAMS
, lp
);
608 /* Schedule Opaque-LSA refresh. *//* XXX */
616 ospf_mpls_te_ism_change (struct ospf_interface
*oi
, int old_state
)
618 struct te_link_subtlv_link_type old_type
;
619 struct te_link_subtlv_link_id old_id
;
620 struct mpls_te_link
*lp
;
622 if ((lp
= lookup_linkparams_by_ifp (oi
->ifp
)) == NULL
)
624 zlog_warn ("ospf_mpls_te_ism_change: Cannot get linkparams from OI(%s)?", IF_NAME (oi
));
627 if (oi
->area
== NULL
|| oi
->area
->ospf
== NULL
)
629 zlog_warn ("ospf_mpls_te_ism_change: Cannot refer to OSPF from OI(%s)?",
634 if ((lp
->area
!= NULL
635 && ! IPV4_ADDR_SAME (&lp
->area
->area_id
, &oi
->area
->area_id
))
636 || (lp
->area
!= NULL
&& oi
->area
== NULL
))
638 /* How should we consider this case? */
639 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");
640 ospf_mpls_te_lsa_schedule (lp
, FLUSH_THIS_LSA
);
643 /* Keep Area information in conbination with linkparams. */
648 case ISM_PointToPoint
:
652 old_type
= lp
->link_type
;
653 old_id
= lp
->link_id
;
655 set_linkparams_link_type (oi
, lp
);
656 set_linkparams_link_id (oi
, lp
);
658 if ((ntohs (old_type
.header
.type
) != ntohs (lp
->link_type
.header
.type
)
659 || old_type
.link_type
.value
!= lp
->link_type
.link_type
.value
)
660 || (ntohs (old_id
.header
.type
) != ntohs (lp
->link_id
.header
.type
)
661 || ntohl (old_id
.value
.s_addr
) != ntohl (lp
->link_id
.value
.s_addr
)))
663 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
664 ospf_mpls_te_lsa_schedule (lp
, REFRESH_THIS_LSA
);
666 ospf_mpls_te_lsa_schedule (lp
, REORIGINATE_PER_AREA
);
670 lp
->link_type
.header
.type
= htons (0);
671 lp
->link_id
.header
.type
= htons (0);
673 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
674 ospf_mpls_te_lsa_schedule (lp
, FLUSH_THIS_LSA
);
683 ospf_mpls_te_nsm_change (struct ospf_neighbor
*nbr
, int old_state
)
685 /* So far, nothing to do here. */
689 /*------------------------------------------------------------------------*
690 * Followings are OSPF protocol processing functions for MPLS-TE.
691 *------------------------------------------------------------------------*/
694 build_tlv_header (struct stream
*s
, struct te_tlv_header
*tlvh
)
696 stream_put (s
, tlvh
, sizeof (struct te_tlv_header
));
701 build_router_tlv (struct stream
*s
)
703 struct te_tlv_header
*tlvh
= &OspfMplsTE
.router_addr
.header
;
704 if (ntohs (tlvh
->type
) != 0)
706 build_tlv_header (s
, tlvh
);
707 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
713 build_link_subtlv_link_type (struct stream
*s
, struct mpls_te_link
*lp
)
715 struct te_tlv_header
*tlvh
= &lp
->link_type
.header
;
716 if (ntohs (tlvh
->type
) != 0)
718 build_tlv_header (s
, tlvh
);
719 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
725 build_link_subtlv_link_id (struct stream
*s
, struct mpls_te_link
*lp
)
727 struct te_tlv_header
*tlvh
= &lp
->link_id
.header
;
728 if (ntohs (tlvh
->type
) != 0)
730 build_tlv_header (s
, tlvh
);
731 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
737 build_link_subtlv_lclif_ipaddr (struct stream
*s
, struct mpls_te_link
*lp
)
739 struct te_tlv_header
*tlvh
= (struct te_tlv_header
*) lp
->lclif_ipaddr
;
740 if (tlvh
!= NULL
&& ntohs (tlvh
->type
) != 0)
742 build_tlv_header (s
, tlvh
);
743 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
749 build_link_subtlv_rmtif_ipaddr (struct stream
*s
, struct mpls_te_link
*lp
)
751 struct te_tlv_header
*tlvh
= (struct te_tlv_header
*) lp
->rmtif_ipaddr
;
752 if (tlvh
!= NULL
&& ntohs (tlvh
->type
) != 0)
754 build_tlv_header (s
, tlvh
);
755 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
761 build_link_subtlv_te_metric (struct stream
*s
, struct mpls_te_link
*lp
)
763 struct te_tlv_header
*tlvh
= &lp
->te_metric
.header
;
764 if (ntohs (tlvh
->type
) != 0)
766 build_tlv_header (s
, tlvh
);
767 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
773 build_link_subtlv_max_bw (struct stream
*s
, struct mpls_te_link
*lp
)
775 struct te_tlv_header
*tlvh
= &lp
->max_bw
.header
;
776 if (ntohs (tlvh
->type
) != 0)
778 build_tlv_header (s
, tlvh
);
779 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
785 build_link_subtlv_max_rsv_bw (struct stream
*s
, struct mpls_te_link
*lp
)
787 struct te_tlv_header
*tlvh
= &lp
->max_rsv_bw
.header
;
788 if (ntohs (tlvh
->type
) != 0)
790 build_tlv_header (s
, tlvh
);
791 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
797 build_link_subtlv_unrsv_bw (struct stream
*s
, struct mpls_te_link
*lp
)
799 struct te_tlv_header
*tlvh
= &lp
->unrsv_bw
.header
;
800 if (ntohs (tlvh
->type
) != 0)
802 build_tlv_header (s
, tlvh
);
803 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
809 build_link_subtlv_rsc_clsclr (struct stream
*s
, struct mpls_te_link
*lp
)
811 struct te_tlv_header
*tlvh
= &lp
->rsc_clsclr
.header
;
812 if (ntohs (tlvh
->type
) != 0)
814 build_tlv_header (s
, tlvh
);
815 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
821 build_link_tlv (struct stream
*s
, struct mpls_te_link
*lp
)
823 set_linkparams_link_header (lp
);
824 build_tlv_header (s
, &lp
->link_header
.header
);
826 build_link_subtlv_link_type (s
, lp
);
827 build_link_subtlv_link_id (s
, lp
);
828 build_link_subtlv_lclif_ipaddr (s
, lp
);
829 build_link_subtlv_rmtif_ipaddr (s
, lp
);
830 build_link_subtlv_te_metric (s
, lp
);
831 build_link_subtlv_max_bw (s
, lp
);
832 build_link_subtlv_max_rsv_bw (s
, lp
);
833 build_link_subtlv_unrsv_bw (s
, lp
);
834 build_link_subtlv_rsc_clsclr (s
, lp
);
839 ospf_mpls_te_lsa_body_set (struct stream
*s
, struct mpls_te_link
*lp
)
842 * The router address TLV is type 1, and ...
843 * It must appear in exactly one
844 * Traffic Engineering LSA originated by a router.
846 build_router_tlv (s
);
849 * Only one Link TLV shall be carried in each LSA, allowing for fine
850 * granularity changes in topology.
852 build_link_tlv (s
, lp
);
856 /* Create new opaque-LSA. */
857 static struct ospf_lsa
*
858 ospf_mpls_te_lsa_new (struct ospf_area
*area
, struct mpls_te_link
*lp
)
861 struct lsa_header
*lsah
;
862 struct ospf_lsa
*new = NULL
;
863 u_char options
, lsa_type
;
864 struct in_addr lsa_id
;
868 /* Create a stream for LSA. */
869 if ((s
= stream_new (OSPF_MAX_LSA_SIZE
)) == NULL
)
871 zlog_warn ("ospf_mpls_te_lsa_new: stream_new() ?");
874 lsah
= (struct lsa_header
*) STREAM_DATA (s
);
876 options
= LSA_OPTIONS_GET (area
);
877 options
|= LSA_OPTIONS_NSSA_GET (area
);
878 options
|= OSPF_OPTION_O
; /* Don't forget this :-) */
880 lsa_type
= OSPF_OPAQUE_AREA_LSA
;
881 tmp
= SET_OPAQUE_LSID (OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA
, lp
->instance
);
882 lsa_id
.s_addr
= htonl (tmp
);
884 if (IS_DEBUG_OSPF (lsa
, LSA_GENERATE
))
885 zlog_debug ("LSA[Type%d:%s]: Create an Opaque-LSA/MPLS-TE instance", lsa_type
, inet_ntoa (lsa_id
));
887 /* Set opaque-LSA header fields. */
888 lsa_header_set (s
, options
, lsa_type
, lsa_id
, area
->ospf
->router_id
);
890 /* Set opaque-LSA body fields. */
891 ospf_mpls_te_lsa_body_set (s
, lp
);
894 length
= stream_get_endp (s
);
895 lsah
->length
= htons (length
);
897 /* Now, create an OSPF LSA instance. */
898 if ((new = ospf_lsa_new ()) == NULL
)
900 zlog_warn ("ospf_mpls_te_lsa_new: ospf_lsa_new() ?");
904 if ((new->data
= ospf_lsa_data_new (length
)) == NULL
)
906 zlog_warn ("ospf_mpls_te_lsa_new: ospf_lsa_data_new() ?");
907 ospf_lsa_unlock (&new);
914 SET_FLAG (new->flags
, OSPF_LSA_SELF
);
915 memcpy (new->data
, lsah
, length
);
923 ospf_mpls_te_lsa_originate1 (struct ospf_area
*area
, struct mpls_te_link
*lp
)
925 struct ospf_lsa
*new;
928 /* Create new Opaque-LSA/MPLS-TE instance. */
929 if ((new = ospf_mpls_te_lsa_new (area
, lp
)) == NULL
)
931 zlog_warn ("ospf_mpls_te_lsa_originate1: ospf_mpls_te_lsa_new() ?");
935 /* Install this LSA into LSDB. */
936 if (ospf_lsa_install (area
->ospf
, NULL
/*oi*/, new) == NULL
)
938 zlog_warn ("ospf_mpls_te_lsa_originate1: ospf_lsa_install() ?");
939 ospf_lsa_unlock (&new);
943 /* Now this linkparameter entry has associated LSA. */
944 lp
->flags
|= LPFLG_LSA_ENGAGED
;
946 /* Update new LSA origination count. */
947 area
->ospf
->lsa_originate_count
++;
949 /* Flood new LSA through area. */
950 ospf_flood_through_area (area
, NULL
/*nbr*/, new);
952 if (IS_DEBUG_OSPF (lsa
, LSA_GENERATE
))
954 char area_id
[INET_ADDRSTRLEN
];
955 strcpy (area_id
, inet_ntoa (area
->area_id
));
956 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
);
957 ospf_lsa_header_dump (new->data
);
966 ospf_mpls_te_lsa_originate (void *arg
)
968 struct ospf_area
*area
= (struct ospf_area
*) arg
;
969 struct listnode
*node
, *nnode
;
970 struct mpls_te_link
*lp
;
973 if (OspfMplsTE
.status
== disabled
)
975 zlog_info ("ospf_mpls_te_lsa_originate: MPLS-TE is disabled now.");
976 rc
= 0; /* This is not an error case. */
980 for (ALL_LIST_ELEMENTS (OspfMplsTE
.iflist
, node
, nnode
, lp
))
982 if (lp
->area
== NULL
)
984 if (! IPV4_ADDR_SAME (&lp
->area
->area_id
, &area
->area_id
))
987 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
989 if (lp
->flags
& LPFLG_LSA_FORCED_REFRESH
)
991 lp
->flags
&= ~LPFLG_LSA_FORCED_REFRESH
;
992 ospf_mpls_te_lsa_schedule (lp
, REFRESH_THIS_LSA
);
996 if (! is_mandated_params_set (lp
))
998 zlog_warn ("ospf_mpls_te_lsa_originate: Link(%s) lacks some mandated MPLS-TE parameters.", lp
->ifp
? lp
->ifp
->name
: "?");
1002 /* Ok, let's try to originate an LSA for this area and Link. */
1003 if (ospf_mpls_te_lsa_originate1 (area
, lp
) != 0)
1013 ospf_mpls_te_lsa_refresh (struct ospf_lsa
*lsa
)
1015 struct mpls_te_link
*lp
;
1016 struct ospf_area
*area
= lsa
->area
;
1017 struct ospf_lsa
*new = NULL
;
1019 if (OspfMplsTE
.status
== disabled
)
1022 * This LSA must have flushed before due to MPLS-TE status change.
1023 * It seems a slip among routers in the routing domain.
1025 zlog_info ("ospf_mpls_te_lsa_refresh: MPLS-TE is disabled now.");
1026 lsa
->data
->ls_age
= htons (OSPF_LSA_MAXAGE
); /* Flush it anyway. */
1029 /* At first, resolve lsa/lp relationship. */
1030 if ((lp
= lookup_linkparams_by_instance (lsa
)) == NULL
)
1032 zlog_warn ("ospf_mpls_te_lsa_refresh: Invalid parameter?");
1033 lsa
->data
->ls_age
= htons (OSPF_LSA_MAXAGE
); /* Flush it anyway. */
1036 /* If the lsa's age reached to MaxAge, start flushing procedure. */
1037 if (IS_LSA_MAXAGE (lsa
))
1039 lp
->flags
&= ~LPFLG_LSA_ENGAGED
;
1040 ospf_opaque_lsa_flush_schedule (lsa
);
1044 /* Create new Opaque-LSA/MPLS-TE instance. */
1045 if ((new = ospf_mpls_te_lsa_new (area
, lp
)) == NULL
)
1047 zlog_warn ("ospf_mpls_te_lsa_refresh: ospf_mpls_te_lsa_new() ?");
1050 new->data
->ls_seqnum
= lsa_seqnum_increment (lsa
);
1052 /* Install this LSA into LSDB. */
1053 /* Given "lsa" will be freed in the next function. */
1054 if (ospf_lsa_install (area
->ospf
, NULL
/*oi*/, new) == NULL
)
1056 zlog_warn ("ospf_mpls_te_lsa_refresh: ospf_lsa_install() ?");
1057 ospf_lsa_unlock (&new);
1061 /* Flood updated LSA through area. */
1062 ospf_flood_through_area (area
, NULL
/*nbr*/, new);
1064 /* Debug logging. */
1065 if (IS_DEBUG_OSPF (lsa
, LSA_GENERATE
))
1067 zlog_debug ("LSA[Type%d:%s]: Refresh Opaque-LSA/MPLS-TE",
1068 new->data
->type
, inet_ntoa (new->data
->id
));
1069 ospf_lsa_header_dump (new->data
);
1077 ospf_mpls_te_lsa_schedule (struct mpls_te_link
*lp
,
1078 enum sched_opcode opcode
)
1080 struct ospf_lsa lsa
;
1081 struct lsa_header lsah
;
1084 memset (&lsa
, 0, sizeof (lsa
));
1085 memset (&lsah
, 0, sizeof (lsah
));
1087 lsa
.area
= lp
->area
;
1089 lsah
.type
= OSPF_OPAQUE_AREA_LSA
;
1090 tmp
= SET_OPAQUE_LSID (OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA
, lp
->instance
);
1091 lsah
.id
.s_addr
= htonl (tmp
);
1095 case REORIGINATE_PER_AREA
:
1096 ospf_opaque_lsa_reoriginate_schedule ((void *) lp
->area
,
1097 OSPF_OPAQUE_AREA_LSA
, OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA
);
1099 case REFRESH_THIS_LSA
:
1100 ospf_opaque_lsa_refresh_schedule (&lsa
);
1102 case FLUSH_THIS_LSA
:
1103 lp
->flags
&= ~LPFLG_LSA_ENGAGED
;
1104 ospf_opaque_lsa_flush_schedule (&lsa
);
1107 zlog_warn ("ospf_mpls_te_lsa_schedule: Unknown opcode (%u)", opcode
);
1114 /*------------------------------------------------------------------------*
1115 * Followings are vty session control functions.
1116 *------------------------------------------------------------------------*/
1119 show_vty_router_addr (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1121 struct te_tlv_router_addr
*top
= (struct te_tlv_router_addr
*) tlvh
;
1124 vty_out (vty
, " Router-Address: %s%s", inet_ntoa (top
->value
), VTY_NEWLINE
);
1126 zlog_debug (" Router-Address: %s", inet_ntoa (top
->value
));
1128 return TLV_SIZE (tlvh
);
1132 show_vty_link_header (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1134 struct te_tlv_link
*top
= (struct te_tlv_link
*) tlvh
;
1137 vty_out (vty
, " Link: %u octets of data%s", ntohs (top
->header
.length
), VTY_NEWLINE
);
1139 zlog_debug (" Link: %u octets of data", ntohs (top
->header
.length
));
1141 return TLV_HDR_SIZE
; /* Here is special, not "TLV_SIZE". */
1145 show_vty_link_subtlv_link_type (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1147 struct te_link_subtlv_link_type
*top
;
1148 const char *cp
= "Unknown";
1150 top
= (struct te_link_subtlv_link_type
*) tlvh
;
1151 switch (top
->link_type
.value
)
1153 case LINK_TYPE_SUBTLV_VALUE_PTP
:
1154 cp
= "Point-to-point";
1156 case LINK_TYPE_SUBTLV_VALUE_MA
:
1164 vty_out (vty
, " Link-Type: %s (%u)%s", cp
, top
->link_type
.value
, VTY_NEWLINE
);
1166 zlog_debug (" Link-Type: %s (%u)", cp
, top
->link_type
.value
);
1168 return TLV_SIZE (tlvh
);
1172 show_vty_link_subtlv_link_id (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1174 struct te_link_subtlv_link_id
*top
;
1176 top
= (struct te_link_subtlv_link_id
*) tlvh
;
1178 vty_out (vty
, " Link-ID: %s%s", inet_ntoa (top
->value
), VTY_NEWLINE
);
1180 zlog_debug (" Link-ID: %s", inet_ntoa (top
->value
));
1182 return TLV_SIZE (tlvh
);
1186 show_vty_link_subtlv_lclif_ipaddr (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1188 struct te_link_subtlv_lclif_ipaddr
*top
;
1191 top
= (struct te_link_subtlv_lclif_ipaddr
*) tlvh
;
1192 n
= ntohs (tlvh
->length
) / sizeof (top
->value
[0]);
1195 vty_out (vty
, " Local Interface IP Address(es): %d%s", n
, VTY_NEWLINE
);
1197 zlog_debug (" Local Interface IP Address(es): %d", n
);
1199 for (i
= 0; i
< n
; i
++)
1202 vty_out (vty
, " #%d: %s%s", i
, inet_ntoa (top
->value
[i
]), VTY_NEWLINE
);
1204 zlog_debug (" #%d: %s", i
, inet_ntoa (top
->value
[i
]));
1206 return TLV_SIZE (tlvh
);
1210 show_vty_link_subtlv_rmtif_ipaddr (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1212 struct te_link_subtlv_rmtif_ipaddr
*top
;
1215 top
= (struct te_link_subtlv_rmtif_ipaddr
*) tlvh
;
1216 n
= ntohs (tlvh
->length
) / sizeof (top
->value
[0]);
1218 vty_out (vty
, " Remote Interface IP Address(es): %d%s", n
, VTY_NEWLINE
);
1220 zlog_debug (" Remote Interface IP Address(es): %d", n
);
1222 for (i
= 0; i
< n
; i
++)
1225 vty_out (vty
, " #%d: %s%s", i
, inet_ntoa (top
->value
[i
]), VTY_NEWLINE
);
1227 zlog_debug (" #%d: %s", i
, inet_ntoa (top
->value
[i
]));
1229 return TLV_SIZE (tlvh
);
1233 show_vty_link_subtlv_te_metric (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1235 struct te_link_subtlv_te_metric
*top
;
1237 top
= (struct te_link_subtlv_te_metric
*) tlvh
;
1239 vty_out (vty
, " Traffic Engineering Metric: %u%s", (u_int32_t
) ntohl (top
->value
), VTY_NEWLINE
);
1241 zlog_debug (" Traffic Engineering Metric: %u", (u_int32_t
) ntohl (top
->value
));
1243 return TLV_SIZE (tlvh
);
1247 show_vty_link_subtlv_max_bw (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1249 struct te_link_subtlv_max_bw
*top
;
1252 top
= (struct te_link_subtlv_max_bw
*) tlvh
;
1253 ntohf (&top
->value
, &fval
);
1256 vty_out (vty
, " Maximum Bandwidth: %g (Bytes/sec)%s", fval
, VTY_NEWLINE
);
1258 zlog_debug (" Maximum Bandwidth: %g (Bytes/sec)", fval
);
1260 return TLV_SIZE (tlvh
);
1264 show_vty_link_subtlv_max_rsv_bw (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1266 struct te_link_subtlv_max_rsv_bw
*top
;
1269 top
= (struct te_link_subtlv_max_rsv_bw
*) tlvh
;
1270 ntohf (&top
->value
, &fval
);
1273 vty_out (vty
, " Maximum Reservable Bandwidth: %g (Bytes/sec)%s", fval
, VTY_NEWLINE
);
1275 zlog_debug (" Maximum Reservable Bandwidth: %g (Bytes/sec)", fval
);
1277 return TLV_SIZE (tlvh
);
1281 show_vty_link_subtlv_unrsv_bw (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1283 struct te_link_subtlv_unrsv_bw
*top
;
1287 top
= (struct te_link_subtlv_unrsv_bw
*) tlvh
;
1288 for (i
= 0; i
< 8; i
++)
1290 ntohf (&top
->value
[i
], &fval
);
1292 vty_out (vty
, " Unreserved Bandwidth (pri %d): %g (Bytes/sec)%s", i
, fval
, VTY_NEWLINE
);
1294 zlog_debug (" Unreserved Bandwidth (pri %d): %g (Bytes/sec)", i
, fval
);
1297 return TLV_SIZE (tlvh
);
1301 show_vty_link_subtlv_rsc_clsclr (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1303 struct te_link_subtlv_rsc_clsclr
*top
;
1305 top
= (struct te_link_subtlv_rsc_clsclr
*) tlvh
;
1307 vty_out (vty
, " Resource class/color: 0x%x%s", (u_int32_t
) ntohl (top
->value
), VTY_NEWLINE
);
1309 zlog_debug (" Resource Class/Color: 0x%x", (u_int32_t
) ntohl (top
->value
));
1311 return TLV_SIZE (tlvh
);
1315 show_vty_unknown_tlv (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1318 vty_out (vty
, " Unknown TLV: [type(0x%x), length(0x%x)]%s", ntohs (tlvh
->type
), ntohs (tlvh
->length
), VTY_NEWLINE
);
1320 zlog_debug (" Unknown TLV: [type(0x%x), length(0x%x)]", ntohs (tlvh
->type
), ntohs (tlvh
->length
));
1322 return TLV_SIZE (tlvh
);
1326 ospf_mpls_te_show_link_subtlv (struct vty
*vty
, struct te_tlv_header
*tlvh0
,
1327 u_int16_t subtotal
, u_int16_t total
)
1329 struct te_tlv_header
*tlvh
, *next
;
1330 u_int16_t sum
= subtotal
;
1332 for (tlvh
= tlvh0
; sum
< total
; tlvh
= (next
? next
: TLV_HDR_NEXT (tlvh
)))
1335 switch (ntohs (tlvh
->type
))
1337 case TE_LINK_SUBTLV_LINK_TYPE
:
1338 sum
+= show_vty_link_subtlv_link_type (vty
, tlvh
);
1340 case TE_LINK_SUBTLV_LINK_ID
:
1341 sum
+= show_vty_link_subtlv_link_id (vty
, tlvh
);
1343 case TE_LINK_SUBTLV_LCLIF_IPADDR
:
1344 sum
+= show_vty_link_subtlv_lclif_ipaddr (vty
, tlvh
);
1346 case TE_LINK_SUBTLV_RMTIF_IPADDR
:
1347 sum
+= show_vty_link_subtlv_rmtif_ipaddr (vty
, tlvh
);
1349 case TE_LINK_SUBTLV_TE_METRIC
:
1350 sum
+= show_vty_link_subtlv_te_metric (vty
, tlvh
);
1352 case TE_LINK_SUBTLV_MAX_BW
:
1353 sum
+= show_vty_link_subtlv_max_bw (vty
, tlvh
);
1355 case TE_LINK_SUBTLV_MAX_RSV_BW
:
1356 sum
+= show_vty_link_subtlv_max_rsv_bw (vty
, tlvh
);
1358 case TE_LINK_SUBTLV_UNRSV_BW
:
1359 sum
+= show_vty_link_subtlv_unrsv_bw (vty
, tlvh
);
1361 case TE_LINK_SUBTLV_RSC_CLSCLR
:
1362 sum
+= show_vty_link_subtlv_rsc_clsclr (vty
, tlvh
);
1365 sum
+= show_vty_unknown_tlv (vty
, tlvh
);
1373 ospf_mpls_te_show_info (struct vty
*vty
, struct ospf_lsa
*lsa
)
1375 struct lsa_header
*lsah
= (struct lsa_header
*) lsa
->data
;
1376 struct te_tlv_header
*tlvh
, *next
;
1377 u_int16_t sum
, total
;
1378 u_int16_t (* subfunc
)(struct vty
*vty
, struct te_tlv_header
*tlvh
,
1379 u_int16_t subtotal
, u_int16_t total
) = NULL
;
1382 total
= ntohs (lsah
->length
) - OSPF_LSA_HEADER_SIZE
;
1384 for (tlvh
= TLV_HDR_TOP (lsah
); sum
< total
;
1385 tlvh
= (next
? next
: TLV_HDR_NEXT (tlvh
)))
1387 if (subfunc
!= NULL
)
1389 sum
= (* subfunc
)(vty
, tlvh
, sum
, total
);
1390 next
= (struct te_tlv_header
*)((char *) tlvh
+ sum
);
1396 switch (ntohs (tlvh
->type
))
1398 case TE_TLV_ROUTER_ADDR
:
1399 sum
+= show_vty_router_addr (vty
, tlvh
);
1402 sum
+= show_vty_link_header (vty
, tlvh
);
1403 subfunc
= ospf_mpls_te_show_link_subtlv
;
1407 sum
+= show_vty_unknown_tlv (vty
, tlvh
);
1415 ospf_mpls_te_config_write_router (struct vty
*vty
)
1417 if (OspfMplsTE
.status
== enabled
)
1419 vty_out (vty
, " mpls-te%s", VTY_NEWLINE
);
1420 vty_out (vty
, " mpls-te router-address %s%s",
1421 inet_ntoa (OspfMplsTE
.router_addr
.value
), VTY_NEWLINE
);
1427 ospf_mpls_te_config_write_if (struct vty
*vty
, struct interface
*ifp
)
1429 struct mpls_te_link
*lp
;
1431 if ((OspfMplsTE
.status
== enabled
)
1432 && (! if_is_loopback (ifp
) && if_is_up (ifp
) && ospf_oi_count (ifp
) > 0)
1433 && ((lp
= lookup_linkparams_by_ifp (ifp
)) != NULL
))
1438 vty_out (vty
, " mpls-te link metric %u%s",
1439 (u_int32_t
) ntohl (lp
->te_metric
.value
), VTY_NEWLINE
);
1441 ntohf (&lp
->max_bw
.value
, &fval
);
1442 if (fval
>= MPLS_TE_MINIMUM_BANDWIDTH
)
1443 vty_out (vty
, " mpls-te link max-bw %g%s", fval
, VTY_NEWLINE
);
1445 ntohf (&lp
->max_rsv_bw
.value
, &fval
);
1446 if (fval
>= MPLS_TE_MINIMUM_BANDWIDTH
)
1447 vty_out (vty
, " mpls-te link max-rsv-bw %g%s", fval
, VTY_NEWLINE
);
1449 for (i
= 0; i
< 8; i
++)
1451 ntohf (&lp
->unrsv_bw
.value
[i
], &fval
);
1452 if (fval
>= MPLS_TE_MINIMUM_BANDWIDTH
)
1453 vty_out (vty
, " mpls-te link unrsv-bw %d %g%s",
1454 i
, fval
, VTY_NEWLINE
);
1457 vty_out (vty
, " mpls-te link rsc-clsclr 0x%x%s",
1458 (u_int32_t
) ntohl (lp
->rsc_clsclr
.value
), VTY_NEWLINE
);
1463 /*------------------------------------------------------------------------*
1464 * Followings are vty command functions.
1465 *------------------------------------------------------------------------*/
1470 "Configure MPLS-TE parameters\n"
1471 "Enable the MPLS-TE functionality\n")
1473 struct listnode
*node
, *nnode
;
1474 struct mpls_te_link
*lp
;
1476 if (OspfMplsTE
.status
== enabled
)
1479 if (IS_DEBUG_OSPF_EVENT
)
1480 zlog_debug ("MPLS-TE: OFF -> ON");
1482 OspfMplsTE
.status
= enabled
;
1485 * Following code is intended to handle two cases;
1487 * 1) MPLS-TE was disabled at startup time, but now become enabled.
1488 * 2) MPLS-TE was once enabled then disabled, and now enabled again.
1490 for (ALL_LIST_ELEMENTS (OspfMplsTE
.iflist
, node
, nnode
, lp
))
1491 initialize_linkparams (lp
);
1493 ospf_mpls_te_foreach_area (ospf_mpls_te_lsa_schedule
, REORIGINATE_PER_AREA
);
1501 "Configure MPLS-TE parameters\n"
1502 "Enable the MPLS-TE functionality\n")
1508 "Configure MPLS-TE parameters\n"
1509 "Disable the MPLS-TE functionality\n")
1511 struct listnode
*node
, *nnode
;
1512 struct mpls_te_link
*lp
;
1514 if (OspfMplsTE
.status
== disabled
)
1517 if (IS_DEBUG_OSPF_EVENT
)
1518 zlog_debug ("MPLS-TE: ON -> OFF");
1520 OspfMplsTE
.status
= disabled
;
1522 for (ALL_LIST_ELEMENTS (OspfMplsTE
.iflist
, node
, nnode
, lp
))
1523 if (lp
->area
!= NULL
)
1524 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
1525 ospf_mpls_te_lsa_schedule (lp
, FLUSH_THIS_LSA
);
1530 DEFUN (mpls_te_router_addr
,
1531 mpls_te_router_addr_cmd
,
1532 "mpls-te router-address A.B.C.D",
1533 "MPLS-TE specific commands\n"
1534 "Stable IP address of the advertising router\n"
1535 "MPLS-TE router address in IPv4 address format\n")
1537 struct te_tlv_router_addr
*ra
= &OspfMplsTE
.router_addr
;
1538 struct in_addr value
;
1540 if (! inet_aton (argv
[0], &value
))
1542 vty_out (vty
, "Please specify Router-Addr by A.B.C.D%s", VTY_NEWLINE
);
1546 if (ntohs (ra
->header
.type
) == 0
1547 || ntohl (ra
->value
.s_addr
) != ntohl (value
.s_addr
))
1549 struct listnode
*node
, *nnode
;
1550 struct mpls_te_link
*lp
;
1551 int need_to_reoriginate
= 0;
1553 set_mpls_te_router_addr (value
);
1555 if (OspfMplsTE
.status
== disabled
)
1558 for (ALL_LIST_ELEMENTS (OspfMplsTE
.iflist
, node
, nnode
, lp
))
1560 if (lp
->area
== NULL
)
1563 if ((lp
->flags
& LPFLG_LSA_ENGAGED
) == 0)
1565 need_to_reoriginate
= 1;
1570 for (ALL_LIST_ELEMENTS (OspfMplsTE
.iflist
, node
, nnode
, lp
))
1572 if (lp
->area
== NULL
)
1575 if (need_to_reoriginate
)
1576 lp
->flags
|= LPFLG_LSA_FORCED_REFRESH
;
1578 ospf_mpls_te_lsa_schedule (lp
, REFRESH_THIS_LSA
);
1581 if (need_to_reoriginate
)
1582 ospf_mpls_te_foreach_area (
1583 ospf_mpls_te_lsa_schedule
, REORIGINATE_PER_AREA
);
1589 DEFUN (mpls_te_link_metric
,
1590 mpls_te_link_metric_cmd
,
1591 "mpls-te link metric <0-4294967295>",
1592 "MPLS-TE specific commands\n"
1593 "Configure MPLS-TE link parameters\n"
1594 "Link metric for MPLS-TE purpose\n"
1597 struct interface
*ifp
= (struct interface
*) vty
->index
;
1598 struct mpls_te_link
*lp
;
1601 if ((lp
= lookup_linkparams_by_ifp (ifp
)) == NULL
)
1603 vty_out (vty
, "mpls_te_link_metric: Something wrong!%s", VTY_NEWLINE
);
1607 value
= strtoul (argv
[0], NULL
, 10);
1609 if (ntohs (lp
->te_metric
.header
.type
) == 0
1610 || ntohl (lp
->te_metric
.value
) != value
)
1612 set_linkparams_te_metric (lp
, value
);
1614 if (OspfMplsTE
.status
== enabled
)
1615 if (lp
->area
!= NULL
)
1617 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
1618 ospf_mpls_te_lsa_schedule (lp
, REFRESH_THIS_LSA
);
1620 ospf_mpls_te_lsa_schedule (lp
, REORIGINATE_PER_AREA
);
1626 DEFUN (mpls_te_link_maxbw
,
1627 mpls_te_link_maxbw_cmd
,
1628 "mpls-te link max-bw BANDWIDTH",
1629 "MPLS-TE specific commands\n"
1630 "Configure MPLS-TE link parameters\n"
1631 "Maximum bandwidth that can be used\n"
1632 "Bytes/second (IEEE floating point format)\n")
1634 struct interface
*ifp
= (struct interface
*) vty
->index
;
1635 struct mpls_te_link
*lp
;
1638 if ((lp
= lookup_linkparams_by_ifp (ifp
)) == NULL
)
1640 vty_out (vty
, "mpls_te_link_maxbw: Something wrong!%s", VTY_NEWLINE
);
1644 ntohf (&lp
->max_bw
.value
, &f1
);
1645 if (sscanf (argv
[0], "%g", &f2
) != 1)
1647 vty_out (vty
, "mpls_te_link_maxbw: fscanf: %s%s", safe_strerror (errno
), VTY_NEWLINE
);
1651 if (ntohs (lp
->max_bw
.header
.type
) == 0
1654 set_linkparams_max_bw (lp
, &f2
);
1656 if (OspfMplsTE
.status
== enabled
)
1657 if (lp
->area
!= NULL
)
1659 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
1660 ospf_mpls_te_lsa_schedule (lp
, REFRESH_THIS_LSA
);
1662 ospf_mpls_te_lsa_schedule (lp
, REORIGINATE_PER_AREA
);
1668 DEFUN (mpls_te_link_max_rsv_bw
,
1669 mpls_te_link_max_rsv_bw_cmd
,
1670 "mpls-te link max-rsv-bw BANDWIDTH",
1671 "MPLS-TE specific commands\n"
1672 "Configure MPLS-TE link parameters\n"
1673 "Maximum bandwidth that may be reserved\n"
1674 "Bytes/second (IEEE floating point format)\n")
1676 struct interface
*ifp
= (struct interface
*) vty
->index
;
1677 struct mpls_te_link
*lp
;
1680 if ((lp
= lookup_linkparams_by_ifp (ifp
)) == NULL
)
1682 vty_out (vty
, "mpls_te_link_max_rsv_bw: Something wrong!%s", VTY_NEWLINE
);
1686 ntohf (&lp
->max_rsv_bw
.value
, &f1
);
1687 if (sscanf (argv
[0], "%g", &f2
) != 1)
1689 vty_out (vty
, "mpls_te_link_max_rsv_bw: fscanf: %s%s", safe_strerror (errno
), VTY_NEWLINE
);
1693 if (ntohs (lp
->max_rsv_bw
.header
.type
) == 0
1696 set_linkparams_max_rsv_bw (lp
, &f2
);
1698 if (OspfMplsTE
.status
== enabled
)
1699 if (lp
->area
!= NULL
)
1701 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
1702 ospf_mpls_te_lsa_schedule (lp
, REFRESH_THIS_LSA
);
1704 ospf_mpls_te_lsa_schedule (lp
, REORIGINATE_PER_AREA
);
1710 DEFUN (mpls_te_link_unrsv_bw
,
1711 mpls_te_link_unrsv_bw_cmd
,
1712 "mpls-te link unrsv-bw <0-7> BANDWIDTH",
1713 "MPLS-TE specific commands\n"
1714 "Configure MPLS-TE link parameters\n"
1715 "Unreserved bandwidth at each priority level\n"
1717 "Bytes/second (IEEE floating point format)\n")
1719 struct interface
*ifp
= (struct interface
*) vty
->index
;
1720 struct mpls_te_link
*lp
;
1724 if ((lp
= lookup_linkparams_by_ifp (ifp
)) == NULL
)
1726 vty_out (vty
, "mpls_te_link_unrsv_bw: Something wrong!%s", VTY_NEWLINE
);
1730 /* We don't have to consider about range check here. */
1731 if (sscanf (argv
[0], "%d", &priority
) != 1)
1733 vty_out (vty
, "mpls_te_link_unrsv_bw: fscanf: %s%s", safe_strerror (errno
), VTY_NEWLINE
);
1737 ntohf (&lp
->unrsv_bw
.value
[priority
], &f1
);
1738 if (sscanf (argv
[1], "%g", &f2
) != 1)
1740 vty_out (vty
, "mpls_te_link_unrsv_bw: fscanf: %s%s", safe_strerror (errno
), VTY_NEWLINE
);
1744 if (ntohs (lp
->unrsv_bw
.header
.type
) == 0
1747 set_linkparams_unrsv_bw (lp
, priority
, &f2
);
1749 if (OspfMplsTE
.status
== enabled
)
1750 if (lp
->area
!= NULL
)
1752 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
1753 ospf_mpls_te_lsa_schedule (lp
, REFRESH_THIS_LSA
);
1755 ospf_mpls_te_lsa_schedule (lp
, REORIGINATE_PER_AREA
);
1761 DEFUN (mpls_te_link_rsc_clsclr
,
1762 mpls_te_link_rsc_clsclr_cmd
,
1763 "mpls-te link rsc-clsclr BITPATTERN",
1764 "MPLS-TE specific commands\n"
1765 "Configure MPLS-TE link parameters\n"
1766 "Administrative group membership\n"
1767 "32-bit Hexadecimal value (ex. 0xa1)\n")
1769 struct interface
*ifp
= (struct interface
*) vty
->index
;
1770 struct mpls_te_link
*lp
;
1771 unsigned long value
;
1773 if ((lp
= lookup_linkparams_by_ifp (ifp
)) == NULL
)
1775 vty_out (vty
, "mpls_te_link_rsc_clsclr: Something wrong!%s", VTY_NEWLINE
);
1779 if (sscanf (argv
[0], "0x%lx", &value
) != 1)
1781 vty_out (vty
, "mpls_te_link_rsc_clsclr: fscanf: %s%s", safe_strerror (errno
), VTY_NEWLINE
);
1785 if (ntohs (lp
->rsc_clsclr
.header
.type
) == 0
1786 || ntohl (lp
->rsc_clsclr
.value
) != value
)
1788 set_linkparams_rsc_clsclr (lp
, value
);
1790 if (OspfMplsTE
.status
== enabled
)
1791 if (lp
->area
!= NULL
)
1793 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
1794 ospf_mpls_te_lsa_schedule (lp
, REFRESH_THIS_LSA
);
1796 ospf_mpls_te_lsa_schedule (lp
, REORIGINATE_PER_AREA
);
1802 DEFUN (show_mpls_te_router
,
1803 show_mpls_te_router_cmd
,
1804 "show mpls-te router",
1806 "MPLS-TE information\n"
1807 "Router information\n")
1809 if (OspfMplsTE
.status
== enabled
)
1811 vty_out (vty
, "--- MPLS-TE router parameters ---%s",
1814 if (ntohs (OspfMplsTE
.router_addr
.header
.type
) != 0)
1815 show_vty_router_addr (vty
, &OspfMplsTE
.router_addr
.header
);
1816 else if (vty
!= NULL
)
1817 vty_out (vty
, " N/A%s", VTY_NEWLINE
);
1823 show_mpls_te_link_sub (struct vty
*vty
, struct interface
*ifp
)
1825 struct mpls_te_link
*lp
;
1826 struct te_tlv_header
*tlvh
;
1828 if ((OspfMplsTE
.status
== enabled
)
1829 && (! if_is_loopback (ifp
) && if_is_up (ifp
) && ospf_oi_count (ifp
) > 0)
1830 && ((lp
= lookup_linkparams_by_ifp (ifp
)) != NULL
))
1832 vty_out (vty
, "-- MPLS-TE link parameters for %s --%s",
1833 ifp
->name
, VTY_NEWLINE
);
1835 show_vty_link_subtlv_link_type (vty
, &lp
->link_type
.header
);
1836 show_vty_link_subtlv_link_id (vty
, &lp
->link_id
.header
);
1838 if ((tlvh
= (struct te_tlv_header
*) lp
->lclif_ipaddr
) != NULL
)
1839 show_vty_link_subtlv_lclif_ipaddr (vty
, tlvh
);
1840 if ((tlvh
= (struct te_tlv_header
*) lp
->rmtif_ipaddr
) != NULL
)
1841 show_vty_link_subtlv_rmtif_ipaddr (vty
, tlvh
);
1843 show_vty_link_subtlv_te_metric (vty
, &lp
->te_metric
.header
);
1845 show_vty_link_subtlv_max_bw (vty
, &lp
->max_bw
.header
);
1846 show_vty_link_subtlv_max_rsv_bw (vty
, &lp
->max_rsv_bw
.header
);
1847 show_vty_link_subtlv_unrsv_bw (vty
, &lp
->unrsv_bw
.header
);
1848 show_vty_link_subtlv_rsc_clsclr (vty
, &lp
->rsc_clsclr
.header
);
1852 vty_out (vty
, " %s: MPLS-TE is disabled on this interface%s",
1853 ifp
->name
, VTY_NEWLINE
);
1859 DEFUN (show_mpls_te_link
,
1860 show_mpls_te_link_cmd
,
1861 "show mpls-te interface [INTERFACE]",
1863 "MPLS-TE information\n"
1864 "Interface information\n"
1867 struct interface
*ifp
;
1868 struct listnode
*node
, *nnode
;
1870 /* Show All Interfaces. */
1873 for (ALL_LIST_ELEMENTS (iflist
, node
, nnode
, ifp
))
1874 show_mpls_te_link_sub (vty
, ifp
);
1876 /* Interface name is specified. */
1879 if ((ifp
= if_lookup_by_name (argv
[0])) == NULL
)
1880 vty_out (vty
, "No such interface name%s", VTY_NEWLINE
);
1882 show_mpls_te_link_sub (vty
, ifp
);
1889 ospf_mpls_te_register_vty (void)
1891 install_element (VIEW_NODE
, &show_mpls_te_router_cmd
);
1892 install_element (VIEW_NODE
, &show_mpls_te_link_cmd
);
1893 install_element (ENABLE_NODE
, &show_mpls_te_router_cmd
);
1894 install_element (ENABLE_NODE
, &show_mpls_te_link_cmd
);
1896 install_element (OSPF_NODE
, &mpls_te_cmd
);
1897 install_element (OSPF_NODE
, &no_mpls_te_cmd
);
1898 install_element (OSPF_NODE
, &mpls_te_on_cmd
);
1899 install_element (OSPF_NODE
, &mpls_te_router_addr_cmd
);
1901 install_element (INTERFACE_NODE
, &mpls_te_link_metric_cmd
);
1902 install_element (INTERFACE_NODE
, &mpls_te_link_maxbw_cmd
);
1903 install_element (INTERFACE_NODE
, &mpls_te_link_max_rsv_bw_cmd
);
1904 install_element (INTERFACE_NODE
, &mpls_te_link_unrsv_bw_cmd
);
1905 install_element (INTERFACE_NODE
, &mpls_te_link_rsc_clsclr_cmd
);
1910 #endif /* HAVE_OSPF_TE */