From 25c780a32a0de196688b3f08e82e6a56d7b49b2f Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sun, 25 Nov 2018 14:41:38 -0200 Subject: [PATCH] lib: make yang_dnode_get_entry() more flexible Add the "abort_if_not_found" parameter to the yang_dnode_get_entry() function instead of always aborting when an user pointer is not found. This will make it possible, for example, to use this function during the validation phase of a configuration transaction. Callers will only need to check if the function returned NULL or not, since new configuration objects (if any) won't be created until the NB_EV_APPLY phase of the transaction. Signed-off-by: Renato Westphal --- lib/if.c | 6 +++--- lib/yang.c | 6 +++++- lib/yang.h | 26 ++++++++++++++++++++++++-- ripd/rip_northbound.c | 36 ++++++++++++++++++------------------ 4 files changed, 50 insertions(+), 24 deletions(-) diff --git a/lib/if.c b/lib/if.c index e02c89b9ac..03a83f4a38 100644 --- a/lib/if.c +++ b/lib/if.c @@ -1338,7 +1338,7 @@ static int lib_interface_delete(enum nb_event event, { struct interface *ifp; - ifp = yang_dnode_get_entry(dnode); + ifp = yang_dnode_get_entry(dnode, true); switch (event) { case NB_EV_VALIDATE: @@ -1372,7 +1372,7 @@ static int lib_interface_description_modify(enum nb_event event, if (event != NB_EV_APPLY) return NB_OK; - ifp = yang_dnode_get_entry(dnode); + ifp = yang_dnode_get_entry(dnode, true); if (ifp->desc) XFREE(MTYPE_TMP, ifp->desc); description = yang_dnode_get_string(dnode, NULL); @@ -1389,7 +1389,7 @@ static int lib_interface_description_delete(enum nb_event event, if (event != NB_EV_APPLY) return NB_OK; - ifp = yang_dnode_get_entry(dnode); + ifp = yang_dnode_get_entry(dnode, true); if (ifp->desc) XFREE(MTYPE_TMP, ifp->desc); diff --git a/lib/yang.c b/lib/yang.c index f41c645758..757982d367 100644 --- a/lib/yang.c +++ b/lib/yang.c @@ -493,7 +493,8 @@ void yang_dnode_set_entry(const struct lyd_node *dnode, void *entry) lyd_set_private(dnode, entry); } -void *yang_dnode_get_entry(const struct lyd_node *dnode) +void *yang_dnode_get_entry(const struct lyd_node *dnode, + bool abort_if_not_found) { const struct lyd_node *orig_dnode = dnode; char xpath[XPATH_MAXLEN]; @@ -512,6 +513,9 @@ void *yang_dnode_get_entry(const struct lyd_node *dnode) dnode = dnode->parent; } + if (!abort_if_not_found) + return NULL; + yang_dnode_get_path(orig_dnode, xpath, sizeof(xpath)); flog_err(EC_LIB_YANG_DNODE_NOT_FOUND, "%s: failed to find entry [xpath %s]", __func__, xpath); diff --git a/lib/yang.h b/lib/yang.h index eac9796df9..c920060071 100644 --- a/lib/yang.h +++ b/lib/yang.h @@ -385,15 +385,37 @@ extern void yang_dnode_change_leaf(struct lyd_node *dnode, const char *value); extern void yang_dnode_set_entry(const struct lyd_node *dnode, void *entry); /* - * Find the closest data node that contains an user pointer and return it. + * Find the user pointer associated to the given libyang data node. + * + * The data node is traversed by following the parent pointers until an user + * pointer is found or until the root node is reached. * * dnode * libyang data node to operate on. * + * abort_if_not_found + * When set to true, abort the program if no user pointer is found. + * + * As a rule of thumb, this parameter should be set to true in the following + * scenarios: + * - Calling this function from any northbound configuration callback during + * the NB_EV_APPLY phase. + * - Calling this function from a 'delete' northbound configuration callback + * during any phase. + * + * In both the above cases, the libyang data node should contain an user + * pointer except when there's a bug in the code, in which case it's better + * to abort the program right away and eliminate the need for unnecessary + * NULL checks. + * + * In all other cases, this parameter should be set to false and the caller + * should check if the function returned NULL or not. + * * Returns: * User pointer if found, NULL otherwise. */ -extern void *yang_dnode_get_entry(const struct lyd_node *dnode); +extern void *yang_dnode_get_entry(const struct lyd_node *dnode, + bool abort_if_not_found); /* * Create a new libyang data node. diff --git a/ripd/rip_northbound.c b/ripd/rip_northbound.c index bb32409a24..d1e298c25c 100644 --- a/ripd/rip_northbound.c +++ b/ripd/rip_northbound.c @@ -188,7 +188,7 @@ static int ripd_instance_distance_source_delete(enum nb_event event, if (event != NB_EV_APPLY) return NB_OK; - rn = yang_dnode_get_entry(dnode); + rn = yang_dnode_get_entry(dnode, true); rdistance = rn->info; if (rdistance->access_list) free(rdistance->access_list); @@ -216,7 +216,7 @@ ripd_instance_distance_source_distance_modify(enum nb_event event, return NB_OK; /* Set distance value. */ - rn = yang_dnode_get_entry(dnode); + rn = yang_dnode_get_entry(dnode, true); distance = yang_dnode_get_uint8(dnode, NULL); rdistance = rn->info; rdistance->distance = distance; @@ -242,7 +242,7 @@ ripd_instance_distance_source_access_list_modify(enum nb_event event, acl_name = yang_dnode_get_string(dnode, NULL); /* Set access-list */ - rn = yang_dnode_get_entry(dnode); + rn = yang_dnode_get_entry(dnode, true); rdistance = rn->info; if (rdistance->access_list) free(rdistance->access_list); @@ -262,7 +262,7 @@ ripd_instance_distance_source_access_list_delete(enum nb_event event, return NB_OK; /* Reset access-list configuration. */ - rn = yang_dnode_get_entry(dnode); + rn = yang_dnode_get_entry(dnode, true); rdistance = rn->info; free(rdistance->access_list); rdistance->access_list = NULL; @@ -396,7 +396,7 @@ static int ripd_instance_offset_list_delete(enum nb_event event, direct = yang_dnode_get_enum(dnode, "./direction"); - offset = yang_dnode_get_entry(dnode); + 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; @@ -426,7 +426,7 @@ ripd_instance_offset_list_access_list_modify(enum nb_event event, direct = yang_dnode_get_enum(dnode, "../direction"); alist_name = yang_dnode_get_string(dnode, NULL); - offset = yang_dnode_get_entry(dnode); + 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); @@ -451,7 +451,7 @@ static int ripd_instance_offset_list_metric_modify(enum nb_event event, direct = yang_dnode_get_enum(dnode, "../direction"); metric = yang_dnode_get_uint8(dnode, NULL); - offset = yang_dnode_get_entry(dnode); + offset = yang_dnode_get_entry(dnode, true); offset->direct[direct].metric = metric; return NB_OK; @@ -791,7 +791,7 @@ static int lib_interface_rip_split_horizon_modify(enum nb_event event, if (event != NB_EV_APPLY) return NB_OK; - ifp = yang_dnode_get_entry(dnode); + ifp = yang_dnode_get_entry(dnode, true); ri = ifp->info; ri->split_horizon = yang_dnode_get_enum(dnode, NULL); @@ -811,7 +811,7 @@ static int lib_interface_rip_v2_broadcast_modify(enum nb_event event, if (event != NB_EV_APPLY) return NB_OK; - ifp = yang_dnode_get_entry(dnode); + ifp = yang_dnode_get_entry(dnode, true); ri = ifp->info; ri->v2_broadcast = yang_dnode_get_bool(dnode, NULL); @@ -832,7 +832,7 @@ lib_interface_rip_version_receive_modify(enum nb_event event, if (event != NB_EV_APPLY) return NB_OK; - ifp = yang_dnode_get_entry(dnode); + ifp = yang_dnode_get_entry(dnode, true); ri = ifp->info; ri->ri_receive = yang_dnode_get_enum(dnode, NULL); @@ -852,7 +852,7 @@ static int lib_interface_rip_version_send_modify(enum nb_event event, if (event != NB_EV_APPLY) return NB_OK; - ifp = yang_dnode_get_entry(dnode); + ifp = yang_dnode_get_entry(dnode, true); ri = ifp->info; ri->ri_send = yang_dnode_get_enum(dnode, NULL); @@ -872,7 +872,7 @@ static int lib_interface_rip_authentication_scheme_mode_modify( if (event != NB_EV_APPLY) return NB_OK; - ifp = yang_dnode_get_entry(dnode); + ifp = yang_dnode_get_entry(dnode, true); ri = ifp->info; ri->auth_type = yang_dnode_get_enum(dnode, NULL); @@ -893,7 +893,7 @@ static int lib_interface_rip_authentication_scheme_md5_auth_length_modify( if (event != NB_EV_APPLY) return NB_OK; - ifp = yang_dnode_get_entry(dnode); + ifp = yang_dnode_get_entry(dnode, true); ri = ifp->info; ri->md5_auth_len = yang_dnode_get_enum(dnode, NULL); @@ -909,7 +909,7 @@ static int lib_interface_rip_authentication_scheme_md5_auth_length_delete( if (event != NB_EV_APPLY) return NB_OK; - ifp = yang_dnode_get_entry(dnode); + ifp = yang_dnode_get_entry(dnode, true); ri = ifp->info; ri->md5_auth_len = yang_get_default_enum( "%s/authentication-scheme/md5-auth-length", RIP_IFACE); @@ -931,7 +931,7 @@ lib_interface_rip_authentication_password_modify(enum nb_event event, if (event != NB_EV_APPLY) return NB_OK; - ifp = yang_dnode_get_entry(dnode); + ifp = yang_dnode_get_entry(dnode, true); ri = ifp->info; if (ri->auth_str) XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str); @@ -951,7 +951,7 @@ lib_interface_rip_authentication_password_delete(enum nb_event event, if (event != NB_EV_APPLY) return NB_OK; - ifp = yang_dnode_get_entry(dnode); + ifp = yang_dnode_get_entry(dnode, true); ri = ifp->info; XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str); @@ -972,7 +972,7 @@ lib_interface_rip_authentication_key_chain_modify(enum nb_event event, if (event != NB_EV_APPLY) return NB_OK; - ifp = yang_dnode_get_entry(dnode); + ifp = yang_dnode_get_entry(dnode, true); ri = ifp->info; if (ri->key_chain) XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain); @@ -992,7 +992,7 @@ lib_interface_rip_authentication_key_chain_delete(enum nb_event event, if (event != NB_EV_APPLY) return NB_OK; - ifp = yang_dnode_get_entry(dnode); + ifp = yang_dnode_get_entry(dnode, true); ri = ifp->info; XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain); -- 2.39.5