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 const char *mode2text
[] = {"Disable", "Area", "AS", "Emulate"};
63 /*------------------------------------------------------------------------*
64 * Followings are control functions for MPLS-TE parameters management.
65 *------------------------------------------------------------------------*/
67 /* Create new MPLS TE Circuit context */
68 struct mpls_te_circuit
*mpls_te_circuit_new(void)
70 struct mpls_te_circuit
*mtc
;
72 zlog_debug("ISIS MPLS-TE: Create new MPLS TE Circuit context");
74 mtc
= XCALLOC(MTYPE_ISIS_MPLS_TE
, sizeof(struct mpls_te_circuit
));
76 mtc
->status
= disable
;
83 /* Copy SUB TLVs parameters into a buffer - No space verification are performed
85 /* Caller must verify before that there is enough free space in the buffer */
86 uint8_t add_te_subtlvs(uint8_t *buf
, struct mpls_te_circuit
*mtc
)
88 uint8_t size
, *tlvs
= buf
;
90 zlog_debug("ISIS MPLS-TE: Add TE Sub TLVs to buffer");
94 "ISIS MPLS-TE: Abort! No MPLS TE Circuit available has been specified");
98 /* Create buffer if not provided */
100 zlog_debug("ISIS MPLS-TE: Abort! No Buffer has been specified");
104 /* TE_SUBTLV_ADMIN_GRP */
105 if (SUBTLV_TYPE(mtc
->admin_grp
) != 0) {
106 size
= SUBTLV_SIZE(&(mtc
->admin_grp
.header
));
107 memcpy(tlvs
, &(mtc
->admin_grp
), size
);
112 if (SUBTLV_TYPE(mtc
->llri
) != 0) {
113 size
= SUBTLV_SIZE(&(mtc
->llri
.header
));
114 memcpy(tlvs
, &(mtc
->llri
), size
);
118 /* TE_SUBTLV_LCLIF_IPADDR */
119 if (SUBTLV_TYPE(mtc
->local_ipaddr
) != 0) {
120 size
= SUBTLV_SIZE(&(mtc
->local_ipaddr
.header
));
121 memcpy(tlvs
, &(mtc
->local_ipaddr
), size
);
125 /* TE_SUBTLV_RMTIF_IPADDR */
126 if (SUBTLV_TYPE(mtc
->rmt_ipaddr
) != 0) {
127 size
= SUBTLV_SIZE(&(mtc
->rmt_ipaddr
.header
));
128 memcpy(tlvs
, &(mtc
->rmt_ipaddr
), size
);
132 /* TE_SUBTLV_MAX_BW */
133 if (SUBTLV_TYPE(mtc
->max_bw
) != 0) {
134 size
= SUBTLV_SIZE(&(mtc
->max_bw
.header
));
135 memcpy(tlvs
, &(mtc
->max_bw
), size
);
139 /* TE_SUBTLV_MAX_RSV_BW */
140 if (SUBTLV_TYPE(mtc
->max_rsv_bw
) != 0) {
141 size
= SUBTLV_SIZE(&(mtc
->max_rsv_bw
.header
));
142 memcpy(tlvs
, &(mtc
->max_rsv_bw
), size
);
146 /* TE_SUBTLV_UNRSV_BW */
147 if (SUBTLV_TYPE(mtc
->unrsv_bw
) != 0) {
148 size
= SUBTLV_SIZE(&(mtc
->unrsv_bw
.header
));
149 memcpy(tlvs
, &(mtc
->unrsv_bw
), size
);
153 /* TE_SUBTLV_TE_METRIC */
154 if (SUBTLV_TYPE(mtc
->te_metric
) != 0) {
155 size
= SUBTLV_SIZE(&(mtc
->te_metric
.header
));
156 memcpy(tlvs
, &(mtc
->te_metric
), size
);
160 /* TE_SUBTLV_AV_DELAY */
161 if (SUBTLV_TYPE(mtc
->av_delay
) != 0) {
162 size
= SUBTLV_SIZE(&(mtc
->av_delay
.header
));
163 memcpy(tlvs
, &(mtc
->av_delay
), size
);
167 /* TE_SUBTLV_MM_DELAY */
168 if (SUBTLV_TYPE(mtc
->mm_delay
) != 0) {
169 size
= SUBTLV_SIZE(&(mtc
->mm_delay
.header
));
170 memcpy(tlvs
, &(mtc
->mm_delay
), size
);
174 /* TE_SUBTLV_DELAY_VAR */
175 if (SUBTLV_TYPE(mtc
->delay_var
) != 0) {
176 size
= SUBTLV_SIZE(&(mtc
->delay_var
.header
));
177 memcpy(tlvs
, &(mtc
->delay_var
), size
);
181 /* TE_SUBTLV_PKT_LOSS */
182 if (SUBTLV_TYPE(mtc
->pkt_loss
) != 0) {
183 size
= SUBTLV_SIZE(&(mtc
->pkt_loss
.header
));
184 memcpy(tlvs
, &(mtc
->pkt_loss
), size
);
188 /* TE_SUBTLV_RES_BW */
189 if (SUBTLV_TYPE(mtc
->res_bw
) != 0) {
190 size
= SUBTLV_SIZE(&(mtc
->res_bw
.header
));
191 memcpy(tlvs
, &(mtc
->res_bw
), size
);
195 /* TE_SUBTLV_AVA_BW */
196 if (SUBTLV_TYPE(mtc
->ava_bw
) != 0) {
197 size
= SUBTLV_SIZE(&(mtc
->ava_bw
.header
));
198 memcpy(tlvs
, &(mtc
->ava_bw
), size
);
202 /* TE_SUBTLV_USE_BW */
203 if (SUBTLV_TYPE(mtc
->use_bw
) != 0) {
204 size
= SUBTLV_SIZE(&(mtc
->use_bw
.header
));
205 memcpy(tlvs
, &(mtc
->use_bw
), size
);
209 /* Add before this line any other parsing of TLV */
212 /* Update SubTLVs length */
213 mtc
->length
= subtlvs_len(mtc
);
215 zlog_debug("ISIS MPLS-TE: Add %d bytes length SubTLVs", mtc
->length
);
220 /* Compute total Sub-TLVs size */
221 uint8_t subtlvs_len(struct mpls_te_circuit
*mtc
)
229 /* TE_SUBTLV_ADMIN_GRP */
230 if (SUBTLV_TYPE(mtc
->admin_grp
) != 0)
231 length
+= SUBTLV_SIZE(&(mtc
->admin_grp
.header
));
234 if (SUBTLV_TYPE(mtc
->llri
) != 0)
235 length
+= SUBTLV_SIZE(&mtc
->llri
.header
);
237 /* TE_SUBTLV_LCLIF_IPADDR */
238 if (SUBTLV_TYPE(mtc
->local_ipaddr
) != 0)
239 length
+= SUBTLV_SIZE(&mtc
->local_ipaddr
.header
);
241 /* TE_SUBTLV_RMTIF_IPADDR */
242 if (SUBTLV_TYPE(mtc
->rmt_ipaddr
) != 0)
243 length
+= SUBTLV_SIZE(&mtc
->rmt_ipaddr
.header
);
245 /* TE_SUBTLV_MAX_BW */
246 if (SUBTLV_TYPE(mtc
->max_bw
) != 0)
247 length
+= SUBTLV_SIZE(&mtc
->max_bw
.header
);
249 /* TE_SUBTLV_MAX_RSV_BW */
250 if (SUBTLV_TYPE(mtc
->max_rsv_bw
) != 0)
251 length
+= SUBTLV_SIZE(&mtc
->max_rsv_bw
.header
);
253 /* TE_SUBTLV_UNRSV_BW */
254 if (SUBTLV_TYPE(mtc
->unrsv_bw
) != 0)
255 length
+= SUBTLV_SIZE(&mtc
->unrsv_bw
.header
);
257 /* TE_SUBTLV_TE_METRIC */
258 if (SUBTLV_TYPE(mtc
->te_metric
) != 0)
259 length
+= SUBTLV_SIZE(&mtc
->te_metric
.header
);
261 /* TE_SUBTLV_AV_DELAY */
262 if (SUBTLV_TYPE(mtc
->av_delay
) != 0)
263 length
+= SUBTLV_SIZE(&mtc
->av_delay
.header
);
265 /* TE_SUBTLV_MM_DELAY */
266 if (SUBTLV_TYPE(mtc
->mm_delay
) != 0)
267 length
+= SUBTLV_SIZE(&mtc
->mm_delay
.header
);
269 /* TE_SUBTLV_DELAY_VAR */
270 if (SUBTLV_TYPE(mtc
->delay_var
) != 0)
271 length
+= SUBTLV_SIZE(&mtc
->delay_var
.header
);
273 /* TE_SUBTLV_PKT_LOSS */
274 if (SUBTLV_TYPE(mtc
->pkt_loss
) != 0)
275 length
+= SUBTLV_SIZE(&mtc
->pkt_loss
.header
);
277 /* TE_SUBTLV_RES_BW */
278 if (SUBTLV_TYPE(mtc
->res_bw
) != 0)
279 length
+= SUBTLV_SIZE(&mtc
->res_bw
.header
);
281 /* TE_SUBTLV_AVA_BW */
282 if (SUBTLV_TYPE(mtc
->ava_bw
) != 0)
283 length
+= SUBTLV_SIZE(&mtc
->ava_bw
.header
);
285 /* TE_SUBTLV_USE_BW */
286 if (SUBTLV_TYPE(mtc
->use_bw
) != 0)
287 length
+= SUBTLV_SIZE(&mtc
->use_bw
.header
);
289 /* Check that length is lower than the MAXIMUM SUBTLV size i.e. 256 */
290 if (length
> MAX_SUBTLV_SIZE
) {
295 mtc
->length
= (uint8_t)length
;
300 /* Following are various functions to set MPLS TE parameters */
301 static void set_circuitparams_admin_grp(struct mpls_te_circuit
*mtc
,
304 SUBTLV_TYPE(mtc
->admin_grp
) = TE_SUBTLV_ADMIN_GRP
;
305 SUBTLV_LEN(mtc
->admin_grp
) = SUBTLV_DEF_SIZE
;
306 mtc
->admin_grp
.value
= htonl(admingrp
);
310 static void __attribute__((unused
))
311 set_circuitparams_llri(struct mpls_te_circuit
*mtc
, uint32_t local
,
314 SUBTLV_TYPE(mtc
->llri
) = TE_SUBTLV_LLRI
;
315 SUBTLV_LEN(mtc
->llri
) = TE_SUBTLV_LLRI_SIZE
;
316 mtc
->llri
.local
= htonl(local
);
317 mtc
->llri
.remote
= htonl(remote
);
320 void set_circuitparams_local_ipaddr(struct mpls_te_circuit
*mtc
,
324 SUBTLV_TYPE(mtc
->local_ipaddr
) = TE_SUBTLV_LOCAL_IPADDR
;
325 SUBTLV_LEN(mtc
->local_ipaddr
) = SUBTLV_DEF_SIZE
;
326 mtc
->local_ipaddr
.value
.s_addr
= addr
.s_addr
;
330 void set_circuitparams_rmt_ipaddr(struct mpls_te_circuit
*mtc
,
334 SUBTLV_TYPE(mtc
->rmt_ipaddr
) = TE_SUBTLV_RMT_IPADDR
;
335 SUBTLV_LEN(mtc
->rmt_ipaddr
) = SUBTLV_DEF_SIZE
;
336 mtc
->rmt_ipaddr
.value
.s_addr
= addr
.s_addr
;
340 static void set_circuitparams_max_bw(struct mpls_te_circuit
*mtc
, float fp
)
342 SUBTLV_TYPE(mtc
->max_bw
) = TE_SUBTLV_MAX_BW
;
343 SUBTLV_LEN(mtc
->max_bw
) = SUBTLV_DEF_SIZE
;
344 mtc
->max_bw
.value
= htonf(fp
);
348 static void set_circuitparams_max_rsv_bw(struct mpls_te_circuit
*mtc
, float fp
)
350 SUBTLV_TYPE(mtc
->max_rsv_bw
) = TE_SUBTLV_MAX_RSV_BW
;
351 SUBTLV_LEN(mtc
->max_rsv_bw
) = SUBTLV_DEF_SIZE
;
352 mtc
->max_rsv_bw
.value
= htonf(fp
);
356 static void set_circuitparams_unrsv_bw(struct mpls_te_circuit
*mtc
,
357 int priority
, float fp
)
359 /* Note that TLV-length field is the size of array. */
360 SUBTLV_TYPE(mtc
->unrsv_bw
) = TE_SUBTLV_UNRSV_BW
;
361 SUBTLV_LEN(mtc
->unrsv_bw
) = TE_SUBTLV_UNRSV_SIZE
;
362 mtc
->unrsv_bw
.value
[priority
] = htonf(fp
);
366 static void set_circuitparams_te_metric(struct mpls_te_circuit
*mtc
,
369 SUBTLV_TYPE(mtc
->te_metric
) = TE_SUBTLV_TE_METRIC
;
370 SUBTLV_LEN(mtc
->te_metric
) = TE_SUBTLV_TE_METRIC_SIZE
;
371 mtc
->te_metric
.value
[0] = (te_metric
>> 16) & 0xFF;
372 mtc
->te_metric
.value
[1] = (te_metric
>> 8) & 0xFF;
373 mtc
->te_metric
.value
[2] = te_metric
& 0xFF;
377 static void set_circuitparams_inter_as(struct mpls_te_circuit
*mtc
,
378 struct in_addr addr
, uint32_t as
)
381 /* Set the Remote ASBR IP address and then the associated AS number */
382 SUBTLV_TYPE(mtc
->rip
) = TE_SUBTLV_RIP
;
383 SUBTLV_LEN(mtc
->rip
) = SUBTLV_DEF_SIZE
;
384 mtc
->rip
.value
.s_addr
= addr
.s_addr
;
386 SUBTLV_TYPE(mtc
->ras
) = TE_SUBTLV_RAS
;
387 SUBTLV_LEN(mtc
->ras
) = SUBTLV_DEF_SIZE
;
388 mtc
->ras
.value
= htonl(as
);
391 static void unset_circuitparams_inter_as(struct mpls_te_circuit
*mtc
)
394 /* Reset the Remote ASBR IP address and then the associated AS number */
395 SUBTLV_TYPE(mtc
->rip
) = 0;
396 SUBTLV_LEN(mtc
->rip
) = 0;
397 mtc
->rip
.value
.s_addr
= 0;
399 SUBTLV_TYPE(mtc
->ras
) = 0;
400 SUBTLV_LEN(mtc
->ras
) = 0;
404 static void set_circuitparams_av_delay(struct mpls_te_circuit
*mtc
,
405 uint32_t delay
, uint8_t anormal
)
408 /* Note that TLV-length field is the size of array. */
409 SUBTLV_TYPE(mtc
->av_delay
) = TE_SUBTLV_AV_DELAY
;
410 SUBTLV_LEN(mtc
->av_delay
) = SUBTLV_DEF_SIZE
;
411 tmp
= delay
& TE_EXT_MASK
;
413 tmp
|= TE_EXT_ANORMAL
;
414 mtc
->av_delay
.value
= htonl(tmp
);
418 static void set_circuitparams_mm_delay(struct mpls_te_circuit
*mtc
,
419 uint32_t low
, uint32_t high
,
423 /* Note that TLV-length field is the size of array. */
424 SUBTLV_TYPE(mtc
->mm_delay
) = TE_SUBTLV_MM_DELAY
;
425 SUBTLV_LEN(mtc
->mm_delay
) = TE_SUBTLV_MM_DELAY_SIZE
;
426 tmp
= low
& TE_EXT_MASK
;
428 tmp
|= TE_EXT_ANORMAL
;
429 mtc
->mm_delay
.low
= htonl(tmp
);
430 mtc
->mm_delay
.high
= htonl(high
);
434 static void set_circuitparams_delay_var(struct mpls_te_circuit
*mtc
,
437 /* Note that TLV-length field is the size of array. */
438 SUBTLV_TYPE(mtc
->delay_var
) = TE_SUBTLV_DELAY_VAR
;
439 SUBTLV_LEN(mtc
->delay_var
) = SUBTLV_DEF_SIZE
;
440 mtc
->delay_var
.value
= htonl(jitter
& TE_EXT_MASK
);
444 static void set_circuitparams_pkt_loss(struct mpls_te_circuit
*mtc
,
445 uint32_t loss
, uint8_t anormal
)
448 /* Note that TLV-length field is the size of array. */
449 SUBTLV_TYPE(mtc
->pkt_loss
) = TE_SUBTLV_PKT_LOSS
;
450 SUBTLV_LEN(mtc
->pkt_loss
) = SUBTLV_DEF_SIZE
;
451 tmp
= loss
& TE_EXT_MASK
;
453 tmp
|= TE_EXT_ANORMAL
;
454 mtc
->pkt_loss
.value
= htonl(tmp
);
458 static void set_circuitparams_res_bw(struct mpls_te_circuit
*mtc
, float fp
)
460 /* Note that TLV-length field is the size of array. */
461 SUBTLV_TYPE(mtc
->res_bw
) = TE_SUBTLV_RES_BW
;
462 SUBTLV_LEN(mtc
->res_bw
) = SUBTLV_DEF_SIZE
;
463 mtc
->res_bw
.value
= htonf(fp
);
467 static void set_circuitparams_ava_bw(struct mpls_te_circuit
*mtc
, float fp
)
469 /* Note that TLV-length field is the size of array. */
470 SUBTLV_TYPE(mtc
->ava_bw
) = TE_SUBTLV_AVA_BW
;
471 SUBTLV_LEN(mtc
->ava_bw
) = SUBTLV_DEF_SIZE
;
472 mtc
->ava_bw
.value
= htonf(fp
);
476 static void set_circuitparams_use_bw(struct mpls_te_circuit
*mtc
, float fp
)
478 /* Note that TLV-length field is the size of array. */
479 SUBTLV_TYPE(mtc
->use_bw
) = TE_SUBTLV_USE_BW
;
480 SUBTLV_LEN(mtc
->use_bw
) = SUBTLV_DEF_SIZE
;
481 mtc
->use_bw
.value
= htonf(fp
);
485 /* Main initialization / update function of the MPLS TE Circuit context */
486 /* Call when interface TE Link parameters are modified */
487 void isis_link_params_update(struct isis_circuit
*circuit
,
488 struct interface
*ifp
)
491 struct prefix_ipv4
*addr
;
492 struct mpls_te_circuit
*mtc
;
495 if ((circuit
== NULL
) || (ifp
== NULL
))
498 zlog_info("MPLS-TE: Initialize circuit parameters for interface %s",
501 /* Check if MPLS TE Circuit context has not been already created */
502 if (circuit
->mtc
== NULL
)
503 circuit
->mtc
= mpls_te_circuit_new();
507 /* Fulfil MTC TLV from ifp TE Link parameters */
508 if (HAS_LINK_PARAMS(ifp
)) {
509 mtc
->status
= enable
;
511 if (IS_PARAM_SET(ifp
->link_params
, LP_ADM_GRP
))
512 set_circuitparams_admin_grp(
513 mtc
, ifp
->link_params
->admin_grp
);
515 SUBTLV_TYPE(mtc
->admin_grp
) = 0;
517 /* If not already set, register local IP addr from ip_addr list
519 if (SUBTLV_TYPE(mtc
->local_ipaddr
) == 0) {
520 if (circuit
->ip_addrs
!= NULL
521 && listcount(circuit
->ip_addrs
) != 0) {
522 addr
= (struct prefix_ipv4
*)listgetdata(
523 (struct listnode
*)listhead(
525 set_circuitparams_local_ipaddr(mtc
,
530 /* If not already set, try to determine Remote IP addr if
532 if ((SUBTLV_TYPE(mtc
->rmt_ipaddr
) == 0)
533 && (circuit
->circ_type
== CIRCUIT_T_P2P
)) {
534 struct isis_adjacency
*adj
= circuit
->u
.p2p
.neighbor
;
535 if (adj
&& adj
->adj_state
== ISIS_ADJ_UP
536 && adj
->ipv4_address_count
) {
537 set_circuitparams_rmt_ipaddr(
538 mtc
, adj
->ipv4_addresses
[0]);
542 if (IS_PARAM_SET(ifp
->link_params
, LP_MAX_BW
))
543 set_circuitparams_max_bw(mtc
, ifp
->link_params
->max_bw
);
545 SUBTLV_TYPE(mtc
->max_bw
) = 0;
547 if (IS_PARAM_SET(ifp
->link_params
, LP_MAX_RSV_BW
))
548 set_circuitparams_max_rsv_bw(
549 mtc
, ifp
->link_params
->max_rsv_bw
);
551 SUBTLV_TYPE(mtc
->max_rsv_bw
) = 0;
553 if (IS_PARAM_SET(ifp
->link_params
, LP_UNRSV_BW
))
554 for (i
= 0; i
< MAX_CLASS_TYPE
; i
++)
555 set_circuitparams_unrsv_bw(
556 mtc
, i
, ifp
->link_params
->unrsv_bw
[i
]);
558 SUBTLV_TYPE(mtc
->unrsv_bw
) = 0;
560 if (IS_PARAM_SET(ifp
->link_params
, LP_TE_METRIC
))
561 set_circuitparams_te_metric(
562 mtc
, ifp
->link_params
->te_metric
);
564 SUBTLV_TYPE(mtc
->te_metric
) = 0;
566 /* TE metric Extensions */
567 if (IS_PARAM_SET(ifp
->link_params
, LP_DELAY
))
568 set_circuitparams_av_delay(
569 mtc
, ifp
->link_params
->av_delay
, 0);
571 SUBTLV_TYPE(mtc
->av_delay
) = 0;
573 if (IS_PARAM_SET(ifp
->link_params
, LP_MM_DELAY
))
574 set_circuitparams_mm_delay(
575 mtc
, ifp
->link_params
->min_delay
,
576 ifp
->link_params
->max_delay
, 0);
578 SUBTLV_TYPE(mtc
->mm_delay
) = 0;
580 if (IS_PARAM_SET(ifp
->link_params
, LP_DELAY_VAR
))
581 set_circuitparams_delay_var(
582 mtc
, ifp
->link_params
->delay_var
);
584 SUBTLV_TYPE(mtc
->delay_var
) = 0;
586 if (IS_PARAM_SET(ifp
->link_params
, LP_PKT_LOSS
))
587 set_circuitparams_pkt_loss(
588 mtc
, ifp
->link_params
->pkt_loss
, 0);
590 SUBTLV_TYPE(mtc
->pkt_loss
) = 0;
592 if (IS_PARAM_SET(ifp
->link_params
, LP_RES_BW
))
593 set_circuitparams_res_bw(mtc
, ifp
->link_params
->res_bw
);
595 SUBTLV_TYPE(mtc
->res_bw
) = 0;
597 if (IS_PARAM_SET(ifp
->link_params
, LP_AVA_BW
))
598 set_circuitparams_ava_bw(mtc
, ifp
->link_params
->ava_bw
);
600 SUBTLV_TYPE(mtc
->ava_bw
) = 0;
602 if (IS_PARAM_SET(ifp
->link_params
, LP_USE_BW
))
603 set_circuitparams_use_bw(mtc
, ifp
->link_params
->use_bw
);
605 SUBTLV_TYPE(mtc
->use_bw
) = 0;
608 if (IS_PARAM_SET(ifp
->link_params
, LP_RMT_AS
))
609 set_circuitparams_inter_as(mtc
,
610 ifp
->link_params
->rmt_ip
,
611 ifp
->link_params
->rmt_as
);
613 /* reset inter-as TE params */
614 unset_circuitparams_inter_as(mtc
);
616 /* Compute total length of SUB TLVs */
617 mtc
->length
= subtlvs_len(mtc
);
620 mtc
->status
= disable
;
622 /* Finally Update LSP */
624 if (circuit
->area
&& IS_MPLS_TE(circuit
->area
->mta
))
625 lsp_regenerate_schedule (circuit
->area
, circuit
->is_type
, 0);
630 void isis_mpls_te_update(struct interface
*ifp
)
632 struct isis_circuit
*circuit
;
638 /* Get circuit context from interface */
639 if ((circuit
= circuit_scan_by_ifp(ifp
)) == NULL
)
642 /* Update TE TLVs ... */
643 isis_link_params_update(circuit
, ifp
);
646 if (circuit
->area
&& IS_MPLS_TE(circuit
->area
->mta
))
647 lsp_regenerate_schedule(circuit
->area
, circuit
->is_type
, 0);
652 /*------------------------------------------------------------------------*
653 * Followings are vty session control functions.
654 *------------------------------------------------------------------------*/
656 static uint8_t print_subtlv_admin_grp(struct sbuf
*buf
, int indent
,
657 struct te_subtlv_admin_grp
*tlv
)
659 sbuf_push(buf
, indent
, "Administrative Group: 0x%" PRIx32
"\n",
661 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
664 static uint8_t print_subtlv_llri(struct sbuf
*buf
, int indent
,
665 struct te_subtlv_llri
*tlv
)
667 sbuf_push(buf
, indent
, "Link Local ID: %" PRIu32
"\n",
669 sbuf_push(buf
, indent
, "Link Remote ID: %" PRIu32
"\n",
672 return (SUBTLV_HDR_SIZE
+ TE_SUBTLV_LLRI_SIZE
);
675 static uint8_t print_subtlv_local_ipaddr(struct sbuf
*buf
, int indent
,
676 struct te_subtlv_local_ipaddr
*tlv
)
678 sbuf_push(buf
, indent
, "Local Interface IP Address(es): %s\n",
679 inet_ntoa(tlv
->value
));
681 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
684 static uint8_t print_subtlv_rmt_ipaddr(struct sbuf
*buf
, int indent
,
685 struct te_subtlv_rmt_ipaddr
*tlv
)
687 sbuf_push(buf
, indent
, "Remote Interface IP Address(es): %s\n",
688 inet_ntoa(tlv
->value
));
690 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
693 static uint8_t print_subtlv_max_bw(struct sbuf
*buf
, int indent
,
694 struct te_subtlv_max_bw
*tlv
)
698 fval
= ntohf(tlv
->value
);
700 sbuf_push(buf
, indent
, "Maximum Bandwidth: %g (Bytes/sec)\n", fval
);
702 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
705 static uint8_t print_subtlv_max_rsv_bw(struct sbuf
*buf
, int indent
,
706 struct te_subtlv_max_rsv_bw
*tlv
)
710 fval
= ntohf(tlv
->value
);
712 sbuf_push(buf
, indent
, "Maximum Reservable Bandwidth: %g (Bytes/sec)\n",
715 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
718 static uint8_t print_subtlv_unrsv_bw(struct sbuf
*buf
, int indent
,
719 struct te_subtlv_unrsv_bw
*tlv
)
724 sbuf_push(buf
, indent
, "Unreserved Bandwidth:\n");
726 for (i
= 0; i
< MAX_CLASS_TYPE
; i
+= 2) {
727 fval1
= ntohf(tlv
->value
[i
]);
728 fval2
= ntohf(tlv
->value
[i
+ 1]);
729 sbuf_push(buf
, indent
+ 2,
730 "[%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n", i
,
731 fval1
, i
+ 1, fval2
);
734 return (SUBTLV_HDR_SIZE
+ TE_SUBTLV_UNRSV_SIZE
);
737 static uint8_t print_subtlv_te_metric(struct sbuf
*buf
, int indent
,
738 struct te_subtlv_te_metric
*tlv
)
742 te_metric
= tlv
->value
[2] | tlv
->value
[1] << 8 | tlv
->value
[0] << 16;
743 sbuf_push(buf
, indent
, "Traffic Engineering Metric: %u\n", te_metric
);
745 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
748 static uint8_t print_subtlv_ras(struct sbuf
*buf
, int indent
,
749 struct te_subtlv_ras
*tlv
)
751 sbuf_push(buf
, indent
, "Inter-AS TE Remote AS number: %" PRIu32
"\n",
754 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
757 static uint8_t print_subtlv_rip(struct sbuf
*buf
, int indent
,
758 struct te_subtlv_rip
*tlv
)
760 sbuf_push(buf
, indent
, "Inter-AS TE Remote ASBR IP address: %s\n",
761 inet_ntoa(tlv
->value
));
763 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
766 static uint8_t print_subtlv_av_delay(struct sbuf
*buf
, int indent
,
767 struct te_subtlv_av_delay
*tlv
)
772 delay
= (uint32_t)ntohl(tlv
->value
) & TE_EXT_MASK
;
773 A
= (uint32_t)ntohl(tlv
->value
) & TE_EXT_ANORMAL
;
775 sbuf_push(buf
, indent
,
776 "%s Average Link Delay: %" PRIu32
" (micro-sec)\n",
777 A
? "Anomalous" : "Normal", delay
);
779 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
782 static uint8_t print_subtlv_mm_delay(struct sbuf
*buf
, int indent
,
783 struct te_subtlv_mm_delay
*tlv
)
788 low
= (uint32_t)ntohl(tlv
->low
) & TE_EXT_MASK
;
789 A
= (uint32_t)ntohl(tlv
->low
) & TE_EXT_ANORMAL
;
790 high
= (uint32_t)ntohl(tlv
->high
) & TE_EXT_MASK
;
792 sbuf_push(buf
, indent
, "%s Min/Max Link Delay: %" PRIu32
" / %" PRIu32
" (micro-sec)\n",
793 A
? "Anomalous" : "Normal", low
, high
);
795 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
798 static uint8_t print_subtlv_delay_var(struct sbuf
*buf
, int indent
,
799 struct te_subtlv_delay_var
*tlv
)
803 jitter
= (uint32_t)ntohl(tlv
->value
) & TE_EXT_MASK
;
805 sbuf_push(buf
, indent
, "Delay Variation: %" PRIu32
" (micro-sec)\n",
808 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
811 static uint8_t print_subtlv_pkt_loss(struct sbuf
*buf
, int indent
,
812 struct te_subtlv_pkt_loss
*tlv
)
818 loss
= (uint32_t)ntohl(tlv
->value
) & TE_EXT_MASK
;
819 fval
= (float)(loss
* LOSS_PRECISION
);
820 A
= (uint32_t)ntohl(tlv
->value
) & TE_EXT_ANORMAL
;
822 sbuf_push(buf
, indent
, "%s Link Packet Loss: %g (%%)\n",
823 A
? "Anomalous" : "Normal", fval
);
825 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
828 static uint8_t print_subtlv_res_bw(struct sbuf
*buf
, int indent
,
829 struct te_subtlv_res_bw
*tlv
)
833 fval
= ntohf(tlv
->value
);
835 sbuf_push(buf
, indent
,
836 "Unidirectional Residual Bandwidth: %g (Bytes/sec)\n", fval
);
838 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
841 static uint8_t print_subtlv_ava_bw(struct sbuf
*buf
, int indent
,
842 struct te_subtlv_ava_bw
*tlv
)
846 fval
= ntohf(tlv
->value
);
848 sbuf_push(buf
, indent
,
849 "Unidirectional Available Bandwidth: %g (Bytes/sec)\n", fval
);
851 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
854 static uint8_t print_subtlv_use_bw(struct sbuf
*buf
, int indent
,
855 struct te_subtlv_use_bw
*tlv
)
859 fval
= ntohf(tlv
->value
);
861 sbuf_push(buf
, indent
,
862 "Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n", fval
);
864 return (SUBTLV_HDR_SIZE
+ SUBTLV_DEF_SIZE
);
867 static uint8_t print_unknown_tlv(struct sbuf
*buf
, int indent
,
868 struct subtlv_header
*tlvh
)
871 uint8_t *v
= (uint8_t *)tlvh
;
873 if (tlvh
->length
!= 0) {
874 sbuf_push(buf
, indent
,
875 "Unknown TLV: [type(%#.2x), length(%#.2x)]\n",
876 tlvh
->type
, tlvh
->length
);
877 sbuf_push(buf
, indent
+ 2, "Dump: [00]");
878 rtn
= 1; /* initialize end of line counter */
879 for (i
= 0; i
< tlvh
->length
; i
++) {
880 sbuf_push(buf
, 0, " %#.2x", v
[i
]);
882 sbuf_push(buf
, 0, "\n");
883 sbuf_push(buf
, indent
+ 8, "[%.2x]", i
+ 1);
888 sbuf_push(buf
, 0, "\n");
890 sbuf_push(buf
, indent
,
891 "Unknown TLV: [type(%#.2x), length(%#.2x)]\n",
892 tlvh
->type
, tlvh
->length
);
895 return SUBTLV_SIZE(tlvh
);
898 /* Main Show function */
899 void mpls_te_print_detail(struct sbuf
*buf
, int indent
,
900 uint8_t *subtlvs
, uint8_t subtlv_len
)
902 struct subtlv_header
*tlvh
= (struct subtlv_header
*)subtlvs
;
905 for (; sum
< subtlv_len
;
906 tlvh
= (struct subtlv_header
*)(subtlvs
+ sum
)) {
907 if (subtlv_len
- sum
< SUBTLV_SIZE(tlvh
)) {
908 sbuf_push(buf
, indent
, "Available data %" PRIu8
" is less than TLV size %u!\n",
909 subtlv_len
- sum
, SUBTLV_SIZE(tlvh
));
913 switch (tlvh
->type
) {
914 case TE_SUBTLV_ADMIN_GRP
:
915 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
916 sbuf_push(buf
, indent
, "TLV size does not match expected size for Administrative Group!\n");
919 sum
+= print_subtlv_admin_grp(buf
, indent
,
920 (struct te_subtlv_admin_grp
*)tlvh
);
923 if (tlvh
->length
!= TE_SUBTLV_LLRI_SIZE
) {
924 sbuf_push(buf
, indent
, "TLV size does not match expected size for Link ID!\n");
927 sum
+= print_subtlv_llri(buf
, indent
,
928 (struct te_subtlv_llri
*)tlvh
);
930 case TE_SUBTLV_LOCAL_IPADDR
:
931 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
932 sbuf_push(buf
, indent
, "TLV size does not match expected size for Local IP address!\n");
935 sum
+= print_subtlv_local_ipaddr(buf
, indent
,
936 (struct te_subtlv_local_ipaddr
*)tlvh
);
938 case TE_SUBTLV_RMT_IPADDR
:
939 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
940 sbuf_push(buf
, indent
, "TLV size does not match expected size for Remote Interface address!\n");
943 sum
+= print_subtlv_rmt_ipaddr(buf
, indent
,
944 (struct te_subtlv_rmt_ipaddr
*)tlvh
);
946 case TE_SUBTLV_MAX_BW
:
947 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
948 sbuf_push(buf
, indent
, "TLV size does not match expected size for Maximum Bandwidth!\n");
951 sum
+= print_subtlv_max_bw(buf
, indent
,
952 (struct te_subtlv_max_bw
*)tlvh
);
954 case TE_SUBTLV_MAX_RSV_BW
:
955 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
956 sbuf_push(buf
, indent
, "TLV size does not match expected size for Maximum Reservable Bandwidth!\n");
959 sum
+= print_subtlv_max_rsv_bw(buf
, indent
,
960 (struct te_subtlv_max_rsv_bw
*)tlvh
);
962 case TE_SUBTLV_UNRSV_BW
:
963 if (tlvh
->length
!= TE_SUBTLV_UNRSV_SIZE
) {
964 sbuf_push(buf
, indent
, "TLV size does not match expected size for Unreserved Bandwidth!\n");
967 sum
+= print_subtlv_unrsv_bw(buf
, indent
,
968 (struct te_subtlv_unrsv_bw
*)tlvh
);
970 case TE_SUBTLV_TE_METRIC
:
971 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
972 sbuf_push(buf
, indent
, "TLV size does not match expected size for Traffic Engineering Metric!\n");
975 sum
+= print_subtlv_te_metric(buf
, indent
,
976 (struct te_subtlv_te_metric
*)tlvh
);
979 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
980 sbuf_push(buf
, indent
, "TLV size does not match expected size for Remote AS number!\n");
983 sum
+= print_subtlv_ras(buf
, indent
,
984 (struct te_subtlv_ras
*)tlvh
);
987 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
988 sbuf_push(buf
, indent
, "TLV size does not match expected size for Remote ASBR IP Address!\n");
991 sum
+= print_subtlv_rip(buf
, indent
,
992 (struct te_subtlv_rip
*)tlvh
);
994 case TE_SUBTLV_AV_DELAY
:
995 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
996 sbuf_push(buf
, indent
, "TLV size does not match expected size for Average Link Delay!\n");
999 sum
+= print_subtlv_av_delay(buf
, indent
,
1000 (struct te_subtlv_av_delay
*)tlvh
);
1002 case TE_SUBTLV_MM_DELAY
:
1003 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1004 sbuf_push(buf
, indent
, "TLV size does not match expected size for Min/Max Link Delay!\n");
1007 sum
+= print_subtlv_mm_delay(buf
, indent
,
1008 (struct te_subtlv_mm_delay
*)tlvh
);
1010 case TE_SUBTLV_DELAY_VAR
:
1011 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1012 sbuf_push(buf
, indent
, "TLV size does not match expected size for Delay Variation!\n");
1015 sum
+= print_subtlv_delay_var(buf
, indent
,
1016 (struct te_subtlv_delay_var
*)tlvh
);
1018 case TE_SUBTLV_PKT_LOSS
:
1019 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1020 sbuf_push(buf
, indent
, "TLV size does not match expected size for Link Packet Loss!\n");
1023 sum
+= print_subtlv_pkt_loss(buf
, indent
,
1024 (struct te_subtlv_pkt_loss
*)tlvh
);
1026 case TE_SUBTLV_RES_BW
:
1027 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1028 sbuf_push(buf
, indent
, "TLV size does not match expected size for Unidirectional Residual Bandwidth!\n");
1031 sum
+= print_subtlv_res_bw(buf
, indent
,
1032 (struct te_subtlv_res_bw
*)tlvh
);
1034 case TE_SUBTLV_AVA_BW
:
1035 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1036 sbuf_push(buf
, indent
, "TLV size does not match expected size for Unidirectional Available Bandwidth!\n");
1039 sum
+= print_subtlv_ava_bw(buf
, indent
,
1040 (struct te_subtlv_ava_bw
*)tlvh
);
1042 case TE_SUBTLV_USE_BW
:
1043 if (tlvh
->length
!= SUBTLV_DEF_SIZE
) {
1044 sbuf_push(buf
, indent
, "TLV size does not match expected size for Unidirectional Utilized Bandwidth!\n");
1047 sum
+= print_subtlv_use_bw(buf
, indent
,
1048 (struct te_subtlv_use_bw
*)tlvh
);
1051 sum
+= print_unknown_tlv(buf
, indent
, tlvh
);
1058 /*------------------------------------------------------------------------*
1059 * Followings are vty command functions.
1060 *------------------------------------------------------------------------*/
1063 DEFUN (show_isis_mpls_te_router
,
1064 show_isis_mpls_te_router_cmd
,
1065 "show " PROTO_NAME
" mpls-te router",
1069 "Router information\n")
1072 struct listnode
*anode
;
1073 struct isis_area
*area
;
1076 vty_out(vty
, "IS-IS Routing Process not enabled\n");
1080 for (ALL_LIST_ELEMENTS_RO(isis
->area_list
, anode
, area
)) {
1082 if (!IS_MPLS_TE(area
->mta
))
1085 vty_out(vty
, "Area %s:\n", area
->area_tag
);
1086 if (ntohs(area
->mta
->router_id
.s_addr
) != 0)
1087 vty_out(vty
, " MPLS-TE Router-Address: %s\n",
1088 inet_ntoa(area
->mta
->router_id
));
1090 vty_out(vty
, " N/A\n");
1096 static void show_mpls_te_sub(struct vty
*vty
, char *name
,
1097 struct mpls_te_circuit
*mtc
)
1101 sbuf_init(&buf
, NULL
, 0);
1103 if (mtc
->status
!= enable
)
1106 vty_out(vty
, "-- MPLS-TE link parameters for %s --\n", name
);
1109 print_subtlv_admin_grp(&buf
, 4, &mtc
->admin_grp
);
1111 if (SUBTLV_TYPE(mtc
->local_ipaddr
) != 0)
1112 print_subtlv_local_ipaddr(&buf
, 4, &mtc
->local_ipaddr
);
1113 if (SUBTLV_TYPE(mtc
->rmt_ipaddr
) != 0)
1114 print_subtlv_rmt_ipaddr(&buf
, 4, &mtc
->rmt_ipaddr
);
1116 print_subtlv_max_bw(&buf
, 4, &mtc
->max_bw
);
1117 print_subtlv_max_rsv_bw(&buf
, 4, &mtc
->max_rsv_bw
);
1118 print_subtlv_unrsv_bw(&buf
, 4, &mtc
->unrsv_bw
);
1119 print_subtlv_te_metric(&buf
, 4, &mtc
->te_metric
);
1121 if (IS_INTER_AS(mtc
->type
)) {
1122 if (SUBTLV_TYPE(mtc
->ras
) != 0)
1123 print_subtlv_ras(&buf
, 4, &mtc
->ras
);
1124 if (SUBTLV_TYPE(mtc
->rip
) != 0)
1125 print_subtlv_rip(&buf
, 4, &mtc
->rip
);
1128 print_subtlv_av_delay(&buf
, 4, &mtc
->av_delay
);
1129 print_subtlv_mm_delay(&buf
, 4, &mtc
->mm_delay
);
1130 print_subtlv_delay_var(&buf
, 4, &mtc
->delay_var
);
1131 print_subtlv_pkt_loss(&buf
, 4, &mtc
->pkt_loss
);
1132 print_subtlv_res_bw(&buf
, 4, &mtc
->res_bw
);
1133 print_subtlv_ava_bw(&buf
, 4, &mtc
->ava_bw
);
1134 print_subtlv_use_bw(&buf
, 4, &mtc
->use_bw
);
1136 vty_multiline(vty
, "", "%s", sbuf_buf(&buf
));
1137 vty_out(vty
, "---------------\n\n");
1143 DEFUN (show_isis_mpls_te_interface
,
1144 show_isis_mpls_te_interface_cmd
,
1145 "show " PROTO_NAME
" mpls-te interface [INTERFACE]",
1149 "Interface information\n"
1152 struct listnode
*anode
, *cnode
;
1153 struct isis_area
*area
;
1154 struct isis_circuit
*circuit
;
1155 struct interface
*ifp
;
1156 int idx_interface
= 4;
1159 vty_out(vty
, "IS-IS Routing Process not enabled\n");
1163 if (argc
== idx_interface
) {
1164 /* Show All Interfaces. */
1165 for (ALL_LIST_ELEMENTS_RO(isis
->area_list
, anode
, area
)) {
1167 if (!IS_MPLS_TE(area
->mta
))
1170 vty_out(vty
, "Area %s:\n", area
->area_tag
);
1172 for (ALL_LIST_ELEMENTS_RO(area
->circuit_list
, cnode
,
1174 show_mpls_te_sub(vty
, circuit
->interface
->name
,
1178 /* Interface name is specified. */
1179 ifp
= if_lookup_by_name(argv
[idx_interface
]->arg
, VRF_DEFAULT
);
1181 vty_out(vty
, "No such interface name\n");
1183 circuit
= circuit_scan_by_ifp(ifp
);
1186 "ISIS is not enabled on circuit %s\n",
1189 show_mpls_te_sub(vty
, ifp
->name
, circuit
->mtc
);
1197 /* Initialize MPLS_TE */
1198 void isis_mpls_te_init(void)
1202 /* Register new VTY commands */
1203 install_element(VIEW_NODE
, &show_isis_mpls_te_router_cmd
);
1204 install_element(VIEW_NODE
, &show_isis_mpls_te_interface_cmd
);