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 for (e
= embeds
; e
; e
= e
->next
) {
57 if (e
->sub_mod_name
&& submod_name
) {
58 if (strcmp(e
->sub_mod_name
, submod_name
))
61 if (submod_rev
&& strcmp(e
->sub_mod_rev
, submod_rev
))
64 if (strcmp(e
->mod_name
, mod_name
))
67 if (mod_rev
&& strcmp(e
->mod_rev
, mod_rev
))
76 EC_LIB_YANG_MODULE_LOAD
,
77 "YANG model \"%s@%s\" \"%s@%s\"not embedded, trying external file",
78 mod_name
, mod_rev
? mod_rev
: "*",
79 submod_name
? submod_name
: "*", submod_rev
? submod_rev
: "*");
83 /* clang-format off */
84 static const char *const frr_native_modules
[] = {
99 /* Generate the yang_modules tree. */
100 static inline int yang_module_compare(const struct yang_module
*a
,
101 const struct yang_module
*b
)
103 return strcmp(a
->name
, b
->name
);
105 RB_GENERATE(yang_modules
, yang_module
, entry
, yang_module_compare
)
107 struct yang_modules yang_modules
= RB_INITIALIZER(&yang_modules
);
109 struct yang_module
*yang_module_load(const char *module_name
)
111 struct yang_module
*module
;
112 const struct lys_module
*module_info
;
114 module_info
= ly_ctx_load_module(ly_native_ctx
, module_name
, NULL
);
116 flog_err(EC_LIB_YANG_MODULE_LOAD
,
117 "%s: failed to load data model: %s", __func__
,
122 module
= XCALLOC(MTYPE_YANG_MODULE
, sizeof(*module
));
123 module
->name
= module_name
;
124 module
->info
= module_info
;
126 if (RB_INSERT(yang_modules
, &yang_modules
, module
) != NULL
) {
127 flog_err(EC_LIB_YANG_MODULE_LOADED_ALREADY
,
128 "%s: YANG module is loaded already: %s", __func__
,
136 void yang_module_load_all(void)
138 for (size_t i
= 0; i
< array_size(frr_native_modules
); i
++)
139 yang_module_load(frr_native_modules
[i
]);
142 struct yang_module
*yang_module_find(const char *module_name
)
144 struct yang_module s
;
146 s
.name
= module_name
;
147 return RB_FIND(yang_modules
, &yang_modules
, &s
);
150 int yang_snodes_iterate_subtree(const struct lys_node
*snode
,
151 const struct lys_module
*module
,
152 yang_iterate_cb cb
, uint16_t flags
, void *arg
)
154 struct lys_node
*child
;
155 int ret
= YANG_ITER_CONTINUE
;
157 if (module
&& snode
->module
!= module
)
160 if (CHECK_FLAG(flags
, YANG_ITER_FILTER_IMPLICIT
)) {
161 switch (snode
->nodetype
) {
165 if (CHECK_FLAG(snode
->flags
, LYS_IMPLICIT
))
173 switch (snode
->nodetype
) {
175 if (CHECK_FLAG(flags
, YANG_ITER_FILTER_NPCONTAINERS
)) {
176 struct lys_node_container
*scontainer
;
178 scontainer
= (struct lys_node_container
*)snode
;
179 if (!scontainer
->presence
)
184 if (CHECK_FLAG(flags
, YANG_ITER_FILTER_LIST_KEYS
)) {
185 struct lys_node_leaf
*sleaf
;
187 /* Ignore list keys. */
188 sleaf
= (struct lys_node_leaf
*)snode
;
189 if (lys_is_key(sleaf
, NULL
))
194 /* Return since we're not interested in the grouping subtree. */
195 return YANG_ITER_CONTINUE
;
198 /* Always ignore nodes of these types. */
202 if (CHECK_FLAG(flags
, YANG_ITER_FILTER_INPUT_OUTPUT
))
209 ret
= (*cb
)(snode
, arg
);
210 if (ret
== YANG_ITER_STOP
)
215 * YANG leafs and leaf-lists can't have child nodes, and trying to
216 * access snode->child is undefined behavior.
218 if (CHECK_FLAG(snode
->nodetype
, LYS_LEAF
| LYS_LEAFLIST
))
219 return YANG_ITER_CONTINUE
;
221 LY_TREE_FOR (snode
->child
, child
) {
222 ret
= yang_snodes_iterate_subtree(child
, module
, cb
, flags
,
224 if (ret
== YANG_ITER_STOP
)
231 int yang_snodes_iterate(const struct lys_module
*module
, yang_iterate_cb cb
,
232 uint16_t flags
, void *arg
)
234 const struct lys_module
*module_iter
;
236 int ret
= YANG_ITER_CONTINUE
;
238 idx
= ly_ctx_internal_modules_count(ly_native_ctx
);
239 while ((module_iter
= ly_ctx_get_module_iter(ly_native_ctx
, &idx
))) {
240 struct lys_node
*snode
;
242 if (!module_iter
->implemented
)
245 LY_TREE_FOR (module_iter
->data
, snode
) {
246 ret
= yang_snodes_iterate_subtree(snode
, module
, cb
,
248 if (ret
== YANG_ITER_STOP
)
256 void yang_snode_get_path(const struct lys_node
*snode
, enum yang_path_type type
,
257 char *xpath
, size_t xpath_len
)
262 case YANG_PATH_SCHEMA
:
263 xpath_ptr
= lys_path(snode
, 0);
266 xpath_ptr
= lys_data_path(snode
);
269 flog_err(EC_LIB_DEVELOPMENT
, "%s: unknown yang path type: %u",
273 strlcpy(xpath
, xpath_ptr
, xpath_len
);
277 struct lys_node
*yang_snode_real_parent(const struct lys_node
*snode
)
279 struct lys_node
*parent
= snode
->parent
;
282 struct lys_node_container
*scontainer
;
284 switch (parent
->nodetype
) {
286 scontainer
= (struct lys_node_container
*)parent
;
287 if (scontainer
->presence
)
295 parent
= parent
->parent
;
301 struct lys_node
*yang_snode_parent_list(const struct lys_node
*snode
)
303 struct lys_node
*parent
= snode
->parent
;
306 switch (parent
->nodetype
) {
312 parent
= parent
->parent
;
318 bool yang_snode_is_typeless_data(const struct lys_node
*snode
)
320 struct lys_node_leaf
*sleaf
;
322 switch (snode
->nodetype
) {
324 sleaf
= (struct lys_node_leaf
*)snode
;
325 if (sleaf
->type
.base
== LY_TYPE_EMPTY
)
335 const char *yang_snode_get_default(const struct lys_node
*snode
)
337 struct lys_node_leaf
*sleaf
;
339 switch (snode
->nodetype
) {
341 sleaf
= (struct lys_node_leaf
*)snode
;
343 /* NOTE: this might be null. */
346 /* TODO: check leaf-list default values */
353 const struct lys_type
*yang_snode_get_type(const struct lys_node
*snode
)
355 struct lys_node_leaf
*sleaf
= (struct lys_node_leaf
*)snode
;
356 struct lys_type
*type
;
358 if (!CHECK_FLAG(sleaf
->nodetype
, LYS_LEAF
| LYS_LEAFLIST
))
362 while (type
->base
== LY_TYPE_LEAFREF
)
363 type
= &type
->info
.lref
.target
->type
;
368 void yang_dnode_get_path(const struct lyd_node
*dnode
, char *xpath
,
373 xpath_ptr
= lyd_path(dnode
);
374 strlcpy(xpath
, xpath_ptr
, xpath_len
);
378 const char *yang_dnode_get_schema_name(const struct lyd_node
*dnode
,
379 const char *xpath_fmt
, ...)
383 char xpath
[XPATH_MAXLEN
];
385 va_start(ap
, xpath_fmt
);
386 vsnprintf(xpath
, sizeof(xpath
), xpath_fmt
, ap
);
389 dnode
= yang_dnode_get(dnode
, xpath
);
391 flog_err(EC_LIB_YANG_DNODE_NOT_FOUND
,
392 "%s: couldn't find %s", __func__
, xpath
);
393 zlog_backtrace(LOG_ERR
);
398 return dnode
->schema
->name
;
401 struct lyd_node
*yang_dnode_get(const struct lyd_node
*dnode
,
402 const char *xpath_fmt
, ...)
405 char xpath
[XPATH_MAXLEN
];
407 struct lyd_node
*dnode_ret
= NULL
;
409 va_start(ap
, xpath_fmt
);
410 vsnprintf(xpath
, sizeof(xpath
), xpath_fmt
, ap
);
413 set
= lyd_find_path(dnode
, xpath
);
415 if (set
->number
== 0)
418 if (set
->number
> 1) {
419 flog_warn(EC_LIB_YANG_DNODE_NOT_FOUND
,
420 "%s: found %u elements (expected 0 or 1) [xpath %s]",
421 __func__
, set
->number
, xpath
);
425 dnode_ret
= set
->set
.d
[0];
433 bool yang_dnode_exists(const struct lyd_node
*dnode
, const char *xpath_fmt
, ...)
436 char xpath
[XPATH_MAXLEN
];
440 va_start(ap
, xpath_fmt
);
441 vsnprintf(xpath
, sizeof(xpath
), xpath_fmt
, ap
);
444 set
= lyd_find_path(dnode
, xpath
);
446 found
= (set
->number
> 0);
452 void yang_dnode_iterate(yang_dnode_iter_cb cb
, void *arg
,
453 const struct lyd_node
*dnode
, const char *xpath_fmt
,
457 char xpath
[XPATH_MAXLEN
];
460 va_start(ap
, xpath_fmt
);
461 vsnprintf(xpath
, sizeof(xpath
), xpath_fmt
, ap
);
464 set
= lyd_find_path(dnode
, xpath
);
466 for (unsigned int i
= 0; i
< set
->number
; i
++) {
469 dnode
= set
->set
.d
[i
];
470 ret
= (*cb
)(dnode
, arg
);
471 if (ret
== YANG_ITER_STOP
)
478 bool yang_dnode_is_default(const struct lyd_node
*dnode
, const char *xpath_fmt
,
481 struct lys_node
*snode
;
482 struct lys_node_leaf
*sleaf
;
483 struct lys_node_container
*scontainer
;
487 char xpath
[XPATH_MAXLEN
];
489 va_start(ap
, xpath_fmt
);
490 vsnprintf(xpath
, sizeof(xpath
), xpath_fmt
, ap
);
493 dnode
= yang_dnode_get(dnode
, xpath
);
497 snode
= dnode
->schema
;
498 switch (snode
->nodetype
) {
500 sleaf
= (struct lys_node_leaf
*)snode
;
501 if (sleaf
->type
.base
== LY_TYPE_EMPTY
)
503 return lyd_wd_default((struct lyd_node_leaf_list
*)dnode
);
505 /* TODO: check leaf-list default values */
508 scontainer
= (struct lys_node_container
*)snode
;
509 if (scontainer
->presence
)
517 bool yang_dnode_is_default_recursive(const struct lyd_node
*dnode
)
519 struct lys_node
*snode
;
520 struct lyd_node
*root
, *next
, *dnode_iter
;
522 snode
= dnode
->schema
;
523 if (CHECK_FLAG(snode
->nodetype
, LYS_LEAF
| LYS_LEAFLIST
))
524 return yang_dnode_is_default(dnode
, NULL
);
526 if (!yang_dnode_is_default(dnode
, NULL
))
529 LY_TREE_FOR (dnode
->child
, root
) {
530 LY_TREE_DFS_BEGIN (root
, next
, dnode_iter
) {
531 if (!yang_dnode_is_default(dnode_iter
, NULL
))
534 LY_TREE_DFS_END(root
, next
, dnode_iter
);
541 void yang_dnode_change_leaf(struct lyd_node
*dnode
, const char *value
)
543 assert(dnode
->schema
->nodetype
== LYS_LEAF
);
544 lyd_change_leaf((struct lyd_node_leaf_list
*)dnode
, value
);
547 struct lyd_node
*yang_dnode_new(struct ly_ctx
*ly_ctx
, bool config_only
)
549 struct lyd_node
*dnode
;
553 options
= LYD_OPT_CONFIG
;
555 options
= LYD_OPT_DATA
| LYD_OPT_DATA_NO_YANGLIB
;
558 if (lyd_validate(&dnode
, options
, ly_ctx
) != 0) {
559 /* Should never happen. */
560 flog_err(EC_LIB_LIBYANG
, "%s: lyd_validate() failed", __func__
);
567 struct lyd_node
*yang_dnode_dup(const struct lyd_node
*dnode
)
569 return lyd_dup_withsiblings(dnode
, 1);
572 void yang_dnode_free(struct lyd_node
*dnode
)
574 while (dnode
->parent
)
575 dnode
= dnode
->parent
;
576 lyd_free_withsiblings(dnode
);
579 struct yang_data
*yang_data_new(const char *xpath
, const char *value
)
581 struct yang_data
*data
;
583 data
= XCALLOC(MTYPE_YANG_DATA
, sizeof(*data
));
584 strlcpy(data
->xpath
, xpath
, sizeof(data
->xpath
));
586 data
->value
= strdup(value
);
591 void yang_data_free(struct yang_data
*data
)
595 XFREE(MTYPE_YANG_DATA
, data
);
598 struct list
*yang_data_list_new(void)
603 list
->del
= (void (*)(void *))yang_data_free
;
608 struct yang_data
*yang_data_list_find(const struct list
*list
,
609 const char *xpath_fmt
, ...)
611 char xpath
[XPATH_MAXLEN
];
612 struct yang_data
*data
;
613 struct listnode
*node
;
616 va_start(ap
, xpath_fmt
);
617 vsnprintf(xpath
, sizeof(xpath
), xpath_fmt
, ap
);
620 for (ALL_LIST_ELEMENTS_RO(list
, node
, data
))
621 if (strmatch(data
->xpath
, xpath
))
627 /* Make libyang log its errors using FRR logging infrastructure. */
628 static void ly_log_cb(LY_LOG_LEVEL level
, const char *msg
, const char *path
)
630 int priority
= LOG_ERR
;
637 priority
= LOG_WARNING
;
641 priority
= LOG_DEBUG
;
646 zlog(priority
, "libyang: %s (%s)", msg
, path
);
648 zlog(priority
, "libyang: %s", msg
);
651 const char *yang_print_errors(struct ly_ctx
*ly_ctx
, char *buf
, size_t buf_len
)
653 struct ly_err_item
*ei
;
656 ei
= ly_err_first(ly_ctx
);
660 strlcpy(buf
, "YANG error(s):\n", buf_len
);
661 for (; ei
; ei
= ei
->next
) {
662 strlcat(buf
, " ", buf_len
);
663 strlcat(buf
, ei
->msg
, buf_len
);
664 strlcat(buf
, "\n", buf_len
);
667 path
= ly_errpath(ly_ctx
);
669 strlcat(buf
, " YANG path: ", buf_len
);
670 strlcat(buf
, path
, buf_len
);
671 strlcat(buf
, "\n", buf_len
);
674 ly_err_clean(ly_ctx
, NULL
);
679 void yang_debugging_set(bool enable
)
690 struct ly_ctx
*yang_ctx_new_setup(bool embedded_modules
)
693 const char *yang_models_path
= YANG_MODELS_PATH
;
695 if (access(yang_models_path
, R_OK
| X_OK
)) {
696 yang_models_path
= NULL
;
698 zlog_info("yang model directory \"%s\" does not exist",
701 flog_err_sys(EC_LIB_LIBYANG
,
702 "cannot access yang model directory \"%s\"",
706 ctx
= ly_ctx_new(yang_models_path
, LY_CTX_DISABLE_SEARCHDIR_CWD
);
710 if (embedded_modules
)
711 ly_ctx_set_module_imp_clb(ctx
, yang_module_imp_clb
, NULL
);
716 void yang_init(bool embedded_modules
)
718 /* Initialize libyang global parameters that affect all containers. */
719 ly_set_log_clb(ly_log_cb
, 1);
720 ly_log_options(LY_LOLOG
| LY_LOSTORE
);
722 /* Initialize libyang container for native models. */
723 ly_native_ctx
= yang_ctx_new_setup(embedded_modules
);
724 if (!ly_native_ctx
) {
725 flog_err(EC_LIB_LIBYANG
, "%s: ly_ctx_new() failed", __func__
);
729 yang_translator_init();
732 void yang_terminate(void)
734 struct yang_module
*module
;
736 yang_translator_terminate();
738 while (!RB_EMPTY(yang_modules
, &yang_modules
)) {
739 module
= RB_ROOT(yang_modules
, &yang_modules
);
742 * We shouldn't call ly_ctx_remove_module() here because this
743 * function also removes other modules that depend on it.
745 * ly_ctx_destroy() will release all memory for us.
747 RB_REMOVE(yang_modules
, &yang_modules
, module
);
748 XFREE(MTYPE_YANG_MODULE
, module
);
751 ly_ctx_destroy(ly_native_ctx
, NULL
);
754 const struct lyd_node
*yang_dnode_get_parent(const struct lyd_node
*dnode
,
757 const struct lyd_node
*orig_dnode
= dnode
;
760 switch (orig_dnode
->schema
->nodetype
) {
763 if (!strcmp(orig_dnode
->schema
->name
, name
))
770 orig_dnode
= orig_dnode
->parent
;
776 bool yang_is_last_list_dnode(const struct lyd_node
*dnode
)
778 return (((dnode
->next
== NULL
)
780 && (strcmp(dnode
->next
->schema
->name
, dnode
->schema
->name
)
783 && ((dnode
->prev
== dnode
)
784 || (strcmp(dnode
->prev
->schema
->name
, dnode
->schema
->name
)
788 bool yang_is_last_level_dnode(const struct lyd_node
*dnode
)
790 const struct lyd_node
*parent
;
791 const struct lys_node_list
*snode
;
792 const struct lyd_node
*key_leaf
;
795 switch (dnode
->schema
->nodetype
) {
797 assert(dnode
->parent
);
798 parent
= dnode
->parent
;
799 snode
= (struct lys_node_list
*)parent
->schema
;
800 key_leaf
= dnode
->prev
;
801 for (keys_size
= 1; keys_size
< snode
->keys_size
; keys_size
++)
802 key_leaf
= key_leaf
->prev
;
803 if (key_leaf
->prev
== dnode
)
816 const struct lyd_node
*
817 yang_get_subtree_with_no_sibling(const struct lyd_node
*dnode
)
820 const struct lyd_node
*node
;
821 const struct lys_node_container
*snode
;
824 if (node
->schema
->nodetype
!= LYS_LIST
)
828 switch (node
->schema
->nodetype
) {
830 snode
= (struct lys_node_container
*)node
->schema
;
831 if ((!snode
->presence
)
832 && yang_is_last_level_dnode(node
)) {
834 && (node
->parent
->schema
->module
835 == dnode
->schema
->module
))
843 if (yang_is_last_list_dnode(node
)
844 && yang_is_last_level_dnode(node
)) {
846 && (node
->parent
->schema
->module
847 == dnode
->schema
->module
))
862 uint32_t yang_get_list_pos(const struct lyd_node
*node
)
864 return lyd_list_pos(node
);
867 uint32_t yang_get_list_elements_count(const struct lyd_node
*node
)
870 struct lys_node
*schema
;
873 || ((node
->schema
->nodetype
!= LYS_LIST
)
874 && (node
->schema
->nodetype
!= LYS_LEAFLIST
))) {
878 schema
= node
->schema
;
881 if (node
->schema
== schema
)
889 const struct lyd_node
*yang_dnode_get_child(const struct lyd_node
*dnode
)