+// 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>
#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,
}
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)
{
}
}
+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,
flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD,
"%s: module translator \"%s\" is loaded already",
__func__, family);
+ yang_dnode_free(dnode);
return NULL;
}
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;
}
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)
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);
}
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];
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);
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__,
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;
}
{
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)
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;
}
/* 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);
}
}
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));
}
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\")",
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;
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",
yang_translator_unload(translator);
}
- ly_ctx_destroy(ly_translator_ctx, NULL);
+ ly_ctx_destroy(ly_translator_ctx);
}