2 * Copyright (C) 2018 NetDEF, Inc.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along
16 * with this program; see the file COPYING; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "lib_errors.h"
25 #include "yang_translator.h"
26 #include "northbound.h"
28 #include <libyang/user_types.h>
30 DEFINE_MTYPE_STATIC(LIB
, YANG_MODULE
, "YANG module")
31 DEFINE_MTYPE_STATIC(LIB
, YANG_DATA
, "YANG data structure")
33 /* libyang container. */
34 struct ly_ctx
*ly_native_ctx
;
36 static struct yang_module_embed
*embeds
, **embedupd
= &embeds
;
38 void yang_module_embed(struct yang_module_embed
*embed
)
42 embedupd
= &embed
->next
;
45 static const char *yang_module_imp_clb(const char *mod_name
,
47 const char *submod_name
,
48 const char *submod_rev
,
51 void (**free_module_data
)
54 struct yang_module_embed
*e
;
56 if (submod_name
|| submod_rev
)
59 for (e
= embeds
; e
; e
= e
->next
) {
60 if (strcmp(e
->mod_name
, mod_name
))
62 if (mod_rev
&& strcmp(e
->mod_rev
, mod_rev
))
69 flog_warn(EC_LIB_YANG_MODULE_LOAD
,
70 "YANG model \"%s@%s\" not embedded, trying external file",
71 mod_name
, mod_rev
? mod_rev
: "*");
75 static const char *const frr_native_modules
[] = {
82 /* Generate the yang_modules tree. */
83 static inline int yang_module_compare(const struct yang_module
*a
,
84 const struct yang_module
*b
)
86 return strcmp(a
->name
, b
->name
);
88 RB_GENERATE(yang_modules
, yang_module
, entry
, yang_module_compare
)
90 struct yang_modules yang_modules
= RB_INITIALIZER(&yang_modules
);
92 struct yang_module
*yang_module_load(const char *module_name
)
94 struct yang_module
*module
;
95 const struct lys_module
*module_info
;
97 module_info
= ly_ctx_load_module(ly_native_ctx
, module_name
, NULL
);
99 flog_err(EC_LIB_YANG_MODULE_LOAD
,
100 "%s: failed to load data model: %s", __func__
,
105 module
= XCALLOC(MTYPE_YANG_MODULE
, sizeof(*module
));
106 module
->name
= module_name
;
107 module
->info
= module_info
;
109 if (RB_INSERT(yang_modules
, &yang_modules
, module
) != NULL
) {
110 flog_err(EC_LIB_YANG_MODULE_LOADED_ALREADY
,
111 "%s: YANG module is loaded already: %s", __func__
,
119 void yang_module_load_all(void)
121 for (size_t i
= 0; i
< array_size(frr_native_modules
); i
++)
122 yang_module_load(frr_native_modules
[i
]);
125 struct yang_module
*yang_module_find(const char *module_name
)
127 struct yang_module s
;
129 s
.name
= module_name
;
130 return RB_FIND(yang_modules
, &yang_modules
, &s
);
133 int yang_snodes_iterate_subtree(const struct lys_node
*snode
,
134 yang_iterate_cb cb
, uint16_t flags
, void *arg
)
136 struct lys_node
*child
;
137 int ret
= YANG_ITER_CONTINUE
;
139 if (CHECK_FLAG(flags
, YANG_ITER_FILTER_IMPLICIT
)) {
140 switch (snode
->nodetype
) {
144 if (CHECK_FLAG(snode
->flags
, LYS_IMPLICIT
))
152 switch (snode
->nodetype
) {
154 if (CHECK_FLAG(flags
, YANG_ITER_FILTER_NPCONTAINERS
)) {
155 struct lys_node_container
*scontainer
;
157 scontainer
= (struct lys_node_container
*)snode
;
158 if (!scontainer
->presence
)
163 if (CHECK_FLAG(flags
, YANG_ITER_FILTER_LIST_KEYS
)) {
164 struct lys_node_leaf
*sleaf
;
166 /* Ignore list keys. */
167 sleaf
= (struct lys_node_leaf
*)snode
;
168 if (lys_is_key(sleaf
, NULL
))
173 /* Return since we're not interested in the grouping subtree. */
174 return YANG_ITER_CONTINUE
;
177 /* Always ignore nodes of these types. */
181 if (CHECK_FLAG(flags
, YANG_ITER_FILTER_INPUT_OUTPUT
))
188 ret
= (*cb
)(snode
, arg
);
189 if (ret
== YANG_ITER_STOP
)
194 * YANG leafs and leaf-lists can't have child nodes, and trying to
195 * access snode->child is undefined behavior.
197 if (CHECK_FLAG(snode
->nodetype
, LYS_LEAF
| LYS_LEAFLIST
))
198 return YANG_ITER_CONTINUE
;
200 LY_TREE_FOR (snode
->child
, child
) {
201 if (!CHECK_FLAG(flags
, YANG_ITER_ALLOW_AUGMENTATIONS
)
202 && child
->parent
!= snode
)
205 ret
= yang_snodes_iterate_subtree(child
, cb
, flags
, arg
);
206 if (ret
== YANG_ITER_STOP
)
213 int yang_snodes_iterate_module(const struct lys_module
*module
,
214 yang_iterate_cb cb
, uint16_t flags
, void *arg
)
216 struct lys_node
*snode
;
217 int ret
= YANG_ITER_CONTINUE
;
219 LY_TREE_FOR (module
->data
, snode
) {
220 ret
= yang_snodes_iterate_subtree(snode
, cb
, flags
, arg
);
221 if (ret
== YANG_ITER_STOP
)
225 for (uint8_t i
= 0; i
< module
->augment_size
; i
++) {
226 ret
= yang_snodes_iterate_subtree(
227 (const struct lys_node
*)&module
->augment
[i
], cb
, flags
,
229 if (ret
== YANG_ITER_STOP
)
236 int yang_snodes_iterate_all(yang_iterate_cb cb
, uint16_t flags
, void *arg
)
238 struct yang_module
*module
;
239 int ret
= YANG_ITER_CONTINUE
;
241 RB_FOREACH (module
, yang_modules
, &yang_modules
) {
242 ret
= yang_snodes_iterate_module(module
->info
, cb
, flags
, arg
);
243 if (ret
== YANG_ITER_STOP
)
250 void yang_snode_get_path(const struct lys_node
*snode
, enum yang_path_type type
,
251 char *xpath
, size_t xpath_len
)
256 case YANG_PATH_SCHEMA
:
257 xpath_ptr
= lys_path(snode
, 0);
260 xpath_ptr
= lys_data_path(snode
);
263 flog_err(EC_LIB_DEVELOPMENT
, "%s: unknown yang path type: %u",
267 strlcpy(xpath
, xpath_ptr
, xpath_len
);
271 struct lys_node
*yang_snode_real_parent(const struct lys_node
*snode
)
273 struct lys_node
*parent
= snode
->parent
;
276 struct lys_node_container
*scontainer
;
278 switch (parent
->nodetype
) {
280 scontainer
= (struct lys_node_container
*)parent
;
281 if (scontainer
->presence
)
289 parent
= parent
->parent
;
295 struct lys_node
*yang_snode_parent_list(const struct lys_node
*snode
)
297 struct lys_node
*parent
= snode
->parent
;
300 switch (parent
->nodetype
) {
306 parent
= parent
->parent
;
312 bool yang_snode_is_typeless_data(const struct lys_node
*snode
)
314 struct lys_node_leaf
*sleaf
;
316 switch (snode
->nodetype
) {
318 sleaf
= (struct lys_node_leaf
*)snode
;
319 if (sleaf
->type
.base
== LY_TYPE_EMPTY
)
329 const char *yang_snode_get_default(const struct lys_node
*snode
)
331 struct lys_node_leaf
*sleaf
;
333 switch (snode
->nodetype
) {
335 sleaf
= (struct lys_node_leaf
*)snode
;
337 /* NOTE: this might be null. */
340 /* TODO: check leaf-list default values */
347 const struct lys_type
*yang_snode_get_type(const struct lys_node
*snode
)
349 struct lys_node_leaf
*sleaf
= (struct lys_node_leaf
*)snode
;
350 struct lys_type
*type
;
352 if (!CHECK_FLAG(sleaf
->nodetype
, LYS_LEAF
| LYS_LEAFLIST
))
356 while (type
->base
== LY_TYPE_LEAFREF
)
357 type
= &type
->info
.lref
.target
->type
;
362 void yang_dnode_get_path(const struct lyd_node
*dnode
, char *xpath
,
367 xpath_ptr
= lyd_path(dnode
);
368 strlcpy(xpath
, xpath_ptr
, xpath_len
);
372 const char *yang_dnode_get_schema_name(const struct lyd_node
*dnode
,
373 const char *xpath_fmt
, ...)
377 char xpath
[XPATH_MAXLEN
];
379 va_start(ap
, xpath_fmt
);
380 vsnprintf(xpath
, sizeof(xpath
), xpath_fmt
, ap
);
383 dnode
= yang_dnode_get(dnode
, xpath
);
385 flog_err(EC_LIB_YANG_DNODE_NOT_FOUND
,
386 "%s: couldn't find %s", __func__
, xpath
);
387 zlog_backtrace(LOG_ERR
);
392 return dnode
->schema
->name
;
395 struct lyd_node
*yang_dnode_get(const struct lyd_node
*dnode
,
396 const char *xpath_fmt
, ...)
399 char xpath
[XPATH_MAXLEN
];
401 struct lyd_node
*dnode_ret
= NULL
;
403 va_start(ap
, xpath_fmt
);
404 vsnprintf(xpath
, sizeof(xpath
), xpath_fmt
, ap
);
407 set
= lyd_find_path(dnode
, xpath
);
409 if (set
->number
== 0)
412 if (set
->number
> 1) {
413 flog_warn(EC_LIB_YANG_DNODE_NOT_FOUND
,
414 "%s: found %u elements (expected 0 or 1) [xpath %s]",
415 __func__
, set
->number
, xpath
);
419 dnode_ret
= set
->set
.d
[0];
427 bool yang_dnode_exists(const struct lyd_node
*dnode
, const char *xpath_fmt
, ...)
430 char xpath
[XPATH_MAXLEN
];
434 va_start(ap
, xpath_fmt
);
435 vsnprintf(xpath
, sizeof(xpath
), xpath_fmt
, ap
);
438 set
= lyd_find_path(dnode
, xpath
);
440 found
= (set
->number
> 0);
446 bool yang_dnode_is_default(const struct lyd_node
*dnode
, const char *xpath_fmt
,
449 struct lys_node
*snode
;
450 struct lys_node_leaf
*sleaf
;
451 struct lys_node_container
*scontainer
;
455 char xpath
[XPATH_MAXLEN
];
457 va_start(ap
, xpath_fmt
);
458 vsnprintf(xpath
, sizeof(xpath
), xpath_fmt
, ap
);
461 dnode
= yang_dnode_get(dnode
, xpath
);
465 snode
= dnode
->schema
;
466 switch (snode
->nodetype
) {
468 sleaf
= (struct lys_node_leaf
*)snode
;
469 if (sleaf
->type
.base
== LY_TYPE_EMPTY
)
471 return lyd_wd_default((struct lyd_node_leaf_list
*)dnode
);
473 /* TODO: check leaf-list default values */
476 scontainer
= (struct lys_node_container
*)snode
;
477 if (scontainer
->presence
)
485 bool yang_dnode_is_default_recursive(const struct lyd_node
*dnode
)
487 struct lys_node
*snode
;
488 struct lyd_node
*root
, *next
, *dnode_iter
;
490 snode
= dnode
->schema
;
491 if (CHECK_FLAG(snode
->nodetype
, LYS_LEAF
| LYS_LEAFLIST
))
492 return yang_dnode_is_default(dnode
, NULL
);
494 if (!yang_dnode_is_default(dnode
, NULL
))
497 LY_TREE_FOR (dnode
->child
, root
) {
498 LY_TREE_DFS_BEGIN (root
, next
, dnode_iter
) {
499 if (!yang_dnode_is_default(dnode_iter
, NULL
))
502 LY_TREE_DFS_END(root
, next
, dnode_iter
);
509 void yang_dnode_change_leaf(struct lyd_node
*dnode
, const char *value
)
511 assert(dnode
->schema
->nodetype
== LYS_LEAF
);
512 lyd_change_leaf((struct lyd_node_leaf_list
*)dnode
, value
);
515 struct lyd_node
*yang_dnode_new(struct ly_ctx
*ly_ctx
, bool config_only
)
517 struct lyd_node
*dnode
;
521 options
= LYD_OPT_CONFIG
;
523 options
= LYD_OPT_DATA
| LYD_OPT_DATA_NO_YANGLIB
;
526 if (lyd_validate(&dnode
, options
, ly_ctx
) != 0) {
527 /* Should never happen. */
528 flog_err(EC_LIB_LIBYANG
, "%s: lyd_validate() failed", __func__
);
535 struct lyd_node
*yang_dnode_dup(const struct lyd_node
*dnode
)
537 return lyd_dup_withsiblings(dnode
, 1);
540 void yang_dnode_free(struct lyd_node
*dnode
)
542 while (dnode
->parent
)
543 dnode
= dnode
->parent
;
544 lyd_free_withsiblings(dnode
);
547 struct yang_data
*yang_data_new(const char *xpath
, const char *value
)
549 struct yang_data
*data
;
551 data
= XCALLOC(MTYPE_YANG_DATA
, sizeof(*data
));
552 strlcpy(data
->xpath
, xpath
, sizeof(data
->xpath
));
554 data
->value
= strdup(value
);
559 void yang_data_free(struct yang_data
*data
)
563 XFREE(MTYPE_YANG_DATA
, data
);
566 struct list
*yang_data_list_new(void)
571 list
->del
= (void (*)(void *))yang_data_free
;
576 struct yang_data
*yang_data_list_find(const struct list
*list
,
577 const char *xpath_fmt
, ...)
579 char xpath
[XPATH_MAXLEN
];
580 struct yang_data
*data
;
581 struct listnode
*node
;
584 va_start(ap
, xpath_fmt
);
585 vsnprintf(xpath
, sizeof(xpath
), xpath_fmt
, ap
);
588 for (ALL_LIST_ELEMENTS_RO(list
, node
, data
))
589 if (strmatch(data
->xpath
, xpath
))
595 /* Make libyang log its errors using FRR logging infrastructure. */
596 static void ly_log_cb(LY_LOG_LEVEL level
, const char *msg
, const char *path
)
598 int priority
= LOG_ERR
;
605 priority
= LOG_WARNING
;
609 priority
= LOG_DEBUG
;
614 zlog(priority
, "libyang: %s (%s)", msg
, path
);
616 zlog(priority
, "libyang: %s", msg
);
619 void yang_debugging_set(bool enable
)
630 struct ly_ctx
*yang_ctx_new_setup(void)
633 const char *yang_models_path
= YANG_MODELS_PATH
;
635 if (access(yang_models_path
, R_OK
| X_OK
)) {
636 yang_models_path
= NULL
;
638 zlog_info("yang model directory \"%s\" does not exist",
641 flog_err_sys(EC_LIB_LIBYANG
,
642 "cannot access yang model directory \"%s\"",
646 ctx
= ly_ctx_new(yang_models_path
, LY_CTX_DISABLE_SEARCHDIR_CWD
);
649 ly_ctx_set_module_imp_clb(ctx
, yang_module_imp_clb
, NULL
);
655 /* Initialize libyang global parameters that affect all containers. */
656 ly_set_log_clb(ly_log_cb
, 1);
657 ly_log_options(LY_LOLOG
| LY_LOSTORE
);
659 /* Initialize libyang container for native models. */
660 ly_native_ctx
= yang_ctx_new_setup();
661 if (!ly_native_ctx
) {
662 flog_err(EC_LIB_LIBYANG
, "%s: ly_ctx_new() failed", __func__
);
666 yang_translator_init();
669 void yang_terminate(void)
671 struct yang_module
*module
;
673 yang_translator_terminate();
675 while (!RB_EMPTY(yang_modules
, &yang_modules
)) {
676 module
= RB_ROOT(yang_modules
, &yang_modules
);
679 * We shouldn't call ly_ctx_remove_module() here because this
680 * function also removes other modules that depend on it.
682 * ly_ctx_destroy() will release all memory for us.
684 RB_REMOVE(yang_modules
, &yang_modules
, module
);
685 XFREE(MTYPE_YANG_MODULE
, module
);
688 ly_ctx_destroy(ly_native_ctx
, NULL
);