/* 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)
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;
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:
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. */
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,
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;
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, ...)
{
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))
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];
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);
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);
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);
ly_log_options(LY_LOLOG | LY_LOSTORE);
/* 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);
/* Detect if the required libyang plugin(s) were loaded successfully. */