diff options
| author | Quentin Young <qlyoung@cumulusnetworks.com> | 2020-06-04 19:26:42 -0400 | 
|---|---|---|
| committer | Quentin Young <qlyoung@cumulusnetworks.com> | 2020-06-04 20:24:52 -0400 | 
| commit | f7c20aa1fd5b997a6c545f0f064b82ad8a5cd3ce (patch) | |
| tree | c02e2394dbbff468c651e803ee144d6e818fc649 /lib | |
| parent | f981d44931ced06f594b33c54a27d6d843ad0379 (diff) | |
lib: move all userdata when changing node xpath
All userdata pointers need to be rekeyed to their new xpaths, not just
the one associated with the dnode being moved.
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/if.c | 10 | ||||
| -rw-r--r-- | lib/northbound.c | 24 | ||||
| -rw-r--r-- | lib/northbound.h | 17 | 
3 files changed, 49 insertions, 2 deletions
@@ -263,15 +263,21 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id)  	 */  	if (yang_module_find("frr-interface")) {  		struct lyd_node *if_dnode; +		char oldpath[XPATH_MAXLEN]; +		char newpath[XPATH_MAXLEN];  		if_dnode = yang_dnode_get(  			running_config->dnode,  			"/frr-interface:lib/interface[name='%s'][vrf='%s']/vrf",  			ifp->name, old_vrf->name); +  		if (if_dnode) { -			nb_running_unset_entry(if_dnode->parent); +			yang_dnode_get_path(if_dnode->parent, oldpath, +					    sizeof(oldpath));  			yang_dnode_change_leaf(if_dnode, vrf->name); -			nb_running_set_entry(if_dnode->parent, ifp); +			yang_dnode_get_path(if_dnode->parent, newpath, +					    sizeof(newpath)); +			nb_running_move_tree(oldpath, newpath);  			running_config->version++;  		}  	} diff --git a/lib/northbound.c b/lib/northbound.c index 18bd4f5fd8..e393c33928 100644 --- a/lib/northbound.c +++ b/lib/northbound.c @@ -30,6 +30,7 @@  #include "northbound.h"  #include "northbound_cli.h"  #include "northbound_db.h" +#include "frrstr.h"  DEFINE_MTYPE_STATIC(LIB, NB_NODE, "Northbound Node")  DEFINE_MTYPE_STATIC(LIB, NB_CONFIG, "Northbound Configuration") @@ -1789,6 +1790,29 @@ void nb_running_set_entry(const struct lyd_node *dnode, void *entry)  	config->entry = entry;  } +void nb_running_move_tree(const char *xpath_from, const char *xpath_to) +{ +	struct nb_config_entry *entry; +	struct list *entries = hash_to_list(running_config_entries); +	struct listnode *ln; + +	for (ALL_LIST_ELEMENTS_RO(entries, ln, entry)) { +		if (!frrstr_startswith(entry->xpath, xpath_from)) +			continue; + +		hash_release(running_config_entries, entry); + +		char *newpath = +			frrstr_replace(entry->xpath, xpath_from, xpath_to); +		strlcpy(entry->xpath, newpath, sizeof(entry->xpath)); +		XFREE(MTYPE_TMP, newpath); + +		hash_get(running_config_entries, entry, hash_alloc_intern); +	} + +	list_delete(&entries); +} +  static void *nb_running_unset_entry_helper(const struct lyd_node *dnode)  {  	struct nb_config_entry *config, s; diff --git a/lib/northbound.h b/lib/northbound.h index 84382eeb60..2a1beeabaa 100644 --- a/lib/northbound.h +++ b/lib/northbound.h @@ -993,6 +993,23 @@ extern int nb_notification_send(const char *xpath, struct list *arguments);  extern void nb_running_set_entry(const struct lyd_node *dnode, void *entry);  /* + * Move an entire tree of user pointer nodes. + * + * Suppose we have xpath A/B/C/D, with user pointers associated to C and D. We + * need to move B to be under Z, so the new xpath is Z/B/C/D. Because user + * pointers are indexed with their absolute path, We need to move all user + * pointers at and below B to their new absolute paths; this function does + * that. + * + * xpath_from + *    base xpath of tree to move (A/B) + * + * xpath_to + *    base xpath of new location of tree (Z/B) + */ +extern void nb_running_move_tree(const char *xpath_from, const char *xpath_to); + +/*   * Unset the user pointer associated to a configuration node.   *   * This should be called by northbound 'destroy' callbacks in the NB_EV_APPLY  | 
