diff options
| -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 a22f3054a6..10db5d967e 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 2a05405924..16ed784513 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 498aa322cb..bdad4004d3 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 d2065a4bbb..418ec3fc7b 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 027ad878bb..24bbf226b0 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 9bd9f53f22..4378f75af4 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; |
