diff options
Diffstat (limited to 'isisd/isis_cli.c')
-rw-r--r-- | isisd/isis_cli.c | 3220 |
1 files changed, 3220 insertions, 0 deletions
diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c new file mode 100644 index 0000000..a673cb8 --- /dev/null +++ b/isisd/isis_cli.c @@ -0,0 +1,3220 @@ +/* + * Copyright (C) 2001,2002 Sampo Saaristo + * Tampere University of Technology + * Institute of Communications Engineering + * Copyright (C) 2018 Volta Networks + * Emanuele Di Pascale + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <zebra.h> + +#include "if.h" +#include "vrf.h" +#include "log.h" +#include "prefix.h" +#include "command.h" +#include "northbound_cli.h" +#include "libfrr.h" +#include "yang.h" +#include "lib/linklist.h" +#include "isisd/isisd.h" +#include "isisd/isis_nb.h" +#include "isisd/isis_misc.h" +#include "isisd/isis_circuit.h" +#include "isisd/isis_csm.h" + +#ifndef VTYSH_EXTRACT_PL +#include "isisd/isis_cli_clippy.c" +#endif + +#ifndef FABRICD + +/* + * XPath: /frr-isisd:isis/instance + */ +DEFPY_YANG_NOSH(router_isis, router_isis_cmd, + "router isis WORD$tag [vrf NAME$vrf_name]", + ROUTER_STR + "ISO IS-IS\n" + "ISO Routing area tag\n" VRF_CMD_HELP_STR) +{ + int ret; + char base_xpath[XPATH_MAXLEN]; + + if (!vrf_name) + vrf_name = VRF_DEFAULT_NAME; + + snprintf(base_xpath, XPATH_MAXLEN, + "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']", tag, + vrf_name); + nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); + + ret = nb_cli_apply_changes(vty, base_xpath); + if (ret == CMD_SUCCESS) + VTY_PUSH_XPATH(ISIS_NODE, base_xpath); + + return ret; +} + +DEFPY_YANG(no_router_isis, no_router_isis_cmd, + "no router isis WORD$tag [vrf NAME$vrf_name]", + NO_STR ROUTER_STR + "ISO IS-IS\n" + "ISO Routing area tag\n" VRF_CMD_HELP_STR) +{ + if (!vrf_name) + vrf_name = VRF_DEFAULT_NAME; + + if (!yang_dnode_existsf( + vty->candidate_config->dnode, + "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']", tag, + vrf_name)) { + vty_out(vty, "ISIS area %s not found.\n", tag); + return CMD_ERR_NOTHING_TODO; + } + + nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes_clear_pending( + vty, "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']", tag, + vrf_name); +} + +void cli_show_router_isis(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + const char *vrf = NULL; + + vrf = yang_dnode_get_string(dnode, "./vrf"); + + vty_out(vty, "!\n"); + vty_out(vty, "router isis %s", + yang_dnode_get_string(dnode, "./area-tag")); + if (!strmatch(vrf, VRF_DEFAULT_NAME)) + vty_out(vty, " vrf %s", yang_dnode_get_string(dnode, "./vrf")); + vty_out(vty, "\n"); +} + +void cli_show_router_isis_end(struct vty *vty, const struct lyd_node *dnode) +{ + vty_out(vty, "exit\n"); +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/ + * XPath: /frr-interface:lib/interface/frr-isisd:isis/ipv4-routing + * XPath: /frr-interface:lib/interface/frr-isisd:isis/ipv6-routing + * XPath: /frr-isisd:isis/instance + */ +DEFPY_YANG(ip_router_isis, ip_router_isis_cmd, + "ip router isis WORD$tag", + "Interface Internet Protocol config commands\n" + "IP router interface commands\n" + "IS-IS routing protocol\n" + "Routing process tag\n") +{ + nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag", NB_OP_MODIFY, + tag); + nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv4-routing", + NB_OP_MODIFY, "true"); + + return nb_cli_apply_changes(vty, NULL); +} + +ALIAS_HIDDEN(ip_router_isis, ip_router_isis_vrf_cmd, + "ip router isis WORD$tag vrf NAME$vrf_name", + "Interface Internet Protocol config commands\n" + "IP router interface commands\n" + "IS-IS routing protocol\n" + "Routing process tag\n" VRF_CMD_HELP_STR) + +DEFPY_YANG(ip6_router_isis, ip6_router_isis_cmd, + "ipv6 router isis WORD$tag", + "Interface Internet Protocol config commands\n" + "IP router interface commands\n" + "IS-IS routing protocol\n" + "Routing process tag\n") +{ + nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag", NB_OP_MODIFY, + tag); + nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv6-routing", + NB_OP_MODIFY, "true"); + + return nb_cli_apply_changes(vty, NULL); +} + +ALIAS_HIDDEN(ip6_router_isis, ip6_router_isis_vrf_cmd, + "ipv6 router isis WORD$tag vrf NAME$vrf_name", + "Interface Internet Protocol config commands\n" + "IP router interface commands\n" + "IS-IS routing protocol\n" + "Routing process tag\n" VRF_CMD_HELP_STR) + +DEFPY_YANG(no_ip_router_isis, no_ip_router_isis_cmd, + "no <ip|ipv6>$ip router isis [WORD]$tag", + NO_STR + "Interface Internet Protocol config commands\n" + "IP router interface commands\n" + "IP router interface commands\n" + "IS-IS routing protocol\n" + "Routing process tag\n") +{ + const struct lyd_node *dnode; + + dnode = yang_dnode_getf(vty->candidate_config->dnode, + "%s/frr-isisd:isis", VTY_CURR_XPATH); + if (!dnode) + return CMD_SUCCESS; + + /* + * If both ipv4 and ipv6 are off delete the interface isis container. + */ + if (strmatch(ip, "ipv6")) { + if (!yang_dnode_get_bool(dnode, "./ipv4-routing")) + nb_cli_enqueue_change(vty, "./frr-isisd:isis", + NB_OP_DESTROY, NULL); + else + nb_cli_enqueue_change(vty, + "./frr-isisd:isis/ipv6-routing", + NB_OP_MODIFY, "false"); + } else { + if (!yang_dnode_get_bool(dnode, "./ipv6-routing")) + nb_cli_enqueue_change(vty, "./frr-isisd:isis", + NB_OP_DESTROY, NULL); + else + nb_cli_enqueue_change(vty, + "./frr-isisd:isis/ipv4-routing", + NB_OP_MODIFY, "false"); + } + + return nb_cli_apply_changes(vty, NULL); +} + +ALIAS_HIDDEN(no_ip_router_isis, no_ip_router_isis_vrf_cmd, + "no <ip|ipv6>$ip router isis WORD$tag vrf NAME$vrf_name", + NO_STR + "Interface Internet Protocol config commands\n" + "IP router interface commands\n" + "IP router interface commands\n" + "IS-IS routing protocol\n" + "Routing process tag\n" + VRF_CMD_HELP_STR) + +void cli_show_ip_isis_ipv4(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + vty_out(vty, " ip router isis %s\n", + yang_dnode_get_string(dnode, "../area-tag")); +} + +void cli_show_ip_isis_ipv6(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + vty_out(vty, " ipv6 router isis %s\n", + yang_dnode_get_string(dnode, "../area-tag")); +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/bfd-monitoring + */ +DEFPY_YANG(isis_bfd, + isis_bfd_cmd, + "[no] isis bfd", + NO_STR PROTO_HELP + "Enable BFD support\n") +{ + const struct lyd_node *dnode; + + dnode = yang_dnode_getf(vty->candidate_config->dnode, + "%s/frr-isisd:isis", VTY_CURR_XPATH); + if (dnode == NULL) { + vty_out(vty, "ISIS is not enabled on this circuit\n"); + return CMD_SUCCESS; + } + + nb_cli_enqueue_change(vty, "./frr-isisd:isis/bfd-monitoring/enabled", + NB_OP_MODIFY, no ? "false" : "true"); + + return nb_cli_apply_changes(vty, NULL); +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/bfd-monitoring/profile + */ +DEFPY_YANG(isis_bfd_profile, + isis_bfd_profile_cmd, + "[no] isis bfd profile BFDPROF$profile", + NO_STR PROTO_HELP + "Enable BFD support\n" + "Use a pre-configured profile\n" + "Profile name\n") +{ + const struct lyd_node *dnode; + + dnode = yang_dnode_getf(vty->candidate_config->dnode, + "%s/frr-isisd:isis", VTY_CURR_XPATH); + if (dnode == NULL) { + vty_out(vty, "ISIS is not enabled on this circuit\n"); + return CMD_SUCCESS; + } + + if (no) + nb_cli_enqueue_change(vty, + "./frr-isisd:isis/bfd-monitoring/profile", + NB_OP_DESTROY, NULL); + else + nb_cli_enqueue_change(vty, + "./frr-isisd:isis/bfd-monitoring/profile", + NB_OP_MODIFY, profile); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_ip_isis_bfd_monitoring(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, "./enabled")) { + if (show_defaults) + vty_out(vty, " no isis bfd\n"); + } else { + vty_out(vty, " isis bfd\n"); + } + + if (yang_dnode_exists(dnode, "./profile")) + vty_out(vty, " isis bfd profile %s\n", + yang_dnode_get_string(dnode, "./profile")); +} + +/* + * XPath: /frr-isisd:isis/instance/area-address + */ +DEFPY_YANG(net, net_cmd, "[no] net WORD", + "Remove an existing Network Entity Title for this process\n" + "A Network Entity Title for this process (OSI only)\n" + "XX.XXXX. ... .XXX.XX Network entity title (NET)\n") +{ + nb_cli_enqueue_change(vty, "./area-address", + no ? NB_OP_DESTROY : NB_OP_CREATE, net); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_area_address(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " net %s\n", yang_dnode_get_string(dnode, NULL)); +} + +/* + * XPath: /frr-isisd:isis/instance/is-type + */ +DEFPY_YANG(is_type, is_type_cmd, "is-type <level-1|level-1-2|level-2-only>$level", + "IS Level for this routing process (OSI only)\n" + "Act as a station router only\n" + "Act as both a station router and an area router\n" + "Act as an area router only\n") +{ + nb_cli_enqueue_change(vty, "./is-type", NB_OP_MODIFY, + strmatch(level, "level-2-only") ? "level-2" + : level); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG(no_is_type, no_is_type_cmd, + "no is-type [<level-1|level-1-2|level-2-only>]", + NO_STR + "IS Level for this routing process (OSI only)\n" + "Act as a station router only\n" + "Act as both a station router and an area router\n" + "Act as an area router only\n") +{ + nb_cli_enqueue_change(vty, "./is-type", NB_OP_MODIFY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_is_type(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + int is_type = yang_dnode_get_enum(dnode, NULL); + + switch (is_type) { + case IS_LEVEL_1: + vty_out(vty, " is-type level-1\n"); + break; + case IS_LEVEL_2: + vty_out(vty, " is-type level-2-only\n"); + break; + case IS_LEVEL_1_AND_2: + vty_out(vty, " is-type level-1-2\n"); + break; + } +} + +/* + * XPath: /frr-isisd:isis/instance/dynamic-hostname + */ +DEFPY_YANG(dynamic_hostname, dynamic_hostname_cmd, "[no] hostname dynamic", + NO_STR + "Dynamic hostname for IS-IS\n" + "Dynamic hostname\n") +{ + nb_cli_enqueue_change(vty, "./dynamic-hostname", NB_OP_MODIFY, + no ? "false" : "true"); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_dynamic_hostname(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + + vty_out(vty, " hostname dynamic\n"); +} + +/* + * XPath: /frr-isisd:isis/instance/overload + */ +DEFPY_YANG(set_overload_bit, set_overload_bit_cmd, "[no] set-overload-bit", + "Reset overload bit to accept transit traffic\n" + "Set overload bit to avoid any transit traffic\n") +{ + nb_cli_enqueue_change(vty, "./overload", NB_OP_MODIFY, + no ? "false" : "true"); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_overload(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + vty_out(vty, " set-overload-bit\n"); +} + +/* + * XPath: /frr-isisd:isis/instance/attach-send + */ +DEFPY_YANG(attached_bit_send, attached_bit_send_cmd, "[no] attached-bit send", + "Reset attached bit\n" + "Set attached bit for inter-area traffic\n" + "Set attached bit in LSP sent to L1 router\n") +{ + nb_cli_enqueue_change(vty, "./attach-send", NB_OP_MODIFY, + no ? "false" : "true"); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_attached_send(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + vty_out(vty, " attached-bit send\n"); +} + +/* + * XPath: /frr-isisd:isis/instance/attach-receive-ignore + */ +DEFPY_YANG( + attached_bit_receive_ignore, attached_bit_receive_ignore_cmd, + "[no] attached-bit receive ignore", + "Reset attached bit\n" + "Set attach bit for inter-area traffic\n" + "If LSP received with attached bit set, create default route to neighbor\n" + "Do not process attached bit\n") +{ + nb_cli_enqueue_change(vty, "./attach-receive-ignore", NB_OP_MODIFY, + no ? "false" : "true"); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_attached_receive(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + vty_out(vty, " attached-bit receive ignore\n"); +} + +/* + * XPath: /frr-isisd:isis/instance/metric-style + */ +DEFPY_YANG(metric_style, metric_style_cmd, + "metric-style <narrow|transition|wide>$style", + "Use old-style (ISO 10589) or new-style packet formats\n" + "Use old style of TLVs with narrow metric\n" + "Send and accept both styles of TLVs during transition\n" + "Use new style of TLVs to carry wider metric\n") +{ + nb_cli_enqueue_change(vty, "./metric-style", NB_OP_MODIFY, style); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG(no_metric_style, no_metric_style_cmd, + "no metric-style [narrow|transition|wide]", + NO_STR + "Use old-style (ISO 10589) or new-style packet formats\n" + "Use old style of TLVs with narrow metric\n" + "Send and accept both styles of TLVs during transition\n" + "Use new style of TLVs to carry wider metric\n") +{ + nb_cli_enqueue_change(vty, "./metric-style", NB_OP_MODIFY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_metric_style(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + int metric = yang_dnode_get_enum(dnode, NULL); + + switch (metric) { + case ISIS_NARROW_METRIC: + vty_out(vty, " metric-style narrow\n"); + break; + case ISIS_WIDE_METRIC: + vty_out(vty, " metric-style wide\n"); + break; + case ISIS_TRANSITION_METRIC: + vty_out(vty, " metric-style transition\n"); + break; + } +} + +/* + * XPath: /frr-isisd:isis/instance/area-password + */ +DEFPY_YANG(area_passwd, area_passwd_cmd, + "area-password <clear|md5>$pwd_type WORD$pwd [authenticate snp <send-only|validate>$snp]", + "Configure the authentication password for an area\n" + "Clear-text authentication type\n" + "MD5 authentication type\n" + "Level-wide password\n" + "Authentication\n" + "SNP PDUs\n" + "Send but do not check PDUs on receiving\n" + "Send and check PDUs on receiving\n") +{ + nb_cli_enqueue_change(vty, "./area-password", NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./area-password/password", NB_OP_MODIFY, + pwd); + nb_cli_enqueue_change(vty, "./area-password/password-type", + NB_OP_MODIFY, pwd_type); + nb_cli_enqueue_change(vty, "./area-password/authenticate-snp", + NB_OP_MODIFY, snp ? snp : "none"); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_area_pwd(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + const char *snp; + + vty_out(vty, " area-password %s %s", + yang_dnode_get_string(dnode, "./password-type"), + yang_dnode_get_string(dnode, "./password")); + snp = yang_dnode_get_string(dnode, "./authenticate-snp"); + if (!strmatch("none", snp)) + vty_out(vty, " authenticate snp %s", snp); + vty_out(vty, "\n"); +} + +/* + * XPath: /frr-isisd:isis/instance/domain-password + */ +DEFPY_YANG(domain_passwd, domain_passwd_cmd, + "domain-password <clear|md5>$pwd_type WORD$pwd [authenticate snp <send-only|validate>$snp]", + "Set the authentication password for a routing domain\n" + "Clear-text authentication type\n" + "MD5 authentication type\n" + "Level-wide password\n" + "Authentication\n" + "SNP PDUs\n" + "Send but do not check PDUs on receiving\n" + "Send and check PDUs on receiving\n") +{ + nb_cli_enqueue_change(vty, "./domain-password", NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./domain-password/password", NB_OP_MODIFY, + pwd); + nb_cli_enqueue_change(vty, "./domain-password/password-type", + NB_OP_MODIFY, pwd_type); + nb_cli_enqueue_change(vty, "./domain-password/authenticate-snp", + NB_OP_MODIFY, snp ? snp : "none"); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG(no_area_passwd, no_area_passwd_cmd, + "no <area-password|domain-password>$cmd", + NO_STR + "Configure the authentication password for an area\n" + "Set the authentication password for a routing domain\n") +{ + nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, "./%s", cmd); +} + +void cli_show_isis_domain_pwd(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + const char *snp; + + vty_out(vty, " domain-password %s %s", + yang_dnode_get_string(dnode, "./password-type"), + yang_dnode_get_string(dnode, "./password")); + snp = yang_dnode_get_string(dnode, "./authenticate-snp"); + if (!strmatch("none", snp)) + vty_out(vty, " authenticate snp %s", snp); + vty_out(vty, "\n"); +} + +/* + * XPath: /frr-isisd:isis/instance/lsp/timers/level-1/generation-interval + * XPath: /frr-isisd:isis/instance/lsp/timers/level-2/generation-interval + */ +DEFPY_YANG(lsp_gen_interval, lsp_gen_interval_cmd, + "lsp-gen-interval [level-1|level-2]$level (1-120)$val", + "Minimum interval between regenerating same LSP\n" + "Set interval for level 1 only\n" + "Set interval for level 2 only\n" + "Minimum interval in seconds\n") +{ + if (!level || strmatch(level, "level-1")) + nb_cli_enqueue_change( + vty, "./lsp/timers/level-1/generation-interval", + NB_OP_MODIFY, val_str); + if (!level || strmatch(level, "level-2")) + nb_cli_enqueue_change( + vty, "./lsp/timers/level-2/generation-interval", + NB_OP_MODIFY, val_str); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG(no_lsp_gen_interval, no_lsp_gen_interval_cmd, + "no lsp-gen-interval [level-1|level-2]$level [(1-120)]", + NO_STR + "Minimum interval between regenerating same LSP\n" + "Set interval for level 1 only\n" + "Set interval for level 2 only\n" + "Minimum interval in seconds\n") +{ + if (!level || strmatch(level, "level-1")) + nb_cli_enqueue_change( + vty, "./lsp/timers/level-1/generation-interval", + NB_OP_MODIFY, NULL); + if (!level || strmatch(level, "level-2")) + nb_cli_enqueue_change( + vty, "./lsp/timers/level-2/generation-interval", + NB_OP_MODIFY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +/* + * XPath: /frr-isisd:isis/instance/lsp/timers/level-1/refresh-interval + * XPath: /frr-isisd:isis/instance/lsp/timers/level-2/refresh-interval + */ +DEFPY_YANG(lsp_refresh_interval, lsp_refresh_interval_cmd, + "lsp-refresh-interval [level-1|level-2]$level (1-65235)$val", + "LSP refresh interval\n" + "LSP refresh interval for Level 1 only\n" + "LSP refresh interval for Level 2 only\n" + "LSP refresh interval in seconds\n") +{ + if (!level || strmatch(level, "level-1")) + nb_cli_enqueue_change(vty, + "./lsp/timers/level-1/refresh-interval", + NB_OP_MODIFY, val_str); + if (!level || strmatch(level, "level-2")) + nb_cli_enqueue_change(vty, + "./lsp/timers/level-2/refresh-interval", + NB_OP_MODIFY, val_str); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG(no_lsp_refresh_interval, no_lsp_refresh_interval_cmd, + "no lsp-refresh-interval [level-1|level-2]$level [(1-65235)]", + NO_STR + "LSP refresh interval\n" + "LSP refresh interval for Level 1 only\n" + "LSP refresh interval for Level 2 only\n" + "LSP refresh interval in seconds\n") +{ + if (!level || strmatch(level, "level-1")) + nb_cli_enqueue_change(vty, + "./lsp/timers/level-1/refresh-interval", + NB_OP_MODIFY, NULL); + if (!level || strmatch(level, "level-2")) + nb_cli_enqueue_change(vty, + "./lsp/timers/level-2/refresh-interval", + NB_OP_MODIFY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +/* + * XPath: /frr-isisd:isis/instance/lsp/timers/level-1/maximum-lifetime + * XPath: /frr-isisd:isis/instance/lsp/timers/level-1/maximum-lifetime + */ + +DEFPY_YANG(max_lsp_lifetime, max_lsp_lifetime_cmd, + "max-lsp-lifetime [level-1|level-2]$level (350-65535)$val", + "Maximum LSP lifetime\n" + "Maximum LSP lifetime for Level 1 only\n" + "Maximum LSP lifetime for Level 2 only\n" + "LSP lifetime in seconds\n") +{ + if (!level || strmatch(level, "level-1")) + nb_cli_enqueue_change(vty, + "./lsp/timers/level-1/maximum-lifetime", + NB_OP_MODIFY, val_str); + if (!level || strmatch(level, "level-2")) + nb_cli_enqueue_change(vty, + "./lsp/timers/level-2/maximum-lifetime", + NB_OP_MODIFY, val_str); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG(no_max_lsp_lifetime, no_max_lsp_lifetime_cmd, + "no max-lsp-lifetime [level-1|level-2]$level [(350-65535)]", + NO_STR + "Maximum LSP lifetime\n" + "Maximum LSP lifetime for Level 1 only\n" + "Maximum LSP lifetime for Level 2 only\n" + "LSP lifetime in seconds\n") +{ + if (!level || strmatch(level, "level-1")) + nb_cli_enqueue_change(vty, + "./lsp/timers/level-1/maximum-lifetime", + NB_OP_MODIFY, NULL); + if (!level || strmatch(level, "level-2")) + nb_cli_enqueue_change(vty, + "./lsp/timers/level-2/maximum-lifetime", + NB_OP_MODIFY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +/* unified LSP timers command + * XPath: /frr-isisd:isis/instance/lsp/timers + */ + +DEFPY_YANG(lsp_timers, lsp_timers_cmd, + "lsp-timers [level-1|level-2]$level gen-interval (1-120)$gen refresh-interval (1-65235)$refresh max-lifetime (350-65535)$lifetime", + "LSP-related timers\n" + "LSP-related timers for Level 1 only\n" + "LSP-related timers for Level 2 only\n" + "Minimum interval between regenerating same LSP\n" + "Generation interval in seconds\n" + "LSP refresh interval\n" + "LSP refresh interval in seconds\n" + "Maximum LSP lifetime\n" + "Maximum LSP lifetime in seconds\n") +{ + if (!level || strmatch(level, "level-1")) { + nb_cli_enqueue_change( + vty, "./lsp/timers/level-1/generation-interval", + NB_OP_MODIFY, gen_str); + nb_cli_enqueue_change(vty, + "./lsp/timers/level-1/refresh-interval", + NB_OP_MODIFY, refresh_str); + nb_cli_enqueue_change(vty, + "./lsp/timers/level-1/maximum-lifetime", + NB_OP_MODIFY, lifetime_str); + } + if (!level || strmatch(level, "level-2")) { + nb_cli_enqueue_change( + vty, "./lsp/timers/level-2/generation-interval", + NB_OP_MODIFY, gen_str); + nb_cli_enqueue_change(vty, + "./lsp/timers/level-2/refresh-interval", + NB_OP_MODIFY, refresh_str); + nb_cli_enqueue_change(vty, + "./lsp/timers/level-2/maximum-lifetime", + NB_OP_MODIFY, lifetime_str); + } + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG(no_lsp_timers, no_lsp_timers_cmd, + "no lsp-timers [level-1|level-2]$level [gen-interval (1-120) refresh-interval (1-65235) max-lifetime (350-65535)]", + NO_STR + "LSP-related timers\n" + "LSP-related timers for Level 1 only\n" + "LSP-related timers for Level 2 only\n" + "Minimum interval between regenerating same LSP\n" + "Generation interval in seconds\n" + "LSP refresh interval\n" + "LSP refresh interval in seconds\n" + "Maximum LSP lifetime\n" + "Maximum LSP lifetime in seconds\n") +{ + if (!level || strmatch(level, "level-1")) { + nb_cli_enqueue_change( + vty, "./lsp/timers/level-1/generation-interval", + NB_OP_MODIFY, NULL); + nb_cli_enqueue_change(vty, + "./lsp/timers/level-1/refresh-interval", + NB_OP_MODIFY, NULL); + nb_cli_enqueue_change(vty, + "./lsp/timers/level-1/maximum-lifetime", + NB_OP_MODIFY, NULL); + } + if (!level || strmatch(level, "level-2")) { + nb_cli_enqueue_change( + vty, "./lsp/timers/level-2/generation-interval", + NB_OP_MODIFY, NULL); + nb_cli_enqueue_change(vty, + "./lsp/timers/level-2/refresh-interval", + NB_OP_MODIFY, NULL); + nb_cli_enqueue_change(vty, + "./lsp/timers/level-2/maximum-lifetime", + NB_OP_MODIFY, NULL); + } + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_lsp_timers(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + const char *l1_refresh = + yang_dnode_get_string(dnode, "./level-1/refresh-interval"); + const char *l2_refresh = + yang_dnode_get_string(dnode, "./level-2/refresh-interval"); + const char *l1_lifetime = + yang_dnode_get_string(dnode, "./level-1/maximum-lifetime"); + const char *l2_lifetime = + yang_dnode_get_string(dnode, "./level-2/maximum-lifetime"); + const char *l1_gen = + yang_dnode_get_string(dnode, "./level-1/generation-interval"); + const char *l2_gen = + yang_dnode_get_string(dnode, "./level-2/generation-interval"); + if (strmatch(l1_refresh, l2_refresh) + && strmatch(l1_lifetime, l2_lifetime) && strmatch(l1_gen, l2_gen)) + vty_out(vty, + " lsp-timers gen-interval %s refresh-interval %s max-lifetime %s\n", + l1_gen, l1_refresh, l1_lifetime); + else { + vty_out(vty, + " lsp-timers level-1 gen-interval %s refresh-interval %s max-lifetime %s\n", + l1_gen, l1_refresh, l1_lifetime); + vty_out(vty, + " lsp-timers level-2 gen-interval %s refresh-interval %s max-lifetime %s\n", + l2_gen, l2_refresh, l2_lifetime); + } +} + +/* + * XPath: /frr-isisd:isis/instance/lsp/mtu + */ +DEFPY_YANG(area_lsp_mtu, area_lsp_mtu_cmd, "lsp-mtu (128-4352)$val", + "Configure the maximum size of generated LSPs\n" + "Maximum size of generated LSPs\n") +{ + nb_cli_enqueue_change(vty, "./lsp/mtu", NB_OP_MODIFY, val_str); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG(no_area_lsp_mtu, no_area_lsp_mtu_cmd, "no lsp-mtu [(128-4352)]", + NO_STR + "Configure the maximum size of generated LSPs\n" + "Maximum size of generated LSPs\n") +{ + nb_cli_enqueue_change(vty, "./lsp/mtu", NB_OP_MODIFY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_lsp_mtu(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " lsp-mtu %s\n", yang_dnode_get_string(dnode, NULL)); +} + +/* + * XPath: /frr-isisd:isis/instance/spf/minimum-interval + */ +DEFPY_YANG(spf_interval, spf_interval_cmd, + "spf-interval [level-1|level-2]$level (1-120)$val", + "Minimum interval between SPF calculations\n" + "Set interval for level 1 only\n" + "Set interval for level 2 only\n" + "Minimum interval between consecutive SPFs in seconds\n") +{ + if (!level || strmatch(level, "level-1")) + nb_cli_enqueue_change(vty, "./spf/minimum-interval/level-1", + NB_OP_MODIFY, val_str); + if (!level || strmatch(level, "level-2")) + nb_cli_enqueue_change(vty, "./spf/minimum-interval/level-2", + NB_OP_MODIFY, val_str); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG(no_spf_interval, no_spf_interval_cmd, + "no spf-interval [level-1|level-2]$level [(1-120)]", + NO_STR + "Minimum interval between SPF calculations\n" + "Set interval for level 1 only\n" + "Set interval for level 2 only\n" + "Minimum interval between consecutive SPFs in seconds\n") +{ + if (!level || strmatch(level, "level-1")) + nb_cli_enqueue_change(vty, "./spf/minimum-interval/level-1", + NB_OP_MODIFY, NULL); + if (!level || strmatch(level, "level-2")) + nb_cli_enqueue_change(vty, "./spf/minimum-interval/level-2", + NB_OP_MODIFY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_spf_min_interval(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + const char *l1 = yang_dnode_get_string(dnode, "./level-1"); + const char *l2 = yang_dnode_get_string(dnode, "./level-2"); + + if (strmatch(l1, l2)) + vty_out(vty, " spf-interval %s\n", l1); + else { + vty_out(vty, " spf-interval level-1 %s\n", l1); + vty_out(vty, " spf-interval level-2 %s\n", l2); + } +} + +/* + * XPath: /frr-isisd:isis/instance/spf/ietf-backoff-delay + */ +DEFPY_YANG(spf_delay_ietf, spf_delay_ietf_cmd, + "spf-delay-ietf init-delay (0-60000) short-delay (0-60000) long-delay (0-60000) holddown (0-60000) time-to-learn (0-60000)", + "IETF SPF delay algorithm\n" + "Delay used while in QUIET state\n" + "Delay used while in QUIET state in milliseconds\n" + "Delay used while in SHORT_WAIT state\n" + "Delay used while in SHORT_WAIT state in milliseconds\n" + "Delay used while in LONG_WAIT\n" + "Delay used while in LONG_WAIT state in milliseconds\n" + "Time with no received IGP events before considering IGP stable\n" + "Time with no received IGP events before considering IGP stable (in milliseconds)\n" + "Maximum duration needed to learn all the events related to a single failure\n" + "Maximum duration needed to learn all the events related to a single failure (in milliseconds)\n") +{ + nb_cli_enqueue_change(vty, "./spf/ietf-backoff-delay", NB_OP_CREATE, + NULL); + nb_cli_enqueue_change(vty, "./spf/ietf-backoff-delay/init-delay", + NB_OP_MODIFY, init_delay_str); + nb_cli_enqueue_change(vty, "./spf/ietf-backoff-delay/short-delay", + NB_OP_MODIFY, short_delay_str); + nb_cli_enqueue_change(vty, "./spf/ietf-backoff-delay/long-delay", + NB_OP_MODIFY, long_delay_str); + nb_cli_enqueue_change(vty, "./spf/ietf-backoff-delay/hold-down", + NB_OP_MODIFY, holddown_str); + nb_cli_enqueue_change(vty, "./spf/ietf-backoff-delay/time-to-learn", + NB_OP_MODIFY, time_to_learn_str); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG(no_spf_delay_ietf, no_spf_delay_ietf_cmd, + "no spf-delay-ietf [init-delay (0-60000) short-delay (0-60000) long-delay (0-60000) holddown (0-60000) time-to-learn (0-60000)]", + NO_STR + "IETF SPF delay algorithm\n" + "Delay used while in QUIET state\n" + "Delay used while in QUIET state in milliseconds\n" + "Delay used while in SHORT_WAIT state\n" + "Delay used while in SHORT_WAIT state in milliseconds\n" + "Delay used while in LONG_WAIT\n" + "Delay used while in LONG_WAIT state in milliseconds\n" + "Time with no received IGP events before considering IGP stable\n" + "Time with no received IGP events before considering IGP stable (in milliseconds)\n" + "Maximum duration needed to learn all the events related to a single failure\n" + "Maximum duration needed to learn all the events related to a single failure (in milliseconds)\n") +{ + nb_cli_enqueue_change(vty, "./spf/ietf-backoff-delay", NB_OP_DESTROY, + NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_spf_ietf_backoff(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, + " spf-delay-ietf init-delay %s short-delay %s long-delay %s holddown %s time-to-learn %s\n", + yang_dnode_get_string(dnode, "./init-delay"), + yang_dnode_get_string(dnode, "./short-delay"), + yang_dnode_get_string(dnode, "./long-delay"), + yang_dnode_get_string(dnode, "./hold-down"), + yang_dnode_get_string(dnode, "./time-to-learn")); +} + +/* + * XPath: /frr-isisd:isis/instance/spf/prefix-priorities/medium/access-list-name + */ +DEFPY_YANG(spf_prefix_priority, spf_prefix_priority_cmd, + "spf prefix-priority <critical|high|medium>$priority ACCESSLIST_NAME$acl_name", + "SPF configuration\n" + "Configure a prefix priority list\n" + "Specify critical priority prefixes\n" + "Specify high priority prefixes\n" + "Specify medium priority prefixes\n" + "Access-list name\n") +{ + char xpath[XPATH_MAXLEN]; + + snprintf(xpath, XPATH_MAXLEN, + "./spf/prefix-priorities/%s/access-list-name", priority); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, acl_name); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG(no_spf_prefix_priority, no_spf_prefix_priority_cmd, + "no spf prefix-priority <critical|high|medium>$priority [ACCESSLIST_NAME]", + NO_STR + "SPF configuration\n" + "Configure a prefix priority list\n" + "Specify critical priority prefixes\n" + "Specify high priority prefixes\n" + "Specify medium priority prefixes\n" + "Access-list name\n") +{ + char xpath[XPATH_MAXLEN]; + + snprintf(xpath, XPATH_MAXLEN, + "./spf/prefix-priorities/%s/access-list-name", priority); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_spf_prefix_priority(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " spf prefix-priority %s %s\n", + dnode->parent->schema->name, + yang_dnode_get_string(dnode, NULL)); +} + +/* + * XPath: /frr-isisd:isis/instance/purge-originator + */ +DEFPY_YANG(area_purge_originator, area_purge_originator_cmd, "[no] purge-originator", + NO_STR "Use the RFC 6232 purge-originator\n") +{ + nb_cli_enqueue_change(vty, "./purge-originator", NB_OP_MODIFY, + no ? "false" : "true"); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_purge_origin(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + vty_out(vty, " purge-originator\n"); +} + +/* + * XPath: /frr-isisd:isis/instance/mpls-te + */ +DEFPY_YANG(isis_mpls_te_on, isis_mpls_te_on_cmd, "mpls-te on", + MPLS_TE_STR "Enable the MPLS-TE functionality\n") +{ + nb_cli_enqueue_change(vty, "./mpls-te", NB_OP_CREATE, + NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG(no_isis_mpls_te_on, no_isis_mpls_te_on_cmd, "no mpls-te [on]", + NO_STR + "Disable the MPLS-TE functionality\n" + "Disable the MPLS-TE functionality\n") +{ + nb_cli_enqueue_change(vty, "./mpls-te", NB_OP_DESTROY, + NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_mpls_te(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " mpls-te on\n"); +} + +/* + * XPath: /frr-isisd:isis/instance/mpls-te/router-address + */ +DEFPY_YANG(isis_mpls_te_router_addr, isis_mpls_te_router_addr_cmd, + "mpls-te router-address A.B.C.D", + MPLS_TE_STR + "Stable IP address of the advertising router\n" + "MPLS-TE router address in IPv4 address format\n") +{ + nb_cli_enqueue_change(vty, "./mpls-te/router-address", + NB_OP_MODIFY, router_address_str); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG(no_isis_mpls_te_router_addr, no_isis_mpls_te_router_addr_cmd, + "no mpls-te router-address [A.B.C.D]", + NO_STR MPLS_TE_STR + "Delete IP address of the advertising router\n" + "MPLS-TE router address in IPv4 address format\n") +{ + nb_cli_enqueue_change(vty, "./mpls-te/router-address", + NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_mpls_te_router_addr(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " mpls-te router-address %s\n", + yang_dnode_get_string(dnode, NULL)); +} + +/* + * XPath: /frr-isisd:isis/instance/mpls-te/router-address-v6 + */ +DEFPY_YANG(isis_mpls_te_router_addr_v6, isis_mpls_te_router_addr_v6_cmd, + "mpls-te router-address ipv6 X:X::X:X", + MPLS_TE_STR + "Stable IP address of the advertising router\n" + "IPv6 address\n" + "MPLS-TE router address in IPv6 address format\n") +{ + nb_cli_enqueue_change(vty, "./mpls-te/router-address-v6", NB_OP_MODIFY, + ipv6_str); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG(no_isis_mpls_te_router_addr_v6, no_isis_mpls_te_router_addr_v6_cmd, + "no mpls-te router-address ipv6 [X:X::X:X]", + NO_STR MPLS_TE_STR + "Delete IP address of the advertising router\n" + "IPv6 address\n" + "MPLS-TE router address in IPv6 address format\n") +{ + nb_cli_enqueue_change(vty, "./mpls-te/router-address-v6", NB_OP_DESTROY, + NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_mpls_te_router_addr_ipv6(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " mpls-te router-address ipv6 %s\n", + yang_dnode_get_string(dnode, NULL)); +} + +DEFPY_YANG(isis_mpls_te_inter_as, isis_mpls_te_inter_as_cmd, + "[no] mpls-te inter-as [level-1|level-1-2|level-2-only]", + NO_STR MPLS_TE_STR + "Configure MPLS-TE Inter-AS support\n" + "AREA native mode self originate INTER-AS LSP with L1 only flooding scope\n" + "AREA native mode self originate INTER-AS LSP with L1 and L2 flooding scope\n" + "AS native mode self originate INTER-AS LSP with L2 only flooding scope\n") +{ + vty_out(vty, "MPLS-TE Inter-AS is not yet supported\n"); + return CMD_SUCCESS; +} + +/* + * XPath: /frr-isisd:isis/instance/mpls-te/export + */ +DEFPY_YANG(isis_mpls_te_export, isis_mpls_te_export_cmd, "mpls-te export", + MPLS_TE_STR "Enable export of MPLS-TE Link State information\n") +{ + nb_cli_enqueue_change(vty, "./mpls-te/export", NB_OP_MODIFY, "true"); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG(no_isis_mpls_te_export, no_isis_mpls_te_export_cmd, + "no mpls-te export", + NO_STR MPLS_TE_STR + "Disable export of MPLS-TE Link State information\n") +{ + nb_cli_enqueue_change(vty, "./mpls-te/export", NB_OP_MODIFY, "false"); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_mpls_te_export(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + + vty_out(vty, " mpls-te export\n"); +} + +/* + * XPath: /frr-isisd:isis/instance/default-information-originate + */ +DEFPY_YANG(isis_default_originate, isis_default_originate_cmd, + "[no] default-information originate <ipv4|ipv6>$ip <level-1|level-2>$level [always]$always [{metric (0-16777215)$metric|route-map RMAP_NAME$rmap}]", + NO_STR + "Control distribution of default information\n" + "Distribute a default route\n" + "Distribute default route for IPv4\n" + "Distribute default route for IPv6\n" + "Distribute default route into level-1\n" + "Distribute default route into level-2\n" + "Always advertise default route\n" + "Metric for default route\n" + "IS-IS default metric\n" + "Route map reference\n" + "Pointer to route-map entries\n") +{ + if (no) + nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL); + else { + nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./always", NB_OP_MODIFY, + always ? "true" : "false"); + nb_cli_enqueue_change(vty, "./route-map", + rmap ? NB_OP_MODIFY : NB_OP_DESTROY, + rmap ? rmap : NULL); + nb_cli_enqueue_change(vty, "./metric", NB_OP_MODIFY, + metric_str ? metric_str : NULL); + if (strmatch(ip, "ipv6") && !always) { + vty_out(vty, + "Zebra doesn't implement default-originate for IPv6 yet\n"); + vty_out(vty, + "so use with care or use default-originate always.\n"); + } + } + + return nb_cli_apply_changes( + vty, "./default-information-originate/%s[level='%s']", ip, + level); +} + +static void vty_print_def_origin(struct vty *vty, const struct lyd_node *dnode, + const char *family, const char *level, + bool show_defaults) +{ + vty_out(vty, " default-information originate %s %s", family, level); + if (yang_dnode_get_bool(dnode, "./always")) + vty_out(vty, " always"); + + if (yang_dnode_exists(dnode, "./route-map")) + vty_out(vty, " route-map %s", + yang_dnode_get_string(dnode, "./route-map")); + if (show_defaults || !yang_dnode_is_default(dnode, "./metric")) + vty_out(vty, " metric %s", + yang_dnode_get_string(dnode, "./metric")); + + vty_out(vty, "\n"); +} + +void cli_show_isis_def_origin_ipv4(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + const char *level = yang_dnode_get_string(dnode, "./level"); + + vty_print_def_origin(vty, dnode, "ipv4", level, show_defaults); +} + +void cli_show_isis_def_origin_ipv6(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + const char *level = yang_dnode_get_string(dnode, "./level"); + + vty_print_def_origin(vty, dnode, "ipv6", level, show_defaults); +} + +/* + * XPath: /frr-isisd:isis/instance/redistribute + */ +DEFPY_YANG(isis_redistribute, isis_redistribute_cmd, + "[no] redistribute <ipv4$ip " PROTO_IP_REDIST_STR "$proto|ipv6$ip " + PROTO_IP6_REDIST_STR "$proto> <level-1|level-2>$level" + "[{metric (0-16777215)|route-map RMAP_NAME$route_map}]", + NO_STR REDIST_STR + "Redistribute IPv4 routes\n" + PROTO_IP_REDIST_HELP + "Redistribute IPv6 routes\n" + PROTO_IP6_REDIST_HELP + "Redistribute into level-1\n" + "Redistribute into level-2\n" + "Metric for redistributed routes\n" + "IS-IS default metric\n" + "Route map reference\n" + "Pointer to route-map entries\n") +{ + if (no) + nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL); + else { + nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./route-map", + route_map ? NB_OP_MODIFY : NB_OP_DESTROY, + route_map ? route_map : NULL); + nb_cli_enqueue_change(vty, "./metric", NB_OP_MODIFY, + metric_str ? metric_str : NULL); + } + + return nb_cli_apply_changes( + vty, "./redistribute/%s[protocol='%s'][level='%s']", ip, proto, + level); +} + +static void vty_print_redistribute(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults, const char *family) +{ + const char *level = yang_dnode_get_string(dnode, "./level"); + const char *protocol = yang_dnode_get_string(dnode, "./protocol"); + + vty_out(vty, " redistribute %s %s %s", family, protocol, level); + if (show_defaults || !yang_dnode_is_default(dnode, "./metric")) + vty_out(vty, " metric %s", + yang_dnode_get_string(dnode, "./metric")); + if (yang_dnode_exists(dnode, "./route-map")) + vty_out(vty, " route-map %s", + yang_dnode_get_string(dnode, "./route-map")); + vty_out(vty, "\n"); +} + +void cli_show_isis_redistribute_ipv4(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_print_redistribute(vty, dnode, show_defaults, "ipv4"); +} +void cli_show_isis_redistribute_ipv6(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_print_redistribute(vty, dnode, show_defaults, "ipv6"); +} + +/* + * XPath: /frr-isisd:isis/instance/multi-topology + */ +DEFPY_YANG( + isis_topology, isis_topology_cmd, + "[no] topology <standard|ipv4-unicast|ipv4-mgmt|ipv6-unicast|ipv4-multicast|ipv6-multicast|ipv6-mgmt|ipv6-dstsrc>$topology [overload]$overload", + NO_STR + "Configure IS-IS topologies\n" + "standard topology\n" + "IPv4 unicast topology\n" + "IPv4 management topology\n" + "IPv6 unicast topology\n" + "IPv4 multicast topology\n" + "IPv6 multicast topology\n" + "IPv6 management topology\n" + "IPv6 dst-src topology\n" + "Set overload bit for topology\n") +{ + char base_xpath[XPATH_MAXLEN]; + + /* Since standard is not configurable it is not present in the + * YANG model, so we need to validate it here + */ + if (strmatch(topology, "standard") || + strmatch(topology, "ipv4-unicast")) { + vty_out(vty, + "Cannot configure IPv4 unicast (Standard) topology\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (strmatch(topology, "ipv4-mgmt")) + snprintf(base_xpath, XPATH_MAXLEN, + "./multi-topology/ipv4-management"); + else if (strmatch(topology, "ipv6-mgmt")) + snprintf(base_xpath, XPATH_MAXLEN, + "./multi-topology/ipv6-management"); + else + snprintf(base_xpath, XPATH_MAXLEN, "./multi-topology/%s", + topology); + + if (no) + nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL); + else { + nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./overload", NB_OP_MODIFY, + overload ? "true" : "false"); + } + + return nb_cli_apply_changes(vty, base_xpath); +} + +void cli_show_isis_mt_ipv4_multicast(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " topology ipv4-multicast"); + if (yang_dnode_get_bool(dnode, "./overload")) + vty_out(vty, " overload"); + vty_out(vty, "\n"); +} + +void cli_show_isis_mt_ipv4_mgmt(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " topology ipv4-mgmt"); + if (yang_dnode_get_bool(dnode, "./overload")) + vty_out(vty, " overload"); + vty_out(vty, "\n"); +} + +void cli_show_isis_mt_ipv6_unicast(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " topology ipv6-unicast"); + if (yang_dnode_get_bool(dnode, "./overload")) + vty_out(vty, " overload"); + vty_out(vty, "\n"); +} + +void cli_show_isis_mt_ipv6_multicast(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " topology ipv6-multicast"); + if (yang_dnode_get_bool(dnode, "./overload")) + vty_out(vty, " overload"); + vty_out(vty, "\n"); +} + +void cli_show_isis_mt_ipv6_mgmt(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " topology ipv6-mgmt"); + if (yang_dnode_get_bool(dnode, "./overload")) + vty_out(vty, " overload"); + vty_out(vty, "\n"); +} + +void cli_show_isis_mt_ipv6_dstsrc(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " topology ipv6-dstsrc"); + if (yang_dnode_get_bool(dnode, "./overload")) + vty_out(vty, " overload"); + vty_out(vty, "\n"); +} + +/* + * XPath: /frr-isisd:isis/instance/segment-routing/enabled + */ +DEFPY_YANG (isis_sr_enable, + isis_sr_enable_cmd, + "segment-routing on", + SR_STR + "Enable Segment Routing\n") +{ + nb_cli_enqueue_change(vty, "./segment-routing/enabled", NB_OP_MODIFY, + "true"); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG (no_isis_sr_enable, + no_isis_sr_enable_cmd, + "no segment-routing [on]", + NO_STR + SR_STR + "Disable Segment Routing\n") +{ + nb_cli_enqueue_change(vty, "./segment-routing/enabled", NB_OP_MODIFY, + "false"); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_sr_enabled(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + + vty_out(vty, " segment-routing on\n"); +} + +/* + * XPath: /frr-isisd:isis/instance/segment-routing/label-block + */ + +DEFPY_YANG( + isis_sr_global_block_label_range, isis_sr_global_block_label_range_cmd, + "segment-routing global-block (16-1048575)$gb_lower_bound (16-1048575)$gb_upper_bound [local-block (16-1048575)$lb_lower_bound (16-1048575)$lb_upper_bound]", + SR_STR + "Segment Routing Global Block label range\n" + "The lower bound of the global block\n" + "The upper bound of the global block (block size may not exceed 65535)\n" + "Segment Routing Local Block label range\n" + "The lower bound of the local block\n" + "The upper bound of the local block (block size may not exceed 65535)\n") +{ + nb_cli_enqueue_change(vty, + "./segment-routing/label-blocks/srgb/lower-bound", + NB_OP_MODIFY, gb_lower_bound_str); + nb_cli_enqueue_change(vty, + "./segment-routing/label-blocks/srgb/upper-bound", + NB_OP_MODIFY, gb_upper_bound_str); + + nb_cli_enqueue_change( + vty, "./segment-routing/label-blocks/srlb/lower-bound", + NB_OP_MODIFY, lb_lower_bound ? lb_lower_bound_str : NULL); + nb_cli_enqueue_change( + vty, "./segment-routing/label-blocks/srlb/upper-bound", + NB_OP_MODIFY, lb_upper_bound ? lb_upper_bound_str : NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG(no_isis_sr_global_block_label_range, + no_isis_sr_global_block_label_range_cmd, + "no segment-routing global-block [(16-1048575) (16-1048575) local-block (16-1048575) (16-1048575)]", + NO_STR SR_STR + "Segment Routing Global Block label range\n" + "The lower bound of the global block\n" + "The upper bound of the global block (block size may not exceed 65535)\n" + "Segment Routing Local Block label range\n" + "The lower bound of the local block\n" + "The upper bound of the local block (block size may not exceed 65535)\n") +{ + nb_cli_enqueue_change(vty, + "./segment-routing/label-blocks/srgb/lower-bound", + NB_OP_MODIFY, NULL); + nb_cli_enqueue_change(vty, + "./segment-routing/label-blocks/srgb/upper-bound", + NB_OP_MODIFY, NULL); + nb_cli_enqueue_change(vty, + "./segment-routing/label-blocks/srlb/lower-bound", + NB_OP_MODIFY, NULL); + nb_cli_enqueue_change(vty, + "./segment-routing/label-blocks/srlb/upper-bound", + NB_OP_MODIFY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_label_blocks(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " segment-routing global-block %s %s", + yang_dnode_get_string(dnode, "./srgb/lower-bound"), + yang_dnode_get_string(dnode, "./srgb/upper-bound")); + if (!yang_dnode_is_default(dnode, "./srlb/lower-bound") + || !yang_dnode_is_default(dnode, "./srlb/upper-bound")) + vty_out(vty, " local-block %s %s", + yang_dnode_get_string(dnode, "./srlb/lower-bound"), + yang_dnode_get_string(dnode, "./srlb/upper-bound")); + vty_out(vty, "\n"); +} + +/* + * XPath: /frr-isisd:isis/instance/segment-routing/msd/node-msd + */ +DEFPY_YANG (isis_sr_node_msd, + isis_sr_node_msd_cmd, + "segment-routing node-msd (1-16)$msd", + SR_STR + "Maximum Stack Depth for this router\n" + "Maximum number of label that can be stack (1-16)\n") +{ + nb_cli_enqueue_change(vty, "./segment-routing/msd/node-msd", + NB_OP_MODIFY, msd_str); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG (no_isis_sr_node_msd, + no_isis_sr_node_msd_cmd, + "no segment-routing node-msd [(1-16)]", + NO_STR + SR_STR + "Maximum Stack Depth for this router\n" + "Maximum number of label that can be stack (1-16)\n") +{ + nb_cli_enqueue_change(vty, "./segment-routing/msd/node-msd", + NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_node_msd(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " segment-routing node-msd %s\n", + yang_dnode_get_string(dnode, NULL)); +} + +/* + * XPath: /frr-isisd:isis/instance/segment-routing/prefix-sid-map/prefix-sid + */ +DEFPY_YANG (isis_sr_prefix_sid, + isis_sr_prefix_sid_cmd, + "segment-routing prefix\ + <A.B.C.D/M|X:X::X:X/M>$prefix\ + <absolute$sid_type (16-1048575)$sid_value|index$sid_type (0-65535)$sid_value>\ + [<no-php-flag|explicit-null>$lh_behavior] [n-flag-clear$n_flag_clear]", + SR_STR + "Prefix SID\n" + "IPv4 Prefix\n" + "IPv6 Prefix\n" + "Specify the absolute value of Prefix Segment ID\n" + "The Prefix Segment ID value\n" + "Specify the index of Prefix Segment ID\n" + "The Prefix Segment ID index\n" + "Don't request Penultimate Hop Popping (PHP)\n" + "Upstream neighbor must replace prefix-sid with explicit null label\n" + "Not a node SID\n") +{ + nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./sid-value-type", NB_OP_MODIFY, sid_type); + nb_cli_enqueue_change(vty, "./sid-value", NB_OP_MODIFY, sid_value_str); + if (lh_behavior) { + const char *value; + + if (strmatch(lh_behavior, "no-php-flag")) + value = "no-php"; + else if (strmatch(lh_behavior, "explicit-null")) + value = "explicit-null"; + else + value = "php"; + + nb_cli_enqueue_change(vty, "./last-hop-behavior", NB_OP_MODIFY, + value); + } else + nb_cli_enqueue_change(vty, "./last-hop-behavior", NB_OP_MODIFY, + NULL); + nb_cli_enqueue_change(vty, "./n-flag-clear", NB_OP_MODIFY, + n_flag_clear ? "true" : "false"); + + return nb_cli_apply_changes( + vty, "./segment-routing/prefix-sid-map/prefix-sid[prefix='%s']", + prefix_str); +} + +DEFPY_YANG (no_isis_sr_prefix_sid, + no_isis_sr_prefix_sid_cmd, + "no segment-routing prefix <A.B.C.D/M|X:X::X:X/M>$prefix\ + [<absolute$sid_type (16-1048575)|index (0-65535)> [<no-php-flag|explicit-null>]]\ + [n-flag-clear]", + NO_STR + SR_STR + "Prefix SID\n" + "IPv4 Prefix\n" + "IPv6 Prefix\n" + "Specify the absolute value of Prefix Segment ID\n" + "The Prefix Segment ID value\n" + "Specify the index of Prefix Segment ID\n" + "The Prefix Segment ID index\n" + "Don't request Penultimate Hop Popping (PHP)\n" + "Upstream neighbor must replace prefix-sid with explicit null label\n" + "Not a node SID\n") +{ + nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes( + vty, "./segment-routing/prefix-sid-map/prefix-sid[prefix='%s']", + prefix_str); +} + +void cli_show_isis_prefix_sid(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + const char *prefix; + const char *lh_behavior; + const char *sid_value_type; + const char *sid_value; + bool n_flag_clear; + + prefix = yang_dnode_get_string(dnode, "./prefix"); + lh_behavior = yang_dnode_get_string(dnode, "./last-hop-behavior"); + sid_value_type = yang_dnode_get_string(dnode, "./sid-value-type"); + sid_value = yang_dnode_get_string(dnode, "./sid-value"); + n_flag_clear = yang_dnode_get_bool(dnode, "./n-flag-clear"); + + vty_out(vty, " segment-routing prefix %s", prefix); + if (strmatch(sid_value_type, "absolute")) + vty_out(vty, " absolute"); + else + vty_out(vty, " index"); + vty_out(vty, " %s", sid_value); + if (strmatch(lh_behavior, "no-php")) + vty_out(vty, " no-php-flag"); + else if (strmatch(lh_behavior, "explicit-null")) + vty_out(vty, " explicit-null"); + if (n_flag_clear) + vty_out(vty, " n-flag-clear"); + vty_out(vty, "\n"); +} + + +/* + * XPath: /frr-isisd:isis/instance/fast-reroute/level-{1,2}/lfa/priority-limit + */ +DEFPY_YANG (isis_frr_lfa_priority_limit, + isis_frr_lfa_priority_limit_cmd, + "[no] fast-reroute priority-limit <critical|high|medium>$priority [<level-1|level-2>$level]", + NO_STR + "Configure Fast ReRoute\n" + "Limit backup computation up to the prefix priority\n" + "Compute for critical priority prefixes only\n" + "Compute for critical & high priority prefixes\n" + "Compute for critical, high & medium priority prefixes\n" + "Set priority-limit for level-1 only\n" + "Set priority-limit for level-2 only\n") +{ + if (!level || strmatch(level, "level-1")) { + if (no) { + nb_cli_enqueue_change( + vty, + "./fast-reroute/level-1/lfa/priority-limit", + NB_OP_DESTROY, NULL); + } else { + nb_cli_enqueue_change( + vty, + "./fast-reroute/level-1/lfa/priority-limit", + NB_OP_CREATE, priority); + } + } + if (!level || strmatch(level, "level-2")) { + if (no) { + nb_cli_enqueue_change( + vty, + "./fast-reroute/level-2/lfa/priority-limit", + NB_OP_DESTROY, NULL); + } else { + nb_cli_enqueue_change( + vty, + "./fast-reroute/level-2/lfa/priority-limit", + NB_OP_CREATE, priority); + } + } + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_frr_lfa_priority_limit(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " fast-reroute priority-limit %s %s\n", + yang_dnode_get_string(dnode, NULL), + dnode->parent->parent->schema->name); +} + +/* + * XPath: /frr-isisd:isis/instance/fast-reroute/level-{1,2}/lfa/tiebreaker + */ +DEFPY_YANG (isis_frr_lfa_tiebreaker, + isis_frr_lfa_tiebreaker_cmd, + "[no] fast-reroute lfa\ + tiebreaker <downstream|lowest-backup-metric|node-protecting>$type\ + index (1-255)$index\ + [<level-1|level-2>$level]", + NO_STR + "Configure Fast ReRoute\n" + "LFA configuration\n" + "Configure tiebreaker for multiple backups\n" + "Prefer backup path via downstream node\n" + "Prefer backup path with lowest total metric\n" + "Prefer node protecting backup path\n" + "Set preference order among tiebreakers\n" + "Index\n" + "Configure tiebreaker for level-1 only\n" + "Configure tiebreaker for level-2 only\n") +{ + char xpath[XPATH_MAXLEN]; + + if (!level || strmatch(level, "level-1")) { + if (no) { + snprintf( + xpath, XPATH_MAXLEN, + "./fast-reroute/level-1/lfa/tiebreaker[index='%s']", + index_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + } else { + snprintf( + xpath, XPATH_MAXLEN, + "./fast-reroute/level-1/lfa/tiebreaker[index='%s']/type", + index_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, type); + } + } + if (!level || strmatch(level, "level-2")) { + if (no) { + snprintf( + xpath, XPATH_MAXLEN, + "./fast-reroute/level-2/lfa/tiebreaker[index='%s']", + index_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + } else { + snprintf( + xpath, XPATH_MAXLEN, + "./fast-reroute/level-2/lfa/tiebreaker[index='%s']/type", + index_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, type); + } + } + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_frr_lfa_tiebreaker(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " fast-reroute lfa tiebreaker %s index %s %s\n", + yang_dnode_get_string(dnode, "./type"), + yang_dnode_get_string(dnode, "./index"), + dnode->parent->parent->schema->name); +} + +/* + * XPath: /frr-isisd:isis/instance/fast-reroute/level-{1,2}/lfa/load-sharing + */ +DEFPY_YANG (isis_frr_lfa_load_sharing, + isis_frr_lfa_load_sharing_cmd, + "[no] fast-reroute load-sharing disable [<level-1|level-2>$level]", + NO_STR + "Configure Fast ReRoute\n" + "Load share prefixes across multiple backups\n" + "Disable load sharing\n" + "Disable load sharing for level-1 only\n" + "Disable load sharing for level-2 only\n") +{ + if (!level || strmatch(level, "level-1")) { + if (no) { + nb_cli_enqueue_change( + vty, "./fast-reroute/level-1/lfa/load-sharing", + NB_OP_MODIFY, "true"); + } else { + nb_cli_enqueue_change( + vty, "./fast-reroute/level-1/lfa/load-sharing", + NB_OP_MODIFY, "false"); + } + } + if (!level || strmatch(level, "level-2")) { + if (no) { + nb_cli_enqueue_change( + vty, "./fast-reroute/level-2/lfa/load-sharing", + NB_OP_MODIFY, "true"); + } else { + nb_cli_enqueue_change( + vty, "./fast-reroute/level-2/lfa/load-sharing", + NB_OP_MODIFY, "false"); + } + } + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_frr_lfa_load_sharing(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + if (yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + + vty_out(vty, " fast-reroute load-sharing disable %s\n", + dnode->parent->parent->schema->name); +} + +/* + * XPath: /frr-isisd:isis/instance/fast-reroute/level-{1,2}/remote-lfa/prefix-list + */ +DEFPY_YANG (isis_frr_remote_lfa_plist, + isis_frr_remote_lfa_plist_cmd, + "fast-reroute remote-lfa prefix-list WORD$plist [<level-1|level-2>$level]", + "Configure Fast ReRoute\n" + "Enable remote LFA related configuration\n" + "Filter PQ node router ID based on prefix list\n" + "Prefix-list name\n" + "Enable router ID filtering for level-1 only\n" + "Enable router ID filtering for level-2 only\n") +{ + if (!level || strmatch(level, "level-1")) + nb_cli_enqueue_change( + vty, "./fast-reroute/level-1/remote-lfa/prefix-list", + NB_OP_MODIFY, plist); + if (!level || strmatch(level, "level-2")) + nb_cli_enqueue_change( + vty, "./fast-reroute/level-2/remote-lfa/prefix-list", + NB_OP_MODIFY, plist); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG (no_isis_frr_remote_lfa_plist, + no_isis_frr_remote_lfa_plist_cmd, + "no fast-reroute remote-lfa prefix-list [WORD] [<level-1|level-2>$level]", + NO_STR + "Configure Fast ReRoute\n" + "Enable remote LFA related configuration\n" + "Filter PQ node router ID based on prefix list\n" + "Prefix-list name\n" + "Enable router ID filtering for level-1 only\n" + "Enable router ID filtering for level-2 only\n") +{ + if (!level || strmatch(level, "level-1")) + nb_cli_enqueue_change( + vty, "./fast-reroute/level-1/remote-lfa/prefix-list", + NB_OP_DESTROY, NULL); + if (!level || strmatch(level, "level-2")) + nb_cli_enqueue_change( + vty, "./fast-reroute/level-2/remote-lfa/prefix-list", + NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_frr_remote_lfa_plist(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " fast-reroute remote-lfa prefix-list %s %s\n", + yang_dnode_get_string(dnode, NULL), + dnode->parent->parent->schema->name); +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/passive + */ +DEFPY_YANG(isis_passive, isis_passive_cmd, "[no] isis passive", + NO_STR + "IS-IS routing protocol\n" + "Configure the passive mode for interface\n") +{ + nb_cli_enqueue_change(vty, "./frr-isisd:isis/passive", NB_OP_MODIFY, + no ? "false" : "true"); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_ip_isis_passive(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + vty_out(vty, " isis passive\n"); +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/password + */ + +DEFPY_YANG(isis_passwd, isis_passwd_cmd, "isis password <md5|clear>$type WORD$pwd", + "IS-IS routing protocol\n" + "Configure the authentication password for a circuit\n" + "HMAC-MD5 authentication\n" + "Cleartext password\n" + "Circuit password\n") +{ + nb_cli_enqueue_change(vty, "./frr-isisd:isis/password", NB_OP_CREATE, + NULL); + nb_cli_enqueue_change(vty, "./frr-isisd:isis/password/password", + NB_OP_MODIFY, pwd); + nb_cli_enqueue_change(vty, "./frr-isisd:isis/password/password-type", + NB_OP_MODIFY, type); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG(no_isis_passwd, no_isis_passwd_cmd, "no isis password [<md5|clear> WORD]", + NO_STR + "IS-IS routing protocol\n" + "Configure the authentication password for a circuit\n" + "HMAC-MD5 authentication\n" + "Cleartext password\n" + "Circuit password\n") +{ + nb_cli_enqueue_change(vty, "./frr-isisd:isis/password", NB_OP_DESTROY, + NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_ip_isis_password(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " isis password %s %s\n", + yang_dnode_get_string(dnode, "./password-type"), + yang_dnode_get_string(dnode, "./password")); +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/metric + */ +DEFPY_YANG(isis_metric, isis_metric_cmd, + "isis metric [level-1|level-2]$level (0-16777215)$met", + "IS-IS routing protocol\n" + "Set default metric for circuit\n" + "Specify metric for level-1 routing\n" + "Specify metric for level-2 routing\n" + "Default metric value\n") +{ + if (!level || strmatch(level, "level-1")) + nb_cli_enqueue_change(vty, "./frr-isisd:isis/metric/level-1", + NB_OP_MODIFY, met_str); + if (!level || strmatch(level, "level-2")) + nb_cli_enqueue_change(vty, "./frr-isisd:isis/metric/level-2", + NB_OP_MODIFY, met_str); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG(no_isis_metric, no_isis_metric_cmd, + "no isis metric [level-1|level-2]$level [(0-16777215)]", + NO_STR + "IS-IS routing protocol\n" + "Set default metric for circuit\n" + "Specify metric for level-1 routing\n" + "Specify metric for level-2 routing\n" + "Default metric value\n") +{ + if (!level || strmatch(level, "level-1")) + nb_cli_enqueue_change(vty, "./frr-isisd:isis/metric/level-1", + NB_OP_MODIFY, NULL); + if (!level || strmatch(level, "level-2")) + nb_cli_enqueue_change(vty, "./frr-isisd:isis/metric/level-2", + NB_OP_MODIFY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_ip_isis_metric(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + const char *l1 = yang_dnode_get_string(dnode, "./level-1"); + const char *l2 = yang_dnode_get_string(dnode, "./level-2"); + + if (strmatch(l1, l2)) + vty_out(vty, " isis metric %s\n", l1); + else { + vty_out(vty, " isis metric level-1 %s\n", l1); + vty_out(vty, " isis metric level-2 %s\n", l2); + } +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/interval + */ +DEFPY_YANG(isis_hello_interval, isis_hello_interval_cmd, + "isis hello-interval [level-1|level-2]$level (1-600)$intv", + "IS-IS routing protocol\n" + "Set Hello interval\n" + "Specify hello-interval for level-1 IIHs\n" + "Specify hello-interval for level-2 IIHs\n" + "Holdtime 1 seconds, interval depends on multiplier\n") +{ + if (!level || strmatch(level, "level-1")) + nb_cli_enqueue_change(vty, + "./frr-isisd:isis/hello/interval/level-1", + NB_OP_MODIFY, intv_str); + if (!level || strmatch(level, "level-2")) + nb_cli_enqueue_change(vty, + "./frr-isisd:isis/hello/interval/level-2", + NB_OP_MODIFY, intv_str); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG(no_isis_hello_interval, no_isis_hello_interval_cmd, + "no isis hello-interval [level-1|level-2]$level [(1-600)]", + NO_STR + "IS-IS routing protocol\n" + "Set Hello interval\n" + "Specify hello-interval for level-1 IIHs\n" + "Specify hello-interval for level-2 IIHs\n" + "Holdtime 1 second, interval depends on multiplier\n") +{ + if (!level || strmatch(level, "level-1")) + nb_cli_enqueue_change(vty, + "./frr-isisd:isis/hello/interval/level-1", + NB_OP_MODIFY, NULL); + if (!level || strmatch(level, "level-2")) + nb_cli_enqueue_change(vty, + "./frr-isisd:isis/hello/interval/level-2", + NB_OP_MODIFY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_ip_isis_hello_interval(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + const char *l1 = yang_dnode_get_string(dnode, "./level-1"); + const char *l2 = yang_dnode_get_string(dnode, "./level-2"); + + if (strmatch(l1, l2)) + vty_out(vty, " isis hello-interval %s\n", l1); + else { + vty_out(vty, " isis hello-interval level-1 %s\n", l1); + vty_out(vty, " isis hello-interval level-2 %s\n", l2); + } +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/multiplier + */ +DEFPY_YANG(isis_hello_multiplier, isis_hello_multiplier_cmd, + "isis hello-multiplier [level-1|level-2]$level (2-100)$mult", + "IS-IS routing protocol\n" + "Set multiplier for Hello holding time\n" + "Specify hello multiplier for level-1 IIHs\n" + "Specify hello multiplier for level-2 IIHs\n" + "Hello multiplier value\n") +{ + if (!level || strmatch(level, "level-1")) + nb_cli_enqueue_change( + vty, "./frr-isisd:isis/hello/multiplier/level-1", + NB_OP_MODIFY, mult_str); + if (!level || strmatch(level, "level-2")) + nb_cli_enqueue_change( + vty, "./frr-isisd:isis/hello/multiplier/level-2", + NB_OP_MODIFY, mult_str); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG(no_isis_hello_multiplier, no_isis_hello_multiplier_cmd, + "no isis hello-multiplier [level-1|level-2]$level [(2-100)]", + NO_STR + "IS-IS routing protocol\n" + "Set multiplier for Hello holding time\n" + "Specify hello multiplier for level-1 IIHs\n" + "Specify hello multiplier for level-2 IIHs\n" + "Hello multiplier value\n") +{ + if (!level || strmatch(level, "level-1")) + nb_cli_enqueue_change( + vty, "./frr-isisd:isis/hello/multiplier/level-1", + NB_OP_MODIFY, NULL); + if (!level || strmatch(level, "level-2")) + nb_cli_enqueue_change( + vty, "./frr-isisd:isis/hello/multiplier/level-2", + NB_OP_MODIFY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_ip_isis_hello_multi(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + const char *l1 = yang_dnode_get_string(dnode, "./level-1"); + const char *l2 = yang_dnode_get_string(dnode, "./level-2"); + + if (strmatch(l1, l2)) + vty_out(vty, " isis hello-multiplier %s\n", l1); + else { + vty_out(vty, " isis hello-multiplier level-1 %s\n", l1); + vty_out(vty, " isis hello-multiplier level-2 %s\n", l2); + } +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/disable-three-way-handshake + */ +DEFPY_YANG(isis_threeway_adj, isis_threeway_adj_cmd, "[no] isis three-way-handshake", + NO_STR + "IS-IS commands\n" + "Enable/Disable three-way handshake\n") +{ + nb_cli_enqueue_change(vty, + "./frr-isisd:isis/disable-three-way-handshake", + NB_OP_MODIFY, no ? "true" : "false"); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_ip_isis_threeway_shake(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + if (yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + vty_out(vty, " isis three-way-handshake\n"); +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/hello/padding + */ +DEFPY_YANG(isis_hello_padding, isis_hello_padding_cmd, "[no] isis hello padding", + NO_STR + "IS-IS routing protocol\n" + "Add padding to IS-IS hello packets\n" + "Pad hello packets\n") +{ + nb_cli_enqueue_change(vty, "./frr-isisd:isis/hello/padding", + NB_OP_MODIFY, no ? "false" : "true"); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_ip_isis_hello_padding(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + + vty_out(vty, " isis hello padding\n"); +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/csnp-interval + */ +DEFPY_YANG(csnp_interval, csnp_interval_cmd, + "isis csnp-interval (1-600)$intv [level-1|level-2]$level", + "IS-IS routing protocol\n" + "Set CSNP interval in seconds\n" + "CSNP interval value\n" + "Specify interval for level-1 CSNPs\n" + "Specify interval for level-2 CSNPs\n") +{ + if (!level || strmatch(level, "level-1")) + nb_cli_enqueue_change(vty, + "./frr-isisd:isis/csnp-interval/level-1", + NB_OP_MODIFY, intv_str); + if (!level || strmatch(level, "level-2")) + nb_cli_enqueue_change(vty, + "./frr-isisd:isis/csnp-interval/level-2", + NB_OP_MODIFY, intv_str); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG(no_csnp_interval, no_csnp_interval_cmd, + "no isis csnp-interval [(1-600)] [level-1|level-2]$level", + NO_STR + "IS-IS routing protocol\n" + "Set CSNP interval in seconds\n" + "CSNP interval value\n" + "Specify interval for level-1 CSNPs\n" + "Specify interval for level-2 CSNPs\n") +{ + if (!level || strmatch(level, "level-1")) + nb_cli_enqueue_change(vty, + "./frr-isisd:isis/csnp-interval/level-1", + NB_OP_MODIFY, NULL); + if (!level || strmatch(level, "level-2")) + nb_cli_enqueue_change(vty, + "./frr-isisd:isis/csnp-interval/level-2", + NB_OP_MODIFY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_ip_isis_csnp_interval(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + const char *l1 = yang_dnode_get_string(dnode, "./level-1"); + const char *l2 = yang_dnode_get_string(dnode, "./level-2"); + + if (strmatch(l1, l2)) + vty_out(vty, " isis csnp-interval %s\n", l1); + else { + vty_out(vty, " isis csnp-interval %s level-1\n", l1); + vty_out(vty, " isis csnp-interval %s level-2\n", l2); + } +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/psnp-interval + */ +DEFPY_YANG(psnp_interval, psnp_interval_cmd, + "isis psnp-interval (1-120)$intv [level-1|level-2]$level", + "IS-IS routing protocol\n" + "Set PSNP interval in seconds\n" + "PSNP interval value\n" + "Specify interval for level-1 PSNPs\n" + "Specify interval for level-2 PSNPs\n") +{ + if (!level || strmatch(level, "level-1")) + nb_cli_enqueue_change(vty, + "./frr-isisd:isis/psnp-interval/level-1", + NB_OP_MODIFY, intv_str); + if (!level || strmatch(level, "level-2")) + nb_cli_enqueue_change(vty, + "./frr-isisd:isis/psnp-interval/level-2", + NB_OP_MODIFY, intv_str); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG(no_psnp_interval, no_psnp_interval_cmd, + "no isis psnp-interval [(1-120)] [level-1|level-2]$level", + NO_STR + "IS-IS routing protocol\n" + "Set PSNP interval in seconds\n" + "PSNP interval value\n" + "Specify interval for level-1 PSNPs\n" + "Specify interval for level-2 PSNPs\n") +{ + if (!level || strmatch(level, "level-1")) + nb_cli_enqueue_change(vty, + "./frr-isisd:isis/psnp-interval/level-1", + NB_OP_MODIFY, NULL); + if (!level || strmatch(level, "level-2")) + nb_cli_enqueue_change(vty, + "./frr-isisd:isis/psnp-interval/level-2", + NB_OP_MODIFY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_ip_isis_psnp_interval(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + const char *l1 = yang_dnode_get_string(dnode, "./level-1"); + const char *l2 = yang_dnode_get_string(dnode, "./level-2"); + + if (strmatch(l1, l2)) + vty_out(vty, " isis psnp-interval %s\n", l1); + else { + vty_out(vty, " isis psnp-interval %s level-1\n", l1); + vty_out(vty, " isis psnp-interval %s level-2\n", l2); + } +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/multi-topology + */ +DEFPY_YANG(circuit_topology, circuit_topology_cmd, + "[no] isis topology<standard|ipv4-unicast|ipv4-mgmt|ipv6-unicast|ipv4-multicast|ipv6-multicast|ipv6-mgmt|ipv6-dstsrc>$topology", + NO_STR + "IS-IS routing protocol\n" + "Configure interface IS-IS topologies\n" + "Standard topology\n" + "IPv4 unicast topology\n" + "IPv4 management topology\n" + "IPv6 unicast topology\n" + "IPv4 multicast topology\n" + "IPv6 multicast topology\n" + "IPv6 management topology\n" + "IPv6 dst-src topology\n") +{ + nb_cli_enqueue_change(vty, ".", NB_OP_MODIFY, no ? "false" : "true"); + + if (strmatch(topology, "ipv4-mgmt")) + return nb_cli_apply_changes( + vty, "./frr-isisd:isis/multi-topology/ipv4-management"); + else if (strmatch(topology, "ipv6-mgmt")) + return nb_cli_apply_changes( + vty, "./frr-isisd:isis/multi-topology/ipv6-management"); + if (strmatch(topology, "ipv4-unicast")) + return nb_cli_apply_changes( + vty, "./frr-isisd:isis/multi-topology/standard"); + else + return nb_cli_apply_changes( + vty, "./frr-isisd:isis/multi-topology/%s", topology); +} + +void cli_show_ip_isis_mt_standard(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + vty_out(vty, " isis topology standard\n"); +} + +void cli_show_ip_isis_mt_ipv4_multicast(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + vty_out(vty, " isis topology ipv4-multicast\n"); +} + +void cli_show_ip_isis_mt_ipv4_mgmt(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + vty_out(vty, " isis topology ipv4-mgmt\n"); +} + +void cli_show_ip_isis_mt_ipv6_unicast(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + vty_out(vty, " isis topology ipv6-unicast\n"); +} + +void cli_show_ip_isis_mt_ipv6_multicast(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + vty_out(vty, " isis topology ipv6-multicast\n"); +} + +void cli_show_ip_isis_mt_ipv6_mgmt(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + vty_out(vty, " isis topology ipv6-mgmt\n"); +} + +void cli_show_ip_isis_mt_ipv6_dstsrc(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + vty_out(vty, " isis topology ipv6-dstsrc\n"); +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/circuit-type + */ +DEFPY_YANG(isis_circuit_type, isis_circuit_type_cmd, + "isis circuit-type <level-1|level-1-2|level-2-only>$type", + "IS-IS routing protocol\n" + "Configure circuit type for interface\n" + "Level-1 only adjacencies are formed\n" + "Level-1-2 adjacencies are formed\n" + "Level-2 only adjacencies are formed\n") +{ + nb_cli_enqueue_change( + vty, "./frr-isisd:isis/circuit-type", NB_OP_MODIFY, + strmatch(type, "level-2-only") ? "level-2" : type); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG(no_isis_circuit_type, no_isis_circuit_type_cmd, + "no isis circuit-type [level-1|level-1-2|level-2-only]", + NO_STR + "IS-IS routing protocol\n" + "Configure circuit type for interface\n" + "Level-1 only adjacencies are formed\n" + "Level-1-2 adjacencies are formed\n" + "Level-2 only adjacencies are formed\n") +{ + nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type", + NB_OP_MODIFY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_ip_isis_circ_type(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + int level = yang_dnode_get_enum(dnode, NULL); + + switch (level) { + case IS_LEVEL_1: + vty_out(vty, " isis circuit-type level-1\n"); + break; + case IS_LEVEL_2: + vty_out(vty, " isis circuit-type level-2-only\n"); + break; + case IS_LEVEL_1_AND_2: + vty_out(vty, " isis circuit-type level-1-2\n"); + break; + } +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/network-type + */ +DEFPY_YANG(isis_network, isis_network_cmd, "[no] isis network point-to-point", + NO_STR + "IS-IS routing protocol\n" + "Set network type\n" + "point-to-point network type\n") +{ + nb_cli_enqueue_change(vty, "./frr-isisd:isis/network-type", + NB_OP_MODIFY, + no ? "broadcast" : "point-to-point"); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_ip_isis_network_type(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + if (yang_dnode_get_enum(dnode, NULL) != CIRCUIT_T_P2P) + vty_out(vty, " no"); + + vty_out(vty, " isis network point-to-point\n"); +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/priority + */ +DEFPY_YANG(isis_priority, isis_priority_cmd, + "isis priority (0-127)$prio [level-1|level-2]$level", + "IS-IS routing protocol\n" + "Set priority for Designated Router election\n" + "Priority value\n" + "Specify priority for level-1 routing\n" + "Specify priority for level-2 routing\n") +{ + if (!level || strmatch(level, "level-1")) + nb_cli_enqueue_change(vty, "./frr-isisd:isis/priority/level-1", + NB_OP_MODIFY, prio_str); + if (!level || strmatch(level, "level-2")) + nb_cli_enqueue_change(vty, "./frr-isisd:isis/priority/level-2", + NB_OP_MODIFY, prio_str); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG(no_isis_priority, no_isis_priority_cmd, + "no isis priority [(0-127)] [level-1|level-2]$level", + NO_STR + "IS-IS routing protocol\n" + "Set priority for Designated Router election\n" + "Priority value\n" + "Specify priority for level-1 routing\n" + "Specify priority for level-2 routing\n") +{ + if (!level || strmatch(level, "level-1")) + nb_cli_enqueue_change(vty, "./frr-isisd:isis/priority/level-1", + NB_OP_MODIFY, NULL); + if (!level || strmatch(level, "level-2")) + nb_cli_enqueue_change(vty, "./frr-isisd:isis/priority/level-2", + NB_OP_MODIFY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_ip_isis_priority(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + const char *l1 = yang_dnode_get_string(dnode, "./level-1"); + const char *l2 = yang_dnode_get_string(dnode, "./level-2"); + + if (strmatch(l1, l2)) + vty_out(vty, " isis priority %s\n", l1); + else { + vty_out(vty, " isis priority %s level-1\n", l1); + vty_out(vty, " isis priority %s level-2\n", l2); + } +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/fast-reroute + */ +void cli_show_ip_isis_frr(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + bool l1_enabled, l2_enabled; + bool l1_node_protection, l2_node_protection; + bool l1_link_fallback, l2_link_fallback; + + /* Classic LFA */ + l1_enabled = yang_dnode_get_bool(dnode, "./level-1/lfa/enable"); + l2_enabled = yang_dnode_get_bool(dnode, "./level-2/lfa/enable"); + + if (l1_enabled || l2_enabled) { + if (l1_enabled == l2_enabled) { + vty_out(vty, " isis fast-reroute lfa\n"); + vty_out(vty, "\n"); + } else { + if (l1_enabled) + vty_out(vty, + " isis fast-reroute lfa level-1\n"); + if (l2_enabled) + vty_out(vty, + " isis fast-reroute lfa level-2\n"); + } + } + + /* Remote LFA */ + l1_enabled = yang_dnode_get_bool(dnode, "./level-1/remote-lfa/enable"); + l2_enabled = yang_dnode_get_bool(dnode, "./level-2/remote-lfa/enable"); + + if (l1_enabled || l2_enabled) { + if (l1_enabled == l2_enabled) { + vty_out(vty, + " isis fast-reroute remote-lfa tunnel mpls-ldp\n"); + vty_out(vty, "\n"); + } else { + if (l1_enabled) + vty_out(vty, + " isis fast-reroute remote-lfa tunnel mpls-ldp level-1\n"); + if (l2_enabled) + vty_out(vty, + " isis fast-reroute remote-lfa tunnel mpls-ldp level-2\n"); + } + } + + /* TI-LFA */ + l1_enabled = yang_dnode_get_bool(dnode, "./level-1/ti-lfa/enable"); + l2_enabled = yang_dnode_get_bool(dnode, "./level-2/ti-lfa/enable"); + l1_node_protection = + yang_dnode_get_bool(dnode, "./level-1/ti-lfa/node-protection"); + l2_node_protection = + yang_dnode_get_bool(dnode, "./level-2/ti-lfa/node-protection"); + l1_link_fallback = + yang_dnode_get_bool(dnode, "./level-1/ti-lfa/link-fallback"); + l2_link_fallback = + yang_dnode_get_bool(dnode, "./level-2/ti-lfa/link-fallback"); + + + if (l1_enabled || l2_enabled) { + if (l1_enabled == l2_enabled + && l1_node_protection == l2_node_protection + && l1_link_fallback == l2_link_fallback) { + vty_out(vty, " isis fast-reroute ti-lfa"); + if (l1_node_protection) + vty_out(vty, " node-protection"); + if (l1_link_fallback) + vty_out(vty, " link-fallback"); + vty_out(vty, "\n"); + } else { + if (l1_enabled) { + vty_out(vty, + " isis fast-reroute ti-lfa level-1"); + if (l1_node_protection) + vty_out(vty, " node-protection"); + if (l1_link_fallback) + vty_out(vty, " link-fallback"); + vty_out(vty, "\n"); + } + if (l2_enabled) { + vty_out(vty, + " isis fast-reroute ti-lfa level-2"); + if (l2_node_protection) + vty_out(vty, " node-protection"); + if (l2_link_fallback) + vty_out(vty, " link-fallback"); + vty_out(vty, "\n"); + } + } + } +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-{1,2}/lfa/enable + */ +DEFPY(isis_lfa, isis_lfa_cmd, + "[no] isis fast-reroute lfa [level-1|level-2]$level", + NO_STR + "IS-IS routing protocol\n" + "Interface IP Fast-reroute configuration\n" + "Enable LFA computation\n" + "Enable LFA computation for Level 1 only\n" + "Enable LFA computation for Level 2 only\n") +{ + if (!level || strmatch(level, "level-1")) { + if (no) { + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-1/lfa/enable", + NB_OP_MODIFY, "false"); + } else { + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-1/lfa/enable", + NB_OP_MODIFY, "true"); + } + } + if (!level || strmatch(level, "level-2")) { + if (no) { + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-2/lfa/enable", + NB_OP_MODIFY, "false"); + } else { + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-2/lfa/enable", + NB_OP_MODIFY, "true"); + } + } + + return nb_cli_apply_changes(vty, NULL); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-{1,2}/lfa/exclude-interface + */ +DEFPY(isis_lfa_exclude_interface, isis_lfa_exclude_interface_cmd, + "[no] isis fast-reroute lfa [level-1|level-2]$level exclude interface IFNAME$ifname", + NO_STR + "IS-IS routing protocol\n" + "Interface IP Fast-reroute configuration\n" + "Enable LFA computation\n" + "Enable LFA computation for Level 1 only\n" + "Enable LFA computation for Level 2 only\n" + "FRR exclusion information\n" + "Exclude an interface from computation\n" + "Interface name\n") +{ + if (!level || strmatch(level, "level-1")) { + if (no) { + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-1/lfa/exclude-interface", + NB_OP_DESTROY, ifname); + } else { + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-1/lfa/exclude-interface", + NB_OP_CREATE, ifname); + } + } + if (!level || strmatch(level, "level-2")) { + if (no) { + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-2/lfa/exclude-interface", + NB_OP_DESTROY, ifname); + } else { + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-2/lfa/exclude-interface", + NB_OP_CREATE, ifname); + } + } + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_frr_lfa_exclude_interface(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " isis fast-reroute lfa %s exclude interface %s\n", + dnode->parent->parent->schema->name, + yang_dnode_get_string(dnode, NULL)); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-{1,2}/remote-lfa/enable + */ +DEFPY(isis_remote_lfa, isis_remote_lfa_cmd, + "[no] isis fast-reroute remote-lfa tunnel mpls-ldp [level-1|level-2]$level", + NO_STR + "IS-IS routing protocol\n" + "Interface IP Fast-reroute configuration\n" + "Enable remote LFA computation\n" + "Enable remote LFA computation using tunnels\n" + "Use MPLS LDP tunnel to reach the remote LFA node\n" + "Enable LFA computation for Level 1 only\n" + "Enable LFA computation for Level 2 only\n") +{ + if (!level || strmatch(level, "level-1")) { + if (no) { + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-1/remote-lfa/enable", + NB_OP_MODIFY, "false"); + } else { + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-1/remote-lfa/enable", + NB_OP_MODIFY, "true"); + } + } + if (!level || strmatch(level, "level-2")) { + if (no) { + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-2/remote-lfa/enable", + NB_OP_MODIFY, "false"); + } else { + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-2/remote-lfa/enable", + NB_OP_MODIFY, "true"); + } + } + + return nb_cli_apply_changes(vty, NULL); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-{1,2}/remote-lfa/maximum-metric + */ +DEFPY(isis_remote_lfa_max_metric, isis_remote_lfa_max_metric_cmd, + "[no] isis fast-reroute remote-lfa maximum-metric (1-16777215)$metric [level-1|level-2]$level", + NO_STR + "IS-IS routing protocol\n" + "Interface IP Fast-reroute configuration\n" + "Enable remote LFA computation\n" + "Limit remote LFA node selection within the metric\n" + "Value of the metric\n" + "Enable LFA computation for Level 1 only\n" + "Enable LFA computation for Level 2 only\n") +{ + if (!level || strmatch(level, "level-1")) { + if (no) { + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-1/remote-lfa/maximum-metric", + NB_OP_DESTROY, NULL); + } else { + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-1/remote-lfa/maximum-metric", + NB_OP_MODIFY, metric_str); + } + } + if (!level || strmatch(level, "level-2")) { + if (no) { + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-2/remote-lfa/maximum-metric", + NB_OP_DESTROY, NULL); + } else { + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-2/remote-lfa/maximum-metric", + NB_OP_MODIFY, metric_str); + } + } + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_frr_remote_lfa_max_metric(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " isis fast-reroute remote-lfa maximum-metric %s %s\n", + yang_dnode_get_string(dnode, NULL), + dnode->parent->parent->schema->name); +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-{1,2}/ti-lfa/enable + */ +DEFPY(isis_ti_lfa, isis_ti_lfa_cmd, + "[no] isis fast-reroute ti-lfa [level-1|level-2]$level [node-protection$node_protection [link-fallback$link_fallback]]", + NO_STR + "IS-IS routing protocol\n" + "Interface IP Fast-reroute configuration\n" + "Enable TI-LFA computation\n" + "Enable TI-LFA computation for Level 1 only\n" + "Enable TI-LFA computation for Level 2 only\n" + "Protect against node failures\n" + "Enable link-protection fallback\n") +{ + if (!level || strmatch(level, "level-1")) { + if (no) { + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-1/ti-lfa/enable", + NB_OP_MODIFY, "false"); + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-1/ti-lfa/node-protection", + NB_OP_MODIFY, "false"); + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-1/ti-lfa/link-fallback", + NB_OP_MODIFY, "false"); + } else { + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-1/ti-lfa/enable", + NB_OP_MODIFY, "true"); + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-1/ti-lfa/node-protection", + NB_OP_MODIFY, + node_protection ? "true" : "false"); + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-1/ti-lfa/link-fallback", + NB_OP_MODIFY, link_fallback ? "true" : "false"); + } + } + if (!level || strmatch(level, "level-2")) { + if (no) { + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-2/ti-lfa/enable", + NB_OP_MODIFY, "false"); + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-2/ti-lfa/node-protection", + NB_OP_MODIFY, "false"); + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-2/ti-lfa/link-fallback", + NB_OP_MODIFY, "false"); + } else { + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-2/ti-lfa/enable", + NB_OP_MODIFY, "true"); + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-2/ti-lfa/node-protection", + NB_OP_MODIFY, + node_protection ? "true" : "false"); + nb_cli_enqueue_change( + vty, + "./frr-isisd:isis/fast-reroute/level-2/ti-lfa/link-fallback", + NB_OP_MODIFY, link_fallback ? "true" : "false"); + } + } + + return nb_cli_apply_changes(vty, NULL); +} + +/* + * XPath: /frr-isisd:isis/instance/log-adjacency-changes + */ +DEFPY_YANG(log_adj_changes, log_adj_changes_cmd, "[no] log-adjacency-changes", + NO_STR "Log changes in adjacency state\n") +{ + nb_cli_enqueue_change(vty, "./log-adjacency-changes", NB_OP_MODIFY, + no ? "false" : "true"); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_log_adjacency(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + vty_out(vty, " log-adjacency-changes\n"); +} + +/* + * XPath: /frr-isisd:isis/instance/mpls/ldp-sync + */ +DEFPY(isis_mpls_ldp_sync, isis_mpls_ldp_sync_cmd, "mpls ldp-sync", + MPLS_STR MPLS_LDP_SYNC_STR) +{ + nb_cli_enqueue_change(vty, "./mpls/ldp-sync", NB_OP_CREATE, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY(no_isis_mpls_ldp_sync, no_isis_mpls_ldp_sync_cmd, "no mpls ldp-sync", + NO_STR MPLS_STR NO_MPLS_LDP_SYNC_STR) +{ + nb_cli_enqueue_change(vty, "./mpls/ldp-sync", NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_mpls_ldp_sync(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " mpls ldp-sync\n"); +} + +DEFPY(isis_mpls_ldp_sync_holddown, isis_mpls_ldp_sync_holddown_cmd, + "mpls ldp-sync holddown (0-10000)", + MPLS_STR MPLS_LDP_SYNC_STR + "Time to wait for LDP-SYNC to occur before restoring interface metric\n" + "Time in seconds\n") +{ + nb_cli_enqueue_change(vty, "./mpls/ldp-sync/holddown", NB_OP_MODIFY, + holddown_str); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY(no_isis_mpls_ldp_sync_holddown, no_isis_mpls_ldp_sync_holddown_cmd, + "no mpls ldp-sync holddown [<(1-10000)>]", + NO_STR MPLS_STR MPLS_LDP_SYNC_STR NO_MPLS_LDP_SYNC_HOLDDOWN_STR "Time in seconds\n") +{ + nb_cli_enqueue_change(vty, "./mpls/ldp-sync/holddown", NB_OP_DESTROY, + NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_mpls_ldp_sync_holddown(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " mpls ldp-sync holddown %s\n", + yang_dnode_get_string(dnode, NULL)); +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/mpls/ldp-sync + */ +DEFPY(isis_mpls_if_ldp_sync, isis_mpls_if_ldp_sync_cmd, + "[no] isis mpls ldp-sync", + NO_STR "IS-IS routing protocol\n" MPLS_STR MPLS_LDP_SYNC_STR) +{ + const struct lyd_node *dnode; + + dnode = yang_dnode_getf(vty->candidate_config->dnode, + "%s/frr-isisd:isis", VTY_CURR_XPATH); + if (dnode == NULL) { + vty_out(vty, "ISIS is not enabled on this circuit\n"); + return CMD_SUCCESS; + } + + nb_cli_enqueue_change(vty, "./frr-isisd:isis/mpls/ldp-sync", + NB_OP_MODIFY, no ? "false" : "true"); + + return nb_cli_apply_changes(vty, NULL); +} + + +void cli_show_isis_mpls_if_ldp_sync(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + + vty_out(vty, " isis mpls ldp-sync\n"); +} + +DEFPY(isis_mpls_if_ldp_sync_holddown, isis_mpls_if_ldp_sync_holddown_cmd, + "isis mpls ldp-sync holddown (0-10000)", + "IS-IS routing protocol\n" MPLS_STR MPLS_LDP_SYNC_STR + "Time to wait for LDP-SYNC to occur before restoring interface metric\n" + "Time in seconds\n") +{ + const struct lyd_node *dnode; + + dnode = yang_dnode_getf(vty->candidate_config->dnode, + "%s/frr-isisd:isis", VTY_CURR_XPATH); + if (dnode == NULL) { + vty_out(vty, "ISIS is not enabled on this circuit\n"); + return CMD_SUCCESS; + } + + nb_cli_enqueue_change(vty, "./frr-isisd:isis/mpls/holddown", + NB_OP_MODIFY, holddown_str); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY(no_isis_mpls_if_ldp_sync_holddown, no_isis_mpls_if_ldp_sync_holddown_cmd, + "no isis mpls ldp-sync holddown [<(1-10000)>]", + NO_STR "IS-IS routing protocol\n" MPLS_STR NO_MPLS_LDP_SYNC_STR + NO_MPLS_LDP_SYNC_HOLDDOWN_STR "Time in seconds\n") +{ + const struct lyd_node *dnode; + + dnode = yang_dnode_getf(vty->candidate_config->dnode, + "%s/frr-isisd:isis", VTY_CURR_XPATH); + if (dnode == NULL) { + vty_out(vty, "ISIS is not enabled on this circuit\n"); + return CMD_SUCCESS; + } + + nb_cli_enqueue_change(vty, "./frr-isisd:isis/mpls/holddown", + NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_mpls_if_ldp_sync_holddown(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " isis mpls ldp-sync holddown %s\n", + yang_dnode_get_string(dnode, NULL)); +} + +void isis_cli_init(void) +{ + install_element(CONFIG_NODE, &router_isis_cmd); + install_element(CONFIG_NODE, &no_router_isis_cmd); + + install_element(INTERFACE_NODE, &ip_router_isis_cmd); + install_element(INTERFACE_NODE, &ip_router_isis_vrf_cmd); + install_element(INTERFACE_NODE, &ip6_router_isis_cmd); + install_element(INTERFACE_NODE, &ip6_router_isis_vrf_cmd); + install_element(INTERFACE_NODE, &no_ip_router_isis_cmd); + install_element(INTERFACE_NODE, &no_ip_router_isis_vrf_cmd); + install_element(INTERFACE_NODE, &isis_bfd_cmd); + install_element(INTERFACE_NODE, &isis_bfd_profile_cmd); + + install_element(ISIS_NODE, &net_cmd); + + install_element(ISIS_NODE, &is_type_cmd); + install_element(ISIS_NODE, &no_is_type_cmd); + + install_element(ISIS_NODE, &dynamic_hostname_cmd); + + install_element(ISIS_NODE, &set_overload_bit_cmd); + install_element(ISIS_NODE, &attached_bit_send_cmd); + install_element(ISIS_NODE, &attached_bit_receive_ignore_cmd); + + install_element(ISIS_NODE, &metric_style_cmd); + install_element(ISIS_NODE, &no_metric_style_cmd); + + install_element(ISIS_NODE, &area_passwd_cmd); + install_element(ISIS_NODE, &domain_passwd_cmd); + install_element(ISIS_NODE, &no_area_passwd_cmd); + + install_element(ISIS_NODE, &lsp_gen_interval_cmd); + install_element(ISIS_NODE, &no_lsp_gen_interval_cmd); + install_element(ISIS_NODE, &lsp_refresh_interval_cmd); + install_element(ISIS_NODE, &no_lsp_refresh_interval_cmd); + install_element(ISIS_NODE, &max_lsp_lifetime_cmd); + install_element(ISIS_NODE, &no_max_lsp_lifetime_cmd); + install_element(ISIS_NODE, &lsp_timers_cmd); + install_element(ISIS_NODE, &no_lsp_timers_cmd); + install_element(ISIS_NODE, &area_lsp_mtu_cmd); + install_element(ISIS_NODE, &no_area_lsp_mtu_cmd); + + install_element(ISIS_NODE, &spf_interval_cmd); + install_element(ISIS_NODE, &no_spf_interval_cmd); + install_element(ISIS_NODE, &spf_prefix_priority_cmd); + install_element(ISIS_NODE, &no_spf_prefix_priority_cmd); + install_element(ISIS_NODE, &spf_delay_ietf_cmd); + install_element(ISIS_NODE, &no_spf_delay_ietf_cmd); + + install_element(ISIS_NODE, &area_purge_originator_cmd); + + install_element(ISIS_NODE, &isis_mpls_te_on_cmd); + install_element(ISIS_NODE, &no_isis_mpls_te_on_cmd); + install_element(ISIS_NODE, &isis_mpls_te_router_addr_cmd); + install_element(ISIS_NODE, &no_isis_mpls_te_router_addr_cmd); + install_element(ISIS_NODE, &isis_mpls_te_router_addr_v6_cmd); + install_element(ISIS_NODE, &no_isis_mpls_te_router_addr_v6_cmd); + install_element(ISIS_NODE, &isis_mpls_te_inter_as_cmd); + install_element(ISIS_NODE, &isis_mpls_te_export_cmd); + install_element(ISIS_NODE, &no_isis_mpls_te_export_cmd); + + install_element(ISIS_NODE, &isis_default_originate_cmd); + install_element(ISIS_NODE, &isis_redistribute_cmd); + + install_element(ISIS_NODE, &isis_topology_cmd); + + install_element(ISIS_NODE, &isis_sr_enable_cmd); + install_element(ISIS_NODE, &no_isis_sr_enable_cmd); + install_element(ISIS_NODE, &isis_sr_global_block_label_range_cmd); + install_element(ISIS_NODE, &no_isis_sr_global_block_label_range_cmd); + install_element(ISIS_NODE, &isis_sr_node_msd_cmd); + install_element(ISIS_NODE, &no_isis_sr_node_msd_cmd); + install_element(ISIS_NODE, &isis_sr_prefix_sid_cmd); + install_element(ISIS_NODE, &no_isis_sr_prefix_sid_cmd); + install_element(ISIS_NODE, &isis_frr_lfa_priority_limit_cmd); + install_element(ISIS_NODE, &isis_frr_lfa_tiebreaker_cmd); + install_element(ISIS_NODE, &isis_frr_lfa_load_sharing_cmd); + install_element(ISIS_NODE, &isis_frr_remote_lfa_plist_cmd); + install_element(ISIS_NODE, &no_isis_frr_remote_lfa_plist_cmd); + + install_element(INTERFACE_NODE, &isis_passive_cmd); + + install_element(INTERFACE_NODE, &isis_passwd_cmd); + install_element(INTERFACE_NODE, &no_isis_passwd_cmd); + + install_element(INTERFACE_NODE, &isis_metric_cmd); + install_element(INTERFACE_NODE, &no_isis_metric_cmd); + + install_element(INTERFACE_NODE, &isis_hello_interval_cmd); + install_element(INTERFACE_NODE, &no_isis_hello_interval_cmd); + + install_element(INTERFACE_NODE, &isis_hello_multiplier_cmd); + install_element(INTERFACE_NODE, &no_isis_hello_multiplier_cmd); + + install_element(INTERFACE_NODE, &isis_threeway_adj_cmd); + + install_element(INTERFACE_NODE, &isis_hello_padding_cmd); + + install_element(INTERFACE_NODE, &csnp_interval_cmd); + install_element(INTERFACE_NODE, &no_csnp_interval_cmd); + + install_element(INTERFACE_NODE, &psnp_interval_cmd); + install_element(INTERFACE_NODE, &no_psnp_interval_cmd); + + install_element(INTERFACE_NODE, &circuit_topology_cmd); + + install_element(INTERFACE_NODE, &isis_circuit_type_cmd); + install_element(INTERFACE_NODE, &no_isis_circuit_type_cmd); + + install_element(INTERFACE_NODE, &isis_network_cmd); + + install_element(INTERFACE_NODE, &isis_priority_cmd); + install_element(INTERFACE_NODE, &no_isis_priority_cmd); + + install_element(INTERFACE_NODE, &isis_lfa_cmd); + install_element(INTERFACE_NODE, &isis_lfa_exclude_interface_cmd); + install_element(INTERFACE_NODE, &isis_remote_lfa_cmd); + install_element(INTERFACE_NODE, &isis_remote_lfa_max_metric_cmd); + install_element(INTERFACE_NODE, &isis_ti_lfa_cmd); + + install_element(ISIS_NODE, &log_adj_changes_cmd); + + install_element(ISIS_NODE, &isis_mpls_ldp_sync_cmd); + install_element(ISIS_NODE, &no_isis_mpls_ldp_sync_cmd); + install_element(ISIS_NODE, &isis_mpls_ldp_sync_holddown_cmd); + install_element(ISIS_NODE, &no_isis_mpls_ldp_sync_holddown_cmd); + install_element(INTERFACE_NODE, &isis_mpls_if_ldp_sync_cmd); + install_element(INTERFACE_NODE, &isis_mpls_if_ldp_sync_holddown_cmd); + install_element(INTERFACE_NODE, &no_isis_mpls_if_ldp_sync_holddown_cmd); +} + +#endif /* ifndef FABRICD */ |