blob: 03109bc82703fd9f6f137d9f61e8c2154913e99c [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. *****/
David Lamparter23757db2016-02-24 06:26:02 +010025#define MTYPE_OSPF_MPLS_TE_LINKPARAMS MTYPE_TMP
paul718e3742002-12-13 20:15:29 +000026
27#include <zebra.h>
28
paul718e3742002-12-13 20:15:29 +000029#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. */
60struct ospf_mpls_te
61{
62 enum { disabled, enabled } status;
63
64 /* List elements are zebra-interfaces (ifp), not ospf-interfaces (oi). */
paul87d6f872004-09-24 08:01:38 +000065 struct list *iflist;
paul718e3742002-12-13 20:15:29 +000066
67 /* Store Router-TLV in network byte order. */
68 struct te_tlv_router_addr router_addr;
69};
70
71struct 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 */
109static struct ospf_mpls_te OspfMplsTE;
110
111enum oifstate {
112 OI_ANY, OI_DOWN, OI_UP
113};
114
115enum 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
123static int ospf_mpls_te_new_if (struct interface *ifp);
124static int ospf_mpls_te_del_if (struct interface *ifp);
125static void ospf_mpls_te_ism_change (struct ospf_interface *oi, int old_status);
126static void ospf_mpls_te_nsm_change (struct ospf_neighbor *nbr, int old_status);
127static void ospf_mpls_te_config_write_router (struct vty *vty);
128static void ospf_mpls_te_config_write_if (struct vty *vty, struct interface *ifp);
129static void ospf_mpls_te_show_info (struct vty *vty, struct ospf_lsa *lsa);
130static int ospf_mpls_te_lsa_originate (void *arg);
Paul Jakma072990e2011-04-11 16:28:16 +0100131static struct ospf_lsa *ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa);
paul718e3742002-12-13 20:15:29 +0000132static void ospf_mpls_te_lsa_schedule (struct mpls_te_link *lp, enum sched_opcode);
133
134static void del_mpls_te_link (void *val);
135static void ospf_mpls_te_register_vty (void);
136
137int
138ospf_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
170out:
171 return rc;
172}
173
174void
175ospf_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
191static void
192del_mpls_te_link (void *val)
193{
194 XFREE (MTYPE_OSPF_MPLS_TE_LINKPARAMS, val);
195 return;
196}
197
198static u_int32_t
paul4dadc292005-05-06 21:37:42 +0000199get_mpls_te_instance_value (void)
paul718e3742002-12-13 20:15:29 +0000200{
201 static u_int32_t seqno = 0;
202
Andrew Certain703819a2012-12-04 13:36:41 -0800203 if (seqno < MAX_LEGAL_TE_INSTANCE_NUM )
paul718e3742002-12-13 20:15:29 +0000204 seqno += 1;
205 else
206 seqno = 1; /* Avoid zero. */
207
208 return seqno;
209}
210
211static struct ospf_interface *
212lookup_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 }
243out:
244 return NULL;
245}
246
247static struct mpls_te_link *
248lookup_linkparams_by_ifp (struct interface *ifp)
249{
paul1eb8ef22005-04-07 07:30:20 +0000250 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000251 struct mpls_te_link *lp;
252
paul1eb8ef22005-04-07 07:30:20 +0000253 for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
paul87d6f872004-09-24 08:01:38 +0000254 if (lp->ifp == ifp)
255 return lp;
paul718e3742002-12-13 20:15:29 +0000256
257 return NULL;
258}
259
260static struct mpls_te_link *
261lookup_linkparams_by_instance (struct ospf_lsa *lsa)
262{
paul87d6f872004-09-24 08:01:38 +0000263 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000264 struct mpls_te_link *lp;
paul6c835672004-10-11 11:00:30 +0000265 unsigned int key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr));
paul718e3742002-12-13 20:15:29 +0000266
paul1eb8ef22005-04-07 07:30:20 +0000267 for (ALL_LIST_ELEMENTS_RO (OspfMplsTE.iflist, node, lp))
paul87d6f872004-09-24 08:01:38 +0000268 if (lp->instance == key)
269 return lp;
paul718e3742002-12-13 20:15:29 +0000270
271 zlog_warn ("lookup_linkparams_by_instance: Entry not found: key(%x)", key);
272 return NULL;
273}
274
275static void
276ospf_mpls_te_foreach_area (
277 void (*func)(struct mpls_te_link *lp, enum sched_opcode),
278 enum sched_opcode sched_opcode)
279{
paul1eb8ef22005-04-07 07:30:20 +0000280 struct listnode *node, *nnode;
281 struct listnode *node2;
paul718e3742002-12-13 20:15:29 +0000282 struct mpls_te_link *lp;
283 struct ospf_area *area;
284
paul1eb8ef22005-04-07 07:30:20 +0000285 for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
paul718e3742002-12-13 20:15:29 +0000286 {
paul718e3742002-12-13 20:15:29 +0000287 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
paul1eb8ef22005-04-07 07:30:20 +0000295 for (node2 = listnextnode (node); node2; node2 = listnextnode (node2))
296 if ((lp = listgetdata (node2)) != NULL)
paul718e3742002-12-13 20:15:29 +0000297 if (lp->area != NULL)
298 if (IPV4_ADDR_SAME (&lp->area->area_id, &area->area_id))
299 lp->flags |= LPFLG_LOOKUP_DONE;
300 }
301
paul1eb8ef22005-04-07 07:30:20 +0000302 for (ALL_LIST_ELEMENTS_RO (OspfMplsTE.iflist, node, lp))
paul87d6f872004-09-24 08:01:38 +0000303 if (lp->area != NULL)
304 lp->flags &= ~LPFLG_LOOKUP_DONE;
paul718e3742002-12-13 20:15:29 +0000305
306 return;
307}
308
309static void
310set_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
318static void
319set_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
368static void
369set_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
391static void
392set_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. */
pauld4a53d52003-07-12 21:30:57 +0000408 if ((nbr = ospf_nbr_lookup_ptop (oi))
409 && nbr->state == NSM_Full)
paul718e3742002-12-13 20:15:29 +0000410 {
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))
pauld4a53d52003-07-12 21:30:57 +0000423 && ospf_nbr_count (oi, NSM_Full) > 0))
paul718e3742002-12-13 20:15:29 +0000424 {
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
444static void
445set_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
453static void
454set_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
462static void
463set_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
471static void
472set_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
481static void
482set_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
490static void
491initialize_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
523static int
524is_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;
538out:
539 return rc;
540}
541
542/*------------------------------------------------------------------------*
543 * Followings are callback functions against generic Opaque-LSAs handling.
544 *------------------------------------------------------------------------*/
545
546static int
547ospf_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 {
David Lampartereed3c482015-03-03 08:51:53 +0100554 zlog_warn ("ospf_mpls_te_new_if: ifp(%p) already in use?", (void *)ifp);
paul718e3742002-12-13 20:15:29 +0000555 rc = 0; /* Do nothing here. */
556 goto out;
557 }
558
Stephen Hemminger393deb92008-08-18 14:13:29 -0700559 new = XCALLOC (MTYPE_OSPF_MPLS_TE_LINKPARAMS,
560 sizeof (struct mpls_te_link));
561 if (new == NULL)
paul718e3742002-12-13 20:15:29 +0000562 {
ajs6099b3b2004-11-20 02:06:59 +0000563 zlog_warn ("ospf_mpls_te_new_if: XMALLOC: %s", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000564 goto out;
565 }
paul718e3742002-12-13 20:15:29 +0000566
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;
579out:
580 return rc;
581}
582
583static int
584ospf_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 {
paul87d6f872004-09-24 08:01:38 +0000591 struct list *iflist = OspfMplsTE.iflist;
paul718e3742002-12-13 20:15:29 +0000592
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
610static void
611ospf_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 }
pauld4a53d52003-07-12 21:30:57 +0000622 if (oi->area == NULL || oi->area->ospf == NULL)
paul718e3742002-12-13 20:15:29 +0000623 {
624 zlog_warn ("ospf_mpls_te_ism_change: Cannot refer to OSPF from OI(%s)?",
625IF_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
673out:
674 return;
675}
676
677static void
678ospf_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
688static void
689build_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
695static void
696build_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
707static void
708build_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
719static void
720build_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
731static void
732build_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
743static void
744build_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
755static void
756build_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
767static void
768build_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
779static void
780build_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
791static void
792build_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
803static void
804build_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
815static void
816build_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
833static void
834ospf_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. */
852static struct ospf_lsa *
853ospf_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);
pauld4a53d52003-07-12 21:30:57 +0000872 options |= LSA_OPTIONS_NSSA_GET (area);
paul718e3742002-12-13 20:15:29 +0000873 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))
ajs2a42e282004-12-08 18:43:03 +0000880 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 +0000881
882 /* Set opaque-LSA header fields. */
pauld4a53d52003-07-12 21:30:57 +0000883 lsa_header_set (s, options, lsa_type, lsa_id, area->ospf->router_id);
paul718e3742002-12-13 20:15:29 +0000884
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() ?");
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000902 ospf_lsa_unlock (&new);
paul718e3742002-12-13 20:15:29 +0000903 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
913out:
914 return new;
915}
916
917static int
918ospf_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. */
pauld4a53d52003-07-12 21:30:57 +0000931 if (ospf_lsa_install (area->ospf, NULL/*oi*/, new) == NULL)
paul718e3742002-12-13 20:15:29 +0000932 {
933 zlog_warn ("ospf_mpls_te_lsa_originate1: ospf_lsa_install() ?");
Paul Jakma1fe6ed32006-07-26 09:37:26 +0000934 ospf_lsa_unlock (&new);
paul718e3742002-12-13 20:15:29 +0000935 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. */
pauld4a53d52003-07-12 21:30:57 +0000942 area->ospf->lsa_originate_count++;
paul718e3742002-12-13 20:15:29 +0000943
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));
ajs2a42e282004-12-08 18:43:03 +0000951 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 +0000952 ospf_lsa_header_dump (new->data);
953 }
954
955 rc = 0;
956out:
957 return rc;
958}
959
960static int
961ospf_mpls_te_lsa_originate (void *arg)
962{
963 struct ospf_area *area = (struct ospf_area *) arg;
paul1eb8ef22005-04-07 07:30:20 +0000964 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000965 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
paul1eb8ef22005-04-07 07:30:20 +0000975 for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
paul718e3742002-12-13 20:15:29 +0000976 {
paul718e3742002-12-13 20:15:29 +0000977 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;
1003out:
1004 return rc;
1005}
1006
Paul Jakma072990e2011-04-11 16:28:16 +01001007static struct ospf_lsa *
paul718e3742002-12-13 20:15:29 +00001008ospf_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 {
Remi Gacognea11e0122013-09-08 13:48:34 +00001034 if (lp)
1035 lp->flags &= ~LPFLG_LSA_ENGAGED;
paul718e3742002-12-13 20:15:29 +00001036 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. */
pauld4a53d52003-07-12 21:30:57 +00001050 if (ospf_lsa_install (area->ospf, NULL/*oi*/, new) == NULL)
paul718e3742002-12-13 20:15:29 +00001051 {
1052 zlog_warn ("ospf_mpls_te_lsa_refresh: ospf_lsa_install() ?");
Paul Jakma1fe6ed32006-07-26 09:37:26 +00001053 ospf_lsa_unlock (&new);
paul718e3742002-12-13 20:15:29 +00001054 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 {
ajs2a42e282004-12-08 18:43:03 +00001063 zlog_debug ("LSA[Type%d:%s]: Refresh Opaque-LSA/MPLS-TE",
paul718e3742002-12-13 20:15:29 +00001064 new->data->type, inet_ntoa (new->data->id));
1065 ospf_lsa_header_dump (new->data);
1066 }
1067
1068out:
Paul Jakma072990e2011-04-11 16:28:16 +01001069 return new;
paul718e3742002-12-13 20:15:29 +00001070}
1071
1072static void
1073ospf_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
1114static u_int16_t
1115show_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
ajs2a42e282004-12-08 18:43:03 +00001122 zlog_debug (" Router-Address: %s", inet_ntoa (top->value));
paul718e3742002-12-13 20:15:29 +00001123
1124 return TLV_SIZE (tlvh);
1125}
1126
1127static u_int16_t
1128show_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
ajs2a42e282004-12-08 18:43:03 +00001135 zlog_debug (" Link: %u octets of data", ntohs (top->header.length));
paul718e3742002-12-13 20:15:29 +00001136
1137 return TLV_HDR_SIZE; /* Here is special, not "TLV_SIZE". */
1138}
1139
1140static u_int16_t
1141show_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
ajs2a42e282004-12-08 18:43:03 +00001162 zlog_debug (" Link-Type: %s (%u)", cp, top->link_type.value);
paul718e3742002-12-13 20:15:29 +00001163
1164 return TLV_SIZE (tlvh);
1165}
1166
1167static u_int16_t
1168show_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
ajs2a42e282004-12-08 18:43:03 +00001176 zlog_debug (" Link-ID: %s", inet_ntoa (top->value));
paul718e3742002-12-13 20:15:29 +00001177
1178 return TLV_SIZE (tlvh);
1179}
1180
1181static u_int16_t
1182show_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
ajs2a42e282004-12-08 18:43:03 +00001193 zlog_debug (" Local Interface IP Address(es): %d", n);
paul718e3742002-12-13 20:15:29 +00001194
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
ajs2a42e282004-12-08 18:43:03 +00001200 zlog_debug (" #%d: %s", i, inet_ntoa (top->value[i]));
paul718e3742002-12-13 20:15:29 +00001201 }
1202 return TLV_SIZE (tlvh);
1203}
1204
1205static u_int16_t
1206show_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
ajs2a42e282004-12-08 18:43:03 +00001216 zlog_debug (" Remote Interface IP Address(es): %d", n);
paul718e3742002-12-13 20:15:29 +00001217
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
ajs2a42e282004-12-08 18:43:03 +00001223 zlog_debug (" #%d: %s", i, inet_ntoa (top->value[i]));
paul718e3742002-12-13 20:15:29 +00001224 }
1225 return TLV_SIZE (tlvh);
1226}
1227
1228static u_int16_t
1229show_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
ajs2a42e282004-12-08 18:43:03 +00001237 zlog_debug (" Traffic Engineering Metric: %u", (u_int32_t) ntohl (top->value));
paul718e3742002-12-13 20:15:29 +00001238
1239 return TLV_SIZE (tlvh);
1240}
1241
1242static u_int16_t
1243show_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
ajs2a42e282004-12-08 18:43:03 +00001254 zlog_debug (" Maximum Bandwidth: %g (Bytes/sec)", fval);
paul718e3742002-12-13 20:15:29 +00001255
1256 return TLV_SIZE (tlvh);
1257}
1258
1259static u_int16_t
1260show_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
ajs2a42e282004-12-08 18:43:03 +00001271 zlog_debug (" Maximum Reservable Bandwidth: %g (Bytes/sec)", fval);
paul718e3742002-12-13 20:15:29 +00001272
1273 return TLV_SIZE (tlvh);
1274}
1275
1276static u_int16_t
1277show_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
ajs2a42e282004-12-08 18:43:03 +00001290 zlog_debug (" Unreserved Bandwidth (pri %d): %g (Bytes/sec)", i, fval);
paul718e3742002-12-13 20:15:29 +00001291 }
1292
1293 return TLV_SIZE (tlvh);
1294}
1295
1296static u_int16_t
1297show_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
ajs2a42e282004-12-08 18:43:03 +00001305 zlog_debug (" Resource Class/Color: 0x%x", (u_int32_t) ntohl (top->value));
paul718e3742002-12-13 20:15:29 +00001306
1307 return TLV_SIZE (tlvh);
1308}
1309
1310static u_int16_t
1311show_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
ajs2a42e282004-12-08 18:43:03 +00001316 zlog_debug (" Unknown TLV: [type(0x%x), length(0x%x)]", ntohs (tlvh->type), ntohs (tlvh->length));
paul718e3742002-12-13 20:15:29 +00001317
1318 return TLV_SIZE (tlvh);
1319}
1320
1321static u_int16_t
1322ospf_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
1368static void
1369ospf_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
1410static void
1411ospf_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
1422static void
1423ospf_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
1463DEFUN (mpls_te,
1464 mpls_te_cmd,
1465 "mpls-te",
1466 "Configure MPLS-TE parameters\n"
1467 "Enable the MPLS-TE functionality\n")
1468{
paul1eb8ef22005-04-07 07:30:20 +00001469 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001470 struct mpls_te_link *lp;
1471
1472 if (OspfMplsTE.status == enabled)
1473 return CMD_SUCCESS;
1474
1475 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001476 zlog_debug ("MPLS-TE: OFF -> ON");
paul718e3742002-12-13 20:15:29 +00001477
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 */
paul1eb8ef22005-04-07 07:30:20 +00001486 for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
1487 initialize_linkparams (lp);
paul718e3742002-12-13 20:15:29 +00001488
1489 ospf_mpls_te_foreach_area (ospf_mpls_te_lsa_schedule, REORIGINATE_PER_AREA);
1490
1491 return CMD_SUCCESS;
1492}
1493
1494ALIAS (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
1500DEFUN (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{
paul1eb8ef22005-04-07 07:30:20 +00001507 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001508 struct mpls_te_link *lp;
1509
1510 if (OspfMplsTE.status == disabled)
1511 return CMD_SUCCESS;
1512
1513 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001514 zlog_debug ("MPLS-TE: ON -> OFF");
paul718e3742002-12-13 20:15:29 +00001515
1516 OspfMplsTE.status = disabled;
1517
paul1eb8ef22005-04-07 07:30:20 +00001518 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);
paul718e3742002-12-13 20:15:29 +00001522
1523 return CMD_SUCCESS;
1524}
1525
1526DEFUN (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
paul87d6f872004-09-24 08:01:38 +00001543 || ntohl (ra->value.s_addr) != ntohl (value.s_addr))
paul718e3742002-12-13 20:15:29 +00001544 {
paul1eb8ef22005-04-07 07:30:20 +00001545 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001546 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
paul1eb8ef22005-04-07 07:30:20 +00001554 for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
paul718e3742002-12-13 20:15:29 +00001555 {
paul718e3742002-12-13 20:15:29 +00001556 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 }
paul1eb8ef22005-04-07 07:30:20 +00001565
1566 for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp))
paul718e3742002-12-13 20:15:29 +00001567 {
paul718e3742002-12-13 20:15:29 +00001568 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 }
1581out:
1582 return CMD_SUCCESS;
1583}
1584
1585DEFUN (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
1622DEFUN (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 {
ajs6099b3b2004-11-20 02:06:59 +00001643 vty_out (vty, "mpls_te_link_maxbw: fscanf: %s%s", safe_strerror (errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001644 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
1664DEFUN (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 {
ajs6099b3b2004-11-20 02:06:59 +00001685 vty_out (vty, "mpls_te_link_max_rsv_bw: fscanf: %s%s", safe_strerror (errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001686 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
1706DEFUN (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 {
ajs6099b3b2004-11-20 02:06:59 +00001729 vty_out (vty, "mpls_te_link_unrsv_bw: fscanf: %s%s", safe_strerror (errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001730 return CMD_WARNING;
1731 }
1732
1733 ntohf (&lp->unrsv_bw.value [priority], &f1);
1734 if (sscanf (argv[1], "%g", &f2) != 1)
1735 {
ajs6099b3b2004-11-20 02:06:59 +00001736 vty_out (vty, "mpls_te_link_unrsv_bw: fscanf: %s%s", safe_strerror (errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001737 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
1757DEFUN (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 {
ajs6099b3b2004-11-20 02:06:59 +00001777 vty_out (vty, "mpls_te_link_rsc_clsclr: fscanf: %s%s", safe_strerror (errno), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00001778 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
1798DEFUN (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
1818static void
1819show_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
1855DEFUN (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;
paul1eb8ef22005-04-07 07:30:20 +00001864 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001865
1866 /* Show All Interfaces. */
1867 if (argc == 0)
hassoeb1ce602004-10-08 08:17:22 +00001868 {
paul1eb8ef22005-04-07 07:30:20 +00001869 for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
1870 show_mpls_te_link_sub (vty, ifp);
hassoeb1ce602004-10-08 08:17:22 +00001871 }
paul718e3742002-12-13 20:15:29 +00001872 /* 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
1884static void
1885ospf_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}