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