]> git.proxmox.com Git - mirror_frr.git/blame - isisd/isis_te.c
Merge pull request #4539 from opensourcerouting/7.1/watchfrr-sd-timeout
[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 45
f8c06e2c
OD
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"
f8c06e2c
OD
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"
59
d62a17ae 60const char *mode2text[] = {"Disable", "Area", "AS", "Emulate"};
f8c06e2c
OD
61
62/*------------------------------------------------------------------------*
63 * Followings are control functions for MPLS-TE parameters management.
64 *------------------------------------------------------------------------*/
65
f8c06e2c 66/* Create new MPLS TE Circuit context */
4d762f26 67struct mpls_te_circuit *mpls_te_circuit_new(void)
f8c06e2c 68{
d62a17ae 69 struct mpls_te_circuit *mtc;
f8c06e2c 70
d62a17ae 71 zlog_debug("ISIS MPLS-TE: Create new MPLS TE Circuit context");
f8c06e2c 72
d62a17ae 73 mtc = XCALLOC(MTYPE_ISIS_MPLS_TE, sizeof(struct mpls_te_circuit));
f8c06e2c 74
d62a17ae 75 mtc->status = disable;
76 mtc->type = STD_TE;
77 mtc->length = 0;
f8c06e2c 78
d62a17ae 79 return mtc;
f8c06e2c
OD
80}
81
d62a17ae 82/* Copy SUB TLVs parameters into a buffer - No space verification are performed
83 */
f8c06e2c 84/* Caller must verify before that there is enough free space in the buffer */
af8ac8f9 85uint8_t add_te_subtlvs(uint8_t *buf, struct mpls_te_circuit *mtc)
f8c06e2c 86{
af8ac8f9 87 uint8_t size, *tlvs = buf;
d62a17ae 88
89 zlog_debug("ISIS MPLS-TE: Add TE Sub TLVs to buffer");
90
91 if (mtc == NULL) {
92 zlog_debug(
93 "ISIS MPLS-TE: Abort! No MPLS TE Circuit available has been specified");
94 return 0;
95 }
96
97 /* Create buffer if not provided */
98 if (buf == NULL) {
99 zlog_debug("ISIS MPLS-TE: Abort! No Buffer has been specified");
100 return 0;
101 }
102
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);
107 tlvs += size;
108 }
109
110 /* TE_SUBTLV_LLRI */
111 if (SUBTLV_TYPE(mtc->llri) != 0) {
112 size = SUBTLV_SIZE(&(mtc->llri.header));
113 memcpy(tlvs, &(mtc->llri), size);
114 tlvs += size;
115 }
116
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);
121 tlvs += size;
122 }
123
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);
128 tlvs += size;
129 }
130
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);
135 tlvs += size;
136 }
137
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);
142 tlvs += size;
143 }
144
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);
149 tlvs += size;
150 }
151
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);
156 tlvs += size;
157 }
158
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);
163 tlvs += size;
164 }
165
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);
170 tlvs += size;
171 }
172
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);
177 tlvs += size;
178 }
179
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);
184 tlvs += size;
185 }
186
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);
191 tlvs += size;
192 }
193
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);
198 tlvs += size;
199 }
200
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);
205 tlvs += size;
206 }
207
9c5e2b4f
VJ
208 /* Add before this line any other parsing of TLV */
209 (void)tlvs;
210
d62a17ae 211 /* Update SubTLVs length */
212 mtc->length = subtlvs_len(mtc);
213
214 zlog_debug("ISIS MPLS-TE: Add %d bytes length SubTLVs", mtc->length);
215
216 return mtc->length;
f8c06e2c
OD
217}
218
219/* Compute total Sub-TLVs size */
af8ac8f9 220uint8_t subtlvs_len(struct mpls_te_circuit *mtc)
f8c06e2c 221{
d62a17ae 222 int length = 0;
f8c06e2c 223
d62a17ae 224 /* Sanity Check */
225 if (mtc == NULL)
226 return 0;
f8c06e2c 227
d62a17ae 228 /* TE_SUBTLV_ADMIN_GRP */
229 if (SUBTLV_TYPE(mtc->admin_grp) != 0)
230 length += SUBTLV_SIZE(&(mtc->admin_grp.header));
f8c06e2c 231
d62a17ae 232 /* TE_SUBTLV_LLRI */
233 if (SUBTLV_TYPE(mtc->llri) != 0)
234 length += SUBTLV_SIZE(&mtc->llri.header);
f8c06e2c 235
d62a17ae 236 /* TE_SUBTLV_LCLIF_IPADDR */
237 if (SUBTLV_TYPE(mtc->local_ipaddr) != 0)
238 length += SUBTLV_SIZE(&mtc->local_ipaddr.header);
f8c06e2c 239
d62a17ae 240 /* TE_SUBTLV_RMTIF_IPADDR */
241 if (SUBTLV_TYPE(mtc->rmt_ipaddr) != 0)
242 length += SUBTLV_SIZE(&mtc->rmt_ipaddr.header);
f8c06e2c 243
d62a17ae 244 /* TE_SUBTLV_MAX_BW */
245 if (SUBTLV_TYPE(mtc->max_bw) != 0)
246 length += SUBTLV_SIZE(&mtc->max_bw.header);
f8c06e2c 247
d62a17ae 248 /* TE_SUBTLV_MAX_RSV_BW */
249 if (SUBTLV_TYPE(mtc->max_rsv_bw) != 0)
250 length += SUBTLV_SIZE(&mtc->max_rsv_bw.header);
f8c06e2c 251
d62a17ae 252 /* TE_SUBTLV_UNRSV_BW */
253 if (SUBTLV_TYPE(mtc->unrsv_bw) != 0)
254 length += SUBTLV_SIZE(&mtc->unrsv_bw.header);
f8c06e2c 255
d62a17ae 256 /* TE_SUBTLV_TE_METRIC */
257 if (SUBTLV_TYPE(mtc->te_metric) != 0)
258 length += SUBTLV_SIZE(&mtc->te_metric.header);
f8c06e2c 259
d62a17ae 260 /* TE_SUBTLV_AV_DELAY */
261 if (SUBTLV_TYPE(mtc->av_delay) != 0)
262 length += SUBTLV_SIZE(&mtc->av_delay.header);
f8c06e2c 263
d62a17ae 264 /* TE_SUBTLV_MM_DELAY */
265 if (SUBTLV_TYPE(mtc->mm_delay) != 0)
266 length += SUBTLV_SIZE(&mtc->mm_delay.header);
f8c06e2c 267
d62a17ae 268 /* TE_SUBTLV_DELAY_VAR */
269 if (SUBTLV_TYPE(mtc->delay_var) != 0)
270 length += SUBTLV_SIZE(&mtc->delay_var.header);
f8c06e2c 271
d62a17ae 272 /* TE_SUBTLV_PKT_LOSS */
273 if (SUBTLV_TYPE(mtc->pkt_loss) != 0)
274 length += SUBTLV_SIZE(&mtc->pkt_loss.header);
f8c06e2c 275
d62a17ae 276 /* TE_SUBTLV_RES_BW */
277 if (SUBTLV_TYPE(mtc->res_bw) != 0)
278 length += SUBTLV_SIZE(&mtc->res_bw.header);
f8c06e2c 279
d62a17ae 280 /* TE_SUBTLV_AVA_BW */
281 if (SUBTLV_TYPE(mtc->ava_bw) != 0)
282 length += SUBTLV_SIZE(&mtc->ava_bw.header);
f8c06e2c 283
d62a17ae 284 /* TE_SUBTLV_USE_BW */
285 if (SUBTLV_TYPE(mtc->use_bw) != 0)
286 length += SUBTLV_SIZE(&mtc->use_bw.header);
f8c06e2c 287
d62a17ae 288 /* Check that length is lower than the MAXIMUM SUBTLV size i.e. 256 */
289 if (length > MAX_SUBTLV_SIZE) {
290 mtc->length = 0;
291 return 0;
292 }
f8c06e2c 293
af8ac8f9 294 mtc->length = (uint8_t)length;
f8c06e2c 295
d62a17ae 296 return mtc->length;
f8c06e2c
OD
297}
298
299/* Following are various functions to set MPLS TE parameters */
d62a17ae 300static void set_circuitparams_admin_grp(struct mpls_te_circuit *mtc,
d7c0a89a 301 uint32_t admingrp)
f8c06e2c 302{
d62a17ae 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);
306 return;
f8c06e2c
OD
307}
308
d62a17ae 309static void __attribute__((unused))
d7c0a89a
QY
310set_circuitparams_llri(struct mpls_te_circuit *mtc, uint32_t local,
311 uint32_t remote)
f8c06e2c 312{
d62a17ae 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);
f8c06e2c
OD
317}
318
d62a17ae 319void set_circuitparams_local_ipaddr(struct mpls_te_circuit *mtc,
320 struct in_addr addr)
f8c06e2c
OD
321{
322
d62a17ae 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;
326 return;
f8c06e2c
OD
327}
328
d62a17ae 329void set_circuitparams_rmt_ipaddr(struct mpls_te_circuit *mtc,
330 struct in_addr addr)
f8c06e2c
OD
331{
332
d62a17ae 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;
336 return;
f8c06e2c
OD
337}
338
d62a17ae 339static void set_circuitparams_max_bw(struct mpls_te_circuit *mtc, float fp)
f8c06e2c 340{
d62a17ae 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);
344 return;
f8c06e2c
OD
345}
346
d62a17ae 347static void set_circuitparams_max_rsv_bw(struct mpls_te_circuit *mtc, float fp)
f8c06e2c 348{
d62a17ae 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);
352 return;
f8c06e2c
OD
353}
354
d62a17ae 355static void set_circuitparams_unrsv_bw(struct mpls_te_circuit *mtc,
356 int priority, float fp)
f8c06e2c 357{
d62a17ae 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);
362 return;
f8c06e2c
OD
363}
364
d62a17ae 365static void set_circuitparams_te_metric(struct mpls_te_circuit *mtc,
d7c0a89a 366 uint32_t te_metric)
f8c06e2c 367{
d62a17ae 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;
373 return;
f8c06e2c
OD
374}
375
d62a17ae 376static void set_circuitparams_inter_as(struct mpls_te_circuit *mtc,
d7c0a89a 377 struct in_addr addr, uint32_t as)
f8c06e2c
OD
378{
379
d62a17ae 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;
f8c06e2c 384
d62a17ae 385 SUBTLV_TYPE(mtc->ras) = TE_SUBTLV_RAS;
386 SUBTLV_LEN(mtc->ras) = SUBTLV_DEF_SIZE;
387 mtc->ras.value = htonl(as);
f8c06e2c
OD
388}
389
d62a17ae 390static void unset_circuitparams_inter_as(struct mpls_te_circuit *mtc)
f8c06e2c
OD
391{
392
d62a17ae 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;
f8c06e2c 397
d62a17ae 398 SUBTLV_TYPE(mtc->ras) = 0;
399 SUBTLV_LEN(mtc->ras) = 0;
400 mtc->ras.value = 0;
f8c06e2c
OD
401}
402
d62a17ae 403static void set_circuitparams_av_delay(struct mpls_te_circuit *mtc,
d7c0a89a 404 uint32_t delay, uint8_t anormal)
f8c06e2c 405{
d7c0a89a 406 uint32_t tmp;
d62a17ae 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;
411 if (anormal)
412 tmp |= TE_EXT_ANORMAL;
413 mtc->av_delay.value = htonl(tmp);
414 return;
f8c06e2c
OD
415}
416
d62a17ae 417static void set_circuitparams_mm_delay(struct mpls_te_circuit *mtc,
d7c0a89a
QY
418 uint32_t low, uint32_t high,
419 uint8_t anormal)
f8c06e2c 420{
d7c0a89a 421 uint32_t tmp;
d62a17ae 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;
426 if (anormal)
427 tmp |= TE_EXT_ANORMAL;
428 mtc->mm_delay.low = htonl(tmp);
429 mtc->mm_delay.high = htonl(high);
430 return;
f8c06e2c
OD
431}
432
d62a17ae 433static void set_circuitparams_delay_var(struct mpls_te_circuit *mtc,
d7c0a89a 434 uint32_t jitter)
f8c06e2c 435{
d62a17ae 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);
440 return;
f8c06e2c
OD
441}
442
d62a17ae 443static void set_circuitparams_pkt_loss(struct mpls_te_circuit *mtc,
d7c0a89a 444 uint32_t loss, uint8_t anormal)
f8c06e2c 445{
d7c0a89a 446 uint32_t tmp;
d62a17ae 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;
451 if (anormal)
452 tmp |= TE_EXT_ANORMAL;
453 mtc->pkt_loss.value = htonl(tmp);
454 return;
f8c06e2c
OD
455}
456
d62a17ae 457static void set_circuitparams_res_bw(struct mpls_te_circuit *mtc, float fp)
f8c06e2c 458{
d62a17ae 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);
463 return;
f8c06e2c
OD
464}
465
d62a17ae 466static void set_circuitparams_ava_bw(struct mpls_te_circuit *mtc, float fp)
f8c06e2c 467{
d62a17ae 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);
472 return;
f8c06e2c
OD
473}
474
d62a17ae 475static void set_circuitparams_use_bw(struct mpls_te_circuit *mtc, float fp)
f8c06e2c 476{
d62a17ae 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);
481 return;
f8c06e2c
OD
482}
483
484/* Main initialization / update function of the MPLS TE Circuit context */
485/* Call when interface TE Link parameters are modified */
d62a17ae 486void isis_link_params_update(struct isis_circuit *circuit,
487 struct interface *ifp)
f8c06e2c 488{
d62a17ae 489 int i;
490 struct prefix_ipv4 *addr;
491 struct mpls_te_circuit *mtc;
492
493 /* Sanity Check */
494 if ((circuit == NULL) || (ifp == NULL))
495 return;
496
497 zlog_info("MPLS-TE: Initialize circuit parameters for interface %s",
498 ifp->name);
499
500 /* Check if MPLS TE Circuit context has not been already created */
501 if (circuit->mtc == NULL)
502 circuit->mtc = mpls_te_circuit_new();
503
504 mtc = circuit->mtc;
505
506 /* Fulfil MTC TLV from ifp TE Link parameters */
507 if (HAS_LINK_PARAMS(ifp)) {
508 mtc->status = enable;
509 /* STD_TE metrics */
510 if (IS_PARAM_SET(ifp->link_params, LP_ADM_GRP))
511 set_circuitparams_admin_grp(
512 mtc, ifp->link_params->admin_grp);
513 else
514 SUBTLV_TYPE(mtc->admin_grp) = 0;
515
516 /* If not already set, register local IP addr from ip_addr list
517 * if it exists */
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(
523 circuit->ip_addrs));
524 set_circuitparams_local_ipaddr(mtc,
525 addr->prefix);
526 }
527 }
528
529 /* If not already set, try to determine Remote IP addr if
530 * circuit is P2P */
531 if ((SUBTLV_TYPE(mtc->rmt_ipaddr) == 0)
532 && (circuit->circ_type == CIRCUIT_T_P2P)) {
533 struct isis_adjacency *adj = circuit->u.p2p.neighbor;
44b89511
CF
534 if (adj && adj->adj_state == ISIS_ADJ_UP
535 && adj->ipv4_address_count) {
0c1bd758
CF
536 set_circuitparams_rmt_ipaddr(
537 mtc, adj->ipv4_addresses[0]);
d62a17ae 538 }
539 }
540
541 if (IS_PARAM_SET(ifp->link_params, LP_MAX_BW))
542 set_circuitparams_max_bw(mtc, ifp->link_params->max_bw);
543 else
544 SUBTLV_TYPE(mtc->max_bw) = 0;
545
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);
549 else
550 SUBTLV_TYPE(mtc->max_rsv_bw) = 0;
551
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]);
556 else
557 SUBTLV_TYPE(mtc->unrsv_bw) = 0;
558
559 if (IS_PARAM_SET(ifp->link_params, LP_TE_METRIC))
560 set_circuitparams_te_metric(
561 mtc, ifp->link_params->te_metric);
562 else
563 SUBTLV_TYPE(mtc->te_metric) = 0;
564
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);
569 else
570 SUBTLV_TYPE(mtc->av_delay) = 0;
571
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);
576 else
577 SUBTLV_TYPE(mtc->mm_delay) = 0;
578
579 if (IS_PARAM_SET(ifp->link_params, LP_DELAY_VAR))
580 set_circuitparams_delay_var(
581 mtc, ifp->link_params->delay_var);
582 else
583 SUBTLV_TYPE(mtc->delay_var) = 0;
584
585 if (IS_PARAM_SET(ifp->link_params, LP_PKT_LOSS))
586 set_circuitparams_pkt_loss(
587 mtc, ifp->link_params->pkt_loss, 0);
588 else
589 SUBTLV_TYPE(mtc->pkt_loss) = 0;
590
591 if (IS_PARAM_SET(ifp->link_params, LP_RES_BW))
592 set_circuitparams_res_bw(mtc, ifp->link_params->res_bw);
593 else
594 SUBTLV_TYPE(mtc->res_bw) = 0;
595
596 if (IS_PARAM_SET(ifp->link_params, LP_AVA_BW))
597 set_circuitparams_ava_bw(mtc, ifp->link_params->ava_bw);
598 else
599 SUBTLV_TYPE(mtc->ava_bw) = 0;
600
601 if (IS_PARAM_SET(ifp->link_params, LP_USE_BW))
602 set_circuitparams_use_bw(mtc, ifp->link_params->use_bw);
603 else
604 SUBTLV_TYPE(mtc->use_bw) = 0;
605
606 /* INTER_AS */
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);
611 else
612 /* reset inter-as TE params */
613 unset_circuitparams_inter_as(mtc);
614
615 /* Compute total length of SUB TLVs */
616 mtc->length = subtlvs_len(mtc);
617
618 } else
619 mtc->status = disable;
620
621/* Finally Update LSP */
f8c06e2c 622#if 0
2e2a8b91 623 if (circuit->area && IS_MPLS_TE(circuit->area->mta))
f8c06e2c
OD
624 lsp_regenerate_schedule (circuit->area, circuit->is_type, 0);
625#endif
d62a17ae 626 return;
f8c06e2c
OD
627}
628
d62a17ae 629void isis_mpls_te_update(struct interface *ifp)
f8c06e2c 630{
d62a17ae 631 struct isis_circuit *circuit;
f8c06e2c 632
d62a17ae 633 /* Sanity Check */
634 if (ifp == NULL)
635 return;
f8c06e2c 636
d62a17ae 637 /* Get circuit context from interface */
638 if ((circuit = circuit_scan_by_ifp(ifp)) == NULL)
639 return;
f8c06e2c 640
d62a17ae 641 /* Update TE TLVs ... */
642 isis_link_params_update(circuit, ifp);
f8c06e2c 643
d62a17ae 644 /* ... and LSP */
2e2a8b91 645 if (circuit->area && IS_MPLS_TE(circuit->area->mta))
d62a17ae 646 lsp_regenerate_schedule(circuit->area, circuit->is_type, 0);
f8c06e2c 647
d62a17ae 648 return;
f8c06e2c
OD
649}
650
651/*------------------------------------------------------------------------*
652 * Followings are vty session control functions.
653 *------------------------------------------------------------------------*/
654
d7c0a89a
QY
655static uint8_t print_subtlv_admin_grp(struct sbuf *buf, int indent,
656 struct te_subtlv_admin_grp *tlv)
f8c06e2c 657{
af8ac8f9
CF
658 sbuf_push(buf, indent, "Administrative Group: 0x%" PRIx32 "\n",
659 ntohl(tlv->value));
d62a17ae 660 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
661}
662
d7c0a89a
QY
663static uint8_t print_subtlv_llri(struct sbuf *buf, int indent,
664 struct te_subtlv_llri *tlv)
f8c06e2c 665{
af8ac8f9
CF
666 sbuf_push(buf, indent, "Link Local ID: %" PRIu32 "\n",
667 ntohl(tlv->local));
668 sbuf_push(buf, indent, "Link Remote ID: %" PRIu32 "\n",
669 ntohl(tlv->remote));
d62a17ae 670
671 return (SUBTLV_HDR_SIZE + TE_SUBTLV_LLRI_SIZE);
f8c06e2c
OD
672}
673
d7c0a89a
QY
674static uint8_t print_subtlv_local_ipaddr(struct sbuf *buf, int indent,
675 struct te_subtlv_local_ipaddr *tlv)
f8c06e2c 676{
af8ac8f9
CF
677 sbuf_push(buf, indent, "Local Interface IP Address(es): %s\n",
678 inet_ntoa(tlv->value));
d62a17ae 679
680 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
681}
682
d7c0a89a
QY
683static uint8_t print_subtlv_rmt_ipaddr(struct sbuf *buf, int indent,
684 struct te_subtlv_rmt_ipaddr *tlv)
f8c06e2c 685{
af8ac8f9
CF
686 sbuf_push(buf, indent, "Remote Interface IP Address(es): %s\n",
687 inet_ntoa(tlv->value));
d62a17ae 688
689 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
690}
691
d7c0a89a
QY
692static uint8_t print_subtlv_max_bw(struct sbuf *buf, int indent,
693 struct te_subtlv_max_bw *tlv)
f8c06e2c 694{
d62a17ae 695 float fval;
f8c06e2c 696
d62a17ae 697 fval = ntohf(tlv->value);
f8c06e2c 698
af8ac8f9 699 sbuf_push(buf, indent, "Maximum Bandwidth: %g (Bytes/sec)\n", fval);
f8c06e2c 700
d62a17ae 701 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
702}
703
d7c0a89a
QY
704static uint8_t print_subtlv_max_rsv_bw(struct sbuf *buf, int indent,
705 struct te_subtlv_max_rsv_bw *tlv)
f8c06e2c 706{
d62a17ae 707 float fval;
f8c06e2c 708
d62a17ae 709 fval = ntohf(tlv->value);
f8c06e2c 710
996c9314
LB
711 sbuf_push(buf, indent, "Maximum Reservable Bandwidth: %g (Bytes/sec)\n",
712 fval);
f8c06e2c 713
d62a17ae 714 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
715}
716
d7c0a89a
QY
717static uint8_t print_subtlv_unrsv_bw(struct sbuf *buf, int indent,
718 struct te_subtlv_unrsv_bw *tlv)
f8c06e2c 719{
d62a17ae 720 float fval1, fval2;
721 int i;
722
af8ac8f9 723 sbuf_push(buf, indent, "Unreserved Bandwidth:\n");
d62a17ae 724
725 for (i = 0; i < MAX_CLASS_TYPE; i += 2) {
726 fval1 = ntohf(tlv->value[i]);
727 fval2 = ntohf(tlv->value[i + 1]);
996c9314
LB
728 sbuf_push(buf, indent + 2,
729 "[%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n", i,
730 fval1, i + 1, fval2);
d62a17ae 731 }
732
733 return (SUBTLV_HDR_SIZE + TE_SUBTLV_UNRSV_SIZE);
f8c06e2c
OD
734}
735
d7c0a89a
QY
736static uint8_t print_subtlv_te_metric(struct sbuf *buf, int indent,
737 struct te_subtlv_te_metric *tlv)
f8c06e2c 738{
d7c0a89a 739 uint32_t te_metric;
f8c06e2c 740
d62a17ae 741 te_metric = tlv->value[2] | tlv->value[1] << 8 | tlv->value[0] << 16;
af8ac8f9 742 sbuf_push(buf, indent, "Traffic Engineering Metric: %u\n", te_metric);
f8c06e2c 743
d62a17ae 744 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
745}
746
d7c0a89a
QY
747static uint8_t print_subtlv_ras(struct sbuf *buf, int indent,
748 struct te_subtlv_ras *tlv)
f8c06e2c 749{
af8ac8f9
CF
750 sbuf_push(buf, indent, "Inter-AS TE Remote AS number: %" PRIu32 "\n",
751 ntohl(tlv->value));
d62a17ae 752
753 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
754}
755
d7c0a89a
QY
756static uint8_t print_subtlv_rip(struct sbuf *buf, int indent,
757 struct te_subtlv_rip *tlv)
f8c06e2c 758{
af8ac8f9
CF
759 sbuf_push(buf, indent, "Inter-AS TE Remote ASBR IP address: %s\n",
760 inet_ntoa(tlv->value));
d62a17ae 761
762 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
763}
764
d7c0a89a
QY
765static uint8_t print_subtlv_av_delay(struct sbuf *buf, int indent,
766 struct te_subtlv_av_delay *tlv)
f8c06e2c 767{
d7c0a89a
QY
768 uint32_t delay;
769 uint32_t A;
f8c06e2c 770
d7c0a89a
QY
771 delay = (uint32_t)ntohl(tlv->value) & TE_EXT_MASK;
772 A = (uint32_t)ntohl(tlv->value) & TE_EXT_ANORMAL;
f8c06e2c 773
996c9314
LB
774 sbuf_push(buf, indent,
775 "%s Average Link Delay: %" PRIu32 " (micro-sec)\n",
af8ac8f9 776 A ? "Anomalous" : "Normal", delay);
f8c06e2c 777
d62a17ae 778 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
779}
780
d7c0a89a
QY
781static uint8_t print_subtlv_mm_delay(struct sbuf *buf, int indent,
782 struct te_subtlv_mm_delay *tlv)
f8c06e2c 783{
d7c0a89a
QY
784 uint32_t low, high;
785 uint32_t A;
f8c06e2c 786
d7c0a89a
QY
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;
f8c06e2c 790
98c5bc15 791 sbuf_push(buf, indent, "%s Min/Max Link Delay: %" PRIu32 " / %" PRIu32 " (micro-sec)\n",
af8ac8f9 792 A ? "Anomalous" : "Normal", low, high);
f8c06e2c 793
d62a17ae 794 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
795}
796
d7c0a89a
QY
797static uint8_t print_subtlv_delay_var(struct sbuf *buf, int indent,
798 struct te_subtlv_delay_var *tlv)
f8c06e2c 799{
d7c0a89a 800 uint32_t jitter;
f8c06e2c 801
d7c0a89a 802 jitter = (uint32_t)ntohl(tlv->value) & TE_EXT_MASK;
f8c06e2c 803
996c9314
LB
804 sbuf_push(buf, indent, "Delay Variation: %" PRIu32 " (micro-sec)\n",
805 jitter);
f8c06e2c 806
d62a17ae 807 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
808}
809
d7c0a89a
QY
810static uint8_t print_subtlv_pkt_loss(struct sbuf *buf, int indent,
811 struct te_subtlv_pkt_loss *tlv)
f8c06e2c 812{
d7c0a89a
QY
813 uint32_t loss;
814 uint32_t A;
d62a17ae 815 float fval;
816
d7c0a89a 817 loss = (uint32_t)ntohl(tlv->value) & TE_EXT_MASK;
d62a17ae 818 fval = (float)(loss * LOSS_PRECISION);
d7c0a89a 819 A = (uint32_t)ntohl(tlv->value) & TE_EXT_ANORMAL;
d62a17ae 820
af8ac8f9
CF
821 sbuf_push(buf, indent, "%s Link Packet Loss: %g (%%)\n",
822 A ? "Anomalous" : "Normal", fval);
d62a17ae 823
824 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
825}
826
d7c0a89a
QY
827static uint8_t print_subtlv_res_bw(struct sbuf *buf, int indent,
828 struct te_subtlv_res_bw *tlv)
f8c06e2c 829{
d62a17ae 830 float fval;
f8c06e2c 831
d62a17ae 832 fval = ntohf(tlv->value);
f8c06e2c 833
996c9314
LB
834 sbuf_push(buf, indent,
835 "Unidirectional Residual Bandwidth: %g (Bytes/sec)\n", fval);
f8c06e2c 836
d62a17ae 837 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
838}
839
d7c0a89a
QY
840static uint8_t print_subtlv_ava_bw(struct sbuf *buf, int indent,
841 struct te_subtlv_ava_bw *tlv)
f8c06e2c 842{
d62a17ae 843 float fval;
f8c06e2c 844
d62a17ae 845 fval = ntohf(tlv->value);
f8c06e2c 846
996c9314
LB
847 sbuf_push(buf, indent,
848 "Unidirectional Available Bandwidth: %g (Bytes/sec)\n", fval);
f8c06e2c 849
d62a17ae 850 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
851}
852
d7c0a89a
QY
853static uint8_t print_subtlv_use_bw(struct sbuf *buf, int indent,
854 struct te_subtlv_use_bw *tlv)
f8c06e2c 855{
d62a17ae 856 float fval;
f8c06e2c 857
d62a17ae 858 fval = ntohf(tlv->value);
f8c06e2c 859
996c9314
LB
860 sbuf_push(buf, indent,
861 "Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n", fval);
f8c06e2c 862
d62a17ae 863 return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
f8c06e2c
OD
864}
865
d7c0a89a
QY
866static uint8_t print_unknown_tlv(struct sbuf *buf, int indent,
867 struct subtlv_header *tlvh)
f8c06e2c 868{
a2b6e694 869 int i, rtn;
d7c0a89a 870 uint8_t *v = (uint8_t *)tlvh;
d62a17ae 871
af8ac8f9
CF
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]);
880 if (rtn == 8) {
881 sbuf_push(buf, 0, "\n");
996c9314 882 sbuf_push(buf, indent + 8, "[%.2x]", i + 1);
af8ac8f9
CF
883 rtn = 1;
884 } else
885 rtn++;
886 }
887 sbuf_push(buf, 0, "\n");
d62a17ae 888 } else {
af8ac8f9
CF
889 sbuf_push(buf, indent,
890 "Unknown TLV: [type(%#.2x), length(%#.2x)]\n",
891 tlvh->type, tlvh->length);
d62a17ae 892 }
893
894 return SUBTLV_SIZE(tlvh);
f8c06e2c
OD
895}
896
897/* Main Show function */
98c5bc15
CF
898void mpls_te_print_detail(struct sbuf *buf, int indent,
899 uint8_t *subtlvs, uint8_t subtlv_len)
f8c06e2c 900{
af8ac8f9
CF
901 struct subtlv_header *tlvh = (struct subtlv_header *)subtlvs;
902 uint16_t sum = 0;
d62a17ae 903
27a470dc
CF
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));
909 return;
910 }
911
d62a17ae 912 switch (tlvh->type) {
913 case TE_SUBTLV_ADMIN_GRP:
27a470dc
CF
914 if (tlvh->length != SUBTLV_DEF_SIZE) {
915 sbuf_push(buf, indent, "TLV size does not match expected size for Administrative Group!\n");
916 return;
917 }
98c5bc15 918 sum += print_subtlv_admin_grp(buf, indent,
af8ac8f9 919 (struct te_subtlv_admin_grp *)tlvh);
d62a17ae 920 break;
921 case TE_SUBTLV_LLRI:
27a470dc
CF
922 if (tlvh->length != TE_SUBTLV_LLRI_SIZE) {
923 sbuf_push(buf, indent, "TLV size does not match expected size for Link ID!\n");
924 return;
925 }
af8ac8f9 926 sum += print_subtlv_llri(buf, indent,
996c9314 927 (struct te_subtlv_llri *)tlvh);
d62a17ae 928 break;
929 case TE_SUBTLV_LOCAL_IPADDR:
27a470dc
CF
930 if (tlvh->length != SUBTLV_DEF_SIZE) {
931 sbuf_push(buf, indent, "TLV size does not match expected size for Local IP address!\n");
932 return;
933 }
98c5bc15 934 sum += print_subtlv_local_ipaddr(buf, indent,
af8ac8f9 935 (struct te_subtlv_local_ipaddr *)tlvh);
d62a17ae 936 break;
937 case TE_SUBTLV_RMT_IPADDR:
27a470dc
CF
938 if (tlvh->length != SUBTLV_DEF_SIZE) {
939 sbuf_push(buf, indent, "TLV size does not match expected size for Remote Interface address!\n");
940 return;
941 }
98c5bc15 942 sum += print_subtlv_rmt_ipaddr(buf, indent,
af8ac8f9 943 (struct te_subtlv_rmt_ipaddr *)tlvh);
d62a17ae 944 break;
945 case TE_SUBTLV_MAX_BW:
27a470dc
CF
946 if (tlvh->length != SUBTLV_DEF_SIZE) {
947 sbuf_push(buf, indent, "TLV size does not match expected size for Maximum Bandwidth!\n");
948 return;
949 }
98c5bc15
CF
950 sum += print_subtlv_max_bw(buf, indent,
951 (struct te_subtlv_max_bw *)tlvh);
d62a17ae 952 break;
953 case TE_SUBTLV_MAX_RSV_BW:
27a470dc
CF
954 if (tlvh->length != SUBTLV_DEF_SIZE) {
955 sbuf_push(buf, indent, "TLV size does not match expected size for Maximum Reservable Bandwidth!\n");
956 return;
957 }
98c5bc15 958 sum += print_subtlv_max_rsv_bw(buf, indent,
af8ac8f9 959 (struct te_subtlv_max_rsv_bw *)tlvh);
d62a17ae 960 break;
961 case TE_SUBTLV_UNRSV_BW:
27a470dc
CF
962 if (tlvh->length != TE_SUBTLV_UNRSV_SIZE) {
963 sbuf_push(buf, indent, "TLV size does not match expected size for Unreserved Bandwidth!\n");
964 return;
965 }
98c5bc15
CF
966 sum += print_subtlv_unrsv_bw(buf, indent,
967 (struct te_subtlv_unrsv_bw *)tlvh);
d62a17ae 968 break;
969 case TE_SUBTLV_TE_METRIC:
27a470dc
CF
970 if (tlvh->length != SUBTLV_DEF_SIZE) {
971 sbuf_push(buf, indent, "TLV size does not match expected size for Traffic Engineering Metric!\n");
972 return;
973 }
98c5bc15 974 sum += print_subtlv_te_metric(buf, indent,
af8ac8f9 975 (struct te_subtlv_te_metric *)tlvh);
d62a17ae 976 break;
977 case TE_SUBTLV_RAS:
27a470dc
CF
978 if (tlvh->length != SUBTLV_DEF_SIZE) {
979 sbuf_push(buf, indent, "TLV size does not match expected size for Remote AS number!\n");
980 return;
981 }
af8ac8f9 982 sum += print_subtlv_ras(buf, indent,
996c9314 983 (struct te_subtlv_ras *)tlvh);
d62a17ae 984 break;
985 case TE_SUBTLV_RIP:
27a470dc
CF
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");
988 return;
989 }
af8ac8f9 990 sum += print_subtlv_rip(buf, indent,
996c9314 991 (struct te_subtlv_rip *)tlvh);
d62a17ae 992 break;
993 case TE_SUBTLV_AV_DELAY:
27a470dc
CF
994 if (tlvh->length != SUBTLV_DEF_SIZE) {
995 sbuf_push(buf, indent, "TLV size does not match expected size for Average Link Delay!\n");
996 return;
997 }
98c5bc15
CF
998 sum += print_subtlv_av_delay(buf, indent,
999 (struct te_subtlv_av_delay *)tlvh);
d62a17ae 1000 break;
1001 case TE_SUBTLV_MM_DELAY:
27a470dc
CF
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");
1004 return;
1005 }
98c5bc15
CF
1006 sum += print_subtlv_mm_delay(buf, indent,
1007 (struct te_subtlv_mm_delay *)tlvh);
d62a17ae 1008 break;
1009 case TE_SUBTLV_DELAY_VAR:
27a470dc
CF
1010 if (tlvh->length != SUBTLV_DEF_SIZE) {
1011 sbuf_push(buf, indent, "TLV size does not match expected size for Delay Variation!\n");
1012 return;
1013 }
98c5bc15 1014 sum += print_subtlv_delay_var(buf, indent,
af8ac8f9 1015 (struct te_subtlv_delay_var *)tlvh);
d62a17ae 1016 break;
1017 case TE_SUBTLV_PKT_LOSS:
27a470dc
CF
1018 if (tlvh->length != SUBTLV_DEF_SIZE) {
1019 sbuf_push(buf, indent, "TLV size does not match expected size for Link Packet Loss!\n");
1020 return;
1021 }
98c5bc15
CF
1022 sum += print_subtlv_pkt_loss(buf, indent,
1023 (struct te_subtlv_pkt_loss *)tlvh);
d62a17ae 1024 break;
1025 case TE_SUBTLV_RES_BW:
27a470dc
CF
1026 if (tlvh->length != SUBTLV_DEF_SIZE) {
1027 sbuf_push(buf, indent, "TLV size does not match expected size for Unidirectional Residual Bandwidth!\n");
1028 return;
1029 }
98c5bc15
CF
1030 sum += print_subtlv_res_bw(buf, indent,
1031 (struct te_subtlv_res_bw *)tlvh);
d62a17ae 1032 break;
1033 case TE_SUBTLV_AVA_BW:
27a470dc
CF
1034 if (tlvh->length != SUBTLV_DEF_SIZE) {
1035 sbuf_push(buf, indent, "TLV size does not match expected size for Unidirectional Available Bandwidth!\n");
1036 return;
1037 }
98c5bc15
CF
1038 sum += print_subtlv_ava_bw(buf, indent,
1039 (struct te_subtlv_ava_bw *)tlvh);
d62a17ae 1040 break;
1041 case TE_SUBTLV_USE_BW:
27a470dc
CF
1042 if (tlvh->length != SUBTLV_DEF_SIZE) {
1043 sbuf_push(buf, indent, "TLV size does not match expected size for Unidirectional Utilized Bandwidth!\n");
1044 return;
1045 }
98c5bc15
CF
1046 sum += print_subtlv_use_bw(buf, indent,
1047 (struct te_subtlv_use_bw *)tlvh);
d62a17ae 1048 break;
1049 default:
af8ac8f9 1050 sum += print_unknown_tlv(buf, indent, tlvh);
d62a17ae 1051 break;
1052 }
1053 }
1054 return;
f8c06e2c
OD
1055}
1056
f8c06e2c
OD
1057/*------------------------------------------------------------------------*
1058 * Followings are vty command functions.
1059 *------------------------------------------------------------------------*/
ef020087
CF
1060#ifndef FABRICD
1061
f8c06e2c
OD
1062DEFUN (show_isis_mpls_te_router,
1063 show_isis_mpls_te_router_cmd,
7c0cbd0e 1064 "show " PROTO_NAME " mpls-te router",
f8c06e2c 1065 SHOW_STR
7c0cbd0e 1066 PROTO_HELP
f8c06e2c
OD
1067 MPLS_TE_STR
1068 "Router information\n")
1069{
d62a17ae 1070
2e2a8b91
OD
1071 struct listnode *anode;
1072 struct isis_area *area;
1073
1074 if (!isis) {
1075 vty_out(vty, "IS-IS Routing Process not enabled\n");
1076 return CMD_SUCCESS;
1077 }
1078
1079 for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) {
1080
1081 if (!IS_MPLS_TE(area->mta))
1082 continue;
1083
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));
d62a17ae 1088 else
1089 vty_out(vty, " N/A\n");
2e2a8b91 1090 }
d62a17ae 1091
1092 return CMD_SUCCESS;
f8c06e2c
OD
1093}
1094
2e2a8b91
OD
1095static void show_mpls_te_sub(struct vty *vty, char *name,
1096 struct mpls_te_circuit *mtc)
f8c06e2c 1097{
af8ac8f9
CF
1098 struct sbuf buf;
1099
1100 sbuf_init(&buf, NULL, 0);
d62a17ae 1101
2e2a8b91
OD
1102 if (mtc->status != enable)
1103 return;
d62a17ae 1104
2e2a8b91 1105 vty_out(vty, "-- MPLS-TE link parameters for %s --\n", name);
d62a17ae 1106
2e2a8b91
OD
1107 sbuf_reset(&buf);
1108 print_subtlv_admin_grp(&buf, 4, &mtc->admin_grp);
d62a17ae 1109
2e2a8b91
OD
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);
1114
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);
1119
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);
1125 }
231e94e3 1126
2e2a8b91
OD
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);
af8ac8f9 1134
2e2a8b91
OD
1135 vty_multiline(vty, "", "%s", sbuf_buf(&buf));
1136 vty_out(vty, "---------------\n\n");
d62a17ae 1137
af8ac8f9 1138 sbuf_free(&buf);
d62a17ae 1139 return;
f8c06e2c
OD
1140}
1141
1142DEFUN (show_isis_mpls_te_interface,
1143 show_isis_mpls_te_interface_cmd,
7c0cbd0e 1144 "show " PROTO_NAME " mpls-te interface [INTERFACE]",
f8c06e2c 1145 SHOW_STR
7c0cbd0e 1146 PROTO_HELP
f8c06e2c
OD
1147 MPLS_TE_STR
1148 "Interface information\n"
1149 "Interface name\n")
1150{
2e2a8b91
OD
1151 struct listnode *anode, *cnode;
1152 struct isis_area *area;
1153 struct isis_circuit *circuit;
231e94e3 1154 struct interface *ifp;
2e2a8b91 1155 int idx_interface = 4;
d62a17ae 1156
2e2a8b91
OD
1157 if (!isis) {
1158 vty_out(vty, "IS-IS Routing Process not enabled\n");
1159 return CMD_SUCCESS;
d62a17ae 1160 }
2e2a8b91
OD
1161
1162 if (argc == idx_interface) {
1163 /* Show All Interfaces. */
1164 for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) {
1165
1166 if (!IS_MPLS_TE(area->mta))
1167 continue;
1168
1169 vty_out(vty, "Area %s:\n", area->area_tag);
1170
1171 for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode,
1172 circuit))
1173 show_mpls_te_sub(vty, circuit->interface->name,
1174 circuit->mtc);
1175 }
1176 } else {
1177 /* Interface name is specified. */
1178 ifp = if_lookup_by_name(argv[idx_interface]->arg, VRF_DEFAULT);
1179 if (ifp == NULL)
d62a17ae 1180 vty_out(vty, "No such interface name\n");
2e2a8b91
OD
1181 else {
1182 circuit = circuit_scan_by_ifp(ifp);
1183 if (!circuit)
1184 vty_out(vty,
1185 "ISIS is not enabled on circuit %s\n",
1186 ifp->name);
1187 else
1188 show_mpls_te_sub(vty, ifp->name, circuit->mtc);
1189 }
d62a17ae 1190 }
1191
1192 return CMD_SUCCESS;
f8c06e2c 1193}
ef020087 1194#endif
f8c06e2c
OD
1195
1196/* Initialize MPLS_TE */
d62a17ae 1197void isis_mpls_te_init(void)
f8c06e2c
OD
1198{
1199
ef020087 1200#ifndef FABRICD
d62a17ae 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);
ef020087 1204#endif
f8c06e2c 1205
d62a17ae 1206 return;
f8c06e2c 1207}