frr/ripd/rip_cli.c

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

1223 lines
33 KiB
C
Raw Normal View History

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
* Copyright (C) 2018 NetDEF, Inc.
* Renato Westphal
*/
#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 "ripd/ripd.h"
#include "ripd/rip_nb.h"
#include "ripd/rip_cli_clippy.c"
/*
* XPath: /frr-ripd:ripd/instance
*/
DEFPY_YANG_NOSH (router_rip,
router_rip_cmd,
"router rip [vrf NAME]",
"Enable a routing process\n"
"Routing Information Protocol (RIP)\n"
VRF_CMD_HELP_STR)
{
char xpath[XPATH_MAXLEN];
int ret;
/* Build RIP instance XPath. */
if (!vrf)
vrf = VRF_DEFAULT_NAME;
snprintf(xpath, sizeof(xpath), "/frr-ripd:ripd/instance[vrf='%s']",
vrf);
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
ret = nb_cli_apply_changes(vty, NULL);
if (ret == CMD_SUCCESS)
VTY_PUSH_XPATH(RIP_NODE, xpath);
return ret;
}
DEFPY_YANG (no_router_rip,
no_router_rip_cmd,
"no router rip [vrf NAME]",
NO_STR
"Enable a routing process\n"
"Routing Information Protocol (RIP)\n"
VRF_CMD_HELP_STR)
{
char xpath[XPATH_MAXLEN];
/* Build RIP instance XPath. */
if (!vrf)
vrf = VRF_DEFAULT_NAME;
snprintf(xpath, sizeof(xpath), "/frr-ripd:ripd/instance[vrf='%s']",
vrf);
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
northbound: KISS always batch yang config (file read), it's faster The backoff code assumed that yang operations always completed quickly. It checked for > 100 YANG modeled commands happening in under 1 second to enable batching. If 100 yang modeled commands always take longer than 1 second batching is never enabled. This is the exact opposite of what we want to happen since batching speeds the operations up. Here are the results for libyang2 code without and with batching. | action | 1K rts | 2K rts | 1K rts | 2K rts | 20k rts | | | nobatch | nobatch | batch | batch | batch | | Add IPv4 | .881 | 1.28 | .703 | 1.04 | 8.16 | | Add Same IPv4 | 28.7 | 113 | .590 | .860 | 6.09 | | Rem 1/2 IPv4 | .376 | .442 | .379 | .435 | 1.44 | | Add Same IPv4 | 28.7 | 113 | .576 | .841 | 6.02 | | Rem All IPv4 | 17.4 | 71.8 | .559 | .813 | 5.57 | (IPv6 numbers are basically the same as iPv4, a couple percent slower) Clearly we need this. Please note the growth (1K to 2K) w/o batching is non-linear and 100 times slower than batched. Notes on code: The use of the new `nb_cli_apply_changes_clear_pending` is to commit any pending changes (including the current one). This is done when the code would not correctly handle a single diff that included the current changes with possible following changes. For example, a "no" command followed by a new value to replace it would be merged into a change, and the code would not deal well with that. A good example of this is BGP neighbor peer-group changing. The other use is after entering a router level (e.g., "router bgp") where the follow-on command handlers expect that router object to now exists. The code eventually needs to be cleaned up to not fail in these cases, but that is for future NB cleanup. Signed-off-by: Christian Hopps <chopps@labn.net>
2021-05-28 21:16:18 +02:00
return nb_cli_apply_changes_clear_pending(vty, NULL);
}
void cli_show_router_rip(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *vrf_name;
vrf_name = yang_dnode_get_string(dnode, "./vrf");
vty_out(vty, "!\n");
vty_out(vty, "router rip");
if (!strmatch(vrf_name, VRF_DEFAULT_NAME))
vty_out(vty, " vrf %s", vrf_name);
vty_out(vty, "\n");
}
/*
* XPath: /frr-ripd:ripd/instance/allow-ecmp
*/
DEFUN_YANG (rip_allow_ecmp,
rip_allow_ecmp_cmd,
"allow-ecmp [" CMD_RANGE_STR(1, MULTIPATH_NUM) "]",
"Allow Equal Cost MultiPath\n"
"Number of paths\n")
{
int idx_number = 1;
char mpaths[3] = {};
uint32_t paths = MULTIPATH_NUM;
if (argv[idx_number])
paths = strtol(argv[idx_number]->arg, NULL, 10);
snprintf(mpaths, sizeof(mpaths), "%u", paths);
nb_cli_enqueue_change(vty, "./allow-ecmp", NB_OP_MODIFY, mpaths);
return nb_cli_apply_changes(vty, NULL);
}
DEFUN_YANG (no_rip_allow_ecmp,
no_rip_allow_ecmp_cmd,
"no allow-ecmp [" CMD_RANGE_STR(1, MULTIPATH_NUM) "]",
NO_STR
"Allow Equal Cost MultiPath\n"
"Number of paths\n")
{
nb_cli_enqueue_change(vty, "./allow-ecmp", NB_OP_MODIFY, 0);
return nb_cli_apply_changes(vty, NULL);
}
void cli_show_rip_allow_ecmp(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
uint8_t paths;
paths = yang_dnode_get_uint8(dnode, NULL);
if (!paths)
vty_out(vty, " no allow-ecmp\n");
else
vty_out(vty, " allow-ecmp %d\n", paths);
}
/*
* XPath: /frr-ripd:ripd/instance/default-information-originate
*/
DEFPY_YANG (rip_default_information_originate,
rip_default_information_originate_cmd,
"[no] default-information originate",
NO_STR
"Control distribution of default route\n"
"Distribute a default route\n")
{
nb_cli_enqueue_change(vty, "./default-information-originate",
NB_OP_MODIFY, no ? "false" : "true");
return nb_cli_apply_changes(vty, NULL);
}
void cli_show_rip_default_information_originate(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, " default-information originate\n");
}
/*
* XPath: /frr-ripd:ripd/instance/default-metric
*/
DEFPY_YANG (rip_default_metric,
rip_default_metric_cmd,
"default-metric (1-16)",
"Set a metric of redistribute routes\n"
"Default metric\n")
{
nb_cli_enqueue_change(vty, "./default-metric", NB_OP_MODIFY,
default_metric_str);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG (no_rip_default_metric,
no_rip_default_metric_cmd,
"no default-metric [(1-16)]",
NO_STR
"Set a metric of redistribute routes\n"
"Default metric\n")
{
nb_cli_enqueue_change(vty, "./default-metric", NB_OP_MODIFY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
void cli_show_rip_default_metric(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " default-metric %s\n",
yang_dnode_get_string(dnode, NULL));
}
/*
* XPath: /frr-ripd:ripd/instance/distance/default
*/
DEFPY_YANG (rip_distance,
rip_distance_cmd,
"distance (1-255)",
"Administrative distance\n"
"Distance value\n")
{
nb_cli_enqueue_change(vty, "./distance/default", NB_OP_MODIFY,
distance_str);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG (no_rip_distance,
no_rip_distance_cmd,
"no distance [(1-255)]",
NO_STR
"Administrative distance\n"
"Distance value\n")
{
nb_cli_enqueue_change(vty, "./distance/default", NB_OP_MODIFY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
void cli_show_rip_distance(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
if (yang_dnode_is_default(dnode, NULL))
vty_out(vty, " no distance\n");
else
vty_out(vty, " distance %s\n",
yang_dnode_get_string(dnode, NULL));
}
/*
* XPath: /frr-ripd:ripd/instance/distance/source
*/
DEFPY_YANG (rip_distance_source,
rip_distance_source_cmd,
"[no] distance (1-255) A.B.C.D/M$prefix [WORD$acl]",
NO_STR
"Administrative distance\n"
"Distance value\n"
"IP source prefix\n"
"Access list name\n")
{
if (!no) {
nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY,
distance_str);
nb_cli_enqueue_change(vty, "./access-list",
acl ? NB_OP_MODIFY : NB_OP_DESTROY, acl);
} else
nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, "./distance/source[prefix='%s']",
prefix_str);
}
void cli_show_rip_distance_source(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " distance %s %s",
yang_dnode_get_string(dnode, "./distance"),
yang_dnode_get_string(dnode, "./prefix"));
if (yang_dnode_exists(dnode, "./access-list"))
vty_out(vty, " %s",
yang_dnode_get_string(dnode, "./access-list"));
vty_out(vty, "\n");
}
/*
* XPath: /frr-ripd:ripd/instance/explicit-neighbor
*/
DEFPY_YANG (rip_neighbor,
rip_neighbor_cmd,
"[no] neighbor A.B.C.D",
NO_STR
"Specify a neighbor router\n"
"Neighbor address\n")
{
nb_cli_enqueue_change(vty, "./explicit-neighbor",
no ? NB_OP_DESTROY : NB_OP_CREATE, neighbor_str);
return nb_cli_apply_changes(vty, NULL);
}
void cli_show_rip_neighbor(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " neighbor %s\n", yang_dnode_get_string(dnode, NULL));
}
/*
* XPath: /frr-ripd:ripd/instance/network
*/
DEFPY_YANG (rip_network_prefix,
rip_network_prefix_cmd,
"[no] network A.B.C.D/M",
NO_STR
"Enable routing on an IP network\n"
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
{
nb_cli_enqueue_change(vty, "./network",
no ? NB_OP_DESTROY : NB_OP_CREATE, network_str);
return nb_cli_apply_changes(vty, NULL);
}
void cli_show_rip_network_prefix(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " network %s\n", yang_dnode_get_string(dnode, NULL));
}
/*
* XPath: /frr-ripd:ripd/instance/interface
*/
DEFPY_YANG (rip_network_if,
rip_network_if_cmd,
"[no] network WORD",
NO_STR
"Enable routing on an IP network\n"
"Interface name\n")
{
nb_cli_enqueue_change(vty, "./interface",
no ? NB_OP_DESTROY : NB_OP_CREATE, network);
return nb_cli_apply_changes(vty, NULL);
}
void cli_show_rip_network_interface(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " network %s\n", yang_dnode_get_string(dnode, NULL));
}
/*
* XPath: /frr-ripd:ripd/instance/offset-list
*/
DEFPY_YANG (rip_offset_list,
rip_offset_list_cmd,
"[no] offset-list ACCESSLIST4_NAME$acl <in|out>$direction (0-16)$metric [IFNAME]",
NO_STR
"Modify RIP metric\n"
"Access-list name\n"
"For incoming updates\n"
"For outgoing updates\n"
"Metric value\n"
"Interface to match\n")
{
if (!no) {
nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
nb_cli_enqueue_change(vty, "./access-list", NB_OP_MODIFY, acl);
nb_cli_enqueue_change(vty, "./metric", NB_OP_MODIFY,
metric_str);
} else
nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(
vty, "./offset-list[interface='%s'][direction='%s']",
ifname ? ifname : "*", direction);
}
void cli_show_rip_offset_list(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *interface;
interface = yang_dnode_get_string(dnode, "./interface");
vty_out(vty, " offset-list %s %s %s",
yang_dnode_get_string(dnode, "./access-list"),
yang_dnode_get_string(dnode, "./direction"),
yang_dnode_get_string(dnode, "./metric"));
if (!strmatch(interface, "*"))
vty_out(vty, " %s", interface);
vty_out(vty, "\n");
}
ripd: retrofit the 'passive-interface' command to the new northbound model In ripd, the "passive-interface default" command has the following behavior: * All interfaces are converted to the passive mode; * The "passive-interface IFNAME" command becomes a no-operation and "passive-interface IFNAME" statements are removed from the running configuration. * The "no passive-interface IFNAME" can be used to remove interfaces from the passive mode. This command was modeled using the following YANG data nodes in the frr-ripd module: leaf passive-default { type boolean; default "false"; description "Control whether interfaces are in the passive mode by default or not."; } leaf-list passive-interface { when "../passive-default = 'false'"; type string { length "1..16"; } description "A list of interfaces where the sending of RIP packets is disabled."; } leaf-list non-passive-interface { when "../passive-default = 'true'"; type string { length "1..16"; } description "A list of interfaces where the sending of RIP packets is enabled."; } The 'when' statements guarantee that the list of passive interfaces is cleared when the "passive-interface default" command is entered (likewise, they guarantee that the list of non-passive interfaces is cleared when the "passive-interface default" command is removed). This matches exactly the behavior we want to model. Finally, move the 'passive_default' global variable into the 'rip' structure where it belongs. This fixed the bug where the "passive-interface default" command was being retained after a "no router rip" + "router rip". Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
2018-05-09 06:35:00 +02:00
/*
* XPath: /frr-ripd:ripd/instance/passive-default
*/
DEFPY_YANG (rip_passive_default,
ripd: retrofit the 'passive-interface' command to the new northbound model In ripd, the "passive-interface default" command has the following behavior: * All interfaces are converted to the passive mode; * The "passive-interface IFNAME" command becomes a no-operation and "passive-interface IFNAME" statements are removed from the running configuration. * The "no passive-interface IFNAME" can be used to remove interfaces from the passive mode. This command was modeled using the following YANG data nodes in the frr-ripd module: leaf passive-default { type boolean; default "false"; description "Control whether interfaces are in the passive mode by default or not."; } leaf-list passive-interface { when "../passive-default = 'false'"; type string { length "1..16"; } description "A list of interfaces where the sending of RIP packets is disabled."; } leaf-list non-passive-interface { when "../passive-default = 'true'"; type string { length "1..16"; } description "A list of interfaces where the sending of RIP packets is enabled."; } The 'when' statements guarantee that the list of passive interfaces is cleared when the "passive-interface default" command is entered (likewise, they guarantee that the list of non-passive interfaces is cleared when the "passive-interface default" command is removed). This matches exactly the behavior we want to model. Finally, move the 'passive_default' global variable into the 'rip' structure where it belongs. This fixed the bug where the "passive-interface default" command was being retained after a "no router rip" + "router rip". Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
2018-05-09 06:35:00 +02:00
rip_passive_default_cmd,
"[no] passive-interface default",
NO_STR
"Suppress routing updates on an interface\n"
"default for all interfaces\n")
{
nb_cli_enqueue_change(vty, "./passive-default", NB_OP_MODIFY,
no ? "false" : "true");
return nb_cli_apply_changes(vty, NULL);
ripd: retrofit the 'passive-interface' command to the new northbound model In ripd, the "passive-interface default" command has the following behavior: * All interfaces are converted to the passive mode; * The "passive-interface IFNAME" command becomes a no-operation and "passive-interface IFNAME" statements are removed from the running configuration. * The "no passive-interface IFNAME" can be used to remove interfaces from the passive mode. This command was modeled using the following YANG data nodes in the frr-ripd module: leaf passive-default { type boolean; default "false"; description "Control whether interfaces are in the passive mode by default or not."; } leaf-list passive-interface { when "../passive-default = 'false'"; type string { length "1..16"; } description "A list of interfaces where the sending of RIP packets is disabled."; } leaf-list non-passive-interface { when "../passive-default = 'true'"; type string { length "1..16"; } description "A list of interfaces where the sending of RIP packets is enabled."; } The 'when' statements guarantee that the list of passive interfaces is cleared when the "passive-interface default" command is entered (likewise, they guarantee that the list of non-passive interfaces is cleared when the "passive-interface default" command is removed). This matches exactly the behavior we want to model. Finally, move the 'passive_default' global variable into the 'rip' structure where it belongs. This fixed the bug where the "passive-interface default" command was being retained after a "no router rip" + "router rip". Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
2018-05-09 06:35:00 +02:00
}
void cli_show_rip_passive_default(struct vty *vty, const struct lyd_node *dnode,
ripd: retrofit the 'passive-interface' command to the new northbound model In ripd, the "passive-interface default" command has the following behavior: * All interfaces are converted to the passive mode; * The "passive-interface IFNAME" command becomes a no-operation and "passive-interface IFNAME" statements are removed from the running configuration. * The "no passive-interface IFNAME" can be used to remove interfaces from the passive mode. This command was modeled using the following YANG data nodes in the frr-ripd module: leaf passive-default { type boolean; default "false"; description "Control whether interfaces are in the passive mode by default or not."; } leaf-list passive-interface { when "../passive-default = 'false'"; type string { length "1..16"; } description "A list of interfaces where the sending of RIP packets is disabled."; } leaf-list non-passive-interface { when "../passive-default = 'true'"; type string { length "1..16"; } description "A list of interfaces where the sending of RIP packets is enabled."; } The 'when' statements guarantee that the list of passive interfaces is cleared when the "passive-interface default" command is entered (likewise, they guarantee that the list of non-passive interfaces is cleared when the "passive-interface default" command is removed). This matches exactly the behavior we want to model. Finally, move the 'passive_default' global variable into the 'rip' structure where it belongs. This fixed the bug where the "passive-interface default" command was being retained after a "no router rip" + "router rip". Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
2018-05-09 06:35:00 +02:00
bool show_defaults)
{
if (!yang_dnode_get_bool(dnode, NULL))
vty_out(vty, " no");
vty_out(vty, " passive-interface default\n");
}
/*
* XPath: /frr-ripd:ripd/instance/passive-interface
* /frr-ripd:ripd/instance/non-passive-interface
*/
DEFPY_YANG (rip_passive_interface,
ripd: retrofit the 'passive-interface' command to the new northbound model In ripd, the "passive-interface default" command has the following behavior: * All interfaces are converted to the passive mode; * The "passive-interface IFNAME" command becomes a no-operation and "passive-interface IFNAME" statements are removed from the running configuration. * The "no passive-interface IFNAME" can be used to remove interfaces from the passive mode. This command was modeled using the following YANG data nodes in the frr-ripd module: leaf passive-default { type boolean; default "false"; description "Control whether interfaces are in the passive mode by default or not."; } leaf-list passive-interface { when "../passive-default = 'false'"; type string { length "1..16"; } description "A list of interfaces where the sending of RIP packets is disabled."; } leaf-list non-passive-interface { when "../passive-default = 'true'"; type string { length "1..16"; } description "A list of interfaces where the sending of RIP packets is enabled."; } The 'when' statements guarantee that the list of passive interfaces is cleared when the "passive-interface default" command is entered (likewise, they guarantee that the list of non-passive interfaces is cleared when the "passive-interface default" command is removed). This matches exactly the behavior we want to model. Finally, move the 'passive_default' global variable into the 'rip' structure where it belongs. This fixed the bug where the "passive-interface default" command was being retained after a "no router rip" + "router rip". Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
2018-05-09 06:35:00 +02:00
rip_passive_interface_cmd,
"[no] passive-interface IFNAME",
NO_STR
"Suppress routing updates on an interface\n"
"Interface name\n")
{
bool passive_default =
yang_dnode_get_bool(vty->candidate_config->dnode, "%s%s",
VTY_CURR_XPATH, "/passive-default");
if (passive_default) {
nb_cli_enqueue_change(vty, "./non-passive-interface",
no ? NB_OP_CREATE : NB_OP_DESTROY,
ifname);
} else {
nb_cli_enqueue_change(vty, "./passive-interface",
no ? NB_OP_DESTROY : NB_OP_CREATE,
ifname);
}
return nb_cli_apply_changes(vty, NULL);
ripd: retrofit the 'passive-interface' command to the new northbound model In ripd, the "passive-interface default" command has the following behavior: * All interfaces are converted to the passive mode; * The "passive-interface IFNAME" command becomes a no-operation and "passive-interface IFNAME" statements are removed from the running configuration. * The "no passive-interface IFNAME" can be used to remove interfaces from the passive mode. This command was modeled using the following YANG data nodes in the frr-ripd module: leaf passive-default { type boolean; default "false"; description "Control whether interfaces are in the passive mode by default or not."; } leaf-list passive-interface { when "../passive-default = 'false'"; type string { length "1..16"; } description "A list of interfaces where the sending of RIP packets is disabled."; } leaf-list non-passive-interface { when "../passive-default = 'true'"; type string { length "1..16"; } description "A list of interfaces where the sending of RIP packets is enabled."; } The 'when' statements guarantee that the list of passive interfaces is cleared when the "passive-interface default" command is entered (likewise, they guarantee that the list of non-passive interfaces is cleared when the "passive-interface default" command is removed). This matches exactly the behavior we want to model. Finally, move the 'passive_default' global variable into the 'rip' structure where it belongs. This fixed the bug where the "passive-interface default" command was being retained after a "no router rip" + "router rip". Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
2018-05-09 06:35:00 +02:00
}
void cli_show_rip_passive_interface(struct vty *vty,
const struct lyd_node *dnode,
ripd: retrofit the 'passive-interface' command to the new northbound model In ripd, the "passive-interface default" command has the following behavior: * All interfaces are converted to the passive mode; * The "passive-interface IFNAME" command becomes a no-operation and "passive-interface IFNAME" statements are removed from the running configuration. * The "no passive-interface IFNAME" can be used to remove interfaces from the passive mode. This command was modeled using the following YANG data nodes in the frr-ripd module: leaf passive-default { type boolean; default "false"; description "Control whether interfaces are in the passive mode by default or not."; } leaf-list passive-interface { when "../passive-default = 'false'"; type string { length "1..16"; } description "A list of interfaces where the sending of RIP packets is disabled."; } leaf-list non-passive-interface { when "../passive-default = 'true'"; type string { length "1..16"; } description "A list of interfaces where the sending of RIP packets is enabled."; } The 'when' statements guarantee that the list of passive interfaces is cleared when the "passive-interface default" command is entered (likewise, they guarantee that the list of non-passive interfaces is cleared when the "passive-interface default" command is removed). This matches exactly the behavior we want to model. Finally, move the 'passive_default' global variable into the 'rip' structure where it belongs. This fixed the bug where the "passive-interface default" command was being retained after a "no router rip" + "router rip". Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
2018-05-09 06:35:00 +02:00
bool show_defaults)
{
vty_out(vty, " passive-interface %s\n",
yang_dnode_get_string(dnode, NULL));
}
void cli_show_rip_non_passive_interface(struct vty *vty,
const struct lyd_node *dnode,
ripd: retrofit the 'passive-interface' command to the new northbound model In ripd, the "passive-interface default" command has the following behavior: * All interfaces are converted to the passive mode; * The "passive-interface IFNAME" command becomes a no-operation and "passive-interface IFNAME" statements are removed from the running configuration. * The "no passive-interface IFNAME" can be used to remove interfaces from the passive mode. This command was modeled using the following YANG data nodes in the frr-ripd module: leaf passive-default { type boolean; default "false"; description "Control whether interfaces are in the passive mode by default or not."; } leaf-list passive-interface { when "../passive-default = 'false'"; type string { length "1..16"; } description "A list of interfaces where the sending of RIP packets is disabled."; } leaf-list non-passive-interface { when "../passive-default = 'true'"; type string { length "1..16"; } description "A list of interfaces where the sending of RIP packets is enabled."; } The 'when' statements guarantee that the list of passive interfaces is cleared when the "passive-interface default" command is entered (likewise, they guarantee that the list of non-passive interfaces is cleared when the "passive-interface default" command is removed). This matches exactly the behavior we want to model. Finally, move the 'passive_default' global variable into the 'rip' structure where it belongs. This fixed the bug where the "passive-interface default" command was being retained after a "no router rip" + "router rip". Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
2018-05-09 06:35:00 +02:00
bool show_defaults)
{
vty_out(vty, " no passive-interface %s\n",
yang_dnode_get_string(dnode, NULL));
}
/*
* XPath: /frr-ripd:ripd/instance/redistribute
*/
DEFPY_YANG (rip_redistribute,
rip_redistribute_cmd,
"[no] redistribute " FRR_REDIST_STR_RIPD "$protocol [{metric (0-16)|route-map RMAP_NAME$route_map}]",
NO_STR
REDIST_STR
FRR_REDIST_HELP_STR_RIPD
"Metric\n"
"Metric value\n"
"Route map reference\n"
"Pointer to route-map entries\n")
{
if (!no) {
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);
nb_cli_enqueue_change(vty, "./metric",
metric_str ? NB_OP_MODIFY : NB_OP_DESTROY,
metric_str);
} else
nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, "./redistribute[protocol='%s']",
protocol);
}
void cli_show_rip_redistribute(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " redistribute %s",
yang_dnode_get_string(dnode, "./protocol"));
if (yang_dnode_exists(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");
}
/*
* XPath: /frr-ripd:ripd/instance/static-route
*/
DEFPY_YANG (rip_route,
rip_route_cmd,
"[no] route A.B.C.D/M",
NO_STR
"RIP static route configuration\n"
"IP prefix <network>/<length>\n")
{
nb_cli_enqueue_change(vty, "./static-route",
no ? NB_OP_DESTROY : NB_OP_CREATE, route_str);
return nb_cli_apply_changes(vty, NULL);
}
void cli_show_rip_route(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " route %s\n", yang_dnode_get_string(dnode, NULL));
}
/*
* XPath: /frr-ripd:ripd/instance/timers
*/
DEFPY_YANG (rip_timers,
rip_timers_cmd,
"timers basic (5-2147483647)$update (5-2147483647)$timeout (5-2147483647)$garbage",
"Adjust routing timers\n"
"Basic routing protocol update timers\n"
"Routing table update timer value in second. Default is 30.\n"
"Routing information timeout timer. Default is 180.\n"
"Garbage collection timer. Default is 120.\n")
{
nb_cli_enqueue_change(vty, "./update-interval", NB_OP_MODIFY,
update_str);
nb_cli_enqueue_change(vty, "./holddown-interval", NB_OP_MODIFY,
timeout_str);
nb_cli_enqueue_change(vty, "./flush-interval", NB_OP_MODIFY,
garbage_str);
return nb_cli_apply_changes(vty, "./timers");
}
DEFPY_YANG (no_rip_timers,
no_rip_timers_cmd,
"no timers basic [(5-2147483647) (5-2147483647) (5-2147483647)]",
NO_STR
"Adjust routing timers\n"
"Basic routing protocol update timers\n"
"Routing table update timer value in second. Default is 30.\n"
"Routing information timeout timer. Default is 180.\n"
"Garbage collection timer. Default is 120.\n")
{
nb_cli_enqueue_change(vty, "./update-interval", NB_OP_MODIFY, NULL);
nb_cli_enqueue_change(vty, "./holddown-interval", NB_OP_MODIFY, NULL);
nb_cli_enqueue_change(vty, "./flush-interval", NB_OP_MODIFY, NULL);
return nb_cli_apply_changes(vty, "./timers");
}
void cli_show_rip_timers(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " timers basic %s %s %s\n",
yang_dnode_get_string(dnode, "./update-interval"),
yang_dnode_get_string(dnode, "./holddown-interval"),
yang_dnode_get_string(dnode, "./flush-interval"));
}
/*
* XPath: /frr-ripd:ripd/instance/version
*/
DEFPY_YANG (rip_version,
rip_version_cmd,
"version (1-2)",
"Set routing protocol version\n"
"version\n")
{
nb_cli_enqueue_change(vty, "./version/receive", NB_OP_MODIFY,
version_str);
nb_cli_enqueue_change(vty, "./version/send", NB_OP_MODIFY, version_str);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG (no_rip_version,
no_rip_version_cmd,
"no version [(1-2)]",
NO_STR
"Set routing protocol version\n"
"version\n")
{
nb_cli_enqueue_change(vty, "./version/receive", NB_OP_MODIFY, NULL);
nb_cli_enqueue_change(vty, "./version/send", NB_OP_MODIFY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
void cli_show_rip_version(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
/*
* We have only one "version" command and three possible combinations of
* send/receive values.
*/
switch (yang_dnode_get_enum(dnode, "./receive")) {
case RI_RIP_VERSION_1:
vty_out(vty, " version 1\n");
break;
case RI_RIP_VERSION_2:
vty_out(vty, " version 2\n");
break;
case RI_RIP_VERSION_1_AND_2:
vty_out(vty, " no version\n");
break;
}
}
/*
* XPath: /frr-ripd:ripd/instance/default-bfd-profile
*/
DEFPY_YANG(rip_bfd_default_profile, rip_bfd_default_profile_cmd,
"bfd default-profile BFDPROF$profile",
"Bidirectional Forwarding Detection\n"
"BFD default profile\n"
"Profile name\n")
{
nb_cli_enqueue_change(vty, "./default-bfd-profile", NB_OP_MODIFY,
profile);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(no_rip_bfd_default_profile, no_rip_bfd_default_profile_cmd,
"no bfd default-profile [BFDPROF]",
NO_STR
"Bidirectional Forwarding Detection\n"
"BFD default profile\n"
"Profile name\n")
{
nb_cli_enqueue_change(vty, "./default-bfd-profile", NB_OP_DESTROY,
NULL);
return nb_cli_apply_changes(vty, NULL);
}
void cli_show_ripd_instance_default_bfd_profile(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " bfd default-profile %s\n",
yang_dnode_get_string(dnode, NULL));
}
/*
* XPath: /frr-interface:lib/interface/frr-ripd:rip/split-horizon
*/
DEFPY_YANG (ip_rip_split_horizon,
ip_rip_split_horizon_cmd,
"[no] ip rip split-horizon [poisoned-reverse$poisoned_reverse]",
NO_STR
IP_STR
"Routing Information Protocol\n"
"Perform split horizon\n"
"With poisoned-reverse\n")
{
const char *value;
if (no)
value = "disabled";
else if (poisoned_reverse)
value = "poison-reverse";
else
value = "simple";
nb_cli_enqueue_change(vty, "./split-horizon", NB_OP_MODIFY, value);
return nb_cli_apply_changes(vty, "./frr-ripd:rip");
}
void cli_show_ip_rip_split_horizon(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults)
{
int value;
value = yang_dnode_get_enum(dnode, NULL);
switch (value) {
case RIP_NO_SPLIT_HORIZON:
vty_out(vty, " no ip rip split-horizon\n");
break;
case RIP_SPLIT_HORIZON:
vty_out(vty, " ip rip split-horizon\n");
break;
case RIP_SPLIT_HORIZON_POISONED_REVERSE:
vty_out(vty, " ip rip split-horizon poisoned-reverse\n");
break;
}
}
/*
* XPath: /frr-interface:lib/interface/frr-ripd:rip/v2-broadcast
*/
DEFPY_YANG (ip_rip_v2_broadcast,
ip_rip_v2_broadcast_cmd,
"[no] ip rip v2-broadcast",
NO_STR
IP_STR
"Routing Information Protocol\n"
"Send ip broadcast v2 update\n")
{
nb_cli_enqueue_change(vty, "./v2-broadcast", NB_OP_MODIFY,
no ? "false" : "true");
return nb_cli_apply_changes(vty, "./frr-ripd:rip");
}
void cli_show_ip_rip_v2_broadcast(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 rip v2-broadcast\n");
}
/*
* XPath: /frr-interface:lib/interface/frr-ripd:rip/version-receive
*/
DEFPY_YANG (ip_rip_receive_version,
ip_rip_receive_version_cmd,
"ip rip receive version <{1$v1|2$v2}|none>",
IP_STR
"Routing Information Protocol\n"
"Advertisement reception\n"
"Version control\n"
"RIP version 1\n"
"RIP version 2\n"
"None\n")
{
const char *value;
if (v1 && v2)
value = "both";
else if (v1)
value = "1";
else if (v2)
value = "2";
else
value = "none";
nb_cli_enqueue_change(vty, "./version-receive", NB_OP_MODIFY, value);
return nb_cli_apply_changes(vty, "./frr-ripd:rip");
}
DEFPY_YANG (no_ip_rip_receive_version,
no_ip_rip_receive_version_cmd,
"no ip rip receive version [<{1|2}|none>]",
NO_STR
IP_STR
"Routing Information Protocol\n"
"Advertisement reception\n"
"Version control\n"
"RIP version 1\n"
"RIP version 2\n"
"None\n")
{
nb_cli_enqueue_change(vty, "./version-receive", NB_OP_MODIFY, NULL);
return nb_cli_apply_changes(vty, "./frr-ripd:rip");
}
void cli_show_ip_rip_receive_version(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults)
{
switch (yang_dnode_get_enum(dnode, NULL)) {
case RI_RIP_UNSPEC:
vty_out(vty, " no ip rip receive version\n");
break;
case RI_RIP_VERSION_1:
vty_out(vty, " ip rip receive version 1\n");
break;
case RI_RIP_VERSION_2:
vty_out(vty, " ip rip receive version 2\n");
break;
case RI_RIP_VERSION_1_AND_2:
vty_out(vty, " ip rip receive version 1 2\n");
break;
case RI_RIP_VERSION_NONE:
vty_out(vty, " ip rip receive version none\n");
break;
}
}
/*
* XPath: /frr-interface:lib/interface/frr-ripd:rip/version-send
*/
DEFPY_YANG (ip_rip_send_version,
ip_rip_send_version_cmd,
"ip rip send version <{1$v1|2$v2}|none>",
IP_STR
"Routing Information Protocol\n"
"Advertisement transmission\n"
"Version control\n"
"RIP version 1\n"
"RIP version 2\n"
"None\n")
{
const char *value;
if (v1 && v2)
value = "both";
else if (v1)
value = "1";
else if (v2)
value = "2";
else
value = "none";
nb_cli_enqueue_change(vty, "./version-send", NB_OP_MODIFY, value);
return nb_cli_apply_changes(vty, "./frr-ripd:rip");
}
DEFPY_YANG (no_ip_rip_send_version,
no_ip_rip_send_version_cmd,
"no ip rip send version [<{1|2}|none>]",
NO_STR
IP_STR
"Routing Information Protocol\n"
"Advertisement transmission\n"
"Version control\n"
"RIP version 1\n"
"RIP version 2\n"
"None\n")
{
nb_cli_enqueue_change(vty, "./version-send", NB_OP_MODIFY, NULL);
return nb_cli_apply_changes(vty, "./frr-ripd:rip");
}
void cli_show_ip_rip_send_version(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
switch (yang_dnode_get_enum(dnode, NULL)) {
case RI_RIP_UNSPEC:
vty_out(vty, " no ip rip send version\n");
break;
case RI_RIP_VERSION_1:
vty_out(vty, " ip rip send version 1\n");
break;
case RI_RIP_VERSION_2:
vty_out(vty, " ip rip send version 2\n");
break;
case RI_RIP_VERSION_1_AND_2:
vty_out(vty, " ip rip send version 1 2\n");
break;
case RI_RIP_VERSION_NONE:
vty_out(vty, " ip rip send version none\n");
break;
}
}
/*
* XPath: /frr-interface:lib/interface/frr-ripd:rip/authentication-scheme
*/
DEFPY_YANG (ip_rip_authentication_mode,
ip_rip_authentication_mode_cmd,
"ip rip authentication mode <md5$mode [auth-length <rfc|old-ripd>$auth_length]|text$mode>",
IP_STR
"Routing Information Protocol\n"
"Authentication control\n"
"Authentication mode\n"
"Keyed message digest\n"
"MD5 authentication data length\n"
"RFC compatible\n"
"Old ripd compatible\n"
"Clear text authentication\n")
{
const char *value = NULL;
if (auth_length) {
if (strmatch(auth_length, "rfc"))
value = "16";
else
value = "20";
}
nb_cli_enqueue_change(vty, "./authentication-scheme/mode", NB_OP_MODIFY,
strmatch(mode, "md5") ? "md5" : "plain-text");
if (strmatch(mode, "md5"))
nb_cli_enqueue_change(vty,
"./authentication-scheme/md5-auth-length",
NB_OP_MODIFY, value);
return nb_cli_apply_changes(vty, "./frr-ripd:rip");
}
DEFPY_YANG (no_ip_rip_authentication_mode,
no_ip_rip_authentication_mode_cmd,
"no ip rip authentication mode [<md5 [auth-length <rfc|old-ripd>]|text>]",
NO_STR
IP_STR
"Routing Information Protocol\n"
"Authentication control\n"
"Authentication mode\n"
"Keyed message digest\n"
"MD5 authentication data length\n"
"RFC compatible\n"
"Old ripd compatible\n"
"Clear text authentication\n")
{
nb_cli_enqueue_change(vty, "./authentication-scheme/mode", NB_OP_MODIFY,
NULL);
nb_cli_enqueue_change(vty, "./authentication-scheme/md5-auth-length",
NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, "./frr-ripd:rip");
}
void cli_show_ip_rip_authentication_scheme(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults)
{
switch (yang_dnode_get_enum(dnode, "./mode")) {
case RIP_NO_AUTH:
vty_out(vty, " no ip rip authentication mode\n");
break;
case RIP_AUTH_SIMPLE_PASSWORD:
vty_out(vty, " ip rip authentication mode text\n");
break;
case RIP_AUTH_MD5:
vty_out(vty, " ip rip authentication mode md5");
if (show_defaults
|| !yang_dnode_is_default(dnode, "./md5-auth-length")) {
if (yang_dnode_get_enum(dnode, "./md5-auth-length")
== RIP_AUTH_MD5_SIZE)
vty_out(vty, " auth-length rfc");
else
vty_out(vty, " auth-length old-ripd");
}
vty_out(vty, "\n");
break;
}
}
/*
* XPath: /frr-interface:lib/interface/frr-ripd:rip/authentication-password
*/
DEFPY_YANG (ip_rip_authentication_string,
ip_rip_authentication_string_cmd,
"ip rip authentication string LINE$password",
IP_STR
"Routing Information Protocol\n"
"Authentication control\n"
"Authentication string\n"
"Authentication string\n")
{
if (strlen(password) > 16) {
vty_out(vty,
"%% RIPv2 authentication string must be shorter than 16\n");
return CMD_WARNING_CONFIG_FAILED;
}
if (yang_dnode_existsf(vty->candidate_config->dnode, "%s%s",
VTY_CURR_XPATH,
"/frr-ripd:rip/authentication-key-chain")) {
vty_out(vty, "%% key-chain configuration exists\n");
return CMD_WARNING_CONFIG_FAILED;
}
nb_cli_enqueue_change(vty, "./authentication-password", NB_OP_MODIFY,
password);
return nb_cli_apply_changes(vty, "./frr-ripd:rip");
}
DEFPY_YANG (no_ip_rip_authentication_string,
no_ip_rip_authentication_string_cmd,
"no ip rip authentication string [LINE]",
NO_STR
IP_STR
"Routing Information Protocol\n"
"Authentication control\n"
"Authentication string\n"
"Authentication string\n")
{
nb_cli_enqueue_change(vty, "./authentication-password", NB_OP_DESTROY,
NULL);
return nb_cli_apply_changes(vty, "./frr-ripd:rip");
}
void cli_show_ip_rip_authentication_string(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " ip rip authentication string %s\n",
yang_dnode_get_string(dnode, NULL));
}
/*
* XPath: /frr-interface:lib/interface/frr-ripd:rip/authentication-key-chain
*/
DEFPY_YANG (ip_rip_authentication_key_chain,
ip_rip_authentication_key_chain_cmd,
"ip rip authentication key-chain LINE$keychain",
IP_STR
"Routing Information Protocol\n"
"Authentication control\n"
"Authentication key-chain\n"
"name of key-chain\n")
{
if (yang_dnode_existsf(vty->candidate_config->dnode, "%s%s",
VTY_CURR_XPATH,
"/frr-ripd:rip/authentication-password")) {
vty_out(vty, "%% authentication string configuration exists\n");
return CMD_WARNING_CONFIG_FAILED;
}
nb_cli_enqueue_change(vty, "./authentication-key-chain", NB_OP_MODIFY,
keychain);
return nb_cli_apply_changes(vty, "./frr-ripd:rip");
}
DEFPY_YANG (no_ip_rip_authentication_key_chain,
no_ip_rip_authentication_key_chain_cmd,
"no ip rip authentication key-chain [LINE]",
NO_STR
IP_STR
"Routing Information Protocol\n"
"Authentication control\n"
"Authentication key-chain\n"
"name of key-chain\n")
{
nb_cli_enqueue_change(vty, "./authentication-key-chain", NB_OP_DESTROY,
NULL);
return nb_cli_apply_changes(vty, "./frr-ripd:rip");
}
void cli_show_ip_rip_authentication_key_chain(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " ip rip authentication key-chain %s\n",
yang_dnode_get_string(dnode, NULL));
}
/*
* XPath: /frr-interface:lib/interface/frr-ripd:rip/bfd-monitoring/enable
*/
DEFPY_YANG(ip_rip_bfd, ip_rip_bfd_cmd, "[no] ip rip bfd",
NO_STR IP_STR
"Routing Information Protocol\n"
"Enable BFD support\n")
{
nb_cli_enqueue_change(vty, "./bfd-monitoring/enable", NB_OP_MODIFY,
no ? "false" : "true");
return nb_cli_apply_changes(vty, "./frr-ripd:rip");
}
void cli_show_ip_rip_bfd_enable(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " ip rip bfd\n");
}
/*
* XPath: /frr-interface:lib/interface/frr-ripd:rip/bfd/profile
*/
DEFPY_YANG(ip_rip_bfd_profile, ip_rip_bfd_profile_cmd,
"[no] ip rip bfd profile BFDPROF$profile",
NO_STR IP_STR
"Routing Information Protocol\n"
"Enable BFD support\n"
"Use a pre-configured profile\n"
"Profile name\n")
{
if (no)
nb_cli_enqueue_change(vty, "./bfd-monitoring/profile",
NB_OP_DESTROY, NULL);
else
nb_cli_enqueue_change(vty, "./bfd-monitoring/profile",
NB_OP_MODIFY, profile);
return nb_cli_apply_changes(vty, "./frr-ripd:rip");
}
DEFPY_YANG(no_ip_rip_bfd_profile, no_ip_rip_bfd_profile_cmd,
"no ip rip bfd profile",
NO_STR IP_STR
"Routing Information Protocol\n"
"Enable BFD support\n"
"Use a pre-configured profile\n")
{
nb_cli_enqueue_change(vty, "./bfd-monitoring/profile", NB_OP_DESTROY,
NULL);
return nb_cli_apply_changes(vty, "./frr-ripd:rip");
}
void cli_show_ip_rip_bfd_profile(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " ip rip bfd profile %s\n",
yang_dnode_get_string(dnode, NULL));
}
/*
* XPath: /frr-ripd:clear-rip-route
*/
DEFPY_YANG (clear_ip_rip,
clear_ip_rip_cmd,
"clear ip rip [vrf WORD]",
CLEAR_STR
IP_STR
"Clear IP RIP database\n"
VRF_CMD_HELP_STR)
{
struct list *input;
int ret;
input = list_new();
if (vrf) {
struct yang_data *yang_vrf;
yang_vrf = yang_data_new("/frr-ripd:clear-rip-route/input/vrf",
vrf);
listnode_add(input, yang_vrf);
}
ret = nb_cli_rpc(vty, "/frr-ripd:clear-rip-route", input, NULL);
list_delete(&input);
return ret;
}
DEFUN (rip_distribute_list,
rip_distribute_list_cmd,
"distribute-list [prefix] ACCESSLIST4_NAME <in|out> [WORD]",
"Filter networks in routing updates\n"
"Specify a prefix\n"
"Access-list name\n"
"Filter incoming routing updates\n"
"Filter outgoing routing updates\n"
"Interface name\n")
{
const char *ifname = NULL;
int prefix = (argv[1]->type == WORD_TKN) ? 1 : 0;
if (argv[argc - 1]->type == VARIABLE_TKN)
ifname = argv[argc - 1]->arg;
return distribute_list_parser(prefix, true, argv[2 + prefix]->text,
argv[1 + prefix]->arg, ifname);
}
DEFUN (rip_no_distribute_list,
rip_no_distribute_list_cmd,
"no distribute-list [prefix] ACCESSLIST4_NAME <in|out> [WORD]",
NO_STR
"Filter networks in routing updates\n"
"Specify a prefix\n"
"Access-list name\n"
"Filter incoming routing updates\n"
"Filter outgoing routing updates\n"
"Interface name\n")
{
const char *ifname = NULL;
int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0;
if (argv[argc - 1]->type == VARIABLE_TKN)
ifname = argv[argc - 1]->arg;
return distribute_list_no_parser(vty, prefix, true,
argv[3 + prefix]->text,
argv[2 + prefix]->arg, ifname);
}
void rip_cli_init(void)
{
install_element(CONFIG_NODE, &router_rip_cmd);
install_element(CONFIG_NODE, &no_router_rip_cmd);
install_element(RIP_NODE, &rip_distribute_list_cmd);
install_element(RIP_NODE, &rip_no_distribute_list_cmd);
install_element(RIP_NODE, &rip_allow_ecmp_cmd);
install_element(RIP_NODE, &no_rip_allow_ecmp_cmd);
install_element(RIP_NODE, &rip_default_information_originate_cmd);
install_element(RIP_NODE, &rip_default_metric_cmd);
install_element(RIP_NODE, &no_rip_default_metric_cmd);
install_element(RIP_NODE, &rip_distance_cmd);
install_element(RIP_NODE, &no_rip_distance_cmd);
install_element(RIP_NODE, &rip_distance_source_cmd);
install_element(RIP_NODE, &rip_neighbor_cmd);
install_element(RIP_NODE, &rip_network_prefix_cmd);
install_element(RIP_NODE, &rip_network_if_cmd);
install_element(RIP_NODE, &rip_offset_list_cmd);
ripd: retrofit the 'passive-interface' command to the new northbound model In ripd, the "passive-interface default" command has the following behavior: * All interfaces are converted to the passive mode; * The "passive-interface IFNAME" command becomes a no-operation and "passive-interface IFNAME" statements are removed from the running configuration. * The "no passive-interface IFNAME" can be used to remove interfaces from the passive mode. This command was modeled using the following YANG data nodes in the frr-ripd module: leaf passive-default { type boolean; default "false"; description "Control whether interfaces are in the passive mode by default or not."; } leaf-list passive-interface { when "../passive-default = 'false'"; type string { length "1..16"; } description "A list of interfaces where the sending of RIP packets is disabled."; } leaf-list non-passive-interface { when "../passive-default = 'true'"; type string { length "1..16"; } description "A list of interfaces where the sending of RIP packets is enabled."; } The 'when' statements guarantee that the list of passive interfaces is cleared when the "passive-interface default" command is entered (likewise, they guarantee that the list of non-passive interfaces is cleared when the "passive-interface default" command is removed). This matches exactly the behavior we want to model. Finally, move the 'passive_default' global variable into the 'rip' structure where it belongs. This fixed the bug where the "passive-interface default" command was being retained after a "no router rip" + "router rip". Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
2018-05-09 06:35:00 +02:00
install_element(RIP_NODE, &rip_passive_default_cmd);
install_element(RIP_NODE, &rip_passive_interface_cmd);
install_element(RIP_NODE, &rip_redistribute_cmd);
install_element(RIP_NODE, &rip_route_cmd);
install_element(RIP_NODE, &rip_timers_cmd);
install_element(RIP_NODE, &no_rip_timers_cmd);
install_element(RIP_NODE, &rip_version_cmd);
install_element(RIP_NODE, &no_rip_version_cmd);
install_element(RIP_NODE, &rip_bfd_default_profile_cmd);
install_element(RIP_NODE, &no_rip_bfd_default_profile_cmd);
install_element(INTERFACE_NODE, &ip_rip_split_horizon_cmd);
install_element(INTERFACE_NODE, &ip_rip_v2_broadcast_cmd);
install_element(INTERFACE_NODE, &ip_rip_receive_version_cmd);
install_element(INTERFACE_NODE, &no_ip_rip_receive_version_cmd);
install_element(INTERFACE_NODE, &ip_rip_send_version_cmd);
install_element(INTERFACE_NODE, &no_ip_rip_send_version_cmd);
install_element(INTERFACE_NODE, &ip_rip_authentication_mode_cmd);
install_element(INTERFACE_NODE, &no_ip_rip_authentication_mode_cmd);
install_element(INTERFACE_NODE, &ip_rip_authentication_string_cmd);
install_element(INTERFACE_NODE, &no_ip_rip_authentication_string_cmd);
install_element(INTERFACE_NODE, &ip_rip_authentication_key_chain_cmd);
install_element(INTERFACE_NODE,
&no_ip_rip_authentication_key_chain_cmd);
install_element(INTERFACE_NODE, &ip_rip_bfd_cmd);
install_element(INTERFACE_NODE, &ip_rip_bfd_profile_cmd);
install_element(INTERFACE_NODE, &no_ip_rip_bfd_profile_cmd);
install_element(ENABLE_NODE, &clear_ip_rip_cmd);
}