diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/filter.c | 12 | ||||
| -rw-r--r-- | lib/filter.h | 5 | ||||
| -rw-r--r-- | lib/filter_cli.c | 257 | ||||
| -rw-r--r-- | lib/filter_nb.c | 32 | ||||
| -rw-r--r-- | lib/routemap.c | 12 | ||||
| -rw-r--r-- | lib/routemap.h | 2 | ||||
| -rw-r--r-- | lib/routemap_northbound.c | 42 | ||||
| -rw-r--r-- | lib/vty.c | 6 | ||||
| -rw-r--r-- | lib/yang.c | 24 | ||||
| -rw-r--r-- | lib/yang.h | 15 |
10 files changed, 224 insertions, 183 deletions
diff --git a/lib/filter.c b/lib/filter.c index f86adab5d6..a0adff0e35 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -885,7 +885,7 @@ static void access_list_init_ipv6(void) install_element(ENABLE_NODE, &show_ipv6_access_list_name_cmd); } -void access_list_init(void) +void access_list_init_new(bool in_backend) { cmd_variable_handler_register(access_list_handlers); @@ -893,7 +893,15 @@ void access_list_init(void) access_list_init_ipv6(); access_list_init_mac(); - filter_cli_init(); + if (!in_backend) { + /* we do not want to handle config commands in the backend */ + filter_cli_init(); + } +} + +void access_list_init(void) +{ + access_list_init_new(false); } void access_list_reset(void) diff --git a/lib/filter.h b/lib/filter.h index e092f0771a..bd9e22d384 100644 --- a/lib/filter.h +++ b/lib/filter.h @@ -114,6 +114,7 @@ struct access_master { /* Prototypes for access-list. */ extern void access_list_init(void); +extern void access_list_init_new(bool in_backend); extern void access_list_reset(void); extern void access_list_add_hook(void (*func)(struct access_list *)); extern void access_list_delete_hook(void (*func)(struct access_list *)); @@ -124,13 +125,13 @@ extern enum filter_type access_list_apply(struct access_list *access, struct access_list *access_list_get(afi_t afi, const char *name); void access_list_delete(struct access_list *access); struct filter *filter_new(void); -void access_list_filter_add(struct access_list *access, - struct filter *filter); +void access_list_filter_add(struct access_list *access, struct filter *filter); void access_list_filter_delete(struct access_list *access, struct filter *filter); int64_t filter_new_seq_get(struct access_list *access); extern const struct frr_yang_module_info frr_filter_info; +extern const struct frr_yang_module_info frr_filter_cli_info; /* filter_nb.c */ diff --git a/lib/filter_cli.c b/lib/filter_cli.c index 529b46b6ad..28790f69e7 100644 --- a/lib/filter_cli.c +++ b/lib/filter_cli.c @@ -69,53 +69,60 @@ static int64_t acl_get_seq(struct vty *vty, const char *xpath, bool is_remove) return seq; } -static int acl_remove_if_empty(struct vty *vty, const char *iptype, - const char *name) +/** + * Remove main data structure filter list if there are no more entries or + * remark. This fixes compatibility with old CLI and tests. + */ +static int filter_remove_check_empty(struct vty *vty, const char *ftype, + const char *iptype, const char *name, + uint32_t del_seq, bool del_remark) { + const struct lyd_node *remark_dnode = NULL; + const struct lyd_node *entry_dnode = NULL; char xpath[XPATH_MAXLEN]; + uint32_t count; + + /* Count existing entries */ + count = yang_dnode_count(vty->candidate_config->dnode, + "/frr-filter:lib/%s-list[type='%s'][name='%s']/entry", + ftype, iptype, name); + + /* Check entry-to-delete actually exists */ + if (del_seq) { + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/%s-list[type='%s'][name='%s']/entry[sequence='%u']", + ftype, iptype, name, del_seq); + entry_dnode = yang_dnode_get(vty->candidate_config->dnode, + xpath); + + /* If exists, delete and don't count it, we need only remaining entries */ + if (entry_dnode) { + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + count--; + } + } + /* Delete the remark, or check whether it exists if we're keeping it */ snprintf(xpath, sizeof(xpath), - "/frr-filter:lib/access-list[type='%s'][name='%s']/remark", + "/frr-filter:lib/%s-list[type='%s'][name='%s']/remark", ftype, iptype, name); - /* List is not empty if there is a remark, check that: */ - if (yang_dnode_exists(vty->candidate_config->dnode, xpath)) - return CMD_SUCCESS; - - /* Check if we have any entries: */ - snprintf(xpath, sizeof(xpath), - "/frr-filter:lib/access-list[type='%s'][name='%s']", iptype, - name); - /* - * NOTE: if the list is empty it will return the first sequence - * number: 5. - */ - if (acl_get_seq(vty, xpath, true) != 5) - return CMD_SUCCESS; + if (del_remark) + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + else + remark_dnode = yang_dnode_get(vty->candidate_config->dnode, + xpath); + + /* If there are no entries left and no remark, delete the whole list */ + if (count == 0 && !remark_dnode) { + snprintf(xpath, sizeof(xpath), + "/frr-filter:lib/%s-list[type='%s'][name='%s']", ftype, + iptype, name); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + } - /* Nobody is using this list, lets remove it. */ - nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); return nb_cli_apply_changes(vty, NULL); } -static int acl_remove(struct vty *vty, const char *iptype, const char *name, - int64_t sseq) -{ - char xpath[XPATH_MAXLEN]; - int rv; - - snprintfrr( - xpath, sizeof(xpath), - "/frr-filter:lib/access-list[type='%s'][name='%s']/entry[sequence='%" PRId64 "']", - iptype, name, sseq); - nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); - - rv = nb_cli_apply_changes(vty, NULL); - if (rv == CMD_SUCCESS) - return acl_remove_if_empty(vty, iptype, name); - - return rv; -} - /* * Cisco (legacy) access lists. */ @@ -213,7 +220,8 @@ DEFPY_YANG( /* If the user provided sequence number, then just go for it. */ if (seq_str != NULL) - return acl_remove(vty, "ipv4", name, seq); + return filter_remove_check_empty(vty, "access", "ipv4", name, + seq, false); /* Otherwise, to keep compatibility, we need to figure it out. */ ada.ada_type = "ipv4"; @@ -237,7 +245,8 @@ DEFPY_YANG( else return CMD_WARNING_CONFIG_FAILED; - return acl_remove(vty, "ipv4", name, sseq); + return filter_remove_check_empty(vty, "access", "ipv4", name, sseq, + false); } DEFPY_YANG( @@ -384,7 +393,8 @@ DEFPY_YANG( /* If the user provided sequence number, then just go for it. */ if (seq_str != NULL) - return acl_remove(vty, "ipv4", name, seq); + return filter_remove_check_empty(vty, "access", "ipv4", name, + seq, false); /* Otherwise, to keep compatibility, we need to figure it out. */ ada.ada_type = "ipv4"; @@ -429,7 +439,8 @@ DEFPY_YANG( else return CMD_WARNING_CONFIG_FAILED; - return acl_remove(vty, "ipv4", name, sseq); + return filter_remove_check_empty(vty, "access", "ipv4", name, sseq, + false); } /* @@ -525,7 +536,8 @@ DEFPY_YANG( /* If the user provided sequence number, then just go for it. */ if (seq_str != NULL) - return acl_remove(vty, "ipv4", name, seq); + return filter_remove_check_empty(vty, "access", "ipv4", name, + seq, false); /* Otherwise, to keep compatibility, we need to figure it out. */ ada.ada_type = "ipv4"; @@ -549,7 +561,8 @@ DEFPY_YANG( else return CMD_WARNING_CONFIG_FAILED; - return acl_remove(vty, "ipv4", name, sseq); + return filter_remove_check_empty(vty, "access", "ipv4", name, sseq, + false); } DEFPY_YANG( @@ -600,19 +613,7 @@ DEFPY_YANG( ACCESS_LIST_ZEBRA_STR ACCESS_LIST_REMARK_STR) { - char xpath[XPATH_MAXLEN]; - int rv; - - snprintf(xpath, sizeof(xpath), - "/frr-filter:lib/access-list[type='ipv4'][name='%s']/remark", - name); - nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); - - rv = nb_cli_apply_changes(vty, NULL); - if (rv == CMD_SUCCESS) - return acl_remove_if_empty(vty, "ipv4", name); - - return rv; + return filter_remove_check_empty(vty, "access", "ipv4", name, 0, true); } ALIAS( @@ -716,7 +717,8 @@ DEFPY_YANG( /* If the user provided sequence number, then just go for it. */ if (seq_str != NULL) - return acl_remove(vty, "ipv6", name, seq); + return filter_remove_check_empty(vty, "access", "ipv6", name, + seq, false); /* Otherwise, to keep compatibility, we need to figure it out. */ ada.ada_type = "ipv6"; @@ -740,7 +742,8 @@ DEFPY_YANG( else return CMD_WARNING_CONFIG_FAILED; - return acl_remove(vty, "ipv6", name, sseq); + return filter_remove_check_empty(vty, "access", "ipv6", name, sseq, + false); } DEFPY_YANG( @@ -794,19 +797,7 @@ DEFPY_YANG( ACCESS_LIST_ZEBRA_STR ACCESS_LIST_REMARK_STR) { - char xpath[XPATH_MAXLEN]; - int rv; - - snprintf(xpath, sizeof(xpath), - "/frr-filter:lib/access-list[type='ipv6'][name='%s']/remark", - name); - nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); - - rv = nb_cli_apply_changes(vty, NULL); - if (rv == CMD_SUCCESS) - return acl_remove_if_empty(vty, "ipv6", name); - - return rv; + return filter_remove_check_empty(vty, "access", "ipv6", name, 0, true); } ALIAS( @@ -902,7 +893,8 @@ DEFPY_YANG( /* If the user provided sequence number, then just go for it. */ if (seq_str != NULL) - return acl_remove(vty, "mac", name, seq); + return filter_remove_check_empty(vty, "access", "mac", name, + seq, false); /* Otherwise, to keep compatibility, we need to figure it out. */ ada.ada_type = "mac"; @@ -922,7 +914,8 @@ DEFPY_YANG( else return CMD_WARNING_CONFIG_FAILED; - return acl_remove(vty, "mac", name, sseq); + return filter_remove_check_empty(vty, "access", "mac", name, sseq, + false); } DEFPY_YANG( @@ -976,19 +969,7 @@ DEFPY_YANG( ACCESS_LIST_ZEBRA_STR ACCESS_LIST_REMARK_STR) { - char xpath[XPATH_MAXLEN]; - int rv; - - snprintf(xpath, sizeof(xpath), - "/frr-filter:lib/access-list[type='mac'][name='%s']/remark", - name); - nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); - - rv = nb_cli_apply_changes(vty, NULL); - if (rv == CMD_SUCCESS) - return acl_remove_if_empty(vty, "mac", name); - - return rv; + return filter_remove_check_empty(vty, "access", "mac", name, 0, true); } ALIAS( @@ -1149,62 +1130,17 @@ void access_list_remark_show(struct vty *vty, const struct lyd_node *dnode, * Prefix lists. */ -/** - * Remove main data structure prefix list if there are no more entries or - * remark. This fixes compatibility with old CLI and tests. - */ -static int plist_remove_if_empty(struct vty *vty, const char *iptype, - const char *name) -{ - char xpath[XPATH_MAXLEN]; - - snprintf(xpath, sizeof(xpath), - "/frr-filter:lib/prefix-list[type='%s'][name='%s']/remark", - iptype, name); - /* List is not empty if there is a remark, check that: */ - if (yang_dnode_exists(vty->candidate_config->dnode, xpath)) - return CMD_SUCCESS; - - /* Check if we have any entries: */ - snprintf(xpath, sizeof(xpath), - "/frr-filter:lib/prefix-list[type='%s'][name='%s']", iptype, - name); - /* - * NOTE: if the list is empty it will return the first sequence - * number: 5. - */ - if (acl_get_seq(vty, xpath, true) != 5) - return CMD_SUCCESS; - - /* Nobody is using this list, lets remove it. */ - nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); - return nb_cli_apply_changes(vty, NULL); -} - static int plist_remove(struct vty *vty, const char *iptype, const char *name, - const char *seq, const char *action, + uint32_t seq, const char *action, union prefixconstptr prefix, int ge, int le) { int64_t sseq; struct plist_dup_args pda = {}; - char xpath[XPATH_MAXLEN]; - char xpath_entry[XPATH_MAXLEN + 32]; - int rv; /* If the user provided sequence number, then just go for it. */ - if (seq != NULL) { - snprintf( - xpath, sizeof(xpath), - "/frr-filter:lib/prefix-list[type='%s'][name='%s']/entry[sequence='%s']", - iptype, name, seq); - nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); - - rv = nb_cli_apply_changes(vty, NULL); - if (rv == CMD_SUCCESS) - return plist_remove_if_empty(vty, iptype, name); - - return rv; - } + if (seq != 0) + return filter_remove_check_empty(vty, "prefix", iptype, name, + seq, false); /* Otherwise, to keep compatibility, we need to figure it out. */ pda.pda_type = iptype; @@ -1224,17 +1160,8 @@ static int plist_remove(struct vty *vty, const char *iptype, const char *name, else return CMD_WARNING_CONFIG_FAILED; - snprintfrr( - xpath_entry, sizeof(xpath_entry), - "/frr-filter:lib/prefix-list[type='%s'][name='%s']/entry[sequence='%" PRId64 "']", - iptype, name, sseq); - nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL); - - rv = nb_cli_apply_changes(vty, NULL); - if (rv == CMD_SUCCESS) - return plist_remove_if_empty(vty, iptype, name); - - return rv; + return filter_remove_check_empty(vty, "prefix", iptype, name, sseq, + false); } DEFPY_YANG( @@ -1347,7 +1274,7 @@ DEFPY_YANG( "Maximum prefix length to be matched\n" "Maximum prefix length\n") { - return plist_remove(vty, "ipv4", name, seq_str, action, + return plist_remove(vty, "ipv4", name, seq, action, prefix_str ? prefix : NULL, ge, le); } @@ -1360,7 +1287,7 @@ DEFPY_YANG( PREFIX_LIST_NAME_STR ACCESS_LIST_SEQ_STR) { - return plist_remove(vty, "ipv4", name, seq_str, NULL, NULL, 0, 0); + return plist_remove(vty, "ipv4", name, seq, NULL, NULL, 0, 0); } DEFPY_YANG( @@ -1414,19 +1341,7 @@ DEFPY_YANG( PREFIX_LIST_NAME_STR ACCESS_LIST_REMARK_STR) { - char xpath[XPATH_MAXLEN]; - int rv; - - snprintf(xpath, sizeof(xpath), - "/frr-filter:lib/prefix-list[type='ipv4'][name='%s']/remark", - name); - nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); - - rv = nb_cli_apply_changes(vty, NULL); - if (rv == CMD_SUCCESS) - return plist_remove_if_empty(vty, "ipv4", name); - - return rv; + return filter_remove_check_empty(vty, "prefix", "ipv4", name, 0, true); } ALIAS( @@ -1549,7 +1464,7 @@ DEFPY_YANG( "Minimum prefix length to be matched\n" "Minimum prefix length\n") { - return plist_remove(vty, "ipv6", name, seq_str, action, + return plist_remove(vty, "ipv6", name, seq, action, prefix_str ? prefix : NULL, ge, le); } @@ -1562,7 +1477,7 @@ DEFPY_YANG( PREFIX_LIST_NAME_STR ACCESS_LIST_SEQ_STR) { - return plist_remove(vty, "ipv6", name, seq_str, NULL, NULL, 0, 0); + return plist_remove(vty, "ipv6", name, seq, NULL, NULL, 0, 0); } DEFPY_YANG( @@ -1616,19 +1531,7 @@ DEFPY_YANG( PREFIX_LIST_NAME_STR ACCESS_LIST_REMARK_STR) { - char xpath[XPATH_MAXLEN]; - int rv; - - snprintf(xpath, sizeof(xpath), - "/frr-filter:lib/prefix-list[type='ipv6'][name='%s']/remark", - name); - nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); - - rv = nb_cli_apply_changes(vty, NULL); - if (rv == CMD_SUCCESS) - return plist_remove_if_empty(vty, "ipv6", name); - - return rv; + return filter_remove_check_empty(vty, "prefix", "ipv6", name, 0, true); } ALIAS( diff --git a/lib/filter_nb.c b/lib/filter_nb.c index 1c436cc6f1..eba4e421c0 100644 --- a/lib/filter_nb.c +++ b/lib/filter_nb.c @@ -1785,3 +1785,35 @@ const struct frr_yang_module_info frr_filter_info = { }, } }; + +const struct frr_yang_module_info frr_filter_cli_info = { + .name = "frr-filter", + .ignore_cfg_cbs = true, + .nodes = { + { + .xpath = "/frr-filter:lib/access-list/remark", + .cbs.cli_show = access_list_remark_show, + }, + { + .xpath = "/frr-filter:lib/access-list/entry", + .cbs = { + .cli_cmp = access_list_cmp, + .cli_show = access_list_show, + } + }, + { + .xpath = "/frr-filter:lib/prefix-list/remark", + .cbs.cli_show = prefix_list_remark_show, + }, + { + .xpath = "/frr-filter:lib/prefix-list/entry", + .cbs = { + .cli_cmp = prefix_list_cmp, + .cli_show = prefix_list_show, + } + }, + { + .xpath = NULL, + }, + } +}; diff --git a/lib/routemap.c b/lib/routemap.c index e8a92cda0b..6b3f81b4d4 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -3409,7 +3409,7 @@ DEFUN_HIDDEN(show_route_map_pfx_tbl, show_route_map_pfx_tbl_cmd, } /* Initialization of route map vector. */ -void route_map_init(void) +void route_map_init_new(bool in_backend) { int i; @@ -3424,7 +3424,10 @@ void route_map_init(void) UNSET_FLAG(rmap_debug, DEBUG_ROUTEMAP); - route_map_cli_init(); + if (!in_backend) { + /* we do not want to handle config commands in the backend */ + route_map_cli_init(); + } /* Install route map top node. */ install_node(&rmap_debug_node); @@ -3444,3 +3447,8 @@ void route_map_init(void) install_element(ENABLE_NODE, &show_route_map_pfx_tbl_cmd); } + +void route_map_init(void) +{ + route_map_init_new(false); +} diff --git a/lib/routemap.h b/lib/routemap.h index 08e341221d..dfb84ced5b 100644 --- a/lib/routemap.h +++ b/lib/routemap.h @@ -401,6 +401,7 @@ enum ecommunity_lb_type { /* Prototypes. */ extern void route_map_init(void); +extern void route_map_init_new(bool in_backend); /* * This should only be called on shutdown @@ -1024,6 +1025,7 @@ routemap_hook_context_insert(struct route_map_index *rmi); void routemap_hook_context_free(struct routemap_hook_context *rhc); extern const struct frr_yang_module_info frr_route_map_info; +extern const struct frr_yang_module_info frr_route_map_cli_info; /* routemap_cli.c */ extern int route_map_instance_cmp(const struct lyd_node *dnode1, diff --git a/lib/routemap_northbound.c b/lib/routemap_northbound.c index a7a77cc23b..1bba4dad47 100644 --- a/lib/routemap_northbound.c +++ b/lib/routemap_northbound.c @@ -1550,3 +1550,45 @@ const struct frr_yang_module_info frr_route_map_info = { }, } }; + +const struct frr_yang_module_info frr_route_map_cli_info = { + .name = "frr-route-map", + .ignore_cfg_cbs = true, + .nodes = { + { + .xpath = "/frr-route-map:lib/route-map/optimization-disabled", + .cbs.cli_show = route_map_optimization_disabled_show, + }, + { + .xpath = "/frr-route-map:lib/route-map/entry", + .cbs = { + .cli_cmp = route_map_instance_cmp, + .cli_show = route_map_instance_show, + .cli_show_end = route_map_instance_show_end, + } + }, + { + .xpath = "/frr-route-map:lib/route-map/entry/description", + .cbs.cli_show = route_map_description_show, + }, + { + .xpath = "/frr-route-map:lib/route-map/entry/call", + .cbs.cli_show = route_map_call_show, + }, + { + .xpath = "/frr-route-map:lib/route-map/entry/exit-policy", + .cbs.cli_show = route_map_exit_policy_show, + }, + { + .xpath = "/frr-route-map:lib/route-map/entry/match-condition", + .cbs.cli_show = route_map_condition_show, + }, + { + .xpath = "/frr-route-map:lib/route-map/entry/set-action", + .cbs.cli_show = route_map_action_show, + }, + { + .xpath = NULL, + }, + } +}; @@ -124,6 +124,12 @@ bool vty_log_commands; static bool vty_log_commands_perm; char const *const mgmt_daemons[] = { +#ifdef HAVE_RIPD + "ripd", +#endif +#ifdef HAVE_RIPNGD + "ripngd", +#endif #ifdef HAVE_STATICD "staticd", #endif diff --git a/lib/yang.c b/lib/yang.c index 7d35fb0d3d..ed855c8498 100644 --- a/lib/yang.c +++ b/lib/yang.c @@ -508,6 +508,30 @@ void yang_dnode_iterate(yang_dnode_iter_cb cb, void *arg, ly_set_free(set, NULL); } +uint32_t yang_dnode_count(const struct lyd_node *dnode, const char *xpath_fmt, + ...) +{ + va_list ap; + char xpath[XPATH_MAXLEN]; + struct ly_set *set; + uint32_t count; + + va_start(ap, xpath_fmt); + vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); + va_end(ap); + + if (lyd_find_xpath(dnode, xpath, &set)) { + assert(0); + return 0; + } + + count = set->count; + + ly_set_free(set, NULL); + + return count; +} + bool yang_dnode_is_default(const struct lyd_node *dnode, const char *xpath) { const struct lysc_node *snode; diff --git a/lib/yang.h b/lib/yang.h index dbb7f7163b..1235125f26 100644 --- a/lib/yang.h +++ b/lib/yang.h @@ -421,6 +421,21 @@ void yang_dnode_iterate(yang_dnode_iter_cb cb, void *arg, ...) PRINTFRR(4, 5); /* + * Count the number of data nodes that satisfy an XPath query. + * + * dnode + * Base libyang data node to operate on. + * + * xpath_fmt + * XPath expression (absolute or relative). + * + * ... + * any parameters for xpath_fmt. + */ +uint32_t yang_dnode_count(const struct lyd_node *dnode, const char *xpath_fmt, + ...) PRINTFRR(2, 3); + +/* * Check if the libyang data node contains a default value. Non-presence * containers are assumed to always contain a default value. * |
