ripd: retrofit the 'neighbor' command to the new northbound model

Make rip_neighbor_add() and rip_neighbor_delete() return northbound
error codes since their return values are used as the return value of
some northbound callbacks.

These functions shouldn't fail in normal conditions because the northbound
layer guarantees it will never call the 'create' or 'delete' callback
more than once for the same object. Hence any failure in those functions
would indicate an internal inconsistency that needs to be investigated
(by returning NB_ERR the northbound will log a detailed error message
indicating the xpath of the object, the event and the callback where
the error happened).

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This commit is contained in:
Renato Westphal 2018-05-09 01:34:59 -03:00
parent 23b23d8c27
commit f0ab22fb70
5 changed files with 60 additions and 59 deletions

View File

@ -304,6 +304,33 @@ void cli_show_rip_distance_source(struct vty *vty, struct lyd_node *dnode,
vty_out(vty, "\n"); vty_out(vty, "\n");
} }
/*
* XPath: /frr-ripd:ripd/instance/explicit-neighbor
*/
DEFPY (rip_neighbor,
rip_neighbor_cmd,
"[no] neighbor A.B.C.D",
NO_STR
"Specify a neighbor router\n"
"Neighbor address\n")
{
struct cli_config_change changes[] = {
{
.xpath = "./explicit-neighbor",
.operation = no ? NB_OP_DELETE : NB_OP_CREATE,
.value = neighbor_str,
},
};
return nb_cli_cfg_change(vty, NULL, changes, array_size(changes));
}
void cli_show_rip_neighbor(struct vty *vty, struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " neighbor %s\n", yang_dnode_get_string(dnode, NULL));
}
void rip_cli_init(void) void rip_cli_init(void)
{ {
install_element(CONFIG_NODE, &router_rip_cmd); install_element(CONFIG_NODE, &router_rip_cmd);
@ -317,4 +344,5 @@ void rip_cli_init(void)
install_element(RIP_NODE, &no_rip_distance_cmd); install_element(RIP_NODE, &no_rip_distance_cmd);
install_element(RIP_NODE, &rip_distance_source_cmd); install_element(RIP_NODE, &rip_distance_source_cmd);
install_element(RIP_NODE, &no_rip_distance_source_cmd); install_element(RIP_NODE, &no_rip_distance_source_cmd);
install_element(RIP_NODE, &rip_neighbor_cmd);
} }

View File

@ -35,5 +35,7 @@ extern void cli_show_rip_distance(struct vty *vty, struct lyd_node *dnode,
extern void cli_show_rip_distance_source(struct vty *vty, extern void cli_show_rip_distance_source(struct vty *vty,
struct lyd_node *dnode, struct lyd_node *dnode,
bool show_defaults); bool show_defaults);
extern void cli_show_rip_neighbor(struct vty *vty, struct lyd_node *dnode,
bool show_defaults);
#endif /* _FRR_RIP_CLI_H_ */ #endif /* _FRR_RIP_CLI_H_ */

View File

@ -35,6 +35,7 @@
#include "sockopt.h" #include "sockopt.h"
#include "privs.h" #include "privs.h"
#include "lib_errors.h" #include "lib_errors.h"
#include "northbound_cli.h"
#include "zebra/connected.h" #include "zebra/connected.h"
@ -1011,29 +1012,29 @@ int rip_neighbor_lookup(struct sockaddr_in *from)
} }
/* Add new RIP neighbor to the neighbor tree. */ /* Add new RIP neighbor to the neighbor tree. */
static int rip_neighbor_add(struct prefix_ipv4 *p) int rip_neighbor_add(struct prefix_ipv4 *p)
{ {
struct route_node *node; struct route_node *node;
node = route_node_get(rip->neighbor, (struct prefix *)p); node = route_node_get(rip->neighbor, (struct prefix *)p);
if (node->info) if (node->info)
return -1; return NB_ERR_INCONSISTENCY;
node->info = rip->neighbor; node->info = rip->neighbor;
return 0; return NB_OK;
} }
/* Delete RIP neighbor from the neighbor tree. */ /* Delete RIP neighbor from the neighbor tree. */
static int rip_neighbor_delete(struct prefix_ipv4 *p) int rip_neighbor_delete(struct prefix_ipv4 *p)
{ {
struct route_node *node; struct route_node *node;
/* Lock for look up. */ /* Lock for look up. */
node = route_node_lookup(rip->neighbor, (struct prefix *)p); node = route_node_lookup(rip->neighbor, (struct prefix *)p);
if (!node) if (!node)
return -1; return NB_ERR_INCONSISTENCY;
node->info = NULL; node->info = NULL;
@ -1043,7 +1044,7 @@ static int rip_neighbor_delete(struct prefix_ipv4 *p)
/* Unlock real neighbor information lock. */ /* Unlock real neighbor information lock. */
route_unlock_node(node); route_unlock_node(node);
return 0; return NB_OK;
} }
/* Clear all network and neighbor configuration. */ /* Clear all network and neighbor configuration. */
@ -1208,53 +1209,6 @@ DEFUN (no_rip_network,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
/* RIP neighbor configuration set. */
DEFUN (rip_neighbor,
rip_neighbor_cmd,
"neighbor A.B.C.D",
"Specify a neighbor router\n"
"Neighbor address\n")
{
int idx_ipv4 = 1;
int ret;
struct prefix_ipv4 p;
ret = str2prefix_ipv4(argv[idx_ipv4]->arg, &p);
if (ret <= 0) {
vty_out(vty, "Please specify address by A.B.C.D\n");
return CMD_WARNING_CONFIG_FAILED;
}
rip_neighbor_add(&p);
return CMD_SUCCESS;
}
/* RIP neighbor configuration unset. */
DEFUN (no_rip_neighbor,
no_rip_neighbor_cmd,
"no neighbor A.B.C.D",
NO_STR
"Specify a neighbor router\n"
"Neighbor address\n")
{
int idx_ipv4 = 2;
int ret;
struct prefix_ipv4 p;
ret = str2prefix_ipv4(argv[idx_ipv4]->arg, &p);
if (ret <= 0) {
vty_out(vty, "Please specify address by A.B.C.D\n");
return CMD_WARNING_CONFIG_FAILED;
}
rip_neighbor_delete(&p);
return CMD_SUCCESS;
}
DEFUN (ip_rip_receive_version, DEFUN (ip_rip_receive_version,
ip_rip_receive_version_cmd, ip_rip_receive_version_cmd,
"ip rip receive version <(1-2)|none>", "ip rip receive version <(1-2)|none>",
@ -1896,8 +1850,6 @@ void rip_if_init(void)
/* Install commands. */ /* Install commands. */
install_element(RIP_NODE, &rip_network_cmd); install_element(RIP_NODE, &rip_network_cmd);
install_element(RIP_NODE, &no_rip_network_cmd); install_element(RIP_NODE, &no_rip_network_cmd);
install_element(RIP_NODE, &rip_neighbor_cmd);
install_element(RIP_NODE, &no_rip_neighbor_cmd);
install_element(RIP_NODE, &rip_passive_interface_cmd); install_element(RIP_NODE, &rip_passive_interface_cmd);
install_element(RIP_NODE, &no_rip_passive_interface_cmd); install_element(RIP_NODE, &no_rip_passive_interface_cmd);

View File

@ -276,15 +276,31 @@ static int ripd_instance_explicit_neighbor_create(enum nb_event event,
const struct lyd_node *dnode, const struct lyd_node *dnode,
union nb_resource *resource) union nb_resource *resource)
{ {
/* TODO: implement me. */ struct prefix_ipv4 p;
if (event != NB_EV_APPLY)
return NB_OK; return NB_OK;
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
yang_dnode_get_ipv4(&p.prefix, dnode, NULL);
return rip_neighbor_add(&p);
} }
static int ripd_instance_explicit_neighbor_delete(enum nb_event event, static int ripd_instance_explicit_neighbor_delete(enum nb_event event,
const struct lyd_node *dnode) const struct lyd_node *dnode)
{ {
/* TODO: implement me. */ struct prefix_ipv4 p;
if (event != NB_EV_APPLY)
return NB_OK; return NB_OK;
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
yang_dnode_get_ipv4(&p.prefix, dnode, NULL);
return rip_neighbor_delete(&p);
} }
/* /*
@ -858,6 +874,7 @@ const struct frr_yang_module_info frr_ripd_info = {
.xpath = "/frr-ripd:ripd/instance/explicit-neighbor", .xpath = "/frr-ripd:ripd/instance/explicit-neighbor",
.cbs.create = ripd_instance_explicit_neighbor_create, .cbs.create = ripd_instance_explicit_neighbor_create,
.cbs.delete = ripd_instance_explicit_neighbor_delete, .cbs.delete = ripd_instance_explicit_neighbor_delete,
.cbs.cli_show = cli_show_rip_neighbor,
}, },
{ {
.xpath = "/frr-ripd:ripd/instance/network", .xpath = "/frr-ripd:ripd/instance/network",

View File

@ -389,6 +389,8 @@ extern int rip_create(int socket);
extern int rip_request_send(struct sockaddr_in *, struct interface *, uint8_t, extern int rip_request_send(struct sockaddr_in *, struct interface *, uint8_t,
struct connected *); struct connected *);
extern int rip_neighbor_lookup(struct sockaddr_in *); extern int rip_neighbor_lookup(struct sockaddr_in *);
extern int rip_neighbor_add(struct prefix_ipv4 *p);
extern int rip_neighbor_delete(struct prefix_ipv4 *p);
extern void rip_ecmp_disable(void); extern void rip_ecmp_disable(void);