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