From 3c08c6fe28e2345999cdeb3c8cba2ac8903faa8b Mon Sep 17 00:00:00 2001 From: Christian Hopps Date: Tue, 11 Feb 2025 07:12:06 +0000 Subject: [PATCH] lib: nb: call child destroy CBs when YANG container is deleted Previously the code was only calling the child destroy callbacks if the target deleted node was a non-presence container. We now add a flag to the callback structure to instruct northbound to perform the rescursive delete for code that wishes for this to happen. - Fix wrong relative path lookup in keychain destroy callback Signed-off-by: Christian Hopps (cherry picked from commit d03ecf4562ef3ade6b7b83bf6c683c4741f395ba) --- lib/keychain_nb.c | 4 ++-- lib/northbound.c | 29 +++++++++++++++++++++-------- lib/northbound.h | 11 +++++++++++ 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/lib/keychain_nb.c b/lib/keychain_nb.c index 57967b30a5..7c3df1c857 100644 --- a/lib/keychain_nb.c +++ b/lib/keychain_nb.c @@ -587,9 +587,9 @@ static int key_chains_key_chain_key_crypto_algorithm_destroy( if (args->event != NB_EV_APPLY) return NB_OK; - name = yang_dnode_get_string(args->dnode, "../../../name"); + name = yang_dnode_get_string(args->dnode, "../../name"); keychain = keychain_lookup(name); - index = (uint32_t)yang_dnode_get_uint64(args->dnode, "../../key-id"); + index = (uint32_t)yang_dnode_get_uint64(args->dnode, "../key-id"); key = key_lookup(keychain, index); key->hash_algo = KEYCHAIN_ALGO_NULL; keychain_touch(keychain); diff --git a/lib/northbound.c b/lib/northbound.c index 60794b8728..ad9e517d52 100644 --- a/lib/northbound.c +++ b/lib/northbound.c @@ -516,20 +516,33 @@ void nb_config_diff_created(const struct lyd_node *dnode, uint32_t *seq, static void nb_config_diff_deleted(const struct lyd_node *dnode, uint32_t *seq, struct nb_config_cbs *changes) { + struct nb_node *nb_node = dnode->schema->priv; + struct lyd_node *child; + bool recursed = false; + /* Ignore unimplemented nodes. */ - if (!dnode->schema->priv) + if (!nb_node) return; + /* + * If the CB structure indicates it (recurse flag set), call the destroy + * callbacks for the children of a containment node. + */ + if (CHECK_FLAG(dnode->schema->nodetype, LYS_CONTAINER | LYS_LIST) && + CHECK_FLAG(nb_node->cbs.flags, F_NB_CB_DESTROY_RECURSE)) { + recursed = true; + LY_LIST_FOR (lyd_child(dnode), child) { + nb_config_diff_deleted(child, seq, changes); + } + } + if (nb_cb_operation_is_valid(NB_CB_DESTROY, dnode->schema)) nb_config_diff_add_change(changes, NB_CB_DESTROY, seq, dnode); - else if (CHECK_FLAG(dnode->schema->nodetype, LYS_CONTAINER)) { - struct lyd_node *child; - + else if (CHECK_FLAG(dnode->schema->nodetype, LYS_CONTAINER) && !recursed) { /* - * Non-presence containers need special handling since they - * don't have "destroy" callbacks. In this case, what we need to - * do is to call the "destroy" callbacks of their child nodes - * when applicable (i.e. optional nodes). + * If we didn't already above, call destroy on the children of + * this container (it's an NP container) as NP containers have + * no destroy CB themselves. */ LY_LIST_FOR (lyd_child(dnode), child) { nb_config_diff_deleted(child, seq, changes); diff --git a/lib/northbound.h b/lib/northbound.h index c31f007e70..7d38c63a86 100644 --- a/lib/northbound.h +++ b/lib/northbound.h @@ -385,6 +385,11 @@ struct nb_callbacks { */ int (*destroy)(struct nb_cb_destroy_args *args); + /* + * Flags to control the how northbound callbacks are invoked. + */ + uint flags; + /* * Configuration callback. * @@ -622,6 +627,12 @@ struct nb_callbacks { void (*cli_show_end)(struct vty *vty, const struct lyd_node *dnode); }; +/* + * Flag indicating the northbound should recurse destroy the children of this + * node when it is destroyed. + */ +#define F_NB_CB_DESTROY_RECURSE 0x01 + struct nb_dependency_callbacks { void (*get_dependant_xpath)(const struct lyd_node *dnode, char *xpath); void (*get_dependency_xpath)(const struct lyd_node *dnode, char *xpath); -- 2.39.5