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 ()
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
;
256 struct mpls_te_link
*lp
;
258 LIST_LOOP (OspfMplsTE
.iflist
, lp
, node
)
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 LIST_LOOP (OspfMplsTE
.iflist
, lp
, node
)
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
, *node2
;
286 struct mpls_te_link
*lp
;
287 struct ospf_area
*area
;
289 LIST_LOOP (OspfMplsTE
.iflist
, lp
, node
)
291 if ((area
= lp
->area
) == NULL
)
293 if (lp
->flags
& LPFLG_LOOKUP_DONE
)
297 (* func
)(lp
, sched_opcode
);
299 for (node2
= nextnode (node
); node2
; nextnode (node2
))
300 if ((lp
= getdata (node2
)) != NULL
)
301 if (lp
->area
!= NULL
)
302 if (IPV4_ADDR_SAME (&lp
->area
->area_id
, &area
->area_id
))
303 lp
->flags
|= LPFLG_LOOKUP_DONE
;
306 LIST_LOOP (OspfMplsTE
.iflist
, lp
, node
)
307 if (lp
->area
!= NULL
)
308 lp
->flags
&= ~LPFLG_LOOKUP_DONE
;
314 set_mpls_te_router_addr (struct in_addr ipv4
)
316 OspfMplsTE
.router_addr
.header
.type
= htons (TE_TLV_ROUTER_ADDR
);
317 OspfMplsTE
.router_addr
.header
.length
= htons (sizeof (ipv4
));
318 OspfMplsTE
.router_addr
.value
= ipv4
;
323 set_linkparams_link_header (struct mpls_te_link
*lp
)
325 struct te_tlv_header
*tlvh
;
326 u_int16_t length
= 0;
328 /* TE_LINK_SUBTLV_LINK_TYPE */
329 if (ntohs (lp
->link_type
.header
.type
) != 0)
330 length
+= TLV_SIZE (&lp
->link_type
.header
);
332 /* TE_LINK_SUBTLV_LINK_ID */
333 if (ntohs (lp
->link_id
.header
.type
) != 0)
334 length
+= TLV_SIZE (&lp
->link_id
.header
);
336 /* TE_LINK_SUBTLV_LCLIF_IPADDR */
337 if ((tlvh
= (struct te_tlv_header
*) lp
->lclif_ipaddr
) != NULL
338 && ntohs (tlvh
->type
) != 0)
339 length
+= TLV_SIZE (tlvh
);
341 /* TE_LINK_SUBTLV_RMTIF_IPADDR */
342 if ((tlvh
= (struct te_tlv_header
*) lp
->rmtif_ipaddr
) != NULL
343 && ntohs (tlvh
->type
) != 0)
344 length
+= TLV_SIZE (tlvh
);
346 /* TE_LINK_SUBTLV_TE_METRIC */
347 if (ntohs (lp
->te_metric
.header
.type
) != 0)
348 length
+= TLV_SIZE (&lp
->te_metric
.header
);
350 /* TE_LINK_SUBTLV_MAX_BW */
351 if (ntohs (lp
->max_bw
.header
.type
) != 0)
352 length
+= TLV_SIZE (&lp
->max_bw
.header
);
354 /* TE_LINK_SUBTLV_MAX_RSV_BW */
355 if (ntohs (lp
->max_rsv_bw
.header
.type
) != 0)
356 length
+= TLV_SIZE (&lp
->max_rsv_bw
.header
);
358 /* TE_LINK_SUBTLV_UNRSV_BW */
359 if (ntohs (lp
->unrsv_bw
.header
.type
) != 0)
360 length
+= TLV_SIZE (&lp
->unrsv_bw
.header
);
362 /* TE_LINK_SUBTLV_RSC_CLSCLR */
363 if (ntohs (lp
->rsc_clsclr
.header
.type
) != 0)
364 length
+= TLV_SIZE (&lp
->rsc_clsclr
.header
);
366 lp
->link_header
.header
.type
= htons (TE_TLV_LINK
);
367 lp
->link_header
.header
.length
= htons (length
);
373 set_linkparams_link_type (struct ospf_interface
*oi
, struct mpls_te_link
*lp
)
375 lp
->link_type
.header
.type
= htons (TE_LINK_SUBTLV_LINK_TYPE
);
376 lp
->link_type
.header
.length
= htons (sizeof (lp
->link_type
.link_type
.value
));
380 case OSPF_IFTYPE_POINTOPOINT
:
381 lp
->link_type
.link_type
.value
= LINK_TYPE_SUBTLV_VALUE_PTP
;
383 case OSPF_IFTYPE_BROADCAST
:
384 case OSPF_IFTYPE_NBMA
:
385 lp
->link_type
.link_type
.value
= LINK_TYPE_SUBTLV_VALUE_MA
;
388 /* Not supported yet. *//* XXX */
389 lp
->link_type
.header
.type
= htons (0);
396 set_linkparams_link_id (struct ospf_interface
*oi
, struct mpls_te_link
*lp
)
398 struct ospf_neighbor
*nbr
;
401 lp
->link_id
.header
.type
= htons (TE_LINK_SUBTLV_LINK_ID
);
402 lp
->link_id
.header
.length
= htons (sizeof (lp
->link_id
.value
));
405 * The Link ID is identical to the contents of the Link ID field
406 * in the Router LSA for these link types.
410 case OSPF_IFTYPE_POINTOPOINT
:
411 /* Take the router ID of the neighbor. */
412 if ((nbr
= ospf_nbr_lookup_ptop (oi
))
413 && nbr
->state
== NSM_Full
)
415 lp
->link_id
.value
= nbr
->router_id
;
419 case OSPF_IFTYPE_BROADCAST
:
420 case OSPF_IFTYPE_NBMA
:
421 /* Take the interface address of the designated router. */
422 if ((nbr
= ospf_nbr_lookup_by_addr (oi
->nbrs
, &DR (oi
))) == NULL
)
425 if (nbr
->state
== NSM_Full
426 || (IPV4_ADDR_SAME (&oi
->address
->u
.prefix4
, &DR (oi
))
427 && ospf_nbr_count (oi
, NSM_Full
) > 0))
429 lp
->link_id
.value
= DR (oi
);
434 /* Not supported yet. *//* XXX */
435 lp
->link_id
.header
.type
= htons (0);
442 masklen2ip (oi
->address
->prefixlen
, &mask
);
443 lp
->link_id
.value
.s_addr
= oi
->address
->u
.prefix4
.s_addr
& mask
.s_addr
;
449 set_linkparams_te_metric (struct mpls_te_link
*lp
, u_int32_t te_metric
)
451 lp
->te_metric
.header
.type
= htons (TE_LINK_SUBTLV_TE_METRIC
);
452 lp
->te_metric
.header
.length
= htons (sizeof (lp
->te_metric
.value
));
453 lp
->te_metric
.value
= htonl (te_metric
);
458 set_linkparams_max_bw (struct mpls_te_link
*lp
, float *fp
)
460 lp
->max_bw
.header
.type
= htons (TE_LINK_SUBTLV_MAX_BW
);
461 lp
->max_bw
.header
.length
= htons (sizeof (lp
->max_bw
.value
));
462 htonf (fp
, &lp
->max_bw
.value
);
467 set_linkparams_max_rsv_bw (struct mpls_te_link
*lp
, float *fp
)
469 lp
->max_rsv_bw
.header
.type
= htons (TE_LINK_SUBTLV_MAX_RSV_BW
);
470 lp
->max_rsv_bw
.header
.length
= htons (sizeof (lp
->max_rsv_bw
.value
));
471 htonf (fp
, &lp
->max_rsv_bw
.value
);
476 set_linkparams_unrsv_bw (struct mpls_te_link
*lp
, int priority
, float *fp
)
478 /* Note that TLV-length field is the size of array. */
479 lp
->unrsv_bw
.header
.type
= htons (TE_LINK_SUBTLV_UNRSV_BW
);
480 lp
->unrsv_bw
.header
.length
= htons (sizeof (lp
->unrsv_bw
.value
));
481 htonf (fp
, &lp
->unrsv_bw
.value
[priority
]);
486 set_linkparams_rsc_clsclr (struct mpls_te_link
*lp
, u_int32_t classcolor
)
488 lp
->rsc_clsclr
.header
.type
= htons (TE_LINK_SUBTLV_RSC_CLSCLR
);
489 lp
->rsc_clsclr
.header
.length
= htons (sizeof (lp
->rsc_clsclr
.value
));
490 lp
->rsc_clsclr
.value
= htonl (classcolor
);
495 initialize_linkparams (struct mpls_te_link
*lp
)
497 struct interface
*ifp
= lp
->ifp
;
498 struct ospf_interface
*oi
;
502 if ((oi
= lookup_oi_by_ifp (ifp
, NULL
, OI_ANY
)) == NULL
)
506 * Try to set initial values those can be derived from
507 * zebra-interface information.
509 set_linkparams_link_type (oi
, lp
);
512 * Linux and *BSD kernel holds bandwidth parameter as an "int" type.
513 * We may have to reconsider, if "ifp->bandwidth" type changes to float.
515 fval
= (float)((ifp
->bandwidth
? ifp
->bandwidth
516 : OSPF_DEFAULT_BANDWIDTH
) * 1000 / 8);
518 set_linkparams_max_bw (lp
, &fval
);
519 set_linkparams_max_rsv_bw (lp
, &fval
);
521 for (i
= 0; i
< 8; i
++)
522 set_linkparams_unrsv_bw (lp
, i
, &fval
);
528 is_mandated_params_set (struct mpls_te_link
*lp
)
532 if (ntohs (OspfMplsTE
.router_addr
.header
.type
) == 0)
535 if (ntohs (lp
->link_type
.header
.type
) == 0)
538 if (ntohs (lp
->link_id
.header
.type
) == 0)
546 /*------------------------------------------------------------------------*
547 * Followings are callback functions against generic Opaque-LSAs handling.
548 *------------------------------------------------------------------------*/
551 ospf_mpls_te_new_if (struct interface
*ifp
)
553 struct mpls_te_link
*new;
556 if (lookup_linkparams_by_ifp (ifp
) != NULL
)
558 zlog_warn ("ospf_mpls_te_new_if: ifp(%p) already in use?", ifp
);
559 rc
= 0; /* Do nothing here. */
563 if ((new = XMALLOC (MTYPE_OSPF_MPLS_TE_LINKPARAMS
,
564 sizeof (struct mpls_te_link
))) == NULL
)
566 zlog_warn ("ospf_mpls_te_new_if: XMALLOC: %s", strerror (errno
));
569 memset (new, 0, sizeof (struct mpls_te_link
));
573 new->instance
= get_mpls_te_instance_value ();
576 initialize_linkparams (new);
578 listnode_add (OspfMplsTE
.iflist
, new);
580 /* Schedule Opaque-LSA refresh. *//* XXX */
588 ospf_mpls_te_del_if (struct interface
*ifp
)
590 struct mpls_te_link
*lp
;
593 if ((lp
= lookup_linkparams_by_ifp (ifp
)) != NULL
)
595 struct list
*iflist
= OspfMplsTE
.iflist
;
597 /* Dequeue listnode entry from the list. */
598 listnode_delete (iflist
, lp
);
600 /* Avoid misjudgement in the next lookup. */
601 if (listcount (iflist
) == 0)
602 iflist
->head
= iflist
->tail
= NULL
;
604 XFREE (MTYPE_OSPF_MPLS_TE_LINKPARAMS
, lp
);
607 /* Schedule Opaque-LSA refresh. *//* XXX */
615 ospf_mpls_te_ism_change (struct ospf_interface
*oi
, int old_state
)
617 struct te_link_subtlv_link_type old_type
;
618 struct te_link_subtlv_link_id old_id
;
619 struct mpls_te_link
*lp
;
621 if ((lp
= lookup_linkparams_by_ifp (oi
->ifp
)) == NULL
)
623 zlog_warn ("ospf_mpls_te_ism_change: Cannot get linkparams from OI(%s)?", IF_NAME (oi
));
626 if (oi
->area
== NULL
|| oi
->area
->ospf
== NULL
)
628 zlog_warn ("ospf_mpls_te_ism_change: Cannot refer to OSPF from OI(%s)?",
633 if ((lp
->area
!= NULL
634 && ! IPV4_ADDR_SAME (&lp
->area
->area_id
, &oi
->area
->area_id
))
635 || (lp
->area
!= NULL
&& oi
->area
== NULL
))
637 /* How should we consider this case? */
638 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");
639 ospf_mpls_te_lsa_schedule (lp
, FLUSH_THIS_LSA
);
642 /* Keep Area information in conbination with linkparams. */
647 case ISM_PointToPoint
:
651 old_type
= lp
->link_type
;
652 old_id
= lp
->link_id
;
654 set_linkparams_link_type (oi
, lp
);
655 set_linkparams_link_id (oi
, lp
);
657 if ((ntohs (old_type
.header
.type
) != ntohs (lp
->link_type
.header
.type
)
658 || old_type
.link_type
.value
!= lp
->link_type
.link_type
.value
)
659 || (ntohs (old_id
.header
.type
) != ntohs (lp
->link_id
.header
.type
)
660 || ntohl (old_id
.value
.s_addr
) != ntohl (lp
->link_id
.value
.s_addr
)))
662 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
663 ospf_mpls_te_lsa_schedule (lp
, REFRESH_THIS_LSA
);
665 ospf_mpls_te_lsa_schedule (lp
, REORIGINATE_PER_AREA
);
669 lp
->link_type
.header
.type
= htons (0);
670 lp
->link_id
.header
.type
= htons (0);
672 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
673 ospf_mpls_te_lsa_schedule (lp
, FLUSH_THIS_LSA
);
682 ospf_mpls_te_nsm_change (struct ospf_neighbor
*nbr
, int old_state
)
684 /* So far, nothing to do here. */
688 /*------------------------------------------------------------------------*
689 * Followings are OSPF protocol processing functions for MPLS-TE.
690 *------------------------------------------------------------------------*/
693 build_tlv_header (struct stream
*s
, struct te_tlv_header
*tlvh
)
695 stream_put (s
, tlvh
, sizeof (struct te_tlv_header
));
700 build_router_tlv (struct stream
*s
)
702 struct te_tlv_header
*tlvh
= &OspfMplsTE
.router_addr
.header
;
703 if (ntohs (tlvh
->type
) != 0)
705 build_tlv_header (s
, tlvh
);
706 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
712 build_link_subtlv_link_type (struct stream
*s
, struct mpls_te_link
*lp
)
714 struct te_tlv_header
*tlvh
= &lp
->link_type
.header
;
715 if (ntohs (tlvh
->type
) != 0)
717 build_tlv_header (s
, tlvh
);
718 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
724 build_link_subtlv_link_id (struct stream
*s
, struct mpls_te_link
*lp
)
726 struct te_tlv_header
*tlvh
= &lp
->link_id
.header
;
727 if (ntohs (tlvh
->type
) != 0)
729 build_tlv_header (s
, tlvh
);
730 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
736 build_link_subtlv_lclif_ipaddr (struct stream
*s
, struct mpls_te_link
*lp
)
738 struct te_tlv_header
*tlvh
= (struct te_tlv_header
*) lp
->lclif_ipaddr
;
739 if (tlvh
!= NULL
&& ntohs (tlvh
->type
) != 0)
741 build_tlv_header (s
, tlvh
);
742 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
748 build_link_subtlv_rmtif_ipaddr (struct stream
*s
, struct mpls_te_link
*lp
)
750 struct te_tlv_header
*tlvh
= (struct te_tlv_header
*) lp
->rmtif_ipaddr
;
751 if (tlvh
!= NULL
&& ntohs (tlvh
->type
) != 0)
753 build_tlv_header (s
, tlvh
);
754 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
760 build_link_subtlv_te_metric (struct stream
*s
, struct mpls_te_link
*lp
)
762 struct te_tlv_header
*tlvh
= &lp
->te_metric
.header
;
763 if (ntohs (tlvh
->type
) != 0)
765 build_tlv_header (s
, tlvh
);
766 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
772 build_link_subtlv_max_bw (struct stream
*s
, struct mpls_te_link
*lp
)
774 struct te_tlv_header
*tlvh
= &lp
->max_bw
.header
;
775 if (ntohs (tlvh
->type
) != 0)
777 build_tlv_header (s
, tlvh
);
778 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
784 build_link_subtlv_max_rsv_bw (struct stream
*s
, struct mpls_te_link
*lp
)
786 struct te_tlv_header
*tlvh
= &lp
->max_rsv_bw
.header
;
787 if (ntohs (tlvh
->type
) != 0)
789 build_tlv_header (s
, tlvh
);
790 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
796 build_link_subtlv_unrsv_bw (struct stream
*s
, struct mpls_te_link
*lp
)
798 struct te_tlv_header
*tlvh
= &lp
->unrsv_bw
.header
;
799 if (ntohs (tlvh
->type
) != 0)
801 build_tlv_header (s
, tlvh
);
802 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
808 build_link_subtlv_rsc_clsclr (struct stream
*s
, struct mpls_te_link
*lp
)
810 struct te_tlv_header
*tlvh
= &lp
->rsc_clsclr
.header
;
811 if (ntohs (tlvh
->type
) != 0)
813 build_tlv_header (s
, tlvh
);
814 stream_put (s
, tlvh
+1, TLV_BODY_SIZE (tlvh
));
820 build_link_tlv (struct stream
*s
, struct mpls_te_link
*lp
)
822 set_linkparams_link_header (lp
);
823 build_tlv_header (s
, &lp
->link_header
.header
);
825 build_link_subtlv_link_type (s
, lp
);
826 build_link_subtlv_link_id (s
, lp
);
827 build_link_subtlv_lclif_ipaddr (s
, lp
);
828 build_link_subtlv_rmtif_ipaddr (s
, lp
);
829 build_link_subtlv_te_metric (s
, lp
);
830 build_link_subtlv_max_bw (s
, lp
);
831 build_link_subtlv_max_rsv_bw (s
, lp
);
832 build_link_subtlv_unrsv_bw (s
, lp
);
833 build_link_subtlv_rsc_clsclr (s
, lp
);
838 ospf_mpls_te_lsa_body_set (struct stream
*s
, struct mpls_te_link
*lp
)
841 * The router address TLV is type 1, and ...
842 * It must appear in exactly one
843 * Traffic Engineering LSA originated by a router.
845 build_router_tlv (s
);
848 * Only one Link TLV shall be carried in each LSA, allowing for fine
849 * granularity changes in topology.
851 build_link_tlv (s
, lp
);
855 /* Create new opaque-LSA. */
856 static struct ospf_lsa
*
857 ospf_mpls_te_lsa_new (struct ospf_area
*area
, struct mpls_te_link
*lp
)
860 struct lsa_header
*lsah
;
861 struct ospf_lsa
*new = NULL
;
862 u_char options
, lsa_type
;
863 struct in_addr lsa_id
;
867 /* Create a stream for LSA. */
868 if ((s
= stream_new (OSPF_MAX_LSA_SIZE
)) == NULL
)
870 zlog_warn ("ospf_mpls_te_lsa_new: stream_new() ?");
873 lsah
= (struct lsa_header
*) STREAM_DATA (s
);
875 options
= LSA_OPTIONS_GET (area
);
876 options
|= LSA_OPTIONS_NSSA_GET (area
);
877 options
|= OSPF_OPTION_O
; /* Don't forget this :-) */
879 lsa_type
= OSPF_OPAQUE_AREA_LSA
;
880 tmp
= SET_OPAQUE_LSID (OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA
, lp
->instance
);
881 lsa_id
.s_addr
= htonl (tmp
);
883 if (IS_DEBUG_OSPF (lsa
, LSA_GENERATE
))
884 zlog_info ("LSA[Type%d:%s]: Create an Opaque-LSA/MPLS-TE instance", lsa_type
, inet_ntoa (lsa_id
));
886 /* Set opaque-LSA header fields. */
887 lsa_header_set (s
, options
, lsa_type
, lsa_id
, area
->ospf
->router_id
);
889 /* Set opaque-LSA body fields. */
890 ospf_mpls_te_lsa_body_set (s
, lp
);
893 length
= stream_get_endp (s
);
894 lsah
->length
= htons (length
);
896 /* Now, create an OSPF LSA instance. */
897 if ((new = ospf_lsa_new ()) == NULL
)
899 zlog_warn ("ospf_mpls_te_lsa_new: ospf_lsa_new() ?");
903 if ((new->data
= ospf_lsa_data_new (length
)) == NULL
)
905 zlog_warn ("ospf_mpls_te_lsa_new: ospf_lsa_data_new() ?");
906 ospf_lsa_unlock (new);
913 SET_FLAG (new->flags
, OSPF_LSA_SELF
);
914 memcpy (new->data
, lsah
, length
);
922 ospf_mpls_te_lsa_originate1 (struct ospf_area
*area
, struct mpls_te_link
*lp
)
924 struct ospf_lsa
*new;
927 /* Create new Opaque-LSA/MPLS-TE instance. */
928 if ((new = ospf_mpls_te_lsa_new (area
, lp
)) == NULL
)
930 zlog_warn ("ospf_mpls_te_lsa_originate1: ospf_mpls_te_lsa_new() ?");
934 /* Install this LSA into LSDB. */
935 if (ospf_lsa_install (area
->ospf
, NULL
/*oi*/, new) == NULL
)
937 zlog_warn ("ospf_mpls_te_lsa_originate1: ospf_lsa_install() ?");
938 ospf_lsa_unlock (new);
942 /* Now this linkparameter entry has associated LSA. */
943 lp
->flags
|= LPFLG_LSA_ENGAGED
;
945 /* Update new LSA origination count. */
946 area
->ospf
->lsa_originate_count
++;
948 /* Flood new LSA through area. */
949 ospf_flood_through_area (area
, NULL
/*nbr*/, new);
951 if (IS_DEBUG_OSPF (lsa
, LSA_GENERATE
))
953 char area_id
[INET_ADDRSTRLEN
];
954 strcpy (area_id
, inet_ntoa (area
->area_id
));
955 zlog_info ("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
);
956 ospf_lsa_header_dump (new->data
);
965 ospf_mpls_te_lsa_originate (void *arg
)
967 struct ospf_area
*area
= (struct ospf_area
*) arg
;
968 struct listnode
*node
;
969 struct mpls_te_link
*lp
;
972 if (OspfMplsTE
.status
== disabled
)
974 zlog_info ("ospf_mpls_te_lsa_originate: MPLS-TE is disabled now.");
975 rc
= 0; /* This is not an error case. */
979 for (node
= listhead (OspfMplsTE
.iflist
); node
; nextnode (node
))
981 if ((lp
= getdata (node
)) == NULL
)
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)
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
))
1040 lp
->flags
&= ~LPFLG_LSA_ENGAGED
;
1041 ospf_opaque_lsa_flush_schedule (lsa
);
1045 /* Create new Opaque-LSA/MPLS-TE instance. */
1046 if ((new = ospf_mpls_te_lsa_new (area
, lp
)) == NULL
)
1048 zlog_warn ("ospf_mpls_te_lsa_refresh: ospf_mpls_te_lsa_new() ?");
1051 new->data
->ls_seqnum
= lsa_seqnum_increment (lsa
);
1053 /* Install this LSA into LSDB. */
1054 /* Given "lsa" will be freed in the next function. */
1055 if (ospf_lsa_install (area
->ospf
, NULL
/*oi*/, new) == NULL
)
1057 zlog_warn ("ospf_mpls_te_lsa_refresh: ospf_lsa_install() ?");
1058 ospf_lsa_unlock (new);
1062 /* Flood updated LSA through area. */
1063 ospf_flood_through_area (area
, NULL
/*nbr*/, new);
1065 /* Debug logging. */
1066 if (IS_DEBUG_OSPF (lsa
, LSA_GENERATE
))
1068 zlog_info ("LSA[Type%d:%s]: Refresh Opaque-LSA/MPLS-TE",
1069 new->data
->type
, inet_ntoa (new->data
->id
));
1070 ospf_lsa_header_dump (new->data
);
1078 ospf_mpls_te_lsa_schedule (struct mpls_te_link
*lp
,
1079 enum sched_opcode opcode
)
1081 struct ospf_lsa lsa
;
1082 struct lsa_header lsah
;
1085 memset (&lsa
, 0, sizeof (lsa
));
1086 memset (&lsah
, 0, sizeof (lsah
));
1088 lsa
.area
= lp
->area
;
1090 lsah
.type
= OSPF_OPAQUE_AREA_LSA
;
1091 tmp
= SET_OPAQUE_LSID (OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA
, lp
->instance
);
1092 lsah
.id
.s_addr
= htonl (tmp
);
1096 case REORIGINATE_PER_AREA
:
1097 ospf_opaque_lsa_reoriginate_schedule ((void *) lp
->area
,
1098 OSPF_OPAQUE_AREA_LSA
, OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA
);
1100 case REFRESH_THIS_LSA
:
1101 ospf_opaque_lsa_refresh_schedule (&lsa
);
1103 case FLUSH_THIS_LSA
:
1104 lp
->flags
&= ~LPFLG_LSA_ENGAGED
;
1105 ospf_opaque_lsa_flush_schedule (&lsa
);
1108 zlog_warn ("ospf_mpls_te_lsa_schedule: Unknown opcode (%u)", opcode
);
1115 /*------------------------------------------------------------------------*
1116 * Followings are vty session control functions.
1117 *------------------------------------------------------------------------*/
1120 show_vty_router_addr (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1122 struct te_tlv_router_addr
*top
= (struct te_tlv_router_addr
*) tlvh
;
1125 vty_out (vty
, " Router-Address: %s%s", inet_ntoa (top
->value
), VTY_NEWLINE
);
1127 zlog_info (" Router-Address: %s", inet_ntoa (top
->value
));
1129 return TLV_SIZE (tlvh
);
1133 show_vty_link_header (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1135 struct te_tlv_link
*top
= (struct te_tlv_link
*) tlvh
;
1138 vty_out (vty
, " Link: %u octets of data%s", ntohs (top
->header
.length
), VTY_NEWLINE
);
1140 zlog_info (" Link: %u octets of data", ntohs (top
->header
.length
));
1142 return TLV_HDR_SIZE
; /* Here is special, not "TLV_SIZE". */
1146 show_vty_link_subtlv_link_type (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1148 struct te_link_subtlv_link_type
*top
;
1149 const char *cp
= "Unknown";
1151 top
= (struct te_link_subtlv_link_type
*) tlvh
;
1152 switch (top
->link_type
.value
)
1154 case LINK_TYPE_SUBTLV_VALUE_PTP
:
1155 cp
= "Point-to-point";
1157 case LINK_TYPE_SUBTLV_VALUE_MA
:
1165 vty_out (vty
, " Link-Type: %s (%u)%s", cp
, top
->link_type
.value
, VTY_NEWLINE
);
1167 zlog_info (" Link-Type: %s (%u)", cp
, top
->link_type
.value
);
1169 return TLV_SIZE (tlvh
);
1173 show_vty_link_subtlv_link_id (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1175 struct te_link_subtlv_link_id
*top
;
1177 top
= (struct te_link_subtlv_link_id
*) tlvh
;
1179 vty_out (vty
, " Link-ID: %s%s", inet_ntoa (top
->value
), VTY_NEWLINE
);
1181 zlog_info (" Link-ID: %s", inet_ntoa (top
->value
));
1183 return TLV_SIZE (tlvh
);
1187 show_vty_link_subtlv_lclif_ipaddr (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1189 struct te_link_subtlv_lclif_ipaddr
*top
;
1192 top
= (struct te_link_subtlv_lclif_ipaddr
*) tlvh
;
1193 n
= ntohs (tlvh
->length
) / sizeof (top
->value
[0]);
1196 vty_out (vty
, " Local Interface IP Address(es): %d%s", n
, VTY_NEWLINE
);
1198 zlog_info (" Local Interface IP Address(es): %d", n
);
1200 for (i
= 0; i
< n
; i
++)
1203 vty_out (vty
, " #%d: %s%s", i
, inet_ntoa (top
->value
[i
]), VTY_NEWLINE
);
1205 zlog_info (" #%d: %s", i
, inet_ntoa (top
->value
[i
]));
1207 return TLV_SIZE (tlvh
);
1211 show_vty_link_subtlv_rmtif_ipaddr (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1213 struct te_link_subtlv_rmtif_ipaddr
*top
;
1216 top
= (struct te_link_subtlv_rmtif_ipaddr
*) tlvh
;
1217 n
= ntohs (tlvh
->length
) / sizeof (top
->value
[0]);
1219 vty_out (vty
, " Remote Interface IP Address(es): %d%s", n
, VTY_NEWLINE
);
1221 zlog_info (" Remote Interface IP Address(es): %d", n
);
1223 for (i
= 0; i
< n
; i
++)
1226 vty_out (vty
, " #%d: %s%s", i
, inet_ntoa (top
->value
[i
]), VTY_NEWLINE
);
1228 zlog_info (" #%d: %s", i
, inet_ntoa (top
->value
[i
]));
1230 return TLV_SIZE (tlvh
);
1234 show_vty_link_subtlv_te_metric (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1236 struct te_link_subtlv_te_metric
*top
;
1238 top
= (struct te_link_subtlv_te_metric
*) tlvh
;
1240 vty_out (vty
, " Traffic Engineering Metric: %u%s", (u_int32_t
) ntohl (top
->value
), VTY_NEWLINE
);
1242 zlog_info (" Traffic Engineering Metric: %u", (u_int32_t
) ntohl (top
->value
));
1244 return TLV_SIZE (tlvh
);
1248 show_vty_link_subtlv_max_bw (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1250 struct te_link_subtlv_max_bw
*top
;
1253 top
= (struct te_link_subtlv_max_bw
*) tlvh
;
1254 ntohf (&top
->value
, &fval
);
1257 vty_out (vty
, " Maximum Bandwidth: %g (Bytes/sec)%s", fval
, VTY_NEWLINE
);
1259 zlog_info (" Maximum Bandwidth: %g (Bytes/sec)", fval
);
1261 return TLV_SIZE (tlvh
);
1265 show_vty_link_subtlv_max_rsv_bw (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1267 struct te_link_subtlv_max_rsv_bw
*top
;
1270 top
= (struct te_link_subtlv_max_rsv_bw
*) tlvh
;
1271 ntohf (&top
->value
, &fval
);
1274 vty_out (vty
, " Maximum Reservable Bandwidth: %g (Bytes/sec)%s", fval
, VTY_NEWLINE
);
1276 zlog_info (" Maximum Reservable Bandwidth: %g (Bytes/sec)", fval
);
1278 return TLV_SIZE (tlvh
);
1282 show_vty_link_subtlv_unrsv_bw (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1284 struct te_link_subtlv_unrsv_bw
*top
;
1288 top
= (struct te_link_subtlv_unrsv_bw
*) tlvh
;
1289 for (i
= 0; i
< 8; i
++)
1291 ntohf (&top
->value
[i
], &fval
);
1293 vty_out (vty
, " Unreserved Bandwidth (pri %d): %g (Bytes/sec)%s", i
, fval
, VTY_NEWLINE
);
1295 zlog_info (" Unreserved Bandwidth (pri %d): %g (Bytes/sec)", i
, fval
);
1298 return TLV_SIZE (tlvh
);
1302 show_vty_link_subtlv_rsc_clsclr (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1304 struct te_link_subtlv_rsc_clsclr
*top
;
1306 top
= (struct te_link_subtlv_rsc_clsclr
*) tlvh
;
1308 vty_out (vty
, " Resource class/color: 0x%x%s", (u_int32_t
) ntohl (top
->value
), VTY_NEWLINE
);
1310 zlog_info (" Resource Class/Color: 0x%x", (u_int32_t
) ntohl (top
->value
));
1312 return TLV_SIZE (tlvh
);
1316 show_vty_unknown_tlv (struct vty
*vty
, struct te_tlv_header
*tlvh
)
1319 vty_out (vty
, " Unknown TLV: [type(0x%x), length(0x%x)]%s", ntohs (tlvh
->type
), ntohs (tlvh
->length
), VTY_NEWLINE
);
1321 zlog_info (" Unknown TLV: [type(0x%x), length(0x%x)]", ntohs (tlvh
->type
), ntohs (tlvh
->length
));
1323 return TLV_SIZE (tlvh
);
1327 ospf_mpls_te_show_link_subtlv (struct vty
*vty
, struct te_tlv_header
*tlvh0
,
1328 u_int16_t subtotal
, u_int16_t total
)
1330 struct te_tlv_header
*tlvh
, *next
;
1331 u_int16_t sum
= subtotal
;
1333 for (tlvh
= tlvh0
; sum
< total
; tlvh
= (next
? next
: TLV_HDR_NEXT (tlvh
)))
1336 switch (ntohs (tlvh
->type
))
1338 case TE_LINK_SUBTLV_LINK_TYPE
:
1339 sum
+= show_vty_link_subtlv_link_type (vty
, tlvh
);
1341 case TE_LINK_SUBTLV_LINK_ID
:
1342 sum
+= show_vty_link_subtlv_link_id (vty
, tlvh
);
1344 case TE_LINK_SUBTLV_LCLIF_IPADDR
:
1345 sum
+= show_vty_link_subtlv_lclif_ipaddr (vty
, tlvh
);
1347 case TE_LINK_SUBTLV_RMTIF_IPADDR
:
1348 sum
+= show_vty_link_subtlv_rmtif_ipaddr (vty
, tlvh
);
1350 case TE_LINK_SUBTLV_TE_METRIC
:
1351 sum
+= show_vty_link_subtlv_te_metric (vty
, tlvh
);
1353 case TE_LINK_SUBTLV_MAX_BW
:
1354 sum
+= show_vty_link_subtlv_max_bw (vty
, tlvh
);
1356 case TE_LINK_SUBTLV_MAX_RSV_BW
:
1357 sum
+= show_vty_link_subtlv_max_rsv_bw (vty
, tlvh
);
1359 case TE_LINK_SUBTLV_UNRSV_BW
:
1360 sum
+= show_vty_link_subtlv_unrsv_bw (vty
, tlvh
);
1362 case TE_LINK_SUBTLV_RSC_CLSCLR
:
1363 sum
+= show_vty_link_subtlv_rsc_clsclr (vty
, tlvh
);
1366 sum
+= show_vty_unknown_tlv (vty
, tlvh
);
1374 ospf_mpls_te_show_info (struct vty
*vty
, struct ospf_lsa
*lsa
)
1376 struct lsa_header
*lsah
= (struct lsa_header
*) lsa
->data
;
1377 struct te_tlv_header
*tlvh
, *next
;
1378 u_int16_t sum
, total
;
1379 u_int16_t (* subfunc
)(struct vty
*vty
, struct te_tlv_header
*tlvh
,
1380 u_int16_t subtotal
, u_int16_t total
) = NULL
;
1383 total
= ntohs (lsah
->length
) - OSPF_LSA_HEADER_SIZE
;
1385 for (tlvh
= TLV_HDR_TOP (lsah
); sum
< total
;
1386 tlvh
= (next
? next
: TLV_HDR_NEXT (tlvh
)))
1388 if (subfunc
!= NULL
)
1390 sum
= (* subfunc
)(vty
, tlvh
, sum
, total
);
1391 next
= (struct te_tlv_header
*)((char *) tlvh
+ sum
);
1397 switch (ntohs (tlvh
->type
))
1399 case TE_TLV_ROUTER_ADDR
:
1400 sum
+= show_vty_router_addr (vty
, tlvh
);
1403 sum
+= show_vty_link_header (vty
, tlvh
);
1404 subfunc
= ospf_mpls_te_show_link_subtlv
;
1408 sum
+= show_vty_unknown_tlv (vty
, tlvh
);
1416 ospf_mpls_te_config_write_router (struct vty
*vty
)
1418 if (OspfMplsTE
.status
== enabled
)
1420 vty_out (vty
, " mpls-te%s", VTY_NEWLINE
);
1421 vty_out (vty
, " mpls-te router-address %s%s",
1422 inet_ntoa (OspfMplsTE
.router_addr
.value
), VTY_NEWLINE
);
1428 ospf_mpls_te_config_write_if (struct vty
*vty
, struct interface
*ifp
)
1430 struct mpls_te_link
*lp
;
1432 if ((OspfMplsTE
.status
== enabled
)
1433 && (! if_is_loopback (ifp
) && if_is_up (ifp
) && ospf_oi_count (ifp
) > 0)
1434 && ((lp
= lookup_linkparams_by_ifp (ifp
)) != NULL
))
1439 vty_out (vty
, " mpls-te link metric %u%s",
1440 (u_int32_t
) ntohl (lp
->te_metric
.value
), VTY_NEWLINE
);
1442 ntohf (&lp
->max_bw
.value
, &fval
);
1443 if (fval
>= MPLS_TE_MINIMUM_BANDWIDTH
)
1444 vty_out (vty
, " mpls-te link max-bw %g%s", fval
, VTY_NEWLINE
);
1446 ntohf (&lp
->max_rsv_bw
.value
, &fval
);
1447 if (fval
>= MPLS_TE_MINIMUM_BANDWIDTH
)
1448 vty_out (vty
, " mpls-te link max-rsv-bw %g%s", fval
, VTY_NEWLINE
);
1450 for (i
= 0; i
< 8; i
++)
1452 ntohf (&lp
->unrsv_bw
.value
[i
], &fval
);
1453 if (fval
>= MPLS_TE_MINIMUM_BANDWIDTH
)
1454 vty_out (vty
, " mpls-te link unrsv-bw %d %g%s",
1455 i
, fval
, VTY_NEWLINE
);
1458 vty_out (vty
, " mpls-te link rsc-clsclr 0x%x%s",
1459 (u_int32_t
) ntohl (lp
->rsc_clsclr
.value
), VTY_NEWLINE
);
1464 /*------------------------------------------------------------------------*
1465 * Followings are vty command functions.
1466 *------------------------------------------------------------------------*/
1471 "Configure MPLS-TE parameters\n"
1472 "Enable the MPLS-TE functionality\n")
1474 struct listnode
*node
;
1475 struct mpls_te_link
*lp
;
1477 if (OspfMplsTE
.status
== enabled
)
1480 if (IS_DEBUG_OSPF_EVENT
)
1481 zlog_info ("MPLS-TE: OFF -> ON");
1483 OspfMplsTE
.status
= enabled
;
1486 * Following code is intended to handle two cases;
1488 * 1) MPLS-TE was disabled at startup time, but now become enabled.
1489 * 2) MPLS-TE was once enabled then disabled, and now enabled again.
1491 for (node
= listhead (OspfMplsTE
.iflist
); node
; nextnode (node
))
1492 if ((lp
= getdata (node
)) != NULL
)
1493 initialize_linkparams (lp
);
1495 ospf_mpls_te_foreach_area (ospf_mpls_te_lsa_schedule
, REORIGINATE_PER_AREA
);
1503 "Configure MPLS-TE parameters\n"
1504 "Enable the MPLS-TE functionality\n")
1510 "Configure MPLS-TE parameters\n"
1511 "Disable the MPLS-TE functionality\n")
1513 struct listnode
*node
;
1514 struct mpls_te_link
*lp
;
1516 if (OspfMplsTE
.status
== disabled
)
1519 if (IS_DEBUG_OSPF_EVENT
)
1520 zlog_info ("MPLS-TE: ON -> OFF");
1522 OspfMplsTE
.status
= disabled
;
1524 for (node
= listhead (OspfMplsTE
.iflist
); node
; nextnode (node
))
1525 if ((lp
= getdata (node
)) != NULL
)
1526 if (lp
->area
!= NULL
)
1527 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
1528 ospf_mpls_te_lsa_schedule (lp
, FLUSH_THIS_LSA
);
1533 DEFUN (mpls_te_router_addr
,
1534 mpls_te_router_addr_cmd
,
1535 "mpls-te router-address A.B.C.D",
1536 "MPLS-TE specific commands\n"
1537 "Stable IP address of the advertising router\n"
1538 "MPLS-TE router address in IPv4 address format\n")
1540 struct te_tlv_router_addr
*ra
= &OspfMplsTE
.router_addr
;
1541 struct in_addr value
;
1543 if (! inet_aton (argv
[0], &value
))
1545 vty_out (vty
, "Please specify Router-Addr by A.B.C.D%s", VTY_NEWLINE
);
1549 if (ntohs (ra
->header
.type
) == 0
1550 || ntohl (ra
->value
.s_addr
) != ntohl (value
.s_addr
))
1552 struct listnode
*node
;
1553 struct mpls_te_link
*lp
;
1554 int need_to_reoriginate
= 0;
1556 set_mpls_te_router_addr (value
);
1558 if (OspfMplsTE
.status
== disabled
)
1561 LIST_LOOP (OspfMplsTE
.iflist
, lp
, node
)
1563 if (lp
->area
== NULL
)
1566 if ((lp
->flags
& LPFLG_LSA_ENGAGED
) == 0)
1568 need_to_reoriginate
= 1;
1572 for (node
= listhead (OspfMplsTE
.iflist
); node
; nextnode (node
))
1573 LIST_LOOP (OspfMplsTE
.iflist
, lp
, node
)
1575 if (lp
->area
== NULL
)
1578 if (need_to_reoriginate
)
1579 lp
->flags
|= LPFLG_LSA_FORCED_REFRESH
;
1581 ospf_mpls_te_lsa_schedule (lp
, REFRESH_THIS_LSA
);
1584 if (need_to_reoriginate
)
1585 ospf_mpls_te_foreach_area (
1586 ospf_mpls_te_lsa_schedule
, REORIGINATE_PER_AREA
);
1592 DEFUN (mpls_te_link_metric
,
1593 mpls_te_link_metric_cmd
,
1594 "mpls-te link metric <0-4294967295>",
1595 "MPLS-TE specific commands\n"
1596 "Configure MPLS-TE link parameters\n"
1597 "Link metric for MPLS-TE purpose\n"
1600 struct interface
*ifp
= (struct interface
*) vty
->index
;
1601 struct mpls_te_link
*lp
;
1604 if ((lp
= lookup_linkparams_by_ifp (ifp
)) == NULL
)
1606 vty_out (vty
, "mpls_te_link_metric: Something wrong!%s", VTY_NEWLINE
);
1610 value
= strtoul (argv
[0], NULL
, 10);
1612 if (ntohs (lp
->te_metric
.header
.type
) == 0
1613 || ntohl (lp
->te_metric
.value
) != value
)
1615 set_linkparams_te_metric (lp
, value
);
1617 if (OspfMplsTE
.status
== enabled
)
1618 if (lp
->area
!= NULL
)
1620 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
1621 ospf_mpls_te_lsa_schedule (lp
, REFRESH_THIS_LSA
);
1623 ospf_mpls_te_lsa_schedule (lp
, REORIGINATE_PER_AREA
);
1629 DEFUN (mpls_te_link_maxbw
,
1630 mpls_te_link_maxbw_cmd
,
1631 "mpls-te link max-bw BANDWIDTH",
1632 "MPLS-TE specific commands\n"
1633 "Configure MPLS-TE link parameters\n"
1634 "Maximum bandwidth that can be used\n"
1635 "Bytes/second (IEEE floating point format)\n")
1637 struct interface
*ifp
= (struct interface
*) vty
->index
;
1638 struct mpls_te_link
*lp
;
1641 if ((lp
= lookup_linkparams_by_ifp (ifp
)) == NULL
)
1643 vty_out (vty
, "mpls_te_link_maxbw: Something wrong!%s", VTY_NEWLINE
);
1647 ntohf (&lp
->max_bw
.value
, &f1
);
1648 if (sscanf (argv
[0], "%g", &f2
) != 1)
1650 vty_out (vty
, "mpls_te_link_maxbw: fscanf: %s%s", strerror (errno
), VTY_NEWLINE
);
1654 if (ntohs (lp
->max_bw
.header
.type
) == 0
1657 set_linkparams_max_bw (lp
, &f2
);
1659 if (OspfMplsTE
.status
== enabled
)
1660 if (lp
->area
!= NULL
)
1662 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
1663 ospf_mpls_te_lsa_schedule (lp
, REFRESH_THIS_LSA
);
1665 ospf_mpls_te_lsa_schedule (lp
, REORIGINATE_PER_AREA
);
1671 DEFUN (mpls_te_link_max_rsv_bw
,
1672 mpls_te_link_max_rsv_bw_cmd
,
1673 "mpls-te link max-rsv-bw BANDWIDTH",
1674 "MPLS-TE specific commands\n"
1675 "Configure MPLS-TE link parameters\n"
1676 "Maximum bandwidth that may be reserved\n"
1677 "Bytes/second (IEEE floating point format)\n")
1679 struct interface
*ifp
= (struct interface
*) vty
->index
;
1680 struct mpls_te_link
*lp
;
1683 if ((lp
= lookup_linkparams_by_ifp (ifp
)) == NULL
)
1685 vty_out (vty
, "mpls_te_link_max_rsv_bw: Something wrong!%s", VTY_NEWLINE
);
1689 ntohf (&lp
->max_rsv_bw
.value
, &f1
);
1690 if (sscanf (argv
[0], "%g", &f2
) != 1)
1692 vty_out (vty
, "mpls_te_link_max_rsv_bw: fscanf: %s%s", strerror (errno
), VTY_NEWLINE
);
1696 if (ntohs (lp
->max_rsv_bw
.header
.type
) == 0
1699 set_linkparams_max_rsv_bw (lp
, &f2
);
1701 if (OspfMplsTE
.status
== enabled
)
1702 if (lp
->area
!= NULL
)
1704 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
1705 ospf_mpls_te_lsa_schedule (lp
, REFRESH_THIS_LSA
);
1707 ospf_mpls_te_lsa_schedule (lp
, REORIGINATE_PER_AREA
);
1713 DEFUN (mpls_te_link_unrsv_bw
,
1714 mpls_te_link_unrsv_bw_cmd
,
1715 "mpls-te link unrsv-bw <0-7> BANDWIDTH",
1716 "MPLS-TE specific commands\n"
1717 "Configure MPLS-TE link parameters\n"
1718 "Unreserved bandwidth at each priority level\n"
1720 "Bytes/second (IEEE floating point format)\n")
1722 struct interface
*ifp
= (struct interface
*) vty
->index
;
1723 struct mpls_te_link
*lp
;
1727 if ((lp
= lookup_linkparams_by_ifp (ifp
)) == NULL
)
1729 vty_out (vty
, "mpls_te_link_unrsv_bw: Something wrong!%s", VTY_NEWLINE
);
1733 /* We don't have to consider about range check here. */
1734 if (sscanf (argv
[0], "%d", &priority
) != 1)
1736 vty_out (vty
, "mpls_te_link_unrsv_bw: fscanf: %s%s", strerror (errno
), VTY_NEWLINE
);
1740 ntohf (&lp
->unrsv_bw
.value
[priority
], &f1
);
1741 if (sscanf (argv
[1], "%g", &f2
) != 1)
1743 vty_out (vty
, "mpls_te_link_unrsv_bw: fscanf: %s%s", strerror (errno
), VTY_NEWLINE
);
1747 if (ntohs (lp
->unrsv_bw
.header
.type
) == 0
1750 set_linkparams_unrsv_bw (lp
, priority
, &f2
);
1752 if (OspfMplsTE
.status
== enabled
)
1753 if (lp
->area
!= NULL
)
1755 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
1756 ospf_mpls_te_lsa_schedule (lp
, REFRESH_THIS_LSA
);
1758 ospf_mpls_te_lsa_schedule (lp
, REORIGINATE_PER_AREA
);
1764 DEFUN (mpls_te_link_rsc_clsclr
,
1765 mpls_te_link_rsc_clsclr_cmd
,
1766 "mpls-te link rsc-clsclr BITPATTERN",
1767 "MPLS-TE specific commands\n"
1768 "Configure MPLS-TE link parameters\n"
1769 "Administrative group membership\n"
1770 "32-bit Hexadecimal value (ex. 0xa1)\n")
1772 struct interface
*ifp
= (struct interface
*) vty
->index
;
1773 struct mpls_te_link
*lp
;
1774 unsigned long value
;
1776 if ((lp
= lookup_linkparams_by_ifp (ifp
)) == NULL
)
1778 vty_out (vty
, "mpls_te_link_rsc_clsclr: Something wrong!%s", VTY_NEWLINE
);
1782 if (sscanf (argv
[0], "0x%lx", &value
) != 1)
1784 vty_out (vty
, "mpls_te_link_rsc_clsclr: fscanf: %s%s", strerror (errno
), VTY_NEWLINE
);
1788 if (ntohs (lp
->rsc_clsclr
.header
.type
) == 0
1789 || ntohl (lp
->rsc_clsclr
.value
) != value
)
1791 set_linkparams_rsc_clsclr (lp
, value
);
1793 if (OspfMplsTE
.status
== enabled
)
1794 if (lp
->area
!= NULL
)
1796 if (lp
->flags
& LPFLG_LSA_ENGAGED
)
1797 ospf_mpls_te_lsa_schedule (lp
, REFRESH_THIS_LSA
);
1799 ospf_mpls_te_lsa_schedule (lp
, REORIGINATE_PER_AREA
);
1805 DEFUN (show_mpls_te_router
,
1806 show_mpls_te_router_cmd
,
1807 "show mpls-te router",
1809 "MPLS-TE information\n"
1810 "Router information\n")
1812 if (OspfMplsTE
.status
== enabled
)
1814 vty_out (vty
, "--- MPLS-TE router parameters ---%s",
1817 if (ntohs (OspfMplsTE
.router_addr
.header
.type
) != 0)
1818 show_vty_router_addr (vty
, &OspfMplsTE
.router_addr
.header
);
1819 else if (vty
!= NULL
)
1820 vty_out (vty
, " N/A%s", VTY_NEWLINE
);
1826 show_mpls_te_link_sub (struct vty
*vty
, struct interface
*ifp
)
1828 struct mpls_te_link
*lp
;
1829 struct te_tlv_header
*tlvh
;
1831 if ((OspfMplsTE
.status
== enabled
)
1832 && (! if_is_loopback (ifp
) && if_is_up (ifp
) && ospf_oi_count (ifp
) > 0)
1833 && ((lp
= lookup_linkparams_by_ifp (ifp
)) != NULL
))
1835 vty_out (vty
, "-- MPLS-TE link parameters for %s --%s",
1836 ifp
->name
, VTY_NEWLINE
);
1838 show_vty_link_subtlv_link_type (vty
, &lp
->link_type
.header
);
1839 show_vty_link_subtlv_link_id (vty
, &lp
->link_id
.header
);
1841 if ((tlvh
= (struct te_tlv_header
*) lp
->lclif_ipaddr
) != NULL
)
1842 show_vty_link_subtlv_lclif_ipaddr (vty
, tlvh
);
1843 if ((tlvh
= (struct te_tlv_header
*) lp
->rmtif_ipaddr
) != NULL
)
1844 show_vty_link_subtlv_rmtif_ipaddr (vty
, tlvh
);
1846 show_vty_link_subtlv_te_metric (vty
, &lp
->te_metric
.header
);
1848 show_vty_link_subtlv_max_bw (vty
, &lp
->max_bw
.header
);
1849 show_vty_link_subtlv_max_rsv_bw (vty
, &lp
->max_rsv_bw
.header
);
1850 show_vty_link_subtlv_unrsv_bw (vty
, &lp
->unrsv_bw
.header
);
1851 show_vty_link_subtlv_rsc_clsclr (vty
, &lp
->rsc_clsclr
.header
);
1855 vty_out (vty
, " %s: MPLS-TE is disabled on this interface%s",
1856 ifp
->name
, VTY_NEWLINE
);
1862 DEFUN (show_mpls_te_link
,
1863 show_mpls_te_link_cmd
,
1864 "show mpls-te interface [INTERFACE]",
1866 "MPLS-TE information\n"
1867 "Interface information\n"
1870 struct interface
*ifp
;
1871 struct listnode
*node
;
1873 /* Show All Interfaces. */
1876 LIST_LOOP (iflist
, ifp
, node
)
1877 show_mpls_te_link_sub (vty
, ifp
);
1879 /* Interface name is specified. */
1882 if ((ifp
= if_lookup_by_name (argv
[0])) == NULL
)
1883 vty_out (vty
, "No such interface name%s", VTY_NEWLINE
);
1885 show_mpls_te_link_sub (vty
, ifp
);
1892 ospf_mpls_te_register_vty (void)
1894 install_element (VIEW_NODE
, &show_mpls_te_router_cmd
);
1895 install_element (VIEW_NODE
, &show_mpls_te_link_cmd
);
1896 install_element (ENABLE_NODE
, &show_mpls_te_router_cmd
);
1897 install_element (ENABLE_NODE
, &show_mpls_te_link_cmd
);
1899 install_element (OSPF_NODE
, &mpls_te_cmd
);
1900 install_element (OSPF_NODE
, &no_mpls_te_cmd
);
1901 install_element (OSPF_NODE
, &mpls_te_on_cmd
);
1902 install_element (OSPF_NODE
, &mpls_te_router_addr_cmd
);
1904 install_element (INTERFACE_NODE
, &mpls_te_link_metric_cmd
);
1905 install_element (INTERFACE_NODE
, &mpls_te_link_maxbw_cmd
);
1906 install_element (INTERFACE_NODE
, &mpls_te_link_max_rsv_bw_cmd
);
1907 install_element (INTERFACE_NODE
, &mpls_te_link_unrsv_bw_cmd
);
1908 install_element (INTERFACE_NODE
, &mpls_te_link_rsc_clsclr_cmd
);
1913 #endif /* HAVE_OSPF_TE */