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