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