]> git.proxmox.com Git - mirror_frr.git/commitdiff
lib: add support for YANG lists with mixed config and state data
authorRenato Westphal <renato@opensourcerouting.org>
Tue, 13 Nov 2018 22:36:48 +0000 (20:36 -0200)
committerRenato Westphal <renato@opensourcerouting.org>
Mon, 26 Nov 2018 19:38:08 +0000 (17:38 -0200)
A YANG list that contains both configuration and state data must have
the following callbacks: create(), delete(), get_next(), get_keys()
and lookup_entry().

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
lib/northbound.c
lib/northbound.h
lib/yang.c
lib/yang.h
tools/gen_northbound_callbacks.c

index c6991680e05d48dce3a537b20fe0e891be14640f..f8045b89aa9ef4ddd878807392dd1a50d21acaf7 100644 (file)
@@ -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);
index 8ab6662ecc4908141717a4a9b9183eb640140fac..68bce5b3985599e653baae191b2e23eea377fe2d 100644 (file)
@@ -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.
  *
index 6b797ffde3e144f3fe114968a1008837438a8b78..e426b3af3e83bd697dc33f6dcf27a34d29e01821 100644 (file)
@@ -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);
index 940f5d38e89df6231b483e0c2affe4e24b5175a0..2c18017af27040dfcf4e23d204d4390e72037860 100644 (file)
@@ -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. */
index 9417155e61d7d9629f571f9ced17148addc70f4b..5ecb34e0237050d44507eacf7ebe89b5c698a3a9 100644 (file)
@@ -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;