Import Upstream version 1.2.2
[quagga-debian.git] / isisd / isis_te.c
1 /*
2  * IS-IS Rout(e)ing protocol - isis_te.c
3  *
4  * This is an implementation of RFC5305
5  *
6  *      Copyright (C) 2014 Orange Labs
7  *      http://www.orange.com
8  *
9  * This file is part of GNU Zebra.
10  *
11  * GNU Zebra is free software; you can redistribute it and/or modify it
12  * under the terms of the GNU General Public License as published by the
13  * Free Software Foundation; either version 2, or (at your option) any
14  * later version.
15  *
16  * GNU Zebra is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
23  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
24  * 02111-1307, USA.
25  */
26
27 #include <zebra.h>
28 #include <math.h>
29
30 #include "linklist.h"
31 #include "thread.h"
32 #include "vty.h"
33 #include "stream.h"
34 #include "memory.h"
35 #include "log.h"
36 #include "prefix.h"
37 #include "command.h"
38 #include "hash.h"
39 #include "if.h"
40 #include "checksum.h"
41 #include "md5.h"
42 #include "sockunion.h"
43 #include "network.h"
44
45 #include "isisd/dict.h"
46 #include "isisd/isis_constants.h"
47 #include "isisd/isis_common.h"
48 #include "isisd/isis_flags.h"
49 #include "isisd/isis_circuit.h"
50 #include "isisd/isisd.h"
51 #include "isisd/isis_tlv.h"
52 #include "isisd/isis_lsp.h"
53 #include "isisd/isis_pdu.h"
54 #include "isisd/isis_dynhn.h"
55 #include "isisd/isis_misc.h"
56 #include "isisd/isis_csm.h"
57 #include "isisd/isis_adjacency.h"
58 #include "isisd/isis_spf.h"
59 #include "isisd/isis_te.h"
60
61 /* Global varial for MPLS TE management */
62 struct isis_mpls_te isisMplsTE;
63
64 const char *mode2text[] = { "Disable", "Area", "AS", "Emulate" };
65
66 /*------------------------------------------------------------------------*
67  * Followings are control functions for MPLS-TE parameters management.
68  *------------------------------------------------------------------------*/
69
70 /* Search MPLS TE Circuit context from Interface */
71 static struct mpls_te_circuit *
72 lookup_mpls_params_by_ifp (struct interface *ifp)
73 {
74   struct isis_circuit *circuit;
75
76   if ((circuit = circuit_scan_by_ifp (ifp)) == NULL)
77       return NULL;
78
79   return circuit->mtc;
80 }
81
82 /* Create new MPLS TE Circuit context */
83 struct mpls_te_circuit *
84 mpls_te_circuit_new()
85 {
86   struct mpls_te_circuit *mtc;
87
88   zlog_debug ("ISIS MPLS-TE: Create new MPLS TE Circuit context");
89
90   mtc = XCALLOC(MTYPE_ISIS_MPLS_TE, sizeof (struct mpls_te_circuit));
91
92   if (mtc == NULL)
93     return NULL;
94
95   mtc->status = disable;
96   mtc->type = STD_TE;
97   mtc->length = 0;
98
99   return mtc;
100
101 }
102
103 /* Copy SUB TLVs parameters into a buffer - No space verification are performed */
104 /* Caller must verify before that there is enough free space in the buffer */
105 u_char
106 add_te_subtlvs(u_char *buf, struct mpls_te_circuit *mtc)
107 {
108   u_char size, *tlvs = buf;
109
110   zlog_debug ("ISIS MPLS-TE: Add TE Sub TLVs to buffer");
111
112   if (mtc == NULL)
113     {
114       zlog_debug("ISIS MPLS-TE: Abort! No MPLS TE Circuit available has been specified");
115       return 0;
116     }
117
118   /* Create buffer if not provided */
119   if (buf == NULL)
120     {
121       zlog_debug("ISIS MPLS-TE: Abort! No Buffer has been specified");
122       return 0;
123     }
124
125   /* TE_SUBTLV_ADMIN_GRP */
126   if (SUBTLV_TYPE(mtc->admin_grp) != 0)
127     {
128       size = SUBTLV_SIZE (&(mtc->admin_grp.header));
129       memcpy(tlvs, &(mtc->admin_grp), size);
130       tlvs += size;
131     }
132
133   /* TE_SUBTLV_LLRI */
134   if (SUBTLV_TYPE(mtc->llri) != 0)
135     {
136       size = SUBTLV_SIZE (&(mtc->llri.header));
137       memcpy(tlvs, &(mtc->llri), size);
138       tlvs += size;
139     }
140
141   /* TE_SUBTLV_LCLIF_IPADDR */
142   if (SUBTLV_TYPE(mtc->local_ipaddr) != 0)
143     {
144       size = SUBTLV_SIZE (&(mtc->local_ipaddr.header));
145       memcpy(tlvs, &(mtc->local_ipaddr), size);
146       tlvs += size;
147     }
148
149   /* TE_SUBTLV_RMTIF_IPADDR */
150   if (SUBTLV_TYPE(mtc->rmt_ipaddr) != 0)
151     {
152       size = SUBTLV_SIZE (&(mtc->rmt_ipaddr.header));
153       memcpy(tlvs, &(mtc->rmt_ipaddr), size);
154       tlvs += size;
155     }
156
157   /* TE_SUBTLV_MAX_BW */
158   if (SUBTLV_TYPE(mtc->max_bw) != 0)
159     {
160       size = SUBTLV_SIZE (&(mtc->max_bw.header));
161       memcpy(tlvs, &(mtc->max_bw), size);
162       tlvs += size;
163     }
164
165   /* TE_SUBTLV_MAX_RSV_BW */
166   if (SUBTLV_TYPE(mtc->max_rsv_bw) != 0)
167     {
168       size = SUBTLV_SIZE (&(mtc->max_rsv_bw.header));
169       memcpy(tlvs, &(mtc->max_rsv_bw), size);
170       tlvs += size;
171     }
172
173   /* TE_SUBTLV_UNRSV_BW */
174   if (SUBTLV_TYPE(mtc->unrsv_bw) != 0)
175     {
176       size = SUBTLV_SIZE (&(mtc->unrsv_bw.header));
177       memcpy(tlvs, &(mtc->unrsv_bw), size);
178       tlvs += size;
179     }
180
181   /* TE_SUBTLV_TE_METRIC */
182   if (SUBTLV_TYPE(mtc->te_metric) != 0)
183     {
184       size = SUBTLV_SIZE (&(mtc->te_metric.header));
185       memcpy(tlvs, &(mtc->te_metric), size);
186       tlvs += size;
187     }
188
189   /* TE_SUBTLV_AV_DELAY */
190   if (SUBTLV_TYPE(mtc->av_delay) != 0)
191     {
192       size = SUBTLV_SIZE (&(mtc->av_delay.header));
193       memcpy(tlvs, &(mtc->av_delay), size);
194       tlvs += size;
195     }
196
197   /* TE_SUBTLV_MM_DELAY */
198   if (SUBTLV_TYPE(mtc->mm_delay) != 0)
199     {
200       size = SUBTLV_SIZE (&(mtc->mm_delay.header));
201       memcpy(tlvs, &(mtc->mm_delay), size);
202       tlvs += size;
203     }
204
205   /* TE_SUBTLV_DELAY_VAR */
206   if (SUBTLV_TYPE(mtc->delay_var) != 0)
207     {
208       size = SUBTLV_SIZE (&(mtc->delay_var.header));
209       memcpy(tlvs, &(mtc->delay_var), size);
210       tlvs += size;
211     }
212
213   /* TE_SUBTLV_PKT_LOSS */
214   if (SUBTLV_TYPE(mtc->pkt_loss) != 0)
215     {
216       size = SUBTLV_SIZE (&(mtc->pkt_loss.header));
217       memcpy(tlvs, &(mtc->pkt_loss), size);
218       tlvs += size;
219     }
220
221   /* TE_SUBTLV_RES_BW */
222   if (SUBTLV_TYPE(mtc->res_bw) != 0)
223     {
224       size = SUBTLV_SIZE (&(mtc->res_bw.header));
225       memcpy(tlvs, &(mtc->res_bw), size);
226       tlvs += size;
227     }
228
229   /* TE_SUBTLV_AVA_BW */
230   if (SUBTLV_TYPE(mtc->ava_bw) != 0)
231     {
232       size = SUBTLV_SIZE (&(mtc->ava_bw.header));
233       memcpy(tlvs, &(mtc->ava_bw), size);
234       tlvs += size;
235     }
236
237   /* TE_SUBTLV_USE_BW */
238   if (SUBTLV_TYPE(mtc->use_bw) != 0)
239     {
240       size = SUBTLV_SIZE (&(mtc->use_bw.header));
241       memcpy(tlvs, &(mtc->use_bw), size);
242       tlvs += size;
243     }
244
245   /* Update SubTLVs length */
246   mtc->length = subtlvs_len(mtc);
247
248   zlog_debug("ISIS MPLS-TE: Add %d bytes length SubTLVs", mtc->length);
249
250   return mtc->length;
251 }
252
253 /* Compute total Sub-TLVs size */
254 u_char
255 subtlvs_len (struct mpls_te_circuit *mtc)
256 {
257   int length = 0;
258
259   /* Sanity Check */
260   if (mtc == NULL)
261     return 0;
262
263   /* TE_SUBTLV_ADMIN_GRP */
264   if (SUBTLV_TYPE(mtc->admin_grp) != 0)
265     length += SUBTLV_SIZE (&(mtc->admin_grp.header));
266
267   /* TE_SUBTLV_LLRI */
268   if (SUBTLV_TYPE(mtc->llri) != 0)
269     length += SUBTLV_SIZE (&mtc->llri.header);
270
271   /* TE_SUBTLV_LCLIF_IPADDR */
272   if (SUBTLV_TYPE(mtc->local_ipaddr) != 0)
273     length += SUBTLV_SIZE (&mtc->local_ipaddr.header);
274
275   /* TE_SUBTLV_RMTIF_IPADDR */
276   if (SUBTLV_TYPE(mtc->rmt_ipaddr) != 0)
277     length += SUBTLV_SIZE (&mtc->rmt_ipaddr.header);
278
279   /* TE_SUBTLV_MAX_BW */
280   if (SUBTLV_TYPE(mtc->max_bw) != 0)
281     length += SUBTLV_SIZE (&mtc->max_bw.header);
282
283   /* TE_SUBTLV_MAX_RSV_BW */
284   if (SUBTLV_TYPE(mtc->max_rsv_bw) != 0)
285     length += SUBTLV_SIZE (&mtc->max_rsv_bw.header);
286
287   /* TE_SUBTLV_UNRSV_BW */
288   if (SUBTLV_TYPE(mtc->unrsv_bw) != 0)
289     length += SUBTLV_SIZE (&mtc->unrsv_bw.header);
290
291   /* TE_SUBTLV_TE_METRIC */
292   if (SUBTLV_TYPE(mtc->te_metric) != 0)
293     length += SUBTLV_SIZE (&mtc->te_metric.header);
294
295   /* TE_SUBTLV_AV_DELAY */
296   if (SUBTLV_TYPE(mtc->av_delay) != 0)
297     length += SUBTLV_SIZE (&mtc->av_delay.header);
298
299   /* TE_SUBTLV_MM_DELAY */
300   if (SUBTLV_TYPE(mtc->mm_delay) != 0)
301     length += SUBTLV_SIZE (&mtc->mm_delay.header);
302
303   /* TE_SUBTLV_DELAY_VAR */
304   if (SUBTLV_TYPE(mtc->delay_var) != 0)
305     length += SUBTLV_SIZE (&mtc->delay_var.header);
306
307   /* TE_SUBTLV_PKT_LOSS */
308   if (SUBTLV_TYPE(mtc->pkt_loss) != 0)
309     length += SUBTLV_SIZE (&mtc->pkt_loss.header);
310
311   /* TE_SUBTLV_RES_BW */
312   if (SUBTLV_TYPE(mtc->res_bw) != 0)
313     length += SUBTLV_SIZE (&mtc->res_bw.header);
314
315   /* TE_SUBTLV_AVA_BW */
316   if (SUBTLV_TYPE(mtc->ava_bw) != 0)
317     length += SUBTLV_SIZE (&mtc->ava_bw.header);
318
319   /* TE_SUBTLV_USE_BW */
320   if (SUBTLV_TYPE(mtc->use_bw) != 0)
321     length += SUBTLV_SIZE (&mtc->use_bw.header);
322
323   /* Check that length is lower than the MAXIMUM SUBTLV size i.e. 256 */
324   if (length > MAX_SUBTLV_SIZE)
325     {
326       mtc->length = 0;
327       return 0;
328     }
329
330   mtc->length = (u_char)length;
331
332   return mtc->length;
333 }
334
335 /* Following are various functions to set MPLS TE parameters */
336 static void
337 set_circuitparams_admin_grp (struct mpls_te_circuit *mtc, u_int32_t admingrp)
338 {
339   SUBTLV_TYPE(mtc->admin_grp) = TE_SUBTLV_ADMIN_GRP;
340   SUBTLV_LEN(mtc->admin_grp)  = SUBTLV_DEF_SIZE;
341   mtc->admin_grp.value        = htonl(admingrp);
342   return;
343 }
344
345 static void  __attribute__ ((unused))
346 set_circuitparams_llri (struct mpls_te_circuit *mtc, u_int32_t local, u_int32_t remote)
347 {
348   SUBTLV_TYPE(mtc->llri) = TE_SUBTLV_LLRI;
349   SUBTLV_LEN(mtc->llri)  = TE_SUBTLV_LLRI_SIZE;
350   mtc->llri.local        = htonl(local);
351   mtc->llri.remote       = htonl(remote);
352 }
353
354 void
355 set_circuitparams_local_ipaddr (struct mpls_te_circuit *mtc, struct in_addr addr)
356 {
357
358   SUBTLV_TYPE(mtc->local_ipaddr) = TE_SUBTLV_LOCAL_IPADDR;
359   SUBTLV_LEN(mtc->local_ipaddr)  = SUBTLV_DEF_SIZE;
360   mtc->local_ipaddr.value.s_addr = addr.s_addr;
361   return;
362 }
363
364 void
365 set_circuitparams_rmt_ipaddr (struct mpls_te_circuit *mtc, struct in_addr addr)
366 {
367
368   SUBTLV_TYPE(mtc->rmt_ipaddr) = TE_SUBTLV_RMT_IPADDR;
369   SUBTLV_LEN(mtc->rmt_ipaddr)  = SUBTLV_DEF_SIZE;
370   mtc->rmt_ipaddr.value.s_addr = addr.s_addr;
371   return;
372 }
373
374 static void
375 set_circuitparams_max_bw (struct mpls_te_circuit *mtc, float fp)
376 {
377   SUBTLV_TYPE(mtc->max_bw) = TE_SUBTLV_MAX_BW;
378   SUBTLV_LEN(mtc->max_bw)  = SUBTLV_DEF_SIZE;
379   mtc->max_bw.value = htonf(fp);
380   return;
381 }
382
383 static void
384 set_circuitparams_max_rsv_bw (struct mpls_te_circuit *mtc, float fp)
385 {
386   SUBTLV_TYPE(mtc->max_rsv_bw) = TE_SUBTLV_MAX_RSV_BW;
387   SUBTLV_LEN(mtc->max_rsv_bw)  = SUBTLV_DEF_SIZE;
388   mtc->max_rsv_bw.value = htonf(fp);
389   return;
390 }
391
392 static void
393 set_circuitparams_unrsv_bw (struct mpls_te_circuit *mtc, int priority, float fp)
394 {
395   /* Note that TLV-length field is the size of array. */
396   SUBTLV_TYPE(mtc->unrsv_bw) = TE_SUBTLV_UNRSV_BW;
397   SUBTLV_LEN(mtc->unrsv_bw)  = TE_SUBTLV_UNRSV_SIZE;
398   mtc->unrsv_bw.value[priority] = htonf(fp);
399   return;
400 }
401
402 static void
403 set_circuitparams_te_metric (struct mpls_te_circuit *mtc, u_int32_t te_metric)
404 {
405   SUBTLV_TYPE(mtc->te_metric) = TE_SUBTLV_TE_METRIC;
406   SUBTLV_LEN(mtc->te_metric)  = TE_SUBTLV_TE_METRIC_SIZE;
407   mtc->te_metric.value[0] = (te_metric >> 16) & 0xFF;
408   mtc->te_metric.value[1] = (te_metric  >> 8) & 0xFF;
409   mtc->te_metric.value[2] = te_metric & 0xFF;
410   return;
411 }
412
413 static void
414 set_circuitparams_inter_as (struct mpls_te_circuit *mtc, struct in_addr addr, u_int32_t as)
415 {
416
417   /* Set the Remote ASBR IP address and then the associated AS number */
418   SUBTLV_TYPE(mtc->rip) = TE_SUBTLV_RIP;
419   SUBTLV_LEN(mtc->rip)  = SUBTLV_DEF_SIZE;
420   mtc->rip.value.s_addr = addr.s_addr;
421
422   SUBTLV_TYPE(mtc->ras) = TE_SUBTLV_RAS;
423   SUBTLV_LEN(mtc->ras)  = SUBTLV_DEF_SIZE;
424   mtc->ras.value        = htonl(as);
425 }
426
427 static void
428 unset_circuitparams_inter_as (struct mpls_te_circuit *mtc)
429 {
430
431   /* Reset the Remote ASBR IP address and then the associated AS number */
432   SUBTLV_TYPE(mtc->rip) = 0;
433   SUBTLV_LEN(mtc->rip)  = 0;
434   mtc->rip.value.s_addr = 0;
435
436   SUBTLV_TYPE(mtc->ras) = 0;
437   SUBTLV_LEN(mtc->ras)  = 0;
438   mtc->ras.value        = 0;
439 }
440
441 static void
442 set_circuitparams_av_delay (struct mpls_te_circuit *mtc, u_int32_t delay, u_char anormal)
443 {
444   u_int32_t tmp;
445   /* Note that TLV-length field is the size of array. */
446   SUBTLV_TYPE(mtc->av_delay) = TE_SUBTLV_AV_DELAY;
447   SUBTLV_LEN(mtc->av_delay)  = SUBTLV_DEF_SIZE;
448   tmp = delay & TE_EXT_MASK;
449   if (anormal)
450     tmp |= TE_EXT_ANORMAL;
451   mtc->av_delay.value = htonl(tmp);
452   return;
453 }
454
455 static void
456 set_circuitparams_mm_delay (struct mpls_te_circuit *mtc, u_int32_t low, u_int32_t high, u_char anormal)
457 {
458   u_int32_t tmp;
459   /* Note that TLV-length field is the size of array. */
460   SUBTLV_TYPE(mtc->mm_delay) = TE_SUBTLV_MM_DELAY;
461   SUBTLV_LEN(mtc->mm_delay)  = TE_SUBTLV_MM_DELAY_SIZE;
462   tmp = low & TE_EXT_MASK;
463   if (anormal)
464     tmp |= TE_EXT_ANORMAL;
465   mtc->mm_delay.low = htonl(tmp);
466   mtc->mm_delay.high = htonl(high);
467   return;
468 }
469
470 static void
471 set_circuitparams_delay_var (struct mpls_te_circuit *mtc, u_int32_t jitter)
472 {
473   /* Note that TLV-length field is the size of array. */
474   SUBTLV_TYPE(mtc->delay_var) = TE_SUBTLV_DELAY_VAR;
475   SUBTLV_LEN(mtc->delay_var)  = SUBTLV_DEF_SIZE;
476   mtc->delay_var.value        = htonl(jitter & TE_EXT_MASK);
477   return;
478 }
479
480 static void
481 set_circuitparams_pkt_loss (struct mpls_te_circuit *mtc, u_int32_t loss, u_char anormal)
482 {
483   u_int32_t tmp;
484   /* Note that TLV-length field is the size of array. */
485   SUBTLV_TYPE(mtc->pkt_loss) = TE_SUBTLV_PKT_LOSS;
486   SUBTLV_LEN(mtc->pkt_loss)  = SUBTLV_DEF_SIZE;
487   tmp = loss & TE_EXT_MASK;
488   if (anormal)
489     tmp |= TE_EXT_ANORMAL;
490   mtc->pkt_loss.value = htonl(tmp);
491   return;
492 }
493
494 static void
495 set_circuitparams_res_bw (struct mpls_te_circuit *mtc, float fp)
496 {
497   /* Note that TLV-length field is the size of array. */
498   SUBTLV_TYPE(mtc->res_bw) = TE_SUBTLV_RES_BW;
499   SUBTLV_LEN(mtc->res_bw)  = SUBTLV_DEF_SIZE;
500   mtc->res_bw.value = htonf(fp);
501   return;
502 }
503
504 static void
505 set_circuitparams_ava_bw (struct mpls_te_circuit *mtc, float fp)
506 {
507   /* Note that TLV-length field is the size of array. */
508   SUBTLV_TYPE(mtc->ava_bw) = TE_SUBTLV_AVA_BW;
509   SUBTLV_LEN(mtc->ava_bw)  = SUBTLV_DEF_SIZE;
510   mtc->ava_bw.value = htonf(fp);
511   return;
512 }
513
514 static void
515 set_circuitparams_use_bw (struct mpls_te_circuit *mtc, float fp)
516 {
517   /* Note that TLV-length field is the size of array. */
518   SUBTLV_TYPE(mtc->use_bw) = TE_SUBTLV_USE_BW;
519   SUBTLV_LEN(mtc->use_bw)  = SUBTLV_DEF_SIZE;
520   mtc->use_bw.value = htonf(fp);
521   return;
522 }
523
524 /* Main initialization / update function of the MPLS TE Circuit context */
525 /* Call when interface TE Link parameters are modified */
526 void
527 isis_link_params_update (struct isis_circuit *circuit, struct interface *ifp)
528 {
529   int i;
530   struct prefix_ipv4 *addr;
531   struct mpls_te_circuit *mtc;
532
533   /* Sanity Check */
534   if ((circuit == NULL) || (ifp == NULL))
535       return;
536
537   zlog_info ("MPLS-TE: Initialize circuit parameters for interface %s", ifp->name);
538   
539   /* Check if MPLS TE Circuit context has not been already created */
540   if (circuit->mtc == NULL)
541       circuit->mtc = mpls_te_circuit_new();
542
543   mtc = circuit->mtc;
544
545   /* Fulfil MTC TLV from ifp TE Link parameters */
546   if (HAS_LINK_PARAMS(ifp))
547     {
548       mtc->status = enable;
549       /* STD_TE metrics */
550       if (IS_PARAM_SET(ifp->link_params, LP_ADM_GRP))
551         set_circuitparams_admin_grp (mtc, ifp->link_params->admin_grp);
552       else
553         SUBTLV_TYPE(mtc->admin_grp) = 0;
554
555       /* If not already set, register local IP addr from ip_addr list if it exists */
556       if (SUBTLV_TYPE(mtc->local_ipaddr) == 0)
557         {
558           if (circuit->ip_addrs != NULL && listcount(circuit->ip_addrs) != 0)
559             {
560               addr = (struct prefix_ipv4 *)listgetdata ((struct listnode *)listhead (circuit->ip_addrs));
561               set_circuitparams_local_ipaddr (mtc, addr->prefix);
562             }
563         }
564
565       /* If not already set, try to determine Remote IP addr if circuit is P2P */
566       if ((SUBTLV_TYPE(mtc->rmt_ipaddr) == 0) && (circuit->circ_type == CIRCUIT_T_P2P))
567         {
568           struct isis_adjacency *adj = circuit->u.p2p.neighbor;
569           if (adj->ipv4_addrs != NULL && listcount(adj->ipv4_addrs) != 0)
570             {
571               struct in_addr *ip_addr;
572               ip_addr = (struct in_addr *)listgetdata ((struct listnode *)listhead (adj->ipv4_addrs));
573               set_circuitparams_rmt_ipaddr (mtc, *ip_addr);
574             }
575         }
576
577       if (IS_PARAM_SET(ifp->link_params, LP_MAX_BW))
578         set_circuitparams_max_bw (mtc, ifp->link_params->max_bw);
579       else
580         SUBTLV_TYPE(mtc->max_bw) = 0;
581
582       if (IS_PARAM_SET(ifp->link_params, LP_MAX_RSV_BW))
583         set_circuitparams_max_rsv_bw (mtc, ifp->link_params->max_rsv_bw);
584       else
585         SUBTLV_TYPE(mtc->max_rsv_bw) = 0;
586
587       if (IS_PARAM_SET(ifp->link_params, LP_UNRSV_BW))
588         for (i = 0; i < MAX_CLASS_TYPE; i++)
589           set_circuitparams_unrsv_bw (mtc, i, ifp->link_params->unrsv_bw[i]);
590       else
591         SUBTLV_TYPE(mtc->unrsv_bw) = 0;
592
593       if (IS_PARAM_SET(ifp->link_params, LP_TE))
594         set_circuitparams_te_metric(mtc, ifp->link_params->te_metric);
595       else
596         SUBTLV_TYPE(mtc->te_metric) = 0;
597
598       /* TE metric Extensions */
599       if (IS_PARAM_SET(ifp->link_params, LP_DELAY))
600         set_circuitparams_av_delay(mtc, ifp->link_params->av_delay, 0);
601       else
602         SUBTLV_TYPE(mtc->av_delay) = 0;
603
604       if (IS_PARAM_SET(ifp->link_params, LP_MM_DELAY))
605         set_circuitparams_mm_delay(mtc, ifp->link_params->min_delay, ifp->link_params->max_delay, 0);
606       else
607         SUBTLV_TYPE(mtc->mm_delay) = 0;
608
609       if (IS_PARAM_SET(ifp->link_params, LP_DELAY_VAR))
610         set_circuitparams_delay_var(mtc, ifp->link_params->delay_var);
611       else
612         SUBTLV_TYPE(mtc->delay_var) = 0;
613
614       if (IS_PARAM_SET(ifp->link_params, LP_PKT_LOSS))
615         set_circuitparams_pkt_loss(mtc, ifp->link_params->pkt_loss, 0);
616       else
617         SUBTLV_TYPE(mtc->pkt_loss) = 0;
618
619       if (IS_PARAM_SET(ifp->link_params, LP_RES_BW))
620         set_circuitparams_res_bw(mtc, ifp->link_params->res_bw);
621       else
622         SUBTLV_TYPE(mtc->res_bw) = 0;
623
624       if (IS_PARAM_SET(ifp->link_params, LP_AVA_BW))
625         set_circuitparams_ava_bw(mtc, ifp->link_params->ava_bw);
626       else
627         SUBTLV_TYPE(mtc->ava_bw) = 0;
628
629       if (IS_PARAM_SET(ifp->link_params, LP_USE_BW))
630         set_circuitparams_use_bw(mtc, ifp->link_params->use_bw);
631       else
632         SUBTLV_TYPE(mtc->use_bw) = 0;
633
634       /* INTER_AS */
635       if (IS_PARAM_SET(ifp->link_params, LP_RMT_AS))
636         set_circuitparams_inter_as(mtc, ifp->link_params->rmt_ip, ifp->link_params->rmt_as);
637       else
638         /* reset inter-as TE params */
639         unset_circuitparams_inter_as (mtc);
640
641       /* Compute total length of SUB TLVs */
642       mtc->length = subtlvs_len(mtc);
643
644     }
645   else
646     mtc->status = disable;
647
648   /* Finally Update LSP */
649 #if 0
650   if (IS_MPLS_TE(isisMplsTE) && circuit->area)
651        lsp_regenerate_schedule (circuit->area, circuit->is_type, 0);
652 #endif
653   return;
654 }
655
656 void
657 isis_mpls_te_update (struct interface *ifp)
658 {
659   struct isis_circuit *circuit;
660
661   /* Sanity Check */
662   if (ifp == NULL)
663     return;
664
665   /* Get circuit context from interface */
666   if ((circuit = circuit_scan_by_ifp(ifp)) == NULL)
667     return;
668
669   /* Update TE TLVs ... */
670   isis_link_params_update(circuit, ifp);
671
672   /* ... and LSP */
673   if (IS_MPLS_TE(isisMplsTE) && circuit->area)
674      lsp_regenerate_schedule (circuit->area, circuit->is_type, 0);
675
676   return;
677 }
678
679 /*------------------------------------------------------------------------*
680  * Followings are vty session control functions.
681  *------------------------------------------------------------------------*/
682
683 static u_char
684 show_vty_subtlv_admin_grp (struct vty *vty, struct te_subtlv_admin_grp *tlv)
685 {
686
687   if (vty != NULL)
688     vty_out (vty, "    Administrative Group: 0x%x%s",
689              (u_int32_t) ntohl (tlv->value), VTY_NEWLINE);
690   else
691     zlog_debug ("      Administrative Group: 0x%x",
692                 (u_int32_t) ntohl (tlv->value));
693
694   return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
695 }
696
697 static u_char
698 show_vty_subtlv_llri (struct vty *vty, struct te_subtlv_llri *tlv)
699 {
700   if (vty != NULL)
701     {
702       vty_out (vty, "    Link Local  ID: %d%s", (u_int32_t) ntohl (tlv->local),
703                VTY_NEWLINE);
704       vty_out (vty, "    Link Remote ID: %d%s", (u_int32_t) ntohl (tlv->remote),
705                VTY_NEWLINE);
706     }
707   else
708     {
709       zlog_debug ("      Link Local  ID: %d", (u_int32_t) ntohl (tlv->local));
710       zlog_debug ("      Link Remote ID: %d", (u_int32_t) ntohl (tlv->remote));
711     }
712
713   return (SUBTLV_HDR_SIZE + TE_SUBTLV_LLRI_SIZE);
714 }
715
716 static u_char
717 show_vty_subtlv_local_ipaddr (struct vty *vty, struct te_subtlv_local_ipaddr *tlv)
718 {
719   if (vty != NULL)
720     vty_out (vty, "    Local Interface IP Address(es): %s%s", inet_ntoa (tlv->value), VTY_NEWLINE);
721   else
722     zlog_debug ("      Local Interface IP Address(es): %s", inet_ntoa (tlv->value));
723
724   return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
725 }
726
727 static u_char
728 show_vty_subtlv_rmt_ipaddr (struct vty *vty, struct te_subtlv_rmt_ipaddr *tlv)
729 {
730   if (vty != NULL)
731     vty_out (vty, "    Remote Interface IP Address(es): %s%s", inet_ntoa (tlv->value), VTY_NEWLINE);
732   else
733     zlog_debug ("      Remote Interface IP Address(es): %s", inet_ntoa (tlv->value));
734
735   return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
736 }
737
738 static u_char
739 show_vty_subtlv_max_bw (struct vty *vty, struct te_subtlv_max_bw *tlv)
740 {
741   float fval;
742
743   fval = ntohf (tlv->value);
744
745   if (vty != NULL)
746     vty_out (vty, "    Maximum Bandwidth: %g (Bytes/sec)%s", fval, VTY_NEWLINE);
747   else
748     zlog_debug ("      Maximum Bandwidth: %g (Bytes/sec)", fval);
749
750   return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
751 }
752
753 static u_char
754 show_vty_subtlv_max_rsv_bw (struct vty *vty, struct te_subtlv_max_rsv_bw *tlv)
755 {
756   float fval;
757
758   fval = ntohf (tlv->value);
759
760   if (vty != NULL)
761     vty_out (vty, "    Maximum Reservable Bandwidth: %g (Bytes/sec)%s", fval,
762              VTY_NEWLINE);
763   else
764     zlog_debug ("      Maximum Reservable Bandwidth: %g (Bytes/sec)", fval);
765
766   return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
767 }
768
769 static u_char
770 show_vty_subtlv_unrsv_bw (struct vty *vty, struct te_subtlv_unrsv_bw *tlv)
771 {
772   float fval1, fval2;
773   int i;
774
775   if (vty != NULL)
776     vty_out (vty, "    Unreserved Bandwidth:%s",VTY_NEWLINE);
777   else
778     zlog_debug ("      Unreserved Bandwidth:");
779
780   for (i = 0; i < MAX_CLASS_TYPE; i+=2)
781     {
782       fval1 = ntohf (tlv->value[i]);
783       fval2 = ntohf (tlv->value[i+1]);
784       if (vty != NULL)
785         vty_out (vty, "      [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)%s", i, fval1, i+1, fval2, VTY_NEWLINE);
786       else
787         zlog_debug ("        [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)", i, fval1, i+1, fval2);
788     }
789
790   return (SUBTLV_HDR_SIZE + TE_SUBTLV_UNRSV_SIZE);
791 }
792
793 static u_char
794 show_vty_subtlv_te_metric (struct vty *vty, struct te_subtlv_te_metric *tlv)
795 {
796   u_int32_t te_metric;
797
798   te_metric = tlv->value[2] | tlv->value[1] << 8 | tlv->value[0] << 16;
799   if (vty != NULL)
800     vty_out (vty, "    Traffic Engineering Metric: %u%s", te_metric, VTY_NEWLINE);
801   else
802     zlog_debug ("      Traffic Engineering Metric: %u", te_metric);
803
804   return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
805 }
806
807 static u_char
808 show_vty_subtlv_ras (struct vty *vty, struct te_subtlv_ras *tlv)
809 {
810   if (vty != NULL)
811     vty_out (vty, "    Inter-AS TE Remote AS number: %u%s", ntohl (tlv->value), VTY_NEWLINE);
812   else
813     zlog_debug ("      Inter-AS TE Remote AS number: %u", ntohl (tlv->value));
814
815   return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
816 }
817
818 static u_char
819 show_vty_subtlv_rip (struct vty *vty, struct te_subtlv_rip *tlv)
820 {
821   if (vty != NULL)
822     vty_out (vty, "    Inter-AS TE Remote ASBR IP address: %s%s", inet_ntoa (tlv->value), VTY_NEWLINE);
823   else
824     zlog_debug ("      Inter-AS TE Remote ASBR IP address: %s", inet_ntoa (tlv->value));
825
826   return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
827 }
828
829 static u_char
830 show_vty_subtlv_av_delay (struct vty *vty, struct te_subtlv_av_delay *tlv)
831 {
832   u_int32_t delay;
833   u_int32_t A;
834
835   delay = (u_int32_t) ntohl (tlv->value) & TE_EXT_MASK;
836   A = (u_int32_t) ntohl (tlv->value) & TE_EXT_ANORMAL;
837
838   if (vty != NULL)
839     vty_out (vty, "    %s Average Link Delay: %d (micro-sec)%s", A ? "Anomalous" : "Normal", delay, VTY_NEWLINE);
840   else
841     zlog_debug ("      %s Average Link Delay: %d (micro-sec)", A ? "Anomalous" : "Normal", delay);
842
843   return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
844 }
845
846 static u_char
847 show_vty_subtlv_mm_delay (struct vty *vty, struct te_subtlv_mm_delay *tlv)
848 {
849   u_int32_t low, high;
850   u_int32_t A;
851
852   low = (u_int32_t) ntohl (tlv->low) & TE_EXT_MASK;
853   A = (u_int32_t) ntohl (tlv->low) & TE_EXT_ANORMAL;
854   high = (u_int32_t) ntohl (tlv->high) & TE_EXT_MASK;
855
856   if (vty != NULL)
857     vty_out (vty, "    %s Min/Max Link Delay: %d / %d (micro-sec)%s", A ? "Anomalous" : "Normal", low, high, VTY_NEWLINE);
858   else
859     zlog_debug ("      %s Min/Max Link Delay: %d / %d (micro-sec)", A ? "Anomalous" : "Normal", low, high);
860
861   return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
862 }
863
864 static u_char
865 show_vty_subtlv_delay_var (struct vty *vty, struct te_subtlv_delay_var *tlv)
866 {
867   u_int32_t jitter;
868
869   jitter = (u_int32_t) ntohl (tlv->value) & TE_EXT_MASK;
870
871   if (vty != NULL)
872     vty_out (vty, "    Delay Variation: %d (micro-sec)%s", jitter, VTY_NEWLINE);
873   else
874     zlog_debug ("      Delay Variation: %d (micro-sec)", jitter);
875
876   return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
877 }
878
879 static u_char
880 show_vty_subtlv_pkt_loss (struct vty *vty, struct te_subtlv_pkt_loss *tlv)
881 {
882   u_int32_t loss;
883   u_int32_t A;
884   float fval;
885
886   loss = (u_int32_t) ntohl (tlv->value) & TE_EXT_MASK;
887   fval = (float) (loss * LOSS_PRECISION);
888   A = (u_int32_t) ntohl (tlv->value) & TE_EXT_ANORMAL;
889
890   if (vty != NULL)
891     vty_out (vty, "    %s Link Packet Loss: %g (%%)%s", A ? "Anomalous" : "Normal", fval, VTY_NEWLINE);
892   else
893     zlog_debug ("      %s Link Packet Loss: %g (%%)", A ? "Anomalous" : "Normal", fval);
894
895   return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
896 }
897
898 static u_char
899 show_vty_subtlv_res_bw (struct vty *vty, struct te_subtlv_res_bw *tlv)
900 {
901   float fval;
902
903   fval = ntohf(tlv->value);
904
905   if (vty != NULL)
906     vty_out (vty, "    Unidirectional Residual Bandwidth: %g (Bytes/sec)%s", fval, VTY_NEWLINE);
907   else
908     zlog_debug ("      Unidirectional Residual Bandwidth: %g (Bytes/sec)", fval);
909
910   return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
911 }
912
913 static u_char
914 show_vty_subtlv_ava_bw (struct vty *vty, struct te_subtlv_ava_bw *tlv)
915 {
916   float fval;
917
918   fval = ntohf (tlv->value);
919
920   if (vty != NULL)
921     vty_out (vty, "    Unidirectional Available Bandwidth: %g (Bytes/sec)%s", fval, VTY_NEWLINE);
922   else
923     zlog_debug ("      Unidirectional Available Bandwidth: %g (Bytes/sec)", fval);
924
925   return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
926 }
927
928 static u_char
929 show_vty_subtlv_use_bw (struct vty *vty, struct te_subtlv_use_bw *tlv)
930 {
931   float fval;
932
933   fval = ntohf (tlv->value);
934
935   if (vty != NULL)
936     vty_out (vty, "    Unidirectional Utilized Bandwidth: %g (Bytes/sec)%s", fval, VTY_NEWLINE);
937   else
938     zlog_debug ("      Unidirectional Utilized Bandwidth: %g (Bytes/sec)", fval);
939
940   return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
941 }
942
943 static u_char
944 show_vty_unknown_tlv (struct vty *vty, struct subtlv_header *tlvh)
945 {
946   int i, rtn = 1;
947   u_char *v = (u_char *)tlvh;
948
949   if (vty != NULL)
950     {
951       if (tlvh->length != 0)
952         {
953           vty_out (vty, "    Unknown TLV: [type(%#.2x), length(%#.2x)]%s",
954               tlvh->type, tlvh->length, VTY_NEWLINE);
955           vty_out(vty, "       Dump: [00]");
956           rtn = 1;          /* initialize end of line counter */
957           for (i = 0; i < tlvh->length; i++)
958             {
959               vty_out (vty, " %#.2x", v[i]);
960               if (rtn == 8)
961                 {
962                   vty_out (vty, "%s             [%.2x]", VTY_NEWLINE, i + 1);
963                   rtn = 1;
964                 }
965               else
966                 rtn++;
967             }
968           vty_out (vty, "%s", VTY_NEWLINE);
969         }
970       else
971         vty_out (vty, "    Unknown TLV: [type(%#.2x), length(%#.2x)]%s",
972             tlvh->type, tlvh->length, VTY_NEWLINE);
973     }
974   else
975     {
976       zlog_debug ("      Unknown TLV: [type(%#.2x), length(%#.2x)]",
977           tlvh->type, tlvh->length);
978     }
979
980   return SUBTLV_SIZE(tlvh);
981 }
982
983 /* Main Show function */
984 void
985 mpls_te_print_detail(struct vty *vty, struct te_is_neigh *te)
986 {
987   struct subtlv_header *tlvh, *next;
988   u_int16_t sum = 0;
989
990   zlog_debug ("ISIS MPLS-TE: Show database TE detail");
991
992   if (te->sub_tlvs == NULL)
993     return;
994
995   tlvh = (struct subtlv_header *)te->sub_tlvs;
996
997   for (; sum < te->sub_tlvs_length; tlvh = (next ? next : SUBTLV_HDR_NEXT (tlvh)))
998     {
999       next = NULL;
1000
1001       switch (tlvh->type)
1002       {
1003       case TE_SUBTLV_ADMIN_GRP:
1004         sum += show_vty_subtlv_admin_grp (vty, (struct te_subtlv_admin_grp *)tlvh);
1005         break;
1006       case TE_SUBTLV_LLRI:
1007         sum += show_vty_subtlv_llri (vty, (struct te_subtlv_llri *)tlvh);
1008         break;
1009       case TE_SUBTLV_LOCAL_IPADDR:
1010         sum += show_vty_subtlv_local_ipaddr (vty, (struct te_subtlv_local_ipaddr *)tlvh);
1011         break;
1012       case TE_SUBTLV_RMT_IPADDR:
1013         sum += show_vty_subtlv_rmt_ipaddr (vty, (struct te_subtlv_rmt_ipaddr *)tlvh);
1014         break;
1015       case TE_SUBTLV_MAX_BW:
1016         sum += show_vty_subtlv_max_bw (vty, (struct te_subtlv_max_bw *)tlvh);
1017         break;
1018       case TE_SUBTLV_MAX_RSV_BW:
1019         sum += show_vty_subtlv_max_rsv_bw (vty, (struct te_subtlv_max_rsv_bw *)tlvh);
1020         break;
1021       case TE_SUBTLV_UNRSV_BW:
1022         sum += show_vty_subtlv_unrsv_bw (vty, (struct te_subtlv_unrsv_bw *)tlvh);
1023         break;
1024       case TE_SUBTLV_TE_METRIC:
1025         sum += show_vty_subtlv_te_metric (vty, (struct te_subtlv_te_metric *)tlvh);
1026         break;
1027       case TE_SUBTLV_RAS:
1028         sum += show_vty_subtlv_ras (vty, (struct te_subtlv_ras *)tlvh);
1029         break;
1030       case TE_SUBTLV_RIP:
1031         sum += show_vty_subtlv_rip (vty, (struct te_subtlv_rip *)tlvh);
1032         break;
1033       case TE_SUBTLV_AV_DELAY:
1034         sum += show_vty_subtlv_av_delay (vty, (struct te_subtlv_av_delay *)tlvh);
1035         break;
1036       case TE_SUBTLV_MM_DELAY:
1037         sum += show_vty_subtlv_mm_delay (vty, (struct te_subtlv_mm_delay *)tlvh);
1038         break;
1039       case TE_SUBTLV_DELAY_VAR:
1040         sum += show_vty_subtlv_delay_var (vty, (struct te_subtlv_delay_var *)tlvh);
1041         break;
1042       case TE_SUBTLV_PKT_LOSS:
1043         sum += show_vty_subtlv_pkt_loss (vty, (struct te_subtlv_pkt_loss *)tlvh);
1044         break;
1045       case TE_SUBTLV_RES_BW:
1046         sum += show_vty_subtlv_res_bw (vty, (struct te_subtlv_res_bw *)tlvh);
1047         break;
1048       case TE_SUBTLV_AVA_BW:
1049         sum += show_vty_subtlv_ava_bw (vty, (struct te_subtlv_ava_bw *)tlvh);
1050         break;
1051       case TE_SUBTLV_USE_BW:
1052         sum += show_vty_subtlv_use_bw (vty, (struct te_subtlv_use_bw *)tlvh);
1053         break;
1054       default:
1055         sum += show_vty_unknown_tlv (vty, tlvh);
1056         break;
1057       }
1058     }
1059   return;
1060 }
1061
1062 /* Specific MPLS TE router parameters write function */
1063 void
1064 isis_mpls_te_config_write_router (struct vty *vty)
1065 {
1066
1067   zlog_debug ("ISIS MPLS-TE: Write ISIS router configuration");
1068
1069   if (IS_MPLS_TE(isisMplsTE))
1070     {
1071       vty_out (vty, "  mpls-te on%s", VTY_NEWLINE);
1072       vty_out (vty, "  mpls-te router-address %s%s",
1073                inet_ntoa (isisMplsTE.router_id), VTY_NEWLINE);
1074     }
1075
1076   return;
1077 }
1078
1079
1080 /*------------------------------------------------------------------------*
1081  * Followings are vty command functions.
1082  *------------------------------------------------------------------------*/
1083
1084 DEFUN (isis_mpls_te_on,
1085        isis_mpls_te_on_cmd,
1086        "mpls-te on",
1087        MPLS_TE_STR
1088        "Enable MPLS-TE functionality\n")
1089 {
1090   struct listnode *node;
1091   struct isis_circuit *circuit;
1092
1093   if (IS_MPLS_TE(isisMplsTE))
1094     return CMD_SUCCESS;
1095
1096   if (IS_DEBUG_ISIS(DEBUG_TE))
1097     zlog_debug ("ISIS MPLS-TE: OFF -> ON");
1098
1099   isisMplsTE.status = enable;
1100
1101   /*
1102    * Following code is intended to handle two cases;
1103    *
1104    * 1) MPLS-TE was disabled at startup time, but now become enabled.
1105    * In this case, we must enable MPLS-TE Circuit regarding interface MPLS_TE flag
1106    * 2) MPLS-TE was once enabled then disabled, and now enabled again.
1107    */
1108   for (ALL_LIST_ELEMENTS_RO (isisMplsTE.cir_list, node, circuit))
1109     {
1110       if (circuit->mtc == NULL || IS_FLOOD_AS (circuit->mtc->type))
1111         continue;
1112
1113       if ((circuit->mtc->status == disable)
1114           && HAS_LINK_PARAMS(circuit->interface))
1115         circuit->mtc->status = enable;
1116       else
1117         continue;
1118
1119       /* Reoriginate STD_TE & GMPLS circuits */
1120       if (circuit->area)
1121         lsp_regenerate_schedule (circuit->area, circuit->is_type, 0);
1122     }
1123
1124   return CMD_SUCCESS;
1125 }
1126
1127 DEFUN (no_isis_mpls_te_on,
1128        no_isis_mpls_te_on_cmd,
1129        "no mpls-te",
1130        NO_STR
1131        "Disable the MPLS-TE functionality\n")
1132 {
1133   struct listnode *node;
1134   struct isis_circuit *circuit;
1135
1136   if (isisMplsTE.status == disable)
1137     return CMD_SUCCESS;
1138
1139   if (IS_DEBUG_ISIS(DEBUG_TE))
1140     zlog_debug ("ISIS MPLS-TE: ON -> OFF");
1141
1142   isisMplsTE.status = disable;
1143
1144   /* Flush LSP if circuit engage */
1145   for (ALL_LIST_ELEMENTS_RO (isisMplsTE.cir_list, node, circuit))
1146     {
1147       if (circuit->mtc == NULL || (circuit->mtc->status == disable))
1148         continue;
1149
1150       /* disable MPLS_TE Circuit */
1151       circuit->mtc->status = disable;
1152
1153       /* Re-originate circuit without STD_TE & GMPLS parameters */
1154       if (circuit->area)
1155         lsp_regenerate_schedule (circuit->area, circuit->is_type, 0);
1156     }
1157
1158   return CMD_SUCCESS;
1159 }
1160
1161 DEFUN (isis_mpls_te_router_addr,
1162        isis_mpls_te_router_addr_cmd,
1163        "mpls-te router-address A.B.C.D",
1164        MPLS_TE_STR
1165        "Stable IP address of the advertising router\n"
1166        "MPLS-TE router address in IPv4 address format\n")
1167 {
1168   struct in_addr value;
1169   struct listnode *node;
1170   struct isis_area *area;
1171
1172   if (! inet_aton (argv[0], &value))
1173     {
1174       vty_out (vty, "Please specify Router-Addr by A.B.C.D%s", VTY_NEWLINE);
1175       return CMD_WARNING;
1176     }
1177
1178   isisMplsTE.router_id.s_addr = value.s_addr;
1179
1180   if (isisMplsTE.status == disable)
1181     return CMD_SUCCESS;
1182
1183   /* Update main Router ID in isis global structure */
1184   isis->router_id = value.s_addr;
1185   /* And re-schedule LSP update */
1186   for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
1187     if (listcount (area->area_addrs) > 0)
1188       lsp_regenerate_schedule (area, area->is_type, 0);
1189
1190   return CMD_SUCCESS;
1191 }
1192
1193 DEFUN (isis_mpls_te_inter_as,
1194        isis_mpls_te_inter_as_cmd,
1195        "mpls-te inter-as (level-1|level-1-2|level-2-only)",
1196        MPLS_TE_STR
1197        "Configure MPLS-TE Inter-AS support\n"
1198        "AREA native mode self originate INTER-AS LSP with L1 only flooding scope)\n"
1199        "AREA native mode self originate INTER-AS LSP with L1 and L2 flooding scope)\n"
1200        "AS native mode self originate INTER-AS LSP with L2 only flooding scope\n")
1201 {
1202   vty_out (vty, "Not yet supported%s", VTY_NEWLINE);
1203   return CMD_SUCCESS;
1204 }
1205
1206 DEFUN (no_isis_mpls_te_inter_as,
1207        no_isis_mpls_te_inter_as_cmd,
1208        "no mpls-te inter-as",
1209        NO_STR
1210        "Disable the MPLS-TE functionality\n"
1211        "Disable MPLS-TE Inter-AS support\n")
1212 {
1213
1214   vty_out (vty, "Not yet supported%s", VTY_NEWLINE);
1215   return CMD_SUCCESS;
1216 }
1217
1218 DEFUN (show_isis_mpls_te_router,
1219        show_isis_mpls_te_router_cmd,
1220        "show isis mpls-te router",
1221        SHOW_STR
1222        ISIS_STR
1223        MPLS_TE_STR
1224        "Router information\n")
1225 {
1226   if (IS_MPLS_TE(isisMplsTE))
1227     {
1228       vty_out (vty, "--- MPLS-TE router parameters ---%s", VTY_NEWLINE);
1229
1230       if (vty != NULL)
1231         {
1232           if (ntohs (isisMplsTE.router_id.s_addr) != 0)
1233             vty_out (vty, "  Router-Address: %s%s", inet_ntoa (isisMplsTE.router_id), VTY_NEWLINE);
1234           else
1235             vty_out (vty, "  N/A%s", VTY_NEWLINE);
1236         }
1237     }
1238   else
1239     vty_out (vty, "  MPLS-TE is disable on this router%s", VTY_NEWLINE);
1240
1241   return CMD_SUCCESS;
1242 }
1243
1244 static void
1245 show_mpls_te_sub (struct vty *vty, struct interface *ifp)
1246 {
1247   struct mpls_te_circuit *mtc;
1248
1249   if ((IS_MPLS_TE(isisMplsTE))
1250       &&  ((mtc = lookup_mpls_params_by_ifp (ifp)) != NULL))
1251     {
1252       /* Continue only if interface is not passive or support Inter-AS TEv2 */
1253       if (mtc->status != enable)
1254         {
1255           if (IS_INTER_AS(mtc->type))
1256             {
1257               vty_out (vty, "-- Inter-AS TEv2 link parameters for %s --%s",
1258                        ifp->name, VTY_NEWLINE);
1259             }
1260           else
1261             {
1262               /* MPLS-TE is not activate on this interface */
1263               /* or this interface is passive and Inter-AS TEv2 is not activate */
1264               vty_out (vty, "  %s: MPLS-TE is disabled on this interface%s",
1265                        ifp->name, VTY_NEWLINE);
1266               return;
1267             }
1268         }
1269       else
1270         {
1271           vty_out (vty, "-- MPLS-TE link parameters for %s --%s",
1272                    ifp->name, VTY_NEWLINE);
1273         }
1274
1275       show_vty_subtlv_admin_grp (vty, &mtc->admin_grp);
1276
1277       if (SUBTLV_TYPE(mtc->local_ipaddr) != 0)
1278         show_vty_subtlv_local_ipaddr (vty, &mtc->local_ipaddr);
1279       if (SUBTLV_TYPE(mtc->rmt_ipaddr) != 0)
1280         show_vty_subtlv_rmt_ipaddr (vty, &mtc->rmt_ipaddr);
1281
1282       show_vty_subtlv_max_bw (vty, &mtc->max_bw);
1283       show_vty_subtlv_max_rsv_bw (vty, &mtc->max_rsv_bw);
1284       show_vty_subtlv_unrsv_bw (vty, &mtc->unrsv_bw);
1285       show_vty_subtlv_te_metric (vty, &mtc->te_metric);
1286
1287       if (IS_INTER_AS(mtc->type))
1288         {
1289           if (SUBTLV_TYPE(mtc->ras) != 0)
1290             show_vty_subtlv_ras (vty, &mtc->ras);
1291           if (SUBTLV_TYPE(mtc->rip) != 0)
1292             show_vty_subtlv_rip (vty, &mtc->rip);
1293         }
1294
1295       show_vty_subtlv_av_delay (vty, &mtc->av_delay);
1296       show_vty_subtlv_mm_delay (vty, &mtc->mm_delay);
1297       show_vty_subtlv_delay_var (vty, &mtc->delay_var);
1298       show_vty_subtlv_pkt_loss (vty, &mtc->pkt_loss);
1299       show_vty_subtlv_res_bw (vty, &mtc->res_bw);
1300       show_vty_subtlv_ava_bw (vty, &mtc->ava_bw);
1301       show_vty_subtlv_use_bw (vty, &mtc->use_bw);
1302       vty_out (vty, "---------------%s%s", VTY_NEWLINE, VTY_NEWLINE);
1303     }
1304   else
1305     {
1306       vty_out (vty, "  %s: MPLS-TE is disabled on this interface%s",
1307                ifp->name, VTY_NEWLINE);
1308     }
1309
1310   return;
1311 }
1312
1313 DEFUN (show_isis_mpls_te_interface,
1314        show_isis_mpls_te_interface_cmd,
1315        "show isis mpls-te interface [INTERFACE]",
1316        SHOW_STR
1317        ISIS_STR
1318        MPLS_TE_STR
1319        "Interface information\n"
1320        "Interface name\n")
1321 {
1322   struct interface *ifp;
1323   struct listnode *node;
1324
1325   /* Show All Interfaces. */
1326   if (argc == 0)
1327     {
1328       for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
1329         show_mpls_te_sub (vty, ifp);
1330     }
1331   /* Interface name is specified. */
1332   else
1333     {
1334       if ((ifp = if_lookup_by_name (argv[0])) == NULL)
1335         vty_out (vty, "No such interface name%s", VTY_NEWLINE);
1336       else
1337         show_mpls_te_sub (vty, ifp);
1338     }
1339
1340   return CMD_SUCCESS;
1341 }
1342
1343 /* Initialize MPLS_TE */
1344 void
1345 isis_mpls_te_init (void)
1346 {
1347
1348   zlog_debug("ISIS MPLS-TE: Initialize");
1349
1350   /* Initialize MPLS_TE structure */
1351   isisMplsTE.status = disable;
1352   isisMplsTE.level = 0;
1353   isisMplsTE.inter_as = off;
1354   isisMplsTE.interas_areaid.s_addr = 0;
1355   isisMplsTE.cir_list = list_new();
1356   isisMplsTE.router_id.s_addr = 0;
1357   
1358   /* Register new VTY commands */
1359   install_element (VIEW_NODE, &show_isis_mpls_te_router_cmd);
1360   install_element (VIEW_NODE, &show_isis_mpls_te_interface_cmd);
1361
1362   install_element (ISIS_NODE, &isis_mpls_te_on_cmd);
1363   install_element (ISIS_NODE, &no_isis_mpls_te_on_cmd);
1364   install_element (ISIS_NODE, &isis_mpls_te_router_addr_cmd);
1365   install_element (ISIS_NODE, &isis_mpls_te_inter_as_cmd);
1366   install_element (ISIS_NODE, &no_isis_mpls_te_inter_as_cmd);
1367
1368   return;
1369 }
1370