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 /* Create new MPLS TE Circuit context */
71 struct mpls_te_circuit
*mpls_te_circuit_new(void)
73 struct mpls_te_circuit
*mtc
;
75 zlog_debug("ISIS MPLS-TE: Create new MPLS TE Circuit context");
77 mtc
= XCALLOC(MTYPE_ISIS_MPLS_TE
, sizeof(struct mpls_te_circuit
));
79 mtc
->status
= disable
;
86 /* Copy SUB TLVs parameters into a buffer - No space verification are performed
88 /* Caller must verify before that there is enough free space in the buffer */
89 uint8_t add_te_subtlvs(uint8_t *buf
, struct mpls_te_circuit
*mtc
)
91 uint8_t size
, *tlvs
= buf
;
93 zlog_debug("ISIS MPLS-TE: Add TE Sub TLVs to buffer");
97 "ISIS MPLS-TE: Abort! No MPLS TE Circuit available has been specified");
101 /* Create buffer if not provided */
103 zlog_debug("ISIS MPLS-TE: Abort! No Buffer has been specified");
107 /* TE_SUBTLV_ADMIN_GRP */
108 if (SUBTLV_TYPE(mtc
->admin_grp
) != 0) {
109 size
= SUBTLV_SIZE(&(mtc
->admin_grp
.header
));
110 memcpy(tlvs
, &(mtc
->admin_grp
), size
);
115 if (SUBTLV_TYPE(mtc
->llri
) != 0) {
116 size
= SUBTLV_SIZE(&(mtc
->llri
.header
));
117 memcpy(tlvs
, &(mtc
->llri
), size
);
121 /* TE_SUBTLV_LCLIF_IPADDR */
122 if (SUBTLV_TYPE(mtc
->local_ipaddr
) != 0) {
123 size
= SUBTLV_SIZE(&(mtc
->local_ipaddr
.header
));
124 memcpy(tlvs
, &(mtc
->local_ipaddr
), size
);
128 /* TE_SUBTLV_RMTIF_IPADDR */
129 if (SUBTLV_TYPE(mtc
->rmt_ipaddr
) != 0) {
130 size
= SUBTLV_SIZE(&(mtc
->rmt_ipaddr
.header
));
131 memcpy(tlvs
, &(mtc
->rmt_ipaddr
), size
);
135 /* TE_SUBTLV_MAX_BW */
136 if (SUBTLV_TYPE(mtc
->max_bw
) != 0) {
137 size
= SUBTLV_SIZE(&(mtc
->max_bw
.header
));
138 memcpy(tlvs
, &(mtc
->max_bw
), size
);
142 /* TE_SUBTLV_MAX_RSV_BW */
143 if (SUBTLV_TYPE(mtc
->max_rsv_bw
) != 0) {
144 size
= SUBTLV_SIZE(&(mtc
->max_rsv_bw
.header
));
145 memcpy(tlvs
, &(mtc
->max_rsv_bw
), size
);
149 /* TE_SUBTLV_UNRSV_BW */
150 if (SUBTLV_TYPE(mtc
->unrsv_bw
) != 0) {
151 size
= SUBTLV_SIZE(&(mtc
->unrsv_bw
.header
));
152 memcpy(tlvs
, &(mtc
->unrsv_bw
), size
);
156 /* TE_SUBTLV_TE_METRIC */
157 if (SUBTLV_TYPE(mtc
->te_metric
) != 0) {
158 size
= SUBTLV_SIZE(&(mtc
->te_metric
.header
));
159 memcpy(tlvs
, &(mtc
->te_metric
), size
);
163 /* TE_SUBTLV_AV_DELAY */
164 if (SUBTLV_TYPE(mtc
->av_delay
) != 0) {
165 size
= SUBTLV_SIZE(&(mtc
->av_delay
.header
));
166 memcpy(tlvs
, &(mtc
->av_delay
), size
);
170 /* TE_SUBTLV_MM_DELAY */
171 if (SUBTLV_TYPE(mtc
->mm_delay
) != 0) {
172 size
= SUBTLV_SIZE(&(mtc
->mm_delay
.header
));
173 memcpy(tlvs
, &(mtc
->mm_delay
), size
);
177 /* TE_SUBTLV_DELAY_VAR */
178 if (SUBTLV_TYPE(mtc
->delay_var
) != 0) {
179 size
= SUBTLV_SIZE(&(mtc
->delay_var
.header
));
180 memcpy(tlvs
, &(mtc
->delay_var
), size
);
184 /* TE_SUBTLV_PKT_LOSS */
185 if (SUBTLV_TYPE(mtc
->pkt_loss
) != 0) {
186 size
= SUBTLV_SIZE(&(mtc
->pkt_loss
.header
));
187 memcpy(tlvs
, &(mtc
->pkt_loss
), size
);
191 /* TE_SUBTLV_RES_BW */
192 if (SUBTLV_TYPE(mtc
->res_bw
) != 0) {
193 size
= SUBTLV_SIZE(&(mtc
->res_bw
.header
));
194 memcpy(tlvs
, &(mtc
->res_bw
), size
);
198 /* TE_SUBTLV_AVA_BW */
199 if (SUBTLV_TYPE(mtc
->ava_bw
) != 0) {
200 size
= SUBTLV_SIZE(&(mtc
->ava_bw
.header
));
201 memcpy(tlvs
, &(mtc
->ava_bw
), size
);
205 /* TE_SUBTLV_USE_BW */
206 if (SUBTLV_TYPE(mtc
->use_bw
) != 0) {
207 size
= SUBTLV_SIZE(&(mtc
->use_bw
.header
));
208 memcpy(tlvs
, &(mtc
->use_bw
), size
);
212 /* Add before this line any other parsing of TLV */
215 /* Update SubTLVs length */
216 mtc
->length
= subtlvs_len(mtc
);
218 zlog_debug("ISIS MPLS-TE: Add %d bytes length SubTLVs", mtc
->length
);
223 /* Compute total Sub-TLVs size */
224 uint8_t subtlvs_len(struct mpls_te_circuit
*mtc
)
232 /* TE_SUBTLV_ADMIN_GRP */
233 if (SUBTLV_TYPE(mtc
->admin_grp
) != 0)
234 length
+= SUBTLV_SIZE(&(mtc
->admin_grp
.header
));
237 if (SUBTLV_TYPE(mtc
->llri
) != 0)
238 length
+= SUBTLV_SIZE(&mtc
->llri
.header
);
240 /* TE_SUBTLV_LCLIF_IPADDR */
241 if (SUBTLV_TYPE(mtc
->local_ipaddr
) != 0)
242 length
+= SUBTLV_SIZE(&mtc
->local_ipaddr
.header
);
244 /* TE_SUBTLV_RMTIF_IPADDR */
245 if (SUBTLV_TYPE(mtc
->rmt_ipaddr
) != 0)
246 length
+= SUBTLV_SIZE(&mtc
->rmt_ipaddr
.header
);
248 /* TE_SUBTLV_MAX_BW */
249 if (SUBTLV_TYPE(mtc
->max_bw
) != 0)
250 length
+= SUBTLV_SIZE(&mtc
->max_bw
.header
);
252 /* TE_SUBTLV_MAX_RSV_BW */
253 if (SUBTLV_TYPE(mtc
->max_rsv_bw
) != 0)
254 length
+= SUBTLV_SIZE(&mtc
->max_rsv_bw
.header
);
256 /* TE_SUBTLV_UNRSV_BW */
257 if (SUBTLV_TYPE(mtc
->unrsv_bw
) != 0)
258 length
+= SUBTLV_SIZE(&mtc
->unrsv_bw
.header
);
260 /* TE_SUBTLV_TE_METRIC */
261 if (SUBTLV_TYPE(mtc
->te_metric
) != 0)
262 length
+= SUBTLV_SIZE(&mtc
->te_metric
.header
);
264 /* TE_SUBTLV_AV_DELAY */
265 if (SUBTLV_TYPE(mtc
->av_delay
) != 0)
266 length
+= SUBTLV_SIZE(&mtc
->av_delay
.header
);
268 /* TE_SUBTLV_MM_DELAY */
269 if (SUBTLV_TYPE(mtc
->mm_delay
) != 0)
270 length
+= SUBTLV_SIZE(&mtc
->mm_delay
.header
);
272 /* TE_SUBTLV_DELAY_VAR */
273 if (SUBTLV_TYPE(mtc
->delay_var
) != 0)
274 length
+= SUBTLV_SIZE(&mtc
->delay_var
.header
);
276 /* TE_SUBTLV_PKT_LOSS */
277 if (SUBTLV_TYPE(mtc
->pkt_loss
) != 0)
278 length
+= SUBTLV_SIZE(&mtc
->pkt_loss
.header
);
280 /* TE_SUBTLV_RES_BW */
281 if (SUBTLV_TYPE(mtc
->res_bw
) != 0)
282 length
+= SUBTLV_SIZE(&mtc
->res_bw
.header
);
284 /* TE_SUBTLV_AVA_BW */
285 if (SUBTLV_TYPE(mtc
->ava_bw
) != 0)
286 length
+= SUBTLV_SIZE(&mtc
->ava_bw
.header
);
288 /* TE_SUBTLV_USE_BW */
289 if (SUBTLV_TYPE(mtc
->use_bw
) != 0)
290 length
+= SUBTLV_SIZE(&mtc
->use_bw
.header
);
292 /* Check that length is lower than the MAXIMUM SUBTLV size i.e. 256 */
293 if (length
> MAX_SUBTLV_SIZE
) {
298 mtc
->length
= (uint8_t)length
;
303 /* Following are various functions to set MPLS TE parameters */
304 static void set_circuitparams_admin_grp(struct mpls_te_circuit
*mtc
,
307 SUBTLV_TYPE(mtc
->admin_grp
) = TE_SUBTLV_ADMIN_GRP
;
308 SUBTLV_LEN(mtc
->admin_grp
) = SUBTLV_DEF_SIZE
;
309 mtc
->admin_grp
.value
= htonl(admingrp
);
313 static void __attribute__((unused
))
314 set_circuitparams_llri(struct mpls_te_circuit
*mtc
, uint32_t local
,
317 SUBTLV_TYPE(mtc
->llri
) = TE_SUBTLV_LLRI
;
318 SUBTLV_LEN(mtc
->llri
) = TE_SUBTLV_LLRI_SIZE
;
319 mtc
->llri
.local
= htonl(local
);
320 mtc
->llri
.remote
= htonl(remote
);
323 void set_circuitparams_local_ipaddr(struct mpls_te_circuit
*mtc
,
327 SUBTLV_TYPE(mtc
->local_ipaddr
) = TE_SUBTLV_LOCAL_IPADDR
;
328 SUBTLV_LEN(mtc
->local_ipaddr
) = SUBTLV_DEF_SIZE
;
329 mtc
->local_ipaddr
.value
.s_addr
= addr
.s_addr
;
333 void set_circuitparams_rmt_ipaddr(struct mpls_te_circuit
*mtc
,
337 SUBTLV_TYPE(mtc
->rmt_ipaddr
) = TE_SUBTLV_RMT_IPADDR
;
338 SUBTLV_LEN(mtc
->rmt_ipaddr
) = SUBTLV_DEF_SIZE
;
339 mtc
->rmt_ipaddr
.value
.s_addr
= addr
.s_addr
;
343 static void set_circuitparams_max_bw(struct mpls_te_circuit
*mtc
, float fp
)
345 SUBTLV_TYPE(mtc
->max_bw
) = TE_SUBTLV_MAX_BW
;
346 SUBTLV_LEN(mtc
->max_bw
) = SUBTLV_DEF_SIZE
;
347 mtc
->max_bw
.value
= htonf(fp
);
351 static void set_circuitparams_max_rsv_bw(struct mpls_te_circuit
*mtc
, float fp
)
353 SUBTLV_TYPE(mtc
->max_rsv_bw
) = TE_SUBTLV_MAX_RSV_BW
;
354 SUBTLV_LEN(mtc
->max_rsv_bw
) = SUBTLV_DEF_SIZE
;
355 mtc
->max_rsv_bw
.value
= htonf(fp
);
359 static void set_circuitparams_unrsv_bw(struct mpls_te_circuit
*mtc
,
360 int priority
, float fp
)
362 /* Note that TLV-length field is the size of array. */
363 SUBTLV_TYPE(mtc
->unrsv_bw
) = TE_SUBTLV_UNRSV_BW
;
364 SUBTLV_LEN(mtc
->unrsv_bw
) = TE_SUBTLV_UNRSV_SIZE
;
365 mtc
->unrsv_bw
.value
[priority
] = htonf(fp
);
369 static void set_circuitparams_te_metric(struct mpls_te_circuit
*mtc
,
372 SUBTLV_TYPE(mtc
->te_metric
) = TE_SUBTLV_TE_METRIC
;
373 SUBTLV_LEN(mtc
->te_metric
) = TE_SUBTLV_TE_METRIC_SIZE
;
374 mtc
->te_metric
.value
[0] = (te_metric
>> 16) & 0xFF;
375 mtc
->te_metric
.value
[1] = (te_metric
>> 8) & 0xFF;
376 mtc
->te_metric
.value
[2] = te_metric
& 0xFF;
380 static void set_circuitparams_inter_as(struct mpls_te_circuit
*mtc
,
381 struct in_addr addr
, uint32_t as
)
384 /* Set the Remote ASBR IP address and then the associated AS number */
385 SUBTLV_TYPE(mtc
->rip
) = TE_SUBTLV_RIP
;
386 SUBTLV_LEN(mtc
->rip
) = SUBTLV_DEF_SIZE
;
387 mtc
->rip
.value
.s_addr
= addr
.s_addr
;
389 SUBTLV_TYPE(mtc
->ras
) = TE_SUBTLV_RAS
;
390 SUBTLV_LEN(mtc
->ras
) = SUBTLV_DEF_SIZE
;
391 mtc
->ras
.value
= htonl(as
);
394 static void unset_circuitparams_inter_as(struct mpls_te_circuit
*mtc
)
397 /* Reset the Remote ASBR IP address and then the associated AS number */
398 SUBTLV_TYPE(mtc
->rip
) = 0;
399 SUBTLV_LEN(mtc
->rip
) = 0;
400 mtc
->rip
.value
.s_addr
= 0;
402 SUBTLV_TYPE(mtc
->ras
) = 0;
403 SUBTLV_LEN(mtc
->ras
) = 0;
407 static void set_circuitparams_av_delay(struct mpls_te_circuit
*mtc
,
408 uint32_t delay
, uint8_t anormal
)
411 /* Note that TLV-length field is the size of array. */
412 SUBTLV_TYPE(mtc
->av_delay
) = TE_SUBTLV_AV_DELAY
;
413 SUBTLV_LEN(mtc
->av_delay
) = SUBTLV_DEF_SIZE
;
414 tmp
= delay
& TE_EXT_MASK
;
416 tmp
|= TE_EXT_ANORMAL
;
417 mtc
->av_delay
.value
= htonl(tmp
);
421 static void set_circuitparams_mm_delay(struct mpls_te_circuit
*mtc
,
422 uint32_t low
, uint32_t high
,
426 /* Note that TLV-length field is the size of array. */
427 SUBTLV_TYPE(mtc
->mm_delay
) = TE_SUBTLV_MM_DELAY
;
428 SUBTLV_LEN(mtc
->mm_delay
) = TE_SUBTLV_MM_DELAY_SIZE
;
429 tmp
= low
& TE_EXT_MASK
;
431 tmp
|= TE_EXT_ANORMAL
;
432 mtc
->mm_delay
.low
= htonl(tmp
);
433 mtc
->mm_delay
.high
= htonl(high
);
437 static void set_circuitparams_delay_var(struct mpls_te_circuit
*mtc
,
440 /* Note that TLV-length field is the size of array. */
441 SUBTLV_TYPE(mtc
->delay_var
) = TE_SUBTLV_DELAY_VAR
;
442 SUBTLV_LEN(mtc
->delay_var
) = SUBTLV_DEF_SIZE
;
443 mtc
->delay_var
.value
= htonl(jitter
& TE_EXT_MASK
);
447 static void set_circuitparams_pkt_loss(struct mpls_te_circuit
*mtc
,
448 uint32_t loss
, uint8_t anormal
)
451 /* Note that TLV-length field is the size of array. */
452 SUBTLV_TYPE(mtc
->pkt_loss
) = TE_SUBTLV_PKT_LOSS
;
453 SUBTLV_LEN(mtc
->pkt_loss
) = SUBTLV_DEF_SIZE
;
454 tmp
= loss
& TE_EXT_MASK
;
456 tmp
|= TE_EXT_ANORMAL
;
457 mtc
->pkt_loss
.value
= htonl(tmp
);
461 static void set_circuitparams_res_bw(struct mpls_te_circuit
*mtc
, float fp
)
463 /* Note that TLV-length field is the size of array. */
464 SUBTLV_TYPE(mtc
->res_bw
) = TE_SUBTLV_RES_BW
;
465 SUBTLV_LEN(mtc
->res_bw
) = SUBTLV_DEF_SIZE
;
466 mtc
->res_bw
.value
= htonf(fp
);
470 static void set_circuitparams_ava_bw(struct mpls_te_circuit
*mtc
, float fp
)
472 /* Note that TLV-length field is the size of array. */
473 SUBTLV_TYPE(mtc
->ava_bw
) = TE_SUBTLV_AVA_BW
;
474 SUBTLV_LEN(mtc
->ava_bw
) = SUBTLV_DEF_SIZE
;
475 mtc
->ava_bw
.value
= htonf(fp
);
479 static void set_circuitparams_use_bw(struct mpls_te_circuit
*mtc
, float fp
)
481 /* Note that TLV-length field is the size of array. */
482 SUBTLV_TYPE(mtc
->use_bw
) = TE_SUBTLV_USE_BW
;
483 SUBTLV_LEN(mtc
->use_bw
) = SUBTLV_DEF_SIZE
;
484 mtc
->use_bw
.value
= htonf(fp
);
488 /* Main initialization / update function of the MPLS TE Circuit context */
489 /* Call when interface TE Link parameters are modified */
490 void isis_link_params_update(struct isis_circuit
*circuit
,
491 struct interface
*ifp
)
494 struct prefix_ipv4
*addr
;
495 struct mpls_te_circuit
*mtc
;
498 if ((circuit
== NULL
) || (ifp
== NULL
))
501 zlog_info("MPLS-TE: Initialize circuit parameters for interface %s",
504 /* Check if MPLS TE Circuit context has not been already created */
505 if (circuit
->mtc
== NULL
)
506 circuit
->mtc
= mpls_te_circuit_new();
510 /* Fulfil MTC TLV from ifp TE Link parameters */
511 if (HAS_LINK_PARAMS(ifp
)) {
512 mtc
->status
= enable
;
514 if (IS_PARAM_SET(ifp
->link_params
, LP_ADM_GRP
))
515 set_circuitparams_admin_grp(
516 mtc
, ifp
->link_params
->admin_grp
);
518 SUBTLV_TYPE(mtc
->admin_grp
) = 0;
520 /* If not already set, register local IP addr from ip_addr list
522 if (SUBTLV_TYPE(mtc
->local_ipaddr
) == 0) {
523 if (circuit
->ip_addrs
!= NULL
524 && listcount(circuit
->ip_addrs
) != 0) {
525 addr
= (struct prefix_ipv4
*)listgetdata(
526 (struct listnode
*)listhead(
528 set_circuitparams_local_ipaddr(mtc
,
533 /* If not already set, try to determine Remote IP addr if
535 if ((SUBTLV_TYPE(mtc
->rmt_ipaddr
) == 0)
536 && (circuit
->circ_type
== CIRCUIT_T_P2P
)) {
537 struct isis_adjacency
*adj
= circuit
->u
.p2p
.neighbor
;
538 if (adj
&& adj
->adj_state
== ISIS_ADJ_UP
539 && adj
->ipv4_address_count
) {
540 set_circuitparams_rmt_ipaddr(
541 mtc
, adj
->ipv4_addresses
[0]);
545 if (IS_PARAM_SET(ifp
->link_params
, LP_MAX_BW
))
546 set_circuitparams_max_bw(mtc
, ifp
->link_params
->max_bw
);
548 SUBTLV_TYPE(mtc
->max_bw
) = 0;
550 if (IS_PARAM_SET(ifp
->link_params
, LP_MAX_RSV_BW
))
551 set_circuitparams_max_rsv_bw(
552 mtc
, ifp
->link_params
->max_rsv_bw
);
554 SUBTLV_TYPE(mtc
->max_rsv_bw
) = 0;
556 if (IS_PARAM_SET(ifp
->link_params
, LP_UNRSV_BW
))
557 for (i
= 0; i
< MAX_CLASS_TYPE
; i
++)
558 set_circuitparams_unrsv_bw(
559 mtc
, i
, ifp
->link_params
->unrsv_bw
[i
]);
561 SUBTLV_TYPE(mtc
->unrsv_bw
) = 0;
563 if (IS_PARAM_SET(ifp
->link_params
, LP_TE_METRIC
))
564 set_circuitparams_te_metric(
565 mtc
, ifp
->link_params
->te_metric
);
567 SUBTLV_TYPE(mtc
->te_metric
) = 0;
569 /* TE metric Extensions */
570 if (IS_PARAM_SET(ifp
->link_params
, LP_DELAY
))
571 set_circuitparams_av_delay(
572 mtc
, ifp
->link_params
->av_delay
, 0);
574 SUBTLV_TYPE(mtc
->av_delay
) = 0;
576 if (IS_PARAM_SET(ifp
->link_params
, LP_MM_DELAY
))
577 set_circuitparams_mm_delay(
578 mtc
, ifp
->link_params
->min_delay
,
579 ifp
->link_params
->max_delay
, 0);
581 SUBTLV_TYPE(mtc
->mm_delay
) = 0;
583 if (IS_PARAM_SET(ifp
->link_params
, LP_DELAY_VAR
))
584 set_circuitparams_delay_var(
585 mtc
, ifp
->link_params
->delay_var
);
587 SUBTLV_TYPE(mtc
->delay_var
) = 0;
589 if (IS_PARAM_SET(ifp
->link_params
, LP_PKT_LOSS
))
590 set_circuitparams_pkt_loss(
591 mtc
, ifp
->link_params
->pkt_loss
, 0);
593 SUBTLV_TYPE(mtc
->pkt_loss
) = 0;
595 if (IS_PARAM_SET(ifp
->link_params
, LP_RES_BW
))
596 set_circuitparams_res_bw(mtc
, ifp
->link_params
->res_bw
);
598 SUBTLV_TYPE(mtc
->res_bw
) = 0;
600 if (IS_PARAM_SET(ifp
->link_params
, LP_AVA_BW
))
601 set_circuitparams_ava_bw(mtc
, ifp
->link_params
->ava_bw
);
603 SUBTLV_TYPE(mtc
->ava_bw
) = 0;
605 if (IS_PARAM_SET(ifp
->link_params
, LP_USE_BW
))
606 set_circuitparams_use_bw(mtc
, ifp
->link_params
->use_bw
);
608 SUBTLV_TYPE(mtc
->use_bw
) = 0;
611 if (IS_PARAM_SET(ifp
->link_params
, LP_RMT_AS
))
612 set_circuitparams_inter_as(mtc
,
613 ifp
->link_params
->rmt_ip
,
614 ifp
->link_params
->rmt_as
);
616 /* reset inter-as TE params */
617 unset_circuitparams_inter_as(mtc
);
619 /* Compute total length of SUB TLVs */
620 mtc
->length
= subtlvs_len(mtc
);
623 mtc
->status
= disable
;
625 /* Finally Update LSP */
627 if (IS_MPLS_TE(isisMplsTE
) && circuit
->area
)
628 lsp_regenerate_schedule (circuit
->area
, circuit
->is_type
, 0);
633 void isis_mpls_te_update(struct interface
*ifp
)
635 struct isis_circuit
*circuit
;
641 /* Get circuit context from interface */
642 if ((circuit
= circuit_scan_by_ifp(ifp
)) == NULL
)
645 /* Update TE TLVs ... */
646 isis_link_params_update(circuit
, ifp
);
649 if (IS_MPLS_TE(isisMplsTE
) && circuit
->area
)
650 lsp_regenerate_schedule(circuit
->area
, circuit
->is_type
, 0);
655 /*------------------------------------------------------------------------*
656 * Followings are vty session control functions.
657 *------------------------------------------------------------------------*/
659 static uint8_t print_subtlv_admin_grp(struct sbuf
*buf
, int indent
,
660 struct te_subtlv_admin_grp
*tlv
)
662 sbuf_push(buf
, indent
, "Administrative Group: 0x%" PRIx32
"\n",
664 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
667 static uint8_t print_subtlv_llri(struct sbuf
*buf
, int indent
,
668 struct te_subtlv_llri
*tlv
)
670 sbuf_push(buf
, indent
, "Link Local ID: %" PRIu32
"\n",
672 sbuf_push(buf
, indent
, "Link Remote ID: %" PRIu32
"\n",
675 return (SUBTLV_HDR_SIZE
+ TE_SUBTLV_LLRI_SIZE
);
678 static uint8_t print_subtlv_local_ipaddr(struct sbuf
*buf
, int indent
,
679 struct te_subtlv_local_ipaddr
*tlv
)
681 sbuf_push(buf
, indent
, "Local Interface IP Address(es): %s\n",
682 inet_ntoa(tlv
->value
));
684 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
687 static uint8_t print_subtlv_rmt_ipaddr(struct sbuf
*buf
, int indent
,
688 struct te_subtlv_rmt_ipaddr
*tlv
)
690 sbuf_push(buf
, indent
, "Remote Interface IP Address(es): %s\n",
691 inet_ntoa(tlv
->value
));
693 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
696 static uint8_t print_subtlv_max_bw(struct sbuf
*buf
, int indent
,
697 struct te_subtlv_max_bw
*tlv
)
701 fval
= ntohf(tlv
->value
);
703 sbuf_push(buf
, indent
, "Maximum Bandwidth: %g (Bytes/sec)\n", fval
);
705 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
708 static uint8_t print_subtlv_max_rsv_bw(struct sbuf
*buf
, int indent
,
709 struct te_subtlv_max_rsv_bw
*tlv
)
713 fval
= ntohf(tlv
->value
);
715 sbuf_push(buf
, indent
, "Maximum Reservable Bandwidth: %g (Bytes/sec)\n",
718 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
721 static uint8_t print_subtlv_unrsv_bw(struct sbuf
*buf
, int indent
,
722 struct te_subtlv_unrsv_bw
*tlv
)
727 sbuf_push(buf
, indent
, "Unreserved Bandwidth:\n");
729 for (i
= 0; i
< MAX_CLASS_TYPE
; i
+= 2) {
730 fval1
= ntohf(tlv
->value
[i
]);
731 fval2
= ntohf(tlv
->value
[i
+ 1]);
732 sbuf_push(buf
, indent
+ 2,
733 "[%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n", i
,
734 fval1
, i
+ 1, fval2
);
737 return (SUBTLV_HDR_SIZE
+ TE_SUBTLV_UNRSV_SIZE
);
740 static uint8_t print_subtlv_te_metric(struct sbuf
*buf
, int indent
,
741 struct te_subtlv_te_metric
*tlv
)
745 te_metric
= tlv
->value
[2] | tlv
->value
[1] << 8 | tlv
->value
[0] << 16;
746 sbuf_push(buf
, indent
, "Traffic Engineering Metric: %u\n", te_metric
);
748 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
751 static uint8_t print_subtlv_ras(struct sbuf
*buf
, int indent
,
752 struct te_subtlv_ras
*tlv
)
754 sbuf_push(buf
, indent
, "Inter-AS TE Remote AS number: %" PRIu32
"\n",
757 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
760 static uint8_t print_subtlv_rip(struct sbuf
*buf
, int indent
,
761 struct te_subtlv_rip
*tlv
)
763 sbuf_push(buf
, indent
, "Inter-AS TE Remote ASBR IP address: %s\n",
764 inet_ntoa(tlv
->value
));
766 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
769 static uint8_t print_subtlv_av_delay(struct sbuf
*buf
, int indent
,
770 struct te_subtlv_av_delay
*tlv
)
775 delay
= (uint32_t)ntohl(tlv
->value
) & TE_EXT_MASK
;
776 A
= (uint32_t)ntohl(tlv
->value
) & TE_EXT_ANORMAL
;
778 sbuf_push(buf
, indent
,
779 "%s Average Link Delay: %" PRIu32
" (micro-sec)\n",
780 A
? "Anomalous" : "Normal", delay
);
782 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
785 static uint8_t print_subtlv_mm_delay(struct sbuf
*buf
, int indent
,
786 struct te_subtlv_mm_delay
*tlv
)
791 low
= (uint32_t)ntohl(tlv
->low
) & TE_EXT_MASK
;
792 A
= (uint32_t)ntohl(tlv
->low
) & TE_EXT_ANORMAL
;
793 high
= (uint32_t)ntohl(tlv
->high
) & TE_EXT_MASK
;
795 sbuf_push(buf
, indent
, "%s Min/Max Link Delay: %" PRIu32
" / %" PRIu32
" (micro-sec)\n",
796 A
? "Anomalous" : "Normal", low
, high
);
798 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
801 static uint8_t print_subtlv_delay_var(struct sbuf
*buf
, int indent
,
802 struct te_subtlv_delay_var
*tlv
)
806 jitter
= (uint32_t)ntohl(tlv
->value
) & TE_EXT_MASK
;
808 sbuf_push(buf
, indent
, "Delay Variation: %" PRIu32
" (micro-sec)\n",
811 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
814 static uint8_t print_subtlv_pkt_loss(struct sbuf
*buf
, int indent
,
815 struct te_subtlv_pkt_loss
*tlv
)
821 loss
= (uint32_t)ntohl(tlv
->value
) & TE_EXT_MASK
;
822 fval
= (float)(loss
* LOSS_PRECISION
);
823 A
= (uint32_t)ntohl(tlv
->value
) & TE_EXT_ANORMAL
;
825 sbuf_push(buf
, indent
, "%s Link Packet Loss: %g (%%)\n",
826 A
? "Anomalous" : "Normal", fval
);
828 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
831 static uint8_t print_subtlv_res_bw(struct sbuf
*buf
, int indent
,
832 struct te_subtlv_res_bw
*tlv
)
836 fval
= ntohf(tlv
->value
);
838 sbuf_push(buf
, indent
,
839 "Unidirectional Residual Bandwidth: %g (Bytes/sec)\n", fval
);
841 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
844 static uint8_t print_subtlv_ava_bw(struct sbuf
*buf
, int indent
,
845 struct te_subtlv_ava_bw
*tlv
)
849 fval
= ntohf(tlv
->value
);
851 sbuf_push(buf
, indent
,
852 "Unidirectional Available Bandwidth: %g (Bytes/sec)\n", fval
);
854 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
857 static uint8_t print_subtlv_use_bw(struct sbuf
*buf
, int indent
,
858 struct te_subtlv_use_bw
*tlv
)
862 fval
= ntohf(tlv
->value
);
864 sbuf_push(buf
, indent
,
865 "Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n", fval
);
867 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
870 static uint8_t print_unknown_tlv(struct sbuf
*buf
, int indent
,
871 struct subtlv_header
*tlvh
)
874 uint8_t *v
= (uint8_t *)tlvh
;
876 if (tlvh
->length
!= 0) {
877 sbuf_push(buf
, indent
,
878 "Unknown TLV: [type(%#.2x), length(%#.2x)]\n",
879 tlvh
->type
, tlvh
->length
);
880 sbuf_push(buf
, indent
+ 2, "Dump: [00]");
881 rtn
= 1; /* initialize end of line counter */
882 for (i
= 0; i
< tlvh
->length
; i
++) {
883 sbuf_push(buf
, 0, " %#.2x", v
[i
]);
885 sbuf_push(buf
, 0, "\n");
886 sbuf_push(buf
, indent
+ 8, "[%.2x]", i
+ 1);
891 sbuf_push(buf
, 0, "\n");
893 sbuf_push(buf
, indent
,
894 "Unknown TLV: [type(%#.2x), length(%#.2x)]\n",
895 tlvh
->type
, tlvh
->length
);
898 return SUBTLV_SIZE(tlvh
);
901 /* Main Show function */
902 void mpls_te_print_detail(struct sbuf
*buf
, int indent
,
903 uint8_t *subtlvs
, uint8_t subtlv_len
)
905 struct subtlv_header
*tlvh
= (struct subtlv_header
*)subtlvs
;
908 for (; sum
< subtlv_len
;
909 tlvh
= (struct subtlv_header
*)(subtlvs
+ sum
)) {
910 if (subtlv_len
- sum
< SUBTLV_SIZE(tlvh
)) {
911 sbuf_push(buf
, indent
, "Available data %" PRIu8
" is less than TLV size %u!\n",
912 subtlv_len
- sum
, SUBTLV_SIZE(tlvh
));
916 switch (tlvh
->type
) {
917 case TE_SUBTLV_ADMIN_GRP
:
918 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
919 sbuf_push(buf
, indent
, "TLV size does not match expected size for Administrative Group!\n");
922 sum
+= print_subtlv_admin_grp(buf
, indent
,
923 (struct te_subtlv_admin_grp
*)tlvh
);
926 if (tlvh
->length
!= TE_SUBTLV_LLRI_SIZE
) {
927 sbuf_push(buf
, indent
, "TLV size does not match expected size for Link ID!\n");
930 sum
+= print_subtlv_llri(buf
, indent
,
931 (struct te_subtlv_llri
*)tlvh
);
933 case TE_SUBTLV_LOCAL_IPADDR
:
934 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
935 sbuf_push(buf
, indent
, "TLV size does not match expected size for Local IP address!\n");
938 sum
+= print_subtlv_local_ipaddr(buf
, indent
,
939 (struct te_subtlv_local_ipaddr
*)tlvh
);
941 case TE_SUBTLV_RMT_IPADDR
:
942 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
943 sbuf_push(buf
, indent
, "TLV size does not match expected size for Remote Interface address!\n");
946 sum
+= print_subtlv_rmt_ipaddr(buf
, indent
,
947 (struct te_subtlv_rmt_ipaddr
*)tlvh
);
949 case TE_SUBTLV_MAX_BW
:
950 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
951 sbuf_push(buf
, indent
, "TLV size does not match expected size for Maximum Bandwidth!\n");
954 sum
+= print_subtlv_max_bw(buf
, indent
,
955 (struct te_subtlv_max_bw
*)tlvh
);
957 case TE_SUBTLV_MAX_RSV_BW
:
958 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
959 sbuf_push(buf
, indent
, "TLV size does not match expected size for Maximum Reservable Bandwidth!\n");
962 sum
+= print_subtlv_max_rsv_bw(buf
, indent
,
963 (struct te_subtlv_max_rsv_bw
*)tlvh
);
965 case TE_SUBTLV_UNRSV_BW
:
966 if (tlvh
->length
!= TE_SUBTLV_UNRSV_SIZE
) {
967 sbuf_push(buf
, indent
, "TLV size does not match expected size for Unreserved Bandwidth!\n");
970 sum
+= print_subtlv_unrsv_bw(buf
, indent
,
971 (struct te_subtlv_unrsv_bw
*)tlvh
);
973 case TE_SUBTLV_TE_METRIC
:
974 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
975 sbuf_push(buf
, indent
, "TLV size does not match expected size for Traffic Engineering Metric!\n");
978 sum
+= print_subtlv_te_metric(buf
, indent
,
979 (struct te_subtlv_te_metric
*)tlvh
);
982 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
983 sbuf_push(buf
, indent
, "TLV size does not match expected size for Remote AS number!\n");
986 sum
+= print_subtlv_ras(buf
, indent
,
987 (struct te_subtlv_ras
*)tlvh
);
990 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
991 sbuf_push(buf
, indent
, "TLV size does not match expected size for Remote ASBR IP Address!\n");
994 sum
+= print_subtlv_rip(buf
, indent
,
995 (struct te_subtlv_rip
*)tlvh
);
997 case TE_SUBTLV_AV_DELAY
:
998 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
999 sbuf_push(buf
, indent
, "TLV size does not match expected size for Average Link Delay!\n");
1002 sum
+= print_subtlv_av_delay(buf
, indent
,
1003 (struct te_subtlv_av_delay
*)tlvh
);
1005 case TE_SUBTLV_MM_DELAY
:
1006 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1007 sbuf_push(buf
, indent
, "TLV size does not match expected size for Min/Max Link Delay!\n");
1010 sum
+= print_subtlv_mm_delay(buf
, indent
,
1011 (struct te_subtlv_mm_delay
*)tlvh
);
1013 case TE_SUBTLV_DELAY_VAR
:
1014 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1015 sbuf_push(buf
, indent
, "TLV size does not match expected size for Delay Variation!\n");
1018 sum
+= print_subtlv_delay_var(buf
, indent
,
1019 (struct te_subtlv_delay_var
*)tlvh
);
1021 case TE_SUBTLV_PKT_LOSS
:
1022 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1023 sbuf_push(buf
, indent
, "TLV size does not match expected size for Link Packet Loss!\n");
1026 sum
+= print_subtlv_pkt_loss(buf
, indent
,
1027 (struct te_subtlv_pkt_loss
*)tlvh
);
1029 case TE_SUBTLV_RES_BW
:
1030 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1031 sbuf_push(buf
, indent
, "TLV size does not match expected size for Unidirectional Residual Bandwidth!\n");
1034 sum
+= print_subtlv_res_bw(buf
, indent
,
1035 (struct te_subtlv_res_bw
*)tlvh
);
1037 case TE_SUBTLV_AVA_BW
:
1038 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1039 sbuf_push(buf
, indent
, "TLV size does not match expected size for Unidirectional Available Bandwidth!\n");
1042 sum
+= print_subtlv_ava_bw(buf
, indent
,
1043 (struct te_subtlv_ava_bw
*)tlvh
);
1045 case TE_SUBTLV_USE_BW
:
1046 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1047 sbuf_push(buf
, indent
, "TLV size does not match expected size for Unidirectional Utilized Bandwidth!\n");
1050 sum
+= print_subtlv_use_bw(buf
, indent
,
1051 (struct te_subtlv_use_bw
*)tlvh
);
1054 sum
+= print_unknown_tlv(buf
, indent
, tlvh
);
1061 /* Specific MPLS TE router parameters write function */
1062 void isis_mpls_te_config_write_router(struct vty
*vty
)
1064 if (IS_MPLS_TE(isisMplsTE
)) {
1065 vty_out(vty
, " mpls-te on\n");
1066 vty_out(vty
, " mpls-te router-address %s\n",
1067 inet_ntoa(isisMplsTE
.router_id
));
1074 /*------------------------------------------------------------------------*
1075 * Followings are vty command functions.
1076 *------------------------------------------------------------------------*/
1079 /* Search MPLS TE Circuit context from Interface */
1080 static struct mpls_te_circuit
*lookup_mpls_params_by_ifp(struct interface
*ifp
)
1082 struct isis_circuit
*circuit
;
1084 if ((circuit
= circuit_scan_by_ifp(ifp
)) == NULL
)
1087 return circuit
->mtc
;
1090 DEFUN (show_isis_mpls_te_router
,
1091 show_isis_mpls_te_router_cmd
,
1092 "show " PROTO_NAME
" mpls-te router",
1096 "Router information\n")
1098 if (IS_MPLS_TE(isisMplsTE
)) {
1099 vty_out(vty
, "--- MPLS-TE router parameters ---\n");
1101 if (ntohs(isisMplsTE
.router_id
.s_addr
) != 0)
1102 vty_out(vty
, " Router-Address: %s\n",
1103 inet_ntoa(isisMplsTE
.router_id
));
1105 vty_out(vty
, " N/A\n");
1107 vty_out(vty
, " MPLS-TE is disable on this router\n");
1112 static void show_mpls_te_sub(struct vty
*vty
, struct interface
*ifp
)
1114 struct mpls_te_circuit
*mtc
;
1117 sbuf_init(&buf
, NULL
, 0);
1119 if ((IS_MPLS_TE(isisMplsTE
))
1120 && ((mtc
= lookup_mpls_params_by_ifp(ifp
)) != NULL
)) {
1121 /* Continue only if interface is not passive or support Inter-AS
1123 if (mtc
->status
!= enable
) {
1124 if (IS_INTER_AS(mtc
->type
)) {
1126 "-- Inter-AS TEv2 link parameters for %s --\n",
1129 /* MPLS-TE is not activate on this interface */
1130 /* or this interface is passive and Inter-AS
1131 * TEv2 is not activate */
1133 " %s: MPLS-TE is disabled on this interface\n",
1138 vty_out(vty
, "-- MPLS-TE link parameters for %s --\n",
1143 print_subtlv_admin_grp(&buf
, 4, &mtc
->admin_grp
);
1145 if (SUBTLV_TYPE(mtc
->local_ipaddr
) != 0)
1146 print_subtlv_local_ipaddr(&buf
, 4, &mtc
->local_ipaddr
);
1147 if (SUBTLV_TYPE(mtc
->rmt_ipaddr
) != 0)
1148 print_subtlv_rmt_ipaddr(&buf
, 4, &mtc
->rmt_ipaddr
);
1150 print_subtlv_max_bw(&buf
, 4, &mtc
->max_bw
);
1151 print_subtlv_max_rsv_bw(&buf
, 4, &mtc
->max_rsv_bw
);
1152 print_subtlv_unrsv_bw(&buf
, 4, &mtc
->unrsv_bw
);
1153 print_subtlv_te_metric(&buf
, 4, &mtc
->te_metric
);
1155 if (IS_INTER_AS(mtc
->type
)) {
1156 if (SUBTLV_TYPE(mtc
->ras
) != 0)
1157 print_subtlv_ras(&buf
, 4, &mtc
->ras
);
1158 if (SUBTLV_TYPE(mtc
->rip
) != 0)
1159 print_subtlv_rip(&buf
, 4, &mtc
->rip
);
1162 print_subtlv_av_delay(&buf
, 4, &mtc
->av_delay
);
1163 print_subtlv_mm_delay(&buf
, 4, &mtc
->mm_delay
);
1164 print_subtlv_delay_var(&buf
, 4, &mtc
->delay_var
);
1165 print_subtlv_pkt_loss(&buf
, 4, &mtc
->pkt_loss
);
1166 print_subtlv_res_bw(&buf
, 4, &mtc
->res_bw
);
1167 print_subtlv_ava_bw(&buf
, 4, &mtc
->ava_bw
);
1168 print_subtlv_use_bw(&buf
, 4, &mtc
->use_bw
);
1170 vty_multiline(vty
, "", "%s", sbuf_buf(&buf
));
1171 vty_out(vty
, "---------------\n\n");
1173 vty_out(vty
, " %s: MPLS-TE is disabled on this interface\n",
1181 DEFUN (show_isis_mpls_te_interface
,
1182 show_isis_mpls_te_interface_cmd
,
1183 "show " PROTO_NAME
" mpls-te interface [INTERFACE]",
1187 "Interface information\n"
1190 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
1191 int idx_interface
= 4;
1192 struct interface
*ifp
;
1194 /* Show All Interfaces. */
1196 FOR_ALL_INTERFACES (vrf
, ifp
)
1197 show_mpls_te_sub(vty
, ifp
);
1199 /* Interface name is specified. */
1201 if ((ifp
= if_lookup_by_name(argv
[idx_interface
]->arg
,
1204 vty_out(vty
, "No such interface name\n");
1206 show_mpls_te_sub(vty
, ifp
);
1213 /* Initialize MPLS_TE */
1214 void isis_mpls_te_init(void)
1217 zlog_debug("ISIS MPLS-TE: Initialize");
1219 /* Initialize MPLS_TE structure */
1220 isisMplsTE
.status
= disable
;
1221 isisMplsTE
.level
= 0;
1222 isisMplsTE
.inter_as
= off
;
1223 isisMplsTE
.interas_areaid
.s_addr
= 0;
1224 isisMplsTE
.cir_list
= list_new();
1225 isisMplsTE
.router_id
.s_addr
= 0;
1228 /* Register new VTY commands */
1229 install_element(VIEW_NODE
, &show_isis_mpls_te_router_cmd
);
1230 install_element(VIEW_NODE
, &show_isis_mpls_te_interface_cmd
);