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