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