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
));
93 mtc
->status
= disable
;
100 /* Copy SUB TLVs parameters into a buffer - No space verification are performed
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
)
105 uint8_t size
, *tlvs
= buf
;
107 zlog_debug("ISIS MPLS-TE: Add TE Sub TLVs to buffer");
111 "ISIS MPLS-TE: Abort! No MPLS TE Circuit available has been specified");
115 /* Create buffer if not provided */
117 zlog_debug("ISIS MPLS-TE: Abort! No Buffer has been specified");
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
);
129 if (SUBTLV_TYPE(mtc
->llri
) != 0) {
130 size
= SUBTLV_SIZE(&(mtc
->llri
.header
));
131 memcpy(tlvs
, &(mtc
->llri
), size
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
226 /* Add before this line any other parsing of TLV */
229 /* Update SubTLVs length */
230 mtc
->length
= subtlvs_len(mtc
);
232 zlog_debug("ISIS MPLS-TE: Add %d bytes length SubTLVs", mtc
->length
);
237 /* Compute total Sub-TLVs size */
238 uint8_t subtlvs_len(struct mpls_te_circuit
*mtc
)
246 /* TE_SUBTLV_ADMIN_GRP */
247 if (SUBTLV_TYPE(mtc
->admin_grp
) != 0)
248 length
+= SUBTLV_SIZE(&(mtc
->admin_grp
.header
));
251 if (SUBTLV_TYPE(mtc
->llri
) != 0)
252 length
+= SUBTLV_SIZE(&mtc
->llri
.header
);
254 /* TE_SUBTLV_LCLIF_IPADDR */
255 if (SUBTLV_TYPE(mtc
->local_ipaddr
) != 0)
256 length
+= SUBTLV_SIZE(&mtc
->local_ipaddr
.header
);
258 /* TE_SUBTLV_RMTIF_IPADDR */
259 if (SUBTLV_TYPE(mtc
->rmt_ipaddr
) != 0)
260 length
+= SUBTLV_SIZE(&mtc
->rmt_ipaddr
.header
);
262 /* TE_SUBTLV_MAX_BW */
263 if (SUBTLV_TYPE(mtc
->max_bw
) != 0)
264 length
+= SUBTLV_SIZE(&mtc
->max_bw
.header
);
266 /* TE_SUBTLV_MAX_RSV_BW */
267 if (SUBTLV_TYPE(mtc
->max_rsv_bw
) != 0)
268 length
+= SUBTLV_SIZE(&mtc
->max_rsv_bw
.header
);
270 /* TE_SUBTLV_UNRSV_BW */
271 if (SUBTLV_TYPE(mtc
->unrsv_bw
) != 0)
272 length
+= SUBTLV_SIZE(&mtc
->unrsv_bw
.header
);
274 /* TE_SUBTLV_TE_METRIC */
275 if (SUBTLV_TYPE(mtc
->te_metric
) != 0)
276 length
+= SUBTLV_SIZE(&mtc
->te_metric
.header
);
278 /* TE_SUBTLV_AV_DELAY */
279 if (SUBTLV_TYPE(mtc
->av_delay
) != 0)
280 length
+= SUBTLV_SIZE(&mtc
->av_delay
.header
);
282 /* TE_SUBTLV_MM_DELAY */
283 if (SUBTLV_TYPE(mtc
->mm_delay
) != 0)
284 length
+= SUBTLV_SIZE(&mtc
->mm_delay
.header
);
286 /* TE_SUBTLV_DELAY_VAR */
287 if (SUBTLV_TYPE(mtc
->delay_var
) != 0)
288 length
+= SUBTLV_SIZE(&mtc
->delay_var
.header
);
290 /* TE_SUBTLV_PKT_LOSS */
291 if (SUBTLV_TYPE(mtc
->pkt_loss
) != 0)
292 length
+= SUBTLV_SIZE(&mtc
->pkt_loss
.header
);
294 /* TE_SUBTLV_RES_BW */
295 if (SUBTLV_TYPE(mtc
->res_bw
) != 0)
296 length
+= SUBTLV_SIZE(&mtc
->res_bw
.header
);
298 /* TE_SUBTLV_AVA_BW */
299 if (SUBTLV_TYPE(mtc
->ava_bw
) != 0)
300 length
+= SUBTLV_SIZE(&mtc
->ava_bw
.header
);
302 /* TE_SUBTLV_USE_BW */
303 if (SUBTLV_TYPE(mtc
->use_bw
) != 0)
304 length
+= SUBTLV_SIZE(&mtc
->use_bw
.header
);
306 /* Check that length is lower than the MAXIMUM SUBTLV size i.e. 256 */
307 if (length
> MAX_SUBTLV_SIZE
) {
312 mtc
->length
= (uint8_t)length
;
317 /* Following are various functions to set MPLS TE parameters */
318 static void set_circuitparams_admin_grp(struct mpls_te_circuit
*mtc
,
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
);
327 static void __attribute__((unused
))
328 set_circuitparams_llri(struct mpls_te_circuit
*mtc
, u_int32_t local
,
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
);
337 void set_circuitparams_local_ipaddr(struct mpls_te_circuit
*mtc
,
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
;
347 void set_circuitparams_rmt_ipaddr(struct mpls_te_circuit
*mtc
,
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
;
357 static void set_circuitparams_max_bw(struct mpls_te_circuit
*mtc
, float fp
)
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
);
365 static void set_circuitparams_max_rsv_bw(struct mpls_te_circuit
*mtc
, float fp
)
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
);
373 static void set_circuitparams_unrsv_bw(struct mpls_te_circuit
*mtc
,
374 int priority
, float fp
)
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
);
383 static void set_circuitparams_te_metric(struct mpls_te_circuit
*mtc
,
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;
394 static void set_circuitparams_inter_as(struct mpls_te_circuit
*mtc
,
395 struct in_addr addr
, u_int32_t as
)
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
;
403 SUBTLV_TYPE(mtc
->ras
) = TE_SUBTLV_RAS
;
404 SUBTLV_LEN(mtc
->ras
) = SUBTLV_DEF_SIZE
;
405 mtc
->ras
.value
= htonl(as
);
408 static void unset_circuitparams_inter_as(struct mpls_te_circuit
*mtc
)
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;
416 SUBTLV_TYPE(mtc
->ras
) = 0;
417 SUBTLV_LEN(mtc
->ras
) = 0;
421 static void set_circuitparams_av_delay(struct mpls_te_circuit
*mtc
,
422 u_int32_t delay
, u_char anormal
)
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
;
430 tmp
|= TE_EXT_ANORMAL
;
431 mtc
->av_delay
.value
= htonl(tmp
);
435 static void set_circuitparams_mm_delay(struct mpls_te_circuit
*mtc
,
436 u_int32_t low
, u_int32_t high
,
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
;
445 tmp
|= TE_EXT_ANORMAL
;
446 mtc
->mm_delay
.low
= htonl(tmp
);
447 mtc
->mm_delay
.high
= htonl(high
);
451 static void set_circuitparams_delay_var(struct mpls_te_circuit
*mtc
,
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
);
461 static void set_circuitparams_pkt_loss(struct mpls_te_circuit
*mtc
,
462 u_int32_t loss
, u_char anormal
)
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
;
470 tmp
|= TE_EXT_ANORMAL
;
471 mtc
->pkt_loss
.value
= htonl(tmp
);
475 static void set_circuitparams_res_bw(struct mpls_te_circuit
*mtc
, float fp
)
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
);
484 static void set_circuitparams_ava_bw(struct mpls_te_circuit
*mtc
, float fp
)
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
);
493 static void set_circuitparams_use_bw(struct mpls_te_circuit
*mtc
, float fp
)
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
);
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
)
508 struct prefix_ipv4
*addr
;
509 struct mpls_te_circuit
*mtc
;
512 if ((circuit
== NULL
) || (ifp
== NULL
))
515 zlog_info("MPLS-TE: Initialize circuit parameters for interface %s",
518 /* Check if MPLS TE Circuit context has not been already created */
519 if (circuit
->mtc
== NULL
)
520 circuit
->mtc
= mpls_te_circuit_new();
524 /* Fulfil MTC TLV from ifp TE Link parameters */
525 if (HAS_LINK_PARAMS(ifp
)) {
526 mtc
->status
= enable
;
528 if (IS_PARAM_SET(ifp
->link_params
, LP_ADM_GRP
))
529 set_circuitparams_admin_grp(
530 mtc
, ifp
->link_params
->admin_grp
);
532 SUBTLV_TYPE(mtc
->admin_grp
) = 0;
534 /* If not already set, register local IP addr from ip_addr list
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(
542 set_circuitparams_local_ipaddr(mtc
,
547 /* If not already set, try to determine Remote IP addr if
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]);
558 if (IS_PARAM_SET(ifp
->link_params
, LP_MAX_BW
))
559 set_circuitparams_max_bw(mtc
, ifp
->link_params
->max_bw
);
561 SUBTLV_TYPE(mtc
->max_bw
) = 0;
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
);
567 SUBTLV_TYPE(mtc
->max_rsv_bw
) = 0;
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
]);
574 SUBTLV_TYPE(mtc
->unrsv_bw
) = 0;
576 if (IS_PARAM_SET(ifp
->link_params
, LP_TE_METRIC
))
577 set_circuitparams_te_metric(
578 mtc
, ifp
->link_params
->te_metric
);
580 SUBTLV_TYPE(mtc
->te_metric
) = 0;
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);
587 SUBTLV_TYPE(mtc
->av_delay
) = 0;
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);
594 SUBTLV_TYPE(mtc
->mm_delay
) = 0;
596 if (IS_PARAM_SET(ifp
->link_params
, LP_DELAY_VAR
))
597 set_circuitparams_delay_var(
598 mtc
, ifp
->link_params
->delay_var
);
600 SUBTLV_TYPE(mtc
->delay_var
) = 0;
602 if (IS_PARAM_SET(ifp
->link_params
, LP_PKT_LOSS
))
603 set_circuitparams_pkt_loss(
604 mtc
, ifp
->link_params
->pkt_loss
, 0);
606 SUBTLV_TYPE(mtc
->pkt_loss
) = 0;
608 if (IS_PARAM_SET(ifp
->link_params
, LP_RES_BW
))
609 set_circuitparams_res_bw(mtc
, ifp
->link_params
->res_bw
);
611 SUBTLV_TYPE(mtc
->res_bw
) = 0;
613 if (IS_PARAM_SET(ifp
->link_params
, LP_AVA_BW
))
614 set_circuitparams_ava_bw(mtc
, ifp
->link_params
->ava_bw
);
616 SUBTLV_TYPE(mtc
->ava_bw
) = 0;
618 if (IS_PARAM_SET(ifp
->link_params
, LP_USE_BW
))
619 set_circuitparams_use_bw(mtc
, ifp
->link_params
->use_bw
);
621 SUBTLV_TYPE(mtc
->use_bw
) = 0;
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
);
629 /* reset inter-as TE params */
630 unset_circuitparams_inter_as(mtc
);
632 /* Compute total length of SUB TLVs */
633 mtc
->length
= subtlvs_len(mtc
);
636 mtc
->status
= disable
;
638 /* Finally Update LSP */
640 if (IS_MPLS_TE(isisMplsTE
) && circuit
->area
)
641 lsp_regenerate_schedule (circuit
->area
, circuit
->is_type
, 0);
646 void isis_mpls_te_update(struct interface
*ifp
)
648 struct isis_circuit
*circuit
;
654 /* Get circuit context from interface */
655 if ((circuit
= circuit_scan_by_ifp(ifp
)) == NULL
)
658 /* Update TE TLVs ... */
659 isis_link_params_update(circuit
, ifp
);
662 if (IS_MPLS_TE(isisMplsTE
) && circuit
->area
)
663 lsp_regenerate_schedule(circuit
->area
, circuit
->is_type
, 0);
668 /*------------------------------------------------------------------------*
669 * Followings are vty session control functions.
670 *------------------------------------------------------------------------*/
672 static u_char
print_subtlv_admin_grp(struct sbuf
*buf
, int indent
,
673 struct te_subtlv_admin_grp
*tlv
)
675 sbuf_push(buf
, indent
, "Administrative Group: 0x%" PRIx32
"\n",
677 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
680 static u_char
print_subtlv_llri(struct sbuf
*buf
, int indent
,
681 struct te_subtlv_llri
*tlv
)
683 sbuf_push(buf
, indent
, "Link Local ID: %" PRIu32
"\n",
685 sbuf_push(buf
, indent
, "Link Remote ID: %" PRIu32
"\n",
688 return (SUBTLV_HDR_SIZE
+ TE_SUBTLV_LLRI_SIZE
);
691 static u_char
print_subtlv_local_ipaddr(struct sbuf
*buf
, int indent
,
692 struct te_subtlv_local_ipaddr
*tlv
)
694 sbuf_push(buf
, indent
, "Local Interface IP Address(es): %s\n",
695 inet_ntoa(tlv
->value
));
697 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
700 static u_char
print_subtlv_rmt_ipaddr(struct sbuf
*buf
, int indent
,
701 struct te_subtlv_rmt_ipaddr
*tlv
)
703 sbuf_push(buf
, indent
, "Remote Interface IP Address(es): %s\n",
704 inet_ntoa(tlv
->value
));
706 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
709 static u_char
print_subtlv_max_bw(struct sbuf
*buf
, int indent
,
710 struct te_subtlv_max_bw
*tlv
)
714 fval
= ntohf(tlv
->value
);
716 sbuf_push(buf
, indent
, "Maximum Bandwidth: %g (Bytes/sec)\n", fval
);
718 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
721 static u_char
print_subtlv_max_rsv_bw(struct sbuf
*buf
, int indent
,
722 struct te_subtlv_max_rsv_bw
*tlv
)
726 fval
= ntohf(tlv
->value
);
728 sbuf_push(buf
, indent
, "Maximum Reservable Bandwidth: %g (Bytes/sec)\n", fval
);
730 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
733 static u_char
print_subtlv_unrsv_bw(struct sbuf
*buf
, int indent
,
734 struct te_subtlv_unrsv_bw
*tlv
)
739 sbuf_push(buf
, indent
, "Unreserved Bandwidth:\n");
741 for (i
= 0; i
< MAX_CLASS_TYPE
; i
+= 2) {
742 fval1
= ntohf(tlv
->value
[i
]);
743 fval2
= ntohf(tlv
->value
[i
+ 1]);
744 sbuf_push(buf
, indent
+ 2, "[%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n",
745 i
, fval1
, i
+ 1, fval2
);
748 return (SUBTLV_HDR_SIZE
+ TE_SUBTLV_UNRSV_SIZE
);
751 static u_char
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 u_char
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 u_char
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 u_char
print_subtlv_av_delay(struct sbuf
*buf
, int indent
,
781 struct te_subtlv_av_delay
*tlv
)
786 delay
= (u_int32_t
)ntohl(tlv
->value
) & TE_EXT_MASK
;
787 A
= (u_int32_t
)ntohl(tlv
->value
) & TE_EXT_ANORMAL
;
789 sbuf_push(buf
, indent
, "%s Average Link Delay: %" PRIu32
" (micro-sec)\n",
790 A
? "Anomalous" : "Normal", delay
);
792 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
795 static u_char
print_subtlv_mm_delay(struct sbuf
*buf
, int indent
,
796 struct te_subtlv_mm_delay
*tlv
)
801 low
= (u_int32_t
)ntohl(tlv
->low
) & TE_EXT_MASK
;
802 A
= (u_int32_t
)ntohl(tlv
->low
) & TE_EXT_ANORMAL
;
803 high
= (u_int32_t
)ntohl(tlv
->high
) & TE_EXT_MASK
;
805 sbuf_push(buf
, indent
, "%s Min/Max Link Delay: %" PRIu32
" / %" PRIu32
" (micro-sec)\n",
806 A
? "Anomalous" : "Normal", low
, high
);
808 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
811 static u_char
print_subtlv_delay_var(struct sbuf
*buf
, int indent
,
812 struct te_subtlv_delay_var
*tlv
)
816 jitter
= (u_int32_t
)ntohl(tlv
->value
) & TE_EXT_MASK
;
818 sbuf_push(buf
, indent
, "Delay Variation: %" PRIu32
" (micro-sec)\n", jitter
);
820 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
823 static u_char
print_subtlv_pkt_loss(struct sbuf
*buf
, int indent
,
824 struct te_subtlv_pkt_loss
*tlv
)
830 loss
= (u_int32_t
)ntohl(tlv
->value
) & TE_EXT_MASK
;
831 fval
= (float)(loss
* LOSS_PRECISION
);
832 A
= (u_int32_t
)ntohl(tlv
->value
) & TE_EXT_ANORMAL
;
834 sbuf_push(buf
, indent
, "%s Link Packet Loss: %g (%%)\n",
835 A
? "Anomalous" : "Normal", fval
);
837 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
840 static u_char
print_subtlv_res_bw(struct sbuf
*buf
, int indent
,
841 struct te_subtlv_res_bw
*tlv
)
845 fval
= ntohf(tlv
->value
);
847 sbuf_push(buf
, indent
, "Unidirectional Residual Bandwidth: %g (Bytes/sec)\n",
850 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
853 static u_char
print_subtlv_ava_bw(struct sbuf
*buf
, int indent
,
854 struct te_subtlv_ava_bw
*tlv
)
858 fval
= ntohf(tlv
->value
);
860 sbuf_push(buf
, indent
, "Unidirectional Available Bandwidth: %g (Bytes/sec)\n",
863 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
866 static u_char
print_subtlv_use_bw(struct sbuf
*buf
, int indent
,
867 struct te_subtlv_use_bw
*tlv
)
871 fval
= ntohf(tlv
->value
);
873 sbuf_push(buf
, indent
, "Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n",
876 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
879 static u_char
print_unknown_tlv(struct sbuf
*buf
, int indent
,
880 struct subtlv_header
*tlvh
)
883 u_char
*v
= (u_char
*)tlvh
;
885 if (tlvh
->length
!= 0) {
886 sbuf_push(buf
, indent
,
887 "Unknown TLV: [type(%#.2x), length(%#.2x)]\n",
888 tlvh
->type
, tlvh
->length
);
889 sbuf_push(buf
, indent
+ 2, "Dump: [00]");
890 rtn
= 1; /* initialize end of line counter */
891 for (i
= 0; i
< tlvh
->length
; i
++) {
892 sbuf_push(buf
, 0, " %#.2x", v
[i
]);
894 sbuf_push(buf
, 0, "\n");
895 sbuf_push(buf
, indent
+ 8,
901 sbuf_push(buf
, 0, "\n");
903 sbuf_push(buf
, indent
,
904 "Unknown TLV: [type(%#.2x), length(%#.2x)]\n",
905 tlvh
->type
, tlvh
->length
);
908 return SUBTLV_SIZE(tlvh
);
911 /* Main Show function */
912 void mpls_te_print_detail(struct sbuf
*buf
, int indent
,
913 uint8_t *subtlvs
, uint8_t subtlv_len
)
915 struct subtlv_header
*tlvh
= (struct subtlv_header
*)subtlvs
;
918 for (; sum
< subtlv_len
; tlvh
= SUBTLV_HDR_NEXT(tlvh
)) {
919 switch (tlvh
->type
) {
920 case TE_SUBTLV_ADMIN_GRP
:
921 sum
+= print_subtlv_admin_grp(buf
, indent
,
922 (struct te_subtlv_admin_grp
*)tlvh
);
925 sum
+= print_subtlv_llri(buf
, indent
,
926 (struct te_subtlv_llri
*)tlvh
);
928 case TE_SUBTLV_LOCAL_IPADDR
:
929 sum
+= print_subtlv_local_ipaddr(buf
, indent
,
930 (struct te_subtlv_local_ipaddr
*)tlvh
);
932 case TE_SUBTLV_RMT_IPADDR
:
933 sum
+= print_subtlv_rmt_ipaddr(buf
, indent
,
934 (struct te_subtlv_rmt_ipaddr
*)tlvh
);
936 case TE_SUBTLV_MAX_BW
:
937 sum
+= print_subtlv_max_bw(buf
, indent
,
938 (struct te_subtlv_max_bw
*)tlvh
);
940 case TE_SUBTLV_MAX_RSV_BW
:
941 sum
+= print_subtlv_max_rsv_bw(buf
, indent
,
942 (struct te_subtlv_max_rsv_bw
*)tlvh
);
944 case TE_SUBTLV_UNRSV_BW
:
945 sum
+= print_subtlv_unrsv_bw(buf
, indent
,
946 (struct te_subtlv_unrsv_bw
*)tlvh
);
948 case TE_SUBTLV_TE_METRIC
:
949 sum
+= print_subtlv_te_metric(buf
, indent
,
950 (struct te_subtlv_te_metric
*)tlvh
);
953 sum
+= print_subtlv_ras(buf
, indent
,
954 (struct te_subtlv_ras
*)tlvh
);
957 sum
+= print_subtlv_rip(buf
, indent
,
958 (struct te_subtlv_rip
*)tlvh
);
960 case TE_SUBTLV_AV_DELAY
:
961 sum
+= print_subtlv_av_delay(buf
, indent
,
962 (struct te_subtlv_av_delay
*)tlvh
);
964 case TE_SUBTLV_MM_DELAY
:
965 sum
+= print_subtlv_mm_delay(buf
, indent
,
966 (struct te_subtlv_mm_delay
*)tlvh
);
968 case TE_SUBTLV_DELAY_VAR
:
969 sum
+= print_subtlv_delay_var(buf
, indent
,
970 (struct te_subtlv_delay_var
*)tlvh
);
972 case TE_SUBTLV_PKT_LOSS
:
973 sum
+= print_subtlv_pkt_loss(buf
, indent
,
974 (struct te_subtlv_pkt_loss
*)tlvh
);
976 case TE_SUBTLV_RES_BW
:
977 sum
+= print_subtlv_res_bw(buf
, indent
,
978 (struct te_subtlv_res_bw
*)tlvh
);
980 case TE_SUBTLV_AVA_BW
:
981 sum
+= print_subtlv_ava_bw(buf
, indent
,
982 (struct te_subtlv_ava_bw
*)tlvh
);
984 case TE_SUBTLV_USE_BW
:
985 sum
+= print_subtlv_use_bw(buf
, indent
,
986 (struct te_subtlv_use_bw
*)tlvh
);
989 sum
+= print_unknown_tlv(buf
, indent
, tlvh
);
996 /* Specific MPLS TE router parameters write function */
997 void isis_mpls_te_config_write_router(struct vty
*vty
)
999 if (IS_MPLS_TE(isisMplsTE
)) {
1000 vty_out(vty
, " mpls-te on\n");
1001 vty_out(vty
, " mpls-te router-address %s\n",
1002 inet_ntoa(isisMplsTE
.router_id
));
1009 /*------------------------------------------------------------------------*
1010 * Followings are vty command functions.
1011 *------------------------------------------------------------------------*/
1013 DEFUN (isis_mpls_te_on
,
1014 isis_mpls_te_on_cmd
,
1017 "Enable MPLS-TE functionality\n")
1019 struct listnode
*node
;
1020 struct isis_circuit
*circuit
;
1022 if (IS_MPLS_TE(isisMplsTE
))
1025 if (IS_DEBUG_ISIS(DEBUG_TE
))
1026 zlog_debug("ISIS MPLS-TE: OFF -> ON");
1028 isisMplsTE
.status
= enable
;
1031 * Following code is intended to handle two cases;
1033 * 1) MPLS-TE was disabled at startup time, but now become enabled.
1034 * In this case, we must enable MPLS-TE Circuit regarding interface
1036 * 2) MPLS-TE was once enabled then disabled, and now enabled again.
1038 for (ALL_LIST_ELEMENTS_RO(isisMplsTE
.cir_list
, node
, circuit
)) {
1039 if (circuit
->mtc
== NULL
|| IS_FLOOD_AS(circuit
->mtc
->type
))
1042 if ((circuit
->mtc
->status
== disable
)
1043 && HAS_LINK_PARAMS(circuit
->interface
))
1044 circuit
->mtc
->status
= enable
;
1048 /* Reoriginate STD_TE & GMPLS circuits */
1050 lsp_regenerate_schedule(circuit
->area
, circuit
->is_type
,
1057 DEFUN (no_isis_mpls_te_on
,
1058 no_isis_mpls_te_on_cmd
,
1061 "Disable the MPLS-TE functionality\n")
1063 struct listnode
*node
;
1064 struct isis_circuit
*circuit
;
1066 if (isisMplsTE
.status
== disable
)
1069 if (IS_DEBUG_ISIS(DEBUG_TE
))
1070 zlog_debug("ISIS MPLS-TE: ON -> OFF");
1072 isisMplsTE
.status
= disable
;
1074 /* Flush LSP if circuit engage */
1075 for (ALL_LIST_ELEMENTS_RO(isisMplsTE
.cir_list
, node
, circuit
)) {
1076 if (circuit
->mtc
== NULL
|| (circuit
->mtc
->status
== disable
))
1079 /* disable MPLS_TE Circuit */
1080 circuit
->mtc
->status
= disable
;
1082 /* Re-originate circuit without STD_TE & GMPLS parameters */
1084 lsp_regenerate_schedule(circuit
->area
, circuit
->is_type
,
1091 DEFUN (isis_mpls_te_router_addr
,
1092 isis_mpls_te_router_addr_cmd
,
1093 "mpls-te router-address A.B.C.D",
1095 "Stable IP address of the advertising router\n"
1096 "MPLS-TE router address in IPv4 address format\n")
1099 struct in_addr value
;
1100 struct listnode
*node
;
1101 struct isis_area
*area
;
1103 if (!inet_aton(argv
[idx_ipv4
]->arg
, &value
)) {
1104 vty_out(vty
, "Please specify Router-Addr by A.B.C.D\n");
1105 return CMD_WARNING_CONFIG_FAILED
;
1108 isisMplsTE
.router_id
.s_addr
= value
.s_addr
;
1110 if (isisMplsTE
.status
== disable
)
1113 /* Update main Router ID in isis global structure */
1114 isis
->router_id
= value
.s_addr
;
1115 /* And re-schedule LSP update */
1116 for (ALL_LIST_ELEMENTS_RO(isis
->area_list
, node
, area
))
1117 if (listcount(area
->area_addrs
) > 0)
1118 lsp_regenerate_schedule(area
, area
->is_type
, 0);
1123 DEFUN (isis_mpls_te_inter_as
,
1124 isis_mpls_te_inter_as_cmd
,
1125 "mpls-te inter-as <level-1|level-1-2|level-2-only>",
1127 "Configure MPLS-TE Inter-AS support\n"
1128 "AREA native mode self originate INTER-AS LSP with L1 only flooding scope)\n"
1129 "AREA native mode self originate INTER-AS LSP with L1 and L2 flooding scope)\n"
1130 "AS native mode self originate INTER-AS LSP with L2 only flooding scope\n")
1132 vty_out(vty
, "Not yet supported\n");
1136 DEFUN (no_isis_mpls_te_inter_as
,
1137 no_isis_mpls_te_inter_as_cmd
,
1138 "no mpls-te inter-as",
1140 "Disable the MPLS-TE functionality\n"
1141 "Disable MPLS-TE Inter-AS support\n")
1144 vty_out(vty
, "Not yet supported\n");
1148 DEFUN (show_isis_mpls_te_router
,
1149 show_isis_mpls_te_router_cmd
,
1150 "show isis mpls-te router",
1154 "Router information\n")
1156 if (IS_MPLS_TE(isisMplsTE
)) {
1157 vty_out(vty
, "--- MPLS-TE router parameters ---\n");
1159 if (ntohs(isisMplsTE
.router_id
.s_addr
) != 0)
1160 vty_out(vty
, " Router-Address: %s\n",
1161 inet_ntoa(isisMplsTE
.router_id
));
1163 vty_out(vty
, " N/A\n");
1165 vty_out(vty
, " MPLS-TE is disable on this router\n");
1170 static void show_mpls_te_sub(struct vty
*vty
, struct interface
*ifp
)
1172 struct mpls_te_circuit
*mtc
;
1175 sbuf_init(&buf
, NULL
, 0);
1177 if ((IS_MPLS_TE(isisMplsTE
))
1178 && ((mtc
= lookup_mpls_params_by_ifp(ifp
)) != NULL
)) {
1179 /* Continue only if interface is not passive or support Inter-AS
1181 if (mtc
->status
!= enable
) {
1182 if (IS_INTER_AS(mtc
->type
)) {
1184 "-- Inter-AS TEv2 link parameters for %s --\n",
1187 /* MPLS-TE is not activate on this interface */
1188 /* or this interface is passive and Inter-AS
1189 * TEv2 is not activate */
1191 " %s: MPLS-TE is disabled on this interface\n",
1196 vty_out(vty
, "-- MPLS-TE link parameters for %s --\n",
1201 print_subtlv_admin_grp(&buf
, 4, &mtc
->admin_grp
);
1203 if (SUBTLV_TYPE(mtc
->local_ipaddr
) != 0)
1204 print_subtlv_local_ipaddr(&buf
, 4, &mtc
->local_ipaddr
);
1205 if (SUBTLV_TYPE(mtc
->rmt_ipaddr
) != 0)
1206 print_subtlv_rmt_ipaddr(&buf
, 4, &mtc
->rmt_ipaddr
);
1208 print_subtlv_max_bw(&buf
, 4, &mtc
->max_bw
);
1209 print_subtlv_max_rsv_bw(&buf
, 4, &mtc
->max_rsv_bw
);
1210 print_subtlv_unrsv_bw(&buf
, 4, &mtc
->unrsv_bw
);
1211 print_subtlv_te_metric(&buf
, 4, &mtc
->te_metric
);
1213 if (IS_INTER_AS(mtc
->type
)) {
1214 if (SUBTLV_TYPE(mtc
->ras
) != 0)
1215 print_subtlv_ras(&buf
, 4, &mtc
->ras
);
1216 if (SUBTLV_TYPE(mtc
->rip
) != 0)
1217 print_subtlv_rip(&buf
, 4, &mtc
->rip
);
1220 print_subtlv_av_delay(&buf
, 4, &mtc
->av_delay
);
1221 print_subtlv_mm_delay(&buf
, 4, &mtc
->mm_delay
);
1222 print_subtlv_delay_var(&buf
, 4, &mtc
->delay_var
);
1223 print_subtlv_pkt_loss(&buf
, 4, &mtc
->pkt_loss
);
1224 print_subtlv_res_bw(&buf
, 4, &mtc
->res_bw
);
1225 print_subtlv_ava_bw(&buf
, 4, &mtc
->ava_bw
);
1226 print_subtlv_use_bw(&buf
, 4, &mtc
->use_bw
);
1228 vty_multiline(vty
, "", "%s", sbuf_buf(&buf
));
1229 vty_out(vty
, "---------------\n\n");
1231 vty_out(vty
, " %s: MPLS-TE is disabled on this interface\n",
1239 DEFUN (show_isis_mpls_te_interface
,
1240 show_isis_mpls_te_interface_cmd
,
1241 "show isis mpls-te interface [INTERFACE]",
1245 "Interface information\n"
1248 int idx_interface
= 4;
1249 struct interface
*ifp
;
1250 struct listnode
*node
;
1252 /* Show All Interfaces. */
1254 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT
), node
, ifp
))
1255 show_mpls_te_sub(vty
, ifp
);
1257 /* Interface name is specified. */
1259 if ((ifp
= if_lookup_by_name(argv
[idx_interface
]->arg
,
1262 vty_out(vty
, "No such interface name\n");
1264 show_mpls_te_sub(vty
, ifp
);
1270 /* Initialize MPLS_TE */
1271 void isis_mpls_te_init(void)
1274 zlog_debug("ISIS MPLS-TE: Initialize");
1276 /* Initialize MPLS_TE structure */
1277 isisMplsTE
.status
= disable
;
1278 isisMplsTE
.level
= 0;
1279 isisMplsTE
.inter_as
= off
;
1280 isisMplsTE
.interas_areaid
.s_addr
= 0;
1281 isisMplsTE
.cir_list
= list_new();
1282 isisMplsTE
.router_id
.s_addr
= 0;
1284 /* Register new VTY commands */
1285 install_element(VIEW_NODE
, &show_isis_mpls_te_router_cmd
);
1286 install_element(VIEW_NODE
, &show_isis_mpls_te_interface_cmd
);
1288 install_element(ISIS_NODE
, &isis_mpls_te_on_cmd
);
1289 install_element(ISIS_NODE
, &no_isis_mpls_te_on_cmd
);
1290 install_element(ISIS_NODE
, &isis_mpls_te_router_addr_cmd
);
1291 install_element(ISIS_NODE
, &isis_mpls_te_inter_as_cmd
);
1292 install_element(ISIS_NODE
, &no_isis_mpls_te_inter_as_cmd
);