summaryrefslogtreecommitdiff
path: root/lib/yang.c
diff options
context:
space:
mode:
authorRuss White <russ@riw.us>2018-11-29 15:19:38 -0500
committerGitHub <noreply@github.com>2018-11-29 15:19:38 -0500
commit9f7b49e1057b2a950240813bf538e46b4f1566c4 (patch)
treee429cd55fb72ad7573194686de10d0dd70baee56 /lib/yang.c
parentc4affc7bc0204ac6da2d931dc4385c3189173542 (diff)
parent9c47203310828d015de45eceabce074133220435 (diff)
Merge pull request #3342 from opensourcerouting/nb-operational-data
Northbound: improved support for YANG-modeled operational data
Diffstat (limited to 'lib/yang.c')
-rw-r--r--lib/yang.c110
1 files changed, 64 insertions, 46 deletions
diff --git a/lib/yang.c b/lib/yang.c
index 757982d367..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;
@@ -463,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))
@@ -489,7 +511,7 @@ 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);
}
@@ -523,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);
@@ -544,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);