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/isis_constants.h"
47 #include "isisd/isis_common.h"
48 #include "isisd/isis_flags.h"
49 #include "isisd/isis_circuit.h"
50 #include "isisd/isisd.h"
51 #include "isisd/isis_lsp.h"
52 #include "isisd/isis_pdu.h"
53 #include "isisd/isis_dynhn.h"
54 #include "isisd/isis_misc.h"
55 #include "isisd/isis_csm.h"
56 #include "isisd/isis_adjacency.h"
57 #include "isisd/isis_spf.h"
58 #include "isisd/isis_te.h"
60 const char *mode2text
[] = {"Disable", "Area", "AS", "Emulate"};
62 /*------------------------------------------------------------------------*
63 * Followings are control functions for MPLS-TE parameters management.
64 *------------------------------------------------------------------------*/
66 /* Create new MPLS TE Circuit context */
67 struct mpls_te_circuit
*mpls_te_circuit_new(void)
69 struct mpls_te_circuit
*mtc
;
71 zlog_debug("ISIS MPLS-TE: Create new MPLS TE Circuit context");
73 mtc
= XCALLOC(MTYPE_ISIS_MPLS_TE
, sizeof(struct mpls_te_circuit
));
75 mtc
->status
= disable
;
82 /* Copy SUB TLVs parameters into a buffer - No space verification are performed
84 /* Caller must verify before that there is enough free space in the buffer */
85 uint8_t add_te_subtlvs(uint8_t *buf
, struct mpls_te_circuit
*mtc
)
87 uint8_t size
, *tlvs
= buf
;
89 zlog_debug("ISIS MPLS-TE: Add TE Sub TLVs to buffer");
93 "ISIS MPLS-TE: Abort! No MPLS TE Circuit available has been specified");
97 /* Create buffer if not provided */
99 zlog_debug("ISIS MPLS-TE: Abort! No Buffer has been specified");
103 /* TE_SUBTLV_ADMIN_GRP */
104 if (SUBTLV_TYPE(mtc
->admin_grp
) != 0) {
105 size
= SUBTLV_SIZE(&(mtc
->admin_grp
.header
));
106 memcpy(tlvs
, &(mtc
->admin_grp
), size
);
111 if (SUBTLV_TYPE(mtc
->llri
) != 0) {
112 size
= SUBTLV_SIZE(&(mtc
->llri
.header
));
113 memcpy(tlvs
, &(mtc
->llri
), size
);
117 /* TE_SUBTLV_LCLIF_IPADDR */
118 if (SUBTLV_TYPE(mtc
->local_ipaddr
) != 0) {
119 size
= SUBTLV_SIZE(&(mtc
->local_ipaddr
.header
));
120 memcpy(tlvs
, &(mtc
->local_ipaddr
), size
);
124 /* TE_SUBTLV_RMTIF_IPADDR */
125 if (SUBTLV_TYPE(mtc
->rmt_ipaddr
) != 0) {
126 size
= SUBTLV_SIZE(&(mtc
->rmt_ipaddr
.header
));
127 memcpy(tlvs
, &(mtc
->rmt_ipaddr
), size
);
131 /* TE_SUBTLV_MAX_BW */
132 if (SUBTLV_TYPE(mtc
->max_bw
) != 0) {
133 size
= SUBTLV_SIZE(&(mtc
->max_bw
.header
));
134 memcpy(tlvs
, &(mtc
->max_bw
), size
);
138 /* TE_SUBTLV_MAX_RSV_BW */
139 if (SUBTLV_TYPE(mtc
->max_rsv_bw
) != 0) {
140 size
= SUBTLV_SIZE(&(mtc
->max_rsv_bw
.header
));
141 memcpy(tlvs
, &(mtc
->max_rsv_bw
), size
);
145 /* TE_SUBTLV_UNRSV_BW */
146 if (SUBTLV_TYPE(mtc
->unrsv_bw
) != 0) {
147 size
= SUBTLV_SIZE(&(mtc
->unrsv_bw
.header
));
148 memcpy(tlvs
, &(mtc
->unrsv_bw
), size
);
152 /* TE_SUBTLV_TE_METRIC */
153 if (SUBTLV_TYPE(mtc
->te_metric
) != 0) {
154 size
= SUBTLV_SIZE(&(mtc
->te_metric
.header
));
155 memcpy(tlvs
, &(mtc
->te_metric
), size
);
159 /* TE_SUBTLV_AV_DELAY */
160 if (SUBTLV_TYPE(mtc
->av_delay
) != 0) {
161 size
= SUBTLV_SIZE(&(mtc
->av_delay
.header
));
162 memcpy(tlvs
, &(mtc
->av_delay
), size
);
166 /* TE_SUBTLV_MM_DELAY */
167 if (SUBTLV_TYPE(mtc
->mm_delay
) != 0) {
168 size
= SUBTLV_SIZE(&(mtc
->mm_delay
.header
));
169 memcpy(tlvs
, &(mtc
->mm_delay
), size
);
173 /* TE_SUBTLV_DELAY_VAR */
174 if (SUBTLV_TYPE(mtc
->delay_var
) != 0) {
175 size
= SUBTLV_SIZE(&(mtc
->delay_var
.header
));
176 memcpy(tlvs
, &(mtc
->delay_var
), size
);
180 /* TE_SUBTLV_PKT_LOSS */
181 if (SUBTLV_TYPE(mtc
->pkt_loss
) != 0) {
182 size
= SUBTLV_SIZE(&(mtc
->pkt_loss
.header
));
183 memcpy(tlvs
, &(mtc
->pkt_loss
), size
);
187 /* TE_SUBTLV_RES_BW */
188 if (SUBTLV_TYPE(mtc
->res_bw
) != 0) {
189 size
= SUBTLV_SIZE(&(mtc
->res_bw
.header
));
190 memcpy(tlvs
, &(mtc
->res_bw
), size
);
194 /* TE_SUBTLV_AVA_BW */
195 if (SUBTLV_TYPE(mtc
->ava_bw
) != 0) {
196 size
= SUBTLV_SIZE(&(mtc
->ava_bw
.header
));
197 memcpy(tlvs
, &(mtc
->ava_bw
), size
);
201 /* TE_SUBTLV_USE_BW */
202 if (SUBTLV_TYPE(mtc
->use_bw
) != 0) {
203 size
= SUBTLV_SIZE(&(mtc
->use_bw
.header
));
204 memcpy(tlvs
, &(mtc
->use_bw
), size
);
208 /* Add before this line any other parsing of TLV */
211 /* Update SubTLVs length */
212 mtc
->length
= subtlvs_len(mtc
);
214 zlog_debug("ISIS MPLS-TE: Add %d bytes length SubTLVs", mtc
->length
);
219 /* Compute total Sub-TLVs size */
220 uint8_t subtlvs_len(struct mpls_te_circuit
*mtc
)
228 /* TE_SUBTLV_ADMIN_GRP */
229 if (SUBTLV_TYPE(mtc
->admin_grp
) != 0)
230 length
+= SUBTLV_SIZE(&(mtc
->admin_grp
.header
));
233 if (SUBTLV_TYPE(mtc
->llri
) != 0)
234 length
+= SUBTLV_SIZE(&mtc
->llri
.header
);
236 /* TE_SUBTLV_LCLIF_IPADDR */
237 if (SUBTLV_TYPE(mtc
->local_ipaddr
) != 0)
238 length
+= SUBTLV_SIZE(&mtc
->local_ipaddr
.header
);
240 /* TE_SUBTLV_RMTIF_IPADDR */
241 if (SUBTLV_TYPE(mtc
->rmt_ipaddr
) != 0)
242 length
+= SUBTLV_SIZE(&mtc
->rmt_ipaddr
.header
);
244 /* TE_SUBTLV_MAX_BW */
245 if (SUBTLV_TYPE(mtc
->max_bw
) != 0)
246 length
+= SUBTLV_SIZE(&mtc
->max_bw
.header
);
248 /* TE_SUBTLV_MAX_RSV_BW */
249 if (SUBTLV_TYPE(mtc
->max_rsv_bw
) != 0)
250 length
+= SUBTLV_SIZE(&mtc
->max_rsv_bw
.header
);
252 /* TE_SUBTLV_UNRSV_BW */
253 if (SUBTLV_TYPE(mtc
->unrsv_bw
) != 0)
254 length
+= SUBTLV_SIZE(&mtc
->unrsv_bw
.header
);
256 /* TE_SUBTLV_TE_METRIC */
257 if (SUBTLV_TYPE(mtc
->te_metric
) != 0)
258 length
+= SUBTLV_SIZE(&mtc
->te_metric
.header
);
260 /* TE_SUBTLV_AV_DELAY */
261 if (SUBTLV_TYPE(mtc
->av_delay
) != 0)
262 length
+= SUBTLV_SIZE(&mtc
->av_delay
.header
);
264 /* TE_SUBTLV_MM_DELAY */
265 if (SUBTLV_TYPE(mtc
->mm_delay
) != 0)
266 length
+= SUBTLV_SIZE(&mtc
->mm_delay
.header
);
268 /* TE_SUBTLV_DELAY_VAR */
269 if (SUBTLV_TYPE(mtc
->delay_var
) != 0)
270 length
+= SUBTLV_SIZE(&mtc
->delay_var
.header
);
272 /* TE_SUBTLV_PKT_LOSS */
273 if (SUBTLV_TYPE(mtc
->pkt_loss
) != 0)
274 length
+= SUBTLV_SIZE(&mtc
->pkt_loss
.header
);
276 /* TE_SUBTLV_RES_BW */
277 if (SUBTLV_TYPE(mtc
->res_bw
) != 0)
278 length
+= SUBTLV_SIZE(&mtc
->res_bw
.header
);
280 /* TE_SUBTLV_AVA_BW */
281 if (SUBTLV_TYPE(mtc
->ava_bw
) != 0)
282 length
+= SUBTLV_SIZE(&mtc
->ava_bw
.header
);
284 /* TE_SUBTLV_USE_BW */
285 if (SUBTLV_TYPE(mtc
->use_bw
) != 0)
286 length
+= SUBTLV_SIZE(&mtc
->use_bw
.header
);
288 /* Check that length is lower than the MAXIMUM SUBTLV size i.e. 256 */
289 if (length
> MAX_SUBTLV_SIZE
) {
294 mtc
->length
= (uint8_t)length
;
299 /* Following are various functions to set MPLS TE parameters */
300 static void set_circuitparams_admin_grp(struct mpls_te_circuit
*mtc
,
303 SUBTLV_TYPE(mtc
->admin_grp
) = TE_SUBTLV_ADMIN_GRP
;
304 SUBTLV_LEN(mtc
->admin_grp
) = SUBTLV_DEF_SIZE
;
305 mtc
->admin_grp
.value
= htonl(admingrp
);
309 static void __attribute__((unused
))
310 set_circuitparams_llri(struct mpls_te_circuit
*mtc
, uint32_t local
,
313 SUBTLV_TYPE(mtc
->llri
) = TE_SUBTLV_LLRI
;
314 SUBTLV_LEN(mtc
->llri
) = TE_SUBTLV_LLRI_SIZE
;
315 mtc
->llri
.local
= htonl(local
);
316 mtc
->llri
.remote
= htonl(remote
);
319 void set_circuitparams_local_ipaddr(struct mpls_te_circuit
*mtc
,
323 SUBTLV_TYPE(mtc
->local_ipaddr
) = TE_SUBTLV_LOCAL_IPADDR
;
324 SUBTLV_LEN(mtc
->local_ipaddr
) = SUBTLV_DEF_SIZE
;
325 mtc
->local_ipaddr
.value
.s_addr
= addr
.s_addr
;
329 void set_circuitparams_rmt_ipaddr(struct mpls_te_circuit
*mtc
,
333 SUBTLV_TYPE(mtc
->rmt_ipaddr
) = TE_SUBTLV_RMT_IPADDR
;
334 SUBTLV_LEN(mtc
->rmt_ipaddr
) = SUBTLV_DEF_SIZE
;
335 mtc
->rmt_ipaddr
.value
.s_addr
= addr
.s_addr
;
339 static void set_circuitparams_max_bw(struct mpls_te_circuit
*mtc
, float fp
)
341 SUBTLV_TYPE(mtc
->max_bw
) = TE_SUBTLV_MAX_BW
;
342 SUBTLV_LEN(mtc
->max_bw
) = SUBTLV_DEF_SIZE
;
343 mtc
->max_bw
.value
= htonf(fp
);
347 static void set_circuitparams_max_rsv_bw(struct mpls_te_circuit
*mtc
, float fp
)
349 SUBTLV_TYPE(mtc
->max_rsv_bw
) = TE_SUBTLV_MAX_RSV_BW
;
350 SUBTLV_LEN(mtc
->max_rsv_bw
) = SUBTLV_DEF_SIZE
;
351 mtc
->max_rsv_bw
.value
= htonf(fp
);
355 static void set_circuitparams_unrsv_bw(struct mpls_te_circuit
*mtc
,
356 int priority
, float fp
)
358 /* Note that TLV-length field is the size of array. */
359 SUBTLV_TYPE(mtc
->unrsv_bw
) = TE_SUBTLV_UNRSV_BW
;
360 SUBTLV_LEN(mtc
->unrsv_bw
) = TE_SUBTLV_UNRSV_SIZE
;
361 mtc
->unrsv_bw
.value
[priority
] = htonf(fp
);
365 static void set_circuitparams_te_metric(struct mpls_te_circuit
*mtc
,
368 SUBTLV_TYPE(mtc
->te_metric
) = TE_SUBTLV_TE_METRIC
;
369 SUBTLV_LEN(mtc
->te_metric
) = TE_SUBTLV_TE_METRIC_SIZE
;
370 mtc
->te_metric
.value
[0] = (te_metric
>> 16) & 0xFF;
371 mtc
->te_metric
.value
[1] = (te_metric
>> 8) & 0xFF;
372 mtc
->te_metric
.value
[2] = te_metric
& 0xFF;
376 static void set_circuitparams_inter_as(struct mpls_te_circuit
*mtc
,
377 struct in_addr addr
, uint32_t as
)
380 /* Set the Remote ASBR IP address and then the associated AS number */
381 SUBTLV_TYPE(mtc
->rip
) = TE_SUBTLV_RIP
;
382 SUBTLV_LEN(mtc
->rip
) = SUBTLV_DEF_SIZE
;
383 mtc
->rip
.value
.s_addr
= addr
.s_addr
;
385 SUBTLV_TYPE(mtc
->ras
) = TE_SUBTLV_RAS
;
386 SUBTLV_LEN(mtc
->ras
) = SUBTLV_DEF_SIZE
;
387 mtc
->ras
.value
= htonl(as
);
390 static void unset_circuitparams_inter_as(struct mpls_te_circuit
*mtc
)
393 /* Reset the Remote ASBR IP address and then the associated AS number */
394 SUBTLV_TYPE(mtc
->rip
) = 0;
395 SUBTLV_LEN(mtc
->rip
) = 0;
396 mtc
->rip
.value
.s_addr
= 0;
398 SUBTLV_TYPE(mtc
->ras
) = 0;
399 SUBTLV_LEN(mtc
->ras
) = 0;
403 static void set_circuitparams_av_delay(struct mpls_te_circuit
*mtc
,
404 uint32_t delay
, uint8_t anormal
)
407 /* Note that TLV-length field is the size of array. */
408 SUBTLV_TYPE(mtc
->av_delay
) = TE_SUBTLV_AV_DELAY
;
409 SUBTLV_LEN(mtc
->av_delay
) = SUBTLV_DEF_SIZE
;
410 tmp
= delay
& TE_EXT_MASK
;
412 tmp
|= TE_EXT_ANORMAL
;
413 mtc
->av_delay
.value
= htonl(tmp
);
417 static void set_circuitparams_mm_delay(struct mpls_te_circuit
*mtc
,
418 uint32_t low
, uint32_t high
,
422 /* Note that TLV-length field is the size of array. */
423 SUBTLV_TYPE(mtc
->mm_delay
) = TE_SUBTLV_MM_DELAY
;
424 SUBTLV_LEN(mtc
->mm_delay
) = TE_SUBTLV_MM_DELAY_SIZE
;
425 tmp
= low
& TE_EXT_MASK
;
427 tmp
|= TE_EXT_ANORMAL
;
428 mtc
->mm_delay
.low
= htonl(tmp
);
429 mtc
->mm_delay
.high
= htonl(high
);
433 static void set_circuitparams_delay_var(struct mpls_te_circuit
*mtc
,
436 /* Note that TLV-length field is the size of array. */
437 SUBTLV_TYPE(mtc
->delay_var
) = TE_SUBTLV_DELAY_VAR
;
438 SUBTLV_LEN(mtc
->delay_var
) = SUBTLV_DEF_SIZE
;
439 mtc
->delay_var
.value
= htonl(jitter
& TE_EXT_MASK
);
443 static void set_circuitparams_pkt_loss(struct mpls_te_circuit
*mtc
,
444 uint32_t loss
, uint8_t anormal
)
447 /* Note that TLV-length field is the size of array. */
448 SUBTLV_TYPE(mtc
->pkt_loss
) = TE_SUBTLV_PKT_LOSS
;
449 SUBTLV_LEN(mtc
->pkt_loss
) = SUBTLV_DEF_SIZE
;
450 tmp
= loss
& TE_EXT_MASK
;
452 tmp
|= TE_EXT_ANORMAL
;
453 mtc
->pkt_loss
.value
= htonl(tmp
);
457 static void set_circuitparams_res_bw(struct mpls_te_circuit
*mtc
, float fp
)
459 /* Note that TLV-length field is the size of array. */
460 SUBTLV_TYPE(mtc
->res_bw
) = TE_SUBTLV_RES_BW
;
461 SUBTLV_LEN(mtc
->res_bw
) = SUBTLV_DEF_SIZE
;
462 mtc
->res_bw
.value
= htonf(fp
);
466 static void set_circuitparams_ava_bw(struct mpls_te_circuit
*mtc
, float fp
)
468 /* Note that TLV-length field is the size of array. */
469 SUBTLV_TYPE(mtc
->ava_bw
) = TE_SUBTLV_AVA_BW
;
470 SUBTLV_LEN(mtc
->ava_bw
) = SUBTLV_DEF_SIZE
;
471 mtc
->ava_bw
.value
= htonf(fp
);
475 static void set_circuitparams_use_bw(struct mpls_te_circuit
*mtc
, float fp
)
477 /* Note that TLV-length field is the size of array. */
478 SUBTLV_TYPE(mtc
->use_bw
) = TE_SUBTLV_USE_BW
;
479 SUBTLV_LEN(mtc
->use_bw
) = SUBTLV_DEF_SIZE
;
480 mtc
->use_bw
.value
= htonf(fp
);
484 /* Main initialization / update function of the MPLS TE Circuit context */
485 /* Call when interface TE Link parameters are modified */
486 void isis_link_params_update(struct isis_circuit
*circuit
,
487 struct interface
*ifp
)
490 struct prefix_ipv4
*addr
;
491 struct mpls_te_circuit
*mtc
;
494 if ((circuit
== NULL
) || (ifp
== NULL
))
497 zlog_info("MPLS-TE: Initialize circuit parameters for interface %s",
500 /* Check if MPLS TE Circuit context has not been already created */
501 if (circuit
->mtc
== NULL
)
502 circuit
->mtc
= mpls_te_circuit_new();
506 /* Fulfil MTC TLV from ifp TE Link parameters */
507 if (HAS_LINK_PARAMS(ifp
)) {
508 mtc
->status
= enable
;
510 if (IS_PARAM_SET(ifp
->link_params
, LP_ADM_GRP
))
511 set_circuitparams_admin_grp(
512 mtc
, ifp
->link_params
->admin_grp
);
514 SUBTLV_TYPE(mtc
->admin_grp
) = 0;
516 /* If not already set, register local IP addr from ip_addr list
518 if (SUBTLV_TYPE(mtc
->local_ipaddr
) == 0) {
519 if (circuit
->ip_addrs
!= NULL
520 && listcount(circuit
->ip_addrs
) != 0) {
521 addr
= (struct prefix_ipv4
*)listgetdata(
522 (struct listnode
*)listhead(
524 set_circuitparams_local_ipaddr(mtc
,
529 /* If not already set, try to determine Remote IP addr if
531 if ((SUBTLV_TYPE(mtc
->rmt_ipaddr
) == 0)
532 && (circuit
->circ_type
== CIRCUIT_T_P2P
)) {
533 struct isis_adjacency
*adj
= circuit
->u
.p2p
.neighbor
;
534 if (adj
&& adj
->adj_state
== ISIS_ADJ_UP
535 && adj
->ipv4_address_count
) {
536 set_circuitparams_rmt_ipaddr(
537 mtc
, adj
->ipv4_addresses
[0]);
541 if (IS_PARAM_SET(ifp
->link_params
, LP_MAX_BW
))
542 set_circuitparams_max_bw(mtc
, ifp
->link_params
->max_bw
);
544 SUBTLV_TYPE(mtc
->max_bw
) = 0;
546 if (IS_PARAM_SET(ifp
->link_params
, LP_MAX_RSV_BW
))
547 set_circuitparams_max_rsv_bw(
548 mtc
, ifp
->link_params
->max_rsv_bw
);
550 SUBTLV_TYPE(mtc
->max_rsv_bw
) = 0;
552 if (IS_PARAM_SET(ifp
->link_params
, LP_UNRSV_BW
))
553 for (i
= 0; i
< MAX_CLASS_TYPE
; i
++)
554 set_circuitparams_unrsv_bw(
555 mtc
, i
, ifp
->link_params
->unrsv_bw
[i
]);
557 SUBTLV_TYPE(mtc
->unrsv_bw
) = 0;
559 if (IS_PARAM_SET(ifp
->link_params
, LP_TE_METRIC
))
560 set_circuitparams_te_metric(
561 mtc
, ifp
->link_params
->te_metric
);
563 SUBTLV_TYPE(mtc
->te_metric
) = 0;
565 /* TE metric Extensions */
566 if (IS_PARAM_SET(ifp
->link_params
, LP_DELAY
))
567 set_circuitparams_av_delay(
568 mtc
, ifp
->link_params
->av_delay
, 0);
570 SUBTLV_TYPE(mtc
->av_delay
) = 0;
572 if (IS_PARAM_SET(ifp
->link_params
, LP_MM_DELAY
))
573 set_circuitparams_mm_delay(
574 mtc
, ifp
->link_params
->min_delay
,
575 ifp
->link_params
->max_delay
, 0);
577 SUBTLV_TYPE(mtc
->mm_delay
) = 0;
579 if (IS_PARAM_SET(ifp
->link_params
, LP_DELAY_VAR
))
580 set_circuitparams_delay_var(
581 mtc
, ifp
->link_params
->delay_var
);
583 SUBTLV_TYPE(mtc
->delay_var
) = 0;
585 if (IS_PARAM_SET(ifp
->link_params
, LP_PKT_LOSS
))
586 set_circuitparams_pkt_loss(
587 mtc
, ifp
->link_params
->pkt_loss
, 0);
589 SUBTLV_TYPE(mtc
->pkt_loss
) = 0;
591 if (IS_PARAM_SET(ifp
->link_params
, LP_RES_BW
))
592 set_circuitparams_res_bw(mtc
, ifp
->link_params
->res_bw
);
594 SUBTLV_TYPE(mtc
->res_bw
) = 0;
596 if (IS_PARAM_SET(ifp
->link_params
, LP_AVA_BW
))
597 set_circuitparams_ava_bw(mtc
, ifp
->link_params
->ava_bw
);
599 SUBTLV_TYPE(mtc
->ava_bw
) = 0;
601 if (IS_PARAM_SET(ifp
->link_params
, LP_USE_BW
))
602 set_circuitparams_use_bw(mtc
, ifp
->link_params
->use_bw
);
604 SUBTLV_TYPE(mtc
->use_bw
) = 0;
607 if (IS_PARAM_SET(ifp
->link_params
, LP_RMT_AS
))
608 set_circuitparams_inter_as(mtc
,
609 ifp
->link_params
->rmt_ip
,
610 ifp
->link_params
->rmt_as
);
612 /* reset inter-as TE params */
613 unset_circuitparams_inter_as(mtc
);
615 /* Compute total length of SUB TLVs */
616 mtc
->length
= subtlvs_len(mtc
);
619 mtc
->status
= disable
;
621 /* Finally Update LSP */
623 if (circuit
->area
&& IS_MPLS_TE(circuit
->area
->mta
))
624 lsp_regenerate_schedule (circuit
->area
, circuit
->is_type
, 0);
629 void isis_mpls_te_update(struct interface
*ifp
)
631 struct isis_circuit
*circuit
;
637 /* Get circuit context from interface */
638 if ((circuit
= circuit_scan_by_ifp(ifp
)) == NULL
)
641 /* Update TE TLVs ... */
642 isis_link_params_update(circuit
, ifp
);
645 if (circuit
->area
&& IS_MPLS_TE(circuit
->area
->mta
))
646 lsp_regenerate_schedule(circuit
->area
, circuit
->is_type
, 0);
651 /*------------------------------------------------------------------------*
652 * Followings are vty session control functions.
653 *------------------------------------------------------------------------*/
655 static uint8_t print_subtlv_admin_grp(struct sbuf
*buf
, int indent
,
656 struct te_subtlv_admin_grp
*tlv
)
658 sbuf_push(buf
, indent
, "Administrative Group: 0x%" PRIx32
"\n",
660 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
663 static uint8_t print_subtlv_llri(struct sbuf
*buf
, int indent
,
664 struct te_subtlv_llri
*tlv
)
666 sbuf_push(buf
, indent
, "Link Local ID: %" PRIu32
"\n",
668 sbuf_push(buf
, indent
, "Link Remote ID: %" PRIu32
"\n",
671 return (SUBTLV_HDR_SIZE
+ TE_SUBTLV_LLRI_SIZE
);
674 static uint8_t print_subtlv_local_ipaddr(struct sbuf
*buf
, int indent
,
675 struct te_subtlv_local_ipaddr
*tlv
)
677 sbuf_push(buf
, indent
, "Local Interface IP Address(es): %s\n",
678 inet_ntoa(tlv
->value
));
680 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
683 static uint8_t print_subtlv_rmt_ipaddr(struct sbuf
*buf
, int indent
,
684 struct te_subtlv_rmt_ipaddr
*tlv
)
686 sbuf_push(buf
, indent
, "Remote Interface IP Address(es): %s\n",
687 inet_ntoa(tlv
->value
));
689 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
692 static uint8_t print_subtlv_max_bw(struct sbuf
*buf
, int indent
,
693 struct te_subtlv_max_bw
*tlv
)
697 fval
= ntohf(tlv
->value
);
699 sbuf_push(buf
, indent
, "Maximum Bandwidth: %g (Bytes/sec)\n", fval
);
701 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
704 static uint8_t print_subtlv_max_rsv_bw(struct sbuf
*buf
, int indent
,
705 struct te_subtlv_max_rsv_bw
*tlv
)
709 fval
= ntohf(tlv
->value
);
711 sbuf_push(buf
, indent
, "Maximum Reservable Bandwidth: %g (Bytes/sec)\n",
714 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
717 static uint8_t print_subtlv_unrsv_bw(struct sbuf
*buf
, int indent
,
718 struct te_subtlv_unrsv_bw
*tlv
)
723 sbuf_push(buf
, indent
, "Unreserved Bandwidth:\n");
725 for (i
= 0; i
< MAX_CLASS_TYPE
; i
+= 2) {
726 fval1
= ntohf(tlv
->value
[i
]);
727 fval2
= ntohf(tlv
->value
[i
+ 1]);
728 sbuf_push(buf
, indent
+ 2,
729 "[%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n", i
,
730 fval1
, i
+ 1, fval2
);
733 return (SUBTLV_HDR_SIZE
+ TE_SUBTLV_UNRSV_SIZE
);
736 static uint8_t print_subtlv_te_metric(struct sbuf
*buf
, int indent
,
737 struct te_subtlv_te_metric
*tlv
)
741 te_metric
= tlv
->value
[2] | tlv
->value
[1] << 8 | tlv
->value
[0] << 16;
742 sbuf_push(buf
, indent
, "Traffic Engineering Metric: %u\n", te_metric
);
744 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
747 static uint8_t print_subtlv_ras(struct sbuf
*buf
, int indent
,
748 struct te_subtlv_ras
*tlv
)
750 sbuf_push(buf
, indent
, "Inter-AS TE Remote AS number: %" PRIu32
"\n",
753 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
756 static uint8_t print_subtlv_rip(struct sbuf
*buf
, int indent
,
757 struct te_subtlv_rip
*tlv
)
759 sbuf_push(buf
, indent
, "Inter-AS TE Remote ASBR IP address: %s\n",
760 inet_ntoa(tlv
->value
));
762 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
765 static uint8_t print_subtlv_av_delay(struct sbuf
*buf
, int indent
,
766 struct te_subtlv_av_delay
*tlv
)
771 delay
= (uint32_t)ntohl(tlv
->value
) & TE_EXT_MASK
;
772 A
= (uint32_t)ntohl(tlv
->value
) & TE_EXT_ANORMAL
;
774 sbuf_push(buf
, indent
,
775 "%s Average Link Delay: %" PRIu32
" (micro-sec)\n",
776 A
? "Anomalous" : "Normal", delay
);
778 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
781 static uint8_t print_subtlv_mm_delay(struct sbuf
*buf
, int indent
,
782 struct te_subtlv_mm_delay
*tlv
)
787 low
= (uint32_t)ntohl(tlv
->low
) & TE_EXT_MASK
;
788 A
= (uint32_t)ntohl(tlv
->low
) & TE_EXT_ANORMAL
;
789 high
= (uint32_t)ntohl(tlv
->high
) & TE_EXT_MASK
;
791 sbuf_push(buf
, indent
, "%s Min/Max Link Delay: %" PRIu32
" / %" PRIu32
" (micro-sec)\n",
792 A
? "Anomalous" : "Normal", low
, high
);
794 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
797 static uint8_t print_subtlv_delay_var(struct sbuf
*buf
, int indent
,
798 struct te_subtlv_delay_var
*tlv
)
802 jitter
= (uint32_t)ntohl(tlv
->value
) & TE_EXT_MASK
;
804 sbuf_push(buf
, indent
, "Delay Variation: %" PRIu32
" (micro-sec)\n",
807 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
810 static uint8_t print_subtlv_pkt_loss(struct sbuf
*buf
, int indent
,
811 struct te_subtlv_pkt_loss
*tlv
)
817 loss
= (uint32_t)ntohl(tlv
->value
) & TE_EXT_MASK
;
818 fval
= (float)(loss
* LOSS_PRECISION
);
819 A
= (uint32_t)ntohl(tlv
->value
) & TE_EXT_ANORMAL
;
821 sbuf_push(buf
, indent
, "%s Link Packet Loss: %g (%%)\n",
822 A
? "Anomalous" : "Normal", fval
);
824 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
827 static uint8_t print_subtlv_res_bw(struct sbuf
*buf
, int indent
,
828 struct te_subtlv_res_bw
*tlv
)
832 fval
= ntohf(tlv
->value
);
834 sbuf_push(buf
, indent
,
835 "Unidirectional Residual Bandwidth: %g (Bytes/sec)\n", fval
);
837 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
840 static uint8_t print_subtlv_ava_bw(struct sbuf
*buf
, int indent
,
841 struct te_subtlv_ava_bw
*tlv
)
845 fval
= ntohf(tlv
->value
);
847 sbuf_push(buf
, indent
,
848 "Unidirectional Available Bandwidth: %g (Bytes/sec)\n", fval
);
850 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
853 static uint8_t print_subtlv_use_bw(struct sbuf
*buf
, int indent
,
854 struct te_subtlv_use_bw
*tlv
)
858 fval
= ntohf(tlv
->value
);
860 sbuf_push(buf
, indent
,
861 "Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n", fval
);
863 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
866 static uint8_t print_unknown_tlv(struct sbuf
*buf
, int indent
,
867 struct subtlv_header
*tlvh
)
870 uint8_t *v
= (uint8_t *)tlvh
;
872 if (tlvh
->length
!= 0) {
873 sbuf_push(buf
, indent
,
874 "Unknown TLV: [type(%#.2x), length(%#.2x)]\n",
875 tlvh
->type
, tlvh
->length
);
876 sbuf_push(buf
, indent
+ 2, "Dump: [00]");
877 rtn
= 1; /* initialize end of line counter */
878 for (i
= 0; i
< tlvh
->length
; i
++) {
879 sbuf_push(buf
, 0, " %#.2x", v
[i
]);
881 sbuf_push(buf
, 0, "\n");
882 sbuf_push(buf
, indent
+ 8, "[%.2x]", i
+ 1);
887 sbuf_push(buf
, 0, "\n");
889 sbuf_push(buf
, indent
,
890 "Unknown TLV: [type(%#.2x), length(%#.2x)]\n",
891 tlvh
->type
, tlvh
->length
);
894 return SUBTLV_SIZE(tlvh
);
897 /* Main Show function */
898 void mpls_te_print_detail(struct sbuf
*buf
, int indent
,
899 uint8_t *subtlvs
, uint8_t subtlv_len
)
901 struct subtlv_header
*tlvh
= (struct subtlv_header
*)subtlvs
;
904 for (; sum
< subtlv_len
;
905 tlvh
= (struct subtlv_header
*)(subtlvs
+ sum
)) {
906 if (subtlv_len
- sum
< SUBTLV_SIZE(tlvh
)) {
907 sbuf_push(buf
, indent
, "Available data %" PRIu8
" is less than TLV size %u!\n",
908 subtlv_len
- sum
, SUBTLV_SIZE(tlvh
));
912 switch (tlvh
->type
) {
913 case TE_SUBTLV_ADMIN_GRP
:
914 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
915 sbuf_push(buf
, indent
, "TLV size does not match expected size for Administrative Group!\n");
918 sum
+= print_subtlv_admin_grp(buf
, indent
,
919 (struct te_subtlv_admin_grp
*)tlvh
);
922 if (tlvh
->length
!= TE_SUBTLV_LLRI_SIZE
) {
923 sbuf_push(buf
, indent
, "TLV size does not match expected size for Link ID!\n");
926 sum
+= print_subtlv_llri(buf
, indent
,
927 (struct te_subtlv_llri
*)tlvh
);
929 case TE_SUBTLV_LOCAL_IPADDR
:
930 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
931 sbuf_push(buf
, indent
, "TLV size does not match expected size for Local IP address!\n");
934 sum
+= print_subtlv_local_ipaddr(buf
, indent
,
935 (struct te_subtlv_local_ipaddr
*)tlvh
);
937 case TE_SUBTLV_RMT_IPADDR
:
938 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
939 sbuf_push(buf
, indent
, "TLV size does not match expected size for Remote Interface address!\n");
942 sum
+= print_subtlv_rmt_ipaddr(buf
, indent
,
943 (struct te_subtlv_rmt_ipaddr
*)tlvh
);
945 case TE_SUBTLV_MAX_BW
:
946 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
947 sbuf_push(buf
, indent
, "TLV size does not match expected size for Maximum Bandwidth!\n");
950 sum
+= print_subtlv_max_bw(buf
, indent
,
951 (struct te_subtlv_max_bw
*)tlvh
);
953 case TE_SUBTLV_MAX_RSV_BW
:
954 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
955 sbuf_push(buf
, indent
, "TLV size does not match expected size for Maximum Reservable Bandwidth!\n");
958 sum
+= print_subtlv_max_rsv_bw(buf
, indent
,
959 (struct te_subtlv_max_rsv_bw
*)tlvh
);
961 case TE_SUBTLV_UNRSV_BW
:
962 if (tlvh
->length
!= TE_SUBTLV_UNRSV_SIZE
) {
963 sbuf_push(buf
, indent
, "TLV size does not match expected size for Unreserved Bandwidth!\n");
966 sum
+= print_subtlv_unrsv_bw(buf
, indent
,
967 (struct te_subtlv_unrsv_bw
*)tlvh
);
969 case TE_SUBTLV_TE_METRIC
:
970 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
971 sbuf_push(buf
, indent
, "TLV size does not match expected size for Traffic Engineering Metric!\n");
974 sum
+= print_subtlv_te_metric(buf
, indent
,
975 (struct te_subtlv_te_metric
*)tlvh
);
978 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
979 sbuf_push(buf
, indent
, "TLV size does not match expected size for Remote AS number!\n");
982 sum
+= print_subtlv_ras(buf
, indent
,
983 (struct te_subtlv_ras
*)tlvh
);
986 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
987 sbuf_push(buf
, indent
, "TLV size does not match expected size for Remote ASBR IP Address!\n");
990 sum
+= print_subtlv_rip(buf
, indent
,
991 (struct te_subtlv_rip
*)tlvh
);
993 case TE_SUBTLV_AV_DELAY
:
994 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
995 sbuf_push(buf
, indent
, "TLV size does not match expected size for Average Link Delay!\n");
998 sum
+= print_subtlv_av_delay(buf
, indent
,
999 (struct te_subtlv_av_delay
*)tlvh
);
1001 case TE_SUBTLV_MM_DELAY
:
1002 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1003 sbuf_push(buf
, indent
, "TLV size does not match expected size for Min/Max Link Delay!\n");
1006 sum
+= print_subtlv_mm_delay(buf
, indent
,
1007 (struct te_subtlv_mm_delay
*)tlvh
);
1009 case TE_SUBTLV_DELAY_VAR
:
1010 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1011 sbuf_push(buf
, indent
, "TLV size does not match expected size for Delay Variation!\n");
1014 sum
+= print_subtlv_delay_var(buf
, indent
,
1015 (struct te_subtlv_delay_var
*)tlvh
);
1017 case TE_SUBTLV_PKT_LOSS
:
1018 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1019 sbuf_push(buf
, indent
, "TLV size does not match expected size for Link Packet Loss!\n");
1022 sum
+= print_subtlv_pkt_loss(buf
, indent
,
1023 (struct te_subtlv_pkt_loss
*)tlvh
);
1025 case TE_SUBTLV_RES_BW
:
1026 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1027 sbuf_push(buf
, indent
, "TLV size does not match expected size for Unidirectional Residual Bandwidth!\n");
1030 sum
+= print_subtlv_res_bw(buf
, indent
,
1031 (struct te_subtlv_res_bw
*)tlvh
);
1033 case TE_SUBTLV_AVA_BW
:
1034 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1035 sbuf_push(buf
, indent
, "TLV size does not match expected size for Unidirectional Available Bandwidth!\n");
1038 sum
+= print_subtlv_ava_bw(buf
, indent
,
1039 (struct te_subtlv_ava_bw
*)tlvh
);
1041 case TE_SUBTLV_USE_BW
:
1042 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1043 sbuf_push(buf
, indent
, "TLV size does not match expected size for Unidirectional Utilized Bandwidth!\n");
1046 sum
+= print_subtlv_use_bw(buf
, indent
,
1047 (struct te_subtlv_use_bw
*)tlvh
);
1050 sum
+= print_unknown_tlv(buf
, indent
, tlvh
);
1057 /*------------------------------------------------------------------------*
1058 * Followings are vty command functions.
1059 *------------------------------------------------------------------------*/
1062 DEFUN (show_isis_mpls_te_router
,
1063 show_isis_mpls_te_router_cmd
,
1064 "show " PROTO_NAME
" mpls-te router",
1068 "Router information\n")
1071 struct listnode
*anode
;
1072 struct isis_area
*area
;
1075 vty_out(vty
, "IS-IS Routing Process not enabled\n");
1079 for (ALL_LIST_ELEMENTS_RO(isis
->area_list
, anode
, area
)) {
1081 if (!IS_MPLS_TE(area
->mta
))
1084 vty_out(vty
, "Area %s:\n", area
->area_tag
);
1085 if (ntohs(area
->mta
->router_id
.s_addr
) != 0)
1086 vty_out(vty
, " MPLS-TE Router-Address: %s\n",
1087 inet_ntoa(area
->mta
->router_id
));
1089 vty_out(vty
, " N/A\n");
1095 static void show_mpls_te_sub(struct vty
*vty
, char *name
,
1096 struct mpls_te_circuit
*mtc
)
1100 sbuf_init(&buf
, NULL
, 0);
1102 if (mtc
->status
!= enable
)
1105 vty_out(vty
, "-- MPLS-TE link parameters for %s --\n", name
);
1108 print_subtlv_admin_grp(&buf
, 4, &mtc
->admin_grp
);
1110 if (SUBTLV_TYPE(mtc
->local_ipaddr
) != 0)
1111 print_subtlv_local_ipaddr(&buf
, 4, &mtc
->local_ipaddr
);
1112 if (SUBTLV_TYPE(mtc
->rmt_ipaddr
) != 0)
1113 print_subtlv_rmt_ipaddr(&buf
, 4, &mtc
->rmt_ipaddr
);
1115 print_subtlv_max_bw(&buf
, 4, &mtc
->max_bw
);
1116 print_subtlv_max_rsv_bw(&buf
, 4, &mtc
->max_rsv_bw
);
1117 print_subtlv_unrsv_bw(&buf
, 4, &mtc
->unrsv_bw
);
1118 print_subtlv_te_metric(&buf
, 4, &mtc
->te_metric
);
1120 if (IS_INTER_AS(mtc
->type
)) {
1121 if (SUBTLV_TYPE(mtc
->ras
) != 0)
1122 print_subtlv_ras(&buf
, 4, &mtc
->ras
);
1123 if (SUBTLV_TYPE(mtc
->rip
) != 0)
1124 print_subtlv_rip(&buf
, 4, &mtc
->rip
);
1127 print_subtlv_av_delay(&buf
, 4, &mtc
->av_delay
);
1128 print_subtlv_mm_delay(&buf
, 4, &mtc
->mm_delay
);
1129 print_subtlv_delay_var(&buf
, 4, &mtc
->delay_var
);
1130 print_subtlv_pkt_loss(&buf
, 4, &mtc
->pkt_loss
);
1131 print_subtlv_res_bw(&buf
, 4, &mtc
->res_bw
);
1132 print_subtlv_ava_bw(&buf
, 4, &mtc
->ava_bw
);
1133 print_subtlv_use_bw(&buf
, 4, &mtc
->use_bw
);
1135 vty_multiline(vty
, "", "%s", sbuf_buf(&buf
));
1136 vty_out(vty
, "---------------\n\n");
1142 DEFUN (show_isis_mpls_te_interface
,
1143 show_isis_mpls_te_interface_cmd
,
1144 "show " PROTO_NAME
" mpls-te interface [INTERFACE]",
1148 "Interface information\n"
1151 struct listnode
*anode
, *cnode
;
1152 struct isis_area
*area
;
1153 struct isis_circuit
*circuit
;
1154 struct interface
*ifp
;
1155 int idx_interface
= 4;
1158 vty_out(vty
, "IS-IS Routing Process not enabled\n");
1162 if (argc
== idx_interface
) {
1163 /* Show All Interfaces. */
1164 for (ALL_LIST_ELEMENTS_RO(isis
->area_list
, anode
, area
)) {
1166 if (!IS_MPLS_TE(area
->mta
))
1169 vty_out(vty
, "Area %s:\n", area
->area_tag
);
1171 for (ALL_LIST_ELEMENTS_RO(area
->circuit_list
, cnode
,
1173 show_mpls_te_sub(vty
, circuit
->interface
->name
,
1177 /* Interface name is specified. */
1178 ifp
= if_lookup_by_name(argv
[idx_interface
]->arg
, VRF_DEFAULT
);
1180 vty_out(vty
, "No such interface name\n");
1182 circuit
= circuit_scan_by_ifp(ifp
);
1185 "ISIS is not enabled on circuit %s\n",
1188 show_mpls_te_sub(vty
, ifp
->name
, circuit
->mtc
);
1196 /* Initialize MPLS_TE */
1197 void isis_mpls_te_init(void)
1201 /* Register new VTY commands */
1202 install_element(VIEW_NODE
, &show_isis_mpls_te_router_cmd
);
1203 install_element(VIEW_NODE
, &show_isis_mpls_te_interface_cmd
);