summaryrefslogtreecommitdiff
path: root/lib/yang.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/yang.c')
-rw-r--r--lib/yang.c208
1 files changed, 159 insertions, 49 deletions
diff --git a/lib/yang.c b/lib/yang.c
index bb5d38e2e6..f62a8163f9 100644
--- a/lib/yang.c
+++ b/lib/yang.c
@@ -26,12 +26,60 @@
#include "yang_translator.h"
#include "northbound.h"
+#include <libyang/user_types.h>
+
DEFINE_MTYPE(LIB, YANG_MODULE, "YANG module")
DEFINE_MTYPE(LIB, YANG_DATA, "YANG data structure")
/* libyang container. */
struct ly_ctx *ly_native_ctx;
+static struct yang_module_embed *embeds, **embedupd = &embeds;
+
+void yang_module_embed(struct yang_module_embed *embed)
+{
+ embed->next = NULL;
+ *embedupd = embed;
+ embedupd = &embed->next;
+}
+
+static const char *yang_module_imp_clb(const char *mod_name,
+ const char *mod_rev,
+ const char *submod_name,
+ const char *submod_rev,
+ void *user_data,
+ LYS_INFORMAT *format,
+ void (**free_module_data)
+ (void *, void*))
+{
+ struct yang_module_embed *e;
+
+ if (submod_name || submod_rev)
+ return NULL;
+
+ for (e = embeds; e; e = e->next) {
+ if (strcmp(e->mod_name, mod_name))
+ continue;
+ if (mod_rev && strcmp(e->mod_rev, mod_rev))
+ continue;
+
+ *format = e->format;
+ return e->data;
+ }
+
+ flog_warn(EC_LIB_YANG_MODULE_LOAD,
+ "YANG model \"%s@%s\" not embedded, trying external file",
+ mod_name, mod_rev ? mod_rev : "*");
+ return NULL;
+}
+
+static const char *const frr_native_modules[] = {
+ "frr-interface",
+ "frr-ripd",
+ "frr-ripngd",
+ "frr-isisd",
+};
+
/* Generate the yang_modules tree. */
static inline int yang_module_compare(const struct yang_module *a,
const struct yang_module *b)
@@ -69,6 +117,12 @@ struct yang_module *yang_module_load(const char *module_name)
return module;
}
+void yang_module_load_all(void)
+{
+ for (size_t i = 0; i < array_size(frr_native_modules); i++)
+ yang_module_load(frr_native_modules[i]);
+}
+
struct yang_module *yang_module_find(const char *module_name)
{
struct yang_module s;
@@ -77,23 +131,18 @@ struct yang_module *yang_module_find(const char *module_name)
return RB_FIND(yang_modules, &yang_modules, &s);
}
-/*
- * Helper function for yang_module_snodes_iterate() and
- * yang_all_snodes_iterate(). This is a recursive function.
- */
-static void yang_snodes_iterate(const struct lys_node *snode,
- void (*func)(const struct lys_node *, void *,
- void *),
- uint16_t flags, void *arg1, void *arg2)
+int yang_snodes_iterate_subtree(const struct lys_node *snode,
+ yang_iterate_cb cb, uint16_t flags, void *arg)
{
struct lys_node *child;
+ int ret = YANG_ITER_CONTINUE;
if (CHECK_FLAG(flags, YANG_ITER_FILTER_IMPLICIT)) {
switch (snode->nodetype) {
case LYS_CASE:
case LYS_INPUT:
case LYS_OUTPUT:
- if (snode->flags & LYS_IMPLICIT)
+ if (CHECK_FLAG(snode->flags, LYS_IMPLICIT))
goto next;
break;
default:
@@ -123,7 +172,7 @@ static void yang_snodes_iterate(const struct lys_node *snode,
break;
case LYS_GROUPING:
/* Return since we're not interested in the grouping subtree. */
- return;
+ return YANG_ITER_CONTINUE;
case LYS_USES:
case LYS_AUGMENT:
/* Always ignore nodes of these types. */
@@ -137,50 +186,66 @@ static void yang_snodes_iterate(const struct lys_node *snode,
break;
}
- (*func)(snode, arg1, arg2);
+ ret = (*cb)(snode, arg);
+ if (ret == YANG_ITER_STOP)
+ return ret;
next:
/*
* YANG leafs and leaf-lists can't have child nodes, and trying to
* access snode->child is undefined behavior.
*/
- if (snode->nodetype & (LYS_LEAF | LYS_LEAFLIST))
- return;
+ if (CHECK_FLAG(snode->nodetype, LYS_LEAF | LYS_LEAFLIST))
+ 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;
- yang_snodes_iterate(child, func, flags, arg1, arg2);
+
+ ret = yang_snodes_iterate_subtree(child, cb, flags, arg);
+ if (ret == YANG_ITER_STOP)
+ return ret;
}
+
+ return ret;
}
-void yang_module_snodes_iterate(const struct lys_module *module,
- void (*func)(const struct lys_node *, void *,
- void *),
- uint16_t flags, void *arg1, void *arg2)
+int yang_snodes_iterate_module(const struct lys_module *module,
+ yang_iterate_cb cb, uint16_t flags, void *arg)
{
struct lys_node *snode;
+ int ret = YANG_ITER_CONTINUE;
LY_TREE_FOR (module->data, snode) {
- yang_snodes_iterate(snode, func, flags, arg1, arg2);
+ ret = yang_snodes_iterate_subtree(snode, cb, flags, arg);
+ if (ret == YANG_ITER_STOP)
+ return ret;
}
for (uint8_t i = 0; i < module->augment_size; i++) {
- yang_snodes_iterate(
- (const struct lys_node *)&module->augment[i], func,
- flags, arg1, arg2);
+ ret = yang_snodes_iterate_subtree(
+ (const struct lys_node *)&module->augment[i], cb, flags,
+ arg);
+ if (ret == YANG_ITER_STOP)
+ return ret;
}
+
+ return ret;
}
-void yang_all_snodes_iterate(void (*func)(const struct lys_node *, void *,
- void *),
- uint16_t flags, void *arg1, void *arg2)
+int yang_snodes_iterate_all(yang_iterate_cb cb, uint16_t flags, void *arg)
{
struct yang_module *module;
+ int ret = YANG_ITER_CONTINUE;
+
+ RB_FOREACH (module, yang_modules, &yang_modules) {
+ ret = yang_snodes_iterate_module(module->info, cb, flags, arg);
+ if (ret == YANG_ITER_STOP)
+ return ret;
+ }
- RB_FOREACH (module, yang_modules, &yang_modules)
- yang_module_snodes_iterate(module->info, func, flags, arg1,
- arg2);
+ return ret;
}
void yang_snode_get_path(const struct lys_node *snode, enum yang_path_type type,
@@ -285,7 +350,7 @@ const struct lys_type *yang_snode_get_type(const struct lys_node *snode)
struct lys_node_leaf *sleaf = (struct lys_node_leaf *)snode;
struct lys_type *type;
- if (!(sleaf->nodetype & (LYS_LEAF | LYS_LEAFLIST)))
+ if (!CHECK_FLAG(sleaf->nodetype, LYS_LEAF | LYS_LEAFLIST))
return NULL;
type = &sleaf->type;
@@ -305,6 +370,29 @@ void yang_dnode_get_path(const struct lyd_node *dnode, char *xpath,
free(xpath_ptr);
}
+const char *yang_dnode_get_schema_name(const struct lyd_node *dnode,
+ const char *xpath_fmt, ...)
+{
+ if (xpath_fmt) {
+ va_list ap;
+ char xpath[XPATH_MAXLEN];
+
+ va_start(ap, xpath_fmt);
+ vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
+ va_end(ap);
+
+ dnode = yang_dnode_get(dnode, xpath);
+ if (!dnode) {
+ flog_err(EC_LIB_YANG_DNODE_NOT_FOUND,
+ "%s: couldn't find %s", __func__, xpath);
+ zlog_backtrace(LOG_ERR);
+ abort();
+ }
+ }
+
+ return dnode->schema->name;
+}
+
struct lyd_node *yang_dnode_get(const struct lyd_node *dnode,
const char *xpath_fmt, ...)
{
@@ -401,7 +489,7 @@ bool yang_dnode_is_default_recursive(const struct lyd_node *dnode)
struct lyd_node *root, *next, *dnode_iter;
snode = dnode->schema;
- if (snode->nodetype & (LYS_LEAF | LYS_LEAFLIST))
+ if (CHECK_FLAG(snode->nodetype, LYS_LEAF | LYS_LEAFLIST))
return yang_dnode_is_default(dnode, NULL);
if (!yang_dnode_is_default(dnode, NULL))
@@ -427,11 +515,12 @@ void yang_dnode_change_leaf(struct lyd_node *dnode, const char *value)
void yang_dnode_set_entry(const struct lyd_node *dnode, void *entry)
{
- assert(dnode->schema->nodetype & (LYS_LIST | LYS_CONTAINER));
+ assert(CHECK_FLAG(dnode->schema->nodetype, LYS_LIST | LYS_CONTAINER));
lyd_set_private(dnode, entry);
}
-void *yang_dnode_get_entry(const struct lyd_node *dnode)
+void *yang_dnode_get_entry(const struct lyd_node *dnode,
+ bool abort_if_not_found)
{
const struct lyd_node *orig_dnode = dnode;
char xpath[XPATH_MAXLEN];
@@ -450,6 +539,9 @@ void *yang_dnode_get_entry(const struct lyd_node *dnode)
dnode = dnode->parent;
}
+ if (!abort_if_not_found)
+ return NULL;
+
yang_dnode_get_path(orig_dnode, xpath, sizeof(xpath));
flog_err(EC_LIB_YANG_DNODE_NOT_FOUND,
"%s: failed to find entry [xpath %s]", __func__, xpath);
@@ -457,12 +549,18 @@ void *yang_dnode_get_entry(const struct lyd_node *dnode)
abort();
}
-struct lyd_node *yang_dnode_new(struct ly_ctx *ly_ctx)
+struct lyd_node *yang_dnode_new(struct ly_ctx *ly_ctx, bool config_only)
{
struct lyd_node *dnode;
+ int options;
+
+ if (config_only)
+ options = LYD_OPT_CONFIG;
+ else
+ options = LYD_OPT_DATA | LYD_OPT_DATA_NO_YANGLIB;
dnode = NULL;
- if (lyd_validate(&dnode, LYD_OPT_CONFIG, ly_ctx) != 0) {
+ if (lyd_validate(&dnode, options, ly_ctx) != 0) {
/* Should never happen. */
flog_err(EC_LIB_LIBYANG, "%s: lyd_validate() failed", __func__);
exit(1);
@@ -478,27 +576,17 @@ struct lyd_node *yang_dnode_dup(const struct lyd_node *dnode)
void yang_dnode_free(struct lyd_node *dnode)
{
+ while (dnode->parent)
+ dnode = dnode->parent;
lyd_free_withsiblings(dnode);
}
struct yang_data *yang_data_new(const char *xpath, const char *value)
{
- const struct lys_node *snode;
struct yang_data *data;
- snode = ly_ctx_get_node(ly_native_ctx, NULL, xpath, 0);
- if (!snode)
- snode = ly_ctx_get_node(ly_native_ctx, NULL, xpath, 1);
- if (!snode) {
- flog_err(EC_LIB_YANG_UNKNOWN_DATA_PATH,
- "%s: unknown data path: %s", __func__, xpath);
- zlog_backtrace(LOG_ERR);
- abort();
- }
-
data = XCALLOC(MTYPE_YANG_DATA, sizeof(*data));
strlcpy(data->xpath, xpath, sizeof(data->xpath));
- data->snode = snode;
if (value)
data->value = strdup(value);
@@ -553,8 +641,18 @@ static void ly_log_cb(LY_LOG_LEVEL level, const char *msg, const char *path)
zlog(priority, "libyang: %s", msg);
}
+#if CONFDATE > 20190401
+CPP_NOTICE("lib/yang: time to remove non-LIBYANG_EXT_BUILTIN support")
+#endif
+
+#ifdef LIBYANG_EXT_BUILTIN
+extern struct lytype_plugin_list frr_user_types[];
+#endif
+
void yang_init(void)
{
+#ifndef LIBYANG_EXT_BUILTIN
+CPP_NOTICE("lib/yang: deprecated libyang <0.16.74 extension loading in use!")
static char ly_plugin_dir[PATH_MAX];
const char *const *ly_loaded_plugins;
const char *ly_plugin;
@@ -564,20 +662,31 @@ void yang_init(void)
snprintf(ly_plugin_dir, sizeof(ly_plugin_dir), "%s=%s",
"LIBYANG_USER_TYPES_PLUGINS_DIR", LIBYANG_PLUGINS_PATH);
putenv(ly_plugin_dir);
+#endif
/* Initialize libyang global parameters that affect all containers. */
ly_set_log_clb(ly_log_cb, 1);
ly_log_options(LY_LOLOG | LY_LOSTORE);
+#ifdef LIBYANG_EXT_BUILTIN
+ if (ly_register_types(frr_user_types, "frr_user_types")) {
+ flog_err(EC_LIB_LIBYANG_PLUGIN_LOAD,
+ "ly_register_types() failed");
+ exit(1);
+ }
+#endif
+
/* Initialize libyang container for native models. */
- ly_native_ctx = ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIR_CWD);
+ ly_native_ctx =
+ ly_ctx_new(YANG_MODELS_PATH, LY_CTX_DISABLE_SEARCHDIR_CWD);
if (!ly_native_ctx) {
flog_err(EC_LIB_LIBYANG, "%s: ly_ctx_new() failed", __func__);
exit(1);
}
- ly_ctx_set_searchdir(ly_native_ctx, YANG_MODELS_PATH);
+ ly_ctx_set_module_imp_clb(ly_native_ctx, yang_module_imp_clb, NULL);
ly_ctx_set_priv_dup_clb(ly_native_ctx, ly_dup_cb);
+#ifndef LIBYANG_EXT_BUILTIN
/* Detect if the required libyang plugin(s) were loaded successfully. */
ly_loaded_plugins = ly_get_loaded_plugins();
for (size_t i = 0; (ly_plugin = ly_loaded_plugins[i]); i++) {
@@ -591,6 +700,7 @@ void yang_init(void)
"%s: failed to load frr_user_types.so", __func__);
exit(1);
}
+#endif
yang_translator_init();
}