From b09956ca5184a5daff87e144efb935d21504518e Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 29 Nov 2018 02:27:16 -0200 Subject: [PATCH] ripngd: retrofit the 'offset-list' command to the new northbound model Remove the ripng_offset_list_set() and ripng_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-ripngd 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 list keys are mandatory leafs by definition in YANG. Signed-off-by: Renato Westphal --- ripngd/ripng_cli.c | 44 ++++++ ripngd/ripng_cli.h | 2 + ripngd/ripng_northbound.c | 61 +++++++- ripngd/ripng_offset.c | 292 +++----------------------------------- ripngd/ripngd.c | 3 - ripngd/ripngd.h | 22 ++- 6 files changed, 145 insertions(+), 279 deletions(-) diff --git a/ripngd/ripng_cli.c b/ripngd/ripng_cli.c index 53ff3fd061..1eb31a0ce6 100644 --- a/ripngd/ripng_cli.c +++ b/ripngd/ripng_cli.c @@ -203,6 +203,49 @@ void cli_show_ripng_network_interface(struct vty *vty, struct lyd_node *dnode, vty_out(vty, " network %s\n", yang_dnode_get_string(dnode, NULL)); } +/* + * XPath: /frr-ripngd:ripngd/instance/offset-list + */ +DEFPY (ripng_offset_list, + ripng_offset_list_cmd, + "[no] offset-list WORD$acl $direction (0-16)$metric [IFNAME]", + NO_STR + "Modify RIPng 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_DELETE, NULL); + + return nb_cli_apply_changes( + vty, "./offset-list[interface='%s'][direction='%s']", + ifname ? ifname : "*", direction); +} + +void cli_show_ripng_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 ripng_cli_init(void) { install_element(CONFIG_NODE, &router_ripng_cmd); @@ -214,4 +257,5 @@ void ripng_cli_init(void) install_element(RIPNG_NODE, &no_ripng_default_metric_cmd); install_element(RIPNG_NODE, &ripng_network_prefix_cmd); install_element(RIPNG_NODE, &ripng_network_if_cmd); + install_element(RIPNG_NODE, &ripng_offset_list_cmd); } diff --git a/ripngd/ripng_cli.h b/ripngd/ripng_cli.h index 144f0afa2b..d65241436f 100644 --- a/ripngd/ripng_cli.h +++ b/ripngd/ripng_cli.h @@ -37,5 +37,7 @@ extern void cli_show_ripng_network_prefix(struct vty *vty, extern void cli_show_ripng_network_interface(struct vty *vty, struct lyd_node *dnode, bool show_defaults); +extern void cli_show_ripng_offset_list(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); #endif /* _FRR_RIPNG_CLI_H_ */ diff --git a/ripngd/ripng_northbound.c b/ripngd/ripng_northbound.c index ff03e8a91a..614259a7b4 100644 --- a/ripngd/ripng_northbound.c +++ b/ripngd/ripng_northbound.c @@ -202,14 +202,40 @@ static int ripngd_instance_offset_list_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { - /* TODO: implement me. */ + const char *ifname; + struct ripng_offset_list *offset; + + if (event != NB_EV_APPLY) + return NB_OK; + + ifname = yang_dnode_get_string(dnode, "./interface"); + + offset = ripng_offset_list_new(ifname); + yang_dnode_set_entry(dnode, offset); + return NB_OK; } static int ripngd_instance_offset_list_delete(enum nb_event event, const struct lyd_node *dnode) { - /* TODO: implement me. */ + int direct; + struct ripng_offset_list *offset; + + if (event != NB_EV_APPLY) + return NB_OK; + + direct = yang_dnode_get_enum(dnode, "./direction"); + + offset = yang_dnode_get_entry(dnode, true); + if (offset->direct[direct].alist_name) { + free(offset->direct[direct].alist_name); + offset->direct[direct].alist_name = NULL; + } + if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name == NULL + && offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name == NULL) + ripng_offset_list_del(offset); + return NB_OK; } @@ -221,7 +247,21 @@ ripngd_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 ripng_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, true); + if (offset->direct[direct].alist_name) + free(offset->direct[direct].alist_name); + offset->direct[direct].alist_name = strdup(alist_name); + return NB_OK; } @@ -233,7 +273,19 @@ ripngd_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 ripng_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, true); + offset->direct[direct].metric = metric; + return NB_OK; } @@ -592,6 +644,7 @@ const struct frr_yang_module_info frr_ripngd_info = { .xpath = "/frr-ripngd:ripngd/instance/offset-list", .cbs.create = ripngd_instance_offset_list_create, .cbs.delete = ripngd_instance_offset_list_delete, + .cbs.cli_show = cli_show_ripng_offset_list, }, { .xpath = "/frr-ripngd:ripngd/instance/offset-list/access-list", diff --git a/ripngd/ripng_offset.c b/ripngd/ripng_offset.c index 32b81b5480..278df75892 100644 --- a/ripngd/ripng_offset.c +++ b/ripngd/ripng_offset.c @@ -33,165 +33,49 @@ #include "ripngd/ripngd.h" -#define RIPNG_OFFSET_LIST_IN 0 -#define RIPNG_OFFSET_LIST_OUT 1 -#define RIPNG_OFFSET_LIST_MAX 2 - -struct ripng_offset_list { - char *ifname; - - struct { - char *alist_name; - /* struct access_list *alist; */ - int metric; - } direct[RIPNG_OFFSET_LIST_MAX]; -}; - static struct list *ripng_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); -} +#define OFFSET_LIST_IN_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].alist_name) +#define OFFSET_LIST_IN_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].metric) + +#define OFFSET_LIST_OUT_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].alist_name) +#define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].metric) -static struct ripng_offset_list *ripng_offset_list_new(void) +struct ripng_offset_list *ripng_offset_list_new(const char *ifname) { struct ripng_offset_list *new; new = XCALLOC(MTYPE_RIPNG_OFFSET_LIST, sizeof(struct ripng_offset_list)); + new->ifname = strdup(ifname); + listnode_add_sort(ripng_offset_list_master, new); + return new; } -static void ripng_offset_list_free(struct ripng_offset_list *offset) +void ripng_offset_list_del(struct ripng_offset_list *offset) { + listnode_delete(ripng_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_RIPNG_OFFSET_LIST, offset); } -static struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname) +struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname) { struct ripng_offset_list *offset; struct listnode *node, *nnode; for (ALL_LIST_ELEMENTS(ripng_offset_list_master, node, nnode, offset)) { - if (strcmp_safe(offset->ifname, ifname) == 0) + if (strcmp(offset->ifname, ifname) == 0) return offset; } return NULL; } -static struct ripng_offset_list *ripng_offset_list_get(const char *ifname) -{ - struct ripng_offset_list *offset; - - offset = ripng_offset_list_lookup(ifname); - if (offset) - return offset; - - offset = ripng_offset_list_new(); - if (ifname) - offset->ifname = strdup(ifname); - listnode_add_sort(ripng_offset_list_master, offset); - - return offset; -} - -static int ripng_offset_list_set(struct vty *vty, const char *alist, - const char *direct_str, const char *metric_str, - const char *ifname) -{ - int direct; - int metric; - struct ripng_offset_list *offset; - - /* Check direction. */ - if (strncmp(direct_str, "i", 1) == 0) - direct = RIPNG_OFFSET_LIST_IN; - else if (strncmp(direct_str, "o", 1) == 0) - direct = RIPNG_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 = ripng_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; -} - -static int ripng_offset_list_unset(struct vty *vty, const char *alist, - const char *direct_str, - const char *metric_str, const char *ifname) -{ - int direct; - int metric; - struct ripng_offset_list *offset; - - /* Check direction. */ - if (strncmp(direct_str, "i", 1) == 0) - direct = RIPNG_OFFSET_LIST_IN; - else if (strncmp(direct_str, "o", 1) == 0) - direct = RIPNG_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 = ripng_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[RIPNG_OFFSET_LIST_IN].alist_name == NULL - && offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name - == NULL) { - listnode_delete(ripng_offset_list_master, offset); - if (offset->ifname) - free(offset->ifname); - ripng_offset_list_free(offset); - } - } else { - vty_out(vty, "Can't find offset-list\n"); - return CMD_WARNING_CONFIG_FAILED; - } - return CMD_SUCCESS; -} - -#define OFFSET_LIST_IN_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].alist_name) -#define OFFSET_LIST_IN_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].metric) - -#define OFFSET_LIST_OUT_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].alist_name) -#define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].metric) - /* If metric is modifed return 1. */ int ripng_offset_list_apply_in(struct prefix_ipv6 *p, struct interface *ifp, uint8_t *metric) @@ -214,7 +98,7 @@ int ripng_offset_list_apply_in(struct prefix_ipv6 *p, struct interface *ifp, return 0; } /* Look up offset-list without interface name. */ - offset = ripng_offset_list_lookup(NULL); + offset = ripng_offset_list_lookup("*"); if (offset && OFFSET_LIST_IN_NAME(offset)) { alist = access_list_lookup(AFI_IP6, OFFSET_LIST_IN_NAME(offset)); @@ -253,7 +137,7 @@ int ripng_offset_list_apply_out(struct prefix_ipv6 *p, struct interface *ifp, } /* Look up offset-list without interface name. */ - offset = ripng_offset_list_lookup(NULL); + offset = ripng_offset_list_lookup("*"); if (offset && OFFSET_LIST_OUT_NAME(offset)) { alist = access_list_lookup(AFI_IP6, OFFSET_LIST_OUT_NAME(offset)); @@ -269,95 +153,10 @@ int ripng_offset_list_apply_out(struct prefix_ipv6 *p, struct interface *ifp, return 0; } -DEFUN (ripng_offset_list, - ripng_offset_list_cmd, - "offset-list WORD (0-16)", - "Modify RIPng 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 ripng_offset_list_set(vty, argv[idx_word]->arg, - argv[idx_in_out]->arg, - argv[idx_number]->arg, NULL); -} - -DEFUN (ripng_offset_list_ifname, - ripng_offset_list_ifname_cmd, - "offset-list WORD (0-16) IFNAME", - "Modify RIPng 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 ripng_offset_list_set( - vty, argv[idx_word]->arg, argv[idx_in_out]->arg, - argv[idx_number]->arg, argv[idx_ifname]->arg); -} - -DEFUN (no_ripng_offset_list, - no_ripng_offset_list_cmd, - "no offset-list WORD (0-16)", - NO_STR - "Modify RIPng 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 ripng_offset_list_unset(vty, argv[idx_word]->arg, - argv[idx_in_out]->arg, - argv[idx_number]->arg, NULL); -} - -DEFUN (no_ripng_offset_list_ifname, - no_ripng_offset_list_ifname_cmd, - "no offset-list WORD (0-16) IFNAME", - NO_STR - "Modify RIPng 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 ripng_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 ripng_offset_list *o1, struct ripng_offset_list *o2) { - return strcmp_safe(o1->ifname, o2->ifname); -} - -static void offset_list_del(struct ripng_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); - ripng_offset_list_free(offset); + return strcmp(o1->ifname, o2->ifname); } void ripng_offset_init(void) @@ -365,12 +164,7 @@ void ripng_offset_init(void) ripng_offset_list_master = list_new(); ripng_offset_list_master->cmp = (int (*)(void *, void *))offset_list_cmp; - ripng_offset_list_master->del = (void (*)(void *))offset_list_del; - - install_element(RIPNG_NODE, &ripng_offset_list_cmd); - install_element(RIPNG_NODE, &ripng_offset_list_ifname_cmd); - install_element(RIPNG_NODE, &no_ripng_offset_list_cmd); - install_element(RIPNG_NODE, &no_ripng_offset_list_ifname_cmd); + ripng_offset_list_master->del = (void (*)(void *))ripng_offset_list_del; } void ripng_offset_clean(void) @@ -380,45 +174,5 @@ void ripng_offset_clean(void) ripng_offset_list_master = list_new(); ripng_offset_list_master->cmp = (int (*)(void *, void *))offset_list_cmp; - ripng_offset_list_master->del = (void (*)(void *))offset_list_del; -} - -int config_write_ripng_offset_list(struct vty *vty) -{ - struct listnode *node, *nnode; - struct ripng_offset_list *offset; - - for (ALL_LIST_ELEMENTS(ripng_offset_list_master, node, nnode, offset)) { - if (!offset->ifname) { - if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name) - vty_out(vty, " offset-list %s in %d\n", - offset->direct[RIPNG_OFFSET_LIST_IN] - .alist_name, - offset->direct[RIPNG_OFFSET_LIST_IN] - .metric); - if (offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name) - vty_out(vty, " offset-list %s out %d\n", - offset->direct[RIPNG_OFFSET_LIST_OUT] - .alist_name, - offset->direct[RIPNG_OFFSET_LIST_OUT] - .metric); - } else { - if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name) - vty_out(vty, " offset-list %s in %d %s\n", - offset->direct[RIPNG_OFFSET_LIST_IN] - .alist_name, - offset->direct[RIPNG_OFFSET_LIST_IN] - .metric, - offset->ifname); - if (offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name) - vty_out(vty, " offset-list %s out %d %s\n", - offset->direct[RIPNG_OFFSET_LIST_OUT] - .alist_name, - offset->direct[RIPNG_OFFSET_LIST_OUT] - .metric, - offset->ifname); - } - } - - return 0; + ripng_offset_list_master->del = (void (*)(void *))ripng_offset_list_del; } diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index ef32ed19e2..f6aa49f663 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -2524,9 +2524,6 @@ static int ripng_config_write(struct vty *vty) ripng_redistribute_write(vty, 1); - /* RIP offset-list configuration. */ - config_write_ripng_offset_list(vty); - /* RIPng aggregate routes. */ for (rp = agg_route_top(ripng->aggregate); rp; rp = agg_route_next(rp)) diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h index 95a0b25253..fd2ae4ad32 100644 --- a/ripngd/ripngd.h +++ b/ripngd/ripngd.h @@ -325,6 +325,20 @@ enum ripng_event { } \ } while (0) +#define RIPNG_OFFSET_LIST_IN 0 +#define RIPNG_OFFSET_LIST_OUT 1 +#define RIPNG_OFFSET_LIST_MAX 2 + +struct ripng_offset_list { + char *ifname; + + struct { + char *alist_name; + /* struct access_list *alist; */ + uint8_t metric; + } direct[RIPNG_OFFSET_LIST_MAX]; +}; + /* Extern variables. */ extern struct ripng *ripng; extern struct zebra_privs_t ripngd_privs; @@ -350,9 +364,6 @@ extern void ripng_terminate(void); extern void zebra_init(struct thread_master *); extern void ripng_zebra_stop(void); extern void ripng_zclient_reset(void); -extern void ripng_offset_init(void); - -extern int config_write_ripng_offset_list(struct vty *); extern void ripng_peer_init(void); extern void ripng_peer_update(struct sockaddr_in6 *, uint8_t); @@ -362,10 +373,15 @@ extern void ripng_peer_display(struct vty *); extern struct ripng_peer *ripng_peer_lookup(struct in6_addr *); extern struct ripng_peer *ripng_peer_lookup_next(struct in6_addr *); +extern struct ripng_offset_list *ripng_offset_list_new(const char *ifname); +extern void ripng_offset_list_del(struct ripng_offset_list *offset); +extern struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname); +extern struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname); extern int ripng_offset_list_apply_in(struct prefix_ipv6 *, struct interface *, uint8_t *); extern int ripng_offset_list_apply_out(struct prefix_ipv6 *, struct interface *, uint8_t *); +extern void ripng_offset_init(void); extern void ripng_offset_clean(void); extern struct ripng_info *ripng_info_new(void); -- 2.39.5