]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_te.c
2004-12-08 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
[mirror_frr.git] / ospfd / ospf_te.c
CommitLineData
718e3744 1/*
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/
5 *
6 * This file is part of GNU Zebra.
7 *
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
11 * later version.
12 *
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.
17 *
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
21 * 02111-1307, USA.
22 */
23
24/***** MTYPE definition is not reflected to "memory.h" yet. *****/
25#define MTYPE_OSPF_MPLS_TE_LINKPARAMS 0
26
27#include <zebra.h>
28
29#ifdef HAVE_OSPF_TE
30#ifndef HAVE_OPAQUE_LSA
31#error "Wrong configure option"
32#endif /* HAVE_OPAQUE_LSA */
33
34#include "linklist.h"
35#include "prefix.h"
36#include "if.h"
37#include "table.h"
38#include "memory.h"
39#include "command.h"
40#include "vty.h"
41#include "stream.h"
42#include "log.h"
43#include "thread.h"
44#include "hash.h"
45#include "sockunion.h" /* for inet_aton() */
46
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"
63
64/* Following structure are internal use only. */
65struct ospf_mpls_te
66{
67 enum { disabled, enabled } status;
68
69 /* List elements are zebra-interfaces (ifp), not ospf-interfaces (oi). */
87d6f87a 70 struct list *iflist;
718e3744 71
72 /* Store Router-TLV in network byte order. */
73 struct te_tlv_router_addr router_addr;
74};
75
76struct mpls_te_link
77{
78 /*
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.
82 */
83 u_int32_t instance;
84
85 /* Reference pointer to a Zebra-interface. */
86 struct interface *ifp;
87
88 /* Area info in which this MPLS-TE link belongs to. */
89 struct ospf_area *area;
90
91 /* Flags to manage this link parameters. */
92 u_int32_t flags;
93#define LPFLG_LOOKUP_DONE 0x1
94#define LPFLG_LSA_ENGAGED 0x2
95#define LPFLG_LSA_FORCED_REFRESH 0x4
96
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;
108};
109
110/*
111 * Global variable to manage Opaque-LSA/MPLS-TE on this node.
112 * Note that all parameter values are stored in network byte order.
113 */
114static struct ospf_mpls_te OspfMplsTE;
115
116enum oifstate {
117 OI_ANY, OI_DOWN, OI_UP
118};
119
120enum sched_opcode {
121 REORIGINATE_PER_AREA, REFRESH_THIS_LSA, FLUSH_THIS_LSA
122};
123
124/*------------------------------------------------------------------------*
125 * Followings are initialize/terminate functions for MPLS-TE handling.
126 *------------------------------------------------------------------------*/
127
128static int ospf_mpls_te_new_if (struct interface *ifp);
129static int ospf_mpls_te_del_if (struct interface *ifp);
130static void ospf_mpls_te_ism_change (struct ospf_interface *oi, int old_status);
131static void ospf_mpls_te_nsm_change (struct ospf_neighbor *nbr, int old_status);
132static void ospf_mpls_te_config_write_router (struct vty *vty);
133static void ospf_mpls_te_config_write_if (struct vty *vty, struct interface *ifp);
134static void ospf_mpls_te_show_info (struct vty *vty, struct ospf_lsa *lsa);
135static int ospf_mpls_te_lsa_originate (void *arg);
136static void ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa);
137static void ospf_mpls_te_lsa_schedule (struct mpls_te_link *lp, enum sched_opcode);
138
139static void del_mpls_te_link (void *val);
140static void ospf_mpls_te_register_vty (void);
141
142int
143ospf_mpls_te_init (void)
144{
145 int rc;
146
147 rc = ospf_register_opaque_functab (
148 OSPF_OPAQUE_AREA_LSA,
149 OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA,
150 ospf_mpls_te_new_if,
151 ospf_mpls_te_del_if,
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 */);
162 if (rc != 0)
163 {
164 zlog_warn ("ospf_mpls_te_init: Failed to register functions");
165 goto out;
166 }
167
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;
172
173 ospf_mpls_te_register_vty ();
174
175out:
176 return rc;
177}
178
179void
180ospf_mpls_te_term (void)
181{
182 list_delete (OspfMplsTE.iflist);
183
184 OspfMplsTE.iflist = NULL;
185 OspfMplsTE.status = disabled;
186
187 ospf_delete_opaque_functab (OSPF_OPAQUE_AREA_LSA,
188 OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA);
189 return;
190}
191
192/*------------------------------------------------------------------------*
193 * Followings are control functions for MPLS-TE parameters management.
194 *------------------------------------------------------------------------*/
195
196static void
197del_mpls_te_link (void *val)
198{
199 XFREE (MTYPE_OSPF_MPLS_TE_LINKPARAMS, val);
200 return;
201}
202
203static u_int32_t
204get_mpls_te_instance_value ()
205{
206 static u_int32_t seqno = 0;
207
208 if (LEGAL_TE_INSTANCE_RANGE (seqno + 1))
209 seqno += 1;
210 else
211 seqno = 1; /* Avoid zero. */
212
213 return seqno;
214}
215
216static struct ospf_interface *
217lookup_oi_by_ifp (struct interface *ifp,
218 struct ospf_area *area, enum oifstate oifstate)
219{
220 struct ospf_interface *oi = NULL;
221 struct route_node *rn;
222
223 for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
224 {
225 if ((oi = rn->info) == NULL)
226 continue;
227
228 switch (oifstate)
229 {
230 case OI_ANY:
231 break;
232 case OI_DOWN:
233 if (ospf_if_is_enable (oi))
234 continue;
235 break;
236 case OI_UP:
237 if (! ospf_if_is_enable (oi))
238 continue;
239 break;
240 default:
241 zlog_warn ("lookup_oi_by_ifp: Unknown oifstate: %x", oifstate);
242 goto out;
243 }
244
245 if (area == NULL || oi->area == area)
246 return oi;
247 }
248out:
249 return NULL;
250}
251
252static struct mpls_te_link *
253lookup_linkparams_by_ifp (struct interface *ifp)
254{
87d6f87a 255 struct listnode *node;
718e3744 256 struct mpls_te_link *lp;
257
87d6f87a 258 LIST_LOOP (OspfMplsTE.iflist, lp, node)
259 if (lp->ifp == ifp)
260 return lp;
718e3744 261
262 return NULL;
263}
264
265static struct mpls_te_link *
266lookup_linkparams_by_instance (struct ospf_lsa *lsa)
267{
87d6f87a 268 struct listnode *node;
718e3744 269 struct mpls_te_link *lp;
6c835671 270 unsigned int key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr));
718e3744 271
87d6f87a 272 LIST_LOOP (OspfMplsTE.iflist, lp, node)
273 if (lp->instance == key)
274 return lp;
718e3744 275
276 zlog_warn ("lookup_linkparams_by_instance: Entry not found: key(%x)", key);
277 return NULL;
278}
279
280static void
281ospf_mpls_te_foreach_area (
282 void (*func)(struct mpls_te_link *lp, enum sched_opcode),
283 enum sched_opcode sched_opcode)
284{
87d6f87a 285 struct listnode *node, *node2;
718e3744 286 struct mpls_te_link *lp;
287 struct ospf_area *area;
288
87d6f87a 289 LIST_LOOP (OspfMplsTE.iflist, lp, node)
718e3744 290 {
718e3744 291 if ((area = lp->area) == NULL)
292 continue;
293 if (lp->flags & LPFLG_LOOKUP_DONE)
294 continue;
295
296 if (func != NULL)
297 (* func)(lp, sched_opcode);
298
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;
304 }
305
87d6f87a 306 LIST_LOOP (OspfMplsTE.iflist, lp, node)
307 if (lp->area != NULL)
308 lp->flags &= ~LPFLG_LOOKUP_DONE;
718e3744 309
310 return;
311}
312
313static void
314set_mpls_te_router_addr (struct in_addr ipv4)
315{
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;
319 return;
320}
321
322static void
323set_linkparams_link_header (struct mpls_te_link *lp)
324{
325 struct te_tlv_header *tlvh;
326 u_int16_t length = 0;
327
328 /* TE_LINK_SUBTLV_LINK_TYPE */
329 if (ntohs (lp->link_type.header.type) != 0)
330 length += TLV_SIZE (&lp->link_type.header);
331
332 /* TE_LINK_SUBTLV_LINK_ID */
333 if (ntohs (lp->link_id.header.type) != 0)
334 length += TLV_SIZE (&lp->link_id.header);
335
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);
340
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);
345
346 /* TE_LINK_SUBTLV_TE_METRIC */
347 if (ntohs (lp->te_metric.header.type) != 0)
348 length += TLV_SIZE (&lp->te_metric.header);
349
350 /* TE_LINK_SUBTLV_MAX_BW */
351 if (ntohs (lp->max_bw.header.type) != 0)
352 length += TLV_SIZE (&lp->max_bw.header);
353
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);
357
358 /* TE_LINK_SUBTLV_UNRSV_BW */
359 if (ntohs (lp->unrsv_bw.header.type) != 0)
360 length += TLV_SIZE (&lp->unrsv_bw.header);
361
362 /* TE_LINK_SUBTLV_RSC_CLSCLR */
363 if (ntohs (lp->rsc_clsclr.header.type) != 0)
364 length += TLV_SIZE (&lp->rsc_clsclr.header);
365
366 lp->link_header.header.type = htons (TE_TLV_LINK);
367 lp->link_header.header.length = htons (length);
368
369 return;
370}
371
372static void
373set_linkparams_link_type (struct ospf_interface *oi, struct mpls_te_link *lp)
374{
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));
377
378 switch (oi->type)
379 {
380 case OSPF_IFTYPE_POINTOPOINT:
381 lp->link_type.link_type.value = LINK_TYPE_SUBTLV_VALUE_PTP;
382 break;
383 case OSPF_IFTYPE_BROADCAST:
384 case OSPF_IFTYPE_NBMA:
385 lp->link_type.link_type.value = LINK_TYPE_SUBTLV_VALUE_MA;
386 break;
387 default:
388 /* Not supported yet. *//* XXX */
389 lp->link_type.header.type = htons (0);
390 break;
391 }
392 return;
393}
394
395static void
396set_linkparams_link_id (struct ospf_interface *oi, struct mpls_te_link *lp)
397{
398 struct ospf_neighbor *nbr;
399 int done = 0;
400
401 lp->link_id.header.type = htons (TE_LINK_SUBTLV_LINK_ID);
402 lp->link_id.header.length = htons (sizeof (lp->link_id.value));
403
404 /*
405 * The Link ID is identical to the contents of the Link ID field
406 * in the Router LSA for these link types.
407 */
408 switch (oi->type)
409 {
410 case OSPF_IFTYPE_POINTOPOINT:
411 /* Take the router ID of the neighbor. */
d4a53d58 412 if ((nbr = ospf_nbr_lookup_ptop (oi))
413 && nbr->state == NSM_Full)
718e3744 414 {
415 lp->link_id.value = nbr->router_id;
416 done = 1;
417 }
418 break;
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)
423 break;
424
425 if (nbr->state == NSM_Full
426 || (IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi))
d4a53d58 427 && ospf_nbr_count (oi, NSM_Full) > 0))
718e3744 428 {
429 lp->link_id.value = DR (oi);
430 done = 1;
431 }
432 break;
433 default:
434 /* Not supported yet. *//* XXX */
435 lp->link_id.header.type = htons (0);
436 break;
437 }
438
439 if (! done)
440 {
441 struct in_addr mask;
442 masklen2ip (oi->address->prefixlen, &mask);
443 lp->link_id.value.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
444 }
445 return;
446}
447
448static void
449set_linkparams_te_metric (struct mpls_te_link *lp, u_int32_t te_metric)
450{
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);
454 return;
455}
456
457static void
458set_linkparams_max_bw (struct mpls_te_link *lp, float *fp)
459{
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);
463 return;
464}
465
466static void
467set_linkparams_max_rsv_bw (struct mpls_te_link *lp, float *fp)
468{
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);
472 return;
473}
474
475static void
476set_linkparams_unrsv_bw (struct mpls_te_link *lp, int priority, float *fp)
477{
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]);
482 return;
483}
484
485static void
486set_linkparams_rsc_clsclr (struct mpls_te_link *lp, u_int32_t classcolor)
487{
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);
491 return;
492}
493
494static void
495initialize_linkparams (struct mpls_te_link *lp)
496{
497 struct interface *ifp = lp->ifp;
498 struct ospf_interface *oi;
499 float fval;
500 int i;
501
502 if ((oi = lookup_oi_by_ifp (ifp, NULL, OI_ANY)) == NULL)
503 return;
504
505 /*
506 * Try to set initial values those can be derived from
507 * zebra-interface information.
508 */
509 set_linkparams_link_type (oi, lp);
510
511 /*
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.
514 */
515 fval = (float)((ifp->bandwidth ? ifp->bandwidth
516 : OSPF_DEFAULT_BANDWIDTH) * 1000 / 8);
517
518 set_linkparams_max_bw (lp, &fval);
519 set_linkparams_max_rsv_bw (lp, &fval);
520
521 for (i = 0; i < 8; i++)
522 set_linkparams_unrsv_bw (lp, i, &fval);
523
524 return;
525}
526
527static int
528is_mandated_params_set (struct mpls_te_link *lp)
529{
530 int rc = 0;
531
532 if (ntohs (OspfMplsTE.router_addr.header.type) == 0)
533 goto out;
534
535 if (ntohs (lp->link_type.header.type) == 0)
536 goto out;
537
538 if (ntohs (lp->link_id.header.type) == 0)
539 goto out;
540
541 rc = 1;
542out:
543 return rc;
544}
545
546/*------------------------------------------------------------------------*
547 * Followings are callback functions against generic Opaque-LSAs handling.
548 *------------------------------------------------------------------------*/
549
550static int
551ospf_mpls_te_new_if (struct interface *ifp)
552{
553 struct mpls_te_link *new;
554 int rc = -1;
555
556 if (lookup_linkparams_by_ifp (ifp) != NULL)
557 {
558 zlog_warn ("ospf_mpls_te_new_if: ifp(%p) already in use?", ifp);
559 rc = 0; /* Do nothing here. */
560 goto out;
561 }
562
563 if ((new = XMALLOC (MTYPE_OSPF_MPLS_TE_LINKPARAMS,
564 sizeof (struct mpls_te_link))) == NULL)
565 {
6099b3b5 566 zlog_warn ("ospf_mpls_te_new_if: XMALLOC: %s", safe_strerror (errno));
718e3744 567 goto out;
568 }
569 memset (new, 0, sizeof (struct mpls_te_link));
570
571 new->area = NULL;
572 new->flags = 0;
573 new->instance = get_mpls_te_instance_value ();
574 new->ifp = ifp;
575
576 initialize_linkparams (new);
577
578 listnode_add (OspfMplsTE.iflist, new);
579
580 /* Schedule Opaque-LSA refresh. *//* XXX */
581
582 rc = 0;
583out:
584 return rc;
585}
586
587static int
588ospf_mpls_te_del_if (struct interface *ifp)
589{
590 struct mpls_te_link *lp;
591 int rc = -1;
592
593 if ((lp = lookup_linkparams_by_ifp (ifp)) != NULL)
594 {
87d6f87a 595 struct list *iflist = OspfMplsTE.iflist;
718e3744 596
597 /* Dequeue listnode entry from the list. */
598 listnode_delete (iflist, lp);
599
600 /* Avoid misjudgement in the next lookup. */
601 if (listcount (iflist) == 0)
602 iflist->head = iflist->tail = NULL;
603
604 XFREE (MTYPE_OSPF_MPLS_TE_LINKPARAMS, lp);
605 }
606
607 /* Schedule Opaque-LSA refresh. *//* XXX */
608
609 rc = 0;
610/*out:*/
611 return rc;
612}
613
614static void
615ospf_mpls_te_ism_change (struct ospf_interface *oi, int old_state)
616{
617 struct te_link_subtlv_link_type old_type;
618 struct te_link_subtlv_link_id old_id;
619 struct mpls_te_link *lp;
620
621 if ((lp = lookup_linkparams_by_ifp (oi->ifp)) == NULL)
622 {
623 zlog_warn ("ospf_mpls_te_ism_change: Cannot get linkparams from OI(%s)?", IF_NAME (oi));
624 goto out;
625 }
d4a53d58 626 if (oi->area == NULL || oi->area->ospf == NULL)
718e3744 627 {
628 zlog_warn ("ospf_mpls_te_ism_change: Cannot refer to OSPF from OI(%s)?",
629IF_NAME (oi));
630 goto out;
631 }
632#ifdef notyet
633 if ((lp->area != NULL
634 && ! IPV4_ADDR_SAME (&lp->area->area_id, &oi->area->area_id))
635 || (lp->area != NULL && oi->area == NULL))
636 {
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);
640 }
641#endif
642 /* Keep Area information in conbination with linkparams. */
643 lp->area = oi->area;
644
645 switch (oi->state)
646 {
647 case ISM_PointToPoint:
648 case ISM_DROther:
649 case ISM_Backup:
650 case ISM_DR:
651 old_type = lp->link_type;
652 old_id = lp->link_id;
653
654 set_linkparams_link_type (oi, lp);
655 set_linkparams_link_id (oi, lp);
656
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)))
661 {
662 if (lp->flags & LPFLG_LSA_ENGAGED)
663 ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
664 else
665 ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
666 }
667 break;
668 default:
669 lp->link_type.header.type = htons (0);
670 lp->link_id.header.type = htons (0);
671
672 if (lp->flags & LPFLG_LSA_ENGAGED)
673 ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
674 break;
675 }
676
677out:
678 return;
679}
680
681static void
682ospf_mpls_te_nsm_change (struct ospf_neighbor *nbr, int old_state)
683{
684 /* So far, nothing to do here. */
685 return;
686}
687
688/*------------------------------------------------------------------------*
689 * Followings are OSPF protocol processing functions for MPLS-TE.
690 *------------------------------------------------------------------------*/
691
692static void
693build_tlv_header (struct stream *s, struct te_tlv_header *tlvh)
694{
695 stream_put (s, tlvh, sizeof (struct te_tlv_header));
696 return;
697}
698
699static void
700build_router_tlv (struct stream *s)
701{
702 struct te_tlv_header *tlvh = &OspfMplsTE.router_addr.header;
703 if (ntohs (tlvh->type) != 0)
704 {
705 build_tlv_header (s, tlvh);
706 stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
707 }
708 return;
709}
710
711static void
712build_link_subtlv_link_type (struct stream *s, struct mpls_te_link *lp)
713{
714 struct te_tlv_header *tlvh = &lp->link_type.header;
715 if (ntohs (tlvh->type) != 0)
716 {
717 build_tlv_header (s, tlvh);
718 stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
719 }
720 return;
721}
722
723static void
724build_link_subtlv_link_id (struct stream *s, struct mpls_te_link *lp)
725{
726 struct te_tlv_header *tlvh = &lp->link_id.header;
727 if (ntohs (tlvh->type) != 0)
728 {
729 build_tlv_header (s, tlvh);
730 stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
731 }
732 return;
733}
734
735static void
736build_link_subtlv_lclif_ipaddr (struct stream *s, struct mpls_te_link *lp)
737{
738 struct te_tlv_header *tlvh = (struct te_tlv_header *) lp->lclif_ipaddr;
739 if (tlvh != NULL && ntohs (tlvh->type) != 0)
740 {
741 build_tlv_header (s, tlvh);
742 stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
743 }
744 return;
745}
746
747static void
748build_link_subtlv_rmtif_ipaddr (struct stream *s, struct mpls_te_link *lp)
749{
750 struct te_tlv_header *tlvh = (struct te_tlv_header *) lp->rmtif_ipaddr;
751 if (tlvh != NULL && ntohs (tlvh->type) != 0)
752 {
753 build_tlv_header (s, tlvh);
754 stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
755 }
756 return;
757}
758
759static void
760build_link_subtlv_te_metric (struct stream *s, struct mpls_te_link *lp)
761{
762 struct te_tlv_header *tlvh = &lp->te_metric.header;
763 if (ntohs (tlvh->type) != 0)
764 {
765 build_tlv_header (s, tlvh);
766 stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
767 }
768 return;
769}
770
771static void
772build_link_subtlv_max_bw (struct stream *s, struct mpls_te_link *lp)
773{
774 struct te_tlv_header *tlvh = &lp->max_bw.header;
775 if (ntohs (tlvh->type) != 0)
776 {
777 build_tlv_header (s, tlvh);
778 stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
779 }
780 return;
781}
782
783static void
784build_link_subtlv_max_rsv_bw (struct stream *s, struct mpls_te_link *lp)
785{
786 struct te_tlv_header *tlvh = &lp->max_rsv_bw.header;
787 if (ntohs (tlvh->type) != 0)
788 {
789 build_tlv_header (s, tlvh);
790 stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
791 }
792 return;
793}
794
795static void
796build_link_subtlv_unrsv_bw (struct stream *s, struct mpls_te_link *lp)
797{
798 struct te_tlv_header *tlvh = &lp->unrsv_bw.header;
799 if (ntohs (tlvh->type) != 0)
800 {
801 build_tlv_header (s, tlvh);
802 stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
803 }
804 return;
805}
806
807static void
808build_link_subtlv_rsc_clsclr (struct stream *s, struct mpls_te_link *lp)
809{
810 struct te_tlv_header *tlvh = &lp->rsc_clsclr.header;
811 if (ntohs (tlvh->type) != 0)
812 {
813 build_tlv_header (s, tlvh);
814 stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
815 }
816 return;
817}
818
819static void
820build_link_tlv (struct stream *s, struct mpls_te_link *lp)
821{
822 set_linkparams_link_header (lp);
823 build_tlv_header (s, &lp->link_header.header);
824
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);
834 return;
835}
836
837static void
838ospf_mpls_te_lsa_body_set (struct stream *s, struct mpls_te_link *lp)
839{
840 /*
841 * The router address TLV is type 1, and ...
842 * It must appear in exactly one
843 * Traffic Engineering LSA originated by a router.
844 */
845 build_router_tlv (s);
846
847 /*
848 * Only one Link TLV shall be carried in each LSA, allowing for fine
849 * granularity changes in topology.
850 */
851 build_link_tlv (s, lp);
852 return;
853}
854
855/* Create new opaque-LSA. */
856static struct ospf_lsa *
857ospf_mpls_te_lsa_new (struct ospf_area *area, struct mpls_te_link *lp)
858{
859 struct stream *s;
860 struct lsa_header *lsah;
861 struct ospf_lsa *new = NULL;
862 u_char options, lsa_type;
863 struct in_addr lsa_id;
864 u_int32_t tmp;
865 u_int16_t length;
866
867 /* Create a stream for LSA. */
868 if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL)
869 {
870 zlog_warn ("ospf_mpls_te_lsa_new: stream_new() ?");
871 goto out;
872 }
873 lsah = (struct lsa_header *) STREAM_DATA (s);
874
875 options = LSA_OPTIONS_GET (area);
d4a53d58 876 options |= LSA_OPTIONS_NSSA_GET (area);
718e3744 877 options |= OSPF_OPTION_O; /* Don't forget this :-) */
878
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);
882
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));
885
886 /* Set opaque-LSA header fields. */
d4a53d58 887 lsa_header_set (s, options, lsa_type, lsa_id, area->ospf->router_id);
718e3744 888
889 /* Set opaque-LSA body fields. */
890 ospf_mpls_te_lsa_body_set (s, lp);
891
892 /* Set length. */
893 length = stream_get_endp (s);
894 lsah->length = htons (length);
895
896 /* Now, create an OSPF LSA instance. */
897 if ((new = ospf_lsa_new ()) == NULL)
898 {
899 zlog_warn ("ospf_mpls_te_lsa_new: ospf_lsa_new() ?");
900 stream_free (s);
901 goto out;
902 }
903 if ((new->data = ospf_lsa_data_new (length)) == NULL)
904 {
905 zlog_warn ("ospf_mpls_te_lsa_new: ospf_lsa_data_new() ?");
788dab10 906 ospf_lsa_unlock (new);
718e3744 907 new = NULL;
908 stream_free (s);
909 goto out;
910 }
911
912 new->area = area;
913 SET_FLAG (new->flags, OSPF_LSA_SELF);
914 memcpy (new->data, lsah, length);
915 stream_free (s);
916
917out:
918 return new;
919}
920
921static int
922ospf_mpls_te_lsa_originate1 (struct ospf_area *area, struct mpls_te_link *lp)
923{
924 struct ospf_lsa *new;
925 int rc = -1;
926
927 /* Create new Opaque-LSA/MPLS-TE instance. */
928 if ((new = ospf_mpls_te_lsa_new (area, lp)) == NULL)
929 {
930 zlog_warn ("ospf_mpls_te_lsa_originate1: ospf_mpls_te_lsa_new() ?");
931 goto out;
932 }
933
934 /* Install this LSA into LSDB. */
d4a53d58 935 if (ospf_lsa_install (area->ospf, NULL/*oi*/, new) == NULL)
718e3744 936 {
937 zlog_warn ("ospf_mpls_te_lsa_originate1: ospf_lsa_install() ?");
788dab10 938 ospf_lsa_unlock (new);
718e3744 939 goto out;
940 }
941
942 /* Now this linkparameter entry has associated LSA. */
943 lp->flags |= LPFLG_LSA_ENGAGED;
944
945 /* Update new LSA origination count. */
d4a53d58 946 area->ospf->lsa_originate_count++;
718e3744 947
948 /* Flood new LSA through area. */
949 ospf_flood_through_area (area, NULL/*nbr*/, new);
950
951 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
952 {
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);
957 }
958
959 rc = 0;
960out:
961 return rc;
962}
963
964static int
965ospf_mpls_te_lsa_originate (void *arg)
966{
967 struct ospf_area *area = (struct ospf_area *) arg;
87d6f87a 968 struct listnode *node;
718e3744 969 struct mpls_te_link *lp;
970 int rc = -1;
971
972 if (OspfMplsTE.status == disabled)
973 {
974 zlog_info ("ospf_mpls_te_lsa_originate: MPLS-TE is disabled now.");
975 rc = 0; /* This is not an error case. */
976 goto out;
977 }
978
979 for (node = listhead (OspfMplsTE.iflist); node; nextnode (node))
980 {
981 if ((lp = getdata (node)) == NULL)
982 continue;
983 if (lp->area == NULL)
984 continue;
985 if (! IPV4_ADDR_SAME (&lp->area->area_id, &area->area_id))
986 continue;
987
988 if (lp->flags & LPFLG_LSA_ENGAGED)
989 {
990 if (lp->flags & LPFLG_LSA_FORCED_REFRESH)
991 {
992 lp->flags &= ~LPFLG_LSA_FORCED_REFRESH;
993 ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
994 }
995 continue;
996 }
997 if (! is_mandated_params_set (lp))
998 {
999 zlog_warn ("ospf_mpls_te_lsa_originate: Link(%s) lacks some mandated MPLS-TE parameters.", lp->ifp ? lp->ifp->name : "?");
1000 continue;
1001 }
1002
1003 /* Ok, let's try to originate an LSA for this area and Link. */
1004 if (ospf_mpls_te_lsa_originate1 (area, lp) != 0)
1005 goto out;
1006 }
1007
1008 rc = 0;
1009out:
1010 return rc;
1011}
1012
1013static void
1014ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa)
1015{
1016 struct mpls_te_link *lp;
1017 struct ospf_area *area = lsa->area;
1018 struct ospf_lsa *new = NULL;
1019
1020 if (OspfMplsTE.status == disabled)
1021 {
1022 /*
1023 * This LSA must have flushed before due to MPLS-TE status change.
1024 * It seems a slip among routers in the routing domain.
1025 */
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. */
1028 }
1029
1030 /* At first, resolve lsa/lp relationship. */
1031 if ((lp = lookup_linkparams_by_instance (lsa)) == NULL)
1032 {
1033 zlog_warn ("ospf_mpls_te_lsa_refresh: Invalid parameter?");
1034 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
1035 }
1036
1037 /* If the lsa's age reached to MaxAge, start flushing procedure. */
1038 if (IS_LSA_MAXAGE (lsa))
1039 {
1040 lp->flags &= ~LPFLG_LSA_ENGAGED;
1041 ospf_opaque_lsa_flush_schedule (lsa);
1042 goto out;
1043 }
1044
1045 /* Create new Opaque-LSA/MPLS-TE instance. */
1046 if ((new = ospf_mpls_te_lsa_new (area, lp)) == NULL)
1047 {
1048 zlog_warn ("ospf_mpls_te_lsa_refresh: ospf_mpls_te_lsa_new() ?");
1049 goto out;
1050 }
1051 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
1052
1053 /* Install this LSA into LSDB. */
1054 /* Given "lsa" will be freed in the next function. */
d4a53d58 1055 if (ospf_lsa_install (area->ospf, NULL/*oi*/, new) == NULL)
718e3744 1056 {
1057 zlog_warn ("ospf_mpls_te_lsa_refresh: ospf_lsa_install() ?");
788dab10 1058 ospf_lsa_unlock (new);
718e3744 1059 goto out;
1060 }
1061
1062 /* Flood updated LSA through area. */
1063 ospf_flood_through_area (area, NULL/*nbr*/, new);
1064
1065 /* Debug logging. */
1066 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1067 {
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);
1071 }
1072
1073out:
1074 return;
1075}
1076
1077static void
1078ospf_mpls_te_lsa_schedule (struct mpls_te_link *lp,
1079 enum sched_opcode opcode)
1080{
1081 struct ospf_lsa lsa;
1082 struct lsa_header lsah;
1083 u_int32_t tmp;
1084
1085 memset (&lsa, 0, sizeof (lsa));
1086 memset (&lsah, 0, sizeof (lsah));
1087
1088 lsa.area = lp->area;
1089 lsa.data = &lsah;
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);
1093
1094 switch (opcode)
1095 {
1096 case REORIGINATE_PER_AREA:
1097 ospf_opaque_lsa_reoriginate_schedule ((void *) lp->area,
1098 OSPF_OPAQUE_AREA_LSA, OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA);
1099 break;
1100 case REFRESH_THIS_LSA:
1101 ospf_opaque_lsa_refresh_schedule (&lsa);
1102 break;
1103 case FLUSH_THIS_LSA:
1104 lp->flags &= ~LPFLG_LSA_ENGAGED;
1105 ospf_opaque_lsa_flush_schedule (&lsa);
1106 break;
1107 default:
1108 zlog_warn ("ospf_mpls_te_lsa_schedule: Unknown opcode (%u)", opcode);
1109 break;
1110 }
1111
1112 return;
1113}
1114
1115/*------------------------------------------------------------------------*
1116 * Followings are vty session control functions.
1117 *------------------------------------------------------------------------*/
1118
1119static u_int16_t
1120show_vty_router_addr (struct vty *vty, struct te_tlv_header *tlvh)
1121{
1122 struct te_tlv_router_addr *top = (struct te_tlv_router_addr *) tlvh;
1123
1124 if (vty != NULL)
1125 vty_out (vty, " Router-Address: %s%s", inet_ntoa (top->value), VTY_NEWLINE);
1126 else
1127 zlog_info (" Router-Address: %s", inet_ntoa (top->value));
1128
1129 return TLV_SIZE (tlvh);
1130}
1131
1132static u_int16_t
1133show_vty_link_header (struct vty *vty, struct te_tlv_header *tlvh)
1134{
1135 struct te_tlv_link *top = (struct te_tlv_link *) tlvh;
1136
1137 if (vty != NULL)
1138 vty_out (vty, " Link: %u octets of data%s", ntohs (top->header.length), VTY_NEWLINE);
1139 else
1140 zlog_info (" Link: %u octets of data", ntohs (top->header.length));
1141
1142 return TLV_HDR_SIZE; /* Here is special, not "TLV_SIZE". */
1143}
1144
1145static u_int16_t
1146show_vty_link_subtlv_link_type (struct vty *vty, struct te_tlv_header *tlvh)
1147{
1148 struct te_link_subtlv_link_type *top;
1149 const char *cp = "Unknown";
1150
1151 top = (struct te_link_subtlv_link_type *) tlvh;
1152 switch (top->link_type.value)
1153 {
1154 case LINK_TYPE_SUBTLV_VALUE_PTP:
1155 cp = "Point-to-point";
1156 break;
1157 case LINK_TYPE_SUBTLV_VALUE_MA:
1158 cp = "Multiaccess";
1159 break;
1160 default:
1161 break;
1162 }
1163
1164 if (vty != NULL)
1165 vty_out (vty, " Link-Type: %s (%u)%s", cp, top->link_type.value, VTY_NEWLINE);
1166 else
1167 zlog_info (" Link-Type: %s (%u)", cp, top->link_type.value);
1168
1169 return TLV_SIZE (tlvh);
1170}
1171
1172static u_int16_t
1173show_vty_link_subtlv_link_id (struct vty *vty, struct te_tlv_header *tlvh)
1174{
1175 struct te_link_subtlv_link_id *top;
1176
1177 top = (struct te_link_subtlv_link_id *) tlvh;
1178 if (vty != NULL)
1179 vty_out (vty, " Link-ID: %s%s", inet_ntoa (top->value), VTY_NEWLINE);
1180 else
1181 zlog_info (" Link-ID: %s", inet_ntoa (top->value));
1182
1183 return TLV_SIZE (tlvh);
1184}
1185
1186static u_int16_t
1187show_vty_link_subtlv_lclif_ipaddr (struct vty *vty, struct te_tlv_header *tlvh)
1188{
1189 struct te_link_subtlv_lclif_ipaddr *top;
1190 int i, n;
1191
1192 top = (struct te_link_subtlv_lclif_ipaddr *) tlvh;
1193 n = ntohs (tlvh->length) / sizeof (top->value[0]);
1194
1195 if (vty != NULL)
1196 vty_out (vty, " Local Interface IP Address(es): %d%s", n, VTY_NEWLINE);
1197 else
1198 zlog_info (" Local Interface IP Address(es): %d", n);
1199
1200 for (i = 0; i < n; i++)
1201 {
1202 if (vty != NULL)
1203 vty_out (vty, " #%d: %s%s", i, inet_ntoa (top->value[i]), VTY_NEWLINE);
1204 else
1205 zlog_info (" #%d: %s", i, inet_ntoa (top->value[i]));
1206 }
1207 return TLV_SIZE (tlvh);
1208}
1209
1210static u_int16_t
1211show_vty_link_subtlv_rmtif_ipaddr (struct vty *vty, struct te_tlv_header *tlvh)
1212{
1213 struct te_link_subtlv_rmtif_ipaddr *top;
1214 int i, n;
1215
1216 top = (struct te_link_subtlv_rmtif_ipaddr *) tlvh;
1217 n = ntohs (tlvh->length) / sizeof (top->value[0]);
1218 if (vty != NULL)
1219 vty_out (vty, " Remote Interface IP Address(es): %d%s", n, VTY_NEWLINE);
1220 else
1221 zlog_info (" Remote Interface IP Address(es): %d", n);
1222
1223 for (i = 0; i < n; i++)
1224 {
1225 if (vty != NULL)
1226 vty_out (vty, " #%d: %s%s", i, inet_ntoa (top->value[i]), VTY_NEWLINE);
1227 else
1228 zlog_info (" #%d: %s", i, inet_ntoa (top->value[i]));
1229 }
1230 return TLV_SIZE (tlvh);
1231}
1232
1233static u_int16_t
1234show_vty_link_subtlv_te_metric (struct vty *vty, struct te_tlv_header *tlvh)
1235{
1236 struct te_link_subtlv_te_metric *top;
1237
1238 top = (struct te_link_subtlv_te_metric *) tlvh;
1239 if (vty != NULL)
1240 vty_out (vty, " Traffic Engineering Metric: %u%s", (u_int32_t) ntohl (top->value), VTY_NEWLINE);
1241 else
1242 zlog_info (" Traffic Engineering Metric: %u", (u_int32_t) ntohl (top->value));
1243
1244 return TLV_SIZE (tlvh);
1245}
1246
1247static u_int16_t
1248show_vty_link_subtlv_max_bw (struct vty *vty, struct te_tlv_header *tlvh)
1249{
1250 struct te_link_subtlv_max_bw *top;
1251 float fval;
1252
1253 top = (struct te_link_subtlv_max_bw *) tlvh;
1254 ntohf (&top->value, &fval);
1255
1256 if (vty != NULL)
1257 vty_out (vty, " Maximum Bandwidth: %g (Bytes/sec)%s", fval, VTY_NEWLINE);
1258 else
1259 zlog_info (" Maximum Bandwidth: %g (Bytes/sec)", fval);
1260
1261 return TLV_SIZE (tlvh);
1262}
1263
1264static u_int16_t
1265show_vty_link_subtlv_max_rsv_bw (struct vty *vty, struct te_tlv_header *tlvh)
1266{
1267 struct te_link_subtlv_max_rsv_bw *top;
1268 float fval;
1269
1270 top = (struct te_link_subtlv_max_rsv_bw *) tlvh;
1271 ntohf (&top->value, &fval);
1272
1273 if (vty != NULL)
1274 vty_out (vty, " Maximum Reservable Bandwidth: %g (Bytes/sec)%s", fval, VTY_NEWLINE);
1275 else
1276 zlog_info (" Maximum Reservable Bandwidth: %g (Bytes/sec)", fval);
1277
1278 return TLV_SIZE (tlvh);
1279}
1280
1281static u_int16_t
1282show_vty_link_subtlv_unrsv_bw (struct vty *vty, struct te_tlv_header *tlvh)
1283{
1284 struct te_link_subtlv_unrsv_bw *top;
1285 float fval;
1286 int i;
1287
1288 top = (struct te_link_subtlv_unrsv_bw *) tlvh;
1289 for (i = 0; i < 8; i++)
1290 {
1291 ntohf (&top->value[i], &fval);
1292 if (vty != NULL)
1293 vty_out (vty, " Unreserved Bandwidth (pri %d): %g (Bytes/sec)%s", i, fval, VTY_NEWLINE);
1294 else
1295 zlog_info (" Unreserved Bandwidth (pri %d): %g (Bytes/sec)", i, fval);
1296 }
1297
1298 return TLV_SIZE (tlvh);
1299}
1300
1301static u_int16_t
1302show_vty_link_subtlv_rsc_clsclr (struct vty *vty, struct te_tlv_header *tlvh)
1303{
1304 struct te_link_subtlv_rsc_clsclr *top;
1305
1306 top = (struct te_link_subtlv_rsc_clsclr *) tlvh;
1307 if (vty != NULL)
1308 vty_out (vty, " Resource class/color: 0x%x%s", (u_int32_t) ntohl (top->value), VTY_NEWLINE);
1309 else
1310 zlog_info (" Resource Class/Color: 0x%x", (u_int32_t) ntohl (top->value));
1311
1312 return TLV_SIZE (tlvh);
1313}
1314
1315static u_int16_t
1316show_vty_unknown_tlv (struct vty *vty, struct te_tlv_header *tlvh)
1317{
1318 if (vty != NULL)
1319 vty_out (vty, " Unknown TLV: [type(0x%x), length(0x%x)]%s", ntohs (tlvh->type), ntohs (tlvh->length), VTY_NEWLINE);
1320 else
1321 zlog_info (" Unknown TLV: [type(0x%x), length(0x%x)]", ntohs (tlvh->type), ntohs (tlvh->length));
1322
1323 return TLV_SIZE (tlvh);
1324}
1325
1326static u_int16_t
1327ospf_mpls_te_show_link_subtlv (struct vty *vty, struct te_tlv_header *tlvh0,
1328 u_int16_t subtotal, u_int16_t total)
1329{
1330 struct te_tlv_header *tlvh, *next;
1331 u_int16_t sum = subtotal;
1332
1333 for (tlvh = tlvh0; sum < total; tlvh = (next ? next : TLV_HDR_NEXT (tlvh)))
1334 {
1335 next = NULL;
1336 switch (ntohs (tlvh->type))
1337 {
1338 case TE_LINK_SUBTLV_LINK_TYPE:
1339 sum += show_vty_link_subtlv_link_type (vty, tlvh);
1340 break;
1341 case TE_LINK_SUBTLV_LINK_ID:
1342 sum += show_vty_link_subtlv_link_id (vty, tlvh);
1343 break;
1344 case TE_LINK_SUBTLV_LCLIF_IPADDR:
1345 sum += show_vty_link_subtlv_lclif_ipaddr (vty, tlvh);
1346 break;
1347 case TE_LINK_SUBTLV_RMTIF_IPADDR:
1348 sum += show_vty_link_subtlv_rmtif_ipaddr (vty, tlvh);
1349 break;
1350 case TE_LINK_SUBTLV_TE_METRIC:
1351 sum += show_vty_link_subtlv_te_metric (vty, tlvh);
1352 break;
1353 case TE_LINK_SUBTLV_MAX_BW:
1354 sum += show_vty_link_subtlv_max_bw (vty, tlvh);
1355 break;
1356 case TE_LINK_SUBTLV_MAX_RSV_BW:
1357 sum += show_vty_link_subtlv_max_rsv_bw (vty, tlvh);
1358 break;
1359 case TE_LINK_SUBTLV_UNRSV_BW:
1360 sum += show_vty_link_subtlv_unrsv_bw (vty, tlvh);
1361 break;
1362 case TE_LINK_SUBTLV_RSC_CLSCLR:
1363 sum += show_vty_link_subtlv_rsc_clsclr (vty, tlvh);
1364 break;
1365 default:
1366 sum += show_vty_unknown_tlv (vty, tlvh);
1367 break;
1368 }
1369 }
1370 return sum;
1371}
1372
1373static void
1374ospf_mpls_te_show_info (struct vty *vty, struct ospf_lsa *lsa)
1375{
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;
1381
1382 sum = 0;
1383 total = ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE;
1384
1385 for (tlvh = TLV_HDR_TOP (lsah); sum < total;
1386 tlvh = (next ? next : TLV_HDR_NEXT (tlvh)))
1387 {
1388 if (subfunc != NULL)
1389 {
1390 sum = (* subfunc)(vty, tlvh, sum, total);
1391 next = (struct te_tlv_header *)((char *) tlvh + sum);
1392 subfunc = NULL;
1393 continue;
1394 }
1395
1396 next = NULL;
1397 switch (ntohs (tlvh->type))
1398 {
1399 case TE_TLV_ROUTER_ADDR:
1400 sum += show_vty_router_addr (vty, tlvh);
1401 break;
1402 case TE_TLV_LINK:
1403 sum += show_vty_link_header (vty, tlvh);
1404 subfunc = ospf_mpls_te_show_link_subtlv;
1405 next = tlvh + 1;
1406 break;
1407 default:
1408 sum += show_vty_unknown_tlv (vty, tlvh);
1409 break;
1410 }
1411 }
1412 return;
1413}
1414
1415static void
1416ospf_mpls_te_config_write_router (struct vty *vty)
1417{
1418 if (OspfMplsTE.status == enabled)
1419 {
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);
1423 }
1424 return;
1425}
1426
1427static void
1428ospf_mpls_te_config_write_if (struct vty *vty, struct interface *ifp)
1429{
1430 struct mpls_te_link *lp;
1431
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))
1435 {
1436 float fval;
1437 int i;
1438
1439 vty_out (vty, " mpls-te link metric %u%s",
1440 (u_int32_t) ntohl (lp->te_metric.value), VTY_NEWLINE);
1441
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);
1445
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);
1449
1450 for (i = 0; i < 8; i++)
1451 {
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);
1456 }
1457
1458 vty_out (vty, " mpls-te link rsc-clsclr 0x%x%s",
1459 (u_int32_t) ntohl (lp->rsc_clsclr.value), VTY_NEWLINE);
1460 }
1461 return;
1462}
1463
1464/*------------------------------------------------------------------------*
1465 * Followings are vty command functions.
1466 *------------------------------------------------------------------------*/
1467
1468DEFUN (mpls_te,
1469 mpls_te_cmd,
1470 "mpls-te",
1471 "Configure MPLS-TE parameters\n"
1472 "Enable the MPLS-TE functionality\n")
1473{
87d6f87a 1474 struct listnode *node;
718e3744 1475 struct mpls_te_link *lp;
1476
1477 if (OspfMplsTE.status == enabled)
1478 return CMD_SUCCESS;
1479
1480 if (IS_DEBUG_OSPF_EVENT)
1481 zlog_info ("MPLS-TE: OFF -> ON");
1482
1483 OspfMplsTE.status = enabled;
1484
1485 /*
1486 * Following code is intended to handle two cases;
1487 *
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.
1490 */
1491 for (node = listhead (OspfMplsTE.iflist); node; nextnode (node))
1492 if ((lp = getdata (node)) != NULL)
1493 initialize_linkparams (lp);
1494
1495 ospf_mpls_te_foreach_area (ospf_mpls_te_lsa_schedule, REORIGINATE_PER_AREA);
1496
1497 return CMD_SUCCESS;
1498}
1499
1500ALIAS (mpls_te,
1501 mpls_te_on_cmd,
1502 "mpls-te on",
1503 "Configure MPLS-TE parameters\n"
1504 "Enable the MPLS-TE functionality\n")
1505
1506DEFUN (no_mpls_te,
1507 no_mpls_te_cmd,
1508 "no mpls-te",
1509 NO_STR
1510 "Configure MPLS-TE parameters\n"
1511 "Disable the MPLS-TE functionality\n")
1512{
87d6f87a 1513 struct listnode *node;
718e3744 1514 struct mpls_te_link *lp;
1515
1516 if (OspfMplsTE.status == disabled)
1517 return CMD_SUCCESS;
1518
1519 if (IS_DEBUG_OSPF_EVENT)
1520 zlog_info ("MPLS-TE: ON -> OFF");
1521
1522 OspfMplsTE.status = disabled;
1523
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);
1529
1530 return CMD_SUCCESS;
1531}
1532
1533DEFUN (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")
1539{
1540 struct te_tlv_router_addr *ra = &OspfMplsTE.router_addr;
1541 struct in_addr value;
1542
1543 if (! inet_aton (argv[0], &value))
1544 {
1545 vty_out (vty, "Please specify Router-Addr by A.B.C.D%s", VTY_NEWLINE);
1546 return CMD_WARNING;
1547 }
1548
1549 if (ntohs (ra->header.type) == 0
87d6f87a 1550 || ntohl (ra->value.s_addr) != ntohl (value.s_addr))
718e3744 1551 {
87d6f87a 1552 struct listnode *node;
718e3744 1553 struct mpls_te_link *lp;
1554 int need_to_reoriginate = 0;
1555
1556 set_mpls_te_router_addr (value);
1557
1558 if (OspfMplsTE.status == disabled)
1559 goto out;
1560
87d6f87a 1561 LIST_LOOP (OspfMplsTE.iflist, lp, node)
718e3744 1562 {
718e3744 1563 if (lp->area == NULL)
1564 continue;
1565
1566 if ((lp->flags & LPFLG_LSA_ENGAGED) == 0)
1567 {
1568 need_to_reoriginate = 1;
1569 break;
1570 }
1571 }
1572 for (node = listhead (OspfMplsTE.iflist); node; nextnode (node))
87d6f87a 1573 LIST_LOOP (OspfMplsTE.iflist, lp, node)
718e3744 1574 {
718e3744 1575 if (lp->area == NULL)
1576 continue;
1577
1578 if (need_to_reoriginate)
1579 lp->flags |= LPFLG_LSA_FORCED_REFRESH;
1580 else
1581 ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
1582 }
1583
1584 if (need_to_reoriginate)
1585 ospf_mpls_te_foreach_area (
1586 ospf_mpls_te_lsa_schedule, REORIGINATE_PER_AREA);
1587 }
1588out:
1589 return CMD_SUCCESS;
1590}
1591
1592DEFUN (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"
1598 "Metric\n")
1599{
1600 struct interface *ifp = (struct interface *) vty->index;
1601 struct mpls_te_link *lp;
1602 u_int32_t value;
1603
1604 if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL)
1605 {
1606 vty_out (vty, "mpls_te_link_metric: Something wrong!%s", VTY_NEWLINE);
1607 return CMD_WARNING;
1608 }
1609
1610 value = strtoul (argv[0], NULL, 10);
1611
1612 if (ntohs (lp->te_metric.header.type) == 0
1613 || ntohl (lp->te_metric.value) != value)
1614 {
1615 set_linkparams_te_metric (lp, value);
1616
1617 if (OspfMplsTE.status == enabled)
1618 if (lp->area != NULL)
1619 {
1620 if (lp->flags & LPFLG_LSA_ENGAGED)
1621 ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
1622 else
1623 ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
1624 }
1625 }
1626 return CMD_SUCCESS;
1627}
1628
1629DEFUN (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")
1636{
1637 struct interface *ifp = (struct interface *) vty->index;
1638 struct mpls_te_link *lp;
1639 float f1, f2;
1640
1641 if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL)
1642 {
1643 vty_out (vty, "mpls_te_link_maxbw: Something wrong!%s", VTY_NEWLINE);
1644 return CMD_WARNING;
1645 }
1646
1647 ntohf (&lp->max_bw.value, &f1);
1648 if (sscanf (argv[0], "%g", &f2) != 1)
1649 {
6099b3b5 1650 vty_out (vty, "mpls_te_link_maxbw: fscanf: %s%s", safe_strerror (errno), VTY_NEWLINE);
718e3744 1651 return CMD_WARNING;
1652 }
1653
1654 if (ntohs (lp->max_bw.header.type) == 0
1655 || f1 != f2)
1656 {
1657 set_linkparams_max_bw (lp, &f2);
1658
1659 if (OspfMplsTE.status == enabled)
1660 if (lp->area != NULL)
1661 {
1662 if (lp->flags & LPFLG_LSA_ENGAGED)
1663 ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
1664 else
1665 ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
1666 }
1667 }
1668 return CMD_SUCCESS;
1669}
1670
1671DEFUN (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")
1678{
1679 struct interface *ifp = (struct interface *) vty->index;
1680 struct mpls_te_link *lp;
1681 float f1, f2;
1682
1683 if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL)
1684 {
1685 vty_out (vty, "mpls_te_link_max_rsv_bw: Something wrong!%s", VTY_NEWLINE);
1686 return CMD_WARNING;
1687 }
1688
1689 ntohf (&lp->max_rsv_bw.value, &f1);
1690 if (sscanf (argv[0], "%g", &f2) != 1)
1691 {
6099b3b5 1692 vty_out (vty, "mpls_te_link_max_rsv_bw: fscanf: %s%s", safe_strerror (errno), VTY_NEWLINE);
718e3744 1693 return CMD_WARNING;
1694 }
1695
1696 if (ntohs (lp->max_rsv_bw.header.type) == 0
1697 || f1 != f2)
1698 {
1699 set_linkparams_max_rsv_bw (lp, &f2);
1700
1701 if (OspfMplsTE.status == enabled)
1702 if (lp->area != NULL)
1703 {
1704 if (lp->flags & LPFLG_LSA_ENGAGED)
1705 ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
1706 else
1707 ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
1708 }
1709 }
1710 return CMD_SUCCESS;
1711}
1712
1713DEFUN (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"
1719 "Priority\n"
1720 "Bytes/second (IEEE floating point format)\n")
1721{
1722 struct interface *ifp = (struct interface *) vty->index;
1723 struct mpls_te_link *lp;
1724 int priority;
1725 float f1, f2;
1726
1727 if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL)
1728 {
1729 vty_out (vty, "mpls_te_link_unrsv_bw: Something wrong!%s", VTY_NEWLINE);
1730 return CMD_WARNING;
1731 }
1732
1733 /* We don't have to consider about range check here. */
1734 if (sscanf (argv[0], "%d", &priority) != 1)
1735 {
6099b3b5 1736 vty_out (vty, "mpls_te_link_unrsv_bw: fscanf: %s%s", safe_strerror (errno), VTY_NEWLINE);
718e3744 1737 return CMD_WARNING;
1738 }
1739
1740 ntohf (&lp->unrsv_bw.value [priority], &f1);
1741 if (sscanf (argv[1], "%g", &f2) != 1)
1742 {
6099b3b5 1743 vty_out (vty, "mpls_te_link_unrsv_bw: fscanf: %s%s", safe_strerror (errno), VTY_NEWLINE);
718e3744 1744 return CMD_WARNING;
1745 }
1746
1747 if (ntohs (lp->unrsv_bw.header.type) == 0
1748 || f1 != f2)
1749 {
1750 set_linkparams_unrsv_bw (lp, priority, &f2);
1751
1752 if (OspfMplsTE.status == enabled)
1753 if (lp->area != NULL)
1754 {
1755 if (lp->flags & LPFLG_LSA_ENGAGED)
1756 ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
1757 else
1758 ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
1759 }
1760 }
1761 return CMD_SUCCESS;
1762}
1763
1764DEFUN (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")
1771{
1772 struct interface *ifp = (struct interface *) vty->index;
1773 struct mpls_te_link *lp;
1774 unsigned long value;
1775
1776 if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL)
1777 {
1778 vty_out (vty, "mpls_te_link_rsc_clsclr: Something wrong!%s", VTY_NEWLINE);
1779 return CMD_WARNING;
1780 }
1781
1782 if (sscanf (argv[0], "0x%lx", &value) != 1)
1783 {
6099b3b5 1784 vty_out (vty, "mpls_te_link_rsc_clsclr: fscanf: %s%s", safe_strerror (errno), VTY_NEWLINE);
718e3744 1785 return CMD_WARNING;
1786 }
1787
1788 if (ntohs (lp->rsc_clsclr.header.type) == 0
1789 || ntohl (lp->rsc_clsclr.value) != value)
1790 {
1791 set_linkparams_rsc_clsclr (lp, value);
1792
1793 if (OspfMplsTE.status == enabled)
1794 if (lp->area != NULL)
1795 {
1796 if (lp->flags & LPFLG_LSA_ENGAGED)
1797 ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
1798 else
1799 ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
1800 }
1801 }
1802 return CMD_SUCCESS;
1803}
1804
1805DEFUN (show_mpls_te_router,
1806 show_mpls_te_router_cmd,
1807 "show mpls-te router",
1808 SHOW_STR
1809 "MPLS-TE information\n"
1810 "Router information\n")
1811{
1812 if (OspfMplsTE.status == enabled)
1813 {
1814 vty_out (vty, "--- MPLS-TE router parameters ---%s",
1815 VTY_NEWLINE);
1816
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);
1821 }
1822 return CMD_SUCCESS;
1823}
1824
1825static void
1826show_mpls_te_link_sub (struct vty *vty, struct interface *ifp)
1827{
1828 struct mpls_te_link *lp;
1829 struct te_tlv_header *tlvh;
1830
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))
1834 {
1835 vty_out (vty, "-- MPLS-TE link parameters for %s --%s",
1836 ifp->name, VTY_NEWLINE);
1837
1838 show_vty_link_subtlv_link_type (vty, &lp->link_type.header);
1839 show_vty_link_subtlv_link_id (vty, &lp->link_id.header);
1840
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);
1845
1846 show_vty_link_subtlv_te_metric (vty, &lp->te_metric.header);
1847
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);
1852 }
1853 else
1854 {
1855 vty_out (vty, " %s: MPLS-TE is disabled on this interface%s",
1856 ifp->name, VTY_NEWLINE);
1857 }
1858
1859 return;
1860}
1861
1862DEFUN (show_mpls_te_link,
1863 show_mpls_te_link_cmd,
1864 "show mpls-te interface [INTERFACE]",
1865 SHOW_STR
1866 "MPLS-TE information\n"
1867 "Interface information\n"
1868 "Interface name\n")
1869{
1870 struct interface *ifp;
87d6f87a 1871 struct listnode *node;
718e3744 1872
1873 /* Show All Interfaces. */
1874 if (argc == 0)
eb1ce605 1875 {
1876 LIST_LOOP (iflist, ifp, node)
1877 show_mpls_te_link_sub (vty, ifp);
1878 }
718e3744 1879 /* Interface name is specified. */
1880 else
1881 {
1882 if ((ifp = if_lookup_by_name (argv[0])) == NULL)
1883 vty_out (vty, "No such interface name%s", VTY_NEWLINE);
1884 else
1885 show_mpls_te_link_sub (vty, ifp);
1886 }
1887
1888 return CMD_SUCCESS;
1889}
1890
1891static void
1892ospf_mpls_te_register_vty (void)
1893{
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);
1898
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);
1903
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);
1909
1910 return;
1911}
1912
1913#endif /* HAVE_OSPF_TE */