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