]> git.proxmox.com Git - mirror_frr.git/blob - isisd/isis_vty_fabricd.c
Merge pull request #6027 from sarav511/vrfloop
[mirror_frr.git] / isisd / isis_vty_fabricd.c
1 /*
2 * IS-IS Rout(e)ing protocol - isis_vty_fabricd.c
3 *
4 * This file contains the CLI that is specific to OpenFabric
5 *
6 * Copyright (C) 2018 Christian Franke, for NetDEF, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public Licenseas published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; see the file COPYING; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22 #include <zebra.h>
23
24 #include "command.h"
25
26 #include "lib/bfd.h"
27 #include "isisd/isis_bfd.h"
28 #include "isisd/isisd.h"
29 #include "isisd/fabricd.h"
30 #include "isisd/isis_tlvs.h"
31 #include "isisd/isis_misc.h"
32 #include "isisd/isis_lsp.h"
33 #include "isisd/isis_csm.h"
34 #include "isisd/isis_circuit.h"
35 #include "lib/spf_backoff.h"
36 #include "isisd/isis_mt.h"
37
38 static struct isis_circuit *isis_circuit_lookup(struct vty *vty)
39 {
40 struct interface *ifp = VTY_GET_CONTEXT(interface);
41 struct isis_circuit *circuit;
42
43 if (!ifp) {
44 vty_out(vty, "Invalid interface \n");
45 return NULL;
46 }
47
48 circuit = circuit_scan_by_ifp(ifp);
49 if (!circuit) {
50 vty_out(vty, "ISIS is not enabled on circuit %s\n", ifp->name);
51 return NULL;
52 }
53
54 return circuit;
55 }
56
57 DEFUN (fabric_tier,
58 fabric_tier_cmd,
59 "fabric-tier (0-14)",
60 "Statically configure the tier to advertise\n"
61 "Tier to advertise\n")
62 {
63 VTY_DECLVAR_CONTEXT(isis_area, area);
64
65 uint8_t tier = atoi(argv[1]->arg);
66
67 fabricd_configure_tier(area, tier);
68 return CMD_SUCCESS;
69 }
70
71 DEFUN (no_fabric_tier,
72 no_fabric_tier_cmd,
73 "no fabric-tier [(0-14)]",
74 NO_STR
75 "Statically configure the tier to advertise\n"
76 "Tier to advertise\n")
77 {
78 VTY_DECLVAR_CONTEXT(isis_area, area);
79
80 fabricd_configure_tier(area, ISIS_TIER_UNDEFINED);
81 return CMD_SUCCESS;
82 }
83
84 DEFUN (triggered_csnp,
85 triggered_csnp_cmd,
86 "triggered-csnp-delay (100-10000) [always]",
87 "Configure the delay for triggered CSNPs\n"
88 "Delay in milliseconds\n"
89 "Trigger CSNP for all LSPs, not only circuit-scoped\n")
90 {
91 VTY_DECLVAR_CONTEXT(isis_area, area);
92
93 int csnp_delay = atoi(argv[1]->arg);
94 bool always_send_csnp = (argc == 3);
95
96 fabricd_configure_triggered_csnp(area, csnp_delay, always_send_csnp);
97 return CMD_SUCCESS;
98 }
99
100 DEFUN (no_triggered_csnp,
101 no_triggered_csnp_cmd,
102 "no triggered-csnp-delay [(100-10000) [always]]",
103 NO_STR
104 "Configure the delay for triggered CSNPs\n"
105 "Delay in milliseconds\n"
106 "Trigger CSNP for all LSPs, not only circuit-scoped\n")
107 {
108 VTY_DECLVAR_CONTEXT(isis_area, area);
109
110 fabricd_configure_triggered_csnp(area, FABRICD_DEFAULT_CSNP_DELAY,
111 false);
112 return CMD_SUCCESS;
113 }
114
115 static void lsp_print_flooding(struct vty *vty, struct isis_lsp *lsp)
116 {
117 char lspid[255];
118 char buf[MONOTIME_STRLEN];
119
120 lspid_print(lsp->hdr.lsp_id, lspid, true, true);
121 vty_out(vty, "Flooding information for %s\n", lspid);
122
123 if (!lsp->flooding_neighbors[TX_LSP_NORMAL]) {
124 vty_out(vty, " Never received.\n");
125 return;
126 }
127
128 vty_out(vty, " Last received on: %s (",
129 lsp->flooding_interface ?
130 lsp->flooding_interface : "(null)");
131
132 time_t uptime = time(NULL) - lsp->flooding_time;
133
134 frrtime_to_interval(uptime, buf, sizeof(buf));
135
136 vty_out(vty, "%s ago)\n", buf);
137
138 if (lsp->flooding_circuit_scoped) {
139 vty_out(vty, " Received as circuit-scoped LSP, so not "
140 "flooded.\n");
141 return;
142 }
143
144 for (enum isis_tx_type type = TX_LSP_NORMAL;
145 type <= TX_LSP_CIRCUIT_SCOPED; type++) {
146 struct listnode *node;
147 uint8_t *neighbor_id;
148
149 vty_out(vty, " %s:\n",
150 (type == TX_LSP_NORMAL) ? "RF" : "DNR");
151 for (ALL_LIST_ELEMENTS_RO(lsp->flooding_neighbors[type],
152 node, neighbor_id)) {
153 vty_out(vty, " %s\n",
154 print_sys_hostname(neighbor_id));
155 }
156 }
157 }
158
159 DEFUN (show_lsp_flooding,
160 show_lsp_flooding_cmd,
161 "show openfabric flooding [WORD]",
162 SHOW_STR
163 PROTO_HELP
164 "Flooding information\n"
165 "LSP ID\n")
166 {
167 const char *lspid = NULL;
168
169 if (argc == 4)
170 lspid = argv[3]->arg;
171
172 struct listnode *node;
173 struct isis_area *area;
174
175 for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) {
176 struct lspdb_head *head = &area->lspdb[ISIS_LEVEL2 - 1];
177 struct isis_lsp *lsp;
178
179 vty_out(vty, "Area %s:\n", area->area_tag ?
180 area->area_tag : "null");
181
182 if (lspid) {
183 lsp = lsp_for_arg(head, lspid);
184
185 if (lsp)
186 lsp_print_flooding(vty, lsp);
187
188 continue;
189 }
190
191 frr_each (lspdb, head, lsp) {
192 lsp_print_flooding(vty, lsp);
193 vty_out(vty, "\n");
194 }
195 }
196
197 return CMD_SUCCESS;
198 }
199
200 DEFUN (ip_router_isis,
201 ip_router_isis_cmd,
202 "ip router " PROTO_NAME " WORD",
203 "Interface Internet Protocol config commands\n"
204 "IP router interface commands\n"
205 PROTO_HELP
206 "Routing process tag\n")
207 {
208 int idx_afi = 0;
209 int idx_word = 3;
210 VTY_DECLVAR_CONTEXT(interface, ifp);
211 struct isis_circuit *circuit;
212 struct isis_area *area;
213 const char *af = argv[idx_afi]->arg;
214 const char *area_tag = argv[idx_word]->arg;
215
216 /* Prevent more than one area per circuit */
217 circuit = circuit_scan_by_ifp(ifp);
218 if (circuit && circuit->area) {
219 if (strcmp(circuit->area->area_tag, area_tag)) {
220 vty_out(vty, "ISIS circuit is already defined on %s\n",
221 circuit->area->area_tag);
222 return CMD_ERR_NOTHING_TODO;
223 }
224 }
225
226 area = isis_area_lookup(area_tag);
227 if (!area)
228 area = isis_area_create(area_tag);
229
230 if (!circuit || !circuit->area) {
231 circuit = isis_circuit_create(area, ifp);
232
233 if (circuit->state != C_STATE_CONF
234 && circuit->state != C_STATE_UP) {
235 vty_out(vty,
236 "Couldn't bring up interface, please check log.\n");
237 return CMD_WARNING_CONFIG_FAILED;
238 }
239 }
240
241 bool ip = circuit->ip_router, ipv6 = circuit->ipv6_router;
242 if (af[2] != '\0')
243 ipv6 = true;
244 else
245 ip = true;
246
247 isis_circuit_af_set(circuit, ip, ipv6);
248 return CMD_SUCCESS;
249 }
250
251 DEFUN (ip6_router_isis,
252 ip6_router_isis_cmd,
253 "ipv6 router " PROTO_NAME " WORD",
254 "Interface Internet Protocol config commands\n"
255 "IP router interface commands\n"
256 PROTO_HELP
257 "Routing process tag\n")
258 {
259 return ip_router_isis(self, vty, argc, argv);
260 }
261
262 DEFUN (no_ip_router_isis,
263 no_ip_router_isis_cmd,
264 "no <ip|ipv6> router " PROTO_NAME " WORD",
265 NO_STR
266 "Interface Internet Protocol config commands\n"
267 "IP router interface commands\n"
268 "IP router interface commands\n"
269 PROTO_HELP
270 "Routing process tag\n")
271 {
272 int idx_afi = 1;
273 int idx_word = 4;
274 VTY_DECLVAR_CONTEXT(interface, ifp);
275 struct isis_area *area;
276 struct isis_circuit *circuit;
277 const char *af = argv[idx_afi]->arg;
278 const char *area_tag = argv[idx_word]->arg;
279
280 area = isis_area_lookup(area_tag);
281 if (!area) {
282 vty_out(vty, "Can't find ISIS instance %s\n",
283 area_tag);
284 return CMD_ERR_NO_MATCH;
285 }
286
287 circuit = circuit_lookup_by_ifp(ifp, area->circuit_list);
288 if (!circuit) {
289 vty_out(vty, "ISIS is not enabled on circuit %s\n", ifp->name);
290 return CMD_ERR_NO_MATCH;
291 }
292
293 bool ip = circuit->ip_router, ipv6 = circuit->ipv6_router;
294 if (af[2] != '\0')
295 ipv6 = false;
296 else
297 ip = false;
298
299 isis_circuit_af_set(circuit, ip, ipv6);
300 return CMD_SUCCESS;
301 }
302
303 DEFUN (isis_bfd,
304 isis_bfd_cmd,
305 PROTO_NAME " bfd",
306 PROTO_HELP
307 "Enable BFD support\n")
308 {
309 struct isis_circuit *circuit = isis_circuit_lookup(vty);
310
311 if (!circuit)
312 return CMD_ERR_NO_MATCH;
313
314 if (circuit->bfd_info
315 && CHECK_FLAG(circuit->bfd_info->flags, BFD_FLAG_PARAM_CFG)) {
316 return CMD_SUCCESS;
317 }
318
319 isis_bfd_circuit_param_set(circuit, BFD_DEF_MIN_RX,
320 BFD_DEF_MIN_TX, BFD_DEF_DETECT_MULT, true);
321
322 return CMD_SUCCESS;
323 }
324
325 DEFUN (no_isis_bfd,
326 no_isis_bfd_cmd,
327 "no " PROTO_NAME " bfd",
328 NO_STR
329 PROTO_HELP
330 "Disables BFD support\n"
331 )
332 {
333 struct isis_circuit *circuit = isis_circuit_lookup(vty);
334
335 if (!circuit)
336 return CMD_ERR_NO_MATCH;
337
338 if (!circuit->bfd_info)
339 return CMD_SUCCESS;
340
341 isis_bfd_circuit_cmd(circuit, ZEBRA_BFD_DEST_DEREGISTER);
342 bfd_info_free(&circuit->bfd_info);
343 return CMD_SUCCESS;
344 }
345
346 DEFUN (set_overload_bit,
347 set_overload_bit_cmd,
348 "set-overload-bit",
349 "Set overload bit to avoid any transit traffic\n")
350 {
351 VTY_DECLVAR_CONTEXT(isis_area, area);
352
353 isis_area_overload_bit_set(area, true);
354 return CMD_SUCCESS;
355 }
356
357 DEFUN (no_set_overload_bit,
358 no_set_overload_bit_cmd,
359 "no set-overload-bit",
360 "Reset overload bit to accept transit traffic\n"
361 "Reset overload bit\n")
362 {
363 VTY_DECLVAR_CONTEXT(isis_area, area);
364
365 isis_area_overload_bit_set(area, false);
366 return CMD_SUCCESS;
367 }
368
369 static int isis_vty_password_set(struct vty *vty, int argc,
370 struct cmd_token *argv[], int level)
371 {
372 VTY_DECLVAR_CONTEXT(isis_area, area);
373
374 int idx_algo = 1;
375 int idx_password = 2;
376 int idx_snp_auth = 5;
377 uint8_t snp_auth = 0;
378
379 const char *passwd = argv[idx_password]->arg;
380 if (strlen(passwd) > 254) {
381 vty_out(vty, "Too long area password (>254)\n");
382 return CMD_WARNING_CONFIG_FAILED;
383 }
384
385 if (argc > idx_snp_auth) {
386 snp_auth = SNP_AUTH_SEND;
387 if (strmatch(argv[idx_snp_auth]->text, "validate"))
388 snp_auth |= SNP_AUTH_RECV;
389 }
390
391 if (strmatch(argv[idx_algo]->text, "clear")) {
392 return isis_area_passwd_cleartext_set(area, level,
393 passwd, snp_auth);
394 } else if (strmatch(argv[idx_algo]->text, "md5")) {
395 return isis_area_passwd_hmac_md5_set(area, level,
396 passwd, snp_auth);
397 }
398
399 return CMD_WARNING_CONFIG_FAILED;
400 }
401
402 DEFUN (domain_passwd,
403 domain_passwd_cmd,
404 "domain-password <clear|md5> WORD [authenticate snp <send-only|validate>]",
405 "Set the authentication password for a routing domain\n"
406 "Authentication type\n"
407 "Authentication type\n"
408 "Level-wide password\n"
409 "Authentication\n"
410 "SNP PDUs\n"
411 "Send but do not check PDUs on receiving\n"
412 "Send and check PDUs on receiving\n")
413 {
414 return isis_vty_password_set(vty, argc, argv, IS_LEVEL_2);
415 }
416
417 DEFUN (no_domain_passwd,
418 no_domain_passwd_cmd,
419 "no domain-password",
420 NO_STR
421 "Set the authentication password for a routing domain\n")
422 {
423 VTY_DECLVAR_CONTEXT(isis_area, area);
424
425 return isis_area_passwd_unset(area, IS_LEVEL_2);
426 }
427
428 static int
429 isis_vty_lsp_gen_interval_set(struct vty *vty, int level, uint16_t interval)
430 {
431 VTY_DECLVAR_CONTEXT(isis_area, area);
432 int lvl;
433
434 for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl) {
435 if (!(lvl & level))
436 continue;
437
438 if (interval >= area->lsp_refresh[lvl - 1]) {
439 vty_out(vty,
440 "LSP gen interval %us must be less than "
441 "the LSP refresh interval %us\n",
442 interval, area->lsp_refresh[lvl - 1]);
443 return CMD_WARNING_CONFIG_FAILED;
444 }
445 }
446
447 for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl) {
448 if (!(lvl & level))
449 continue;
450 area->lsp_gen_interval[lvl - 1] = interval;
451 }
452
453 return CMD_SUCCESS;
454 }
455
456 DEFUN (lsp_gen_interval,
457 lsp_gen_interval_cmd,
458 "lsp-gen-interval (1-120)",
459 "Minimum interval between regenerating same LSP\n"
460 "Minimum interval in seconds\n")
461 {
462 uint16_t interval = atoi(argv[1]->arg);
463
464 return isis_vty_lsp_gen_interval_set(vty, IS_LEVEL_1_AND_2, interval);
465 }
466
467 DEFUN (no_lsp_gen_interval,
468 no_lsp_gen_interval_cmd,
469 "no lsp-gen-interval [(1-120)]",
470 NO_STR
471 "Minimum interval between regenerating same LSP\n"
472 "Minimum interval in seconds\n")
473 {
474 VTY_DECLVAR_CONTEXT(isis_area, area);
475
476 return isis_vty_lsp_gen_interval_set(vty, IS_LEVEL_1_AND_2,
477 DEFAULT_MIN_LSP_GEN_INTERVAL);
478 }
479
480 static int
481 isis_vty_lsp_refresh_set(struct vty *vty, int level, uint16_t interval)
482 {
483 VTY_DECLVAR_CONTEXT(isis_area, area);
484 int lvl;
485
486 for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl) {
487 if (!(lvl & level))
488 continue;
489 if (interval <= area->lsp_gen_interval[lvl - 1]) {
490 vty_out(vty,
491 "LSP refresh interval %us must be greater than "
492 "the configured LSP gen interval %us\n",
493 interval, area->lsp_gen_interval[lvl - 1]);
494 return CMD_WARNING_CONFIG_FAILED;
495 }
496 if (interval > (area->max_lsp_lifetime[lvl - 1] - 300)) {
497 vty_out(vty,
498 "LSP refresh interval %us must be less than "
499 "the configured LSP lifetime %us less 300\n",
500 interval, area->max_lsp_lifetime[lvl - 1]);
501 return CMD_WARNING_CONFIG_FAILED;
502 }
503 }
504
505 for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl) {
506 if (!(lvl & level))
507 continue;
508 isis_area_lsp_refresh_set(area, lvl, interval);
509 }
510
511 return CMD_SUCCESS;
512 }
513
514 DEFUN (lsp_refresh_interval,
515 lsp_refresh_interval_cmd,
516 "lsp-refresh-interval (1-65235)",
517 "LSP refresh interval\n"
518 "LSP refresh interval in seconds\n")
519 {
520 unsigned int interval = atoi(argv[1]->arg);
521 return isis_vty_lsp_refresh_set(vty, IS_LEVEL_1_AND_2, interval);
522 }
523
524 DEFUN (no_lsp_refresh_interval,
525 no_lsp_refresh_interval_cmd,
526 "no lsp-refresh-interval [(1-65235)]",
527 NO_STR
528 "LSP refresh interval\n"
529 "LSP refresh interval in seconds\n")
530 {
531 return isis_vty_lsp_refresh_set(vty, IS_LEVEL_1_AND_2,
532 DEFAULT_MAX_LSP_GEN_INTERVAL);
533 }
534
535 static int
536 isis_vty_max_lsp_lifetime_set(struct vty *vty, int level, uint16_t interval)
537 {
538 VTY_DECLVAR_CONTEXT(isis_area, area);
539 int lvl;
540 uint16_t refresh_interval = interval - 300;
541 int set_refresh_interval[ISIS_LEVELS] = {0, 0};
542
543 for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++) {
544 if (!(lvl & level))
545 continue;
546
547 if (refresh_interval < area->lsp_refresh[lvl - 1]) {
548 vty_out(vty,
549 "Level %d Max LSP lifetime %us must be 300s greater than "
550 "the configured LSP refresh interval %us\n",
551 lvl, interval, area->lsp_refresh[lvl - 1]);
552 vty_out(vty,
553 "Automatically reducing level %d LSP refresh interval "
554 "to %us\n",
555 lvl, refresh_interval);
556 set_refresh_interval[lvl - 1] = 1;
557
558 if (refresh_interval
559 <= area->lsp_gen_interval[lvl - 1]) {
560 vty_out(vty,
561 "LSP refresh interval %us must be greater than "
562 "the configured LSP gen interval %us\n",
563 refresh_interval,
564 area->lsp_gen_interval[lvl - 1]);
565 return CMD_WARNING_CONFIG_FAILED;
566 }
567 }
568 }
569
570 for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++) {
571 if (!(lvl & level))
572 continue;
573 isis_area_max_lsp_lifetime_set(area, lvl, interval);
574 if (set_refresh_interval[lvl - 1])
575 isis_area_lsp_refresh_set(area, lvl, refresh_interval);
576 }
577
578 return CMD_SUCCESS;
579 }
580
581 DEFUN (max_lsp_lifetime,
582 max_lsp_lifetime_cmd,
583 "max-lsp-lifetime (350-65535)",
584 "Maximum LSP lifetime\n"
585 "LSP lifetime in seconds\n")
586 {
587 int lifetime = atoi(argv[1]->arg);
588
589 return isis_vty_max_lsp_lifetime_set(vty, IS_LEVEL_1_AND_2, lifetime);
590 }
591
592
593 DEFUN (no_max_lsp_lifetime,
594 no_max_lsp_lifetime_cmd,
595 "no max-lsp-lifetime [(350-65535)]",
596 NO_STR
597 "Maximum LSP lifetime\n"
598 "LSP lifetime in seconds\n")
599 {
600 return isis_vty_max_lsp_lifetime_set(vty, IS_LEVEL_1_AND_2,
601 DEFAULT_LSP_LIFETIME);
602 }
603
604 DEFUN (spf_interval,
605 spf_interval_cmd,
606 "spf-interval (1-120)",
607 "Minimum interval between SPF calculations\n"
608 "Minimum interval between consecutive SPFs in seconds\n")
609 {
610 VTY_DECLVAR_CONTEXT(isis_area, area);
611 uint16_t interval = atoi(argv[1]->arg);
612
613 area->min_spf_interval[0] = interval;
614 area->min_spf_interval[1] = interval;
615
616 return CMD_SUCCESS;
617 }
618
619 DEFUN (no_spf_interval,
620 no_spf_interval_cmd,
621 "no spf-interval [(1-120)]",
622 NO_STR
623 "Minimum interval between SPF calculations\n"
624 "Minimum interval between consecutive SPFs in seconds\n")
625 {
626 VTY_DECLVAR_CONTEXT(isis_area, area);
627
628 area->min_spf_interval[0] = MINIMUM_SPF_INTERVAL;
629 area->min_spf_interval[1] = MINIMUM_SPF_INTERVAL;
630
631 return CMD_SUCCESS;
632 }
633
634 static int isis_vty_lsp_mtu_set(struct vty *vty, unsigned int lsp_mtu)
635 {
636 VTY_DECLVAR_CONTEXT(isis_area, area);
637 struct listnode *node;
638 struct isis_circuit *circuit;
639
640 for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) {
641 if (circuit->state != C_STATE_INIT
642 && circuit->state != C_STATE_UP)
643 continue;
644 if (lsp_mtu > isis_circuit_pdu_size(circuit)) {
645 vty_out(vty,
646 "ISIS area contains circuit %s, which has a maximum PDU size of %zu.\n",
647 circuit->interface->name,
648 isis_circuit_pdu_size(circuit));
649 return CMD_WARNING_CONFIG_FAILED;
650 }
651 }
652
653 isis_area_lsp_mtu_set(area, lsp_mtu);
654 return CMD_SUCCESS;
655 }
656
657 DEFUN (area_lsp_mtu,
658 area_lsp_mtu_cmd,
659 "lsp-mtu (128-4352)",
660 "Configure the maximum size of generated LSPs\n"
661 "Maximum size of generated LSPs\n")
662 {
663 int idx_number = 1;
664 unsigned int lsp_mtu;
665
666 lsp_mtu = strtoul(argv[idx_number]->arg, NULL, 10);
667
668 return isis_vty_lsp_mtu_set(vty, lsp_mtu);
669 }
670
671 DEFUN (no_area_lsp_mtu,
672 no_area_lsp_mtu_cmd,
673 "no lsp-mtu [(128-4352)]",
674 NO_STR
675 "Configure the maximum size of generated LSPs\n"
676 "Maximum size of generated LSPs\n")
677 {
678 return isis_vty_lsp_mtu_set(vty, DEFAULT_LSP_MTU);
679 }
680
681 DEFUN (no_spf_delay_ietf,
682 no_spf_delay_ietf_cmd,
683 "no spf-delay-ietf",
684 NO_STR
685 "IETF SPF delay algorithm\n")
686 {
687 VTY_DECLVAR_CONTEXT(isis_area, area);
688
689 spf_backoff_free(area->spf_delay_ietf[0]);
690 spf_backoff_free(area->spf_delay_ietf[1]);
691 area->spf_delay_ietf[0] = NULL;
692 area->spf_delay_ietf[1] = NULL;
693
694 return CMD_SUCCESS;
695 }
696
697 DEFUN (spf_delay_ietf,
698 spf_delay_ietf_cmd,
699 "spf-delay-ietf init-delay (0-60000) short-delay (0-60000) long-delay (0-60000) holddown (0-60000) time-to-learn (0-60000)",
700 "IETF SPF delay algorithm\n"
701 "Delay used while in QUIET state\n"
702 "Delay used while in QUIET state in milliseconds\n"
703 "Delay used while in SHORT_WAIT state\n"
704 "Delay used while in SHORT_WAIT state in milliseconds\n"
705 "Delay used while in LONG_WAIT\n"
706 "Delay used while in LONG_WAIT state in milliseconds\n"
707 "Time with no received IGP events before considering IGP stable\n"
708 "Time with no received IGP events before considering IGP stable (in milliseconds)\n"
709 "Maximum duration needed to learn all the events related to a single failure\n"
710 "Maximum duration needed to learn all the events related to a single failure (in milliseconds)\n")
711 {
712 VTY_DECLVAR_CONTEXT(isis_area, area);
713
714 long init_delay = atol(argv[2]->arg);
715 long short_delay = atol(argv[4]->arg);
716 long long_delay = atol(argv[6]->arg);
717 long holddown = atol(argv[8]->arg);
718 long timetolearn = atol(argv[10]->arg);
719
720 size_t bufsiz = strlen(area->area_tag) + sizeof("IS-IS Lx");
721 char *buf = XCALLOC(MTYPE_TMP, bufsiz);
722
723 snprintf(buf, bufsiz, "IS-IS %s L1", area->area_tag);
724 spf_backoff_free(area->spf_delay_ietf[0]);
725 area->spf_delay_ietf[0] =
726 spf_backoff_new(master, buf, init_delay, short_delay,
727 long_delay, holddown, timetolearn);
728
729 snprintf(buf, bufsiz, "IS-IS %s L2", area->area_tag);
730 spf_backoff_free(area->spf_delay_ietf[1]);
731 area->spf_delay_ietf[1] =
732 spf_backoff_new(master, buf, init_delay, short_delay,
733 long_delay, holddown, timetolearn);
734
735 XFREE(MTYPE_TMP, buf);
736 return CMD_SUCCESS;
737 }
738
739 DEFUN (area_purge_originator,
740 area_purge_originator_cmd,
741 "[no] purge-originator",
742 NO_STR
743 "Use the RFC 6232 purge-originator\n")
744 {
745 VTY_DECLVAR_CONTEXT(isis_area, area);
746
747 area->purge_originator = !!strcmp(argv[0]->text, "no");
748 return CMD_SUCCESS;
749 }
750
751 DEFUN (isis_passive,
752 isis_passive_cmd,
753 PROTO_NAME " passive",
754 PROTO_HELP
755 "Configure the passive mode for interface\n")
756 {
757 struct isis_circuit *circuit = isis_circuit_lookup(vty);
758 if (!circuit)
759 return CMD_ERR_NO_MATCH;
760
761 CMD_FERR_RETURN(isis_circuit_passive_set(circuit, 1),
762 "Cannot set passive: $ERR");
763 return CMD_SUCCESS;
764 }
765
766 DEFUN (no_isis_passive,
767 no_isis_passive_cmd,
768 "no " PROTO_NAME " passive",
769 NO_STR
770 PROTO_HELP
771 "Configure the passive mode for interface\n")
772 {
773 struct isis_circuit *circuit = isis_circuit_lookup(vty);
774 if (!circuit)
775 return CMD_ERR_NO_MATCH;
776
777 CMD_FERR_RETURN(isis_circuit_passive_set(circuit, 0),
778 "Cannot set no passive: $ERR");
779 return CMD_SUCCESS;
780 }
781
782 DEFUN (isis_passwd,
783 isis_passwd_cmd,
784 PROTO_NAME " password <md5|clear> WORD",
785 PROTO_HELP
786 "Configure the authentication password for a circuit\n"
787 "HMAC-MD5 authentication\n"
788 "Cleartext password\n"
789 "Circuit password\n")
790 {
791 int idx_encryption = 2;
792 int idx_word = 3;
793 struct isis_circuit *circuit = isis_circuit_lookup(vty);
794 ferr_r rv;
795
796 if (!circuit)
797 return CMD_ERR_NO_MATCH;
798
799 if (argv[idx_encryption]->arg[0] == 'm')
800 rv = isis_circuit_passwd_hmac_md5_set(circuit,
801 argv[idx_word]->arg);
802 else
803 rv = isis_circuit_passwd_cleartext_set(circuit,
804 argv[idx_word]->arg);
805
806 CMD_FERR_RETURN(rv, "Failed to set circuit password: $ERR");
807 return CMD_SUCCESS;
808 }
809
810 DEFUN (no_isis_passwd,
811 no_isis_passwd_cmd,
812 "no " PROTO_NAME " password [<md5|clear> WORD]",
813 NO_STR
814 PROTO_HELP
815 "Configure the authentication password for a circuit\n"
816 "HMAC-MD5 authentication\n"
817 "Cleartext password\n"
818 "Circuit password\n")
819 {
820 struct isis_circuit *circuit = isis_circuit_lookup(vty);
821 if (!circuit)
822 return CMD_ERR_NO_MATCH;
823
824 CMD_FERR_RETURN(isis_circuit_passwd_unset(circuit),
825 "Failed to unset circuit password: $ERR");
826 return CMD_SUCCESS;
827 }
828
829 DEFUN (isis_metric,
830 isis_metric_cmd,
831 PROTO_NAME " metric (0-16777215)",
832 PROTO_HELP
833 "Set default metric for circuit\n"
834 "Default metric value\n")
835 {
836 int idx_number = 2;
837 int met;
838 struct isis_circuit *circuit = isis_circuit_lookup(vty);
839 if (!circuit)
840 return CMD_ERR_NO_MATCH;
841
842 met = atoi(argv[idx_number]->arg);
843
844 /* RFC3787 section 5.1 */
845 if (circuit->area && circuit->area->oldmetric == 1
846 && met > MAX_NARROW_LINK_METRIC) {
847 vty_out(vty,
848 "Invalid metric %d - should be <0-63> "
849 "when narrow metric type enabled\n",
850 met);
851 return CMD_WARNING_CONFIG_FAILED;
852 }
853
854 /* RFC4444 */
855 if (circuit->area && circuit->area->newmetric == 1
856 && met > MAX_WIDE_LINK_METRIC) {
857 vty_out(vty,
858 "Invalid metric %d - should be <0-16777215> "
859 "when wide metric type enabled\n",
860 met);
861 return CMD_WARNING_CONFIG_FAILED;
862 }
863
864 CMD_FERR_RETURN(isis_circuit_metric_set(circuit, IS_LEVEL_1, met),
865 "Failed to set L1 metric: $ERR");
866 CMD_FERR_RETURN(isis_circuit_metric_set(circuit, IS_LEVEL_2, met),
867 "Failed to set L2 metric: $ERR");
868 return CMD_SUCCESS;
869 }
870
871 DEFUN (no_isis_metric,
872 no_isis_metric_cmd,
873 "no " PROTO_NAME " metric [(0-16777215)]",
874 NO_STR
875 PROTO_HELP
876 "Set default metric for circuit\n"
877 "Default metric value\n")
878 {
879 struct isis_circuit *circuit = isis_circuit_lookup(vty);
880 if (!circuit)
881 return CMD_ERR_NO_MATCH;
882
883 CMD_FERR_RETURN(isis_circuit_metric_set(circuit, IS_LEVEL_1,
884 DEFAULT_CIRCUIT_METRIC),
885 "Failed to set L1 metric: $ERR");
886 CMD_FERR_RETURN(isis_circuit_metric_set(circuit, IS_LEVEL_2,
887 DEFAULT_CIRCUIT_METRIC),
888 "Failed to set L2 metric: $ERR");
889 return CMD_SUCCESS;
890 }
891
892 DEFUN (isis_hello_interval,
893 isis_hello_interval_cmd,
894 PROTO_NAME " hello-interval (1-600)",
895 PROTO_HELP
896 "Set Hello interval\n"
897 "Holdtime 1 seconds, interval depends on multiplier\n")
898 {
899 uint32_t interval = atoi(argv[2]->arg);
900 struct isis_circuit *circuit = isis_circuit_lookup(vty);
901 if (!circuit)
902 return CMD_ERR_NO_MATCH;
903
904 circuit->hello_interval[0] = interval;
905 circuit->hello_interval[1] = interval;
906
907 return CMD_SUCCESS;
908 }
909
910 DEFUN (no_isis_hello_interval,
911 no_isis_hello_interval_cmd,
912 "no " PROTO_NAME " hello-interval [(1-600)]",
913 NO_STR
914 PROTO_HELP
915 "Set Hello interval\n"
916 "Holdtime 1 second, interval depends on multiplier\n")
917 {
918 struct isis_circuit *circuit = isis_circuit_lookup(vty);
919 if (!circuit)
920 return CMD_ERR_NO_MATCH;
921
922 circuit->hello_interval[0] = DEFAULT_HELLO_INTERVAL;
923 circuit->hello_interval[1] = DEFAULT_HELLO_INTERVAL;
924
925 return CMD_SUCCESS;
926 }
927
928 DEFUN (isis_hello_multiplier,
929 isis_hello_multiplier_cmd,
930 PROTO_NAME " hello-multiplier (2-100)",
931 PROTO_HELP
932 "Set multiplier for Hello holding time\n"
933 "Hello multiplier value\n")
934 {
935 uint16_t mult = atoi(argv[2]->arg);
936 struct isis_circuit *circuit = isis_circuit_lookup(vty);
937 if (!circuit)
938 return CMD_ERR_NO_MATCH;
939
940 circuit->hello_multiplier[0] = mult;
941 circuit->hello_multiplier[1] = mult;
942
943 return CMD_SUCCESS;
944 }
945
946 DEFUN (no_isis_hello_multiplier,
947 no_isis_hello_multiplier_cmd,
948 "no " PROTO_NAME " hello-multiplier [(2-100)]",
949 NO_STR
950 PROTO_HELP
951 "Set multiplier for Hello holding time\n"
952 "Hello multiplier value\n")
953 {
954 struct isis_circuit *circuit = isis_circuit_lookup(vty);
955 if (!circuit)
956 return CMD_ERR_NO_MATCH;
957
958 circuit->hello_multiplier[0] = DEFAULT_HELLO_MULTIPLIER;
959 circuit->hello_multiplier[1] = DEFAULT_HELLO_MULTIPLIER;
960
961 return CMD_SUCCESS;
962 }
963
964 DEFUN (csnp_interval,
965 csnp_interval_cmd,
966 PROTO_NAME " csnp-interval (1-600)",
967 PROTO_HELP
968 "Set CSNP interval in seconds\n"
969 "CSNP interval value\n")
970 {
971 uint16_t interval = atoi(argv[2]->arg);
972 struct isis_circuit *circuit = isis_circuit_lookup(vty);
973 if (!circuit)
974 return CMD_ERR_NO_MATCH;
975
976 circuit->csnp_interval[0] = interval;
977 circuit->csnp_interval[1] = interval;
978
979 return CMD_SUCCESS;
980 }
981
982 DEFUN (no_csnp_interval,
983 no_csnp_interval_cmd,
984 "no " PROTO_NAME " csnp-interval [(1-600)]",
985 NO_STR
986 PROTO_HELP
987 "Set CSNP interval in seconds\n"
988 "CSNP interval value\n")
989 {
990 struct isis_circuit *circuit = isis_circuit_lookup(vty);
991 if (!circuit)
992 return CMD_ERR_NO_MATCH;
993
994 circuit->csnp_interval[0] = DEFAULT_CSNP_INTERVAL;
995 circuit->csnp_interval[1] = DEFAULT_CSNP_INTERVAL;
996
997 return CMD_SUCCESS;
998 }
999
1000 DEFUN (psnp_interval,
1001 psnp_interval_cmd,
1002 PROTO_NAME " psnp-interval (1-120)",
1003 PROTO_HELP
1004 "Set PSNP interval in seconds\n"
1005 "PSNP interval value\n")
1006 {
1007 uint16_t interval = atoi(argv[2]->arg);
1008 struct isis_circuit *circuit = isis_circuit_lookup(vty);
1009 if (!circuit)
1010 return CMD_ERR_NO_MATCH;
1011
1012 circuit->psnp_interval[0] = interval;
1013 circuit->psnp_interval[1] = interval;
1014
1015 return CMD_SUCCESS;
1016 }
1017
1018 DEFUN (no_psnp_interval,
1019 no_psnp_interval_cmd,
1020 "no " PROTO_NAME " psnp-interval [(1-120)]",
1021 NO_STR
1022 PROTO_HELP
1023 "Set PSNP interval in seconds\n"
1024 "PSNP interval value\n")
1025 {
1026 struct isis_circuit *circuit = isis_circuit_lookup(vty);
1027 if (!circuit)
1028 return CMD_ERR_NO_MATCH;
1029
1030 circuit->psnp_interval[0] = DEFAULT_PSNP_INTERVAL;
1031 circuit->psnp_interval[1] = DEFAULT_PSNP_INTERVAL;
1032
1033 return CMD_SUCCESS;
1034 }
1035
1036 DEFUN (circuit_topology,
1037 circuit_topology_cmd,
1038 PROTO_NAME " topology " ISIS_MT_NAMES,
1039 PROTO_HELP
1040 "Configure interface IS-IS topologies\n"
1041 ISIS_MT_DESCRIPTIONS)
1042 {
1043 struct isis_circuit *circuit = isis_circuit_lookup(vty);
1044 if (!circuit)
1045 return CMD_ERR_NO_MATCH;
1046 const char *arg = argv[2]->arg;
1047 uint16_t mtid = isis_str2mtid(arg);
1048
1049 if (circuit->area && circuit->area->oldmetric) {
1050 vty_out(vty,
1051 "Multi topology IS-IS can only be used with wide metrics\n");
1052 return CMD_WARNING_CONFIG_FAILED;
1053 }
1054
1055 if (mtid == (uint16_t)-1) {
1056 vty_out(vty, "Don't know topology '%s'\n", arg);
1057 return CMD_WARNING_CONFIG_FAILED;
1058 }
1059
1060 return isis_circuit_mt_enabled_set(circuit, mtid, true);
1061 }
1062
1063 DEFUN (no_circuit_topology,
1064 no_circuit_topology_cmd,
1065 "no " PROTO_NAME " topology " ISIS_MT_NAMES,
1066 NO_STR
1067 PROTO_HELP
1068 "Configure interface IS-IS topologies\n"
1069 ISIS_MT_DESCRIPTIONS)
1070 {
1071 struct isis_circuit *circuit = isis_circuit_lookup(vty);
1072 if (!circuit)
1073 return CMD_ERR_NO_MATCH;
1074 const char *arg = argv[3]->arg;
1075 uint16_t mtid = isis_str2mtid(arg);
1076
1077 if (circuit->area && circuit->area->oldmetric) {
1078 vty_out(vty,
1079 "Multi topology IS-IS can only be used with wide metrics\n");
1080 return CMD_WARNING_CONFIG_FAILED;
1081 }
1082
1083 if (mtid == (uint16_t)-1) {
1084 vty_out(vty, "Don't know topology '%s'\n", arg);
1085 return CMD_WARNING_CONFIG_FAILED;
1086 }
1087
1088 return isis_circuit_mt_enabled_set(circuit, mtid, false);
1089 }
1090
1091 void isis_vty_daemon_init(void)
1092 {
1093 install_element(ROUTER_NODE, &fabric_tier_cmd);
1094 install_element(ROUTER_NODE, &no_fabric_tier_cmd);
1095 install_element(ROUTER_NODE, &triggered_csnp_cmd);
1096 install_element(ROUTER_NODE, &no_triggered_csnp_cmd);
1097
1098 install_element(ENABLE_NODE, &show_lsp_flooding_cmd);
1099
1100 install_element(INTERFACE_NODE, &ip_router_isis_cmd);
1101 install_element(INTERFACE_NODE, &ip6_router_isis_cmd);
1102 install_element(INTERFACE_NODE, &no_ip_router_isis_cmd);
1103 install_element(INTERFACE_NODE, &isis_bfd_cmd);
1104 install_element(INTERFACE_NODE, &no_isis_bfd_cmd);
1105
1106 install_element(ROUTER_NODE, &set_overload_bit_cmd);
1107 install_element(ROUTER_NODE, &no_set_overload_bit_cmd);
1108
1109 install_element(ROUTER_NODE, &domain_passwd_cmd);
1110 install_element(ROUTER_NODE, &no_domain_passwd_cmd);
1111
1112 install_element(ROUTER_NODE, &lsp_gen_interval_cmd);
1113 install_element(ROUTER_NODE, &no_lsp_gen_interval_cmd);
1114
1115 install_element(ROUTER_NODE, &lsp_refresh_interval_cmd);
1116 install_element(ROUTER_NODE, &no_lsp_refresh_interval_cmd);
1117
1118 install_element(ROUTER_NODE, &max_lsp_lifetime_cmd);
1119 install_element(ROUTER_NODE, &no_max_lsp_lifetime_cmd);
1120
1121 install_element(ROUTER_NODE, &area_lsp_mtu_cmd);
1122 install_element(ROUTER_NODE, &no_area_lsp_mtu_cmd);
1123
1124 install_element(ROUTER_NODE, &spf_interval_cmd);
1125 install_element(ROUTER_NODE, &no_spf_interval_cmd);
1126
1127 install_element(ROUTER_NODE, &spf_delay_ietf_cmd);
1128 install_element(ROUTER_NODE, &no_spf_delay_ietf_cmd);
1129
1130 install_element(ROUTER_NODE, &area_purge_originator_cmd);
1131
1132 install_element(INTERFACE_NODE, &isis_passive_cmd);
1133 install_element(INTERFACE_NODE, &no_isis_passive_cmd);
1134
1135 install_element(INTERFACE_NODE, &isis_passwd_cmd);
1136 install_element(INTERFACE_NODE, &no_isis_passwd_cmd);
1137
1138 install_element(INTERFACE_NODE, &isis_metric_cmd);
1139 install_element(INTERFACE_NODE, &no_isis_metric_cmd);
1140
1141 install_element(INTERFACE_NODE, &isis_hello_interval_cmd);
1142 install_element(INTERFACE_NODE, &no_isis_hello_interval_cmd);
1143
1144 install_element(INTERFACE_NODE, &isis_hello_multiplier_cmd);
1145 install_element(INTERFACE_NODE, &no_isis_hello_multiplier_cmd);
1146
1147 install_element(INTERFACE_NODE, &csnp_interval_cmd);
1148 install_element(INTERFACE_NODE, &no_csnp_interval_cmd);
1149
1150 install_element(INTERFACE_NODE, &psnp_interval_cmd);
1151 install_element(INTERFACE_NODE, &no_psnp_interval_cmd);
1152
1153 install_element(INTERFACE_NODE, &circuit_topology_cmd);
1154 install_element(INTERFACE_NODE, &no_circuit_topology_cmd);
1155 }