]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_te.c
2005-05-06 Paul Jakma <paul.jakma@sun.com>
[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
4dadc291 204get_mpls_te_instance_value (void)
718e3744 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{
1eb8ef25 255 struct listnode *node, *nnode;
718e3744 256 struct mpls_te_link *lp;
257
1eb8ef25 258 for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
87d6f87a 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
1eb8ef25 272 for (ALL_LIST_ELEMENTS_RO (OspfMplsTE.iflist, node, lp))
87d6f87a 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{
1eb8ef25 285 struct listnode *node, *nnode;
286 struct listnode *node2;
718e3744 287 struct mpls_te_link *lp;
288 struct ospf_area *area;
289
1eb8ef25 290 for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
718e3744 291 {
718e3744 292 if ((area = lp->area) == NULL)
293 continue;
294 if (lp->flags & LPFLG_LOOKUP_DONE)
295 continue;
296
297 if (func != NULL)
298 (* func)(lp, sched_opcode);
299
1eb8ef25 300 for (node2 = listnextnode (node); node2; node2 = listnextnode (node2))
301 if ((lp = listgetdata (node2)) != NULL)
718e3744 302 if (lp->area != NULL)
303 if (IPV4_ADDR_SAME (&lp->area->area_id, &area->area_id))
304 lp->flags |= LPFLG_LOOKUP_DONE;
305 }
306
1eb8ef25 307 for (ALL_LIST_ELEMENTS_RO (OspfMplsTE.iflist, node, lp))
87d6f87a 308 if (lp->area != NULL)
309 lp->flags &= ~LPFLG_LOOKUP_DONE;
718e3744 310
311 return;
312}
313
314static void
315set_mpls_te_router_addr (struct in_addr ipv4)
316{
317 OspfMplsTE.router_addr.header.type = htons (TE_TLV_ROUTER_ADDR);
318 OspfMplsTE.router_addr.header.length = htons (sizeof (ipv4));
319 OspfMplsTE.router_addr.value = ipv4;
320 return;
321}
322
323static void
324set_linkparams_link_header (struct mpls_te_link *lp)
325{
326 struct te_tlv_header *tlvh;
327 u_int16_t length = 0;
328
329 /* TE_LINK_SUBTLV_LINK_TYPE */
330 if (ntohs (lp->link_type.header.type) != 0)
331 length += TLV_SIZE (&lp->link_type.header);
332
333 /* TE_LINK_SUBTLV_LINK_ID */
334 if (ntohs (lp->link_id.header.type) != 0)
335 length += TLV_SIZE (&lp->link_id.header);
336
337 /* TE_LINK_SUBTLV_LCLIF_IPADDR */
338 if ((tlvh = (struct te_tlv_header *) lp->lclif_ipaddr) != NULL
339 && ntohs (tlvh->type) != 0)
340 length += TLV_SIZE (tlvh);
341
342 /* TE_LINK_SUBTLV_RMTIF_IPADDR */
343 if ((tlvh = (struct te_tlv_header *) lp->rmtif_ipaddr) != NULL
344 && ntohs (tlvh->type) != 0)
345 length += TLV_SIZE (tlvh);
346
347 /* TE_LINK_SUBTLV_TE_METRIC */
348 if (ntohs (lp->te_metric.header.type) != 0)
349 length += TLV_SIZE (&lp->te_metric.header);
350
351 /* TE_LINK_SUBTLV_MAX_BW */
352 if (ntohs (lp->max_bw.header.type) != 0)
353 length += TLV_SIZE (&lp->max_bw.header);
354
355 /* TE_LINK_SUBTLV_MAX_RSV_BW */
356 if (ntohs (lp->max_rsv_bw.header.type) != 0)
357 length += TLV_SIZE (&lp->max_rsv_bw.header);
358
359 /* TE_LINK_SUBTLV_UNRSV_BW */
360 if (ntohs (lp->unrsv_bw.header.type) != 0)
361 length += TLV_SIZE (&lp->unrsv_bw.header);
362
363 /* TE_LINK_SUBTLV_RSC_CLSCLR */
364 if (ntohs (lp->rsc_clsclr.header.type) != 0)
365 length += TLV_SIZE (&lp->rsc_clsclr.header);
366
367 lp->link_header.header.type = htons (TE_TLV_LINK);
368 lp->link_header.header.length = htons (length);
369
370 return;
371}
372
373static void
374set_linkparams_link_type (struct ospf_interface *oi, struct mpls_te_link *lp)
375{
376 lp->link_type.header.type = htons (TE_LINK_SUBTLV_LINK_TYPE);
377 lp->link_type.header.length = htons (sizeof (lp->link_type.link_type.value));
378
379 switch (oi->type)
380 {
381 case OSPF_IFTYPE_POINTOPOINT:
382 lp->link_type.link_type.value = LINK_TYPE_SUBTLV_VALUE_PTP;
383 break;
384 case OSPF_IFTYPE_BROADCAST:
385 case OSPF_IFTYPE_NBMA:
386 lp->link_type.link_type.value = LINK_TYPE_SUBTLV_VALUE_MA;
387 break;
388 default:
389 /* Not supported yet. *//* XXX */
390 lp->link_type.header.type = htons (0);
391 break;
392 }
393 return;
394}
395
396static void
397set_linkparams_link_id (struct ospf_interface *oi, struct mpls_te_link *lp)
398{
399 struct ospf_neighbor *nbr;
400 int done = 0;
401
402 lp->link_id.header.type = htons (TE_LINK_SUBTLV_LINK_ID);
403 lp->link_id.header.length = htons (sizeof (lp->link_id.value));
404
405 /*
406 * The Link ID is identical to the contents of the Link ID field
407 * in the Router LSA for these link types.
408 */
409 switch (oi->type)
410 {
411 case OSPF_IFTYPE_POINTOPOINT:
412 /* Take the router ID of the neighbor. */
d4a53d58 413 if ((nbr = ospf_nbr_lookup_ptop (oi))
414 && nbr->state == NSM_Full)
718e3744 415 {
416 lp->link_id.value = nbr->router_id;
417 done = 1;
418 }
419 break;
420 case OSPF_IFTYPE_BROADCAST:
421 case OSPF_IFTYPE_NBMA:
422 /* Take the interface address of the designated router. */
423 if ((nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &DR (oi))) == NULL)
424 break;
425
426 if (nbr->state == NSM_Full
427 || (IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi))
d4a53d58 428 && ospf_nbr_count (oi, NSM_Full) > 0))
718e3744 429 {
430 lp->link_id.value = DR (oi);
431 done = 1;
432 }
433 break;
434 default:
435 /* Not supported yet. *//* XXX */
436 lp->link_id.header.type = htons (0);
437 break;
438 }
439
440 if (! done)
441 {
442 struct in_addr mask;
443 masklen2ip (oi->address->prefixlen, &mask);
444 lp->link_id.value.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
445 }
446 return;
447}
448
449static void
450set_linkparams_te_metric (struct mpls_te_link *lp, u_int32_t te_metric)
451{
452 lp->te_metric.header.type = htons (TE_LINK_SUBTLV_TE_METRIC);
453 lp->te_metric.header.length = htons (sizeof (lp->te_metric.value));
454 lp->te_metric.value = htonl (te_metric);
455 return;
456}
457
458static void
459set_linkparams_max_bw (struct mpls_te_link *lp, float *fp)
460{
461 lp->max_bw.header.type = htons (TE_LINK_SUBTLV_MAX_BW);
462 lp->max_bw.header.length = htons (sizeof (lp->max_bw.value));
463 htonf (fp, &lp->max_bw.value);
464 return;
465}
466
467static void
468set_linkparams_max_rsv_bw (struct mpls_te_link *lp, float *fp)
469{
470 lp->max_rsv_bw.header.type = htons (TE_LINK_SUBTLV_MAX_RSV_BW);
471 lp->max_rsv_bw.header.length = htons (sizeof (lp->max_rsv_bw.value));
472 htonf (fp, &lp->max_rsv_bw.value);
473 return;
474}
475
476static void
477set_linkparams_unrsv_bw (struct mpls_te_link *lp, int priority, float *fp)
478{
479 /* Note that TLV-length field is the size of array. */
480 lp->unrsv_bw.header.type = htons (TE_LINK_SUBTLV_UNRSV_BW);
481 lp->unrsv_bw.header.length = htons (sizeof (lp->unrsv_bw.value));
482 htonf (fp, &lp->unrsv_bw.value [priority]);
483 return;
484}
485
486static void
487set_linkparams_rsc_clsclr (struct mpls_te_link *lp, u_int32_t classcolor)
488{
489 lp->rsc_clsclr.header.type = htons (TE_LINK_SUBTLV_RSC_CLSCLR);
490 lp->rsc_clsclr.header.length = htons (sizeof (lp->rsc_clsclr.value));
491 lp->rsc_clsclr.value = htonl (classcolor);
492 return;
493}
494
495static void
496initialize_linkparams (struct mpls_te_link *lp)
497{
498 struct interface *ifp = lp->ifp;
499 struct ospf_interface *oi;
500 float fval;
501 int i;
502
503 if ((oi = lookup_oi_by_ifp (ifp, NULL, OI_ANY)) == NULL)
504 return;
505
506 /*
507 * Try to set initial values those can be derived from
508 * zebra-interface information.
509 */
510 set_linkparams_link_type (oi, lp);
511
512 /*
513 * Linux and *BSD kernel holds bandwidth parameter as an "int" type.
514 * We may have to reconsider, if "ifp->bandwidth" type changes to float.
515 */
516 fval = (float)((ifp->bandwidth ? ifp->bandwidth
517 : OSPF_DEFAULT_BANDWIDTH) * 1000 / 8);
518
519 set_linkparams_max_bw (lp, &fval);
520 set_linkparams_max_rsv_bw (lp, &fval);
521
522 for (i = 0; i < 8; i++)
523 set_linkparams_unrsv_bw (lp, i, &fval);
524
525 return;
526}
527
528static int
529is_mandated_params_set (struct mpls_te_link *lp)
530{
531 int rc = 0;
532
533 if (ntohs (OspfMplsTE.router_addr.header.type) == 0)
534 goto out;
535
536 if (ntohs (lp->link_type.header.type) == 0)
537 goto out;
538
539 if (ntohs (lp->link_id.header.type) == 0)
540 goto out;
541
542 rc = 1;
543out:
544 return rc;
545}
546
547/*------------------------------------------------------------------------*
548 * Followings are callback functions against generic Opaque-LSAs handling.
549 *------------------------------------------------------------------------*/
550
551static int
552ospf_mpls_te_new_if (struct interface *ifp)
553{
554 struct mpls_te_link *new;
555 int rc = -1;
556
557 if (lookup_linkparams_by_ifp (ifp) != NULL)
558 {
559 zlog_warn ("ospf_mpls_te_new_if: ifp(%p) already in use?", ifp);
560 rc = 0; /* Do nothing here. */
561 goto out;
562 }
563
564 if ((new = XMALLOC (MTYPE_OSPF_MPLS_TE_LINKPARAMS,
565 sizeof (struct mpls_te_link))) == NULL)
566 {
6099b3b5 567 zlog_warn ("ospf_mpls_te_new_if: XMALLOC: %s", safe_strerror (errno));
718e3744 568 goto out;
569 }
570 memset (new, 0, sizeof (struct mpls_te_link));
571
572 new->area = NULL;
573 new->flags = 0;
574 new->instance = get_mpls_te_instance_value ();
575 new->ifp = ifp;
576
577 initialize_linkparams (new);
578
579 listnode_add (OspfMplsTE.iflist, new);
580
581 /* Schedule Opaque-LSA refresh. *//* XXX */
582
583 rc = 0;
584out:
585 return rc;
586}
587
588static int
589ospf_mpls_te_del_if (struct interface *ifp)
590{
591 struct mpls_te_link *lp;
592 int rc = -1;
593
594 if ((lp = lookup_linkparams_by_ifp (ifp)) != NULL)
595 {
87d6f87a 596 struct list *iflist = OspfMplsTE.iflist;
718e3744 597
598 /* Dequeue listnode entry from the list. */
599 listnode_delete (iflist, lp);
600
601 /* Avoid misjudgement in the next lookup. */
602 if (listcount (iflist) == 0)
603 iflist->head = iflist->tail = NULL;
604
605 XFREE (MTYPE_OSPF_MPLS_TE_LINKPARAMS, lp);
606 }
607
608 /* Schedule Opaque-LSA refresh. *//* XXX */
609
610 rc = 0;
611/*out:*/
612 return rc;
613}
614
615static void
616ospf_mpls_te_ism_change (struct ospf_interface *oi, int old_state)
617{
618 struct te_link_subtlv_link_type old_type;
619 struct te_link_subtlv_link_id old_id;
620 struct mpls_te_link *lp;
621
622 if ((lp = lookup_linkparams_by_ifp (oi->ifp)) == NULL)
623 {
624 zlog_warn ("ospf_mpls_te_ism_change: Cannot get linkparams from OI(%s)?", IF_NAME (oi));
625 goto out;
626 }
d4a53d58 627 if (oi->area == NULL || oi->area->ospf == NULL)
718e3744 628 {
629 zlog_warn ("ospf_mpls_te_ism_change: Cannot refer to OSPF from OI(%s)?",
630IF_NAME (oi));
631 goto out;
632 }
633#ifdef notyet
634 if ((lp->area != NULL
635 && ! IPV4_ADDR_SAME (&lp->area->area_id, &oi->area->area_id))
636 || (lp->area != NULL && oi->area == NULL))
637 {
638 /* How should we consider this case? */
639 zlog_warn ("MPLS-TE: Area for OI(%s) has changed to [%s], flush previous LSAs", IF_NAME (oi), oi->area ? inet_ntoa (oi->area->area_id) : "N/A");
640 ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
641 }
642#endif
643 /* Keep Area information in conbination with linkparams. */
644 lp->area = oi->area;
645
646 switch (oi->state)
647 {
648 case ISM_PointToPoint:
649 case ISM_DROther:
650 case ISM_Backup:
651 case ISM_DR:
652 old_type = lp->link_type;
653 old_id = lp->link_id;
654
655 set_linkparams_link_type (oi, lp);
656 set_linkparams_link_id (oi, lp);
657
658 if ((ntohs (old_type.header.type) != ntohs (lp->link_type.header.type)
659 || old_type.link_type.value != lp->link_type.link_type.value)
660 || (ntohs (old_id.header.type) != ntohs (lp->link_id.header.type)
661 || ntohl (old_id.value.s_addr) != ntohl (lp->link_id.value.s_addr)))
662 {
663 if (lp->flags & LPFLG_LSA_ENGAGED)
664 ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
665 else
666 ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
667 }
668 break;
669 default:
670 lp->link_type.header.type = htons (0);
671 lp->link_id.header.type = htons (0);
672
673 if (lp->flags & LPFLG_LSA_ENGAGED)
674 ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
675 break;
676 }
677
678out:
679 return;
680}
681
682static void
683ospf_mpls_te_nsm_change (struct ospf_neighbor *nbr, int old_state)
684{
685 /* So far, nothing to do here. */
686 return;
687}
688
689/*------------------------------------------------------------------------*
690 * Followings are OSPF protocol processing functions for MPLS-TE.
691 *------------------------------------------------------------------------*/
692
693static void
694build_tlv_header (struct stream *s, struct te_tlv_header *tlvh)
695{
696 stream_put (s, tlvh, sizeof (struct te_tlv_header));
697 return;
698}
699
700static void
701build_router_tlv (struct stream *s)
702{
703 struct te_tlv_header *tlvh = &OspfMplsTE.router_addr.header;
704 if (ntohs (tlvh->type) != 0)
705 {
706 build_tlv_header (s, tlvh);
707 stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
708 }
709 return;
710}
711
712static void
713build_link_subtlv_link_type (struct stream *s, struct mpls_te_link *lp)
714{
715 struct te_tlv_header *tlvh = &lp->link_type.header;
716 if (ntohs (tlvh->type) != 0)
717 {
718 build_tlv_header (s, tlvh);
719 stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
720 }
721 return;
722}
723
724static void
725build_link_subtlv_link_id (struct stream *s, struct mpls_te_link *lp)
726{
727 struct te_tlv_header *tlvh = &lp->link_id.header;
728 if (ntohs (tlvh->type) != 0)
729 {
730 build_tlv_header (s, tlvh);
731 stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
732 }
733 return;
734}
735
736static void
737build_link_subtlv_lclif_ipaddr (struct stream *s, struct mpls_te_link *lp)
738{
739 struct te_tlv_header *tlvh = (struct te_tlv_header *) lp->lclif_ipaddr;
740 if (tlvh != NULL && ntohs (tlvh->type) != 0)
741 {
742 build_tlv_header (s, tlvh);
743 stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
744 }
745 return;
746}
747
748static void
749build_link_subtlv_rmtif_ipaddr (struct stream *s, struct mpls_te_link *lp)
750{
751 struct te_tlv_header *tlvh = (struct te_tlv_header *) lp->rmtif_ipaddr;
752 if (tlvh != NULL && ntohs (tlvh->type) != 0)
753 {
754 build_tlv_header (s, tlvh);
755 stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
756 }
757 return;
758}
759
760static void
761build_link_subtlv_te_metric (struct stream *s, struct mpls_te_link *lp)
762{
763 struct te_tlv_header *tlvh = &lp->te_metric.header;
764 if (ntohs (tlvh->type) != 0)
765 {
766 build_tlv_header (s, tlvh);
767 stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
768 }
769 return;
770}
771
772static void
773build_link_subtlv_max_bw (struct stream *s, struct mpls_te_link *lp)
774{
775 struct te_tlv_header *tlvh = &lp->max_bw.header;
776 if (ntohs (tlvh->type) != 0)
777 {
778 build_tlv_header (s, tlvh);
779 stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
780 }
781 return;
782}
783
784static void
785build_link_subtlv_max_rsv_bw (struct stream *s, struct mpls_te_link *lp)
786{
787 struct te_tlv_header *tlvh = &lp->max_rsv_bw.header;
788 if (ntohs (tlvh->type) != 0)
789 {
790 build_tlv_header (s, tlvh);
791 stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
792 }
793 return;
794}
795
796static void
797build_link_subtlv_unrsv_bw (struct stream *s, struct mpls_te_link *lp)
798{
799 struct te_tlv_header *tlvh = &lp->unrsv_bw.header;
800 if (ntohs (tlvh->type) != 0)
801 {
802 build_tlv_header (s, tlvh);
803 stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
804 }
805 return;
806}
807
808static void
809build_link_subtlv_rsc_clsclr (struct stream *s, struct mpls_te_link *lp)
810{
811 struct te_tlv_header *tlvh = &lp->rsc_clsclr.header;
812 if (ntohs (tlvh->type) != 0)
813 {
814 build_tlv_header (s, tlvh);
815 stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh));
816 }
817 return;
818}
819
820static void
821build_link_tlv (struct stream *s, struct mpls_te_link *lp)
822{
823 set_linkparams_link_header (lp);
824 build_tlv_header (s, &lp->link_header.header);
825
826 build_link_subtlv_link_type (s, lp);
827 build_link_subtlv_link_id (s, lp);
828 build_link_subtlv_lclif_ipaddr (s, lp);
829 build_link_subtlv_rmtif_ipaddr (s, lp);
830 build_link_subtlv_te_metric (s, lp);
831 build_link_subtlv_max_bw (s, lp);
832 build_link_subtlv_max_rsv_bw (s, lp);
833 build_link_subtlv_unrsv_bw (s, lp);
834 build_link_subtlv_rsc_clsclr (s, lp);
835 return;
836}
837
838static void
839ospf_mpls_te_lsa_body_set (struct stream *s, struct mpls_te_link *lp)
840{
841 /*
842 * The router address TLV is type 1, and ...
843 * It must appear in exactly one
844 * Traffic Engineering LSA originated by a router.
845 */
846 build_router_tlv (s);
847
848 /*
849 * Only one Link TLV shall be carried in each LSA, allowing for fine
850 * granularity changes in topology.
851 */
852 build_link_tlv (s, lp);
853 return;
854}
855
856/* Create new opaque-LSA. */
857static struct ospf_lsa *
858ospf_mpls_te_lsa_new (struct ospf_area *area, struct mpls_te_link *lp)
859{
860 struct stream *s;
861 struct lsa_header *lsah;
862 struct ospf_lsa *new = NULL;
863 u_char options, lsa_type;
864 struct in_addr lsa_id;
865 u_int32_t tmp;
866 u_int16_t length;
867
868 /* Create a stream for LSA. */
869 if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL)
870 {
871 zlog_warn ("ospf_mpls_te_lsa_new: stream_new() ?");
872 goto out;
873 }
874 lsah = (struct lsa_header *) STREAM_DATA (s);
875
876 options = LSA_OPTIONS_GET (area);
d4a53d58 877 options |= LSA_OPTIONS_NSSA_GET (area);
718e3744 878 options |= OSPF_OPTION_O; /* Don't forget this :-) */
879
880 lsa_type = OSPF_OPAQUE_AREA_LSA;
881 tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA, lp->instance);
882 lsa_id.s_addr = htonl (tmp);
883
884 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
2a42e285 885 zlog_debug ("LSA[Type%d:%s]: Create an Opaque-LSA/MPLS-TE instance", lsa_type, inet_ntoa (lsa_id));
718e3744 886
887 /* Set opaque-LSA header fields. */
d4a53d58 888 lsa_header_set (s, options, lsa_type, lsa_id, area->ospf->router_id);
718e3744 889
890 /* Set opaque-LSA body fields. */
891 ospf_mpls_te_lsa_body_set (s, lp);
892
893 /* Set length. */
894 length = stream_get_endp (s);
895 lsah->length = htons (length);
896
897 /* Now, create an OSPF LSA instance. */
898 if ((new = ospf_lsa_new ()) == NULL)
899 {
900 zlog_warn ("ospf_mpls_te_lsa_new: ospf_lsa_new() ?");
901 stream_free (s);
902 goto out;
903 }
904 if ((new->data = ospf_lsa_data_new (length)) == NULL)
905 {
906 zlog_warn ("ospf_mpls_te_lsa_new: ospf_lsa_data_new() ?");
788dab10 907 ospf_lsa_unlock (new);
718e3744 908 new = NULL;
909 stream_free (s);
910 goto out;
911 }
912
913 new->area = area;
914 SET_FLAG (new->flags, OSPF_LSA_SELF);
915 memcpy (new->data, lsah, length);
916 stream_free (s);
917
918out:
919 return new;
920}
921
922static int
923ospf_mpls_te_lsa_originate1 (struct ospf_area *area, struct mpls_te_link *lp)
924{
925 struct ospf_lsa *new;
926 int rc = -1;
927
928 /* Create new Opaque-LSA/MPLS-TE instance. */
929 if ((new = ospf_mpls_te_lsa_new (area, lp)) == NULL)
930 {
931 zlog_warn ("ospf_mpls_te_lsa_originate1: ospf_mpls_te_lsa_new() ?");
932 goto out;
933 }
934
935 /* Install this LSA into LSDB. */
d4a53d58 936 if (ospf_lsa_install (area->ospf, NULL/*oi*/, new) == NULL)
718e3744 937 {
938 zlog_warn ("ospf_mpls_te_lsa_originate1: ospf_lsa_install() ?");
788dab10 939 ospf_lsa_unlock (new);
718e3744 940 goto out;
941 }
942
943 /* Now this linkparameter entry has associated LSA. */
944 lp->flags |= LPFLG_LSA_ENGAGED;
945
946 /* Update new LSA origination count. */
d4a53d58 947 area->ospf->lsa_originate_count++;
718e3744 948
949 /* Flood new LSA through area. */
950 ospf_flood_through_area (area, NULL/*nbr*/, new);
951
952 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
953 {
954 char area_id[INET_ADDRSTRLEN];
955 strcpy (area_id, inet_ntoa (area->area_id));
2a42e285 956 zlog_debug ("LSA[Type%d:%s]: Originate Opaque-LSA/MPLS-TE: Area(%s), Link(%s)", new->data->type, inet_ntoa (new->data->id), area_id, lp->ifp->name);
718e3744 957 ospf_lsa_header_dump (new->data);
958 }
959
960 rc = 0;
961out:
962 return rc;
963}
964
965static int
966ospf_mpls_te_lsa_originate (void *arg)
967{
968 struct ospf_area *area = (struct ospf_area *) arg;
1eb8ef25 969 struct listnode *node, *nnode;
718e3744 970 struct mpls_te_link *lp;
971 int rc = -1;
972
973 if (OspfMplsTE.status == disabled)
974 {
975 zlog_info ("ospf_mpls_te_lsa_originate: MPLS-TE is disabled now.");
976 rc = 0; /* This is not an error case. */
977 goto out;
978 }
979
1eb8ef25 980 for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
718e3744 981 {
718e3744 982 if (lp->area == NULL)
983 continue;
984 if (! IPV4_ADDR_SAME (&lp->area->area_id, &area->area_id))
985 continue;
986
987 if (lp->flags & LPFLG_LSA_ENGAGED)
988 {
989 if (lp->flags & LPFLG_LSA_FORCED_REFRESH)
990 {
991 lp->flags &= ~LPFLG_LSA_FORCED_REFRESH;
992 ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
993 }
994 continue;
995 }
996 if (! is_mandated_params_set (lp))
997 {
998 zlog_warn ("ospf_mpls_te_lsa_originate: Link(%s) lacks some mandated MPLS-TE parameters.", lp->ifp ? lp->ifp->name : "?");
999 continue;
1000 }
1001
1002 /* Ok, let's try to originate an LSA for this area and Link. */
1003 if (ospf_mpls_te_lsa_originate1 (area, lp) != 0)
1004 goto out;
1005 }
1006
1007 rc = 0;
1008out:
1009 return rc;
1010}
1011
1012static void
1013ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa)
1014{
1015 struct mpls_te_link *lp;
1016 struct ospf_area *area = lsa->area;
1017 struct ospf_lsa *new = NULL;
1018
1019 if (OspfMplsTE.status == disabled)
1020 {
1021 /*
1022 * This LSA must have flushed before due to MPLS-TE status change.
1023 * It seems a slip among routers in the routing domain.
1024 */
1025 zlog_info ("ospf_mpls_te_lsa_refresh: MPLS-TE is disabled now.");
1026 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
1027 }
1028
1029 /* At first, resolve lsa/lp relationship. */
1030 if ((lp = lookup_linkparams_by_instance (lsa)) == NULL)
1031 {
1032 zlog_warn ("ospf_mpls_te_lsa_refresh: Invalid parameter?");
1033 lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
1034 }
1035
1036 /* If the lsa's age reached to MaxAge, start flushing procedure. */
1037 if (IS_LSA_MAXAGE (lsa))
1038 {
1039 lp->flags &= ~LPFLG_LSA_ENGAGED;
1040 ospf_opaque_lsa_flush_schedule (lsa);
1041 goto out;
1042 }
1043
1044 /* Create new Opaque-LSA/MPLS-TE instance. */
1045 if ((new = ospf_mpls_te_lsa_new (area, lp)) == NULL)
1046 {
1047 zlog_warn ("ospf_mpls_te_lsa_refresh: ospf_mpls_te_lsa_new() ?");
1048 goto out;
1049 }
1050 new->data->ls_seqnum = lsa_seqnum_increment (lsa);
1051
1052 /* Install this LSA into LSDB. */
1053 /* Given "lsa" will be freed in the next function. */
d4a53d58 1054 if (ospf_lsa_install (area->ospf, NULL/*oi*/, new) == NULL)
718e3744 1055 {
1056 zlog_warn ("ospf_mpls_te_lsa_refresh: ospf_lsa_install() ?");
788dab10 1057 ospf_lsa_unlock (new);
718e3744 1058 goto out;
1059 }
1060
1061 /* Flood updated LSA through area. */
1062 ospf_flood_through_area (area, NULL/*nbr*/, new);
1063
1064 /* Debug logging. */
1065 if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
1066 {
2a42e285 1067 zlog_debug ("LSA[Type%d:%s]: Refresh Opaque-LSA/MPLS-TE",
718e3744 1068 new->data->type, inet_ntoa (new->data->id));
1069 ospf_lsa_header_dump (new->data);
1070 }
1071
1072out:
1073 return;
1074}
1075
1076static void
1077ospf_mpls_te_lsa_schedule (struct mpls_te_link *lp,
1078 enum sched_opcode opcode)
1079{
1080 struct ospf_lsa lsa;
1081 struct lsa_header lsah;
1082 u_int32_t tmp;
1083
1084 memset (&lsa, 0, sizeof (lsa));
1085 memset (&lsah, 0, sizeof (lsah));
1086
1087 lsa.area = lp->area;
1088 lsa.data = &lsah;
1089 lsah.type = OSPF_OPAQUE_AREA_LSA;
1090 tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA, lp->instance);
1091 lsah.id.s_addr = htonl (tmp);
1092
1093 switch (opcode)
1094 {
1095 case REORIGINATE_PER_AREA:
1096 ospf_opaque_lsa_reoriginate_schedule ((void *) lp->area,
1097 OSPF_OPAQUE_AREA_LSA, OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA);
1098 break;
1099 case REFRESH_THIS_LSA:
1100 ospf_opaque_lsa_refresh_schedule (&lsa);
1101 break;
1102 case FLUSH_THIS_LSA:
1103 lp->flags &= ~LPFLG_LSA_ENGAGED;
1104 ospf_opaque_lsa_flush_schedule (&lsa);
1105 break;
1106 default:
1107 zlog_warn ("ospf_mpls_te_lsa_schedule: Unknown opcode (%u)", opcode);
1108 break;
1109 }
1110
1111 return;
1112}
1113
1114/*------------------------------------------------------------------------*
1115 * Followings are vty session control functions.
1116 *------------------------------------------------------------------------*/
1117
1118static u_int16_t
1119show_vty_router_addr (struct vty *vty, struct te_tlv_header *tlvh)
1120{
1121 struct te_tlv_router_addr *top = (struct te_tlv_router_addr *) tlvh;
1122
1123 if (vty != NULL)
1124 vty_out (vty, " Router-Address: %s%s", inet_ntoa (top->value), VTY_NEWLINE);
1125 else
2a42e285 1126 zlog_debug (" Router-Address: %s", inet_ntoa (top->value));
718e3744 1127
1128 return TLV_SIZE (tlvh);
1129}
1130
1131static u_int16_t
1132show_vty_link_header (struct vty *vty, struct te_tlv_header *tlvh)
1133{
1134 struct te_tlv_link *top = (struct te_tlv_link *) tlvh;
1135
1136 if (vty != NULL)
1137 vty_out (vty, " Link: %u octets of data%s", ntohs (top->header.length), VTY_NEWLINE);
1138 else
2a42e285 1139 zlog_debug (" Link: %u octets of data", ntohs (top->header.length));
718e3744 1140
1141 return TLV_HDR_SIZE; /* Here is special, not "TLV_SIZE". */
1142}
1143
1144static u_int16_t
1145show_vty_link_subtlv_link_type (struct vty *vty, struct te_tlv_header *tlvh)
1146{
1147 struct te_link_subtlv_link_type *top;
1148 const char *cp = "Unknown";
1149
1150 top = (struct te_link_subtlv_link_type *) tlvh;
1151 switch (top->link_type.value)
1152 {
1153 case LINK_TYPE_SUBTLV_VALUE_PTP:
1154 cp = "Point-to-point";
1155 break;
1156 case LINK_TYPE_SUBTLV_VALUE_MA:
1157 cp = "Multiaccess";
1158 break;
1159 default:
1160 break;
1161 }
1162
1163 if (vty != NULL)
1164 vty_out (vty, " Link-Type: %s (%u)%s", cp, top->link_type.value, VTY_NEWLINE);
1165 else
2a42e285 1166 zlog_debug (" Link-Type: %s (%u)", cp, top->link_type.value);
718e3744 1167
1168 return TLV_SIZE (tlvh);
1169}
1170
1171static u_int16_t
1172show_vty_link_subtlv_link_id (struct vty *vty, struct te_tlv_header *tlvh)
1173{
1174 struct te_link_subtlv_link_id *top;
1175
1176 top = (struct te_link_subtlv_link_id *) tlvh;
1177 if (vty != NULL)
1178 vty_out (vty, " Link-ID: %s%s", inet_ntoa (top->value), VTY_NEWLINE);
1179 else
2a42e285 1180 zlog_debug (" Link-ID: %s", inet_ntoa (top->value));
718e3744 1181
1182 return TLV_SIZE (tlvh);
1183}
1184
1185static u_int16_t
1186show_vty_link_subtlv_lclif_ipaddr (struct vty *vty, struct te_tlv_header *tlvh)
1187{
1188 struct te_link_subtlv_lclif_ipaddr *top;
1189 int i, n;
1190
1191 top = (struct te_link_subtlv_lclif_ipaddr *) tlvh;
1192 n = ntohs (tlvh->length) / sizeof (top->value[0]);
1193
1194 if (vty != NULL)
1195 vty_out (vty, " Local Interface IP Address(es): %d%s", n, VTY_NEWLINE);
1196 else
2a42e285 1197 zlog_debug (" Local Interface IP Address(es): %d", n);
718e3744 1198
1199 for (i = 0; i < n; i++)
1200 {
1201 if (vty != NULL)
1202 vty_out (vty, " #%d: %s%s", i, inet_ntoa (top->value[i]), VTY_NEWLINE);
1203 else
2a42e285 1204 zlog_debug (" #%d: %s", i, inet_ntoa (top->value[i]));
718e3744 1205 }
1206 return TLV_SIZE (tlvh);
1207}
1208
1209static u_int16_t
1210show_vty_link_subtlv_rmtif_ipaddr (struct vty *vty, struct te_tlv_header *tlvh)
1211{
1212 struct te_link_subtlv_rmtif_ipaddr *top;
1213 int i, n;
1214
1215 top = (struct te_link_subtlv_rmtif_ipaddr *) tlvh;
1216 n = ntohs (tlvh->length) / sizeof (top->value[0]);
1217 if (vty != NULL)
1218 vty_out (vty, " Remote Interface IP Address(es): %d%s", n, VTY_NEWLINE);
1219 else
2a42e285 1220 zlog_debug (" Remote Interface IP Address(es): %d", n);
718e3744 1221
1222 for (i = 0; i < n; i++)
1223 {
1224 if (vty != NULL)
1225 vty_out (vty, " #%d: %s%s", i, inet_ntoa (top->value[i]), VTY_NEWLINE);
1226 else
2a42e285 1227 zlog_debug (" #%d: %s", i, inet_ntoa (top->value[i]));
718e3744 1228 }
1229 return TLV_SIZE (tlvh);
1230}
1231
1232static u_int16_t
1233show_vty_link_subtlv_te_metric (struct vty *vty, struct te_tlv_header *tlvh)
1234{
1235 struct te_link_subtlv_te_metric *top;
1236
1237 top = (struct te_link_subtlv_te_metric *) tlvh;
1238 if (vty != NULL)
1239 vty_out (vty, " Traffic Engineering Metric: %u%s", (u_int32_t) ntohl (top->value), VTY_NEWLINE);
1240 else
2a42e285 1241 zlog_debug (" Traffic Engineering Metric: %u", (u_int32_t) ntohl (top->value));
718e3744 1242
1243 return TLV_SIZE (tlvh);
1244}
1245
1246static u_int16_t
1247show_vty_link_subtlv_max_bw (struct vty *vty, struct te_tlv_header *tlvh)
1248{
1249 struct te_link_subtlv_max_bw *top;
1250 float fval;
1251
1252 top = (struct te_link_subtlv_max_bw *) tlvh;
1253 ntohf (&top->value, &fval);
1254
1255 if (vty != NULL)
1256 vty_out (vty, " Maximum Bandwidth: %g (Bytes/sec)%s", fval, VTY_NEWLINE);
1257 else
2a42e285 1258 zlog_debug (" Maximum Bandwidth: %g (Bytes/sec)", fval);
718e3744 1259
1260 return TLV_SIZE (tlvh);
1261}
1262
1263static u_int16_t
1264show_vty_link_subtlv_max_rsv_bw (struct vty *vty, struct te_tlv_header *tlvh)
1265{
1266 struct te_link_subtlv_max_rsv_bw *top;
1267 float fval;
1268
1269 top = (struct te_link_subtlv_max_rsv_bw *) tlvh;
1270 ntohf (&top->value, &fval);
1271
1272 if (vty != NULL)
1273 vty_out (vty, " Maximum Reservable Bandwidth: %g (Bytes/sec)%s", fval, VTY_NEWLINE);
1274 else
2a42e285 1275 zlog_debug (" Maximum Reservable Bandwidth: %g (Bytes/sec)", fval);
718e3744 1276
1277 return TLV_SIZE (tlvh);
1278}
1279
1280static u_int16_t
1281show_vty_link_subtlv_unrsv_bw (struct vty *vty, struct te_tlv_header *tlvh)
1282{
1283 struct te_link_subtlv_unrsv_bw *top;
1284 float fval;
1285 int i;
1286
1287 top = (struct te_link_subtlv_unrsv_bw *) tlvh;
1288 for (i = 0; i < 8; i++)
1289 {
1290 ntohf (&top->value[i], &fval);
1291 if (vty != NULL)
1292 vty_out (vty, " Unreserved Bandwidth (pri %d): %g (Bytes/sec)%s", i, fval, VTY_NEWLINE);
1293 else
2a42e285 1294 zlog_debug (" Unreserved Bandwidth (pri %d): %g (Bytes/sec)", i, fval);
718e3744 1295 }
1296
1297 return TLV_SIZE (tlvh);
1298}
1299
1300static u_int16_t
1301show_vty_link_subtlv_rsc_clsclr (struct vty *vty, struct te_tlv_header *tlvh)
1302{
1303 struct te_link_subtlv_rsc_clsclr *top;
1304
1305 top = (struct te_link_subtlv_rsc_clsclr *) tlvh;
1306 if (vty != NULL)
1307 vty_out (vty, " Resource class/color: 0x%x%s", (u_int32_t) ntohl (top->value), VTY_NEWLINE);
1308 else
2a42e285 1309 zlog_debug (" Resource Class/Color: 0x%x", (u_int32_t) ntohl (top->value));
718e3744 1310
1311 return TLV_SIZE (tlvh);
1312}
1313
1314static u_int16_t
1315show_vty_unknown_tlv (struct vty *vty, struct te_tlv_header *tlvh)
1316{
1317 if (vty != NULL)
1318 vty_out (vty, " Unknown TLV: [type(0x%x), length(0x%x)]%s", ntohs (tlvh->type), ntohs (tlvh->length), VTY_NEWLINE);
1319 else
2a42e285 1320 zlog_debug (" Unknown TLV: [type(0x%x), length(0x%x)]", ntohs (tlvh->type), ntohs (tlvh->length));
718e3744 1321
1322 return TLV_SIZE (tlvh);
1323}
1324
1325static u_int16_t
1326ospf_mpls_te_show_link_subtlv (struct vty *vty, struct te_tlv_header *tlvh0,
1327 u_int16_t subtotal, u_int16_t total)
1328{
1329 struct te_tlv_header *tlvh, *next;
1330 u_int16_t sum = subtotal;
1331
1332 for (tlvh = tlvh0; sum < total; tlvh = (next ? next : TLV_HDR_NEXT (tlvh)))
1333 {
1334 next = NULL;
1335 switch (ntohs (tlvh->type))
1336 {
1337 case TE_LINK_SUBTLV_LINK_TYPE:
1338 sum += show_vty_link_subtlv_link_type (vty, tlvh);
1339 break;
1340 case TE_LINK_SUBTLV_LINK_ID:
1341 sum += show_vty_link_subtlv_link_id (vty, tlvh);
1342 break;
1343 case TE_LINK_SUBTLV_LCLIF_IPADDR:
1344 sum += show_vty_link_subtlv_lclif_ipaddr (vty, tlvh);
1345 break;
1346 case TE_LINK_SUBTLV_RMTIF_IPADDR:
1347 sum += show_vty_link_subtlv_rmtif_ipaddr (vty, tlvh);
1348 break;
1349 case TE_LINK_SUBTLV_TE_METRIC:
1350 sum += show_vty_link_subtlv_te_metric (vty, tlvh);
1351 break;
1352 case TE_LINK_SUBTLV_MAX_BW:
1353 sum += show_vty_link_subtlv_max_bw (vty, tlvh);
1354 break;
1355 case TE_LINK_SUBTLV_MAX_RSV_BW:
1356 sum += show_vty_link_subtlv_max_rsv_bw (vty, tlvh);
1357 break;
1358 case TE_LINK_SUBTLV_UNRSV_BW:
1359 sum += show_vty_link_subtlv_unrsv_bw (vty, tlvh);
1360 break;
1361 case TE_LINK_SUBTLV_RSC_CLSCLR:
1362 sum += show_vty_link_subtlv_rsc_clsclr (vty, tlvh);
1363 break;
1364 default:
1365 sum += show_vty_unknown_tlv (vty, tlvh);
1366 break;
1367 }
1368 }
1369 return sum;
1370}
1371
1372static void
1373ospf_mpls_te_show_info (struct vty *vty, struct ospf_lsa *lsa)
1374{
1375 struct lsa_header *lsah = (struct lsa_header *) lsa->data;
1376 struct te_tlv_header *tlvh, *next;
1377 u_int16_t sum, total;
1378 u_int16_t (* subfunc)(struct vty *vty, struct te_tlv_header *tlvh,
1379 u_int16_t subtotal, u_int16_t total) = NULL;
1380
1381 sum = 0;
1382 total = ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE;
1383
1384 for (tlvh = TLV_HDR_TOP (lsah); sum < total;
1385 tlvh = (next ? next : TLV_HDR_NEXT (tlvh)))
1386 {
1387 if (subfunc != NULL)
1388 {
1389 sum = (* subfunc)(vty, tlvh, sum, total);
1390 next = (struct te_tlv_header *)((char *) tlvh + sum);
1391 subfunc = NULL;
1392 continue;
1393 }
1394
1395 next = NULL;
1396 switch (ntohs (tlvh->type))
1397 {
1398 case TE_TLV_ROUTER_ADDR:
1399 sum += show_vty_router_addr (vty, tlvh);
1400 break;
1401 case TE_TLV_LINK:
1402 sum += show_vty_link_header (vty, tlvh);
1403 subfunc = ospf_mpls_te_show_link_subtlv;
1404 next = tlvh + 1;
1405 break;
1406 default:
1407 sum += show_vty_unknown_tlv (vty, tlvh);
1408 break;
1409 }
1410 }
1411 return;
1412}
1413
1414static void
1415ospf_mpls_te_config_write_router (struct vty *vty)
1416{
1417 if (OspfMplsTE.status == enabled)
1418 {
1419 vty_out (vty, " mpls-te%s", VTY_NEWLINE);
1420 vty_out (vty, " mpls-te router-address %s%s",
1421 inet_ntoa (OspfMplsTE.router_addr.value), VTY_NEWLINE);
1422 }
1423 return;
1424}
1425
1426static void
1427ospf_mpls_te_config_write_if (struct vty *vty, struct interface *ifp)
1428{
1429 struct mpls_te_link *lp;
1430
1431 if ((OspfMplsTE.status == enabled)
1432 && (! if_is_loopback (ifp) && if_is_up (ifp) && ospf_oi_count (ifp) > 0)
1433 && ((lp = lookup_linkparams_by_ifp (ifp)) != NULL))
1434 {
1435 float fval;
1436 int i;
1437
1438 vty_out (vty, " mpls-te link metric %u%s",
1439 (u_int32_t) ntohl (lp->te_metric.value), VTY_NEWLINE);
1440
1441 ntohf (&lp->max_bw.value, &fval);
1442 if (fval >= MPLS_TE_MINIMUM_BANDWIDTH)
1443 vty_out (vty, " mpls-te link max-bw %g%s", fval, VTY_NEWLINE);
1444
1445 ntohf (&lp->max_rsv_bw.value, &fval);
1446 if (fval >= MPLS_TE_MINIMUM_BANDWIDTH)
1447 vty_out (vty, " mpls-te link max-rsv-bw %g%s", fval, VTY_NEWLINE);
1448
1449 for (i = 0; i < 8; i++)
1450 {
1451 ntohf (&lp->unrsv_bw.value[i], &fval);
1452 if (fval >= MPLS_TE_MINIMUM_BANDWIDTH)
1453 vty_out (vty, " mpls-te link unrsv-bw %d %g%s",
1454 i, fval, VTY_NEWLINE);
1455 }
1456
1457 vty_out (vty, " mpls-te link rsc-clsclr 0x%x%s",
1458 (u_int32_t) ntohl (lp->rsc_clsclr.value), VTY_NEWLINE);
1459 }
1460 return;
1461}
1462
1463/*------------------------------------------------------------------------*
1464 * Followings are vty command functions.
1465 *------------------------------------------------------------------------*/
1466
1467DEFUN (mpls_te,
1468 mpls_te_cmd,
1469 "mpls-te",
1470 "Configure MPLS-TE parameters\n"
1471 "Enable the MPLS-TE functionality\n")
1472{
1eb8ef25 1473 struct listnode *node, *nnode;
718e3744 1474 struct mpls_te_link *lp;
1475
1476 if (OspfMplsTE.status == enabled)
1477 return CMD_SUCCESS;
1478
1479 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1480 zlog_debug ("MPLS-TE: OFF -> ON");
718e3744 1481
1482 OspfMplsTE.status = enabled;
1483
1484 /*
1485 * Following code is intended to handle two cases;
1486 *
1487 * 1) MPLS-TE was disabled at startup time, but now become enabled.
1488 * 2) MPLS-TE was once enabled then disabled, and now enabled again.
1489 */
1eb8ef25 1490 for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
1491 initialize_linkparams (lp);
718e3744 1492
1493 ospf_mpls_te_foreach_area (ospf_mpls_te_lsa_schedule, REORIGINATE_PER_AREA);
1494
1495 return CMD_SUCCESS;
1496}
1497
1498ALIAS (mpls_te,
1499 mpls_te_on_cmd,
1500 "mpls-te on",
1501 "Configure MPLS-TE parameters\n"
1502 "Enable the MPLS-TE functionality\n")
1503
1504DEFUN (no_mpls_te,
1505 no_mpls_te_cmd,
1506 "no mpls-te",
1507 NO_STR
1508 "Configure MPLS-TE parameters\n"
1509 "Disable the MPLS-TE functionality\n")
1510{
1eb8ef25 1511 struct listnode *node, *nnode;
718e3744 1512 struct mpls_te_link *lp;
1513
1514 if (OspfMplsTE.status == disabled)
1515 return CMD_SUCCESS;
1516
1517 if (IS_DEBUG_OSPF_EVENT)
2a42e285 1518 zlog_debug ("MPLS-TE: ON -> OFF");
718e3744 1519
1520 OspfMplsTE.status = disabled;
1521
1eb8ef25 1522 for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
1523 if (lp->area != NULL)
1524 if (lp->flags & LPFLG_LSA_ENGAGED)
1525 ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA);
718e3744 1526
1527 return CMD_SUCCESS;
1528}
1529
1530DEFUN (mpls_te_router_addr,
1531 mpls_te_router_addr_cmd,
1532 "mpls-te router-address A.B.C.D",
1533 "MPLS-TE specific commands\n"
1534 "Stable IP address of the advertising router\n"
1535 "MPLS-TE router address in IPv4 address format\n")
1536{
1537 struct te_tlv_router_addr *ra = &OspfMplsTE.router_addr;
1538 struct in_addr value;
1539
1540 if (! inet_aton (argv[0], &value))
1541 {
1542 vty_out (vty, "Please specify Router-Addr by A.B.C.D%s", VTY_NEWLINE);
1543 return CMD_WARNING;
1544 }
1545
1546 if (ntohs (ra->header.type) == 0
87d6f87a 1547 || ntohl (ra->value.s_addr) != ntohl (value.s_addr))
718e3744 1548 {
1eb8ef25 1549 struct listnode *node, *nnode;
718e3744 1550 struct mpls_te_link *lp;
1551 int need_to_reoriginate = 0;
1552
1553 set_mpls_te_router_addr (value);
1554
1555 if (OspfMplsTE.status == disabled)
1556 goto out;
1557
1eb8ef25 1558 for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
718e3744 1559 {
718e3744 1560 if (lp->area == NULL)
1561 continue;
1562
1563 if ((lp->flags & LPFLG_LSA_ENGAGED) == 0)
1564 {
1565 need_to_reoriginate = 1;
1566 break;
1567 }
1568 }
1eb8ef25 1569
1570 for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
718e3744 1571 {
718e3744 1572 if (lp->area == NULL)
1573 continue;
1574
1575 if (need_to_reoriginate)
1576 lp->flags |= LPFLG_LSA_FORCED_REFRESH;
1577 else
1578 ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
1579 }
1580
1581 if (need_to_reoriginate)
1582 ospf_mpls_te_foreach_area (
1583 ospf_mpls_te_lsa_schedule, REORIGINATE_PER_AREA);
1584 }
1585out:
1586 return CMD_SUCCESS;
1587}
1588
1589DEFUN (mpls_te_link_metric,
1590 mpls_te_link_metric_cmd,
1591 "mpls-te link metric <0-4294967295>",
1592 "MPLS-TE specific commands\n"
1593 "Configure MPLS-TE link parameters\n"
1594 "Link metric for MPLS-TE purpose\n"
1595 "Metric\n")
1596{
1597 struct interface *ifp = (struct interface *) vty->index;
1598 struct mpls_te_link *lp;
1599 u_int32_t value;
1600
1601 if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL)
1602 {
1603 vty_out (vty, "mpls_te_link_metric: Something wrong!%s", VTY_NEWLINE);
1604 return CMD_WARNING;
1605 }
1606
1607 value = strtoul (argv[0], NULL, 10);
1608
1609 if (ntohs (lp->te_metric.header.type) == 0
1610 || ntohl (lp->te_metric.value) != value)
1611 {
1612 set_linkparams_te_metric (lp, value);
1613
1614 if (OspfMplsTE.status == enabled)
1615 if (lp->area != NULL)
1616 {
1617 if (lp->flags & LPFLG_LSA_ENGAGED)
1618 ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
1619 else
1620 ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
1621 }
1622 }
1623 return CMD_SUCCESS;
1624}
1625
1626DEFUN (mpls_te_link_maxbw,
1627 mpls_te_link_maxbw_cmd,
1628 "mpls-te link max-bw BANDWIDTH",
1629 "MPLS-TE specific commands\n"
1630 "Configure MPLS-TE link parameters\n"
1631 "Maximum bandwidth that can be used\n"
1632 "Bytes/second (IEEE floating point format)\n")
1633{
1634 struct interface *ifp = (struct interface *) vty->index;
1635 struct mpls_te_link *lp;
1636 float f1, f2;
1637
1638 if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL)
1639 {
1640 vty_out (vty, "mpls_te_link_maxbw: Something wrong!%s", VTY_NEWLINE);
1641 return CMD_WARNING;
1642 }
1643
1644 ntohf (&lp->max_bw.value, &f1);
1645 if (sscanf (argv[0], "%g", &f2) != 1)
1646 {
6099b3b5 1647 vty_out (vty, "mpls_te_link_maxbw: fscanf: %s%s", safe_strerror (errno), VTY_NEWLINE);
718e3744 1648 return CMD_WARNING;
1649 }
1650
1651 if (ntohs (lp->max_bw.header.type) == 0
1652 || f1 != f2)
1653 {
1654 set_linkparams_max_bw (lp, &f2);
1655
1656 if (OspfMplsTE.status == enabled)
1657 if (lp->area != NULL)
1658 {
1659 if (lp->flags & LPFLG_LSA_ENGAGED)
1660 ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
1661 else
1662 ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
1663 }
1664 }
1665 return CMD_SUCCESS;
1666}
1667
1668DEFUN (mpls_te_link_max_rsv_bw,
1669 mpls_te_link_max_rsv_bw_cmd,
1670 "mpls-te link max-rsv-bw BANDWIDTH",
1671 "MPLS-TE specific commands\n"
1672 "Configure MPLS-TE link parameters\n"
1673 "Maximum bandwidth that may be reserved\n"
1674 "Bytes/second (IEEE floating point format)\n")
1675{
1676 struct interface *ifp = (struct interface *) vty->index;
1677 struct mpls_te_link *lp;
1678 float f1, f2;
1679
1680 if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL)
1681 {
1682 vty_out (vty, "mpls_te_link_max_rsv_bw: Something wrong!%s", VTY_NEWLINE);
1683 return CMD_WARNING;
1684 }
1685
1686 ntohf (&lp->max_rsv_bw.value, &f1);
1687 if (sscanf (argv[0], "%g", &f2) != 1)
1688 {
6099b3b5 1689 vty_out (vty, "mpls_te_link_max_rsv_bw: fscanf: %s%s", safe_strerror (errno), VTY_NEWLINE);
718e3744 1690 return CMD_WARNING;
1691 }
1692
1693 if (ntohs (lp->max_rsv_bw.header.type) == 0
1694 || f1 != f2)
1695 {
1696 set_linkparams_max_rsv_bw (lp, &f2);
1697
1698 if (OspfMplsTE.status == enabled)
1699 if (lp->area != NULL)
1700 {
1701 if (lp->flags & LPFLG_LSA_ENGAGED)
1702 ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
1703 else
1704 ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
1705 }
1706 }
1707 return CMD_SUCCESS;
1708}
1709
1710DEFUN (mpls_te_link_unrsv_bw,
1711 mpls_te_link_unrsv_bw_cmd,
1712 "mpls-te link unrsv-bw <0-7> BANDWIDTH",
1713 "MPLS-TE specific commands\n"
1714 "Configure MPLS-TE link parameters\n"
1715 "Unreserved bandwidth at each priority level\n"
1716 "Priority\n"
1717 "Bytes/second (IEEE floating point format)\n")
1718{
1719 struct interface *ifp = (struct interface *) vty->index;
1720 struct mpls_te_link *lp;
1721 int priority;
1722 float f1, f2;
1723
1724 if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL)
1725 {
1726 vty_out (vty, "mpls_te_link_unrsv_bw: Something wrong!%s", VTY_NEWLINE);
1727 return CMD_WARNING;
1728 }
1729
1730 /* We don't have to consider about range check here. */
1731 if (sscanf (argv[0], "%d", &priority) != 1)
1732 {
6099b3b5 1733 vty_out (vty, "mpls_te_link_unrsv_bw: fscanf: %s%s", safe_strerror (errno), VTY_NEWLINE);
718e3744 1734 return CMD_WARNING;
1735 }
1736
1737 ntohf (&lp->unrsv_bw.value [priority], &f1);
1738 if (sscanf (argv[1], "%g", &f2) != 1)
1739 {
6099b3b5 1740 vty_out (vty, "mpls_te_link_unrsv_bw: fscanf: %s%s", safe_strerror (errno), VTY_NEWLINE);
718e3744 1741 return CMD_WARNING;
1742 }
1743
1744 if (ntohs (lp->unrsv_bw.header.type) == 0
1745 || f1 != f2)
1746 {
1747 set_linkparams_unrsv_bw (lp, priority, &f2);
1748
1749 if (OspfMplsTE.status == enabled)
1750 if (lp->area != NULL)
1751 {
1752 if (lp->flags & LPFLG_LSA_ENGAGED)
1753 ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
1754 else
1755 ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
1756 }
1757 }
1758 return CMD_SUCCESS;
1759}
1760
1761DEFUN (mpls_te_link_rsc_clsclr,
1762 mpls_te_link_rsc_clsclr_cmd,
1763 "mpls-te link rsc-clsclr BITPATTERN",
1764 "MPLS-TE specific commands\n"
1765 "Configure MPLS-TE link parameters\n"
1766 "Administrative group membership\n"
1767 "32-bit Hexadecimal value (ex. 0xa1)\n")
1768{
1769 struct interface *ifp = (struct interface *) vty->index;
1770 struct mpls_te_link *lp;
1771 unsigned long value;
1772
1773 if ((lp = lookup_linkparams_by_ifp (ifp)) == NULL)
1774 {
1775 vty_out (vty, "mpls_te_link_rsc_clsclr: Something wrong!%s", VTY_NEWLINE);
1776 return CMD_WARNING;
1777 }
1778
1779 if (sscanf (argv[0], "0x%lx", &value) != 1)
1780 {
6099b3b5 1781 vty_out (vty, "mpls_te_link_rsc_clsclr: fscanf: %s%s", safe_strerror (errno), VTY_NEWLINE);
718e3744 1782 return CMD_WARNING;
1783 }
1784
1785 if (ntohs (lp->rsc_clsclr.header.type) == 0
1786 || ntohl (lp->rsc_clsclr.value) != value)
1787 {
1788 set_linkparams_rsc_clsclr (lp, value);
1789
1790 if (OspfMplsTE.status == enabled)
1791 if (lp->area != NULL)
1792 {
1793 if (lp->flags & LPFLG_LSA_ENGAGED)
1794 ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA);
1795 else
1796 ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA);
1797 }
1798 }
1799 return CMD_SUCCESS;
1800}
1801
1802DEFUN (show_mpls_te_router,
1803 show_mpls_te_router_cmd,
1804 "show mpls-te router",
1805 SHOW_STR
1806 "MPLS-TE information\n"
1807 "Router information\n")
1808{
1809 if (OspfMplsTE.status == enabled)
1810 {
1811 vty_out (vty, "--- MPLS-TE router parameters ---%s",
1812 VTY_NEWLINE);
1813
1814 if (ntohs (OspfMplsTE.router_addr.header.type) != 0)
1815 show_vty_router_addr (vty, &OspfMplsTE.router_addr.header);
1816 else if (vty != NULL)
1817 vty_out (vty, " N/A%s", VTY_NEWLINE);
1818 }
1819 return CMD_SUCCESS;
1820}
1821
1822static void
1823show_mpls_te_link_sub (struct vty *vty, struct interface *ifp)
1824{
1825 struct mpls_te_link *lp;
1826 struct te_tlv_header *tlvh;
1827
1828 if ((OspfMplsTE.status == enabled)
1829 && (! if_is_loopback (ifp) && if_is_up (ifp) && ospf_oi_count (ifp) > 0)
1830 && ((lp = lookup_linkparams_by_ifp (ifp)) != NULL))
1831 {
1832 vty_out (vty, "-- MPLS-TE link parameters for %s --%s",
1833 ifp->name, VTY_NEWLINE);
1834
1835 show_vty_link_subtlv_link_type (vty, &lp->link_type.header);
1836 show_vty_link_subtlv_link_id (vty, &lp->link_id.header);
1837
1838 if ((tlvh = (struct te_tlv_header *) lp->lclif_ipaddr) != NULL)
1839 show_vty_link_subtlv_lclif_ipaddr (vty, tlvh);
1840 if ((tlvh = (struct te_tlv_header *) lp->rmtif_ipaddr) != NULL)
1841 show_vty_link_subtlv_rmtif_ipaddr (vty, tlvh);
1842
1843 show_vty_link_subtlv_te_metric (vty, &lp->te_metric.header);
1844
1845 show_vty_link_subtlv_max_bw (vty, &lp->max_bw.header);
1846 show_vty_link_subtlv_max_rsv_bw (vty, &lp->max_rsv_bw.header);
1847 show_vty_link_subtlv_unrsv_bw (vty, &lp->unrsv_bw.header);
1848 show_vty_link_subtlv_rsc_clsclr (vty, &lp->rsc_clsclr.header);
1849 }
1850 else
1851 {
1852 vty_out (vty, " %s: MPLS-TE is disabled on this interface%s",
1853 ifp->name, VTY_NEWLINE);
1854 }
1855
1856 return;
1857}
1858
1859DEFUN (show_mpls_te_link,
1860 show_mpls_te_link_cmd,
1861 "show mpls-te interface [INTERFACE]",
1862 SHOW_STR
1863 "MPLS-TE information\n"
1864 "Interface information\n"
1865 "Interface name\n")
1866{
1867 struct interface *ifp;
1eb8ef25 1868 struct listnode *node, *nnode;
718e3744 1869
1870 /* Show All Interfaces. */
1871 if (argc == 0)
eb1ce605 1872 {
1eb8ef25 1873 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
1874 show_mpls_te_link_sub (vty, ifp);
eb1ce605 1875 }
718e3744 1876 /* Interface name is specified. */
1877 else
1878 {
1879 if ((ifp = if_lookup_by_name (argv[0])) == NULL)
1880 vty_out (vty, "No such interface name%s", VTY_NEWLINE);
1881 else
1882 show_mpls_te_link_sub (vty, ifp);
1883 }
1884
1885 return CMD_SUCCESS;
1886}
1887
1888static void
1889ospf_mpls_te_register_vty (void)
1890{
1891 install_element (VIEW_NODE, &show_mpls_te_router_cmd);
1892 install_element (VIEW_NODE, &show_mpls_te_link_cmd);
1893 install_element (ENABLE_NODE, &show_mpls_te_router_cmd);
1894 install_element (ENABLE_NODE, &show_mpls_te_link_cmd);
1895
1896 install_element (OSPF_NODE, &mpls_te_cmd);
1897 install_element (OSPF_NODE, &no_mpls_te_cmd);
1898 install_element (OSPF_NODE, &mpls_te_on_cmd);
1899 install_element (OSPF_NODE, &mpls_te_router_addr_cmd);
1900
1901 install_element (INTERFACE_NODE, &mpls_te_link_metric_cmd);
1902 install_element (INTERFACE_NODE, &mpls_te_link_maxbw_cmd);
1903 install_element (INTERFACE_NODE, &mpls_te_link_max_rsv_bw_cmd);
1904 install_element (INTERFACE_NODE, &mpls_te_link_unrsv_bw_cmd);
1905 install_element (INTERFACE_NODE, &mpls_te_link_rsc_clsclr_cmd);
1906
1907 return;
1908}
1909
1910#endif /* HAVE_OSPF_TE */