]> git.proxmox.com Git - mirror_frr.git/blame - isisd/isis_te.c
lib: enforce vrf_name_to_id by returning default_vrf when name is null
[mirror_frr.git] / isisd / isis_te.c
CommitLineData
f8c06e2c
OD
1/*
2 * IS-IS Rout(e)ing protocol - isis_te.c
3 *
68558b13 4 * This is an implementation of RFC5305 & RFC 7810
f8c06e2c
OD
5 *
6 * Copyright (C) 2014 Orange Labs
7 * http://www.orange.com
8 *
9 * This file is part of GNU Zebra.
10 *
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
14 * later version.
15 *
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.
20 *
896014f4
DL
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
f8c06e2c
OD
24 */
25
26#include <zebra.h>
27#include <math.h>
28
29#include "linklist.h"
30#include "thread.h"
31#include "vty.h"
32#include "stream.h"
33#include "memory.h"
34#include "log.h"
35#include "prefix.h"
36#include "command.h"
37#include "hash.h"
38#include "if.h"
39#include "vrf.h"
40#include "checksum.h"
41#include "md5.h"
42#include "sockunion.h"
43#include "network.h"
af8ac8f9 44#include "sbuf.h"
f8c06e2c
OD
45
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"
f8c06e2c
OD
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"
60
61/* Global varial for MPLS TE management */
62struct isis_mpls_te isisMplsTE;
63
d62a17ae 64const char *mode2text[] = {"Disable", "Area", "AS", "Emulate"};
f8c06e2c
OD
65
66/*------------------------------------------------------------------------*
67 * Followings are control functions for MPLS-TE parameters management.
68 *------------------------------------------------------------------------*/
69
f8c06e2c 70/* Create new MPLS TE Circuit context */
d62a17ae 71struct mpls_te_circuit *mpls_te_circuit_new()
f8c06e2c 72{
d62a17ae 73 struct mpls_te_circuit *mtc;
f8c06e2c 74
d62a17ae 75 zlog_debug("ISIS MPLS-TE: Create new MPLS TE Circuit context");
f8c06e2c 76
d62a17ae 77 mtc = XCALLOC(MTYPE_ISIS_MPLS_TE, sizeof(struct mpls_te_circuit));
f8c06e2c 78
d62a17ae 79 mtc->status = disable;
80 mtc->type = STD_TE;
81 mtc->length = 0;
f8c06e2c 82
d62a17ae 83 return mtc;
f8c06e2c
OD
84}
85
d62a17ae 86/* Copy SUB TLVs parameters into a buffer - No space verification are performed
87 */
f8c06e2c 88/* Caller must verify before that there is enough free space in the buffer */
af8ac8f9 89uint8_t add_te_subtlvs(uint8_t *buf, struct mpls_te_circuit *mtc)
f8c06e2c 90{
af8ac8f9 91 uint8_t size, *tlvs = buf;
d62a17ae 92
93 zlog_debug("ISIS MPLS-TE: Add TE Sub TLVs to buffer");
94
95 if (mtc == NULL) {
96 zlog_debug(
97 "ISIS MPLS-TE: Abort! No MPLS TE Circuit available has been specified");
98 return 0;
99 }
100
101 /* Create buffer if not provided */
102 if (buf == NULL) {
103 zlog_debug("ISIS MPLS-TE: Abort! No Buffer has been specified");
104 return 0;
105 }
106
107 /* TE_SUBTLV_ADMIN_GRP */
108 if (SUBTLV_TYPE(mtc->admin_grp) != 0) {
109 size = SUBTLV_SIZE(&(mtc->admin_grp.header));
110 memcpy(tlvs, &(mtc->admin_grp), size);
111 tlvs += size;
112 }
113
114 /* TE_SUBTLV_LLRI */
115 if (SUBTLV_TYPE(mtc->llri) != 0) {
116 size = SUBTLV_SIZE(&(mtc->llri.header));
117 memcpy(tlvs, &(mtc->llri), size);
118 tlvs += size;
119 }
120
121 /* TE_SUBTLV_LCLIF_IPADDR */
122 if (SUBTLV_TYPE(mtc->local_ipaddr) != 0) {
123 size = SUBTLV_SIZE(&(mtc->local_ipaddr.header));
124 memcpy(tlvs, &(mtc->local_ipaddr), size);
125 tlvs += size;
126 }
127
128 /* TE_SUBTLV_RMTIF_IPADDR */
129 if (SUBTLV_TYPE(mtc->rmt_ipaddr) != 0) {
130 size = SUBTLV_SIZE(&(mtc->rmt_ipaddr.header));
131 memcpy(tlvs, &(mtc->rmt_ipaddr), size);
132 tlvs += size;
133 }
134
135 /* TE_SUBTLV_MAX_BW */
136 if (SUBTLV_TYPE(mtc->max_bw) != 0) {
137 size = SUBTLV_SIZE(&(mtc->max_bw.header));
138 memcpy(tlvs, &(mtc->max_bw), size);
139 tlvs += size;
140 }
141
142 /* TE_SUBTLV_MAX_RSV_BW */
143 if (SUBTLV_TYPE(mtc->max_rsv_bw) != 0) {
144 size = SUBTLV_SIZE(&(mtc->max_rsv_bw.header));
145 memcpy(tlvs, &(mtc->max_rsv_bw), size);
146 tlvs += size;
147 }
148
149 /* TE_SUBTLV_UNRSV_BW */
150 if (SUBTLV_TYPE(mtc->unrsv_bw) != 0) {
151 size = SUBTLV_SIZE(&(mtc->unrsv_bw.header));
152 memcpy(tlvs, &(mtc->unrsv_bw), size);
153 tlvs += size;
154 }
155
156 /* TE_SUBTLV_TE_METRIC */
157 if (SUBTLV_TYPE(mtc->te_metric) != 0) {
158 size = SUBTLV_SIZE(&(mtc->te_metric.header));
159 memcpy(tlvs, &(mtc->te_metric), size);
160 tlvs += size;
161 }
162
163 /* TE_SUBTLV_AV_DELAY */
164 if (SUBTLV_TYPE(mtc->av_delay) != 0) {
165 size = SUBTLV_SIZE(&(mtc->av_delay.header));
166 memcpy(tlvs, &(mtc->av_delay), size);
167 tlvs += size;
168 }
169
170 /* TE_SUBTLV_MM_DELAY */
171 if (SUBTLV_TYPE(mtc->mm_delay) != 0) {
172 size = SUBTLV_SIZE(&(mtc->mm_delay.header));
173 memcpy(tlvs, &(mtc->mm_delay), size);
174 tlvs += size;
175 }
176
177 /* TE_SUBTLV_DELAY_VAR */
178 if (SUBTLV_TYPE(mtc->delay_var) != 0) {
179 size = SUBTLV_SIZE(&(mtc->delay_var.header));
180 memcpy(tlvs, &(mtc->delay_var), size);
181 tlvs += size;
182 }
183
184 /* TE_SUBTLV_PKT_LOSS */
185 if (SUBTLV_TYPE(mtc->pkt_loss) != 0) {
186 size = SUBTLV_SIZE(&(mtc->pkt_loss.header));
187 memcpy(tlvs, &(mtc->pkt_loss), size);
188 tlvs += size;
189 }
190
191 /* TE_SUBTLV_RES_BW */
192 if (SUBTLV_TYPE(mtc->res_bw) != 0) {
193 size = SUBTLV_SIZE(&(mtc->res_bw.header));
194 memcpy(tlvs, &(mtc->res_bw), size);
195 tlvs += size;
196 }
197
198 /* TE_SUBTLV_AVA_BW */
199 if (SUBTLV_TYPE(mtc->ava_bw) != 0) {
200 size = SUBTLV_SIZE(&(mtc->ava_bw.header));
201 memcpy(tlvs, &(mtc->ava_bw), size);
202 tlvs += size;
203 }
204
205 /* TE_SUBTLV_USE_BW */
206 if (SUBTLV_TYPE(mtc->use_bw) != 0) {
207 size = SUBTLV_SIZE(&(mtc->use_bw.header));
208 memcpy(tlvs, &(mtc->use_bw), size);
209 tlvs += size;
210 }
211
9c5e2b4f
VJ
212 /* Add before this line any other parsing of TLV */
213 (void)tlvs;
214
d62a17ae 215 /* Update SubTLVs length */
216 mtc->length = subtlvs_len(mtc);
217
218 zlog_debug("ISIS MPLS-TE: Add %d bytes length SubTLVs", mtc->length);
219
220 return mtc->length;
f8c06e2c
OD
221}
222
223/* Compute total Sub-TLVs size */
af8ac8f9 224uint8_t subtlvs_len(struct mpls_te_circuit *mtc)
f8c06e2c 225{
d62a17ae 226 int length = 0;
f8c06e2c 227
d62a17ae 228 /* Sanity Check */
229 if (mtc == NULL)
230 return 0;
f8c06e2c 231
d62a17ae 232 /* TE_SUBTLV_ADMIN_GRP */
233 if (SUBTLV_TYPE(mtc->admin_grp) != 0)
234 length += SUBTLV_SIZE(&(mtc->admin_grp.header));
f8c06e2c 235
d62a17ae 236 /* TE_SUBTLV_LLRI */
237 if (SUBTLV_TYPE(mtc->llri) != 0)
238 length += SUBTLV_SIZE(&mtc->llri.header);
f8c06e2c 239
d62a17ae 240 /* TE_SUBTLV_LCLIF_IPADDR */
241 if (SUBTLV_TYPE(mtc->local_ipaddr) != 0)
242 length += SUBTLV_SIZE(&mtc->local_ipaddr.header);
f8c06e2c 243
d62a17ae 244 /* TE_SUBTLV_RMTIF_IPADDR */
245 if (SUBTLV_TYPE(mtc->rmt_ipaddr) != 0)
246 length += SUBTLV_SIZE(&mtc->rmt_ipaddr.header);
f8c06e2c 247
d62a17ae 248 /* TE_SUBTLV_MAX_BW */
249 if (SUBTLV_TYPE(mtc->max_bw) != 0)
250 length += SUBTLV_SIZE(&mtc->max_bw.header);
f8c06e2c 251
d62a17ae 252 /* TE_SUBTLV_MAX_RSV_BW */
253 if (SUBTLV_TYPE(mtc->max_rsv_bw) != 0)
254 length += SUBTLV_SIZE(&mtc->max_rsv_bw.header);
f8c06e2c 255
d62a17ae 256 /* TE_SUBTLV_UNRSV_BW */
257 if (SUBTLV_TYPE(mtc->unrsv_bw) != 0)
258 length += SUBTLV_SIZE(&mtc->unrsv_bw.header);
f8c06e2c 259
d62a17ae 260 /* TE_SUBTLV_TE_METRIC */
261 if (SUBTLV_TYPE(mtc->te_metric) != 0)
262 length += SUBTLV_SIZE(&mtc->te_metric.header);
f8c06e2c 263
d62a17ae 264 /* TE_SUBTLV_AV_DELAY */
265 if (SUBTLV_TYPE(mtc->av_delay) != 0)
266 length += SUBTLV_SIZE(&mtc->av_delay.header);
f8c06e2c 267
d62a17ae 268 /* TE_SUBTLV_MM_DELAY */
269 if (SUBTLV_TYPE(mtc->mm_delay) != 0)
270 length += SUBTLV_SIZE(&mtc->mm_delay.header);
f8c06e2c 271
d62a17ae 272 /* TE_SUBTLV_DELAY_VAR */
273 if (SUBTLV_TYPE(mtc->delay_var) != 0)
274 length += SUBTLV_SIZE(&mtc->delay_var.header);
f8c06e2c 275
d62a17ae 276 /* TE_SUBTLV_PKT_LOSS */
277 if (SUBTLV_TYPE(mtc->pkt_loss) != 0)
278 length += SUBTLV_SIZE(&mtc->pkt_loss.header);
f8c06e2c 279
d62a17ae 280 /* TE_SUBTLV_RES_BW */
281 if (SUBTLV_TYPE(mtc->res_bw) != 0)
282 length += SUBTLV_SIZE(&mtc->res_bw.header);
f8c06e2c 283
d62a17ae 284 /* TE_SUBTLV_AVA_BW */
285 if (SUBTLV_TYPE(mtc->ava_bw) != 0)
286 length += SUBTLV_SIZE(&mtc->ava_bw.header);
f8c06e2c 287
d62a17ae 288 /* TE_SUBTLV_USE_BW */
289 if (SUBTLV_TYPE(mtc->use_bw) != 0)
290 length += SUBTLV_SIZE(&mtc->use_bw.header);
f8c06e2c 291
d62a17ae 292 /* Check that length is lower than the MAXIMUM SUBTLV size i.e. 256 */
293 if (length > MAX_SUBTLV_SIZE) {
294 mtc->length = 0;
295 return 0;
296 }
f8c06e2c 297
af8ac8f9 298 mtc->length = (uint8_t)length;
f8c06e2c 299
d62a17ae 300 return mtc->length;
f8c06e2c
OD
301}
302
303/* Following are various functions to set MPLS TE parameters */
d62a17ae 304static void set_circuitparams_admin_grp(struct mpls_te_circuit *mtc,
d7c0a89a 305 uint32_t admingrp)
f8c06e2c 306{
d62a17ae 307 SUBTLV_TYPE(mtc->admin_grp) = TE_SUBTLV_ADMIN_GRP;
308 SUBTLV_LEN(mtc->admin_grp) = SUBTLV_DEF_SIZE;
309 mtc->admin_grp.value = htonl(admingrp);
310 return;
f8c06e2c
OD
311}
312
d62a17ae 313static void __attribute__((unused))
d7c0a89a
QY
314set_circuitparams_llri(struct mpls_te_circuit *mtc, uint32_t local,
315 uint32_t remote)
f8c06e2c 316{
d62a17ae 317 SUBTLV_TYPE(mtc->llri) = TE_SUBTLV_LLRI;
318 SUBTLV_LEN(mtc->llri) = TE_SUBTLV_LLRI_SIZE;
319 mtc->llri.local = htonl(local);
320 mtc->llri.remote = htonl(remote);
f8c06e2c
OD
321}
322
d62a17ae 323void set_circuitparams_local_ipaddr(struct mpls_te_circuit *mtc,
324 struct in_addr addr)
f8c06e2c
OD
325{
326
d62a17ae 327 SUBTLV_TYPE(mtc->local_ipaddr) = TE_SUBTLV_LOCAL_IPADDR;
328 SUBTLV_LEN(mtc->local_ipaddr) = SUBTLV_DEF_SIZE;
329 mtc->local_ipaddr.value.s_addr = addr.s_addr;
330 return;
f8c06e2c
OD
331}
332
d62a17ae 333void set_circuitparams_rmt_ipaddr(struct mpls_te_circuit *mtc,
334 struct in_addr addr)
f8c06e2c
OD
335{
336
d62a17ae 337 SUBTLV_TYPE(mtc->rmt_ipaddr) = TE_SUBTLV_RMT_IPADDR;
338 SUBTLV_LEN(mtc->rmt_ipaddr) = SUBTLV_DEF_SIZE;
339 mtc->rmt_ipaddr.value.s_addr = addr.s_addr;
340 return;
f8c06e2c
OD
341}
342
d62a17ae 343static void set_circuitparams_max_bw(struct mpls_te_circuit *mtc, float fp)
f8c06e2c 344{
d62a17ae 345 SUBTLV_TYPE(mtc->max_bw) = TE_SUBTLV_MAX_BW;
346 SUBTLV_LEN(mtc->max_bw) = SUBTLV_DEF_SIZE;
347 mtc->max_bw.value = htonf(fp);
348 return;
f8c06e2c
OD
349}
350
d62a17ae 351static void set_circuitparams_max_rsv_bw(struct mpls_te_circuit *mtc, float fp)
f8c06e2c 352{
d62a17ae 353 SUBTLV_TYPE(mtc->max_rsv_bw) = TE_SUBTLV_MAX_RSV_BW;
354 SUBTLV_LEN(mtc->max_rsv_bw) = SUBTLV_DEF_SIZE;
355 mtc->max_rsv_bw.value = htonf(fp);
356 return;
f8c06e2c
OD
357}
358
d62a17ae 359static void set_circuitparams_unrsv_bw(struct mpls_te_circuit *mtc,
360 int priority, float fp)
f8c06e2c 361{
d62a17ae 362 /* Note that TLV-length field is the size of array. */
363 SUBTLV_TYPE(mtc->unrsv_bw) = TE_SUBTLV_UNRSV_BW;
364 SUBTLV_LEN(mtc->unrsv_bw) = TE_SUBTLV_UNRSV_SIZE;
365 mtc->unrsv_bw.value[priority] = htonf(fp);
366 return;
f8c06e2c
OD
367}
368
d62a17ae 369static void set_circuitparams_te_metric(struct mpls_te_circuit *mtc,
d7c0a89a 370 uint32_t te_metric)
f8c06e2c 371{
d62a17ae 372 SUBTLV_TYPE(mtc->te_metric) = TE_SUBTLV_TE_METRIC;
373 SUBTLV_LEN(mtc->te_metric) = TE_SUBTLV_TE_METRIC_SIZE;
374 mtc->te_metric.value[0] = (te_metric >> 16) & 0xFF;
375 mtc->te_metric.value[1] = (te_metric >> 8) & 0xFF;
376 mtc->te_metric.value[2] = te_metric & 0xFF;
377 return;
f8c06e2c
OD
378}
379
d62a17ae 380static void set_circuitparams_inter_as(struct mpls_te_circuit *mtc,
d7c0a89a 381 struct in_addr addr, uint32_t as)
f8c06e2c
OD
382{
383
d62a17ae 384 /* Set the Remote ASBR IP address and then the associated AS number */
385 SUBTLV_TYPE(mtc->rip) = TE_SUBTLV_RIP;
386 SUBTLV_LEN(mtc->rip) = SUBTLV_DEF_SIZE;
387 mtc->rip.value.s_addr = addr.s_addr;
f8c06e2c 388
d62a17ae 389 SUBTLV_TYPE(mtc->ras) = TE_SUBTLV_RAS;
390 SUBTLV_LEN(mtc->ras) = SUBTLV_DEF_SIZE;
391 mtc->ras.value = htonl(as);
f8c06e2c
OD
392}
393
d62a17ae 394static void unset_circuitparams_inter_as(struct mpls_te_circuit *mtc)
f8c06e2c
OD
395{
396
d62a17ae 397 /* Reset the Remote ASBR IP address and then the associated AS number */
398 SUBTLV_TYPE(mtc->rip) = 0;
399 SUBTLV_LEN(mtc->rip) = 0;
400 mtc->rip.value.s_addr = 0;
f8c06e2c 401
d62a17ae 402 SUBTLV_TYPE(mtc->ras) = 0;
403 SUBTLV_LEN(mtc->ras) = 0;
404 mtc->ras.value = 0;
f8c06e2c
OD
405}
406
d62a17ae 407static void set_circuitparams_av_delay(struct mpls_te_circuit *mtc,
d7c0a89a 408 uint32_t delay, uint8_t anormal)
f8c06e2c 409{
d7c0a89a 410 uint32_t tmp;
d62a17ae 411 /* Note that TLV-length field is the size of array. */
412 SUBTLV_TYPE(mtc->av_delay) = TE_SUBTLV_AV_DELAY;
413 SUBTLV_LEN(mtc->av_delay) = SUBTLV_DEF_SIZE;
414 tmp = delay & TE_EXT_MASK;
415 if (anormal)
416 tmp |= TE_EXT_ANORMAL;
417 mtc->av_delay.value = htonl(tmp);
418 return;
f8c06e2c
OD
419}
420
d62a17ae 421static void set_circuitparams_mm_delay(struct mpls_te_circuit *mtc,
d7c0a89a
QY
422 uint32_t low, uint32_t high,
423 uint8_t anormal)
f8c06e2c 424{
d7c0a89a 425 uint32_t tmp;
d62a17ae 426 /* Note that TLV-length field is the size of array. */
427 SUBTLV_TYPE(mtc->mm_delay) = TE_SUBTLV_MM_DELAY;
428 SUBTLV_LEN(mtc->mm_delay) = TE_SUBTLV_MM_DELAY_SIZE;
429 tmp = low & TE_EXT_MASK;
430 if (anormal)
431 tmp |= TE_EXT_ANORMAL;
432 mtc->mm_delay.low = htonl(tmp);
433 mtc->mm_delay.high = htonl(high);
434 return;
f8c06e2c
OD
435}
436
d62a17ae 437static void set_circuitparams_delay_var(struct mpls_te_circuit *mtc,
d7c0a89a 438 uint32_t jitter)
f8c06e2c 439{
d62a17ae 440 /* Note that TLV-length field is the size of array. */
441 SUBTLV_TYPE(mtc->delay_var) = TE_SUBTLV_DELAY_VAR;
442 SUBTLV_LEN(mtc->delay_var) = SUBTLV_DEF_SIZE;
443 mtc->delay_var.value = htonl(jitter & TE_EXT_MASK);
444 return;
f8c06e2c
OD
445}
446
d62a17ae 447static void set_circuitparams_pkt_loss(struct mpls_te_circuit *mtc,
d7c0a89a 448 uint32_t loss, uint8_t anormal)
f8c06e2c 449{
d7c0a89a 450 uint32_t tmp;
d62a17ae 451 /* Note that TLV-length field is the size of array. */
452 SUBTLV_TYPE(mtc->pkt_loss) = TE_SUBTLV_PKT_LOSS;
453 SUBTLV_LEN(mtc->pkt_loss) = SUBTLV_DEF_SIZE;
454 tmp = loss & TE_EXT_MASK;
455 if (anormal)
456 tmp |= TE_EXT_ANORMAL;
457 mtc->pkt_loss.value = htonl(tmp);
458 return;
f8c06e2c
OD
459}
460
d62a17ae 461static void set_circuitparams_res_bw(struct mpls_te_circuit *mtc, float fp)
f8c06e2c 462{
d62a17ae 463 /* Note that TLV-length field is the size of array. */
464 SUBTLV_TYPE(mtc->res_bw) = TE_SUBTLV_RES_BW;
465 SUBTLV_LEN(mtc->res_bw) = SUBTLV_DEF_SIZE;
466 mtc->res_bw.value = htonf(fp);
467 return;
f8c06e2c
OD
468}
469
d62a17ae 470static void set_circuitparams_ava_bw(struct mpls_te_circuit *mtc, float fp)
f8c06e2c 471{
d62a17ae 472 /* Note that TLV-length field is the size of array. */
473 SUBTLV_TYPE(mtc->ava_bw) = TE_SUBTLV_AVA_BW;
474 SUBTLV_LEN(mtc->ava_bw) = SUBTLV_DEF_SIZE;
475 mtc->ava_bw.value = htonf(fp);
476 return;
f8c06e2c
OD
477}
478
d62a17ae 479static void set_circuitparams_use_bw(struct mpls_te_circuit *mtc, float fp)
f8c06e2c 480{
d62a17ae 481 /* Note that TLV-length field is the size of array. */
482 SUBTLV_TYPE(mtc->use_bw) = TE_SUBTLV_USE_BW;
483 SUBTLV_LEN(mtc->use_bw) = SUBTLV_DEF_SIZE;
484 mtc->use_bw.value = htonf(fp);
485 return;
f8c06e2c
OD
486}
487
488/* Main initialization / update function of the MPLS TE Circuit context */
489/* Call when interface TE Link parameters are modified */
d62a17ae 490void isis_link_params_update(struct isis_circuit *circuit,
491 struct interface *ifp)
f8c06e2c 492{
d62a17ae 493 int i;
494 struct prefix_ipv4 *addr;
495 struct mpls_te_circuit *mtc;
496
497 /* Sanity Check */
498 if ((circuit == NULL) || (ifp == NULL))
499 return;
500
501 zlog_info("MPLS-TE: Initialize circuit parameters for interface %s",
502 ifp->name);
503
504 /* Check if MPLS TE Circuit context has not been already created */
505 if (circuit->mtc == NULL)
506 circuit->mtc = mpls_te_circuit_new();
507
508 mtc = circuit->mtc;
509
510 /* Fulfil MTC TLV from ifp TE Link parameters */
511 if (HAS_LINK_PARAMS(ifp)) {
512 mtc->status = enable;
513 /* STD_TE metrics */
514 if (IS_PARAM_SET(ifp->link_params, LP_ADM_GRP))
515 set_circuitparams_admin_grp(
516 mtc, ifp->link_params->admin_grp);
517 else
518 SUBTLV_TYPE(mtc->admin_grp) = 0;
519
520 /* If not already set, register local IP addr from ip_addr list
521 * if it exists */
522 if (SUBTLV_TYPE(mtc->local_ipaddr) == 0) {
523 if (circuit->ip_addrs != NULL
524 && listcount(circuit->ip_addrs) != 0) {
525 addr = (struct prefix_ipv4 *)listgetdata(
526 (struct listnode *)listhead(
527 circuit->ip_addrs));
528 set_circuitparams_local_ipaddr(mtc,
529 addr->prefix);
530 }
531 }
532
533 /* If not already set, try to determine Remote IP addr if
534 * circuit is P2P */
535 if ((SUBTLV_TYPE(mtc->rmt_ipaddr) == 0)
536 && (circuit->circ_type == CIRCUIT_T_P2P)) {
537 struct isis_adjacency *adj = circuit->u.p2p.neighbor;
44b89511
CF
538 if (adj && adj->adj_state == ISIS_ADJ_UP
539 && adj->ipv4_address_count) {
0c1bd758
CF
540 set_circuitparams_rmt_ipaddr(
541 mtc, adj->ipv4_addresses[0]);
d62a17ae 542 }
543 }
544
545 if (IS_PARAM_SET(ifp->link_params, LP_MAX_BW))
546 set_circuitparams_max_bw(mtc, ifp->link_params->max_bw);
547 else
548 SUBTLV_TYPE(mtc->max_bw) = 0;
549
550 if (IS_PARAM_SET(ifp->link_params, LP_MAX_RSV_BW))
551 set_circuitparams_max_rsv_bw(
552 mtc, ifp->link_params->max_rsv_bw);
553 else
554 SUBTLV_TYPE(mtc->max_rsv_bw) = 0;
555
556 if (IS_PARAM_SET(ifp->link_params, LP_UNRSV_BW))
557 for (i = 0; i < MAX_CLASS_TYPE; i++)
558 set_circuitparams_unrsv_bw(
559 mtc, i, ifp->link_params->unrsv_bw[i]);
560 else
561 SUBTLV_TYPE(mtc->unrsv_bw) = 0;
562
563 if (IS_PARAM_SET(ifp->link_params, LP_TE_METRIC))
564 set_circuitparams_te_metric(
565 mtc, ifp->link_params->te_metric);
566 else
567 SUBTLV_TYPE(mtc->te_metric) = 0;
568
569 /* TE metric Extensions */
570 if (IS_PARAM_SET(ifp->link_params, LP_DELAY))
571 set_circuitparams_av_delay(
572 mtc, ifp->link_params->av_delay, 0);
573 else
574 SUBTLV_TYPE(mtc->av_delay) = 0;
575
576 if (IS_PARAM_SET(ifp->link_params, LP_MM_DELAY))
577 set_circuitparams_mm_delay(
578 mtc, ifp->link_params->min_delay,
579 ifp->link_params->max_delay, 0);
580 else
581 SUBTLV_TYPE(mtc->mm_delay) = 0;
582
583 if (IS_PARAM_SET(ifp->link_params, LP_DELAY_VAR))
584 set_circuitparams_delay_var(
585 mtc, ifp->link_params->delay_var);
586 else
587 SUBTLV_TYPE(mtc->delay_var) = 0;
588
589 if (IS_PARAM_SET(ifp->link_params, LP_PKT_LOSS))
590 set_circuitparams_pkt_loss(
591 mtc, ifp->link_params->pkt_loss, 0);
592 else
593 SUBTLV_TYPE(mtc->pkt_loss) = 0;
594
595 if (IS_PARAM_SET(ifp->link_params, LP_RES_BW))
596 set_circuitparams_res_bw(mtc, ifp->link_params->res_bw);
597 else
598 SUBTLV_TYPE(mtc->res_bw) = 0;
599
600 if (IS_PARAM_SET(ifp->link_params, LP_AVA_BW))
601 set_circuitparams_ava_bw(mtc, ifp->link_params->ava_bw);
602 else
603 SUBTLV_TYPE(mtc->ava_bw) = 0;
604
605 if (IS_PARAM_SET(ifp->link_params, LP_USE_BW))
606 set_circuitparams_use_bw(mtc, ifp->link_params->use_bw);
607 else
608 SUBTLV_TYPE(mtc->use_bw) = 0;
609
610 /* INTER_AS */
611 if (IS_PARAM_SET(ifp->link_params, LP_RMT_AS))
612 set_circuitparams_inter_as(mtc,
613 ifp->link_params->rmt_ip,
614 ifp->link_params->rmt_as);
615 else
616 /* reset inter-as TE params */
617 unset_circuitparams_inter_as(mtc);
618
619 /* Compute total length of SUB TLVs */
620 mtc->length = subtlvs_len(mtc);
621
622 } else
623 mtc->status = disable;
624
625/* Finally Update LSP */
f8c06e2c
OD
626#if 0
627 if (IS_MPLS_TE(isisMplsTE) && circuit->area)
628 lsp_regenerate_schedule (circuit->area, circuit->is_type, 0);
629#endif
d62a17ae 630 return;
f8c06e2c
OD
631}
632
d62a17ae 633void isis_mpls_te_update(struct interface *ifp)
f8c06e2c 634{
d62a17ae 635 struct isis_circuit *circuit;
f8c06e2c 636
d62a17ae 637 /* Sanity Check */
638 if (ifp == NULL)
639 return;
f8c06e2c 640
d62a17ae 641 /* Get circuit context from interface */
642 if ((circuit = circuit_scan_by_ifp(ifp)) == NULL)
643 return;
f8c06e2c 644
d62a17ae 645 /* Update TE TLVs ... */
646 isis_link_params_update(circuit, ifp);
f8c06e2c 647
d62a17ae 648 /* ... and LSP */
649 if (IS_MPLS_TE(isisMplsTE) && circuit->area)
650 lsp_regenerate_schedule(circuit->area, circuit->is_type, 0);
f8c06e2c 651
d62a17ae 652 return;
f8c06e2c
OD
653}
654
655/*------------------------------------------------------------------------*
656 * Followings are vty session control functions.
657 *------------------------------------------------------------------------*/
658
d7c0a89a
QY
659static uint8_t print_subtlv_admin_grp(struct sbuf *buf, int indent,
660 struct te_subtlv_admin_grp *tlv)
f8c06e2c 661{
af8ac8f9
CF
662 sbuf_push(buf, indent, "Administrative Group: 0x%" PRIx32 "\n",
663 ntohl(tlv->value));
d62a17ae 664 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
665}
666
d7c0a89a
QY
667static uint8_t print_subtlv_llri(struct sbuf *buf, int indent,
668 struct te_subtlv_llri *tlv)
f8c06e2c 669{
af8ac8f9
CF
670 sbuf_push(buf, indent, "Link Local ID: %" PRIu32 "\n",
671 ntohl(tlv->local));
672 sbuf_push(buf, indent, "Link Remote ID: %" PRIu32 "\n",
673 ntohl(tlv->remote));
d62a17ae 674
675 return (SUBTLV_HDR_SIZE + TE_SUBTLV_LLRI_SIZE);
f8c06e2c
OD
676}
677
d7c0a89a
QY
678static uint8_t print_subtlv_local_ipaddr(struct sbuf *buf, int indent,
679 struct te_subtlv_local_ipaddr *tlv)
f8c06e2c 680{
af8ac8f9
CF
681 sbuf_push(buf, indent, "Local Interface IP Address(es): %s\n",
682 inet_ntoa(tlv->value));
d62a17ae 683
684 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
685}
686
d7c0a89a
QY
687static uint8_t print_subtlv_rmt_ipaddr(struct sbuf *buf, int indent,
688 struct te_subtlv_rmt_ipaddr *tlv)
f8c06e2c 689{
af8ac8f9
CF
690 sbuf_push(buf, indent, "Remote Interface IP Address(es): %s\n",
691 inet_ntoa(tlv->value));
d62a17ae 692
693 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
694}
695
d7c0a89a
QY
696static uint8_t print_subtlv_max_bw(struct sbuf *buf, int indent,
697 struct te_subtlv_max_bw *tlv)
f8c06e2c 698{
d62a17ae 699 float fval;
f8c06e2c 700
d62a17ae 701 fval = ntohf(tlv->value);
f8c06e2c 702
af8ac8f9 703 sbuf_push(buf, indent, "Maximum Bandwidth: %g (Bytes/sec)\n", fval);
f8c06e2c 704
d62a17ae 705 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
706}
707
d7c0a89a
QY
708static uint8_t print_subtlv_max_rsv_bw(struct sbuf *buf, int indent,
709 struct te_subtlv_max_rsv_bw *tlv)
f8c06e2c 710{
d62a17ae 711 float fval;
f8c06e2c 712
d62a17ae 713 fval = ntohf(tlv->value);
f8c06e2c 714
996c9314
LB
715 sbuf_push(buf, indent, "Maximum Reservable Bandwidth: %g (Bytes/sec)\n",
716 fval);
f8c06e2c 717
d62a17ae 718 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
719}
720
d7c0a89a
QY
721static uint8_t print_subtlv_unrsv_bw(struct sbuf *buf, int indent,
722 struct te_subtlv_unrsv_bw *tlv)
f8c06e2c 723{
d62a17ae 724 float fval1, fval2;
725 int i;
726
af8ac8f9 727 sbuf_push(buf, indent, "Unreserved Bandwidth:\n");
d62a17ae 728
729 for (i = 0; i < MAX_CLASS_TYPE; i += 2) {
730 fval1 = ntohf(tlv->value[i]);
731 fval2 = ntohf(tlv->value[i + 1]);
996c9314
LB
732 sbuf_push(buf, indent + 2,
733 "[%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n", i,
734 fval1, i + 1, fval2);
d62a17ae 735 }
736
737 return (SUBTLV_HDR_SIZE + TE_SUBTLV_UNRSV_SIZE);
f8c06e2c
OD
738}
739
d7c0a89a
QY
740static uint8_t print_subtlv_te_metric(struct sbuf *buf, int indent,
741 struct te_subtlv_te_metric *tlv)
f8c06e2c 742{
d7c0a89a 743 uint32_t te_metric;
f8c06e2c 744
d62a17ae 745 te_metric = tlv->value[2] | tlv->value[1] << 8 | tlv->value[0] << 16;
af8ac8f9 746 sbuf_push(buf, indent, "Traffic Engineering Metric: %u\n", te_metric);
f8c06e2c 747
d62a17ae 748 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
749}
750
d7c0a89a
QY
751static uint8_t print_subtlv_ras(struct sbuf *buf, int indent,
752 struct te_subtlv_ras *tlv)
f8c06e2c 753{
af8ac8f9
CF
754 sbuf_push(buf, indent, "Inter-AS TE Remote AS number: %" PRIu32 "\n",
755 ntohl(tlv->value));
d62a17ae 756
757 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
758}
759
d7c0a89a
QY
760static uint8_t print_subtlv_rip(struct sbuf *buf, int indent,
761 struct te_subtlv_rip *tlv)
f8c06e2c 762{
af8ac8f9
CF
763 sbuf_push(buf, indent, "Inter-AS TE Remote ASBR IP address: %s\n",
764 inet_ntoa(tlv->value));
d62a17ae 765
766 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
767}
768
d7c0a89a
QY
769static uint8_t print_subtlv_av_delay(struct sbuf *buf, int indent,
770 struct te_subtlv_av_delay *tlv)
f8c06e2c 771{
d7c0a89a
QY
772 uint32_t delay;
773 uint32_t A;
f8c06e2c 774
d7c0a89a
QY
775 delay = (uint32_t)ntohl(tlv->value) & TE_EXT_MASK;
776 A = (uint32_t)ntohl(tlv->value) & TE_EXT_ANORMAL;
f8c06e2c 777
996c9314
LB
778 sbuf_push(buf, indent,
779 "%s Average Link Delay: %" PRIu32 " (micro-sec)\n",
af8ac8f9 780 A ? "Anomalous" : "Normal", delay);
f8c06e2c 781
d62a17ae 782 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
783}
784
d7c0a89a
QY
785static uint8_t print_subtlv_mm_delay(struct sbuf *buf, int indent,
786 struct te_subtlv_mm_delay *tlv)
f8c06e2c 787{
d7c0a89a
QY
788 uint32_t low, high;
789 uint32_t A;
f8c06e2c 790
d7c0a89a
QY
791 low = (uint32_t)ntohl(tlv->low) & TE_EXT_MASK;
792 A = (uint32_t)ntohl(tlv->low) & TE_EXT_ANORMAL;
793 high = (uint32_t)ntohl(tlv->high) & TE_EXT_MASK;
f8c06e2c 794
98c5bc15 795 sbuf_push(buf, indent, "%s Min/Max Link Delay: %" PRIu32 " / %" PRIu32 " (micro-sec)\n",
af8ac8f9 796 A ? "Anomalous" : "Normal", low, high);
f8c06e2c 797
d62a17ae 798 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
799}
800
d7c0a89a
QY
801static uint8_t print_subtlv_delay_var(struct sbuf *buf, int indent,
802 struct te_subtlv_delay_var *tlv)
f8c06e2c 803{
d7c0a89a 804 uint32_t jitter;
f8c06e2c 805
d7c0a89a 806 jitter = (uint32_t)ntohl(tlv->value) & TE_EXT_MASK;
f8c06e2c 807
996c9314
LB
808 sbuf_push(buf, indent, "Delay Variation: %" PRIu32 " (micro-sec)\n",
809 jitter);
f8c06e2c 810
d62a17ae 811 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
812}
813
d7c0a89a
QY
814static uint8_t print_subtlv_pkt_loss(struct sbuf *buf, int indent,
815 struct te_subtlv_pkt_loss *tlv)
f8c06e2c 816{
d7c0a89a
QY
817 uint32_t loss;
818 uint32_t A;
d62a17ae 819 float fval;
820
d7c0a89a 821 loss = (uint32_t)ntohl(tlv->value) & TE_EXT_MASK;
d62a17ae 822 fval = (float)(loss * LOSS_PRECISION);
d7c0a89a 823 A = (uint32_t)ntohl(tlv->value) & TE_EXT_ANORMAL;
d62a17ae 824
af8ac8f9
CF
825 sbuf_push(buf, indent, "%s Link Packet Loss: %g (%%)\n",
826 A ? "Anomalous" : "Normal", fval);
d62a17ae 827
828 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
829}
830
d7c0a89a
QY
831static uint8_t print_subtlv_res_bw(struct sbuf *buf, int indent,
832 struct te_subtlv_res_bw *tlv)
f8c06e2c 833{
d62a17ae 834 float fval;
f8c06e2c 835
d62a17ae 836 fval = ntohf(tlv->value);
f8c06e2c 837
996c9314
LB
838 sbuf_push(buf, indent,
839 "Unidirectional Residual Bandwidth: %g (Bytes/sec)\n", fval);
f8c06e2c 840
d62a17ae 841 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
842}
843
d7c0a89a
QY
844static uint8_t print_subtlv_ava_bw(struct sbuf *buf, int indent,
845 struct te_subtlv_ava_bw *tlv)
f8c06e2c 846{
d62a17ae 847 float fval;
f8c06e2c 848
d62a17ae 849 fval = ntohf(tlv->value);
f8c06e2c 850
996c9314
LB
851 sbuf_push(buf, indent,
852 "Unidirectional Available Bandwidth: %g (Bytes/sec)\n", fval);
f8c06e2c 853
d62a17ae 854 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
855}
856
d7c0a89a
QY
857static uint8_t print_subtlv_use_bw(struct sbuf *buf, int indent,
858 struct te_subtlv_use_bw *tlv)
f8c06e2c 859{
d62a17ae 860 float fval;
f8c06e2c 861
d62a17ae 862 fval = ntohf(tlv->value);
f8c06e2c 863
996c9314
LB
864 sbuf_push(buf, indent,
865 "Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n", fval);
f8c06e2c 866
d62a17ae 867 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
868}
869
d7c0a89a
QY
870static uint8_t print_unknown_tlv(struct sbuf *buf, int indent,
871 struct subtlv_header *tlvh)
f8c06e2c 872{
a2b6e694 873 int i, rtn;
d7c0a89a 874 uint8_t *v = (uint8_t *)tlvh;
d62a17ae 875
af8ac8f9
CF
876 if (tlvh->length != 0) {
877 sbuf_push(buf, indent,
878 "Unknown TLV: [type(%#.2x), length(%#.2x)]\n",
879 tlvh->type, tlvh->length);
880 sbuf_push(buf, indent + 2, "Dump: [00]");
881 rtn = 1; /* initialize end of line counter */
882 for (i = 0; i < tlvh->length; i++) {
883 sbuf_push(buf, 0, " %#.2x", v[i]);
884 if (rtn == 8) {
885 sbuf_push(buf, 0, "\n");
996c9314 886 sbuf_push(buf, indent + 8, "[%.2x]", i + 1);
af8ac8f9
CF
887 rtn = 1;
888 } else
889 rtn++;
890 }
891 sbuf_push(buf, 0, "\n");
d62a17ae 892 } else {
af8ac8f9
CF
893 sbuf_push(buf, indent,
894 "Unknown TLV: [type(%#.2x), length(%#.2x)]\n",
895 tlvh->type, tlvh->length);
d62a17ae 896 }
897
898 return SUBTLV_SIZE(tlvh);
f8c06e2c
OD
899}
900
901/* Main Show function */
98c5bc15
CF
902void mpls_te_print_detail(struct sbuf *buf, int indent,
903 uint8_t *subtlvs, uint8_t subtlv_len)
f8c06e2c 904{
af8ac8f9
CF
905 struct subtlv_header *tlvh = (struct subtlv_header *)subtlvs;
906 uint16_t sum = 0;
d62a17ae 907
27a470dc
CF
908 for (; sum < subtlv_len;
909 tlvh = (struct subtlv_header *)(subtlvs + sum)) {
910 if (subtlv_len - sum < SUBTLV_SIZE(tlvh)) {
911 sbuf_push(buf, indent, "Available data %" PRIu8 " is less than TLV size %u!\n",
912 subtlv_len - sum, SUBTLV_SIZE(tlvh));
913 return;
914 }
915
d62a17ae 916 switch (tlvh->type) {
917 case TE_SUBTLV_ADMIN_GRP:
27a470dc
CF
918 if (tlvh->length != SUBTLV_DEF_SIZE) {
919 sbuf_push(buf, indent, "TLV size does not match expected size for Administrative Group!\n");
920 return;
921 }
98c5bc15 922 sum += print_subtlv_admin_grp(buf, indent,
af8ac8f9 923 (struct te_subtlv_admin_grp *)tlvh);
d62a17ae 924 break;
925 case TE_SUBTLV_LLRI:
27a470dc
CF
926 if (tlvh->length != TE_SUBTLV_LLRI_SIZE) {
927 sbuf_push(buf, indent, "TLV size does not match expected size for Link ID!\n");
928 return;
929 }
af8ac8f9 930 sum += print_subtlv_llri(buf, indent,
996c9314 931 (struct te_subtlv_llri *)tlvh);
d62a17ae 932 break;
933 case TE_SUBTLV_LOCAL_IPADDR:
27a470dc
CF
934 if (tlvh->length != SUBTLV_DEF_SIZE) {
935 sbuf_push(buf, indent, "TLV size does not match expected size for Local IP address!\n");
936 return;
937 }
98c5bc15 938 sum += print_subtlv_local_ipaddr(buf, indent,
af8ac8f9 939 (struct te_subtlv_local_ipaddr *)tlvh);
d62a17ae 940 break;
941 case TE_SUBTLV_RMT_IPADDR:
27a470dc
CF
942 if (tlvh->length != SUBTLV_DEF_SIZE) {
943 sbuf_push(buf, indent, "TLV size does not match expected size for Remote Interface address!\n");
944 return;
945 }
98c5bc15 946 sum += print_subtlv_rmt_ipaddr(buf, indent,
af8ac8f9 947 (struct te_subtlv_rmt_ipaddr *)tlvh);
d62a17ae 948 break;
949 case TE_SUBTLV_MAX_BW:
27a470dc
CF
950 if (tlvh->length != SUBTLV_DEF_SIZE) {
951 sbuf_push(buf, indent, "TLV size does not match expected size for Maximum Bandwidth!\n");
952 return;
953 }
98c5bc15
CF
954 sum += print_subtlv_max_bw(buf, indent,
955 (struct te_subtlv_max_bw *)tlvh);
d62a17ae 956 break;
957 case TE_SUBTLV_MAX_RSV_BW:
27a470dc
CF
958 if (tlvh->length != SUBTLV_DEF_SIZE) {
959 sbuf_push(buf, indent, "TLV size does not match expected size for Maximum Reservable Bandwidth!\n");
960 return;
961 }
98c5bc15 962 sum += print_subtlv_max_rsv_bw(buf, indent,
af8ac8f9 963 (struct te_subtlv_max_rsv_bw *)tlvh);
d62a17ae 964 break;
965 case TE_SUBTLV_UNRSV_BW:
27a470dc
CF
966 if (tlvh->length != TE_SUBTLV_UNRSV_SIZE) {
967 sbuf_push(buf, indent, "TLV size does not match expected size for Unreserved Bandwidth!\n");
968 return;
969 }
98c5bc15
CF
970 sum += print_subtlv_unrsv_bw(buf, indent,
971 (struct te_subtlv_unrsv_bw *)tlvh);
d62a17ae 972 break;
973 case TE_SUBTLV_TE_METRIC:
27a470dc
CF
974 if (tlvh->length != SUBTLV_DEF_SIZE) {
975 sbuf_push(buf, indent, "TLV size does not match expected size for Traffic Engineering Metric!\n");
976 return;
977 }
98c5bc15 978 sum += print_subtlv_te_metric(buf, indent,
af8ac8f9 979 (struct te_subtlv_te_metric *)tlvh);
d62a17ae 980 break;
981 case TE_SUBTLV_RAS:
27a470dc
CF
982 if (tlvh->length != SUBTLV_DEF_SIZE) {
983 sbuf_push(buf, indent, "TLV size does not match expected size for Remote AS number!\n");
984 return;
985 }
af8ac8f9 986 sum += print_subtlv_ras(buf, indent,
996c9314 987 (struct te_subtlv_ras *)tlvh);
d62a17ae 988 break;
989 case TE_SUBTLV_RIP:
27a470dc
CF
990 if (tlvh->length != SUBTLV_DEF_SIZE) {
991 sbuf_push(buf, indent, "TLV size does not match expected size for Remote ASBR IP Address!\n");
992 return;
993 }
af8ac8f9 994 sum += print_subtlv_rip(buf, indent,
996c9314 995 (struct te_subtlv_rip *)tlvh);
d62a17ae 996 break;
997 case TE_SUBTLV_AV_DELAY:
27a470dc
CF
998 if (tlvh->length != SUBTLV_DEF_SIZE) {
999 sbuf_push(buf, indent, "TLV size does not match expected size for Average Link Delay!\n");
1000 return;
1001 }
98c5bc15
CF
1002 sum += print_subtlv_av_delay(buf, indent,
1003 (struct te_subtlv_av_delay *)tlvh);
d62a17ae 1004 break;
1005 case TE_SUBTLV_MM_DELAY:
27a470dc
CF
1006 if (tlvh->length != SUBTLV_DEF_SIZE) {
1007 sbuf_push(buf, indent, "TLV size does not match expected size for Min/Max Link Delay!\n");
1008 return;
1009 }
98c5bc15
CF
1010 sum += print_subtlv_mm_delay(buf, indent,
1011 (struct te_subtlv_mm_delay *)tlvh);
d62a17ae 1012 break;
1013 case TE_SUBTLV_DELAY_VAR:
27a470dc
CF
1014 if (tlvh->length != SUBTLV_DEF_SIZE) {
1015 sbuf_push(buf, indent, "TLV size does not match expected size for Delay Variation!\n");
1016 return;
1017 }
98c5bc15 1018 sum += print_subtlv_delay_var(buf, indent,
af8ac8f9 1019 (struct te_subtlv_delay_var *)tlvh);
d62a17ae 1020 break;
1021 case TE_SUBTLV_PKT_LOSS:
27a470dc
CF
1022 if (tlvh->length != SUBTLV_DEF_SIZE) {
1023 sbuf_push(buf, indent, "TLV size does not match expected size for Link Packet Loss!\n");
1024 return;
1025 }
98c5bc15
CF
1026 sum += print_subtlv_pkt_loss(buf, indent,
1027 (struct te_subtlv_pkt_loss *)tlvh);
d62a17ae 1028 break;
1029 case TE_SUBTLV_RES_BW:
27a470dc
CF
1030 if (tlvh->length != SUBTLV_DEF_SIZE) {
1031 sbuf_push(buf, indent, "TLV size does not match expected size for Unidirectional Residual Bandwidth!\n");
1032 return;
1033 }
98c5bc15
CF
1034 sum += print_subtlv_res_bw(buf, indent,
1035 (struct te_subtlv_res_bw *)tlvh);
d62a17ae 1036 break;
1037 case TE_SUBTLV_AVA_BW:
27a470dc
CF
1038 if (tlvh->length != SUBTLV_DEF_SIZE) {
1039 sbuf_push(buf, indent, "TLV size does not match expected size for Unidirectional Available Bandwidth!\n");
1040 return;
1041 }
98c5bc15
CF
1042 sum += print_subtlv_ava_bw(buf, indent,
1043 (struct te_subtlv_ava_bw *)tlvh);
d62a17ae 1044 break;
1045 case TE_SUBTLV_USE_BW:
27a470dc
CF
1046 if (tlvh->length != SUBTLV_DEF_SIZE) {
1047 sbuf_push(buf, indent, "TLV size does not match expected size for Unidirectional Utilized Bandwidth!\n");
1048 return;
1049 }
98c5bc15
CF
1050 sum += print_subtlv_use_bw(buf, indent,
1051 (struct te_subtlv_use_bw *)tlvh);
d62a17ae 1052 break;
1053 default:
af8ac8f9 1054 sum += print_unknown_tlv(buf, indent, tlvh);
d62a17ae 1055 break;
1056 }
1057 }
1058 return;
f8c06e2c
OD
1059}
1060
1061/* Specific MPLS TE router parameters write function */
d62a17ae 1062void isis_mpls_te_config_write_router(struct vty *vty)
f8c06e2c 1063{
d62a17ae 1064 if (IS_MPLS_TE(isisMplsTE)) {
1065 vty_out(vty, " mpls-te on\n");
1066 vty_out(vty, " mpls-te router-address %s\n",
1067 inet_ntoa(isisMplsTE.router_id));
1068 }
1069
1070 return;
f8c06e2c
OD
1071}
1072
1073
1074/*------------------------------------------------------------------------*
1075 * Followings are vty command functions.
1076 *------------------------------------------------------------------------*/
ef020087
CF
1077#ifndef FABRICD
1078
1079/* Search MPLS TE Circuit context from Interface */
1080static struct mpls_te_circuit *lookup_mpls_params_by_ifp(struct interface *ifp)
1081{
1082 struct isis_circuit *circuit;
1083
1084 if ((circuit = circuit_scan_by_ifp(ifp)) == NULL)
1085 return NULL;
1086
1087 return circuit->mtc;
1088}
f8c06e2c 1089
f8c06e2c
OD
1090DEFUN (show_isis_mpls_te_router,
1091 show_isis_mpls_te_router_cmd,
7c0cbd0e 1092 "show " PROTO_NAME " mpls-te router",
f8c06e2c 1093 SHOW_STR
7c0cbd0e 1094 PROTO_HELP
f8c06e2c
OD
1095 MPLS_TE_STR
1096 "Router information\n")
1097{
d62a17ae 1098 if (IS_MPLS_TE(isisMplsTE)) {
1099 vty_out(vty, "--- MPLS-TE router parameters ---\n");
1100
1101 if (ntohs(isisMplsTE.router_id.s_addr) != 0)
1102 vty_out(vty, " Router-Address: %s\n",
1103 inet_ntoa(isisMplsTE.router_id));
1104 else
1105 vty_out(vty, " N/A\n");
1106 } else
1107 vty_out(vty, " MPLS-TE is disable on this router\n");
1108
1109 return CMD_SUCCESS;
f8c06e2c
OD
1110}
1111
d62a17ae 1112static void show_mpls_te_sub(struct vty *vty, struct interface *ifp)
f8c06e2c 1113{
d62a17ae 1114 struct mpls_te_circuit *mtc;
af8ac8f9
CF
1115 struct sbuf buf;
1116
1117 sbuf_init(&buf, NULL, 0);
d62a17ae 1118
1119 if ((IS_MPLS_TE(isisMplsTE))
1120 && ((mtc = lookup_mpls_params_by_ifp(ifp)) != NULL)) {
1121 /* Continue only if interface is not passive or support Inter-AS
1122 * TEv2 */
1123 if (mtc->status != enable) {
1124 if (IS_INTER_AS(mtc->type)) {
1125 vty_out(vty,
1126 "-- Inter-AS TEv2 link parameters for %s --\n",
1127 ifp->name);
1128 } else {
1129 /* MPLS-TE is not activate on this interface */
1130 /* or this interface is passive and Inter-AS
1131 * TEv2 is not activate */
1132 vty_out(vty,
1133 " %s: MPLS-TE is disabled on this interface\n",
1134 ifp->name);
1135 return;
1136 }
1137 } else {
1138 vty_out(vty, "-- MPLS-TE link parameters for %s --\n",
1139 ifp->name);
1140 }
1141
af8ac8f9
CF
1142 sbuf_reset(&buf);
1143 print_subtlv_admin_grp(&buf, 4, &mtc->admin_grp);
d62a17ae 1144
1145 if (SUBTLV_TYPE(mtc->local_ipaddr) != 0)
af8ac8f9 1146 print_subtlv_local_ipaddr(&buf, 4, &mtc->local_ipaddr);
d62a17ae 1147 if (SUBTLV_TYPE(mtc->rmt_ipaddr) != 0)
af8ac8f9 1148 print_subtlv_rmt_ipaddr(&buf, 4, &mtc->rmt_ipaddr);
d62a17ae 1149
af8ac8f9
CF
1150 print_subtlv_max_bw(&buf, 4, &mtc->max_bw);
1151 print_subtlv_max_rsv_bw(&buf, 4, &mtc->max_rsv_bw);
1152 print_subtlv_unrsv_bw(&buf, 4, &mtc->unrsv_bw);
1153 print_subtlv_te_metric(&buf, 4, &mtc->te_metric);
d62a17ae 1154
1155 if (IS_INTER_AS(mtc->type)) {
1156 if (SUBTLV_TYPE(mtc->ras) != 0)
af8ac8f9 1157 print_subtlv_ras(&buf, 4, &mtc->ras);
d62a17ae 1158 if (SUBTLV_TYPE(mtc->rip) != 0)
af8ac8f9 1159 print_subtlv_rip(&buf, 4, &mtc->rip);
d62a17ae 1160 }
1161
af8ac8f9
CF
1162 print_subtlv_av_delay(&buf, 4, &mtc->av_delay);
1163 print_subtlv_mm_delay(&buf, 4, &mtc->mm_delay);
1164 print_subtlv_delay_var(&buf, 4, &mtc->delay_var);
1165 print_subtlv_pkt_loss(&buf, 4, &mtc->pkt_loss);
1166 print_subtlv_res_bw(&buf, 4, &mtc->res_bw);
1167 print_subtlv_ava_bw(&buf, 4, &mtc->ava_bw);
1168 print_subtlv_use_bw(&buf, 4, &mtc->use_bw);
1169
1170 vty_multiline(vty, "", "%s", sbuf_buf(&buf));
d62a17ae 1171 vty_out(vty, "---------------\n\n");
1172 } else {
1173 vty_out(vty, " %s: MPLS-TE is disabled on this interface\n",
1174 ifp->name);
1175 }
1176
af8ac8f9 1177 sbuf_free(&buf);
d62a17ae 1178 return;
f8c06e2c
OD
1179}
1180
1181DEFUN (show_isis_mpls_te_interface,
1182 show_isis_mpls_te_interface_cmd,
7c0cbd0e 1183 "show " PROTO_NAME " mpls-te interface [INTERFACE]",
f8c06e2c 1184 SHOW_STR
7c0cbd0e 1185 PROTO_HELP
f8c06e2c
OD
1186 MPLS_TE_STR
1187 "Interface information\n"
1188 "Interface name\n")
1189{
f4e14fdb 1190 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
d62a17ae 1191 int idx_interface = 4;
1192 struct interface *ifp;
d62a17ae 1193
1194 /* Show All Interfaces. */
1195 if (argc == 4) {
451fda4f 1196 FOR_ALL_INTERFACES (vrf, ifp)
d62a17ae 1197 show_mpls_te_sub(vty, ifp);
1198 }
1199 /* Interface name is specified. */
1200 else {
1201 if ((ifp = if_lookup_by_name(argv[idx_interface]->arg,
1202 VRF_DEFAULT))
1203 == NULL)
1204 vty_out(vty, "No such interface name\n");
1205 else
1206 show_mpls_te_sub(vty, ifp);
1207 }
1208
1209 return CMD_SUCCESS;
f8c06e2c 1210}
ef020087 1211#endif
f8c06e2c
OD
1212
1213/* Initialize MPLS_TE */
d62a17ae 1214void isis_mpls_te_init(void)
f8c06e2c
OD
1215{
1216
d62a17ae 1217 zlog_debug("ISIS MPLS-TE: Initialize");
f8c06e2c 1218
d62a17ae 1219 /* Initialize MPLS_TE structure */
1220 isisMplsTE.status = disable;
1221 isisMplsTE.level = 0;
1222 isisMplsTE.inter_as = off;
1223 isisMplsTE.interas_areaid.s_addr = 0;
1224 isisMplsTE.cir_list = list_new();
1225 isisMplsTE.router_id.s_addr = 0;
f8c06e2c 1226
ef020087 1227#ifndef FABRICD
d62a17ae 1228 /* Register new VTY commands */
1229 install_element(VIEW_NODE, &show_isis_mpls_te_router_cmd);
1230 install_element(VIEW_NODE, &show_isis_mpls_te_interface_cmd);
ef020087 1231#endif
f8c06e2c 1232
d62a17ae 1233 return;
f8c06e2c 1234}