2 * IS-IS Rout(e)ing protocol - isis_te.c
4 * This is an implementation of RFC5305 & RFC 7810
6 * Copyright (C) 2014 Orange Labs
7 * http://www.orange.com
9 * This file is part of GNU Zebra.
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
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.
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
42 #include "sockunion.h"
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"
61 /* Global varial for MPLS TE management */
62 struct isis_mpls_te isisMplsTE
;
64 const char *mode2text
[] = {"Disable", "Area", "AS", "Emulate"};
66 /*------------------------------------------------------------------------*
67 * Followings are control functions for MPLS-TE parameters management.
68 *------------------------------------------------------------------------*/
70 /* Search MPLS TE Circuit context from Interface */
71 static struct mpls_te_circuit
*lookup_mpls_params_by_ifp(struct interface
*ifp
)
73 struct isis_circuit
*circuit
;
75 if ((circuit
= circuit_scan_by_ifp(ifp
)) == NULL
)
81 /* Create new MPLS TE Circuit context */
82 struct mpls_te_circuit
*mpls_te_circuit_new()
84 struct mpls_te_circuit
*mtc
;
86 zlog_debug("ISIS MPLS-TE: Create new MPLS TE Circuit context");
88 mtc
= XCALLOC(MTYPE_ISIS_MPLS_TE
, sizeof(struct mpls_te_circuit
));
90 mtc
->status
= disable
;
97 /* Copy SUB TLVs parameters into a buffer - No space verification are performed
99 /* Caller must verify before that there is enough free space in the buffer */
100 uint8_t add_te_subtlvs(uint8_t *buf
, struct mpls_te_circuit
*mtc
)
102 uint8_t size
, *tlvs
= buf
;
104 zlog_debug("ISIS MPLS-TE: Add TE Sub TLVs to buffer");
108 "ISIS MPLS-TE: Abort! No MPLS TE Circuit available has been specified");
112 /* Create buffer if not provided */
114 zlog_debug("ISIS MPLS-TE: Abort! No Buffer has been specified");
118 /* TE_SUBTLV_ADMIN_GRP */
119 if (SUBTLV_TYPE(mtc
->admin_grp
) != 0) {
120 size
= SUBTLV_SIZE(&(mtc
->admin_grp
.header
));
121 memcpy(tlvs
, &(mtc
->admin_grp
), size
);
126 if (SUBTLV_TYPE(mtc
->llri
) != 0) {
127 size
= SUBTLV_SIZE(&(mtc
->llri
.header
));
128 memcpy(tlvs
, &(mtc
->llri
), size
);
132 /* TE_SUBTLV_LCLIF_IPADDR */
133 if (SUBTLV_TYPE(mtc
->local_ipaddr
) != 0) {
134 size
= SUBTLV_SIZE(&(mtc
->local_ipaddr
.header
));
135 memcpy(tlvs
, &(mtc
->local_ipaddr
), size
);
139 /* TE_SUBTLV_RMTIF_IPADDR */
140 if (SUBTLV_TYPE(mtc
->rmt_ipaddr
) != 0) {
141 size
= SUBTLV_SIZE(&(mtc
->rmt_ipaddr
.header
));
142 memcpy(tlvs
, &(mtc
->rmt_ipaddr
), size
);
146 /* TE_SUBTLV_MAX_BW */
147 if (SUBTLV_TYPE(mtc
->max_bw
) != 0) {
148 size
= SUBTLV_SIZE(&(mtc
->max_bw
.header
));
149 memcpy(tlvs
, &(mtc
->max_bw
), size
);
153 /* TE_SUBTLV_MAX_RSV_BW */
154 if (SUBTLV_TYPE(mtc
->max_rsv_bw
) != 0) {
155 size
= SUBTLV_SIZE(&(mtc
->max_rsv_bw
.header
));
156 memcpy(tlvs
, &(mtc
->max_rsv_bw
), size
);
160 /* TE_SUBTLV_UNRSV_BW */
161 if (SUBTLV_TYPE(mtc
->unrsv_bw
) != 0) {
162 size
= SUBTLV_SIZE(&(mtc
->unrsv_bw
.header
));
163 memcpy(tlvs
, &(mtc
->unrsv_bw
), size
);
167 /* TE_SUBTLV_TE_METRIC */
168 if (SUBTLV_TYPE(mtc
->te_metric
) != 0) {
169 size
= SUBTLV_SIZE(&(mtc
->te_metric
.header
));
170 memcpy(tlvs
, &(mtc
->te_metric
), size
);
174 /* TE_SUBTLV_AV_DELAY */
175 if (SUBTLV_TYPE(mtc
->av_delay
) != 0) {
176 size
= SUBTLV_SIZE(&(mtc
->av_delay
.header
));
177 memcpy(tlvs
, &(mtc
->av_delay
), size
);
181 /* TE_SUBTLV_MM_DELAY */
182 if (SUBTLV_TYPE(mtc
->mm_delay
) != 0) {
183 size
= SUBTLV_SIZE(&(mtc
->mm_delay
.header
));
184 memcpy(tlvs
, &(mtc
->mm_delay
), size
);
188 /* TE_SUBTLV_DELAY_VAR */
189 if (SUBTLV_TYPE(mtc
->delay_var
) != 0) {
190 size
= SUBTLV_SIZE(&(mtc
->delay_var
.header
));
191 memcpy(tlvs
, &(mtc
->delay_var
), size
);
195 /* TE_SUBTLV_PKT_LOSS */
196 if (SUBTLV_TYPE(mtc
->pkt_loss
) != 0) {
197 size
= SUBTLV_SIZE(&(mtc
->pkt_loss
.header
));
198 memcpy(tlvs
, &(mtc
->pkt_loss
), size
);
202 /* TE_SUBTLV_RES_BW */
203 if (SUBTLV_TYPE(mtc
->res_bw
) != 0) {
204 size
= SUBTLV_SIZE(&(mtc
->res_bw
.header
));
205 memcpy(tlvs
, &(mtc
->res_bw
), size
);
209 /* TE_SUBTLV_AVA_BW */
210 if (SUBTLV_TYPE(mtc
->ava_bw
) != 0) {
211 size
= SUBTLV_SIZE(&(mtc
->ava_bw
.header
));
212 memcpy(tlvs
, &(mtc
->ava_bw
), size
);
216 /* TE_SUBTLV_USE_BW */
217 if (SUBTLV_TYPE(mtc
->use_bw
) != 0) {
218 size
= SUBTLV_SIZE(&(mtc
->use_bw
.header
));
219 memcpy(tlvs
, &(mtc
->use_bw
), size
);
223 /* Add before this line any other parsing of TLV */
226 /* Update SubTLVs length */
227 mtc
->length
= subtlvs_len(mtc
);
229 zlog_debug("ISIS MPLS-TE: Add %d bytes length SubTLVs", mtc
->length
);
234 /* Compute total Sub-TLVs size */
235 uint8_t subtlvs_len(struct mpls_te_circuit
*mtc
)
243 /* TE_SUBTLV_ADMIN_GRP */
244 if (SUBTLV_TYPE(mtc
->admin_grp
) != 0)
245 length
+= SUBTLV_SIZE(&(mtc
->admin_grp
.header
));
248 if (SUBTLV_TYPE(mtc
->llri
) != 0)
249 length
+= SUBTLV_SIZE(&mtc
->llri
.header
);
251 /* TE_SUBTLV_LCLIF_IPADDR */
252 if (SUBTLV_TYPE(mtc
->local_ipaddr
) != 0)
253 length
+= SUBTLV_SIZE(&mtc
->local_ipaddr
.header
);
255 /* TE_SUBTLV_RMTIF_IPADDR */
256 if (SUBTLV_TYPE(mtc
->rmt_ipaddr
) != 0)
257 length
+= SUBTLV_SIZE(&mtc
->rmt_ipaddr
.header
);
259 /* TE_SUBTLV_MAX_BW */
260 if (SUBTLV_TYPE(mtc
->max_bw
) != 0)
261 length
+= SUBTLV_SIZE(&mtc
->max_bw
.header
);
263 /* TE_SUBTLV_MAX_RSV_BW */
264 if (SUBTLV_TYPE(mtc
->max_rsv_bw
) != 0)
265 length
+= SUBTLV_SIZE(&mtc
->max_rsv_bw
.header
);
267 /* TE_SUBTLV_UNRSV_BW */
268 if (SUBTLV_TYPE(mtc
->unrsv_bw
) != 0)
269 length
+= SUBTLV_SIZE(&mtc
->unrsv_bw
.header
);
271 /* TE_SUBTLV_TE_METRIC */
272 if (SUBTLV_TYPE(mtc
->te_metric
) != 0)
273 length
+= SUBTLV_SIZE(&mtc
->te_metric
.header
);
275 /* TE_SUBTLV_AV_DELAY */
276 if (SUBTLV_TYPE(mtc
->av_delay
) != 0)
277 length
+= SUBTLV_SIZE(&mtc
->av_delay
.header
);
279 /* TE_SUBTLV_MM_DELAY */
280 if (SUBTLV_TYPE(mtc
->mm_delay
) != 0)
281 length
+= SUBTLV_SIZE(&mtc
->mm_delay
.header
);
283 /* TE_SUBTLV_DELAY_VAR */
284 if (SUBTLV_TYPE(mtc
->delay_var
) != 0)
285 length
+= SUBTLV_SIZE(&mtc
->delay_var
.header
);
287 /* TE_SUBTLV_PKT_LOSS */
288 if (SUBTLV_TYPE(mtc
->pkt_loss
) != 0)
289 length
+= SUBTLV_SIZE(&mtc
->pkt_loss
.header
);
291 /* TE_SUBTLV_RES_BW */
292 if (SUBTLV_TYPE(mtc
->res_bw
) != 0)
293 length
+= SUBTLV_SIZE(&mtc
->res_bw
.header
);
295 /* TE_SUBTLV_AVA_BW */
296 if (SUBTLV_TYPE(mtc
->ava_bw
) != 0)
297 length
+= SUBTLV_SIZE(&mtc
->ava_bw
.header
);
299 /* TE_SUBTLV_USE_BW */
300 if (SUBTLV_TYPE(mtc
->use_bw
) != 0)
301 length
+= SUBTLV_SIZE(&mtc
->use_bw
.header
);
303 /* Check that length is lower than the MAXIMUM SUBTLV size i.e. 256 */
304 if (length
> MAX_SUBTLV_SIZE
) {
309 mtc
->length
= (uint8_t)length
;
314 /* Following are various functions to set MPLS TE parameters */
315 static void set_circuitparams_admin_grp(struct mpls_te_circuit
*mtc
,
318 SUBTLV_TYPE(mtc
->admin_grp
) = TE_SUBTLV_ADMIN_GRP
;
319 SUBTLV_LEN(mtc
->admin_grp
) = SUBTLV_DEF_SIZE
;
320 mtc
->admin_grp
.value
= htonl(admingrp
);
324 static void __attribute__((unused
))
325 set_circuitparams_llri(struct mpls_te_circuit
*mtc
, uint32_t local
,
328 SUBTLV_TYPE(mtc
->llri
) = TE_SUBTLV_LLRI
;
329 SUBTLV_LEN(mtc
->llri
) = TE_SUBTLV_LLRI_SIZE
;
330 mtc
->llri
.local
= htonl(local
);
331 mtc
->llri
.remote
= htonl(remote
);
334 void set_circuitparams_local_ipaddr(struct mpls_te_circuit
*mtc
,
338 SUBTLV_TYPE(mtc
->local_ipaddr
) = TE_SUBTLV_LOCAL_IPADDR
;
339 SUBTLV_LEN(mtc
->local_ipaddr
) = SUBTLV_DEF_SIZE
;
340 mtc
->local_ipaddr
.value
.s_addr
= addr
.s_addr
;
344 void set_circuitparams_rmt_ipaddr(struct mpls_te_circuit
*mtc
,
348 SUBTLV_TYPE(mtc
->rmt_ipaddr
) = TE_SUBTLV_RMT_IPADDR
;
349 SUBTLV_LEN(mtc
->rmt_ipaddr
) = SUBTLV_DEF_SIZE
;
350 mtc
->rmt_ipaddr
.value
.s_addr
= addr
.s_addr
;
354 static void set_circuitparams_max_bw(struct mpls_te_circuit
*mtc
, float fp
)
356 SUBTLV_TYPE(mtc
->max_bw
) = TE_SUBTLV_MAX_BW
;
357 SUBTLV_LEN(mtc
->max_bw
) = SUBTLV_DEF_SIZE
;
358 mtc
->max_bw
.value
= htonf(fp
);
362 static void set_circuitparams_max_rsv_bw(struct mpls_te_circuit
*mtc
, float fp
)
364 SUBTLV_TYPE(mtc
->max_rsv_bw
) = TE_SUBTLV_MAX_RSV_BW
;
365 SUBTLV_LEN(mtc
->max_rsv_bw
) = SUBTLV_DEF_SIZE
;
366 mtc
->max_rsv_bw
.value
= htonf(fp
);
370 static void set_circuitparams_unrsv_bw(struct mpls_te_circuit
*mtc
,
371 int priority
, float fp
)
373 /* Note that TLV-length field is the size of array. */
374 SUBTLV_TYPE(mtc
->unrsv_bw
) = TE_SUBTLV_UNRSV_BW
;
375 SUBTLV_LEN(mtc
->unrsv_bw
) = TE_SUBTLV_UNRSV_SIZE
;
376 mtc
->unrsv_bw
.value
[priority
] = htonf(fp
);
380 static void set_circuitparams_te_metric(struct mpls_te_circuit
*mtc
,
383 SUBTLV_TYPE(mtc
->te_metric
) = TE_SUBTLV_TE_METRIC
;
384 SUBTLV_LEN(mtc
->te_metric
) = TE_SUBTLV_TE_METRIC_SIZE
;
385 mtc
->te_metric
.value
[0] = (te_metric
>> 16) & 0xFF;
386 mtc
->te_metric
.value
[1] = (te_metric
>> 8) & 0xFF;
387 mtc
->te_metric
.value
[2] = te_metric
& 0xFF;
391 static void set_circuitparams_inter_as(struct mpls_te_circuit
*mtc
,
392 struct in_addr addr
, uint32_t as
)
395 /* Set the Remote ASBR IP address and then the associated AS number */
396 SUBTLV_TYPE(mtc
->rip
) = TE_SUBTLV_RIP
;
397 SUBTLV_LEN(mtc
->rip
) = SUBTLV_DEF_SIZE
;
398 mtc
->rip
.value
.s_addr
= addr
.s_addr
;
400 SUBTLV_TYPE(mtc
->ras
) = TE_SUBTLV_RAS
;
401 SUBTLV_LEN(mtc
->ras
) = SUBTLV_DEF_SIZE
;
402 mtc
->ras
.value
= htonl(as
);
405 static void unset_circuitparams_inter_as(struct mpls_te_circuit
*mtc
)
408 /* Reset the Remote ASBR IP address and then the associated AS number */
409 SUBTLV_TYPE(mtc
->rip
) = 0;
410 SUBTLV_LEN(mtc
->rip
) = 0;
411 mtc
->rip
.value
.s_addr
= 0;
413 SUBTLV_TYPE(mtc
->ras
) = 0;
414 SUBTLV_LEN(mtc
->ras
) = 0;
418 static void set_circuitparams_av_delay(struct mpls_te_circuit
*mtc
,
419 uint32_t delay
, uint8_t anormal
)
422 /* Note that TLV-length field is the size of array. */
423 SUBTLV_TYPE(mtc
->av_delay
) = TE_SUBTLV_AV_DELAY
;
424 SUBTLV_LEN(mtc
->av_delay
) = SUBTLV_DEF_SIZE
;
425 tmp
= delay
& TE_EXT_MASK
;
427 tmp
|= TE_EXT_ANORMAL
;
428 mtc
->av_delay
.value
= htonl(tmp
);
432 static void set_circuitparams_mm_delay(struct mpls_te_circuit
*mtc
,
433 uint32_t low
, uint32_t high
,
437 /* Note that TLV-length field is the size of array. */
438 SUBTLV_TYPE(mtc
->mm_delay
) = TE_SUBTLV_MM_DELAY
;
439 SUBTLV_LEN(mtc
->mm_delay
) = TE_SUBTLV_MM_DELAY_SIZE
;
440 tmp
= low
& TE_EXT_MASK
;
442 tmp
|= TE_EXT_ANORMAL
;
443 mtc
->mm_delay
.low
= htonl(tmp
);
444 mtc
->mm_delay
.high
= htonl(high
);
448 static void set_circuitparams_delay_var(struct mpls_te_circuit
*mtc
,
451 /* Note that TLV-length field is the size of array. */
452 SUBTLV_TYPE(mtc
->delay_var
) = TE_SUBTLV_DELAY_VAR
;
453 SUBTLV_LEN(mtc
->delay_var
) = SUBTLV_DEF_SIZE
;
454 mtc
->delay_var
.value
= htonl(jitter
& TE_EXT_MASK
);
458 static void set_circuitparams_pkt_loss(struct mpls_te_circuit
*mtc
,
459 uint32_t loss
, uint8_t anormal
)
462 /* Note that TLV-length field is the size of array. */
463 SUBTLV_TYPE(mtc
->pkt_loss
) = TE_SUBTLV_PKT_LOSS
;
464 SUBTLV_LEN(mtc
->pkt_loss
) = SUBTLV_DEF_SIZE
;
465 tmp
= loss
& TE_EXT_MASK
;
467 tmp
|= TE_EXT_ANORMAL
;
468 mtc
->pkt_loss
.value
= htonl(tmp
);
472 static void set_circuitparams_res_bw(struct mpls_te_circuit
*mtc
, float fp
)
474 /* Note that TLV-length field is the size of array. */
475 SUBTLV_TYPE(mtc
->res_bw
) = TE_SUBTLV_RES_BW
;
476 SUBTLV_LEN(mtc
->res_bw
) = SUBTLV_DEF_SIZE
;
477 mtc
->res_bw
.value
= htonf(fp
);
481 static void set_circuitparams_ava_bw(struct mpls_te_circuit
*mtc
, float fp
)
483 /* Note that TLV-length field is the size of array. */
484 SUBTLV_TYPE(mtc
->ava_bw
) = TE_SUBTLV_AVA_BW
;
485 SUBTLV_LEN(mtc
->ava_bw
) = SUBTLV_DEF_SIZE
;
486 mtc
->ava_bw
.value
= htonf(fp
);
490 static void set_circuitparams_use_bw(struct mpls_te_circuit
*mtc
, float fp
)
492 /* Note that TLV-length field is the size of array. */
493 SUBTLV_TYPE(mtc
->use_bw
) = TE_SUBTLV_USE_BW
;
494 SUBTLV_LEN(mtc
->use_bw
) = SUBTLV_DEF_SIZE
;
495 mtc
->use_bw
.value
= htonf(fp
);
499 /* Main initialization / update function of the MPLS TE Circuit context */
500 /* Call when interface TE Link parameters are modified */
501 void isis_link_params_update(struct isis_circuit
*circuit
,
502 struct interface
*ifp
)
505 struct prefix_ipv4
*addr
;
506 struct mpls_te_circuit
*mtc
;
509 if ((circuit
== NULL
) || (ifp
== NULL
))
512 zlog_info("MPLS-TE: Initialize circuit parameters for interface %s",
515 /* Check if MPLS TE Circuit context has not been already created */
516 if (circuit
->mtc
== NULL
)
517 circuit
->mtc
= mpls_te_circuit_new();
521 /* Fulfil MTC TLV from ifp TE Link parameters */
522 if (HAS_LINK_PARAMS(ifp
)) {
523 mtc
->status
= enable
;
525 if (IS_PARAM_SET(ifp
->link_params
, LP_ADM_GRP
))
526 set_circuitparams_admin_grp(
527 mtc
, ifp
->link_params
->admin_grp
);
529 SUBTLV_TYPE(mtc
->admin_grp
) = 0;
531 /* If not already set, register local IP addr from ip_addr list
533 if (SUBTLV_TYPE(mtc
->local_ipaddr
) == 0) {
534 if (circuit
->ip_addrs
!= NULL
535 && listcount(circuit
->ip_addrs
) != 0) {
536 addr
= (struct prefix_ipv4
*)listgetdata(
537 (struct listnode
*)listhead(
539 set_circuitparams_local_ipaddr(mtc
,
544 /* If not already set, try to determine Remote IP addr if
546 if ((SUBTLV_TYPE(mtc
->rmt_ipaddr
) == 0)
547 && (circuit
->circ_type
== CIRCUIT_T_P2P
)) {
548 struct isis_adjacency
*adj
= circuit
->u
.p2p
.neighbor
;
549 if (adj
&& adj
->adj_state
== ISIS_ADJ_UP
550 && adj
->ipv4_address_count
) {
551 set_circuitparams_rmt_ipaddr(
552 mtc
, adj
->ipv4_addresses
[0]);
556 if (IS_PARAM_SET(ifp
->link_params
, LP_MAX_BW
))
557 set_circuitparams_max_bw(mtc
, ifp
->link_params
->max_bw
);
559 SUBTLV_TYPE(mtc
->max_bw
) = 0;
561 if (IS_PARAM_SET(ifp
->link_params
, LP_MAX_RSV_BW
))
562 set_circuitparams_max_rsv_bw(
563 mtc
, ifp
->link_params
->max_rsv_bw
);
565 SUBTLV_TYPE(mtc
->max_rsv_bw
) = 0;
567 if (IS_PARAM_SET(ifp
->link_params
, LP_UNRSV_BW
))
568 for (i
= 0; i
< MAX_CLASS_TYPE
; i
++)
569 set_circuitparams_unrsv_bw(
570 mtc
, i
, ifp
->link_params
->unrsv_bw
[i
]);
572 SUBTLV_TYPE(mtc
->unrsv_bw
) = 0;
574 if (IS_PARAM_SET(ifp
->link_params
, LP_TE_METRIC
))
575 set_circuitparams_te_metric(
576 mtc
, ifp
->link_params
->te_metric
);
578 SUBTLV_TYPE(mtc
->te_metric
) = 0;
580 /* TE metric Extensions */
581 if (IS_PARAM_SET(ifp
->link_params
, LP_DELAY
))
582 set_circuitparams_av_delay(
583 mtc
, ifp
->link_params
->av_delay
, 0);
585 SUBTLV_TYPE(mtc
->av_delay
) = 0;
587 if (IS_PARAM_SET(ifp
->link_params
, LP_MM_DELAY
))
588 set_circuitparams_mm_delay(
589 mtc
, ifp
->link_params
->min_delay
,
590 ifp
->link_params
->max_delay
, 0);
592 SUBTLV_TYPE(mtc
->mm_delay
) = 0;
594 if (IS_PARAM_SET(ifp
->link_params
, LP_DELAY_VAR
))
595 set_circuitparams_delay_var(
596 mtc
, ifp
->link_params
->delay_var
);
598 SUBTLV_TYPE(mtc
->delay_var
) = 0;
600 if (IS_PARAM_SET(ifp
->link_params
, LP_PKT_LOSS
))
601 set_circuitparams_pkt_loss(
602 mtc
, ifp
->link_params
->pkt_loss
, 0);
604 SUBTLV_TYPE(mtc
->pkt_loss
) = 0;
606 if (IS_PARAM_SET(ifp
->link_params
, LP_RES_BW
))
607 set_circuitparams_res_bw(mtc
, ifp
->link_params
->res_bw
);
609 SUBTLV_TYPE(mtc
->res_bw
) = 0;
611 if (IS_PARAM_SET(ifp
->link_params
, LP_AVA_BW
))
612 set_circuitparams_ava_bw(mtc
, ifp
->link_params
->ava_bw
);
614 SUBTLV_TYPE(mtc
->ava_bw
) = 0;
616 if (IS_PARAM_SET(ifp
->link_params
, LP_USE_BW
))
617 set_circuitparams_use_bw(mtc
, ifp
->link_params
->use_bw
);
619 SUBTLV_TYPE(mtc
->use_bw
) = 0;
622 if (IS_PARAM_SET(ifp
->link_params
, LP_RMT_AS
))
623 set_circuitparams_inter_as(mtc
,
624 ifp
->link_params
->rmt_ip
,
625 ifp
->link_params
->rmt_as
);
627 /* reset inter-as TE params */
628 unset_circuitparams_inter_as(mtc
);
630 /* Compute total length of SUB TLVs */
631 mtc
->length
= subtlvs_len(mtc
);
634 mtc
->status
= disable
;
636 /* Finally Update LSP */
638 if (IS_MPLS_TE(isisMplsTE
) && circuit
->area
)
639 lsp_regenerate_schedule (circuit
->area
, circuit
->is_type
, 0);
644 void isis_mpls_te_update(struct interface
*ifp
)
646 struct isis_circuit
*circuit
;
652 /* Get circuit context from interface */
653 if ((circuit
= circuit_scan_by_ifp(ifp
)) == NULL
)
656 /* Update TE TLVs ... */
657 isis_link_params_update(circuit
, ifp
);
660 if (IS_MPLS_TE(isisMplsTE
) && circuit
->area
)
661 lsp_regenerate_schedule(circuit
->area
, circuit
->is_type
, 0);
666 /*------------------------------------------------------------------------*
667 * Followings are vty session control functions.
668 *------------------------------------------------------------------------*/
670 static uint8_t print_subtlv_admin_grp(struct sbuf
*buf
, int indent
,
671 struct te_subtlv_admin_grp
*tlv
)
673 sbuf_push(buf
, indent
, "Administrative Group: 0x%" PRIx32
"\n",
675 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
678 static uint8_t print_subtlv_llri(struct sbuf
*buf
, int indent
,
679 struct te_subtlv_llri
*tlv
)
681 sbuf_push(buf
, indent
, "Link Local ID: %" PRIu32
"\n",
683 sbuf_push(buf
, indent
, "Link Remote ID: %" PRIu32
"\n",
686 return (SUBTLV_HDR_SIZE
+ TE_SUBTLV_LLRI_SIZE
);
689 static uint8_t print_subtlv_local_ipaddr(struct sbuf
*buf
, int indent
,
690 struct te_subtlv_local_ipaddr
*tlv
)
692 sbuf_push(buf
, indent
, "Local Interface IP Address(es): %s\n",
693 inet_ntoa(tlv
->value
));
695 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
698 static uint8_t print_subtlv_rmt_ipaddr(struct sbuf
*buf
, int indent
,
699 struct te_subtlv_rmt_ipaddr
*tlv
)
701 sbuf_push(buf
, indent
, "Remote Interface IP Address(es): %s\n",
702 inet_ntoa(tlv
->value
));
704 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
707 static uint8_t print_subtlv_max_bw(struct sbuf
*buf
, int indent
,
708 struct te_subtlv_max_bw
*tlv
)
712 fval
= ntohf(tlv
->value
);
714 sbuf_push(buf
, indent
, "Maximum Bandwidth: %g (Bytes/sec)\n", fval
);
716 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
719 static uint8_t print_subtlv_max_rsv_bw(struct sbuf
*buf
, int indent
,
720 struct te_subtlv_max_rsv_bw
*tlv
)
724 fval
= ntohf(tlv
->value
);
726 sbuf_push(buf
, indent
, "Maximum Reservable Bandwidth: %g (Bytes/sec)\n",
729 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
732 static uint8_t print_subtlv_unrsv_bw(struct sbuf
*buf
, int indent
,
733 struct te_subtlv_unrsv_bw
*tlv
)
738 sbuf_push(buf
, indent
, "Unreserved Bandwidth:\n");
740 for (i
= 0; i
< MAX_CLASS_TYPE
; i
+= 2) {
741 fval1
= ntohf(tlv
->value
[i
]);
742 fval2
= ntohf(tlv
->value
[i
+ 1]);
743 sbuf_push(buf
, indent
+ 2,
744 "[%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n", i
,
745 fval1
, i
+ 1, fval2
);
748 return (SUBTLV_HDR_SIZE
+ TE_SUBTLV_UNRSV_SIZE
);
751 static uint8_t print_subtlv_te_metric(struct sbuf
*buf
, int indent
,
752 struct te_subtlv_te_metric
*tlv
)
756 te_metric
= tlv
->value
[2] | tlv
->value
[1] << 8 | tlv
->value
[0] << 16;
757 sbuf_push(buf
, indent
, "Traffic Engineering Metric: %u\n", te_metric
);
759 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
762 static uint8_t print_subtlv_ras(struct sbuf
*buf
, int indent
,
763 struct te_subtlv_ras
*tlv
)
765 sbuf_push(buf
, indent
, "Inter-AS TE Remote AS number: %" PRIu32
"\n",
768 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
771 static uint8_t print_subtlv_rip(struct sbuf
*buf
, int indent
,
772 struct te_subtlv_rip
*tlv
)
774 sbuf_push(buf
, indent
, "Inter-AS TE Remote ASBR IP address: %s\n",
775 inet_ntoa(tlv
->value
));
777 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
780 static uint8_t print_subtlv_av_delay(struct sbuf
*buf
, int indent
,
781 struct te_subtlv_av_delay
*tlv
)
786 delay
= (uint32_t)ntohl(tlv
->value
) & TE_EXT_MASK
;
787 A
= (uint32_t)ntohl(tlv
->value
) & TE_EXT_ANORMAL
;
789 sbuf_push(buf
, indent
,
790 "%s Average Link Delay: %" PRIu32
" (micro-sec)\n",
791 A
? "Anomalous" : "Normal", delay
);
793 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
796 static uint8_t print_subtlv_mm_delay(struct sbuf
*buf
, int indent
,
797 struct te_subtlv_mm_delay
*tlv
)
802 low
= (uint32_t)ntohl(tlv
->low
) & TE_EXT_MASK
;
803 A
= (uint32_t)ntohl(tlv
->low
) & TE_EXT_ANORMAL
;
804 high
= (uint32_t)ntohl(tlv
->high
) & TE_EXT_MASK
;
806 sbuf_push(buf
, indent
, "%s Min/Max Link Delay: %" PRIu32
" / %" PRIu32
" (micro-sec)\n",
807 A
? "Anomalous" : "Normal", low
, high
);
809 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
812 static uint8_t print_subtlv_delay_var(struct sbuf
*buf
, int indent
,
813 struct te_subtlv_delay_var
*tlv
)
817 jitter
= (uint32_t)ntohl(tlv
->value
) & TE_EXT_MASK
;
819 sbuf_push(buf
, indent
, "Delay Variation: %" PRIu32
" (micro-sec)\n",
822 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
825 static uint8_t print_subtlv_pkt_loss(struct sbuf
*buf
, int indent
,
826 struct te_subtlv_pkt_loss
*tlv
)
832 loss
= (uint32_t)ntohl(tlv
->value
) & TE_EXT_MASK
;
833 fval
= (float)(loss
* LOSS_PRECISION
);
834 A
= (uint32_t)ntohl(tlv
->value
) & TE_EXT_ANORMAL
;
836 sbuf_push(buf
, indent
, "%s Link Packet Loss: %g (%%)\n",
837 A
? "Anomalous" : "Normal", fval
);
839 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
842 static uint8_t print_subtlv_res_bw(struct sbuf
*buf
, int indent
,
843 struct te_subtlv_res_bw
*tlv
)
847 fval
= ntohf(tlv
->value
);
849 sbuf_push(buf
, indent
,
850 "Unidirectional Residual Bandwidth: %g (Bytes/sec)\n", fval
);
852 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
855 static uint8_t print_subtlv_ava_bw(struct sbuf
*buf
, int indent
,
856 struct te_subtlv_ava_bw
*tlv
)
860 fval
= ntohf(tlv
->value
);
862 sbuf_push(buf
, indent
,
863 "Unidirectional Available Bandwidth: %g (Bytes/sec)\n", fval
);
865 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
868 static uint8_t print_subtlv_use_bw(struct sbuf
*buf
, int indent
,
869 struct te_subtlv_use_bw
*tlv
)
873 fval
= ntohf(tlv
->value
);
875 sbuf_push(buf
, indent
,
876 "Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n", fval
);
878 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
881 static uint8_t print_unknown_tlv(struct sbuf
*buf
, int indent
,
882 struct subtlv_header
*tlvh
)
885 uint8_t *v
= (uint8_t *)tlvh
;
887 if (tlvh
->length
!= 0) {
888 sbuf_push(buf
, indent
,
889 "Unknown TLV: [type(%#.2x), length(%#.2x)]\n",
890 tlvh
->type
, tlvh
->length
);
891 sbuf_push(buf
, indent
+ 2, "Dump: [00]");
892 rtn
= 1; /* initialize end of line counter */
893 for (i
= 0; i
< tlvh
->length
; i
++) {
894 sbuf_push(buf
, 0, " %#.2x", v
[i
]);
896 sbuf_push(buf
, 0, "\n");
897 sbuf_push(buf
, indent
+ 8, "[%.2x]", i
+ 1);
902 sbuf_push(buf
, 0, "\n");
904 sbuf_push(buf
, indent
,
905 "Unknown TLV: [type(%#.2x), length(%#.2x)]\n",
906 tlvh
->type
, tlvh
->length
);
909 return SUBTLV_SIZE(tlvh
);
912 /* Main Show function */
913 void mpls_te_print_detail(struct sbuf
*buf
, int indent
,
914 uint8_t *subtlvs
, uint8_t subtlv_len
)
916 struct subtlv_header
*tlvh
= (struct subtlv_header
*)subtlvs
;
919 for (; sum
< subtlv_len
;
920 tlvh
= (struct subtlv_header
*)(subtlvs
+ sum
)) {
921 if (subtlv_len
- sum
< SUBTLV_SIZE(tlvh
)) {
922 sbuf_push(buf
, indent
, "Available data %" PRIu8
" is less than TLV size %u!\n",
923 subtlv_len
- sum
, SUBTLV_SIZE(tlvh
));
927 switch (tlvh
->type
) {
928 case TE_SUBTLV_ADMIN_GRP
:
929 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
930 sbuf_push(buf
, indent
, "TLV size does not match expected size for Administrative Group!\n");
933 sum
+= print_subtlv_admin_grp(buf
, indent
,
934 (struct te_subtlv_admin_grp
*)tlvh
);
937 if (tlvh
->length
!= TE_SUBTLV_LLRI_SIZE
) {
938 sbuf_push(buf
, indent
, "TLV size does not match expected size for Link ID!\n");
941 sum
+= print_subtlv_llri(buf
, indent
,
942 (struct te_subtlv_llri
*)tlvh
);
944 case TE_SUBTLV_LOCAL_IPADDR
:
945 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
946 sbuf_push(buf
, indent
, "TLV size does not match expected size for Local IP address!\n");
949 sum
+= print_subtlv_local_ipaddr(buf
, indent
,
950 (struct te_subtlv_local_ipaddr
*)tlvh
);
952 case TE_SUBTLV_RMT_IPADDR
:
953 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
954 sbuf_push(buf
, indent
, "TLV size does not match expected size for Remote Interface address!\n");
957 sum
+= print_subtlv_rmt_ipaddr(buf
, indent
,
958 (struct te_subtlv_rmt_ipaddr
*)tlvh
);
960 case TE_SUBTLV_MAX_BW
:
961 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
962 sbuf_push(buf
, indent
, "TLV size does not match expected size for Maximum Bandwidth!\n");
965 sum
+= print_subtlv_max_bw(buf
, indent
,
966 (struct te_subtlv_max_bw
*)tlvh
);
968 case TE_SUBTLV_MAX_RSV_BW
:
969 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
970 sbuf_push(buf
, indent
, "TLV size does not match expected size for Maximum Reservable Bandwidth!\n");
973 sum
+= print_subtlv_max_rsv_bw(buf
, indent
,
974 (struct te_subtlv_max_rsv_bw
*)tlvh
);
976 case TE_SUBTLV_UNRSV_BW
:
977 if (tlvh
->length
!= TE_SUBTLV_UNRSV_SIZE
) {
978 sbuf_push(buf
, indent
, "TLV size does not match expected size for Unreserved Bandwidth!\n");
981 sum
+= print_subtlv_unrsv_bw(buf
, indent
,
982 (struct te_subtlv_unrsv_bw
*)tlvh
);
984 case TE_SUBTLV_TE_METRIC
:
985 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
986 sbuf_push(buf
, indent
, "TLV size does not match expected size for Traffic Engineering Metric!\n");
989 sum
+= print_subtlv_te_metric(buf
, indent
,
990 (struct te_subtlv_te_metric
*)tlvh
);
993 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
994 sbuf_push(buf
, indent
, "TLV size does not match expected size for Remote AS number!\n");
997 sum
+= print_subtlv_ras(buf
, indent
,
998 (struct te_subtlv_ras
*)tlvh
);
1001 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1002 sbuf_push(buf
, indent
, "TLV size does not match expected size for Remote ASBR IP Address!\n");
1005 sum
+= print_subtlv_rip(buf
, indent
,
1006 (struct te_subtlv_rip
*)tlvh
);
1008 case TE_SUBTLV_AV_DELAY
:
1009 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1010 sbuf_push(buf
, indent
, "TLV size does not match expected size for Average Link Delay!\n");
1013 sum
+= print_subtlv_av_delay(buf
, indent
,
1014 (struct te_subtlv_av_delay
*)tlvh
);
1016 case TE_SUBTLV_MM_DELAY
:
1017 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1018 sbuf_push(buf
, indent
, "TLV size does not match expected size for Min/Max Link Delay!\n");
1021 sum
+= print_subtlv_mm_delay(buf
, indent
,
1022 (struct te_subtlv_mm_delay
*)tlvh
);
1024 case TE_SUBTLV_DELAY_VAR
:
1025 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1026 sbuf_push(buf
, indent
, "TLV size does not match expected size for Delay Variation!\n");
1029 sum
+= print_subtlv_delay_var(buf
, indent
,
1030 (struct te_subtlv_delay_var
*)tlvh
);
1032 case TE_SUBTLV_PKT_LOSS
:
1033 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1034 sbuf_push(buf
, indent
, "TLV size does not match expected size for Link Packet Loss!\n");
1037 sum
+= print_subtlv_pkt_loss(buf
, indent
,
1038 (struct te_subtlv_pkt_loss
*)tlvh
);
1040 case TE_SUBTLV_RES_BW
:
1041 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1042 sbuf_push(buf
, indent
, "TLV size does not match expected size for Unidirectional Residual Bandwidth!\n");
1045 sum
+= print_subtlv_res_bw(buf
, indent
,
1046 (struct te_subtlv_res_bw
*)tlvh
);
1048 case TE_SUBTLV_AVA_BW
:
1049 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1050 sbuf_push(buf
, indent
, "TLV size does not match expected size for Unidirectional Available Bandwidth!\n");
1053 sum
+= print_subtlv_ava_bw(buf
, indent
,
1054 (struct te_subtlv_ava_bw
*)tlvh
);
1056 case TE_SUBTLV_USE_BW
:
1057 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1058 sbuf_push(buf
, indent
, "TLV size does not match expected size for Unidirectional Utilized Bandwidth!\n");
1061 sum
+= print_subtlv_use_bw(buf
, indent
,
1062 (struct te_subtlv_use_bw
*)tlvh
);
1065 sum
+= print_unknown_tlv(buf
, indent
, tlvh
);
1072 /* Specific MPLS TE router parameters write function */
1073 void isis_mpls_te_config_write_router(struct vty
*vty
)
1075 if (IS_MPLS_TE(isisMplsTE
)) {
1076 vty_out(vty
, " mpls-te on\n");
1077 vty_out(vty
, " mpls-te router-address %s\n",
1078 inet_ntoa(isisMplsTE
.router_id
));
1085 /*------------------------------------------------------------------------*
1086 * Followings are vty command functions.
1087 *------------------------------------------------------------------------*/
1089 DEFUN (isis_mpls_te_on
,
1090 isis_mpls_te_on_cmd
,
1093 "Enable MPLS-TE functionality\n")
1095 struct listnode
*node
;
1096 struct isis_circuit
*circuit
;
1098 if (IS_MPLS_TE(isisMplsTE
))
1101 if (IS_DEBUG_ISIS(DEBUG_TE
))
1102 zlog_debug("ISIS MPLS-TE: OFF -> ON");
1104 isisMplsTE
.status
= enable
;
1107 * Following code is intended to handle two cases;
1109 * 1) MPLS-TE was disabled at startup time, but now become enabled.
1110 * In this case, we must enable MPLS-TE Circuit regarding interface
1112 * 2) MPLS-TE was once enabled then disabled, and now enabled again.
1114 for (ALL_LIST_ELEMENTS_RO(isisMplsTE
.cir_list
, node
, circuit
)) {
1115 if (circuit
->mtc
== NULL
|| IS_FLOOD_AS(circuit
->mtc
->type
))
1118 if ((circuit
->mtc
->status
== disable
)
1119 && HAS_LINK_PARAMS(circuit
->interface
))
1120 circuit
->mtc
->status
= enable
;
1124 /* Reoriginate STD_TE & GMPLS circuits */
1126 lsp_regenerate_schedule(circuit
->area
, circuit
->is_type
,
1133 DEFUN (no_isis_mpls_te_on
,
1134 no_isis_mpls_te_on_cmd
,
1137 "Disable the MPLS-TE functionality\n")
1139 struct listnode
*node
;
1140 struct isis_circuit
*circuit
;
1142 if (isisMplsTE
.status
== disable
)
1145 if (IS_DEBUG_ISIS(DEBUG_TE
))
1146 zlog_debug("ISIS MPLS-TE: ON -> OFF");
1148 isisMplsTE
.status
= disable
;
1150 /* Flush LSP if circuit engage */
1151 for (ALL_LIST_ELEMENTS_RO(isisMplsTE
.cir_list
, node
, circuit
)) {
1152 if (circuit
->mtc
== NULL
|| (circuit
->mtc
->status
== disable
))
1155 /* disable MPLS_TE Circuit */
1156 circuit
->mtc
->status
= disable
;
1158 /* Re-originate circuit without STD_TE & GMPLS parameters */
1160 lsp_regenerate_schedule(circuit
->area
, circuit
->is_type
,
1167 DEFUN (isis_mpls_te_router_addr
,
1168 isis_mpls_te_router_addr_cmd
,
1169 "mpls-te router-address A.B.C.D",
1171 "Stable IP address of the advertising router\n"
1172 "MPLS-TE router address in IPv4 address format\n")
1175 struct in_addr value
;
1176 struct listnode
*node
;
1177 struct isis_area
*area
;
1179 if (!inet_aton(argv
[idx_ipv4
]->arg
, &value
)) {
1180 vty_out(vty
, "Please specify Router-Addr by A.B.C.D\n");
1181 return CMD_WARNING_CONFIG_FAILED
;
1184 isisMplsTE
.router_id
.s_addr
= value
.s_addr
;
1186 if (isisMplsTE
.status
== disable
)
1189 /* Update main Router ID in isis global structure */
1190 isis
->router_id
= value
.s_addr
;
1191 /* And re-schedule LSP update */
1192 for (ALL_LIST_ELEMENTS_RO(isis
->area_list
, node
, area
))
1193 if (listcount(area
->area_addrs
) > 0)
1194 lsp_regenerate_schedule(area
, area
->is_type
, 0);
1199 DEFUN (isis_mpls_te_inter_as
,
1200 isis_mpls_te_inter_as_cmd
,
1201 "mpls-te inter-as <level-1|level-1-2|level-2-only>",
1203 "Configure MPLS-TE Inter-AS support\n"
1204 "AREA native mode self originate INTER-AS LSP with L1 only flooding scope)\n"
1205 "AREA native mode self originate INTER-AS LSP with L1 and L2 flooding scope)\n"
1206 "AS native mode self originate INTER-AS LSP with L2 only flooding scope\n")
1208 vty_out(vty
, "Not yet supported\n");
1212 DEFUN (no_isis_mpls_te_inter_as
,
1213 no_isis_mpls_te_inter_as_cmd
,
1214 "no mpls-te inter-as",
1216 "Disable the MPLS-TE functionality\n"
1217 "Disable MPLS-TE Inter-AS support\n")
1220 vty_out(vty
, "Not yet supported\n");
1224 DEFUN (show_isis_mpls_te_router
,
1225 show_isis_mpls_te_router_cmd
,
1226 "show isis mpls-te router",
1230 "Router information\n")
1232 if (IS_MPLS_TE(isisMplsTE
)) {
1233 vty_out(vty
, "--- MPLS-TE router parameters ---\n");
1235 if (ntohs(isisMplsTE
.router_id
.s_addr
) != 0)
1236 vty_out(vty
, " Router-Address: %s\n",
1237 inet_ntoa(isisMplsTE
.router_id
));
1239 vty_out(vty
, " N/A\n");
1241 vty_out(vty
, " MPLS-TE is disable on this router\n");
1246 static void show_mpls_te_sub(struct vty
*vty
, struct interface
*ifp
)
1248 struct mpls_te_circuit
*mtc
;
1251 sbuf_init(&buf
, NULL
, 0);
1253 if ((IS_MPLS_TE(isisMplsTE
))
1254 && ((mtc
= lookup_mpls_params_by_ifp(ifp
)) != NULL
)) {
1255 /* Continue only if interface is not passive or support Inter-AS
1257 if (mtc
->status
!= enable
) {
1258 if (IS_INTER_AS(mtc
->type
)) {
1260 "-- Inter-AS TEv2 link parameters for %s --\n",
1263 /* MPLS-TE is not activate on this interface */
1264 /* or this interface is passive and Inter-AS
1265 * TEv2 is not activate */
1267 " %s: MPLS-TE is disabled on this interface\n",
1272 vty_out(vty
, "-- MPLS-TE link parameters for %s --\n",
1277 print_subtlv_admin_grp(&buf
, 4, &mtc
->admin_grp
);
1279 if (SUBTLV_TYPE(mtc
->local_ipaddr
) != 0)
1280 print_subtlv_local_ipaddr(&buf
, 4, &mtc
->local_ipaddr
);
1281 if (SUBTLV_TYPE(mtc
->rmt_ipaddr
) != 0)
1282 print_subtlv_rmt_ipaddr(&buf
, 4, &mtc
->rmt_ipaddr
);
1284 print_subtlv_max_bw(&buf
, 4, &mtc
->max_bw
);
1285 print_subtlv_max_rsv_bw(&buf
, 4, &mtc
->max_rsv_bw
);
1286 print_subtlv_unrsv_bw(&buf
, 4, &mtc
->unrsv_bw
);
1287 print_subtlv_te_metric(&buf
, 4, &mtc
->te_metric
);
1289 if (IS_INTER_AS(mtc
->type
)) {
1290 if (SUBTLV_TYPE(mtc
->ras
) != 0)
1291 print_subtlv_ras(&buf
, 4, &mtc
->ras
);
1292 if (SUBTLV_TYPE(mtc
->rip
) != 0)
1293 print_subtlv_rip(&buf
, 4, &mtc
->rip
);
1296 print_subtlv_av_delay(&buf
, 4, &mtc
->av_delay
);
1297 print_subtlv_mm_delay(&buf
, 4, &mtc
->mm_delay
);
1298 print_subtlv_delay_var(&buf
, 4, &mtc
->delay_var
);
1299 print_subtlv_pkt_loss(&buf
, 4, &mtc
->pkt_loss
);
1300 print_subtlv_res_bw(&buf
, 4, &mtc
->res_bw
);
1301 print_subtlv_ava_bw(&buf
, 4, &mtc
->ava_bw
);
1302 print_subtlv_use_bw(&buf
, 4, &mtc
->use_bw
);
1304 vty_multiline(vty
, "", "%s", sbuf_buf(&buf
));
1305 vty_out(vty
, "---------------\n\n");
1307 vty_out(vty
, " %s: MPLS-TE is disabled on this interface\n",
1315 DEFUN (show_isis_mpls_te_interface
,
1316 show_isis_mpls_te_interface_cmd
,
1317 "show isis mpls-te interface [INTERFACE]",
1321 "Interface information\n"
1324 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
1325 int idx_interface
= 4;
1326 struct interface
*ifp
;
1328 /* Show All Interfaces. */
1330 FOR_ALL_INTERFACES (vrf
, ifp
)
1331 show_mpls_te_sub(vty
, ifp
);
1333 /* Interface name is specified. */
1335 if ((ifp
= if_lookup_by_name(argv
[idx_interface
]->arg
,
1338 vty_out(vty
, "No such interface name\n");
1340 show_mpls_te_sub(vty
, ifp
);
1346 /* Initialize MPLS_TE */
1347 void isis_mpls_te_init(void)
1350 zlog_debug("ISIS MPLS-TE: Initialize");
1352 /* Initialize MPLS_TE structure */
1353 isisMplsTE
.status
= disable
;
1354 isisMplsTE
.level
= 0;
1355 isisMplsTE
.inter_as
= off
;
1356 isisMplsTE
.interas_areaid
.s_addr
= 0;
1357 isisMplsTE
.cir_list
= list_new();
1358 isisMplsTE
.router_id
.s_addr
= 0;
1360 /* Register new VTY commands */
1361 install_element(VIEW_NODE
, &show_isis_mpls_te_router_cmd
);
1362 install_element(VIEW_NODE
, &show_isis_mpls_te_interface_cmd
);
1364 install_element(ISIS_NODE
, &isis_mpls_te_on_cmd
);
1365 install_element(ISIS_NODE
, &no_isis_mpls_te_on_cmd
);
1366 install_element(ISIS_NODE
, &isis_mpls_te_router_addr_cmd
);
1367 install_element(ISIS_NODE
, &isis_mpls_te_inter_as_cmd
);
1368 install_element(ISIS_NODE
, &no_isis_mpls_te_inter_as_cmd
);