diff options
author | Renato Westphal <renato@opensourcerouting.org> | 2018-05-09 06:35:00 +0200 |
---|---|---|
committer | Renato Westphal <renato@opensourcerouting.org> | 2018-10-27 20:16:12 +0200 |
commit | 8c942f65062ac96978fb9c058875a4a602f66dcf (patch) | |
tree | edb539ba4fc9e2768455b4bbe2fb49b1d373a649 | |
parent | ripd: retrofit the 'network' command to the new northbound model (diff) | |
download | frr-8c942f65062ac96978fb9c058875a4a602f66dcf.tar.xz frr-8c942f65062ac96978fb9c058875a4a602f66dcf.zip |
ripd: retrofit the 'offset-list' command to the new northbound model
Remove the rip_offset_list_set() and rip_offset_list_unset() functions
since they set/unset multiple configuration options at the same time. The
northbound callbacks need to set/unset configuration options individually.
The frr-ripd YANG module models the "offset-list" command using a list
keyed by the 'interface' and 'direction' leafs. One important detail is
that the IFNAME parameter is optional, and when it's not present it means
we want to match all interfaces. This is modeled using an interface name
of '*' since key lists are mandatory by definition in YANG.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
-rw-r--r-- | ripd/rip_cli.c | 82 | ||||
-rw-r--r-- | ripd/rip_cli.h | 2 | ||||
-rw-r--r-- | ripd/rip_northbound.c | 61 | ||||
-rw-r--r-- | ripd/rip_offset.c | 290 | ||||
-rw-r--r-- | ripd/ripd.c | 3 | ||||
-rw-r--r-- | ripd/ripd.h | 32 |
6 files changed, 189 insertions, 281 deletions
diff --git a/ripd/rip_cli.c b/ripd/rip_cli.c index a22f3054a..10db5d967 100644 --- a/ripd/rip_cli.c +++ b/ripd/rip_cli.c @@ -385,6 +385,86 @@ void cli_show_rip_network_interface(struct vty *vty, struct lyd_node *dnode, vty_out(vty, " network %s\n", yang_dnode_get_string(dnode, NULL)); } +/* + * XPath: /frr-ripd:ripd/instance/offset-list + */ +DEFPY (rip_offset_list, + rip_offset_list_cmd, + "offset-list WORD$acl <in|out>$direction (0-16)$metric [IFNAME]", + "Modify RIP metric\n" + "Access-list name\n" + "For incoming updates\n" + "For outgoing updates\n" + "Metric value\n" + "Interface to match\n") +{ + char xpath_list[XPATH_MAXLEN]; + struct cli_config_change changes[] = { + { + .xpath = ".", + .operation = NB_OP_CREATE, + }, + { + .xpath = "./access-list", + .operation = NB_OP_MODIFY, + .value = acl, + }, + { + .xpath = "./metric", + .operation = NB_OP_MODIFY, + .value = metric_str, + }, + }; + + snprintf(xpath_list, sizeof(xpath_list), + "./offset-list[interface='%s'][direction='%s']", + ifname ? ifname : "*", direction); + + return nb_cli_cfg_change(vty, xpath_list, changes, array_size(changes)); +} + +DEFPY (no_rip_offset_list, + no_rip_offset_list_cmd, + "no offset-list WORD$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") +{ + char xpath_list[XPATH_MAXLEN]; + struct cli_config_change changes[] = { + { + .xpath = ".", + .operation = NB_OP_DELETE, + }, + }; + + snprintf(xpath_list, sizeof(xpath_list), + "./offset-list[interface='%s'][direction='%s']", + ifname ? ifname : "*", direction); + + return nb_cli_cfg_change(vty, xpath_list, changes, array_size(changes)); +} + +void cli_show_rip_offset_list(struct vty *vty, 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"); +} + void rip_cli_init(void) { install_element(CONFIG_NODE, &router_rip_cmd); @@ -401,4 +481,6 @@ void rip_cli_init(void) 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); + install_element(RIP_NODE, &no_rip_offset_list_cmd); } diff --git a/ripd/rip_cli.h b/ripd/rip_cli.h index 2a0540592..16ed78451 100644 --- a/ripd/rip_cli.h +++ b/ripd/rip_cli.h @@ -42,5 +42,7 @@ extern void cli_show_rip_network_prefix(struct vty *vty, struct lyd_node *dnode, extern void cli_show_rip_network_interface(struct vty *vty, struct lyd_node *dnode, bool show_defaults); +extern void cli_show_rip_offset_list(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 498aa322c..bdad4004d 100644 --- a/ripd/rip_northbound.c +++ b/ripd/rip_northbound.c @@ -370,14 +370,40 @@ static int ripd_instance_offset_list_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { - /* TODO: implement me. */ + const char *ifname; + struct rip_offset_list *offset; + + if (event != NB_EV_APPLY) + return NB_OK; + + ifname = yang_dnode_get_string(dnode, "./interface"); + + offset = rip_offset_list_new(ifname); + yang_dnode_set_entry(dnode, offset); + return NB_OK; } static int ripd_instance_offset_list_delete(enum nb_event event, const struct lyd_node *dnode) { - /* TODO: implement me. */ + int direct; + struct rip_offset_list *offset; + + if (event != NB_EV_APPLY) + return NB_OK; + + direct = yang_dnode_get_enum(dnode, "./direction"); + + offset = yang_dnode_get_entry(dnode); + if (offset->direct[direct].alist_name) { + free(offset->direct[direct].alist_name); + offset->direct[direct].alist_name = NULL; + } + if (offset->direct[RIP_OFFSET_LIST_IN].alist_name == NULL + && offset->direct[RIP_OFFSET_LIST_OUT].alist_name == NULL) + offset_list_del(offset); + return NB_OK; } @@ -389,7 +415,21 @@ ripd_instance_offset_list_access_list_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { - /* TODO: implement me. */ + int direct; + struct rip_offset_list *offset; + const char *alist_name; + + if (event != NB_EV_APPLY) + return NB_OK; + + direct = yang_dnode_get_enum(dnode, "../direction"); + alist_name = yang_dnode_get_string(dnode, NULL); + + offset = yang_dnode_get_entry(dnode); + if (offset->direct[direct].alist_name) + free(offset->direct[direct].alist_name); + offset->direct[direct].alist_name = strdup(alist_name); + return NB_OK; } @@ -400,7 +440,19 @@ static int ripd_instance_offset_list_metric_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { - /* TODO: implement me. */ + int direct; + uint8_t metric; + struct rip_offset_list *offset; + + if (event != NB_EV_APPLY) + return NB_OK; + + direct = yang_dnode_get_enum(dnode, "../direction"); + metric = yang_dnode_get_uint8(dnode, NULL); + + offset = yang_dnode_get_entry(dnode); + offset->direct[direct].metric = metric; + return NB_OK; } @@ -916,6 +968,7 @@ const struct frr_yang_module_info frr_ripd_info = { .xpath = "/frr-ripd:ripd/instance/offset-list", .cbs.create = ripd_instance_offset_list_create, .cbs.delete = ripd_instance_offset_list_delete, + .cbs.cli_show = cli_show_rip_offset_list, }, { .xpath = "/frr-ripd:ripd/instance/offset-list/access-list", diff --git a/ripd/rip_offset.c b/ripd/rip_offset.c index d2065a4bb..418ec3fc7 100644 --- a/ripd/rip_offset.c +++ b/ripd/rip_offset.c @@ -29,160 +29,48 @@ #include "ripd/ripd.h" -#define RIP_OFFSET_LIST_IN 0 -#define RIP_OFFSET_LIST_OUT 1 -#define RIP_OFFSET_LIST_MAX 2 - -struct rip_offset_list { - char *ifname; - - struct { - char *alist_name; - /* struct access_list *alist; */ - int metric; - } direct[RIP_OFFSET_LIST_MAX]; -}; - static struct list *rip_offset_list_master; -static int strcmp_safe(const char *s1, const char *s2) -{ - if (s1 == NULL && s2 == NULL) - return 0; - if (s1 == NULL) - return -1; - if (s2 == NULL) - return 1; - return strcmp(s1, s2); -} - -static struct rip_offset_list *rip_offset_list_new(void) -{ - return XCALLOC(MTYPE_RIP_OFFSET_LIST, sizeof(struct rip_offset_list)); -} - -static void rip_offset_list_free(struct rip_offset_list *offset) -{ - XFREE(MTYPE_RIP_OFFSET_LIST, offset); -} - -static struct rip_offset_list *rip_offset_list_lookup(const char *ifname) -{ - struct rip_offset_list *offset; - struct listnode *node, *nnode; +#define OFFSET_LIST_IN_NAME(O) ((O)->direct[RIP_OFFSET_LIST_IN].alist_name) +#define OFFSET_LIST_IN_METRIC(O) ((O)->direct[RIP_OFFSET_LIST_IN].metric) - for (ALL_LIST_ELEMENTS(rip_offset_list_master, node, nnode, offset)) { - if (strcmp_safe(offset->ifname, ifname) == 0) - return offset; - } - return NULL; -} +#define OFFSET_LIST_OUT_NAME(O) ((O)->direct[RIP_OFFSET_LIST_OUT].alist_name) +#define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIP_OFFSET_LIST_OUT].metric) -static struct rip_offset_list *rip_offset_list_get(const char *ifname) +struct rip_offset_list *rip_offset_list_new(const char *ifname) { struct rip_offset_list *offset; - offset = rip_offset_list_lookup(ifname); - if (offset) - return offset; - - offset = rip_offset_list_new(); - if (ifname) - offset->ifname = strdup(ifname); + offset = XCALLOC(MTYPE_RIP_OFFSET_LIST, sizeof(struct rip_offset_list)); + offset->ifname = strdup(ifname); listnode_add_sort(rip_offset_list_master, offset); return offset; } -static int rip_offset_list_set(struct vty *vty, const char *alist, - const char *direct_str, const char *metric_str, - const char *ifname) +void offset_list_del(struct rip_offset_list *offset) { - int direct; - int metric; - struct rip_offset_list *offset; - - /* Check direction. */ - if (strncmp(direct_str, "i", 1) == 0) - direct = RIP_OFFSET_LIST_IN; - else if (strncmp(direct_str, "o", 1) == 0) - direct = RIP_OFFSET_LIST_OUT; - else { - vty_out(vty, "Invalid direction: %s\n", direct_str); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check metric. */ - metric = atoi(metric_str); - if (metric < 0 || metric > 16) { - vty_out(vty, "Invalid metric: %s\n", metric_str); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Get offset-list structure with interface name. */ - offset = rip_offset_list_get(ifname); - - if (offset->direct[direct].alist_name) - free(offset->direct[direct].alist_name); - offset->direct[direct].alist_name = strdup(alist); - offset->direct[direct].metric = metric; - - return CMD_SUCCESS; + listnode_delete(rip_offset_list_master, offset); + if (OFFSET_LIST_IN_NAME(offset)) + free(OFFSET_LIST_IN_NAME(offset)); + if (OFFSET_LIST_OUT_NAME(offset)) + free(OFFSET_LIST_OUT_NAME(offset)); + free(offset->ifname); + XFREE(MTYPE_RIP_OFFSET_LIST, offset); } -static int rip_offset_list_unset(struct vty *vty, const char *alist, - const char *direct_str, const char *metric_str, - const char *ifname) +struct rip_offset_list *rip_offset_list_lookup(const char *ifname) { - int direct; - int metric; struct rip_offset_list *offset; + struct listnode *node, *nnode; - /* Check direction. */ - if (strncmp(direct_str, "i", 1) == 0) - direct = RIP_OFFSET_LIST_IN; - else if (strncmp(direct_str, "o", 1) == 0) - direct = RIP_OFFSET_LIST_OUT; - else { - vty_out(vty, "Invalid direction: %s\n", direct_str); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check metric. */ - metric = atoi(metric_str); - if (metric < 0 || metric > 16) { - vty_out(vty, "Invalid metric: %s\n", metric_str); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Get offset-list structure with interface name. */ - offset = rip_offset_list_lookup(ifname); - - if (offset) { - if (offset->direct[direct].alist_name) - free(offset->direct[direct].alist_name); - offset->direct[direct].alist_name = NULL; - - if (offset->direct[RIP_OFFSET_LIST_IN].alist_name == NULL - && offset->direct[RIP_OFFSET_LIST_OUT].alist_name == NULL) { - listnode_delete(rip_offset_list_master, offset); - if (offset->ifname) - free(offset->ifname); - rip_offset_list_free(offset); - } - } else { - vty_out(vty, "Can't find offset-list\n"); - return CMD_WARNING_CONFIG_FAILED; + for (ALL_LIST_ELEMENTS(rip_offset_list_master, node, nnode, offset)) { + if (strcmp(offset->ifname, ifname) == 0) + return offset; } - return CMD_SUCCESS; + return NULL; } -#define OFFSET_LIST_IN_NAME(O) ((O)->direct[RIP_OFFSET_LIST_IN].alist_name) -#define OFFSET_LIST_IN_METRIC(O) ((O)->direct[RIP_OFFSET_LIST_IN].metric) - -#define OFFSET_LIST_OUT_NAME(O) ((O)->direct[RIP_OFFSET_LIST_OUT].alist_name) -#define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIP_OFFSET_LIST_OUT].metric) - /* If metric is modifed return 1. */ int rip_offset_list_apply_in(struct prefix_ipv4 *p, struct interface *ifp, uint32_t *metric) @@ -204,7 +92,7 @@ int rip_offset_list_apply_in(struct prefix_ipv4 *p, struct interface *ifp, return 0; } /* Look up offset-list without interface name. */ - offset = rip_offset_list_lookup(NULL); + offset = rip_offset_list_lookup("*"); if (offset && OFFSET_LIST_IN_NAME(offset)) { alist = access_list_lookup(AFI_IP, OFFSET_LIST_IN_NAME(offset)); @@ -242,7 +130,7 @@ int rip_offset_list_apply_out(struct prefix_ipv4 *p, struct interface *ifp, } /* Look up offset-list without interface name. */ - offset = rip_offset_list_lookup(NULL); + offset = rip_offset_list_lookup("*"); if (offset && OFFSET_LIST_OUT_NAME(offset)) { alist = access_list_lookup(AFI_IP, OFFSET_LIST_OUT_NAME(offset)); @@ -258,95 +146,10 @@ int rip_offset_list_apply_out(struct prefix_ipv4 *p, struct interface *ifp, return 0; } -DEFUN (rip_offset_list, - rip_offset_list_cmd, - "offset-list WORD <in|out> (0-16)", - "Modify RIP metric\n" - "Access-list name\n" - "For incoming updates\n" - "For outgoing updates\n" - "Metric value\n") -{ - int idx_word = 1; - int idx_in_out = 2; - int idx_number = 3; - return rip_offset_list_set(vty, argv[idx_word]->arg, - argv[idx_in_out]->arg, argv[idx_number]->arg, - NULL); -} - -DEFUN (rip_offset_list_ifname, - rip_offset_list_ifname_cmd, - "offset-list WORD <in|out> (0-16) IFNAME", - "Modify RIP metric\n" - "Access-list name\n" - "For incoming updates\n" - "For outgoing updates\n" - "Metric value\n" - "Interface to match\n") -{ - int idx_word = 1; - int idx_in_out = 2; - int idx_number = 3; - int idx_ifname = 4; - return rip_offset_list_set(vty, argv[idx_word]->arg, - argv[idx_in_out]->arg, argv[idx_number]->arg, - argv[idx_ifname]->arg); -} - -DEFUN (no_rip_offset_list, - no_rip_offset_list_cmd, - "no offset-list WORD <in|out> (0-16)", - NO_STR - "Modify RIP metric\n" - "Access-list name\n" - "For incoming updates\n" - "For outgoing updates\n" - "Metric value\n") -{ - int idx_word = 2; - int idx_in_out = 3; - int idx_number = 4; - return rip_offset_list_unset(vty, argv[idx_word]->arg, - argv[idx_in_out]->arg, - argv[idx_number]->arg, NULL); -} - -DEFUN (no_rip_offset_list_ifname, - no_rip_offset_list_ifname_cmd, - "no offset-list WORD <in|out> (0-16) 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") -{ - int idx_word = 2; - int idx_in_out = 3; - int idx_number = 4; - int idx_ifname = 5; - return rip_offset_list_unset( - vty, argv[idx_word]->arg, argv[idx_in_out]->arg, - argv[idx_number]->arg, argv[idx_ifname]->arg); -} - static int offset_list_cmp(struct rip_offset_list *o1, struct rip_offset_list *o2) { - return strcmp_safe(o1->ifname, o2->ifname); -} - -static void offset_list_del(struct rip_offset_list *offset) -{ - if (OFFSET_LIST_IN_NAME(offset)) - free(OFFSET_LIST_IN_NAME(offset)); - if (OFFSET_LIST_OUT_NAME(offset)) - free(OFFSET_LIST_OUT_NAME(offset)); - if (offset->ifname) - free(offset->ifname); - rip_offset_list_free(offset); + return strcmp(o1->ifname, o2->ifname); } void rip_offset_init() @@ -354,11 +157,6 @@ void rip_offset_init() rip_offset_list_master = list_new(); rip_offset_list_master->cmp = (int (*)(void *, void *))offset_list_cmp; rip_offset_list_master->del = (void (*)(void *))offset_list_del; - - install_element(RIP_NODE, &rip_offset_list_cmd); - install_element(RIP_NODE, &rip_offset_list_ifname_cmd); - install_element(RIP_NODE, &no_rip_offset_list_cmd); - install_element(RIP_NODE, &no_rip_offset_list_ifname_cmd); } void rip_offset_clean() @@ -369,43 +167,3 @@ void rip_offset_clean() rip_offset_list_master->cmp = (int (*)(void *, void *))offset_list_cmp; rip_offset_list_master->del = (void (*)(void *))offset_list_del; } - -int config_write_rip_offset_list(struct vty *vty) -{ - struct listnode *node, *nnode; - struct rip_offset_list *offset; - - for (ALL_LIST_ELEMENTS(rip_offset_list_master, node, nnode, offset)) { - if (!offset->ifname) { - if (offset->direct[RIP_OFFSET_LIST_IN].alist_name) - vty_out(vty, " offset-list %s in %d\n", - offset->direct[RIP_OFFSET_LIST_IN] - .alist_name, - offset->direct[RIP_OFFSET_LIST_IN] - .metric); - if (offset->direct[RIP_OFFSET_LIST_OUT].alist_name) - vty_out(vty, " offset-list %s out %d\n", - offset->direct[RIP_OFFSET_LIST_OUT] - .alist_name, - offset->direct[RIP_OFFSET_LIST_OUT] - .metric); - } else { - if (offset->direct[RIP_OFFSET_LIST_IN].alist_name) - vty_out(vty, " offset-list %s in %d %s\n", - offset->direct[RIP_OFFSET_LIST_IN] - .alist_name, - offset->direct[RIP_OFFSET_LIST_IN] - .metric, - offset->ifname); - if (offset->direct[RIP_OFFSET_LIST_OUT].alist_name) - vty_out(vty, " offset-list %s out %d %s\n", - offset->direct[RIP_OFFSET_LIST_OUT] - .alist_name, - offset->direct[RIP_OFFSET_LIST_OUT] - .metric, - offset->ifname); - } - } - - return 0; -} diff --git a/ripd/ripd.c b/ripd/ripd.c index 027ad878b..24bbf226b 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -3412,9 +3412,6 @@ static int config_write_rip(struct vty *vty) /* Redistribute configuration. */ config_write_rip_redistribute(vty, 1); - /* RIP offset-list configuration. */ - config_write_rip_offset_list(vty); - /* Distribute configuration. */ write += config_write_distribute(vty); diff --git a/ripd/ripd.h b/ripd/ripd.h index 9bd9f53f2..4378f75af 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -367,6 +367,20 @@ enum rip_event { /* Macro for timer turn off. */ #define RIP_TIMER_OFF(X) THREAD_TIMER_OFF(X) +#define RIP_OFFSET_LIST_IN 0 +#define RIP_OFFSET_LIST_OUT 1 +#define RIP_OFFSET_LIST_MAX 2 + +struct rip_offset_list { + char *ifname; + + struct { + char *alist_name; + /* struct access_list *alist; */ + uint8_t metric; + } direct[RIP_OFFSET_LIST_MAX]; +}; + /* Prototypes. */ extern void rip_init(void); extern void rip_reset(void); @@ -382,7 +396,6 @@ extern void rip_route_map_reset(void); extern void rip_zclient_init(struct thread_master *); extern void rip_zclient_stop(void); extern void rip_zclient_reset(void); -extern void rip_offset_init(void); extern int if_check_address(struct in_addr addr); extern int rip_create(int socket); @@ -414,7 +427,6 @@ extern void rip_distribute_update_interface(struct interface *); extern void rip_if_rmap_update_interface(struct interface *); extern int config_write_rip_network(struct vty *, int); -extern int config_write_rip_offset_list(struct vty *); extern int config_write_rip_redistribute(struct vty *, int); extern void rip_peer_init(void); @@ -425,12 +437,6 @@ extern void rip_peer_display(struct vty *); extern struct rip_peer *rip_peer_lookup(struct in_addr *); extern struct rip_peer *rip_peer_lookup_next(struct in_addr *); -extern int rip_offset_list_apply_in(struct prefix_ipv4 *, struct interface *, - uint32_t *); -extern int rip_offset_list_apply_out(struct prefix_ipv4 *, struct interface *, - uint32_t *); -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); @@ -441,6 +447,16 @@ extern struct rip_info *rip_ecmp_add(struct rip_info *); extern struct rip_info *rip_ecmp_replace(struct rip_info *); extern struct rip_info *rip_ecmp_delete(struct rip_info *); +extern struct rip_offset_list *rip_offset_list_new(const char *ifname); +extern void offset_list_del(struct rip_offset_list *offset); +extern struct rip_offset_list *rip_offset_list_lookup(const char *ifname); +extern int rip_offset_list_apply_in(struct prefix_ipv4 *, struct interface *, + uint32_t *); +extern int rip_offset_list_apply_out(struct prefix_ipv4 *, struct interface *, + uint32_t *); +extern void rip_offset_init(void); +extern void rip_offset_clean(void); + /* There is only one rip strucutre. */ extern struct rip *rip; |