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