diff options
Diffstat (limited to 'lib/yang.c')
| -rw-r--r-- | lib/yang.c | 208 |
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(); } |
