diff --git a/lib/northbound.c b/lib/northbound.c index c6991680e0..f8045b89aa 100644 --- a/lib/northbound.c +++ b/lib/northbound.c @@ -51,6 +51,18 @@ static int nb_transaction_process(enum nb_event event, struct nb_transaction *transaction); static void nb_transaction_apply_finish(struct nb_transaction *transaction); +static int nb_node_check_config_only(const struct lys_node *snode, void *arg) +{ + bool *config_only = arg; + + if (CHECK_FLAG(snode->flags, LYS_CONFIG_R)) { + *config_only = false; + return YANG_ITER_STOP; + } + + return YANG_ITER_CONTINUE; +} + static int nb_node_new_cb(const struct lys_node *snode, void *arg) { struct nb_node *nb_node; @@ -67,6 +79,17 @@ static int nb_node_new_cb(const struct lys_node *snode, void *arg) if (sparent_list) nb_node->parent_list = sparent_list->priv; + /* Set flags. */ + if (CHECK_FLAG(snode->nodetype, LYS_CONTAINER | LYS_LIST)) { + bool config_only = true; + + yang_snodes_iterate_subtree(snode, nb_node_check_config_only, + YANG_ITER_ALLOW_AUGMENTATIONS, + &config_only); + if (config_only) + SET_FLAG(nb_node->flags, F_NB_NODE_CONFIG_ONLY); + } + /* * Link the northbound node and the libyang schema node with one * another. @@ -88,6 +111,16 @@ static int nb_node_del_cb(const struct lys_node *snode, void *arg) return YANG_ITER_CONTINUE; } +void nb_nodes_create(void) +{ + yang_snodes_iterate_all(nb_node_new_cb, 0, NULL); +} + +void nb_nodes_delete(void) +{ + yang_snodes_iterate_all(nb_node_del_cb, 0, NULL); +} + struct nb_node *nb_node_find(const char *xpath) { const struct lys_node *snode; @@ -900,6 +933,7 @@ static void nb_transaction_apply_finish(struct nb_transaction *transaction) bool nb_operation_is_valid(enum nb_operation operation, const struct lys_node *snode) { + struct nb_node *nb_node = snode->priv; struct lys_node_container *scontainer; struct lys_node_leaf *sleaf; @@ -1017,11 +1051,10 @@ bool nb_operation_is_valid(enum nb_operation operation, case NB_OP_GET_NEXT: case NB_OP_GET_KEYS: case NB_OP_LOOKUP_ENTRY: - if (!CHECK_FLAG(snode->flags, LYS_CONFIG_R)) - return false; - switch (snode->nodetype) { case LYS_LIST: + if (CHECK_FLAG(nb_node->flags, F_NB_NODE_CONFIG_ONLY)) + return false; break; default: return false; @@ -1170,7 +1203,7 @@ void nb_init(const struct frr_yang_module_info *modules[], size_t nmodules) yang_module_load(modules[i]->name); /* Create a nb_node for all YANG schema nodes. */ - yang_snodes_iterate_all(nb_node_new_cb, 0, NULL); + nb_nodes_create(); /* Load northbound callbacks. */ for (size_t i = 0; i < nmodules; i++) @@ -1205,7 +1238,7 @@ void nb_terminate(void) nb_cli_terminate(); /* Delete all nb_node's from all YANG modules. */ - yang_snodes_iterate_all(nb_node_del_cb, 0, NULL); + nb_nodes_delete(); /* Delete the running configuration. */ nb_config_free(running_config); diff --git a/lib/northbound.h b/lib/northbound.h index 8ab6662ecc..68bce5b398 100644 --- a/lib/northbound.h +++ b/lib/northbound.h @@ -349,11 +349,16 @@ struct nb_node { /* Pointer to the nearest parent list, if any. */ struct nb_node *parent_list; + /* Flags. */ + uint8_t flags; + #ifdef HAVE_CONFD /* ConfD hash value corresponding to this YANG path. */ int confd_hash; #endif }; +/* The YANG container or list contains only config data. */ +#define F_NB_NODE_CONFIG_ONLY 0x01 struct frr_yang_module_info { /* YANG module name. */ @@ -435,6 +440,16 @@ DECLARE_HOOK(nb_notification_send, (const char *xpath, struct list *arguments), extern int debug_northbound; extern struct nb_config *running_config; +/* + * Create a northbound node for all YANG schema nodes. + */ +void nb_nodes_create(void); + +/* + * Delete all northbound nodes from all YANG schema nodes. + */ +void nb_nodes_delete(void); + /* * Find the northbound node corresponding to a YANG data path. * diff --git a/lib/yang.c b/lib/yang.c index 6b797ffde3..e426b3af3e 100644 --- a/lib/yang.c +++ b/lib/yang.c @@ -195,7 +195,8 @@ next: return YANG_ITER_CONTINUE; LY_TREE_FOR (snode->child, child) { - if (child->parent != snode) + if (!CHECK_FLAG(flags, YANG_ITER_ALLOW_AUGMENTATIONS) + && child->parent != snode) continue; ret = yang_snodes_iterate_subtree(child, cb, flags, arg); diff --git a/lib/yang.h b/lib/yang.h index 940f5d38e8..2c18017af2 100644 --- a/lib/yang.h +++ b/lib/yang.h @@ -98,6 +98,9 @@ enum yang_iter_flags { /* Filter implicitely created nodes. */ YANG_ITER_FILTER_IMPLICIT = (1<<3), + + /* Allow iteration over augmentations. */ + YANG_ITER_ALLOW_AUGMENTATIONS = (1<<4), }; /* Callback used by the yang_snodes_iterate_*() family of functions. */ diff --git a/tools/gen_northbound_callbacks.c b/tools/gen_northbound_callbacks.c index 9417155e61..5ecb34e023 100644 --- a/tools/gen_northbound_callbacks.c +++ b/tools/gen_northbound_callbacks.c @@ -272,8 +272,15 @@ int main(int argc, char *argv[]) yang_init(); - /* Load YANG module. */ - module = yang_module_load(argv[0]); + /* Load all FRR native models to ensure all augmentations are loaded. */ + yang_module_load_all(); + module = yang_module_find(argv[0]); + if (!module) + /* Non-native FRR module (e.g. modules from unit tests). */ + module = yang_module_load(argv[0]); + + /* Create a nb_node for all YANG schema nodes. */ + nb_nodes_create(); /* Generate callback functions. */ yang_snodes_iterate_module(module->info, generate_callbacks, 0, NULL); @@ -296,6 +303,7 @@ int main(int argc, char *argv[]) "};\n"); /* Cleanup and exit. */ + nb_nodes_delete(); yang_terminate(); return 0;