frr/ripd/rip_cli.c

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

1423 lines
39 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 "if_rmap.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");
}
void cli_show_end_router_rip(struct vty *vty, const struct lyd_node *dnode)
{
vty_out(vty, "exit\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")
{
ripd: Use argv_find to avoid buffer overflow when parsing allow-ecmp args ==13211==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6020000af158 at pc 0x55d48c5f1e38 bp 0x7fffd8a713d0 sp 0x7fffd8a713c0 READ of size 8 at 0x6020000af158 thread T0 #0 0x55d48c5f1e37 in rip_allow_ecmp ripd/rip_cli.c:98 #1 0x7f2ec125aa0f in cmd_execute_command_real lib/command.c:990 #2 0x7f2ec125ae90 in cmd_execute_command lib/command.c:1049 #3 0x7f2ec125b406 in cmd_execute lib/command.c:1217 #4 0x7f2ec137ca36 in vty_command lib/vty.c:551 #5 0x7f2ec137ce52 in vty_execute lib/vty.c:1314 #6 0x7f2ec1384f9e in vtysh_read lib/vty.c:2223 #7 0x7f2ec137041b in event_call lib/event.c:1995 #8 0x7f2ec12b54bf in frr_run lib/libfrr.c:1204 #9 0x55d48c5f0f32 in main ripd/rip_main.c:171 #10 0x7f2ec0ad9c86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86) #11 0x55d48c5f1349 in _start (/usr/lib/frr/ripd+0x3b349) 0x6020000af158 is located 0 bytes to the right of 8-byte region [0x6020000af150,0x6020000af158) allocated by thread T0 here: #0 0x7f2ec18ccb40 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb40) #1 0x7f2ec12d2e41 in qmalloc lib/memory.c:100 #2 0x7f2ec125a815 in cmd_execute_command_real lib/command.c:955 #3 0x7f2ec125ae90 in cmd_execute_command lib/command.c:1049 #4 0x7f2ec125b406 in cmd_execute lib/command.c:1217 #5 0x7f2ec137ca36 in vty_command lib/vty.c:551 #6 0x7f2ec137ce52 in vty_execute lib/vty.c:1314 #7 0x7f2ec1384f9e in vtysh_read lib/vty.c:2223 #8 0x7f2ec137041b in event_call lib/event.c:1995 #9 0x7f2ec12b54bf in frr_run lib/libfrr.c:1204 #10 0x55d48c5f0f32 in main ripd/rip_main.c:171 #11 0x7f2ec0ad9c86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86) SUMMARY: AddressSanitizer: heap-buffer-overflow ripd/rip_cli.c:98 in rip_allow_ecmp Shadow bytes around the buggy address: 0x0c048000ddd0: fa fa fd fa fa fa fd fa fa fa fd fd fa fa fd fa 0x0c048000dde0: fa fa fd fa fa fa fd fd fa fa fd fa fa fa fd fd 0x0c048000ddf0: fa fa fd fa fa fa fd fd fa fa fd fd fa fa fd fd 0x0c048000de00: fa fa fd fa fa fa fd fd fa fa 00 03 fa fa fd fa 0x0c048000de10: fa fa fd fa fa fa 00 00 fa fa fd fa fa fa 00 03 =>0x0c048000de20: fa fa 00 03 fa fa fd fa fa fa 00[fa]fa fa fa fa 0x0c048000de30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c048000de40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c048000de50: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c048000de60: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c048000de70: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==13211==ABORTING Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
2023-05-23 08:20:27 +02:00
int idx_number = 0;
char mpaths[3] = {};
uint32_t paths = MULTIPATH_NUM;
ripd: Use argv_find to avoid buffer overflow when parsing allow-ecmp args ==13211==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6020000af158 at pc 0x55d48c5f1e38 bp 0x7fffd8a713d0 sp 0x7fffd8a713c0 READ of size 8 at 0x6020000af158 thread T0 #0 0x55d48c5f1e37 in rip_allow_ecmp ripd/rip_cli.c:98 #1 0x7f2ec125aa0f in cmd_execute_command_real lib/command.c:990 #2 0x7f2ec125ae90 in cmd_execute_command lib/command.c:1049 #3 0x7f2ec125b406 in cmd_execute lib/command.c:1217 #4 0x7f2ec137ca36 in vty_command lib/vty.c:551 #5 0x7f2ec137ce52 in vty_execute lib/vty.c:1314 #6 0x7f2ec1384f9e in vtysh_read lib/vty.c:2223 #7 0x7f2ec137041b in event_call lib/event.c:1995 #8 0x7f2ec12b54bf in frr_run lib/libfrr.c:1204 #9 0x55d48c5f0f32 in main ripd/rip_main.c:171 #10 0x7f2ec0ad9c86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86) #11 0x55d48c5f1349 in _start (/usr/lib/frr/ripd+0x3b349) 0x6020000af158 is located 0 bytes to the right of 8-byte region [0x6020000af150,0x6020000af158) allocated by thread T0 here: #0 0x7f2ec18ccb40 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb40) #1 0x7f2ec12d2e41 in qmalloc lib/memory.c:100 #2 0x7f2ec125a815 in cmd_execute_command_real lib/command.c:955 #3 0x7f2ec125ae90 in cmd_execute_command lib/command.c:1049 #4 0x7f2ec125b406 in cmd_execute lib/command.c:1217 #5 0x7f2ec137ca36 in vty_command lib/vty.c:551 #6 0x7f2ec137ce52 in vty_execute lib/vty.c:1314 #7 0x7f2ec1384f9e in vtysh_read lib/vty.c:2223 #8 0x7f2ec137041b in event_call lib/event.c:1995 #9 0x7f2ec12b54bf in frr_run lib/libfrr.c:1204 #10 0x55d48c5f0f32 in main ripd/rip_main.c:171 #11 0x7f2ec0ad9c86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86) SUMMARY: AddressSanitizer: heap-buffer-overflow ripd/rip_cli.c:98 in rip_allow_ecmp Shadow bytes around the buggy address: 0x0c048000ddd0: fa fa fd fa fa fa fd fa fa fa fd fd fa fa fd fa 0x0c048000dde0: fa fa fd fa fa fa fd fd fa fa fd fa fa fa fd fd 0x0c048000ddf0: fa fa fd fa fa fa fd fd fa fa fd fd fa fa fd fd 0x0c048000de00: fa fa fd fa fa fa fd fd fa fa 00 03 fa fa fd fa 0x0c048000de10: fa fa fd fa fa fa 00 00 fa fa fd fa fa fa 00 03 =>0x0c048000de20: fa fa 00 03 fa fa fd fa fa fa 00[fa]fa fa fa fa 0x0c048000de30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c048000de40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c048000de50: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c048000de60: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c048000de70: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==13211==ABORTING Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
2023-05-23 08:20:27 +02:00
if (argv_find(argv, argc, CMD_RANGE_STR(1, MULTIPATH_NUM), &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")
{
char xpath[XPATH_MAXLEN];
snprintf(xpath, sizeof(xpath), "./explicit-neighbor[.='%s']",
neighbor_str);
nb_cli_enqueue_change(vty, xpath, no ? NB_OP_DESTROY : NB_OP_CREATE,
NULL);
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")
{
char xpath[XPATH_MAXLEN];
snprintf(xpath, sizeof(xpath), "./network[.='%s']", network_str);
nb_cli_enqueue_change(vty, xpath, no ? NB_OP_DESTROY : NB_OP_CREATE,
NULL);
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")
{
char xpath[XPATH_MAXLEN];
snprintf(xpath, sizeof(xpath), "./interface[.='%s']", network);
nb_cli_enqueue_change(vty, xpath, no ? NB_OP_DESTROY : NB_OP_CREATE,
NULL);
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");
char xpath[XPATH_MAXLEN];
enum nb_operation op;
if (passive_default) {
snprintf(xpath, sizeof(xpath),
"./non-passive-interface[.='%s']", ifname);
op = no ? NB_OP_CREATE : NB_OP_DESTROY;
} else {
snprintf(xpath, sizeof(xpath), "./passive-interface[.='%s']",
ifname);
op = no ? NB_OP_DESTROY : NB_OP_CREATE;
}
nb_cli_enqueue_change(vty, xpath, op, NULL);
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")
{
char xpath[XPATH_MAXLEN];
snprintf(xpath, sizeof(xpath), "./static-route[.='%s']", route_str);
nb_cli_enqueue_change(vty, xpath, no ? NB_OP_DESTROY : NB_OP_CREATE,
NULL);
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));
}
DEFPY_YANG(
rip_distribute_list, rip_distribute_list_cmd,
"distribute-list ACCESSLIST4_NAME$name <in|out>$dir [WORD$ifname]",
"Filter networks in routing updates\n"
"Access-list name\n"
"Filter incoming routing updates\n"
"Filter outgoing routing updates\n"
"Interface name\n")
{
char xpath[XPATH_MAXLEN];
snprintf(xpath, sizeof(xpath),
"./distribute-list[interface='%s']/%s/access-list",
ifname ? ifname : "", dir);
/* nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); */
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, name);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
rip_distribute_list_prefix, rip_distribute_list_prefix_cmd,
"distribute-list prefix PREFIXLIST4_NAME$name <in|out>$dir [WORD$ifname]",
"Filter networks in routing updates\n"
"Specify a prefix list\n"
"Prefix-list name\n"
"Filter incoming routing updates\n"
"Filter outgoing routing updates\n"
"Interface name\n")
{
char xpath[XPATH_MAXLEN];
snprintf(xpath, sizeof(xpath),
"./distribute-list[interface='%s']/%s/prefix-list",
ifname ? ifname : "", dir);
/* nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); */
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, name);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(no_rip_distribute_list,
no_rip_distribute_list_cmd,
"no distribute-list [ACCESSLIST4_NAME$name] <in|out>$dir [WORD$ifname]",
NO_STR
"Filter networks in routing updates\n"
"Access-list name\n"
"Filter incoming routing updates\n"
"Filter outgoing routing updates\n"
"Interface name\n")
{
const struct lyd_node *value_node;
char xpath[XPATH_MAXLEN];
snprintf(xpath, sizeof(xpath),
"./distribute-list[interface='%s']/%s/access-list",
ifname ? ifname : "", dir);
/*
* See if the user has specified specific list so check it exists.
*
* NOTE: Other FRR CLI commands do not do this sort of verification and
* there may be an official decision not to.
*/
if (name) {
value_node = yang_dnode_getf(vty->candidate_config->dnode, "%s/%s",
VTY_CURR_XPATH, xpath);
if (!value_node || strcmp(name, lyd_get_value(value_node))) {
vty_out(vty, "distribute list doesn't exist\n");
return CMD_WARNING_CONFIG_FAILED;
}
}
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(no_rip_distribute_list_prefix,
no_rip_distribute_list_prefix_cmd,
"no distribute-list prefix [PREFIXLIST4_NAME$name] <in|out>$dir [WORD$ifname]",
NO_STR
"Filter networks in routing updates\n"
"Specify a prefix list\n"
"Prefix-list name\n"
"Filter incoming routing updates\n"
"Filter outgoing routing updates\n"
"Interface name\n")
{
const struct lyd_node *value_node;
char xpath[XPATH_MAXLEN];
snprintf(xpath, sizeof(xpath),
"./distribute-list[interface='%s']/%s/prefix-list",
ifname ? ifname : "", dir);
/*
* See if the user has specified specific list so check it exists.
*
* NOTE: Other FRR CLI commands do not do this sort of verification and
* there may be an official decision not to.
*/
if (name) {
value_node = yang_dnode_getf(vty->candidate_config->dnode, "%s/%s",
VTY_CURR_XPATH, xpath);
if (!value_node || strcmp(name, lyd_get_value(value_node))) {
vty_out(vty, "distribute list doesn't exist\n");
return CMD_WARNING_CONFIG_FAILED;
}
}
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
/* RIP node structure. */
static struct cmd_node rip_node = {
.name = "rip",
.node = RIP_NODE,
.parent_node = CONFIG_NODE,
.prompt = "%s(config-router)# ",
// .config_write = config_write_rip,
};
void rip_cli_init(void)
{
install_node(&rip_node);
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_distribute_list_prefix_cmd);
install_element(RIP_NODE, &no_rip_distribute_list_cmd);
install_element(RIP_NODE, &no_rip_distribute_list_prefix_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_default(RIP_NODE);
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);
if_rmap_init(RIP_NODE);
}
/* clang-format off */
const struct frr_yang_module_info frr_ripd_cli_info = {
.name = "frr-ripd",
.ignore_cfg_cbs = true,
.nodes = {
{
.xpath = "/frr-ripd:ripd/instance",
.cbs.cli_show = cli_show_router_rip,
.cbs.cli_show_end = cli_show_end_router_rip,
},
{
.xpath = "/frr-ripd:ripd/instance/allow-ecmp",
.cbs.cli_show = cli_show_rip_allow_ecmp,
},
{
.xpath = "/frr-ripd:ripd/instance/default-information-originate",
.cbs.cli_show = cli_show_rip_default_information_originate,
},
{
.xpath = "/frr-ripd:ripd/instance/default-metric",
.cbs.cli_show = cli_show_rip_default_metric,
},
{
.xpath = "/frr-ripd:ripd/instance/distance/default",
.cbs.cli_show = cli_show_rip_distance,
},
{
.xpath = "/frr-ripd:ripd/instance/distance/source",
.cbs.cli_show = cli_show_rip_distance_source,
},
{
.xpath = "/frr-ripd:ripd/instance/explicit-neighbor",
.cbs.cli_show = cli_show_rip_neighbor,
},
{
.xpath = "/frr-ripd:ripd/instance/network",
.cbs.cli_show = cli_show_rip_network_prefix,
},
{
.xpath = "/frr-ripd:ripd/instance/interface",
.cbs.cli_show = cli_show_rip_network_interface,
},
{
.xpath = "/frr-ripd:ripd/instance/offset-list",
.cbs.cli_show = cli_show_rip_offset_list,
},
{
.xpath = "/frr-ripd:ripd/instance/passive-default",
.cbs.cli_show = cli_show_rip_passive_default,
},
{
.xpath = "/frr-ripd:ripd/instance/passive-interface",
.cbs.cli_show = cli_show_rip_passive_interface,
},
{
.xpath = "/frr-ripd:ripd/instance/non-passive-interface",
.cbs.cli_show = cli_show_rip_non_passive_interface,
},
{
.xpath = "/frr-ripd:ripd/instance/redistribute",
.cbs.cli_show = cli_show_rip_redistribute,
},
{
.xpath = "/frr-ripd:ripd/instance/if-route-maps/if-route-map",
.cbs.cli_show = cli_show_if_route_map,
},
{
.xpath = "/frr-ripd:ripd/instance/static-route",
.cbs.cli_show = cli_show_rip_route,
},
{
.xpath = "/frr-ripd:ripd/instance/timers",
.cbs.cli_show = cli_show_rip_timers,
},
{
.xpath = "/frr-ripd:ripd/instance/version",
.cbs.cli_show = cli_show_rip_version,
},
{
.xpath = "/frr-ripd:ripd/instance/default-bfd-profile",
.cbs.cli_show = cli_show_ripd_instance_default_bfd_profile,
},
{
.xpath = "/frr-interface:lib/interface/frr-ripd:rip/split-horizon",
.cbs.cli_show = cli_show_ip_rip_split_horizon,
},
{
.xpath = "/frr-interface:lib/interface/frr-ripd:rip/v2-broadcast",
.cbs.cli_show = cli_show_ip_rip_v2_broadcast,
},
{
.xpath = "/frr-interface:lib/interface/frr-ripd:rip/version-receive",
.cbs.cli_show = cli_show_ip_rip_receive_version,
},
{
.xpath = "/frr-interface:lib/interface/frr-ripd:rip/version-send",
.cbs.cli_show = cli_show_ip_rip_send_version,
},
{
.xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-scheme",
.cbs.cli_show = cli_show_ip_rip_authentication_scheme,
},
{
.xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-password",
.cbs.cli_show = cli_show_ip_rip_authentication_string,
},
{
.xpath = "/frr-interface:lib/interface/frr-ripd:rip/authentication-key-chain",
.cbs.cli_show = cli_show_ip_rip_authentication_key_chain,
},
{
.xpath = "/frr-interface:lib/interface/frr-ripd:rip/bfd-monitoring/enable",
.cbs.cli_show = cli_show_ip_rip_bfd_enable,
},
{
.xpath = "/frr-interface:lib/interface/frr-ripd:rip/bfd-monitoring/profile",
.cbs.cli_show = cli_show_ip_rip_bfd_profile,
},
{
.xpath = NULL,
},
}
};