]> git.proxmox.com Git - mirror_frr.git/blobdiff - lib/yang_translator.c
Merge pull request #13649 from donaldsharp/unlock_the_node_or_else
[mirror_frr.git] / lib / yang_translator.c
index 1f64675d6a410bbf3584d23b276b03b7d25c8d22..eae7577a0d1c2c905261a9c211c73deb283f08dc 100644 (file)
@@ -1,20 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright (C) 2018  NetDEF, Inc.
  *                     Renato Westphal
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 #include <zebra.h>
@@ -26,9 +13,9 @@
 #include "yang_translator.h"
 #include "frrstr.h"
 
-DEFINE_MTYPE_STATIC(LIB, YANG_TRANSLATOR, "YANG Translator")
-DEFINE_MTYPE_STATIC(LIB, YANG_TRANSLATOR_MODULE, "YANG Translator Module")
-DEFINE_MTYPE_STATIC(LIB, YANG_TRANSLATOR_MAPPING, "YANG Translator Mapping")
+DEFINE_MTYPE_STATIC(LIB, YANG_TRANSLATOR, "YANG Translator");
+DEFINE_MTYPE_STATIC(LIB, YANG_TRANSLATOR_MODULE, "YANG Translator Module");
+DEFINE_MTYPE_STATIC(LIB, YANG_TRANSLATOR_MAPPING, "YANG Translator Mapping");
 
 /* Generate the yang_translators tree. */
 static inline int yang_translator_compare(const struct yang_translator *a,
@@ -93,7 +80,7 @@ yang_mapping_lookup(const struct yang_translator *translator, int dir,
 }
 
 static void yang_mapping_add(struct yang_translator *translator, int dir,
-                            const struct lys_node *snode,
+                            const struct lysc_node *snode,
                             const char *xpath_from_fmt,
                             const char *xpath_to_fmt)
 {
@@ -127,21 +114,28 @@ static void yang_mapping_add(struct yang_translator *translator, int dir,
        }
 }
 
+static void yang_tmodule_delete(struct yang_tmodule *tmodule)
+{
+       XFREE(MTYPE_YANG_TRANSLATOR_MODULE, tmodule);
+}
+
 struct yang_translator *yang_translator_load(const char *path)
 {
        struct yang_translator *translator;
-       struct yang_tmodule *tmodule;
+       struct yang_tmodule *tmodule = NULL;
        const char *family;
        struct lyd_node *dnode;
        struct ly_set *set;
        struct listnode *ln;
+       LY_ERR err;
 
        /* Load module translator (JSON file). */
-       dnode = lyd_parse_path(ly_translator_ctx, path, LYD_JSON,
-                              LYD_OPT_CONFIG);
-       if (!dnode) {
+       err = lyd_parse_data_path(ly_translator_ctx, path, LYD_JSON,
+                                 LYD_PARSE_NO_STATE, LYD_VALIDATE_NO_STATE,
+                                 &dnode);
+       if (err) {
                flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD,
-                         "%s: lyd_parse_path() failed", __func__);
+                         "%s: lyd_parse_path() failed: %d", __func__, err);
                return NULL;
        }
        dnode = yang_dnode_get(dnode,
@@ -158,6 +152,7 @@ struct yang_translator *yang_translator_load(const char *path)
                flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD,
                          "%s: module translator \"%s\" is loaded already",
                          __func__, family);
+               yang_dnode_free(dnode);
                return NULL;
        }
 
@@ -171,89 +166,93 @@ struct yang_translator *yang_translator_load(const char *path)
        RB_INSERT(yang_translators, &yang_translators, translator);
 
        /* Initialize the translator libyang context. */
-       translator->ly_ctx = yang_ctx_new_setup(false);
+       translator->ly_ctx = yang_ctx_new_setup(false, false);
        if (!translator->ly_ctx) {
                flog_warn(EC_LIB_LIBYANG, "%s: ly_ctx_new() failed", __func__);
                goto error;
        }
 
-       /* Load modules and deviations. */
-       set = lyd_find_path(dnode, "./module");
-       assert(set);
-       for (size_t i = 0; i < set->number; i++) {
+       /* Load modules */
+       if (lyd_find_xpath(dnode, "./module", &set) != LY_SUCCESS)
+               assert(0); /* XXX libyang2: old ly1 code asserted success */
+
+       for (size_t i = 0; i < set->count; i++) {
                const char *module_name;
 
                tmodule =
                        XCALLOC(MTYPE_YANG_TRANSLATOR_MODULE, sizeof(*tmodule));
 
-               module_name = yang_dnode_get_string(set->set.d[i], "./name");
+               module_name = yang_dnode_get_string(set->dnodes[i], "./name");
                tmodule->module = ly_ctx_load_module(translator->ly_ctx,
-                                                    module_name, NULL);
+                                                    module_name, NULL, NULL);
                if (!tmodule->module) {
                        flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD,
                                  "%s: failed to load module: %s", __func__,
                                  module_name);
-                       ly_set_free(set);
+                       ly_set_free(set, NULL);
                        goto error;
                }
+       }
 
-               module_name =
-                       yang_dnode_get_string(set->set.d[i], "./deviations");
-               tmodule->deviations = ly_ctx_load_module(translator->ly_ctx,
-                                                        module_name, NULL);
+       /* Count nodes in modules. */
+       for (ALL_LIST_ELEMENTS_RO(translator->modules, ln, tmodule)) {
+               tmodule->nodes_before_deviations =
+                       yang_module_nodes_count(tmodule->module);
+       }
+
+       /* Load the deviations and count nodes again */
+       for (ALL_LIST_ELEMENTS_RO(translator->modules, ln, tmodule)) {
+               const char *module_name = tmodule->module->name;
+               tmodule->deviations = ly_ctx_load_module(
+                       translator->ly_ctx, module_name, NULL, NULL);
                if (!tmodule->deviations) {
                        flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD,
                                  "%s: failed to load module: %s", __func__,
                                  module_name);
-                       ly_set_free(set);
+                       ly_set_free(set, NULL);
                        goto error;
                }
-               lys_set_disabled(tmodule->deviations);
 
-               listnode_add(translator->modules, tmodule);
+               tmodule->nodes_after_deviations =
+                       yang_module_nodes_count(tmodule->module);
        }
-       ly_set_free(set);
+       ly_set_free(set, NULL);
 
        /* Calculate the coverage. */
        for (ALL_LIST_ELEMENTS_RO(translator->modules, ln, tmodule)) {
-               tmodule->nodes_before_deviations =
-                       yang_module_nodes_count(tmodule->module);
-
-               lys_set_enabled(tmodule->deviations);
-
-               tmodule->nodes_after_deviations =
-                       yang_module_nodes_count(tmodule->module);
                tmodule->coverage = ((double)tmodule->nodes_after_deviations
                                     / (double)tmodule->nodes_before_deviations)
                                    * 100;
        }
 
        /* Load mappings. */
-       set = lyd_find_path(dnode, "./module/mappings");
-       assert(set);
-       for (size_t i = 0; i < set->number; i++) {
+       if (lyd_find_xpath(dnode, "./module/mappings", &set) != LY_SUCCESS)
+               assert(0); /* XXX libyang2: old ly1 code asserted success */
+       for (size_t i = 0; i < set->count; i++) {
                const char *xpath_custom, *xpath_native;
-               const struct lys_node *snode_custom, *snode_native;
+               const struct lysc_node *snode_custom, *snode_native;
+
+               xpath_custom =
+                       yang_dnode_get_string(set->dnodes[i], "./custom");
 
-               xpath_custom = yang_dnode_get_string(set->set.d[i], "./custom");
-               snode_custom = ly_ctx_get_node(translator->ly_ctx, NULL,
-                                              xpath_custom, 0);
+               snode_custom =
+                       yang_find_snode(translator->ly_ctx, xpath_custom, 0);
                if (!snode_custom) {
                        flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD,
                                  "%s: unknown data path: %s", __func__,
                                  xpath_custom);
-                       ly_set_free(set);
+                       ly_set_free(set, NULL);
                        goto error;
                }
 
-               xpath_native = yang_dnode_get_string(set->set.d[i], "./native");
-               snode_native =
-                       ly_ctx_get_node(ly_native_ctx, NULL, xpath_native, 0);
+               xpath_native =
+                       yang_dnode_get_string(set->dnodes[i], "./native");
+               snode_native = yang_find_snode(ly_native_ctx, xpath_native, 0);
                if (!snode_native) {
                        flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD,
                                  "%s: unknown data path: %s", __func__,
                                  xpath_native);
-                       ly_set_free(set);
+                       ly_set_free(set, NULL);
                        goto error;
                }
 
@@ -262,7 +261,7 @@ struct yang_translator *yang_translator_load(const char *path)
                yang_mapping_add(translator, YANG_TRANSLATE_FROM_NATIVE,
                                 snode_native, xpath_native, xpath_custom);
        }
-       ly_set_free(set);
+       ly_set_free(set, NULL);
 
        /* Validate mappings. */
        if (yang_translator_validate(translator) != 0)
@@ -275,22 +274,18 @@ struct yang_translator *yang_translator_load(const char *path)
 error:
        yang_dnode_free(dnode);
        yang_translator_unload(translator);
+       yang_tmodule_delete(tmodule);
 
        return NULL;
 }
 
-static void yang_tmodule_delete(struct yang_tmodule *tmodule)
-{
-       XFREE(MTYPE_YANG_TRANSLATOR_MODULE, tmodule);
-}
-
 void yang_translator_unload(struct yang_translator *translator)
 {
        for (size_t i = 0; i < YANG_TRANSLATE_MAX; i++)
                hash_clean(translator->mappings[i], yang_mapping_hash_free);
        translator->modules->del = (void (*)(void *))yang_tmodule_delete;
        list_delete(&translator->modules);
-       ly_ctx_destroy(translator->ly_ctx, NULL);
+       ly_ctx_destroy(translator->ly_ctx);
        RB_REMOVE(yang_translators, &yang_translators, translator);
        XFREE(MTYPE_YANG_TRANSLATOR, translator);
 }
@@ -308,7 +303,7 @@ yang_translate_xpath(const struct yang_translator *translator, int dir,
                     char *xpath, size_t xpath_len)
 {
        struct ly_ctx *ly_ctx;
-       const struct lys_node *snode;
+       const struct lysc_node *snode;
        struct yang_mapping_node *mapping;
        char xpath_canonical[XPATH_MAXLEN];
        char keys[4][LIST_MAXKEYLEN];
@@ -319,7 +314,7 @@ yang_translate_xpath(const struct yang_translator *translator, int dir,
        else
                ly_ctx = ly_native_ctx;
 
-       snode = ly_ctx_get_node(ly_ctx, NULL, xpath, 0);
+       snode = yang_find_snode(ly_ctx, xpath, 0);
        if (!snode) {
                flog_warn(EC_LIB_YANG_TRANSLATION_ERROR,
                          "%s: unknown data path: %s", __func__, xpath);
@@ -332,8 +327,12 @@ yang_translate_xpath(const struct yang_translator *translator, int dir,
        if (!mapping)
                return YANG_TRANSLATE_NOTFOUND;
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+       /* processing format strings from mapping node... */
        n = sscanf(xpath, mapping->xpath_from_fmt, keys[0], keys[1], keys[2],
                   keys[3]);
+#pragma GCC diagnostic pop
        if (n < 0) {
                flog_warn(EC_LIB_YANG_TRANSLATION_ERROR,
                          "%s: sscanf() failed: %s", __func__,
@@ -341,8 +340,12 @@ yang_translate_xpath(const struct yang_translator *translator, int dir,
                return YANG_TRANSLATE_FAILURE;
        }
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+       /* processing format strings from mapping node... */
        snprintf(xpath, xpath_len, mapping->xpath_to_fmt, keys[0], keys[1],
                 keys[2], keys[3]);
+#pragma GCC diagnostic pop
 
        return YANG_TRANSLATE_SUCCESS;
 }
@@ -352,7 +355,7 @@ int yang_translate_dnode(const struct yang_translator *translator, int dir,
 {
        struct ly_ctx *ly_ctx;
        struct lyd_node *new;
-       struct lyd_node *root, *next, *dnode_iter;
+       struct lyd_node *root, *dnode_iter;
 
        /* Create new libyang data node to hold the translated data. */
        if (dir == YANG_TRANSLATE_TO_NATIVE)
@@ -362,8 +365,8 @@ int yang_translate_dnode(const struct yang_translator *translator, int dir,
        new = yang_dnode_new(ly_ctx, false);
 
        /* Iterate over all nodes from the data tree. */
-       LY_TREE_FOR (*dnode, root) {
-               LY_TREE_DFS_BEGIN (root, next, dnode_iter) {
+       LY_LIST_FOR (*dnode, root) {
+               LYD_TREE_DFS_BEGIN (root, dnode_iter) {
                        char xpath[XPATH_MAXLEN];
                        enum yang_translate_result ret;
 
@@ -380,19 +383,17 @@ int yang_translate_dnode(const struct yang_translator *translator, int dir,
                        }
 
                        /* Create new node in the tree of translated data. */
-                       ly_errno = 0;
-                       if (!lyd_new_path(new, ly_ctx, xpath,
-                                         (void *)yang_dnode_get_string(
-                                                 dnode_iter, NULL),
-                                         0, LYD_PATH_OPT_UPDATE)
-                           && ly_errno) {
+                       if (lyd_new_path(new, ly_ctx, xpath,
+                                        (void *)yang_dnode_get_string(
+                                                dnode_iter, NULL),
+                                        LYD_NEW_PATH_UPDATE, NULL)) {
                                flog_err(EC_LIB_LIBYANG,
                                         "%s: lyd_new_path() failed", __func__);
                                goto error;
                        }
 
                next:
-                       LY_TREE_DFS_END(root, next, dnode_iter);
+                       LYD_TREE_DFS_END(root, dnode_iter);
                }
        }
 
@@ -413,13 +414,13 @@ struct translator_validate_args {
        unsigned int errors;
 };
 
-static int yang_translator_validate_cb(const struct lys_node *snode_custom,
+static int yang_translator_validate_cb(const struct lysc_node *snode_custom,
                                       void *arg)
 {
        struct translator_validate_args *args = arg;
        struct yang_mapping_node *mapping;
-       const struct lys_node *snode_native;
-       const struct lys_type *stype_custom, *stype_native;
+       const struct lysc_node *snode_native;
+       const struct lysc_type *stype_custom, *stype_native;
        char xpath[XPATH_MAXLEN];
 
        yang_snode_get_path(snode_custom, YANG_PATH_DATA, xpath, sizeof(xpath));
@@ -433,14 +434,14 @@ static int yang_translator_validate_cb(const struct lys_node *snode_custom,
        }
 
        snode_native =
-               ly_ctx_get_node(ly_native_ctx, NULL, mapping->xpath_to_fmt, 0);
+               lys_find_path(ly_native_ctx, NULL, mapping->xpath_to_fmt, 0);
        assert(snode_native);
 
        /* Check if the YANG types are compatible. */
        stype_custom = yang_snode_get_type(snode_custom);
        stype_native = yang_snode_get_type(snode_native);
        if (stype_custom && stype_native) {
-               if (stype_custom->base != stype_native->base) {
+               if (stype_custom->basetype != stype_native->basetype) {
                        flog_warn(
                                EC_LIB_YANG_TRANSLATOR_LOAD,
                                "%s: YANG types are incompatible (xpath: \"%s\")",
@@ -486,7 +487,7 @@ static unsigned int yang_translator_validate(struct yang_translator *translator)
        return args.errors;
 }
 
-static int yang_module_nodes_count_cb(const struct lys_node *snode, void *arg)
+static int yang_module_nodes_count_cb(const struct lysc_node *snode, void *arg)
 {
        unsigned int *total = arg;
 
@@ -511,14 +512,14 @@ static unsigned int yang_module_nodes_count(const struct lys_module *module)
 
 void yang_translator_init(void)
 {
-       ly_translator_ctx = yang_ctx_new_setup(true);
+       ly_translator_ctx = yang_ctx_new_setup(true, false);
        if (!ly_translator_ctx) {
                flog_err(EC_LIB_LIBYANG, "%s: ly_ctx_new() failed", __func__);
                exit(1);
        }
 
        if (!ly_ctx_load_module(ly_translator_ctx, "frr-module-translator",
-                               NULL)) {
+                               NULL, NULL)) {
                flog_err(
                        EC_LIB_YANG_MODULE_LOAD,
                        "%s: failed to load the \"frr-module-translator\" module",
@@ -536,5 +537,5 @@ void yang_translator_terminate(void)
                yang_translator_unload(translator);
        }
 
-       ly_ctx_destroy(ly_translator_ctx, NULL);
+       ly_ctx_destroy(ly_translator_ctx);
 }