From 23b23d8c27e972ab254503479ad891880ec597d9 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Wed, 9 May 2018 01:34:59 -0300 Subject: [PATCH] ripd: retrofit the 'distance source' commands to the new northbound model The "distance (1-255) A.B.C.D/M [WORD]" command was modeled using a YANG list, which makes it a little bit more complicated to convert to the new northbound model. The rip_distance_set() and rip_distance_unset() functions were removed since they set/unset multiple configuration options at the same time. The northbound callbacks need to set/unset configuration options individually. When a distance list is created, use yang_dnode_set_entry() to store a pointer in the configuration node, and retrieve this pointer in the other callbacks using yang_dnode_get_entry(). The 'rip_distance' structure was moved to ripd.h so that it can be used in the rip_northbound.c file. Signed-off-by: Renato Westphal --- ripd/rip_cli.c | 72 ++++++++++++++++++ ripd/rip_cli.h | 3 + ripd/rip_northbound.c | 75 +++++++++++++++++-- ripd/ripd.c | 165 +----------------------------------------- ripd/ripd.h | 12 +++ 5 files changed, 159 insertions(+), 168 deletions(-) diff --git a/ripd/rip_cli.c b/ripd/rip_cli.c index b9824d352..4f394bf19 100644 --- a/ripd/rip_cli.c +++ b/ripd/rip_cli.c @@ -234,6 +234,76 @@ void cli_show_rip_distance(struct vty *vty, struct lyd_node *dnode, vty_out(vty, " distance %s\n", yang_dnode_get_string(dnode, NULL)); } +/* + * XPath: /frr-ripd:ripd/instance/distance/source + */ +DEFPY (rip_distance_source, + rip_distance_source_cmd, + "distance (1-255) A.B.C.D/M$prefix [WORD$acl]", + "Administrative distance\n" + "Distance value\n" + "IP source prefix\n" + "Access list name\n") +{ + char xpath_list[XPATH_MAXLEN]; + struct cli_config_change changes[] = { + { + .xpath = ".", + .operation = NB_OP_CREATE, + }, + { + .xpath = "./distance", + .operation = NB_OP_MODIFY, + .value = distance_str, + }, + { + .xpath = "./access-list", + .operation = acl ? NB_OP_MODIFY : NB_OP_DELETE, + .value = acl, + }, + }; + + snprintf(xpath_list, sizeof(xpath_list), + "./distance/source[prefix='%s']", prefix_str); + + return nb_cli_cfg_change(vty, xpath_list, changes, array_size(changes)); +} + +DEFPY (no_rip_distance_source, + no_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") +{ + char xpath_list[XPATH_MAXLEN]; + struct cli_config_change changes[] = { + { + .xpath = ".", + .operation = NB_OP_DELETE, + }, + }; + + snprintf(xpath_list, sizeof(xpath_list), + "./distance/source[prefix='%s']", prefix_str); + + return nb_cli_cfg_change(vty, xpath_list, changes, 1); +} + +void cli_show_rip_distance_source(struct vty *vty, 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"); +} + void rip_cli_init(void) { install_element(CONFIG_NODE, &router_rip_cmd); @@ -245,4 +315,6 @@ void rip_cli_init(void) 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, &no_rip_distance_source_cmd); } diff --git a/ripd/rip_cli.h b/ripd/rip_cli.h index 1e2faac7f..dd810fb70 100644 --- a/ripd/rip_cli.h +++ b/ripd/rip_cli.h @@ -32,5 +32,8 @@ extern void cli_show_rip_default_metric(struct vty *vty, struct lyd_node *dnode, bool show_defaults); extern void cli_show_rip_distance(struct vty *vty, struct lyd_node *dnode, bool show_defaults); +extern void cli_show_rip_distance_source(struct vty *vty, + struct lyd_node *dnode, + bool show_defaults); #endif /* _FRR_RIP_CLI_H_ */ diff --git a/ripd/rip_northbound.c b/ripd/rip_northbound.c index 79b3d252e..25c279a77 100644 --- a/ripd/rip_northbound.c +++ b/ripd/rip_northbound.c @@ -162,14 +162,40 @@ static int ripd_instance_distance_source_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { - /* TODO: implement me. */ + struct prefix_ipv4 prefix; + struct route_node *rn; + + if (event != NB_EV_APPLY) + return NB_OK; + + yang_dnode_get_ipv4p(&prefix, dnode, "./prefix"); + + /* Get RIP distance node. */ + rn = route_node_get(rip_distance_table, (struct prefix *)&prefix); + rn->info = rip_distance_new(); + yang_dnode_set_entry(dnode, rn); + return NB_OK; } static int ripd_instance_distance_source_delete(enum nb_event event, const struct lyd_node *dnode) { - /* TODO: implement me. */ + struct route_node *rn; + struct rip_distance *rdistance; + + if (event != NB_EV_APPLY) + return NB_OK; + + rn = yang_dnode_get_entry(dnode); + rdistance = rn->info; + if (rdistance->access_list) + free(rdistance->access_list); + rip_distance_free(rdistance); + + rn->info = NULL; + route_unlock_node(rn); + return NB_OK; } @@ -181,7 +207,19 @@ ripd_instance_distance_source_distance_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { - /* TODO: implement me. */ + struct route_node *rn; + uint8_t distance; + struct rip_distance *rdistance; + + if (event != NB_EV_APPLY) + return NB_OK; + + /* Set distance value. */ + rn = yang_dnode_get_entry(dnode); + distance = yang_dnode_get_uint8(dnode, NULL); + rdistance = rn->info; + rdistance->distance = distance; + return NB_OK; } @@ -193,7 +231,22 @@ ripd_instance_distance_source_access_list_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { - /* TODO: implement me. */ + const char *acl_name; + struct route_node *rn; + struct rip_distance *rdistance; + + if (event != NB_EV_APPLY) + return NB_OK; + + acl_name = yang_dnode_get_string(dnode, NULL); + + /* Set access-list */ + rn = yang_dnode_get_entry(dnode); + rdistance = rn->info; + if (rdistance->access_list) + free(rdistance->access_list); + rdistance->access_list = strdup(acl_name); + return NB_OK; } @@ -201,7 +254,18 @@ static int ripd_instance_distance_source_access_list_delete(enum nb_event event, const struct lyd_node *dnode) { - /* TODO: implement me. */ + struct route_node *rn; + struct rip_distance *rdistance; + + if (event != NB_EV_APPLY) + return NB_OK; + + /* Reset access-list configuration. */ + rn = yang_dnode_get_entry(dnode); + rdistance = rn->info; + free(rdistance->access_list); + rdistance->access_list = NULL; + return NB_OK; } @@ -779,6 +843,7 @@ const struct frr_yang_module_info frr_ripd_info = { .xpath = "/frr-ripd:ripd/instance/distance/source", .cbs.create = ripd_instance_distance_source_create, .cbs.delete = ripd_instance_distance_source_delete, + .cbs.cli_show = cli_show_rip_distance_source, }, { .xpath = "/frr-ripd:ripd/instance/distance/source/distance", diff --git a/ripd/ripd.c b/ripd/ripd.c index d85ebcc53..4dbb47ebd 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -3001,98 +3001,16 @@ DEFUN (no_rip_timers, struct route_table *rip_distance_table; -struct rip_distance { - /* Distance value for the IP source prefix. */ - uint8_t distance; - - /* Name of the access-list to be matched. */ - char *access_list; -}; - -static struct rip_distance *rip_distance_new(void) +struct rip_distance *rip_distance_new(void) { return XCALLOC(MTYPE_RIP_DISTANCE, sizeof(struct rip_distance)); } -static void rip_distance_free(struct rip_distance *rdistance) +void rip_distance_free(struct rip_distance *rdistance) { XFREE(MTYPE_RIP_DISTANCE, rdistance); } -static int rip_distance_set(struct vty *vty, const char *distance_str, - const char *ip_str, const char *access_list_str) -{ - int ret; - struct prefix_ipv4 p; - uint8_t distance; - struct route_node *rn; - struct rip_distance *rdistance; - - ret = str2prefix_ipv4(ip_str, &p); - if (ret == 0) { - vty_out(vty, "Malformed prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - distance = atoi(distance_str); - - /* Get RIP distance node. */ - rn = route_node_get(rip_distance_table, (struct prefix *)&p); - if (rn->info) { - rdistance = rn->info; - route_unlock_node(rn); - } else { - rdistance = rip_distance_new(); - rn->info = rdistance; - } - - /* Set distance value. */ - rdistance->distance = distance; - - /* Reset access-list configuration. */ - if (rdistance->access_list) { - free(rdistance->access_list); - rdistance->access_list = NULL; - } - if (access_list_str) - rdistance->access_list = strdup(access_list_str); - - return CMD_SUCCESS; -} - -static int rip_distance_unset(struct vty *vty, const char *distance_str, - const char *ip_str, const char *access_list_str) -{ - int ret; - struct prefix_ipv4 p; - struct route_node *rn; - struct rip_distance *rdistance; - - ret = str2prefix_ipv4(ip_str, &p); - if (ret == 0) { - vty_out(vty, "Malformed prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - rn = route_node_lookup(rip_distance_table, (struct prefix *)&p); - if (!rn) { - vty_out(vty, "Can't find specified prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - rdistance = rn->info; - - if (rdistance->access_list) - free(rdistance->access_list); - rip_distance_free(rdistance); - - rn->info = NULL; - route_unlock_node(rn); - route_unlock_node(rn); - - return CMD_SUCCESS; -} - static void rip_distance_reset(void) { struct route_node *rn; @@ -3176,68 +3094,6 @@ static void rip_distance_show(struct vty *vty) } } -DEFUN (rip_distance_source, - rip_distance_source_cmd, - "distance (1-255) A.B.C.D/M", - "Administrative distance\n" - "Distance value\n" - "IP source prefix\n") -{ - int idx_number = 1; - int idx_ipv4_prefixlen = 2; - rip_distance_set(vty, argv[idx_number]->arg, - argv[idx_ipv4_prefixlen]->arg, NULL); - return CMD_SUCCESS; -} - -DEFUN (no_rip_distance_source, - no_rip_distance_source_cmd, - "no distance (1-255) A.B.C.D/M", - NO_STR - "Administrative distance\n" - "Distance value\n" - "IP source prefix\n") -{ - int idx_number = 2; - int idx_ipv4_prefixlen = 3; - rip_distance_unset(vty, argv[idx_number]->arg, - argv[idx_ipv4_prefixlen]->arg, NULL); - return CMD_SUCCESS; -} - -DEFUN (rip_distance_source_access_list, - rip_distance_source_access_list_cmd, - "distance (1-255) A.B.C.D/M WORD", - "Administrative distance\n" - "Distance value\n" - "IP source prefix\n" - "Access list name\n") -{ - int idx_number = 1; - int idx_ipv4_prefixlen = 2; - int idx_word = 3; - rip_distance_set(vty, argv[idx_number]->arg, - argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg); - return CMD_SUCCESS; -} - -DEFUN (no_rip_distance_source_access_list, - no_rip_distance_source_access_list_cmd, - "no distance (1-255) A.B.C.D/M WORD", - NO_STR - "Administrative distance\n" - "Distance value\n" - "IP source prefix\n" - "Access list name\n") -{ - int idx_number = 2; - int idx_ipv4_prefixlen = 3; - int idx_word = 4; - rip_distance_unset(vty, argv[idx_number]->arg, - argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg); - return CMD_SUCCESS; -} - /* Update ECMP routes to zebra when ECMP is disabled. */ void rip_ecmp_disable(void) { @@ -3531,7 +3387,6 @@ static int config_write_rip(struct vty *vty) { int write = 0; struct route_node *rn; - struct rip_distance *rdistance; struct lyd_node *dnode; dnode = yang_dnode_get(running_config->dnode, @@ -3569,18 +3424,6 @@ static int config_write_rip(struct vty *vty) /* Interface routemap configuration */ write += config_write_if_rmap(vty); - /* RIP source IP prefix distance configuration. */ - for (rn = route_top(rip_distance_table); rn; - rn = route_next(rn)) - if ((rdistance = rn->info) != NULL) - vty_out(vty, " distance %d %s/%d %s\n", - rdistance->distance, - inet_ntoa(rn->p.u.prefix4), - rn->p.prefixlen, - rdistance->access_list - ? rdistance->access_list - : ""); - /* RIP static route configuration. */ for (rn = route_top(rip->route); rn; rn = route_next(rn)) if (rn->info) @@ -3863,10 +3706,6 @@ void rip_init(void) install_element(RIP_NODE, &no_rip_timers_cmd); install_element(RIP_NODE, &rip_route_cmd); install_element(RIP_NODE, &no_rip_route_cmd); - install_element(RIP_NODE, &rip_distance_source_cmd); - install_element(RIP_NODE, &no_rip_distance_source_cmd); - install_element(RIP_NODE, &rip_distance_source_access_list_cmd); - install_element(RIP_NODE, &no_rip_distance_source_access_list_cmd); /* Debug related init. */ rip_debug_init(); diff --git a/ripd/ripd.h b/ripd/ripd.h index 1ecedf368..31697264a 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -320,6 +320,14 @@ struct rip_peer { struct thread *t_timeout; }; +struct rip_distance { + /* Distance value for the IP source prefix. */ + uint8_t distance; + + /* Name of the access-list to be matched. */ + char *access_list; +}; + struct rip_md5_info { uint16_t family; uint16_t type; @@ -417,6 +425,8 @@ extern int rip_offset_list_apply_out(struct prefix_ipv4 *, struct interface *, extern void rip_offset_clean(void); extern void rip_info_free(struct rip_info *); +extern struct rip_distance *rip_distance_new(void); +extern void rip_distance_free(struct rip_distance *rdistance); extern uint8_t rip_distance_apply(struct rip_info *); extern void rip_redistribute_clean(void); @@ -439,6 +449,8 @@ extern long rip_global_queries; DECLARE_HOOK(rip_ifaddr_add, (struct connected * ifc), (ifc)) DECLARE_HOOK(rip_ifaddr_del, (struct connected * ifc), (ifc)) +extern struct route_table *rip_distance_table; + /* Northbound. */ extern void rip_cli_init(void); extern const struct frr_yang_module_info frr_ripd_info; -- 2.39.5