diff options
Diffstat (limited to 'lib/yang.c')
| -rw-r--r-- | lib/yang.c | 143 |
1 files changed, 94 insertions, 49 deletions
diff --git a/lib/yang.c b/lib/yang.c index a7a50a46b0..462e693549 100644 --- a/lib/yang.c +++ b/lib/yang.c @@ -71,6 +71,11 @@ static const char *yang_module_imp_clb(const char *mod_name, return NULL; } +static const char * const frr_native_modules[] = { + "frr-interface", + "frr-ripd", +}; + /* Generate the yang_modules tree. */ static inline int yang_module_compare(const struct yang_module *a, const struct yang_module *b) @@ -108,6 +113,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; @@ -116,23 +127,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: @@ -162,7 +168,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. */ @@ -176,50 +182,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) - yang_module_snodes_iterate(module->info, func, flags, arg1, - arg2); + RB_FOREACH (module, yang_modules, &yang_modules) { + ret = yang_snodes_iterate_module(module->info, cb, flags, arg); + if (ret == YANG_ITER_STOP) + return ret; + } + + return ret; } void yang_snode_get_path(const struct lys_node *snode, enum yang_path_type type, @@ -324,7 +346,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; @@ -344,6 +366,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, ...) { @@ -440,7 +485,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)) @@ -466,11 +511,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]; @@ -489,6 +535,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); @@ -496,12 +545,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); @@ -517,27 +572,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); @@ -609,13 +654,13 @@ void yang_init(void) 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_module_imp_clb(ly_native_ctx, yang_module_imp_clb, NULL); - ly_ctx_set_searchdir(ly_native_ctx, YANG_MODELS_PATH); ly_ctx_set_priv_dup_clb(ly_native_ctx, ly_dup_cb); /* Detect if the required libyang plugin(s) were loaded successfully. */ |
