Merge pull request #8311 from idryzhov/nb-sorting

Sort route-maps/access-lists/prefix-lists by sequence number in running-config
This commit is contained in:
Russ White 2021-03-30 10:37:31 -04:00 committed by GitHub
commit fb7c845e0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 109 additions and 53 deletions

View File

@ -240,10 +240,12 @@ bool plist_is_dup(const struct lyd_node *dnode, struct plist_dup_args *pda);
struct lyd_node;
struct vty;
extern int access_list_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2);
extern void access_list_show(struct vty *vty, struct lyd_node *dnode,
bool show_defaults);
extern void access_list_remark_show(struct vty *vty, struct lyd_node *dnode,
bool show_defaults);
extern int prefix_list_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2);
extern void prefix_list_show(struct vty *vty, struct lyd_node *dnode,
bool show_defaults);
extern void prefix_list_remark_show(struct vty *vty, struct lyd_node *dnode,

View File

@ -1077,6 +1077,14 @@ ALIAS(
ACCESS_LIST_REMARK_STR
ACCESS_LIST_REMARK_LINE_STR)
int access_list_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2)
{
uint32_t seq1 = yang_dnode_get_uint32(dnode1, "./sequence");
uint32_t seq2 = yang_dnode_get_uint32(dnode2, "./sequence");
return seq1 - seq2;
}
void access_list_show(struct vty *vty, struct lyd_node *dnode,
bool show_defaults)
{
@ -1700,6 +1708,14 @@ ALIAS(
ACCESS_LIST_REMARK_STR
ACCESS_LIST_REMARK_LINE_STR)
int prefix_list_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2)
{
uint32_t seq1 = yang_dnode_get_uint32(dnode1, "./sequence");
uint32_t seq2 = yang_dnode_get_uint32(dnode2, "./sequence");
return seq1 - seq2;
}
void prefix_list_show(struct vty *vty, struct lyd_node *dnode,
bool show_defaults)
{

View File

@ -1665,6 +1665,7 @@ const struct frr_yang_module_info frr_filter_info = {
.cbs = {
.create = lib_access_list_entry_create,
.destroy = lib_access_list_entry_destroy,
.cli_cmp = access_list_cmp,
.cli_show = access_list_show,
}
},
@ -1788,6 +1789,7 @@ const struct frr_yang_module_info frr_filter_info = {
.cbs = {
.create = lib_prefix_list_entry_create,
.destroy = lib_prefix_list_entry_destroy,
.cli_cmp = prefix_list_cmp,
.cli_show = prefix_list_show,
}
},

View File

@ -473,6 +473,23 @@ struct nb_callbacks {
*/
int (*rpc)(struct nb_cb_rpc_args *args);
/*
* Optional callback to compare the data nodes when printing
* the CLI commands associated with them.
*
* dnode1
* The first data node to compare.
*
* dnode2
* The second data node to compare.
*
* Returns:
* <0 when the CLI command for the dnode1 should be printed first
* >0 when the CLI command for the dnode2 should be printed first
* 0 when there is no difference
*/
int (*cli_cmp)(struct lyd_node *dnode1, struct lyd_node *dnode2);
/*
* Optional callback to show the CLI command associated to the given
* YANG data node.

View File

@ -529,25 +529,6 @@ static int nb_cli_candidate_load_transaction(struct vty *vty,
return CMD_SUCCESS;
}
/*
* ly_iter_next_is_up: detects when iterating up on the yang model.
*
* This function detects whether next node in the iteration is upwards,
* then return the node otherwise return NULL.
*/
static struct lyd_node *ly_iter_next_up(const struct lyd_node *elem)
{
/* Are we going downwards? Is this still not a leaf? */
if (!(elem->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)))
return NULL;
/* Are there still leaves in this branch? */
if (elem->next != NULL)
return NULL;
return elem->parent;
}
/* Prepare the configuration for display. */
void nb_cli_show_config_prepare(struct nb_config *config, bool with_defaults)
{
@ -569,51 +550,78 @@ void nb_cli_show_config_prepare(struct nb_config *config, bool with_defaults)
ly_native_ctx);
}
void nb_cli_show_dnode_cmds(struct vty *vty, struct lyd_node *root,
bool with_defaults)
static void show_dnode_children_cmds(struct vty *vty, struct lyd_node *root,
bool with_defaults)
{
struct lyd_node *next, *child, *parent;
LY_TREE_DFS_BEGIN (root, next, child) {
struct nb_node *nb_node;
struct nb_node *nb_node, *sort_node = NULL;
struct listnode *listnode;
struct lyd_node *child;
struct list *sort_list;
void *data;
LY_TREE_FOR (root->child, child) {
nb_node = child->schema->priv;
if (!nb_node || !nb_node->cbs.cli_show)
goto next;
/* Skip default values. */
if (!with_defaults && yang_dnode_is_default_recursive(child))
goto next;
(*nb_node->cbs.cli_show)(vty, child, with_defaults);
next:
/*
* When transiting upwards in the yang model we should
* give the previous container/list node a chance to
* print its close vty output (e.g. "!" or "end-family"
* etc...).
* We finished processing current list,
* it's time to print the config.
*/
parent = ly_iter_next_up(child);
if (parent != NULL) {
nb_node = parent->schema->priv;
if (nb_node && nb_node->cbs.cli_show_end)
(*nb_node->cbs.cli_show_end)(vty, parent);
if (sort_node && nb_node != sort_node) {
for (ALL_LIST_ELEMENTS_RO(sort_list, listnode, data))
nb_cli_show_dnode_cmds(vty, data,
with_defaults);
list_delete(&sort_list);
sort_node = NULL;
}
/*
* There is a possible path in this macro that ends up
* dereferencing child->parent->parent. We just null checked
* child->parent by checking (ly_iter_next_up(child) != NULL)
* above.
*
* I am not sure whether it is possible for the other
* conditions within this macro guarding the problem
* dereference to be satisfied when child->parent == NULL.
* If the config needs to be sorted,
* then add the dnode to the sorting
* list for later processing.
*/
#ifndef __clang_analyzer__
LY_TREE_DFS_END(root, next, child);
#endif
if (nb_node && nb_node->cbs.cli_cmp) {
if (!sort_node) {
sort_node = nb_node;
sort_list = list_new();
sort_list->cmp = (int (*)(void *, void *))
nb_node->cbs.cli_cmp;
}
listnode_add_sort(sort_list, child);
continue;
}
nb_cli_show_dnode_cmds(vty, child, with_defaults);
}
if (sort_node) {
for (ALL_LIST_ELEMENTS_RO(sort_list, listnode, data))
nb_cli_show_dnode_cmds(vty, data, with_defaults);
list_delete(&sort_list);
sort_node = NULL;
}
}
void nb_cli_show_dnode_cmds(struct vty *vty, struct lyd_node *root,
bool with_defaults)
{
struct nb_node *nb_node;
if (!with_defaults && yang_dnode_is_default_recursive(root))
return;
nb_node = root->schema->priv;
if (nb_node && nb_node->cbs.cli_show)
(*nb_node->cbs.cli_show)(vty, root, with_defaults);
if (!(root->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)))
show_dnode_children_cmds(vty, root, with_defaults);
if (nb_node && nb_node->cbs.cli_show_end)
(*nb_node->cbs.cli_show_end)(vty, root);
}
static void nb_cli_show_config_cmds(struct vty *vty, struct nb_config *config,

View File

@ -694,6 +694,8 @@ void routemap_hook_context_free(struct routemap_hook_context *rhc);
extern const struct frr_yang_module_info frr_route_map_info;
/* routemap_cli.c */
extern int route_map_instance_cmp(struct lyd_node *dnode1,
struct lyd_node *dnode2);
extern void route_map_instance_show(struct vty *vty, struct lyd_node *dnode,
bool show_defaults);
extern void route_map_instance_show_end(struct vty *vty,

View File

@ -113,6 +113,14 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
int route_map_instance_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2)
{
uint16_t seq1 = yang_dnode_get_uint16(dnode1, "./sequence");
uint16_t seq2 = yang_dnode_get_uint16(dnode2, "./sequence");
return seq1 - seq2;
}
void route_map_instance_show(struct vty *vty, struct lyd_node *dnode,
bool show_defaults)
{

View File

@ -1140,6 +1140,7 @@ const struct frr_yang_module_info frr_route_map_info = {
.cbs = {
.create = lib_route_map_entry_create,
.destroy = lib_route_map_entry_destroy,
.cli_cmp = route_map_instance_cmp,
.cli_show = route_map_instance_show,
.cli_show_end = route_map_instance_show_end,
}