diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/grammar_sandbox_main.c | 1 | ||||
| -rw-r--r-- | lib/if.c | 6 | ||||
| -rw-r--r-- | lib/if.h | 3 | ||||
| -rw-r--r-- | lib/libfrr.c | 6 | ||||
| -rw-r--r-- | lib/northbound.c | 377 | ||||
| -rw-r--r-- | lib/northbound.h | 15 | ||||
| -rw-r--r-- | lib/northbound_cli.c | 93 | ||||
| -rw-r--r-- | lib/northbound_confd.c | 16 | ||||
| -rw-r--r-- | lib/northbound_db.c | 17 | ||||
| -rw-r--r-- | lib/northbound_grpc.cpp | 102 | ||||
| -rw-r--r-- | lib/northbound_sysrepo.c | 22 | ||||
| -rw-r--r-- | lib/vrf.c | 3 | ||||
| -rw-r--r-- | lib/xref.h | 1 | ||||
| -rw-r--r-- | lib/yang.c | 400 | ||||
| -rw-r--r-- | lib/yang.h | 143 | ||||
| -rw-r--r-- | lib/yang_translator.c | 129 | ||||
| -rw-r--r-- | lib/yang_wrappers.c | 546 |
17 files changed, 962 insertions, 918 deletions
diff --git a/lib/grammar_sandbox_main.c b/lib/grammar_sandbox_main.c index 2066e4c96d..6469b49262 100644 --- a/lib/grammar_sandbox_main.c +++ b/lib/grammar_sandbox_main.c @@ -54,7 +54,6 @@ int main(int argc, char **argv) vty_init(master, true); lib_cmd_init(); - yang_init(true); nb_init(master, NULL, 0, false); vty_stdio(vty_do_exit); @@ -266,16 +266,16 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id) char oldpath[XPATH_MAXLEN]; char newpath[XPATH_MAXLEN]; - if_dnode = yang_dnode_get( + if_dnode = yang_dnode_getf( running_config->dnode, "/frr-interface:lib/interface[name='%s'][vrf='%s']/vrf", ifp->name, old_vrf->name); if (if_dnode) { - yang_dnode_get_path(if_dnode->parent, oldpath, + yang_dnode_get_path(lyd_parent(if_dnode), oldpath, sizeof(oldpath)); yang_dnode_change_leaf(if_dnode, vrf->name); - yang_dnode_get_path(if_dnode->parent, newpath, + yang_dnode_get_path(lyd_parent(if_dnode), newpath, sizeof(newpath)); nb_running_move_tree(oldpath, newpath); running_config->version++; @@ -393,6 +393,7 @@ struct connected { #define ZEBRA_IFC_REAL (1 << 0) #define ZEBRA_IFC_CONFIGURED (1 << 1) #define ZEBRA_IFC_QUEUED (1 << 2) +#define ZEBRA_IFC_DOWN (1 << 3) /* The ZEBRA_IFC_REAL flag should be set if and only if this address exists in the kernel and is actually usable. (A case where it exists @@ -406,6 +407,8 @@ struct connected { in the kernel. It may and should be set although the address might not be usable yet. (compare with ZEBRA_IFC_REAL) + The ZEBRA_IFC_DOWN flag is used to record that an address is + present, but down/unavailable. */ /* Flags for connected address. */ diff --git a/lib/libfrr.c b/lib/libfrr.c index 970e82c064..0817182f7a 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -765,16 +765,14 @@ struct thread_master *frr_init(void) log_ref_vty_init(); lib_error_init(); - yang_init(true); - - debug_init_cli(); - nb_init(master, di->yang_modules, di->n_yang_modules, true); if (nb_db_init() != NB_OK) flog_warn(EC_LIB_NB_DATABASE, "%s: failed to initialize northbound database", __func__); + debug_init_cli(); + return master; } diff --git a/lib/northbound.c b/lib/northbound.c index 34ad5dbfa9..3634fed04f 100644 --- a/lib/northbound.c +++ b/lib/northbound.c @@ -83,14 +83,14 @@ static int nb_transaction_process(enum nb_event event, char *errmsg, size_t errmsg_len); static void nb_transaction_apply_finish(struct nb_transaction *transaction, char *errmsg, size_t errmsg_len); -static int nb_oper_data_iter_node(const struct lys_node *snode, +static int nb_oper_data_iter_node(const struct lysc_node *snode, const char *xpath, const void *list_entry, const struct yang_list_keys *list_keys, struct yang_translator *translator, bool first, uint32_t flags, nb_oper_data_cb cb, void *arg); -static int nb_node_check_config_only(const struct lys_node *snode, void *arg) +static int nb_node_check_config_only(const struct lysc_node *snode, void *arg) { bool *config_only = arg; @@ -102,10 +102,10 @@ static int nb_node_check_config_only(const struct lys_node *snode, void *arg) return YANG_ITER_CONTINUE; } -static int nb_node_new_cb(const struct lys_node *snode, void *arg) +static int nb_node_new_cb(const struct lysc_node *snode, void *arg) { struct nb_node *nb_node; - struct lys_node *sparent, *sparent_list; + struct lysc_node *sparent, *sparent_list; nb_node = XCALLOC(MTYPE_NB_NODE, sizeof(*nb_node)); yang_snode_get_path(snode, YANG_PATH_DATA, nb_node->xpath, @@ -129,10 +129,7 @@ static int nb_node_new_cb(const struct lys_node *snode, void *arg) SET_FLAG(nb_node->flags, F_NB_NODE_CONFIG_ONLY); } if (CHECK_FLAG(snode->nodetype, LYS_LIST)) { - struct lys_node_list *slist; - - slist = (struct lys_node_list *)snode; - if (slist->keys_size == 0) + if (yang_snode_num_keys(snode) == 0) SET_FLAG(nb_node->flags, F_NB_NODE_KEYLESS_LIST); } @@ -142,18 +139,18 @@ static int nb_node_new_cb(const struct lys_node *snode, void *arg) */ nb_node->snode = snode; assert(snode->priv == NULL); - lys_set_private(snode, nb_node); + ((struct lysc_node *)snode)->priv = nb_node; return YANG_ITER_CONTINUE; } -static int nb_node_del_cb(const struct lys_node *snode, void *arg) +static int nb_node_del_cb(const struct lysc_node *snode, void *arg) { struct nb_node *nb_node; nb_node = snode->priv; if (nb_node) { - lys_set_private(snode, NULL); + ((struct lysc_node *)snode)->priv = NULL; XFREE(MTYPE_NB_NODE, nb_node); } @@ -170,15 +167,15 @@ void nb_nodes_delete(void) yang_snodes_iterate(NULL, nb_node_del_cb, 0, NULL); } -struct nb_node *nb_node_find(const char *xpath) +struct nb_node *nb_node_find(const char *path) { - const struct lys_node *snode; + const struct lysc_node *snode; /* - * Use libyang to find the schema node associated to the xpath and get + * Use libyang to find the schema node associated to the path and get * the northbound node from there (snode private pointer). */ - snode = ly_ctx_get_node(ly_native_ctx, NULL, xpath, 0); + snode = lys_find_path(ly_native_ctx, NULL, path, 0); if (!snode) return NULL; @@ -288,7 +285,7 @@ static unsigned int nb_node_validate_priority(const struct nb_node *nb_node) return 0; } -static int nb_node_validate(const struct lys_node *snode, void *arg) +static int nb_node_validate(const struct lysc_node *snode, void *arg) { struct nb_node *nb_node = snode->priv; unsigned int *errors = arg; @@ -339,7 +336,7 @@ int nb_config_merge(struct nb_config *config_dst, struct nb_config *config_src, { int ret; - ret = lyd_merge(config_dst->dnode, config_src->dnode, LYD_OPT_EXPLICIT); + ret = lyd_merge_tree(&config_dst->dnode, config_src->dnode, 0); if (ret != 0) flog_warn(EC_LIB_LIBYANG, "%s: lyd_merge() failed", __func__); @@ -451,7 +448,7 @@ static void nb_config_diff_created(const struct lyd_node *dnode, uint32_t *seq, switch (dnode->schema->nodetype) { case LYS_LEAF: case LYS_LEAFLIST: - if (lyd_wd_default((struct lyd_node_leaf_list *)dnode)) + if (lyd_is_default(dnode)) break; if (nb_operation_is_valid(NB_OP_CREATE, dnode->schema)) @@ -470,7 +467,7 @@ static void nb_config_diff_created(const struct lyd_node *dnode, uint32_t *seq, dnode); /* Process child nodes recursively. */ - LY_TREE_FOR (dnode->child, child) { + LY_LIST_FOR (lyd_child(dnode), child) { nb_config_diff_created(child, seq, changes); } break; @@ -497,52 +494,142 @@ static void nb_config_diff_deleted(const struct lyd_node *dnode, uint32_t *seq, * do is to call the "destroy" callbacks of their child nodes * when applicable (i.e. optional nodes). */ - LY_TREE_FOR (dnode->child, child) { + LY_LIST_FOR (lyd_child(dnode), child) { nb_config_diff_deleted(child, seq, changes); } } } +static int nb_lyd_diff_get_op(const struct lyd_node *dnode) +{ + const struct lyd_meta *meta; + LY_LIST_FOR (dnode->meta, meta) { + if (strcmp(meta->name, "operation") + || strcmp(meta->annotation->module->name, "yang")) + continue; + return lyd_get_meta_value(meta)[0]; + } + return 'n'; +} + +static inline void nb_config_diff_dnode_log_path(const char *context, + const char *path, + const struct lyd_node *dnode) +{ + if (dnode->schema->nodetype & LYD_NODE_TERM) + zlog_debug("nb_config_diff: %s: %s: %s", context, path, + lyd_get_value(dnode)); + else + zlog_debug("nb_config_diff: %s: %s", context, path); +} + +static inline void nb_config_diff_dnode_log(const char *context, + const struct lyd_node *dnode) +{ + if (!dnode) { + zlog_debug("nb_config_diff: %s: NULL", context); + return; + } + + char *path = lyd_path(dnode, LYD_PATH_STD, NULL, 0); + nb_config_diff_dnode_log_path(context, path, dnode); + free(path); +} + /* Calculate the delta between two different configurations. */ static void nb_config_diff(const struct nb_config *config1, const struct nb_config *config2, struct nb_config_cbs *changes) { - struct lyd_difflist *diff; - uint32_t seq = 0; + struct lyd_node *diff = NULL; + const struct lyd_node *root, *dnode; + struct lyd_node *target; + int op; + LY_ERR err; + char *path; + +#if 0 /* Useful (but noisy) when debugging diff code, and for improving later \ + */ + if (DEBUG_MODE_CHECK(&nb_dbg_cbs_config, DEBUG_MODE_ALL)) { + LY_LIST_FOR(config1->dnode, root) { + LYD_TREE_DFS_BEGIN(root, dnode) { + nb_config_diff_dnode_log("from", dnode); + LYD_TREE_DFS_END(root, dnode); + } + } + LY_LIST_FOR(config2->dnode, root) { + LYD_TREE_DFS_BEGIN(root, dnode) { + nb_config_diff_dnode_log("to", dnode); + LYD_TREE_DFS_END(root, dnode); + } + } + } +#endif - diff = lyd_diff(config1->dnode, config2->dnode, - LYD_DIFFOPT_WITHDEFAULTS); - assert(diff); + err = lyd_diff_siblings(config1->dnode, config2->dnode, + LYD_DIFF_DEFAULTS, &diff); + assert(!err); - for (int i = 0; diff->type[i] != LYD_DIFF_END; i++) { - LYD_DIFFTYPE type; - struct lyd_node *dnode; + if (diff && DEBUG_MODE_CHECK(&nb_dbg_cbs_config, DEBUG_MODE_ALL)) + nb_config_diff_dnode_log("iterating diff", diff); - type = diff->type[i]; + uint32_t seq = 0; + LY_LIST_FOR (diff, root) { + LYD_TREE_DFS_BEGIN (root, dnode) { + op = nb_lyd_diff_get_op(dnode); + + path = lyd_path(dnode, LYD_PATH_STD, NULL, 0); + +#if 0 /* Useful (but noisy) when debugging diff code, and for improving later \ + */ + if (DEBUG_MODE_CHECK(&nb_dbg_cbs_config, DEBUG_MODE_ALL)) { + char context[80]; + snprintf(context, sizeof(context), + "iterating diff: oper: %c seq: %u", op, seq); + nb_config_diff_dnode_log_path(context, path, dnode); + } +#endif + switch (op) { + case 'c': /* create */ + /* + * This is rather inefficient, but when we use + * dnode from the diff instead of the + * candidate config node we get failures when + * looking up default values, etc, based on + * the diff tree. + */ + target = yang_dnode_get(config2->dnode, path); + nb_config_diff_created(target, &seq, changes); + + /* Skip rest of sub-tree, move to next sibling + */ + LYD_TREE_DFS_continue = 1; + break; + case 'd': /* delete */ + target = yang_dnode_get(config1->dnode, path); + nb_config_diff_deleted(target, &seq, changes); - switch (type) { - case LYD_DIFF_CREATED: - dnode = diff->second[i]; - nb_config_diff_created(dnode, &seq, changes); - break; - case LYD_DIFF_DELETED: - dnode = diff->first[i]; - nb_config_diff_deleted(dnode, &seq, changes); - break; - case LYD_DIFF_CHANGED: - dnode = diff->second[i]; - nb_config_diff_add_change(changes, NB_OP_MODIFY, &seq, - dnode); - break; - case LYD_DIFF_MOVEDAFTER1: - case LYD_DIFF_MOVEDAFTER2: - default: - continue; + /* Skip rest of sub-tree, move to next sibling + */ + LYD_TREE_DFS_continue = 1; + break; + case 'r': /* replace */ + /* either moving an entry or changing a value */ + target = yang_dnode_get(config2->dnode, path); + assert(target); + nb_config_diff_add_change(changes, NB_OP_MODIFY, + &seq, target); + break; + case 'n': /* none */ + default: + break; + } + free(path); + LYD_TREE_DFS_END(root, dnode); } } - lyd_free_diff(diff); + lyd_free_tree(diff); } int nb_candidate_edit(struct nb_config *candidate, @@ -554,6 +641,7 @@ int nb_candidate_edit(struct nb_config *candidate, struct lyd_node *dnode, *dep_dnode; char xpath_edit[XPATH_MAXLEN]; char dep_xpath[XPATH_MAXLEN]; + LY_ERR err; /* Use special notation for leaf-lists (RFC 6020, section 9.13.5). */ if (nb_node->snode->nodetype == LYS_LEAFLIST) @@ -565,11 +653,15 @@ int nb_candidate_edit(struct nb_config *candidate, switch (operation) { case NB_OP_CREATE: case NB_OP_MODIFY: - ly_errno = 0; - dnode = lyd_new_path(candidate->dnode, ly_native_ctx, - xpath_edit, (void *)data->value, 0, - LYD_PATH_OPT_UPDATE); - if (dnode) { + err = lyd_new_path(candidate->dnode, ly_native_ctx, xpath_edit, + (void *)data->value, LYD_NEW_PATH_UPDATE, + &dnode); + if (err) { + flog_warn(EC_LIB_LIBYANG, + "%s: lyd_new_path(%s) failed: %d", __func__, + xpath_edit, err); + return NB_ERR; + } else if (dnode) { /* * create dependency * @@ -581,22 +673,18 @@ int nb_candidate_edit(struct nb_config *candidate, nb_node->dep_cbs.get_dependency_xpath( dnode, dep_xpath); - ly_errno = 0; - dep_dnode = lyd_new_path(candidate->dnode, - ly_native_ctx, - dep_xpath, NULL, 0, - LYD_PATH_OPT_UPDATE); - if (!dep_dnode && ly_errno) { - flog_warn(EC_LIB_LIBYANG, - "%s: lyd_new_path(%s) failed", - __func__, dep_xpath); + err = lyd_new_path(candidate->dnode, + ly_native_ctx, dep_xpath, + NULL, LYD_NEW_PATH_UPDATE, + &dep_dnode); + if (err) { + flog_warn( + EC_LIB_LIBYANG, + "%s: lyd_new_path(%s) failed: %d", + __func__, dep_xpath, err); return NB_ERR; } } - } else if (ly_errno) { - flog_warn(EC_LIB_LIBYANG, "%s: lyd_new_path(%s) failed", - __func__, xpath_edit); - return NB_ERR; } break; case NB_OP_DESTROY: @@ -613,9 +701,9 @@ int nb_candidate_edit(struct nb_config *candidate, dep_dnode = yang_dnode_get(candidate->dnode, dep_xpath); if (dep_dnode) - lyd_free(dep_dnode); + lyd_free_tree(dep_dnode); } - lyd_free(dnode); + lyd_free_tree(dnode); break; case NB_OP_MOVE: /* TODO: update configuration. */ @@ -660,9 +748,8 @@ int nb_candidate_update(struct nb_config *candidate) static int nb_candidate_validate_yang(struct nb_config *candidate, char *errmsg, size_t errmsg_len) { - if (lyd_validate(&candidate->dnode, - LYD_OPT_STRICT | LYD_OPT_CONFIG | LYD_OPT_WHENAUTODEL, - ly_native_ctx) + if (lyd_validate_all(&candidate->dnode, ly_native_ctx, + LYD_VALIDATE_NO_STATE, NULL) != 0) { yang_print_errors(ly_native_ctx, errmsg, errmsg_len); return NB_ERR_VALIDATION; @@ -678,12 +765,12 @@ static int nb_candidate_validate_code(struct nb_context *context, char *errmsg, size_t errmsg_len) { struct nb_config_cb *cb; - struct lyd_node *root, *next, *child; + struct lyd_node *root, *child; int ret; /* First validate the candidate as a whole. */ - LY_TREE_FOR (candidate->dnode, root) { - LY_TREE_DFS_BEGIN (root, next, child) { + LY_LIST_FOR (candidate->dnode, root) { + LYD_TREE_DFS_BEGIN (root, child) { struct nb_node *nb_node; nb_node = child->schema->priv; @@ -696,7 +783,7 @@ static int nb_candidate_validate_code(struct nb_context *context, return NB_ERR_VALIDATION; next: - LY_TREE_DFS_END(root, next, child); + LYD_TREE_DFS_END(root, child); } } @@ -1439,7 +1526,7 @@ static void nb_transaction_apply_finish(struct nb_transaction *transaction, if (change->cb.operation == NB_OP_DESTROY) { char xpath[XPATH_MAXLEN]; - dnode = dnode->parent; + dnode = lyd_parent(dnode); if (!dnode) break; @@ -1470,7 +1557,7 @@ static void nb_transaction_apply_finish(struct nb_transaction *transaction, nb_apply_finish_cb_new(&cbs, nb_node, dnode); next: - dnode = dnode->parent; + dnode = lyd_parent(dnode); } } @@ -1487,16 +1574,16 @@ static void nb_transaction_apply_finish(struct nb_transaction *transaction, } } -static int nb_oper_data_iter_children(const struct lys_node *snode, +static int nb_oper_data_iter_children(const struct lysc_node *snode, const char *xpath, const void *list_entry, const struct yang_list_keys *list_keys, struct yang_translator *translator, bool first, uint32_t flags, nb_oper_data_cb cb, void *arg) { - struct lys_node *child; + const struct lysc_node *child; - LY_TREE_FOR (snode->child, child) { + LY_LIST_FOR (lysc_node_child(snode), child) { int ret; ret = nb_oper_data_iter_node(child, xpath, list_entry, @@ -1521,7 +1608,7 @@ static int nb_oper_data_iter_leaf(const struct nb_node *nb_node, return NB_OK; /* Ignore list keys. */ - if (lys_is_key((struct lys_node_leaf *)nb_node->snode, NULL)) + if (lysc_is_key(nb_node->snode)) return NB_OK; data = nb_callback_get_elem(nb_node, xpath, list_entry); @@ -1605,7 +1692,7 @@ static int nb_oper_data_iter_list(const struct nb_node *nb_node, struct yang_translator *translator, uint32_t flags, nb_oper_data_cb cb, void *arg) { - struct lys_node_list *slist = (struct lys_node_list *)nb_node->snode; + const struct lysc_node *snode = nb_node->snode; const void *list_entry = NULL; uint32_t position = 1; @@ -1614,6 +1701,7 @@ static int nb_oper_data_iter_list(const struct nb_node *nb_node, /* Iterate over all list entries. */ do { + const struct lysc_node_leaf *skey; struct yang_list_keys list_keys; char xpath[XPATH_MAXLEN * 2]; int ret; @@ -1638,12 +1726,16 @@ static int nb_oper_data_iter_list(const struct nb_node *nb_node, /* Build XPath of the list entry. */ strlcpy(xpath, xpath_list, sizeof(xpath)); - for (unsigned int i = 0; i < list_keys.num; i++) { + unsigned int i = 0; + LY_FOR_KEYS (snode, skey) { + assert(i < list_keys.num); snprintf(xpath + strlen(xpath), sizeof(xpath) - strlen(xpath), - "[%s='%s']", slist->keys[i]->name, + "[%s='%s']", skey->name, list_keys.key[i]); + i++; } + assert(i == list_keys.num); } else { /* * Keyless list - build XPath using a positional index. @@ -1664,7 +1756,7 @@ static int nb_oper_data_iter_list(const struct nb_node *nb_node, return NB_OK; } -static int nb_oper_data_iter_node(const struct lys_node *snode, +static int nb_oper_data_iter_node(const struct lysc_node *snode, const char *xpath_parent, const void *list_entry, const struct yang_list_keys *list_keys, @@ -1683,18 +1775,16 @@ static int nb_oper_data_iter_node(const struct lys_node *snode, /* Update XPath. */ strlcpy(xpath, xpath_parent, sizeof(xpath)); if (!first && snode->nodetype != LYS_USES) { - struct lys_node *parent; + struct lysc_node *parent; /* Get the real parent. */ parent = snode->parent; - while (parent && parent->nodetype == LYS_USES) - parent = parent->parent; /* * When necessary, include the namespace of the augmenting * module. */ - if (parent && parent->nodetype == LYS_AUGMENT) + if (parent && parent->module != snode->module) snprintf(xpath + strlen(xpath), sizeof(xpath) - strlen(xpath), "/%s:%s", snode->module->name, snode->name); @@ -1769,12 +1859,14 @@ int nb_oper_data_iterate(const char *xpath, struct yang_translator *translator, * Create a data tree from the XPath so that we can parse the keys of * all YANG lists (if any). */ - ly_errno = 0; - dnode = lyd_new_path(NULL, ly_native_ctx, xpath, NULL, 0, - LYD_PATH_OPT_UPDATE | LYD_PATH_OPT_NOPARENTRET); - if (!dnode) { - flog_warn(EC_LIB_LIBYANG, "%s: lyd_new_path() failed", - __func__); + + LY_ERR err = lyd_new_path(NULL, ly_native_ctx, xpath, NULL, + LYD_NEW_PATH_UPDATE, &dnode); + if (err || !dnode) { + const char *errmsg = + err ? ly_errmsg(ly_native_ctx) : "node not found"; + flog_warn(EC_LIB_LIBYANG, "%s: lyd_new_path() failed %s", + __func__, errmsg); return NB_ERR; } @@ -1782,8 +1874,8 @@ int nb_oper_data_iterate(const char *xpath, struct yang_translator *translator, * Create a linked list to sort the data nodes starting from the root. */ list_dnodes = list_new(); - for (dn = dnode; dn; dn = dn->parent) { - if (dn->schema->nodetype != LYS_LIST || !dn->child) + for (dn = dnode; dn; dn = lyd_parent(dn)) { + if (dn->schema->nodetype != LYS_LIST || !lyd_child(dn)) continue; listnode_add_head(list_dnodes, dn); } @@ -1798,18 +1890,16 @@ int nb_oper_data_iterate(const char *xpath, struct yang_translator *translator, /* Obtain the list entry keys. */ memset(&list_keys, 0, sizeof(list_keys)); - LY_TREE_FOR (dn->child, child) { - if (!lys_is_key((struct lys_node_leaf *)child->schema, - NULL)) - continue; + LY_LIST_FOR (lyd_child(dn), child) { + if (!lysc_is_key(child->schema)) + break; strlcpy(list_keys.key[n], yang_dnode_get_string(child, NULL), sizeof(list_keys.key[n])); n++; } list_keys.num = n; - if (list_keys.num - != ((struct lys_node_list *)dn->schema)->keys_size) { + if (list_keys.num != yang_snode_num_keys(dn->schema)) { list_delete(&list_dnodes); yang_dnode_free(dnode); return NB_ERR_NOT_FOUND; @@ -1837,7 +1927,7 @@ int nb_oper_data_iterate(const char *xpath, struct yang_translator *translator, } /* If a list entry was given, iterate over that list entry only. */ - if (dnode->schema->nodetype == LYS_LIST && dnode->child) + if (dnode->schema->nodetype == LYS_LIST && lyd_child(dnode)) ret = nb_oper_data_iter_children( nb_node->snode, xpath, list_entry, &list_keys, translator, true, flags, cb, arg); @@ -1853,11 +1943,11 @@ int nb_oper_data_iterate(const char *xpath, struct yang_translator *translator, } bool nb_operation_is_valid(enum nb_operation operation, - const struct lys_node *snode) + const struct lysc_node *snode) { struct nb_node *nb_node = snode->priv; - struct lys_node_container *scontainer; - struct lys_node_leaf *sleaf; + struct lysc_node_container *scontainer; + struct lysc_node_leaf *sleaf; switch (operation) { case NB_OP_CREATE: @@ -1866,13 +1956,13 @@ bool nb_operation_is_valid(enum nb_operation operation, switch (snode->nodetype) { case LYS_LEAF: - sleaf = (struct lys_node_leaf *)snode; - if (sleaf->type.base != LY_TYPE_EMPTY) + sleaf = (struct lysc_node_leaf *)snode; + if (sleaf->type->basetype != LY_TYPE_EMPTY) return false; break; case LYS_CONTAINER: - scontainer = (struct lys_node_container *)snode; - if (!scontainer->presence) + scontainer = (struct lysc_node_container *)snode; + if (!CHECK_FLAG(scontainer->flags, LYS_PRESENCE)) return false; break; case LYS_LIST: @@ -1888,12 +1978,12 @@ bool nb_operation_is_valid(enum nb_operation operation, switch (snode->nodetype) { case LYS_LEAF: - sleaf = (struct lys_node_leaf *)snode; - if (sleaf->type.base == LY_TYPE_EMPTY) + sleaf = (struct lysc_node_leaf *)snode; + if (sleaf->type->basetype == LY_TYPE_EMPTY) return false; /* List keys can't be modified. */ - if (lys_is_key(sleaf, NULL)) + if (lysc_is_key(sleaf)) return false; break; default: @@ -1906,10 +1996,10 @@ bool nb_operation_is_valid(enum nb_operation operation, switch (snode->nodetype) { case LYS_LEAF: - sleaf = (struct lys_node_leaf *)snode; + sleaf = (struct lysc_node_leaf *)snode; /* List keys can't be deleted. */ - if (lys_is_key(sleaf, NULL)) + if (lysc_is_key(sleaf)) return false; /* @@ -1925,8 +2015,8 @@ bool nb_operation_is_valid(enum nb_operation operation, return false; break; case LYS_CONTAINER: - scontainer = (struct lys_node_container *)snode; - if (!scontainer->presence) + scontainer = (struct lysc_node_container *)snode; + if (!CHECK_FLAG(scontainer->flags, LYS_PRESENCE)) return false; break; case LYS_LIST: @@ -1943,7 +2033,7 @@ bool nb_operation_is_valid(enum nb_operation operation, switch (snode->nodetype) { case LYS_LIST: case LYS_LEAFLIST: - if (!CHECK_FLAG(snode->flags, LYS_USERORDERED)) + if (!CHECK_FLAG(snode->flags, LYS_ORDBY_USER)) return false; break; default: @@ -1964,8 +2054,8 @@ bool nb_operation_is_valid(enum nb_operation operation, case LYS_LEAFLIST: break; case LYS_CONTAINER: - scontainer = (struct lys_node_container *)snode; - if (!scontainer->presence) + scontainer = (struct lysc_node_container *)snode; + if (!CHECK_FLAG(scontainer->flags, LYS_PRESENCE)) return false; break; default: @@ -2114,7 +2204,7 @@ static void *nb_running_unset_entry_helper(const struct lyd_node *dnode) /* Unset user pointers from the child nodes. */ if (CHECK_FLAG(dnode->schema->nodetype, LYS_LIST | LYS_CONTAINER)) { - LY_TREE_FOR (dnode->child, child) { + LY_LIST_FOR (lyd_child(dnode), child) { (void)nb_running_unset_entry_helper(child); } } @@ -2156,7 +2246,7 @@ static void *nb_running_get_entry_worker(const struct lyd_node *dnode, rec_flag = rec_search; - dnode = dnode->parent; + dnode = lyd_parent(dnode); } if (!abort_if_not_found) @@ -2312,27 +2402,42 @@ void nb_validate_callbacks(void) } } -void nb_load_module(const struct frr_yang_module_info *module_info) -{ - struct yang_module *module; - - DEBUGD(&nb_dbg_events, "northbound: loading %s.yang", - module_info->name); - - module = yang_module_load(module_info->name); - yang_snodes_iterate(module->info, nb_node_new_cb, 0, NULL); - nb_load_callbacks(module_info); -} void nb_init(struct thread_master *tm, const struct frr_yang_module_info *const modules[], size_t nmodules, bool db_enabled) { + struct yang_module *loaded[nmodules], **loadedp = loaded; + bool explicit_compile; + + /* + * Currently using this explicit compile feature in libyang2 leads to + * incorrect behavior in FRR. The functionality suppresses the compiling + * of modules until they have all been loaded into the context. This + * avoids multiple recompiles of the same modules as they are + * imported/augmented etc. + */ + explicit_compile = false; + nb_db_enabled = db_enabled; + yang_init(true, explicit_compile); + /* Load YANG modules and their corresponding northbound callbacks. */ - for (size_t i = 0; i < nmodules; i++) - nb_load_module(modules[i]); + for (size_t i = 0; i < nmodules; i++) { + DEBUGD(&nb_dbg_events, "northbound: loading %s.yang", + modules[i]->name); + *loadedp++ = yang_module_load(modules[i]->name); + } + + if (explicit_compile) + yang_init_loading_complete(); + + /* Initialize the compiled nodes with northbound data */ + for (size_t i = 0; i < nmodules; i++) { + yang_snodes_iterate(loaded[i]->info, nb_node_new_cb, 0, NULL); + nb_load_callbacks(modules[i]); + } /* Validate northbound callbacks. */ nb_validate_callbacks(); diff --git a/lib/northbound.h b/lib/northbound.h index 417ecc81ea..7ccab5cad5 100644 --- a/lib/northbound.h +++ b/lib/northbound.h @@ -537,7 +537,7 @@ struct nb_dependency_callbacks { */ struct nb_node { /* Back pointer to the libyang schema node. */ - const struct lys_node *snode; + const struct lysc_node *snode; /* Data path of this YANG node. */ char xpath[XPATH_MAXLEN]; @@ -685,7 +685,7 @@ struct nb_transaction { }; /* Callback function used by nb_oper_data_iterate(). */ -typedef int (*nb_oper_data_cb)(const struct lys_node *snode, +typedef int (*nb_oper_data_cb)(const struct lysc_node *snode, struct yang_translator *translator, struct yang_data *data, void *arg); @@ -1114,7 +1114,7 @@ extern int nb_oper_data_iterate(const char *xpath, * true if the operation is valid, false otherwise. */ extern bool nb_operation_is_valid(enum nb_operation operation, - const struct lys_node *snode); + const struct lysc_node *snode); /* * Send a YANG notification. This is a no-op unless the 'nb_notification_send' @@ -1285,15 +1285,6 @@ extern const char *nb_client_name(enum nb_client client); void nb_validate_callbacks(void); /* - * Load a YANG module with its corresponding northbound callbacks. - * - * module_info - * Pointer to structure containing the module name and its northbound - * callbacks. - */ -void nb_load_module(const struct frr_yang_module_info *module_info); - -/* * Initialize the northbound layer. Should be called only once during the * daemon initialization process. * diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c index 81e30bce49..d291a1f24d 100644 --- a/lib/northbound_cli.c +++ b/lib/northbound_cli.c @@ -448,6 +448,7 @@ static int nb_cli_candidate_load_file(struct vty *vty, struct ly_ctx *ly_ctx; int ly_format; char buf[BUFSIZ]; + LY_ERR err; switch (format) { case NB_CFG_FMT_CMDS: @@ -465,8 +466,10 @@ static int nb_cli_candidate_load_file(struct vty *vty, ly_format = (format == NB_CFG_FMT_JSON) ? LYD_JSON : LYD_XML; ly_ctx = translator ? translator->ly_ctx : ly_native_ctx; - dnode = lyd_parse_path(ly_ctx, path, ly_format, LYD_OPT_EDIT); - if (!dnode) { + err = lyd_parse_data_path(ly_ctx, path, ly_format, + LYD_PARSE_ONLY | LYD_PARSE_NO_STATE, + 0, &dnode); + if (err || !dnode) { flog_warn(EC_LIB_LIBYANG, "%s: lyd_parse_path() failed", __func__); vty_out(vty, "%% Failed to load configuration:\n\n"); @@ -536,8 +539,6 @@ void nb_cli_show_config_prepare(struct nb_config *config, bool with_defaults) if (config->dnode == NULL) return; - lyd_schema_sort(config->dnode, 1); - /* * Call lyd_validate() only to create default child nodes, ignoring * any possible validation error. This doesn't need to be done when @@ -545,9 +546,8 @@ void nb_cli_show_config_prepare(struct nb_config *config, bool with_defaults) * validated. */ if (config != running_config) - (void)lyd_validate(&config->dnode, - LYD_OPT_CONFIG | LYD_OPT_WHENAUTODEL, - ly_native_ctx); + (void)lyd_validate_all(&config->dnode, ly_native_ctx, + LYD_VALIDATE_NO_STATE, NULL); } static void show_dnode_children_cmds(struct vty *vty, struct lyd_node *root, @@ -559,7 +559,7 @@ static void show_dnode_children_cmds(struct vty *vty, struct lyd_node *root, struct list *sort_list; void *data; - LY_TREE_FOR (root->child, child) { + LY_LIST_FOR (lyd_child(root), child) { nb_node = child->schema->priv; /* @@ -634,8 +634,9 @@ static void nb_cli_show_config_cmds(struct vty *vty, struct nb_config *config, vty_out(vty, "frr version %s\n", FRR_VER_SHORT); vty_out(vty, "frr defaults %s\n", frr_defaults_profile()); - LY_TREE_FOR (config->dnode, root) + LY_LIST_FOR (config->dnode, root) { nb_cli_show_dnode_cmds(vty, root, with_defaults); + } vty_out(vty, "!\n"); vty_out(vty, "end\n"); @@ -660,11 +661,11 @@ static int nb_cli_show_config_libyang(struct vty *vty, LYD_FORMAT format, return CMD_WARNING; } - SET_FLAG(options, LYP_FORMAT | LYP_WITHSIBLINGS); + SET_FLAG(options, LYD_PRINT_WITHSIBLINGS); if (with_defaults) - SET_FLAG(options, LYP_WD_ALL); + SET_FLAG(options, LYD_PRINT_WD_ALL); else - SET_FLAG(options, LYP_WD_TRIM); + SET_FLAG(options, LYD_PRINT_WD_TRIM); if (lyd_print_mem(&strp, dnode, format, options) == 0 && strp) { vty_out(vty, "%s", strp); @@ -1401,7 +1402,7 @@ DEFPY (show_config_transaction, #endif /* HAVE_CONFIG_ROLLBACKS */ } -static int nb_cli_oper_data_cb(const struct lys_node *snode, +static int nb_cli_oper_data_cb(const struct lysc_node *snode, struct yang_translator *translator, struct yang_data *data, void *arg) { @@ -1427,12 +1428,12 @@ static int nb_cli_oper_data_cb(const struct lys_node *snode, } else ly_ctx = ly_native_ctx; - ly_errno = 0; - dnode = lyd_new_path(dnode, ly_ctx, data->xpath, (void *)data->value, 0, - LYD_PATH_OPT_UPDATE); - if (!dnode && ly_errno) { - flog_warn(EC_LIB_LIBYANG, "%s: lyd_new_path() failed", - __func__); + LY_ERR err = + lyd_new_path(dnode, ly_ctx, data->xpath, (void *)data->value, + LYD_NEW_PATH_UPDATE, &dnode); + if (err) { + flog_warn(EC_LIB_LIBYANG, "%s: lyd_new_path(%s) failed: %s", + __func__, data->xpath, ly_errmsg(ly_native_ctx)); goto error; } @@ -1494,11 +1495,11 @@ DEFPY (show_yang_operational_data, yang_dnode_free(dnode); return CMD_WARNING; } - lyd_validate(&dnode, LYD_OPT_GET, ly_ctx); + (void)lyd_validate_all(&dnode, ly_ctx, 0, NULL); /* Display the data. */ if (lyd_print_mem(&strp, dnode, format, - LYP_FORMAT | LYP_WITHSIBLINGS | LYP_WD_ALL) + LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_ALL) != 0 || !strp) { vty_out(vty, "%% Failed to display operational data.\n"); @@ -1551,13 +1552,12 @@ DEFPY (show_yang_module, snprintf(flags, sizeof(flags), "%c%c", module->implemented ? 'I' : ' ', - (module->deviated == 1) ? 'D' : ' '); + LY_ARRAY_COUNT(module->deviated_by) ? 'D' : ' '); ttable_add_row(tt, "%s|%s|%s|%s|%s", module->name, - (module->version == 2) ? "1.1" : "1.0", - (module->rev_size > 0) ? module->rev[0].date - : "-", - flags, module->ns); + (module->parsed->version == 2) ? "1.1" : "1.0", + module->revision ? module->revision : "-", flags, + module->ns); } /* Dump the generated table. */ @@ -1577,21 +1577,21 @@ DEFPY (show_yang_module, return CMD_SUCCESS; } -DEFPY (show_yang_module_detail, - show_yang_module_detail_cmd, - "show yang module\ +DEFPY(show_yang_module_detail, show_yang_module_detail_cmd, + "show yang module\ [module-translator WORD$translator_family]\ - WORD$module_name <summary|tree$tree|yang$yang|yin$yin>", - SHOW_STR - "YANG information\n" - "Show loaded modules\n" - "YANG module translator\n" - "YANG module translator\n" - "Module name\n" - "Display summary information about the module\n" - "Display module in the tree (RFC 8340) format\n" - "Display module in the YANG format\n" - "Display module in the YIN format\n") + WORD$module_name <compiled$compiled|summary|tree$tree|yang$yang|yin$yin>", + SHOW_STR + "YANG information\n" + "Show loaded modules\n" + "YANG module translator\n" + "YANG module translator\n" + "Module name\n" + "Display compiled module in YANG format\n" + "Display summary information about the module\n" + "Display module in the tree (RFC 8340) format\n" + "Display module in the YANG format\n" + "Display module in the YIN format\n") { struct ly_ctx *ly_ctx; struct yang_translator *translator = NULL; @@ -1610,7 +1610,7 @@ DEFPY (show_yang_module_detail, } else ly_ctx = ly_native_ctx; - module = ly_ctx_get_module(ly_ctx, module_name, NULL, 0); + module = ly_ctx_get_module_latest(ly_ctx, module_name); if (!module) { vty_out(vty, "%% Module \"%s\" not found\n", module_name); return CMD_WARNING; @@ -1620,12 +1620,17 @@ DEFPY (show_yang_module_detail, format = LYS_OUT_YANG; else if (yin) format = LYS_OUT_YIN; + else if (compiled) + format = LYS_OUT_YANG_COMPILED; else if (tree) format = LYS_OUT_TREE; - else - format = LYS_OUT_INFO; + else { + vty_out(vty, + "%% libyang v2 does not currently support summary\n"); + return CMD_WARNING; + } - if (lys_print_mem(&strp, module, format, NULL, 0, 0) == 0) { + if (lys_print_mem(&strp, module, format, 0) == 0) { vty_out(vty, "%s\n", strp); free(strp); } else { diff --git a/lib/northbound_confd.c b/lib/northbound_confd.c index 403537e043..76af494e30 100644 --- a/lib/northbound_confd.c +++ b/lib/northbound_confd.c @@ -515,7 +515,7 @@ static int frr_confd_init_cdb(void) /* Subscribe to all loaded YANG data modules. */ confd_spoints = list_new(); RB_FOREACH (module, yang_modules, &yang_modules) { - struct lys_node *snode; + struct lysc_node *snode; module->confd_hash = confd_str2hash(module->info->ns); if (module->confd_hash == 0) { @@ -531,7 +531,7 @@ static int frr_confd_init_cdb(void) * entire YANG module. So we have to find the top level * nodes ourselves and subscribe to their paths. */ - LY_TREE_FOR (module->info->data, snode) { + LY_LIST_FOR (module->info->data, snode) { struct nb_node *nb_node; int *spoint; int ret; @@ -762,7 +762,7 @@ static int frr_confd_data_get_object(struct confd_trans_ctx *tctx, confd_hkeypath_t *kp) { struct nb_node *nb_node; - const struct lys_node *child; + const struct lysc_node *child; char xpath[XPATH_MAXLEN]; char xpath_child[XPATH_MAXLEN * 2]; struct list *elements; @@ -789,7 +789,7 @@ static int frr_confd_data_get_object(struct confd_trans_ctx *tctx, elements = yang_data_list_new(); /* Loop through list child nodes. */ - LY_TREE_FOR (nb_node->snode->child, child) { + LY_LIST_FOR (lysc_node_child(nb_node->snode), child) { struct nb_node *nb_node_child = child->priv; confd_value_t *v; @@ -869,7 +869,7 @@ static int frr_confd_data_get_next_object(struct confd_trans_ctx *tctx, memset(objects, 0, sizeof(objects)); for (int j = 0; j < CONFD_OBJECTS_PER_TIME; j++) { struct confd_next_object *object; - struct lys_node *child; + struct lysc_node *child; struct yang_data *data; size_t nvalues = 0; @@ -919,7 +919,7 @@ static int frr_confd_data_get_next_object(struct confd_trans_ctx *tctx, } /* Loop through list child nodes. */ - LY_TREE_FOR (nb_node->snode->child, child) { + LY_LIST_FOR (lysc_node_child(nb_node->snode), child) { struct nb_node *nb_node_child = child->priv; char xpath_child[XPATH_MAXLEN * 2]; confd_value_t *v; @@ -1187,7 +1187,7 @@ static int frr_confd_dp_read(struct thread *thread) return 0; } -static int frr_confd_subscribe_state(const struct lys_node *snode, void *arg) +static int frr_confd_subscribe_state(const struct lysc_node *snode, void *arg) { struct nb_node *nb_node = snode->priv; struct confd_data_cbs *data_cbs = arg; @@ -1391,7 +1391,7 @@ static void frr_confd_cli_init(void) /* ------------ Main ------------ */ -static int frr_confd_calculate_snode_hash(const struct lys_node *snode, +static int frr_confd_calculate_snode_hash(const struct lysc_node *snode, void *arg) { struct nb_node *nb_node = snode->priv; diff --git a/lib/northbound_db.c b/lib/northbound_db.c index 244e760b2b..dce9b2ec24 100644 --- a/lib/northbound_db.c +++ b/lib/northbound_db.c @@ -87,9 +87,12 @@ int nb_db_transaction_save(const struct nb_transaction *transaction, goto exit; client_name = nb_client_name(transaction->context->client); - /* Always record configurations in the XML format. */ + /* + * Always record configurations in the XML format, save the default + * values too, as this covers the case where defaults may change. + */ if (lyd_print_mem(&config_str, transaction->config->dnode, LYD_XML, - LYP_FORMAT | LYP_WITHSIBLINGS) + LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_ALL) != 0) goto exit; @@ -149,6 +152,7 @@ struct nb_config *nb_db_transaction_load(uint32_t transaction_id) struct lyd_node *dnode; const char *config_str; struct sqlite3_stmt *ss; + LY_ERR err; ss = db_prepare( "SELECT\n" @@ -169,10 +173,11 @@ struct nb_config *nb_db_transaction_load(uint32_t transaction_id) if (db_loadf(ss, "%s", &config_str) != 0) goto exit; - dnode = lyd_parse_mem(ly_native_ctx, config_str, LYD_XML, - LYD_OPT_CONFIG); - if (!dnode) - flog_warn(EC_LIB_LIBYANG, "%s: lyd_parse_mem() failed", + err = lyd_parse_data_mem(ly_native_ctx, config_str, LYD_XML, + LYD_PARSE_STRICT | LYD_PARSE_NO_STATE, + LYD_VALIDATE_NO_STATE, &dnode); + if (err || !dnode) + flog_warn(EC_LIB_LIBYANG, "%s: lyd_parse_data_mem() failed", __func__); else config = nb_config_new(dnode); diff --git a/lib/northbound_grpc.cpp b/lib/northbound_grpc.cpp index 58f4e42516..c61effdda5 100644 --- a/lib/northbound_grpc.cpp +++ b/lib/northbound_grpc.cpp @@ -199,9 +199,8 @@ class NorthboundImpl auto m = tag->response.add_supported_modules(); m->set_name(module->name); - if (module->info->rev_size) - m->set_revision( - module->info->rev[0].date); + if (module->info->revision) + m->set_revision(module->info->revision); m->set_organization(module->info->org); } @@ -1068,14 +1067,13 @@ class NorthboundImpl const std::string &path, const std::string &value) { - ly_errno = LY_SUCCESS; - dnode = lyd_new_path(dnode, ly_native_ctx, path.c_str(), - (void *)value.c_str(), - (LYD_ANYDATA_VALUETYPE)0, - LYD_PATH_OPT_UPDATE); - if (!dnode && ly_errno != LY_SUCCESS) { - flog_warn(EC_LIB_LIBYANG, "%s: lyd_new_path() failed", - __func__); + LY_ERR err = lyd_new_path(dnode, ly_native_ctx, path.c_str(), + value.c_str(), LYD_NEW_PATH_UPDATE, + &dnode); + if (err != LY_SUCCESS) { + flog_warn(EC_LIB_LIBYANG, + "%s: lyd_new_path() failed: %s", __func__, + ly_errmsg(ly_native_ctx)); return -1; } @@ -1089,7 +1087,7 @@ class NorthboundImpl if (!dnode) return -1; - lyd_free(dnode); + lyd_free_tree(dnode); return 0; } @@ -1109,7 +1107,7 @@ class NorthboundImpl } } - static int get_oper_data_cb(const struct lys_node *snode, + static int get_oper_data_cb(const struct lysc_node *snode, struct yang_translator *translator, struct yang_data *data, void *arg) { @@ -1132,46 +1130,53 @@ class NorthboundImpl std::string(date), std::string(comment))); } - static int data_tree_from_dnode(frr::DataTree *dt, - const struct lyd_node *dnode, - LYD_FORMAT lyd_format, - bool with_defaults) + static LY_ERR data_tree_from_dnode(frr::DataTree *dt, + const struct lyd_node *dnode, + LYD_FORMAT lyd_format, + bool with_defaults) { char *strp; int options = 0; - SET_FLAG(options, LYP_FORMAT | LYP_WITHSIBLINGS); + SET_FLAG(options, LYD_PRINT_WITHSIBLINGS); if (with_defaults) - SET_FLAG(options, LYP_WD_ALL); + SET_FLAG(options, LYD_PRINT_WD_ALL); else - SET_FLAG(options, LYP_WD_TRIM); + SET_FLAG(options, LYD_PRINT_WD_TRIM); - if (lyd_print_mem(&strp, dnode, lyd_format, options) == 0) { + LY_ERR err = lyd_print_mem(&strp, dnode, lyd_format, options); + if (err == LY_SUCCESS) { if (strp) { dt->set_data(strp); free(strp); } - return 0; } - - return -1; + return err; } static struct lyd_node *dnode_from_data_tree(const frr::DataTree *dt, 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 = lyd_parse_mem(ly_native_ctx, dt->data().c_str(), - encoding2lyd_format(dt->encoding()), - options); + int options, opt2; + LY_ERR err; + + if (config_only) { + options = LYD_PARSE_STRICT | LYD_PARSE_NO_STATE; + opt2 = LYD_VALIDATE_NO_STATE; + } else { + options = LYD_PARSE_STRICT; + opt2 = 0; + } + err = lyd_parse_data_mem(ly_native_ctx, dt->data().c_str(), + encoding2lyd_format(dt->encoding()), + options, opt2, &dnode); + if (err != LY_SUCCESS) { + flog_warn(EC_LIB_LIBYANG, + "%s: lyd_parse_mem() failed: %s", __func__, + ly_errmsg(ly_native_ctx)); + } return dnode; } @@ -1239,14 +1244,15 @@ class NorthboundImpl // Combine configuration and state data into a single // dnode. // - if (lyd_merge(dnode_state, dnode_config, - LYD_OPT_EXPLICIT) - != 0) { + if (lyd_merge_tree(&dnode_state, dnode_config, + LYD_MERGE_DESTRUCT) + != LY_SUCCESS) { yang_dnode_free(dnode_state); yang_dnode_free(dnode_config); return grpc::Status( grpc::StatusCode::INTERNAL, - "Failed to merge configuration and state data"); + "Failed to merge configuration and state data", + ly_errmsg(ly_native_ctx)); } dnode_final = dnode_state; @@ -1262,19 +1268,25 @@ class NorthboundImpl // Validate data to create implicit default nodes if necessary. int validate_opts = 0; if (type == frr::GetRequest_DataType_CONFIG) - validate_opts = LYD_OPT_CONFIG; + validate_opts = LYD_VALIDATE_NO_STATE; else - validate_opts = LYD_OPT_DATA | LYD_OPT_DATA_NO_YANGLIB; - lyd_validate(&dnode_final, validate_opts, ly_native_ctx); + validate_opts = 0; + LY_ERR err = lyd_validate_all(&dnode_final, ly_native_ctx, + validate_opts, NULL); + + if (err) + flog_warn(EC_LIB_LIBYANG, + "%s: lyd_validate_all() failed: %s", __func__, + ly_errmsg(ly_native_ctx)); // Dump data using the requested format. - int ret = data_tree_from_dnode(dt, dnode_final, lyd_format, - with_defaults); + if (!err) + err = data_tree_from_dnode(dt, dnode_final, lyd_format, + with_defaults); yang_dnode_free(dnode_final); - if (ret != 0) + if (err) return grpc::Status(grpc::StatusCode::INTERNAL, "Failed to dump data"); - return grpc::Status::OK; } diff --git a/lib/northbound_sysrepo.c b/lib/northbound_sysrepo.c index 63fd40f8d3..7c463dd61f 100644 --- a/lib/northbound_sysrepo.c +++ b/lib/northbound_sysrepo.c @@ -48,10 +48,10 @@ static int frr_sr_finish(void); static int yang_data_frr2sr(struct yang_data *frr_data, sr_val_t *sr_data) { struct nb_node *nb_node; - const struct lys_node *snode; - struct lys_node_container *scontainer; - struct lys_node_leaf *sleaf; - struct lys_node_leaflist *sleaflist; + const struct lysc_node *snode; + struct lysc_node_container *scontainer; + struct lysc_node_leaf *sleaf; + struct lysc_node_leaflist *sleaflist; LY_DATA_TYPE type; sr_val_set_xpath(sr_data, frr_data->xpath); @@ -67,8 +67,8 @@ static int yang_data_frr2sr(struct yang_data *frr_data, sr_val_t *sr_data) snode = nb_node->snode; switch (snode->nodetype) { case LYS_CONTAINER: - scontainer = (struct lys_node_container *)snode; - if (!scontainer->presence) + scontainer = (struct lysc_node_container *)snode; + if (!CHECK_FLAG(scontainer->flags, LYS_PRESENCE)) return -1; sr_data->type = SR_CONTAINER_PRESENCE_T; return 0; @@ -76,11 +76,11 @@ static int yang_data_frr2sr(struct yang_data *frr_data, sr_val_t *sr_data) sr_data->type = SR_LIST_T; return 0; case LYS_LEAF: - sleaf = (struct lys_node_leaf *)snode; + sleaf = (struct lysc_node_leaf *)snode; type = sleaf->type.base; break; case LYS_LEAFLIST: - sleaflist = (struct lys_node_leaflist *)snode; + sleaflist = (struct lysc_node_leaflist *)snode; type = sleaflist->type.base; break; default: @@ -359,7 +359,7 @@ static int frr_sr_config_change_cb(sr_session_ctx_t *session, } } -static int frr_sr_state_data_iter_cb(const struct lys_node *snode, +static int frr_sr_state_data_iter_cb(const struct lysc_node *snode, struct yang_translator *translator, struct yang_data *data, void *arg) { @@ -562,7 +562,7 @@ static void frr_sr_subscribe_config(struct yang_module *module) sr_strerror(ret)); } -static int frr_sr_subscribe_state(const struct lys_node *snode, void *arg) +static int frr_sr_subscribe_state(const struct lysc_node *snode, void *arg) { struct yang_module *module = arg; struct nb_node *nb_node; @@ -591,7 +591,7 @@ static int frr_sr_subscribe_state(const struct lys_node *snode, void *arg) return YANG_ITER_CONTINUE; } -static int frr_sr_subscribe_rpc(const struct lys_node *snode, void *arg) +static int frr_sr_subscribe_rpc(const struct lysc_node *snode, void *arg) { struct yang_module *module = arg; struct nb_node *nb_node; @@ -1214,7 +1214,8 @@ const struct frr_yang_module_info frr_vrf_info = { .get_next = lib_vrf_get_next, .get_keys = lib_vrf_get_keys, .lookup_entry = lib_vrf_lookup_entry, - } + }, + .priority = NB_DFLT_PRIORITY - 2, }, { .xpath = "/frr-vrf:lib/vrf/state/id", diff --git a/lib/xref.h b/lib/xref.h index 949458b313..6cff1a3769 100644 --- a/lib/xref.h +++ b/lib/xref.h @@ -169,6 +169,7 @@ extern const struct xref * const __stop_xref_array[1] DSO_LOCAL; static void __attribute__((used, _CONSTRUCTOR(1100))) \ _xref_init(void) { \ static struct xref_block _xref_block = { \ + .next = NULL, \ .start = __start_xref_array, \ .stop = __stop_xref_array, \ }; \ diff --git a/lib/yang.c b/lib/yang.c index df3b07fb09..1e241f049e 100644 --- a/lib/yang.c +++ b/lib/yang.c @@ -25,8 +25,6 @@ #include "yang_translator.h" #include "northbound.h" -#include <libyang/user_types.h> - DEFINE_MTYPE_STATIC(LIB, YANG_MODULE, "YANG module"); DEFINE_MTYPE_STATIC(LIB, YANG_DATA, "YANG data structure"); @@ -42,14 +40,12 @@ void yang_module_embed(struct yang_module_embed *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*)) +static LY_ERR 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, + const char **module_data, + void (**free_module_data)(void *, void *)) { struct yang_module_embed *e; @@ -69,15 +65,17 @@ static const char *yang_module_imp_clb(const char *mod_name, } *format = e->format; - return e->data; + *module_data = e->data; + return LY_SUCCESS; } - flog_warn( - EC_LIB_YANG_MODULE_LOAD, + /* We get here for indirect modules like ietf-inet-types */ + zlog_debug( "YANG model \"%s@%s\" \"%s@%s\"not embedded, trying external file", mod_name, mod_rev ? mod_rev : "*", submod_name ? submod_name : "*", submod_rev ? submod_rev : "*"); - return NULL; + + return LY_ENOTFOUND; } /* clang-format off */ @@ -111,7 +109,8 @@ struct yang_module *yang_module_load(const char *module_name) struct yang_module *module; const struct lys_module *module_info; - module_info = ly_ctx_load_module(ly_native_ctx, module_name, NULL); + module_info = + ly_ctx_load_module(ly_native_ctx, module_name, NULL, NULL); if (!module_info) { flog_err(EC_LIB_YANG_MODULE_LOAD, "%s: failed to load data model: %s", __func__, @@ -147,62 +146,39 @@ struct yang_module *yang_module_find(const char *module_name) return RB_FIND(yang_modules, &yang_modules, &s); } -int yang_snodes_iterate_subtree(const struct lys_node *snode, +int yang_snodes_iterate_subtree(const struct lysc_node *snode, const struct lys_module *module, yang_iterate_cb cb, uint16_t flags, void *arg) { - struct lys_node *child; + const struct lysc_node *child; int ret = YANG_ITER_CONTINUE; if (module && snode->module != module) goto next; - if (CHECK_FLAG(flags, YANG_ITER_FILTER_IMPLICIT)) { - switch (snode->nodetype) { - case LYS_CASE: - case LYS_INPUT: - case LYS_OUTPUT: - if (CHECK_FLAG(snode->flags, LYS_IMPLICIT)) - goto next; - break; - default: - break; - } - } - switch (snode->nodetype) { case LYS_CONTAINER: if (CHECK_FLAG(flags, YANG_ITER_FILTER_NPCONTAINERS)) { - struct lys_node_container *scontainer; - - scontainer = (struct lys_node_container *)snode; - if (!scontainer->presence) + if (!CHECK_FLAG(snode->flags, LYS_PRESENCE)) goto next; } break; case LYS_LEAF: if (CHECK_FLAG(flags, YANG_ITER_FILTER_LIST_KEYS)) { - struct lys_node_leaf *sleaf; - /* Ignore list keys. */ - sleaf = (struct lys_node_leaf *)snode; - if (lys_is_key(sleaf, NULL)) + if (lysc_is_key(snode)) goto next; } break; - case LYS_GROUPING: - /* Return since we're not interested in the grouping subtree. */ - return YANG_ITER_CONTINUE; - case LYS_USES: - case LYS_AUGMENT: - /* Always ignore nodes of these types. */ - goto next; case LYS_INPUT: case LYS_OUTPUT: if (CHECK_FLAG(flags, YANG_ITER_FILTER_INPUT_OUTPUT)) goto next; break; default: + assert(snode->nodetype != LYS_AUGMENT + && snode->nodetype != LYS_GROUPING + && snode->nodetype != LYS_USES); break; } @@ -212,19 +188,17 @@ int yang_snodes_iterate_subtree(const struct lys_node *snode, next: /* - * YANG leafs and leaf-lists can't have child nodes, and trying to - * access snode->child is undefined behavior. + * YANG leafs and leaf-lists can't have child nodes. */ if (CHECK_FLAG(snode->nodetype, LYS_LEAF | LYS_LEAFLIST)) return YANG_ITER_CONTINUE; - LY_TREE_FOR (snode->child, child) { + LY_LIST_FOR (lysc_node_child(snode), child) { ret = yang_snodes_iterate_subtree(child, module, cb, flags, arg); if (ret == YANG_ITER_STOP) return ret; } - return ret; } @@ -237,12 +211,24 @@ int yang_snodes_iterate(const struct lys_module *module, yang_iterate_cb cb, idx = ly_ctx_internal_modules_count(ly_native_ctx); while ((module_iter = ly_ctx_get_module_iter(ly_native_ctx, &idx))) { - struct lys_node *snode; + struct lysc_node *snode; if (!module_iter->implemented) continue; - LY_TREE_FOR (module_iter->data, snode) { + LY_LIST_FOR (module_iter->compiled->data, snode) { + ret = yang_snodes_iterate_subtree(snode, module, cb, + flags, arg); + if (ret == YANG_ITER_STOP) + return ret; + } + LY_LIST_FOR (&module_iter->compiled->rpcs->node, snode) { + ret = yang_snodes_iterate_subtree(snode, module, cb, + flags, arg); + if (ret == YANG_ITER_STOP) + return ret; + } + LY_LIST_FOR (&module_iter->compiled->notifs->node, snode) { ret = yang_snodes_iterate_subtree(snode, module, cb, flags, arg); if (ret == YANG_ITER_STOP) @@ -253,38 +239,32 @@ int yang_snodes_iterate(const struct lys_module *module, yang_iterate_cb cb, return ret; } -void yang_snode_get_path(const struct lys_node *snode, enum yang_path_type type, - char *xpath, size_t xpath_len) +void yang_snode_get_path(const struct lysc_node *snode, + enum yang_path_type type, char *xpath, + size_t xpath_len) { - char *xpath_ptr; - switch (type) { case YANG_PATH_SCHEMA: - xpath_ptr = lys_path(snode, 0); + (void)lysc_path(snode, LYSC_PATH_LOG, xpath, xpath_len); break; case YANG_PATH_DATA: - xpath_ptr = lys_data_path(snode); + (void)lysc_path(snode, LYSC_PATH_DATA, xpath, xpath_len); break; default: flog_err(EC_LIB_DEVELOPMENT, "%s: unknown yang path type: %u", __func__, type); exit(1); } - strlcpy(xpath, xpath_ptr, xpath_len); - free(xpath_ptr); } -struct lys_node *yang_snode_real_parent(const struct lys_node *snode) +struct lysc_node *yang_snode_real_parent(const struct lysc_node *snode) { - struct lys_node *parent = snode->parent; + struct lysc_node *parent = snode->parent; while (parent) { - struct lys_node_container *scontainer; - switch (parent->nodetype) { case LYS_CONTAINER: - scontainer = (struct lys_node_container *)parent; - if (scontainer->presence) + if (CHECK_FLAG(parent->flags, LYS_PRESENCE)) return parent; break; case LYS_LIST: @@ -298,9 +278,9 @@ struct lys_node *yang_snode_real_parent(const struct lys_node *snode) return NULL; } -struct lys_node *yang_snode_parent_list(const struct lys_node *snode) +struct lysc_node *yang_snode_parent_list(const struct lysc_node *snode) { - struct lys_node *parent = snode->parent; + struct lysc_node *parent = snode->parent; while (parent) { switch (parent->nodetype) { @@ -315,14 +295,14 @@ struct lys_node *yang_snode_parent_list(const struct lys_node *snode) return NULL; } -bool yang_snode_is_typeless_data(const struct lys_node *snode) +bool yang_snode_is_typeless_data(const struct lysc_node *snode) { - struct lys_node_leaf *sleaf; + const struct lysc_node_leaf *sleaf; switch (snode->nodetype) { case LYS_LEAF: - sleaf = (struct lys_node_leaf *)snode; - if (sleaf->type.base == LY_TYPE_EMPTY) + sleaf = (struct lysc_node_leaf *)snode; + if (sleaf->type->basetype == LY_TYPE_EMPTY) return true; return false; case LYS_LEAFLIST: @@ -332,16 +312,16 @@ bool yang_snode_is_typeless_data(const struct lys_node *snode) } } -const char *yang_snode_get_default(const struct lys_node *snode) +const char *yang_snode_get_default(const struct lysc_node *snode) { - struct lys_node_leaf *sleaf; + const struct lysc_node_leaf *sleaf; switch (snode->nodetype) { case LYS_LEAF: - sleaf = (struct lys_node_leaf *)snode; - - /* NOTE: this might be null. */ - return sleaf->dflt; + sleaf = (const struct lysc_node_leaf *)snode; + return sleaf->dflt ? lyd_value_get_canonical(sleaf->module->ctx, + sleaf->dflt) + : NULL; case LYS_LEAFLIST: /* TODO: check leaf-list default values */ return NULL; @@ -350,29 +330,40 @@ const char *yang_snode_get_default(const struct lys_node *snode) } } -const struct lys_type *yang_snode_get_type(const struct lys_node *snode) +const struct lysc_type *yang_snode_get_type(const struct lysc_node *snode) { - struct lys_node_leaf *sleaf = (struct lys_node_leaf *)snode; - struct lys_type *type; + struct lysc_node_leaf *sleaf = (struct lysc_node_leaf *)snode; + struct lysc_type *type; if (!CHECK_FLAG(sleaf->nodetype, LYS_LEAF | LYS_LEAFLIST)) return NULL; - type = &sleaf->type; - while (type->base == LY_TYPE_LEAFREF) - type = &type->info.lref.target->type; + type = sleaf->type; + while (type->basetype == LY_TYPE_LEAFREF) + type = ((struct lysc_type_leafref *)type)->realtype; return type; } +unsigned int yang_snode_num_keys(const struct lysc_node *snode) +{ + const struct lysc_node_leaf *skey; + uint count = 0; + + if (!CHECK_FLAG(snode->nodetype, LYS_LIST)) + return 0; + + /* Walk list of children */ + LY_FOR_KEYS (snode, skey) { + count++; + } + return count; +} + void yang_dnode_get_path(const struct lyd_node *dnode, char *xpath, size_t xpath_len) { - char *xpath_ptr; - - xpath_ptr = lyd_path(dnode); - strlcpy(xpath, xpath_ptr, xpath_len); - free(xpath_ptr); + lyd_path(dnode, LYD_PATH_STD, xpath, xpath_len); } const char *yang_dnode_get_schema_name(const struct lyd_node *dnode, @@ -398,55 +389,78 @@ const char *yang_dnode_get_schema_name(const struct lyd_node *dnode, return dnode->schema->name; } -struct lyd_node *yang_dnode_get(const struct lyd_node *dnode, - const char *xpath_fmt, ...) +struct lyd_node *yang_dnode_get(const struct lyd_node *dnode, const char *xpath) { - va_list ap; - char xpath[XPATH_MAXLEN]; - struct ly_set *set; + struct ly_set *set = NULL; struct lyd_node *dnode_ret = NULL; - va_start(ap, xpath_fmt); - vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); - va_end(ap); + /* + * XXX a lot of the code uses this for style I guess. It shouldn't, as + * it adds to the xpath parsing complexity in libyang. + */ + if (xpath[0] == '.' && xpath[1] == '/') + xpath += 2; - set = lyd_find_path(dnode, xpath); - assert(set); - if (set->number == 0) + if (lyd_find_xpath(dnode, xpath, &set)) { + assert(0); /* XXX replicates old libyang1 base code */ + goto exit; + } + if (set->count == 0) goto exit; - if (set->number > 1) { + if (set->count > 1) { flog_warn(EC_LIB_YANG_DNODE_NOT_FOUND, "%s: found %u elements (expected 0 or 1) [xpath %s]", - __func__, set->number, xpath); + __func__, set->count, xpath); goto exit; } - dnode_ret = set->set.d[0]; + dnode_ret = set->dnodes[0]; exit: - ly_set_free(set); + ly_set_free(set, NULL); return dnode_ret; } -bool yang_dnode_exists(const struct lyd_node *dnode, const char *xpath_fmt, ...) +struct lyd_node *yang_dnode_getf(const struct lyd_node *dnode, + const char *xpath_fmt, ...) { va_list ap; char xpath[XPATH_MAXLEN]; - struct ly_set *set; - bool found; va_start(ap, xpath_fmt); vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); va_end(ap); - set = lyd_find_path(dnode, xpath); - assert(set); - found = (set->number > 0); - ly_set_free(set); + return yang_dnode_get(dnode, xpath); +} + +bool yang_dnode_exists(const struct lyd_node *dnode, const char *xpath) +{ + struct ly_set *set = NULL; + bool exists = false; - return found; + if (xpath[0] == '.' && xpath[1] == '/') + xpath += 2; + if (lyd_find_xpath(dnode, xpath, &set)) + return false; + exists = set->count > 0; + ly_set_free(set, NULL); + return exists; +} + +bool yang_dnode_existsf(const struct lyd_node *dnode, const char *xpath_fmt, + ...) +{ + va_list ap; + char xpath[XPATH_MAXLEN]; + + va_start(ap, xpath_fmt); + vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); + va_end(ap); + + return yang_dnode_exists(dnode, xpath); } void yang_dnode_iterate(yang_dnode_iter_cb cb, void *arg, @@ -461,52 +475,42 @@ void yang_dnode_iterate(yang_dnode_iter_cb cb, void *arg, vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); va_end(ap); - set = lyd_find_path(dnode, xpath); - assert(set); - for (unsigned int i = 0; i < set->number; i++) { + if (lyd_find_xpath(dnode, xpath, &set)) { + assert(0); /* XXX libyang2: ly1 code asserted success */ + return; + } + for (unsigned int i = 0; i < set->count; i++) { int ret; - dnode = set->set.d[i]; - ret = (*cb)(dnode, arg); + ret = (*cb)(set->dnodes[i], arg); if (ret == YANG_ITER_STOP) break; } - ly_set_free(set); + ly_set_free(set, NULL); } -bool yang_dnode_is_default(const struct lyd_node *dnode, const char *xpath_fmt, - ...) +bool yang_dnode_is_default(const struct lyd_node *dnode, const char *xpath) { - struct lys_node *snode; - struct lys_node_leaf *sleaf; - struct lys_node_container *scontainer; - - 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); + const struct lysc_node *snode; + struct lysc_node_leaf *sleaf; + if (xpath) dnode = yang_dnode_get(dnode, xpath); - } assert(dnode); snode = dnode->schema; switch (snode->nodetype) { case LYS_LEAF: - sleaf = (struct lys_node_leaf *)snode; - if (sleaf->type.base == LY_TYPE_EMPTY) + sleaf = (struct lysc_node_leaf *)snode; + if (sleaf->type->basetype == LY_TYPE_EMPTY) return false; - return lyd_wd_default((struct lyd_node_leaf_list *)dnode); + return lyd_is_default(dnode); case LYS_LEAFLIST: /* TODO: check leaf-list default values */ return false; case LYS_CONTAINER: - scontainer = (struct lys_node_container *)snode; - if (scontainer->presence) + if (CHECK_FLAG(snode->flags, LYS_PRESENCE)) return false; return true; default: @@ -514,24 +518,39 @@ bool yang_dnode_is_default(const struct lyd_node *dnode, const char *xpath_fmt, } } -bool yang_dnode_is_default_recursive(const struct lyd_node *dnode) +bool yang_dnode_is_defaultf(const struct lyd_node *dnode, const char *xpath_fmt, + ...) { - struct lys_node *snode; - struct lyd_node *root, *next, *dnode_iter; - - snode = dnode->schema; - if (CHECK_FLAG(snode->nodetype, LYS_LEAF | LYS_LEAFLIST)) + if (!xpath_fmt) return yang_dnode_is_default(dnode, NULL); + else { + va_list ap; + char xpath[XPATH_MAXLEN]; + + va_start(ap, xpath_fmt); + vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); + va_end(ap); + + return yang_dnode_is_default(dnode, xpath); + } +} + +bool yang_dnode_is_default_recursive(const struct lyd_node *dnode) +{ + struct lyd_node *root, *dnode_iter; if (!yang_dnode_is_default(dnode, NULL)) return false; - LY_TREE_FOR (dnode->child, root) { - LY_TREE_DFS_BEGIN (root, next, dnode_iter) { + if (CHECK_FLAG(dnode->schema->nodetype, LYS_LEAF | LYS_LEAFLIST)) + return true; + + LY_LIST_FOR (lyd_child(dnode), root) { + LYD_TREE_DFS_BEGIN (root, dnode_iter) { if (!yang_dnode_is_default(dnode_iter, NULL)) return false; - LY_TREE_DFS_END(root, next, dnode_iter); + LYD_TREE_DFS_END(root, dnode_iter); } } @@ -541,21 +560,15 @@ bool yang_dnode_is_default_recursive(const struct lyd_node *dnode) void yang_dnode_change_leaf(struct lyd_node *dnode, const char *value) { assert(dnode->schema->nodetype == LYS_LEAF); - lyd_change_leaf((struct lyd_node_leaf_list *)dnode, value); + lyd_change_term(dnode, value); } 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; + struct lyd_node *dnode = NULL; + int options = config_only ? LYD_VALIDATE_NO_STATE : 0; - dnode = NULL; - if (lyd_validate(&dnode, options, ly_ctx) != 0) { + if (lyd_validate_all(&dnode, ly_ctx, options, NULL) != 0) { /* Should never happen. */ flog_err(EC_LIB_LIBYANG, "%s: lyd_validate() failed", __func__); exit(1); @@ -566,14 +579,18 @@ struct lyd_node *yang_dnode_new(struct ly_ctx *ly_ctx, bool config_only) struct lyd_node *yang_dnode_dup(const struct lyd_node *dnode) { - return lyd_dup_withsiblings(dnode, 1); + struct lyd_node *dup = NULL; + LY_ERR err; + err = lyd_dup_siblings(dnode, NULL, LYD_DUP_RECURSIVE, &dup); + assert(!err); + return dup; } void yang_dnode_free(struct lyd_node *dnode) { while (dnode->parent) - dnode = dnode->parent; - lyd_free_withsiblings(dnode); + dnode = lyd_parent(dnode); + lyd_free_all(dnode); } struct yang_data *yang_data_new(const char *xpath, const char *value) @@ -679,18 +696,19 @@ const char *yang_print_errors(struct ly_ctx *ly_ctx, char *buf, size_t buf_len) void yang_debugging_set(bool enable) { if (enable) { - ly_verb(LY_LLDBG); - ly_verb_dbg(0xFF); + ly_log_level(LY_LLDBG); + ly_log_dbg_groups(0xFF); } else { - ly_verb(LY_LLERR); - ly_verb_dbg(0); + ly_log_level(LY_LLERR); + ly_log_dbg_groups(0); } } -struct ly_ctx *yang_ctx_new_setup(bool embedded_modules) +struct ly_ctx *yang_ctx_new_setup(bool embedded_modules, bool explicit_compile) { - struct ly_ctx *ctx; + struct ly_ctx *ctx = NULL; const char *yang_models_path = YANG_MODELS_PATH; + LY_ERR err; if (access(yang_models_path, R_OK | X_OK)) { yang_models_path = NULL; @@ -703,8 +721,11 @@ struct ly_ctx *yang_ctx_new_setup(bool embedded_modules) YANG_MODELS_PATH); } - ctx = ly_ctx_new(yang_models_path, LY_CTX_DISABLE_SEARCHDIR_CWD); - if (!ctx) + uint options = LY_CTX_NO_YANGLIBRARY | LY_CTX_DISABLE_SEARCHDIR_CWD; + if (explicit_compile) + options |= LY_CTX_EXPLICIT_COMPILE; + err = ly_ctx_new(yang_models_path, options, &ctx); + if (err) return NULL; if (embedded_modules) @@ -713,14 +734,14 @@ struct ly_ctx *yang_ctx_new_setup(bool embedded_modules) return ctx; } -void yang_init(bool embedded_modules) +void yang_init(bool embedded_modules, bool defer_compile) { /* Initialize libyang global parameters that affect all containers. */ ly_set_log_clb(ly_log_cb, 1); ly_log_options(LY_LOLOG | LY_LOSTORE); /* Initialize libyang container for native models. */ - ly_native_ctx = yang_ctx_new_setup(embedded_modules); + ly_native_ctx = yang_ctx_new_setup(embedded_modules, defer_compile); if (!ly_native_ctx) { flog_err(EC_LIB_LIBYANG, "%s: ly_ctx_new() failed", __func__); exit(1); @@ -729,6 +750,17 @@ void yang_init(bool embedded_modules) yang_translator_init(); } +void yang_init_loading_complete(void) +{ + /* Compile everything */ + if (ly_ctx_compile(ly_native_ctx) != LY_SUCCESS) { + flog_err(EC_LIB_YANG_MODULE_LOAD, + "%s: failed to compile loaded modules: %s", __func__, + ly_errmsg(ly_native_ctx)); + exit(1); + } +} + void yang_terminate(void) { struct yang_module *module; @@ -748,7 +780,7 @@ void yang_terminate(void) XFREE(MTYPE_YANG_MODULE, module); } - ly_ctx_destroy(ly_native_ctx, NULL); + ly_ctx_destroy(ly_native_ctx); } const struct lyd_node *yang_dnode_get_parent(const struct lyd_node *dnode, @@ -767,7 +799,7 @@ const struct lyd_node *yang_dnode_get_parent(const struct lyd_node *dnode, break; } - orig_dnode = orig_dnode->parent; + orig_dnode = lyd_parent(orig_dnode); } return NULL; @@ -788,17 +820,17 @@ bool yang_is_last_list_dnode(const struct lyd_node *dnode) bool yang_is_last_level_dnode(const struct lyd_node *dnode) { const struct lyd_node *parent; - const struct lys_node_list *snode; const struct lyd_node *key_leaf; uint8_t keys_size; switch (dnode->schema->nodetype) { case LYS_LIST: assert(dnode->parent); - parent = dnode->parent; - snode = (struct lys_node_list *)parent->schema; + parent = lyd_parent(dnode); + uint snode_num_keys = yang_snode_num_keys(parent->schema); + /* XXX libyang2: q: really don't understand this code. */ key_leaf = dnode->prev; - for (keys_size = 1; keys_size < snode->keys_size; keys_size++) + for (keys_size = 1; keys_size < snode_num_keys; keys_size++) key_leaf = key_leaf->prev; if (key_leaf->prev == dnode) return true; @@ -812,13 +844,11 @@ bool yang_is_last_level_dnode(const struct lyd_node *dnode) return false; } - const struct lyd_node * yang_get_subtree_with_no_sibling(const struct lyd_node *dnode) { bool parent = true; const struct lyd_node *node; - const struct lys_node_container *snode; node = dnode; if (node->schema->nodetype != LYS_LIST) @@ -827,13 +857,11 @@ yang_get_subtree_with_no_sibling(const struct lyd_node *dnode) while (parent) { switch (node->schema->nodetype) { case LYS_CONTAINER: - snode = (struct lys_node_container *)node->schema; - if ((!snode->presence) - && yang_is_last_level_dnode(node)) { + if (!CHECK_FLAG(node->schema->flags, LYS_PRESENCE)) { if (node->parent && (node->parent->schema->module == dnode->schema->module)) - node = node->parent; + node = lyd_parent(node); else parent = false; } else @@ -845,7 +873,7 @@ yang_get_subtree_with_no_sibling(const struct lyd_node *dnode) if (node->parent && (node->parent->schema->module == dnode->schema->module)) - node = node->parent; + node = lyd_parent(node); else parent = false; } else @@ -867,7 +895,7 @@ uint32_t yang_get_list_pos(const struct lyd_node *node) uint32_t yang_get_list_elements_count(const struct lyd_node *node) { unsigned int count; - struct lys_node *schema; + const struct lysc_node *schema; if (!node || ((node->schema->nodetype != LYS_LIST) @@ -884,11 +912,3 @@ uint32_t yang_get_list_elements_count(const struct lyd_node *node) } while (node); return count; } - - -const struct lyd_node *yang_dnode_get_child(const struct lyd_node *dnode) -{ - if (dnode) - return dnode->child; - return NULL; -} diff --git a/lib/yang.h b/lib/yang.h index b8bf07ee7e..d4517f969a 100644 --- a/lib/yang.h +++ b/lib/yang.h @@ -99,13 +99,10 @@ enum yang_iter_flags { /* Filter RPC input/output nodes. */ YANG_ITER_FILTER_INPUT_OUTPUT = (1<<2), - - /* Filter implicitely created nodes. */ - YANG_ITER_FILTER_IMPLICIT = (1<<3), }; /* Callback used by the yang_snodes_iterate_*() family of functions. */ -typedef int (*yang_iterate_cb)(const struct lys_node *snode, void *arg); +typedef int (*yang_iterate_cb)(const struct lysc_node *snode, void *arg); /* Callback used by the yang_dnode_iterate() function. */ typedef int (*yang_dnode_iter_cb)(const struct lyd_node *dnode, void *arg); @@ -180,7 +177,7 @@ extern void yang_module_embed(struct yang_module_embed *embed); * Returns: * The return value of the last called callback. */ -extern int yang_snodes_iterate_subtree(const struct lys_node *snode, +extern int yang_snodes_iterate_subtree(const struct lysc_node *snode, const struct lys_module *module, yang_iterate_cb cb, uint16_t flags, void *arg); @@ -222,7 +219,7 @@ extern int yang_snodes_iterate(const struct lys_module *module, * xpath_len * Size of the xpath buffer. */ -extern void yang_snode_get_path(const struct lys_node *snode, +extern void yang_snode_get_path(const struct lysc_node *snode, enum yang_path_type type, char *xpath, size_t xpath_len); @@ -236,7 +233,7 @@ extern void yang_snode_get_path(const struct lys_node *snode, * Returns: * The parent libyang schema node if found, or NULL if not found. */ -extern struct lys_node *yang_snode_real_parent(const struct lys_node *snode); +extern struct lysc_node *yang_snode_real_parent(const struct lysc_node *snode); /* * Find first parent schema node which is a list. @@ -247,7 +244,7 @@ extern struct lys_node *yang_snode_real_parent(const struct lys_node *snode); * Returns: * The parent libyang schema node (list) if found, or NULL if not found. */ -extern struct lys_node *yang_snode_parent_list(const struct lys_node *snode); +extern struct lysc_node *yang_snode_parent_list(const struct lysc_node *snode); /* * Check if the libyang schema node represents typeless data (e.g. containers, @@ -259,7 +256,7 @@ extern struct lys_node *yang_snode_parent_list(const struct lys_node *snode); * Returns: * true if the schema node represents typeless data, false otherwise. */ -extern bool yang_snode_is_typeless_data(const struct lys_node *snode); +extern bool yang_snode_is_typeless_data(const struct lysc_node *snode); /* * Get the default value associated to a YANG leaf or leaf-list. @@ -270,7 +267,7 @@ extern bool yang_snode_is_typeless_data(const struct lys_node *snode); * Returns: * The default value if it exists, NULL otherwise. */ -extern const char *yang_snode_get_default(const struct lys_node *snode); +extern const char *yang_snode_get_default(const struct lysc_node *snode); /* * Get the type structure of a leaf of leaf-list. If the type is a leafref, the @@ -283,7 +280,27 @@ extern const char *yang_snode_get_default(const struct lys_node *snode); * The found type if the schema node represents a leaf or a leaf-list, NULL * otherwise. */ -extern const struct lys_type *yang_snode_get_type(const struct lys_node *snode); +extern const struct lysc_type * +yang_snode_get_type(const struct lysc_node *snode); + +/* + * Get the number of key nodes for the given list. + * + * snode + * libyang (LYS_LIST) schema node to operate on. + * + * Returns: + * The number of key LYS_LEAFs as children of this list node. + */ +extern unsigned int yang_snode_num_keys(const struct lysc_node *snode); + +#define LY_FOR_KEYS(snode, skey) \ + for ((skey) = (const struct lysc_node_leaf *)lysc_node_child((snode)); \ + (skey); (skey) = (const struct lysc_node_leaf *)((skey)->next)) \ + if (!lysc_is_key(skey)) { \ + break; \ + } else + /* * Build data path of the data node. @@ -322,14 +339,49 @@ extern const char *yang_dnode_get_schema_name(const struct lyd_node *dnode, * dnode * Base libyang data node to operate on. * - * xpath_fmt - * XPath expression (absolute or relative). + * xpath + * Limited XPath (absolute or relative) string. See Path in libyang + * documentation for restrictions. * * Returns: * The libyang data node if found, or NULL if not found. */ extern struct lyd_node *yang_dnode_get(const struct lyd_node *dnode, - const char *xpath_fmt, ...); + const char *xpath); + +/* + * Find a libyang data node by its YANG data path. + * + * dnode + * Base libyang data node to operate on. + * + * xpath_fmt + * Limited XPath (absolute or relative) format string. See Path in libyang + * documentation for restrictions. + * + * ... + * any parameters for xpath_fmt. + * + * Returns: + * The libyang data node if found, or NULL if not found. + */ +extern struct lyd_node *yang_dnode_getf(const struct lyd_node *dnode, + const char *path_fmt, ...); + +/* + * Check if a libyang data node exists. + * + * dnode + * Base libyang data node to operate on. + * + * xpath + * Limited XPath (absolute or relative) string. See Path in libyang + * documentation for restrictions. + * + * Returns: + * true if a libyang data node was found, false otherwise. + */ +extern bool yang_dnode_exists(const struct lyd_node *dnode, const char *xpath); /* * Check if a libyang data node exists. @@ -338,13 +390,17 @@ extern struct lyd_node *yang_dnode_get(const struct lyd_node *dnode, * Base libyang data node to operate on. * * xpath_fmt - * XPath expression (absolute or relative). + * Limited XPath (absolute or relative) format string. See Path in + * libyang documentation for restrictions. + * + * ... + * any parameters for xpath_fmt. * * Returns: - * true if the libyang data node was found, false otherwise. + * true if a libyang data node was found, false otherwise. */ -extern bool yang_dnode_exists(const struct lyd_node *dnode, - const char *xpath_fmt, ...); +extern bool yang_dnode_existsf(const struct lyd_node *dnode, + const char *xpath_fmt, ...); /* * Iterate over all libyang data nodes that satisfy an XPath query. @@ -360,6 +416,9 @@ extern bool yang_dnode_exists(const struct lyd_node *dnode, * * xpath_fmt * XPath expression (absolute or relative). + * + * ... + * any parameters for xpath_fmt. */ void yang_dnode_iterate(yang_dnode_iter_cb cb, void *arg, const struct lyd_node *dnode, const char *xpath_fmt, @@ -372,7 +431,7 @@ void yang_dnode_iterate(yang_dnode_iter_cb cb, void *arg, * dnode * Base libyang data node to operate on. * - * xpath_fmt + * xpath * Optional XPath expression (absolute or relative) to specify a different * data node to operate on in the same data tree. * @@ -380,7 +439,27 @@ void yang_dnode_iterate(yang_dnode_iter_cb cb, void *arg, * true if the data node contains the default value, false otherwise. */ extern bool yang_dnode_is_default(const struct lyd_node *dnode, - const char *xpath_fmt, ...); + const char *xpath); + +/* + * Check if the libyang data node contains a default value. Non-presence + * containers are assumed to always contain a default value. + * + * dnode + * Base libyang data node to operate on. + * + * xpath + * Optional limited XPath (absolute or relative) format string. See Path in + * libyang documentation for restrictions. + * + * ... + * any parameters for xpath_fmt. + * + * Returns: + * true if the data node contains the default value, false otherwise. + */ +extern bool yang_dnode_is_defaultf(const struct lyd_node *dnode, + const char *xpath_fmt, ...); /* * Check if the libyang data node and all of its children contain default @@ -437,7 +516,8 @@ extern struct lyd_node *yang_dnode_dup(const struct lyd_node *dnode); * Delete a libyang data node. * * dnode - * Pointer to the libyang data node that is going to be deleted. + * Pointer to the libyang data node that is going to be deleted along with + * the entire tree it belongs to. */ extern void yang_dnode_free(struct lyd_node *dnode); @@ -493,8 +573,13 @@ extern struct yang_data *yang_data_list_find(const struct list *list, * * embedded_modules * Specify whether libyang should attempt to look for embedded YANG modules. + * + * explicit_compile + * True if the caller will later call ly_ctx_compile to compile all loaded + * modules at once. */ -extern struct ly_ctx *yang_ctx_new_setup(bool embedded_modules); +extern struct ly_ctx *yang_ctx_new_setup(bool embedded_modules, + bool explicit_compile); /* * Enable or disable libyang verbose debugging. @@ -528,8 +613,16 @@ extern const char *yang_print_errors(struct ly_ctx *ly_ctx, char *buf, * * embedded_modules * Specify whether libyang should attempt to look for embedded YANG modules. + * defer_compile + * Hold off on compiling modules until yang_init_loading_complete is called. */ -extern void yang_init(bool embedded_modules); +extern void yang_init(bool embedded_modules, bool defer_compile); + +/* + * Should be called after yang_init and all yang_module_load()s have been done, + * compiles all modules loaded into the yang context. + */ +extern void yang_init_loading_complete(void); /* * Finish the YANG subsystem gracefully. Should be called only when the daemon @@ -583,10 +676,6 @@ extern uint32_t yang_get_list_pos(const struct lyd_node *node); */ extern uint32_t yang_get_list_elements_count(const struct lyd_node *node); - -/* To get the immediate child of a dnode */ -const struct lyd_node *yang_dnode_get_child(const struct lyd_node *dnode); - /* API to check if the given node is last node in the list */ bool yang_is_last_list_dnode(const struct lyd_node *dnode); diff --git a/lib/yang_translator.c b/lib/yang_translator.c index 5b1d96f24c..d562e4d29e 100644 --- a/lib/yang_translator.c +++ b/lib/yang_translator.c @@ -93,7 +93,7 @@ yang_mapping_lookup(const struct yang_translator *translator, int dir, } static void yang_mapping_add(struct yang_translator *translator, int dir, - const struct lys_node *snode, + const struct lysc_node *snode, const char *xpath_from_fmt, const char *xpath_to_fmt) { @@ -135,13 +135,15 @@ struct yang_translator *yang_translator_load(const char *path) struct lyd_node *dnode; struct ly_set *set; struct listnode *ln; + LY_ERR err; /* Load module translator (JSON file). */ - dnode = lyd_parse_path(ly_translator_ctx, path, LYD_JSON, - LYD_OPT_CONFIG); - if (!dnode) { + err = lyd_parse_data_path(ly_translator_ctx, path, LYD_JSON, + LYD_PARSE_NO_STATE, LYD_VALIDATE_NO_STATE, + &dnode); + if (err) { flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD, - "%s: lyd_parse_path() failed", __func__); + "%s: lyd_parse_path() failed: %d", __func__, err); return NULL; } dnode = yang_dnode_get(dnode, @@ -171,89 +173,94 @@ struct yang_translator *yang_translator_load(const char *path) RB_INSERT(yang_translators, &yang_translators, translator); /* Initialize the translator libyang context. */ - translator->ly_ctx = yang_ctx_new_setup(false); + translator->ly_ctx = yang_ctx_new_setup(false, false); if (!translator->ly_ctx) { flog_warn(EC_LIB_LIBYANG, "%s: ly_ctx_new() failed", __func__); goto error; } - /* Load modules and deviations. */ - set = lyd_find_path(dnode, "./module"); - assert(set); - for (size_t i = 0; i < set->number; i++) { + /* Load modules */ + if (lyd_find_xpath(dnode, "./module", &set) != LY_SUCCESS) + assert(0); /* XXX libyang2: old ly1 code asserted success */ + + for (size_t i = 0; i < set->count; i++) { const char *module_name; tmodule = XCALLOC(MTYPE_YANG_TRANSLATOR_MODULE, sizeof(*tmodule)); - module_name = yang_dnode_get_string(set->set.d[i], "./name"); + module_name = yang_dnode_get_string(set->dnodes[i], "./name"); tmodule->module = ly_ctx_load_module(translator->ly_ctx, - module_name, NULL); + module_name, NULL, NULL); if (!tmodule->module) { flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD, "%s: failed to load module: %s", __func__, module_name); - ly_set_free(set); + ly_set_free(set, NULL); goto error; } + } - module_name = - yang_dnode_get_string(set->set.d[i], "./deviations"); - tmodule->deviations = ly_ctx_load_module(translator->ly_ctx, - module_name, NULL); + /* Count nodes in modules. */ + for (ALL_LIST_ELEMENTS_RO(translator->modules, ln, tmodule)) { + tmodule->nodes_before_deviations = + yang_module_nodes_count(tmodule->module); + } + + /* Load the deviations and count nodes again */ + for (ALL_LIST_ELEMENTS_RO(translator->modules, ln, tmodule)) { + const char *module_name = tmodule->module->name; + tmodule->deviations = ly_ctx_load_module( + translator->ly_ctx, module_name, NULL, NULL); if (!tmodule->deviations) { flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD, "%s: failed to load module: %s", __func__, module_name); - ly_set_free(set); + ly_set_free(set, NULL); goto error; } - lys_set_disabled(tmodule->deviations); - listnode_add(translator->modules, tmodule); + tmodule->nodes_after_deviations = + yang_module_nodes_count(tmodule->module); } - ly_set_free(set); + ly_set_free(set, NULL); /* Calculate the coverage. */ for (ALL_LIST_ELEMENTS_RO(translator->modules, ln, tmodule)) { - tmodule->nodes_before_deviations = - yang_module_nodes_count(tmodule->module); - - lys_set_enabled(tmodule->deviations); - - tmodule->nodes_after_deviations = - yang_module_nodes_count(tmodule->module); tmodule->coverage = ((double)tmodule->nodes_after_deviations / (double)tmodule->nodes_before_deviations) * 100; } /* Load mappings. */ - set = lyd_find_path(dnode, "./module/mappings"); - assert(set); - for (size_t i = 0; i < set->number; i++) { + if (lyd_find_xpath(dnode, "./module/mappings", &set) != LY_SUCCESS) + assert(0); /* XXX libyang2: old ly1 code asserted success */ + for (size_t i = 0; i < set->count; i++) { const char *xpath_custom, *xpath_native; - const struct lys_node *snode_custom, *snode_native; + const struct lysc_node *snode_custom, *snode_native; + + xpath_custom = + yang_dnode_get_string(set->dnodes[i], "./custom"); - xpath_custom = yang_dnode_get_string(set->set.d[i], "./custom"); - snode_custom = ly_ctx_get_node(translator->ly_ctx, NULL, - xpath_custom, 0); + snode_custom = lys_find_path(translator->ly_ctx, NULL, + xpath_custom, 0); if (!snode_custom) { flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD, "%s: unknown data path: %s", __func__, xpath_custom); - ly_set_free(set); + ly_set_free(set, NULL); goto error; } - xpath_native = yang_dnode_get_string(set->set.d[i], "./native"); + xpath_native = + yang_dnode_get_string(set->dnodes[i], "./native"); snode_native = - ly_ctx_get_node(ly_native_ctx, NULL, xpath_native, 0); + lys_find_path(ly_native_ctx, NULL, xpath_native, 0); if (!snode_native) { flog_warn(EC_LIB_YANG_TRANSLATOR_LOAD, "%s: unknown data path: %s", __func__, xpath_native); - ly_set_free(set); + ly_set_free(set, NULL); goto error; } @@ -262,7 +269,7 @@ struct yang_translator *yang_translator_load(const char *path) yang_mapping_add(translator, YANG_TRANSLATE_FROM_NATIVE, snode_native, xpath_native, xpath_custom); } - ly_set_free(set); + ly_set_free(set, NULL); /* Validate mappings. */ if (yang_translator_validate(translator) != 0) @@ -290,7 +297,7 @@ void yang_translator_unload(struct yang_translator *translator) hash_clean(translator->mappings[i], yang_mapping_hash_free); translator->modules->del = (void (*)(void *))yang_tmodule_delete; list_delete(&translator->modules); - ly_ctx_destroy(translator->ly_ctx, NULL); + ly_ctx_destroy(translator->ly_ctx); RB_REMOVE(yang_translators, &yang_translators, translator); XFREE(MTYPE_YANG_TRANSLATOR, translator); } @@ -308,7 +315,7 @@ yang_translate_xpath(const struct yang_translator *translator, int dir, char *xpath, size_t xpath_len) { struct ly_ctx *ly_ctx; - const struct lys_node *snode; + const struct lysc_node *snode; struct yang_mapping_node *mapping; char xpath_canonical[XPATH_MAXLEN]; char keys[4][LIST_MAXKEYLEN]; @@ -319,7 +326,7 @@ yang_translate_xpath(const struct yang_translator *translator, int dir, else ly_ctx = ly_native_ctx; - snode = ly_ctx_get_node(ly_ctx, NULL, xpath, 0); + snode = lys_find_path(ly_ctx, NULL, xpath, 0); if (!snode) { flog_warn(EC_LIB_YANG_TRANSLATION_ERROR, "%s: unknown data path: %s", __func__, xpath); @@ -352,7 +359,7 @@ int yang_translate_dnode(const struct yang_translator *translator, int dir, { struct ly_ctx *ly_ctx; struct lyd_node *new; - struct lyd_node *root, *next, *dnode_iter; + struct lyd_node *root, *dnode_iter; /* Create new libyang data node to hold the translated data. */ if (dir == YANG_TRANSLATE_TO_NATIVE) @@ -362,8 +369,8 @@ int yang_translate_dnode(const struct yang_translator *translator, int dir, new = yang_dnode_new(ly_ctx, false); /* Iterate over all nodes from the data tree. */ - LY_TREE_FOR (*dnode, root) { - LY_TREE_DFS_BEGIN (root, next, dnode_iter) { + LY_LIST_FOR (*dnode, root) { + LYD_TREE_DFS_BEGIN (root, dnode_iter) { char xpath[XPATH_MAXLEN]; enum yang_translate_result ret; @@ -380,19 +387,17 @@ int yang_translate_dnode(const struct yang_translator *translator, int dir, } /* Create new node in the tree of translated data. */ - ly_errno = 0; - if (!lyd_new_path(new, ly_ctx, xpath, - (void *)yang_dnode_get_string( - dnode_iter, NULL), - 0, LYD_PATH_OPT_UPDATE) - && ly_errno) { + if (lyd_new_path(new, ly_ctx, xpath, + (void *)yang_dnode_get_string( + dnode_iter, NULL), + LYD_NEW_PATH_UPDATE, NULL)) { flog_err(EC_LIB_LIBYANG, "%s: lyd_new_path() failed", __func__); goto error; } next: - LY_TREE_DFS_END(root, next, dnode_iter); + LYD_TREE_DFS_END(root, dnode_iter); } } @@ -413,13 +418,13 @@ struct translator_validate_args { unsigned int errors; }; -static int yang_translator_validate_cb(const struct lys_node *snode_custom, +static int yang_translator_validate_cb(const struct lysc_node *snode_custom, void *arg) { struct translator_validate_args *args = arg; struct yang_mapping_node *mapping; - const struct lys_node *snode_native; - const struct lys_type *stype_custom, *stype_native; + const struct lysc_node *snode_native; + const struct lysc_type *stype_custom, *stype_native; char xpath[XPATH_MAXLEN]; yang_snode_get_path(snode_custom, YANG_PATH_DATA, xpath, sizeof(xpath)); @@ -433,14 +438,14 @@ static int yang_translator_validate_cb(const struct lys_node *snode_custom, } snode_native = - ly_ctx_get_node(ly_native_ctx, NULL, mapping->xpath_to_fmt, 0); + lys_find_path(ly_native_ctx, NULL, mapping->xpath_to_fmt, 0); assert(snode_native); /* Check if the YANG types are compatible. */ stype_custom = yang_snode_get_type(snode_custom); stype_native = yang_snode_get_type(snode_native); if (stype_custom && stype_native) { - if (stype_custom->base != stype_native->base) { + if (stype_custom->basetype != stype_native->basetype) { flog_warn( EC_LIB_YANG_TRANSLATOR_LOAD, "%s: YANG types are incompatible (xpath: \"%s\")", @@ -486,7 +491,7 @@ static unsigned int yang_translator_validate(struct yang_translator *translator) return args.errors; } -static int yang_module_nodes_count_cb(const struct lys_node *snode, void *arg) +static int yang_module_nodes_count_cb(const struct lysc_node *snode, void *arg) { unsigned int *total = arg; @@ -511,14 +516,14 @@ static unsigned int yang_module_nodes_count(const struct lys_module *module) void yang_translator_init(void) { - ly_translator_ctx = yang_ctx_new_setup(true); + ly_translator_ctx = yang_ctx_new_setup(true, false); if (!ly_translator_ctx) { flog_err(EC_LIB_LIBYANG, "%s: ly_ctx_new() failed", __func__); exit(1); } if (!ly_ctx_load_module(ly_translator_ctx, "frr-module-translator", - NULL)) { + NULL, NULL)) { flog_err( EC_LIB_YANG_MODULE_LOAD, "%s: failed to load the \"frr-module-translator\" module", @@ -536,5 +541,5 @@ void yang_translator_terminate(void) yang_translator_unload(translator); } - ly_ctx_destroy(ly_translator_ctx, NULL); + ly_ctx_destroy(ly_translator_ctx); } diff --git a/lib/yang_wrappers.c b/lib/yang_wrappers.c index 98f8fea0fe..85aa003db7 100644 --- a/lib/yang_wrappers.c +++ b/lib/yang_wrappers.c @@ -26,12 +26,80 @@ #include "nexthop.h" #include "printfrr.h" + +#define YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt) \ + ({ \ + va_list __ap; \ + va_start(__ap, (xpath_fmt)); \ + const struct lyd_value *__dvalue = \ + yang_dnode_xpath_get_value(dnode, xpath_fmt, __ap); \ + va_end(__ap); \ + __dvalue; \ + }) + +#define YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt) \ + ({ \ + va_list __ap; \ + va_start(__ap, (xpath_fmt)); \ + const char *__canon = \ + yang_dnode_xpath_get_canon(dnode, xpath_fmt, __ap); \ + va_end(__ap); \ + __canon; \ + }) + +#define YANG_DNODE_GET_ASSERT(dnode, xpath) \ + do { \ + if ((dnode) == NULL) { \ + flog_err(EC_LIB_YANG_DNODE_NOT_FOUND, \ + "%s: couldn't find %s", __func__, (xpath)); \ + zlog_backtrace(LOG_ERR); \ + abort(); \ + } \ + } while (0) + +static inline const char * +yang_dnode_xpath_get_canon(const struct lyd_node *dnode, const char *xpath_fmt, + va_list ap) +{ + const struct lyd_node_term *__dleaf = + (const struct lyd_node_term *)dnode; + assert(__dleaf); + if (xpath_fmt) { + char __xpath[XPATH_MAXLEN]; + vsnprintf(__xpath, sizeof(__xpath), xpath_fmt, ap); + __dleaf = (const struct lyd_node_term *)yang_dnode_get(dnode, + __xpath); + YANG_DNODE_GET_ASSERT(__dleaf, __xpath); + } + return lyd_get_value(&__dleaf->node); +} + +static inline const struct lyd_value * +yang_dnode_xpath_get_value(const struct lyd_node *dnode, const char *xpath_fmt, + va_list ap) +{ + const struct lyd_node_term *__dleaf = + (const struct lyd_node_term *)dnode; + assert(__dleaf); + if (xpath_fmt) { + char __xpath[XPATH_MAXLEN]; + vsnprintf(__xpath, sizeof(__xpath), xpath_fmt, ap); + __dleaf = (const struct lyd_node_term *)yang_dnode_get(dnode, + __xpath); + YANG_DNODE_GET_ASSERT(__dleaf, __xpath); + } + const struct lyd_value *__dvalue = &__dleaf->value; + if (__dvalue->realtype->basetype == LY_TYPE_UNION) + __dvalue = &__dvalue->subvalue->value; + return __dvalue; +} + static const char *yang_get_default_value(const char *xpath) { - const struct lys_node *snode; + const struct lysc_node *snode; const char *value; - snode = ly_ctx_get_node(ly_native_ctx, NULL, xpath, 0); + snode = lys_find_path(ly_native_ctx, NULL, xpath, 0); if (snode == NULL) { flog_err(EC_LIB_YANG_UNKNOWN_DATA_PATH, "%s: unknown data path: %s", __func__, xpath); @@ -45,16 +113,6 @@ static const char *yang_get_default_value(const char *xpath) return value; } -#define YANG_DNODE_GET_ASSERT(dnode, xpath) \ - do { \ - if ((dnode) == NULL) { \ - flog_err(EC_LIB_YANG_DNODE_NOT_FOUND, \ - "%s: couldn't find %s", __func__, (xpath)); \ - zlog_backtrace(LOG_ERR); \ - abort(); \ - } \ - } while (0) - /* * Primitive type: bool. */ @@ -71,23 +129,10 @@ struct yang_data *yang_data_new_bool(const char *xpath, bool value) bool yang_dnode_get_bool(const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - 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); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_BOOL); - return dleaf->value.bln; + const struct lyd_value *dvalue; + dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); + assert(dvalue->realtype->basetype == LY_TYPE_BOOL); + return dvalue->boolean; } bool yang_get_default_bool(const char *xpath_fmt, ...) @@ -133,24 +178,18 @@ struct yang_data *yang_data_new_dec64(const char *xpath, double value) double yang_dnode_get_dec64(const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - 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); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } + const double denom[19] = {1e0, 1e-1, 1e-2, 1e-3, 1e-4, + 1e-5, 1e-6, 1e-7, 1e-8, 1e-9, + 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, + 1e-15, 1e-16, 1e-17, 1e-18}; + const struct lysc_type_dec *dectype; + const struct lyd_value *dvalue; - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_DEC64); - - return lyd_dec64_to_double(dnode); + dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); + dectype = (const struct lysc_type_dec *)dvalue->realtype; + assert(dectype->basetype == LY_TYPE_DEC64); + assert(dectype->fraction_digits < sizeof(denom) / sizeof(*denom)); + return (double)dvalue->dec64 * denom[dectype->fraction_digits]; } double yang_get_default_dec64(const char *xpath_fmt, ...) @@ -172,12 +211,12 @@ double yang_get_default_dec64(const char *xpath_fmt, ...) */ int yang_str2enum(const char *xpath, const char *value) { - const struct lys_node *snode; - const struct lys_node_leaf *sleaf; - const struct lys_type *type; - const struct lys_type_info_enums *enums; + const struct lysc_node *snode; + const struct lysc_node_leaf *sleaf; + const struct lysc_type_enum *type; + const struct lysc_type_bitenum_item *enums; - snode = ly_ctx_get_node(ly_native_ctx, NULL, xpath, 0); + snode = lys_find_path(ly_native_ctx, NULL, xpath, 0); if (snode == NULL) { flog_err(EC_LIB_YANG_UNKNOWN_DATA_PATH, "%s: unknown data path: %s", __func__, xpath); @@ -185,18 +224,17 @@ int yang_str2enum(const char *xpath, const char *value) abort(); } - sleaf = (const struct lys_node_leaf *)snode; - type = &sleaf->type; - enums = &type->info.enums; - while (enums->count == 0 && type->der) { - type = &type->der->type; - enums = &type->info.enums; - } - for (unsigned int i = 0; i < enums->count; i++) { - const struct lys_type_enum *enm = &enums->enm[i]; - - if (strmatch(value, enm->name)) - return enm->value; + assert(snode->nodetype == LYS_LEAF); + sleaf = (const struct lysc_node_leaf *)snode; + type = (const struct lysc_type_enum *)sleaf->type; + assert(type->basetype == LY_TYPE_ENUM); + enums = type->enums; + unsigned int count = LY_ARRAY_COUNT(enums); + for (unsigned int i = 0; i < count; i++) { + if (strmatch(value, enums[i].name)) { + assert(CHECK_FLAG(enums[i].flags, LYS_SET_VALUE)); + return enums[i].value; + } } flog_err(EC_LIB_YANG_DATA_CONVERT, @@ -208,12 +246,12 @@ int yang_str2enum(const char *xpath, const char *value) struct yang_data *yang_data_new_enum(const char *xpath, int value) { - const struct lys_node *snode; - const struct lys_node_leaf *sleaf; - const struct lys_type *type; - const struct lys_type_info_enums *enums; + const struct lysc_node *snode; + const struct lysc_node_leaf *sleaf; + const struct lysc_type_enum *type; + const struct lysc_type_bitenum_item *enums; - snode = ly_ctx_get_node(ly_native_ctx, NULL, xpath, 0); + snode = lys_find_path(ly_native_ctx, NULL, xpath, 0); if (snode == NULL) { flog_err(EC_LIB_YANG_UNKNOWN_DATA_PATH, "%s: unknown data path: %s", __func__, xpath); @@ -221,18 +259,16 @@ struct yang_data *yang_data_new_enum(const char *xpath, int value) abort(); } - sleaf = (const struct lys_node_leaf *)snode; - type = &sleaf->type; - enums = &type->info.enums; - while (enums->count == 0 && type->der) { - type = &type->der->type; - enums = &type->info.enums; - } - for (unsigned int i = 0; i < enums->count; i++) { - const struct lys_type_enum *enm = &enums->enm[i]; - - if (value == enm->value) - return yang_data_new(xpath, enm->name); + assert(snode->nodetype == LYS_LEAF); + sleaf = (const struct lysc_node_leaf *)snode; + type = (const struct lysc_type_enum *)sleaf->type; + assert(type->basetype == LY_TYPE_ENUM); + enums = type->enums; + unsigned int count = LY_ARRAY_COUNT(enums); + for (unsigned int i = 0; i < count; i++) { + if (CHECK_FLAG(enums[i].flags, LYS_SET_VALUE) + && value == enums[i].value) + return yang_data_new(xpath, enums[i].name); } flog_err(EC_LIB_YANG_DATA_CONVERT, @@ -245,23 +281,12 @@ struct yang_data *yang_data_new_enum(const char *xpath, int value) int yang_dnode_get_enum(const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; + const struct lyd_value *dvalue; - assert(dnode); - 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); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_ENUM); - return dleaf->value.enm->value; + dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); + assert(dvalue->realtype->basetype == LY_TYPE_ENUM); + assert(dvalue->enum_item->flags & LYS_SET_VALUE); + return dvalue->enum_item->value; } int yang_get_default_enum(const char *xpath_fmt, ...) @@ -297,23 +322,10 @@ struct yang_data *yang_data_new_int8(const char *xpath, int8_t value) int8_t yang_dnode_get_int8(const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - 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); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_INT8); - return dleaf->value.int8; + const struct lyd_value *dvalue; + dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); + assert(dvalue->realtype->basetype == LY_TYPE_INT8); + return dvalue->int8; } int8_t yang_get_default_int8(const char *xpath_fmt, ...) @@ -349,23 +361,10 @@ struct yang_data *yang_data_new_int16(const char *xpath, int16_t value) int16_t yang_dnode_get_int16(const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - 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); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_INT16); - return dleaf->value.int16; + const struct lyd_value *dvalue; + dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); + assert(dvalue->realtype->basetype == LY_TYPE_INT16); + return dvalue->int16; } int16_t yang_get_default_int16(const char *xpath_fmt, ...) @@ -401,23 +400,10 @@ struct yang_data *yang_data_new_int32(const char *xpath, int32_t value) int32_t yang_dnode_get_int32(const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - 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); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_INT32); - return dleaf->value.int32; + const struct lyd_value *dvalue; + dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); + assert(dvalue->realtype->basetype == LY_TYPE_INT32); + return dvalue->int32; } int32_t yang_get_default_int32(const char *xpath_fmt, ...) @@ -453,23 +439,10 @@ struct yang_data *yang_data_new_int64(const char *xpath, int64_t value) int64_t yang_dnode_get_int64(const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - 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); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_INT64); - return dleaf->value.int64; + const struct lyd_value *dvalue; + dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); + assert(dvalue->realtype->basetype == LY_TYPE_INT64); + return dvalue->int64; } int64_t yang_get_default_int64(const char *xpath_fmt, ...) @@ -505,23 +478,10 @@ struct yang_data *yang_data_new_uint8(const char *xpath, uint8_t value) uint8_t yang_dnode_get_uint8(const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - 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); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_UINT8); - return dleaf->value.uint8; + const struct lyd_value *dvalue; + dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); + assert(dvalue->realtype->basetype == LY_TYPE_UINT8); + return dvalue->uint8; } uint8_t yang_get_default_uint8(const char *xpath_fmt, ...) @@ -557,23 +517,10 @@ struct yang_data *yang_data_new_uint16(const char *xpath, uint16_t value) uint16_t yang_dnode_get_uint16(const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - 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); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_UINT16); - return dleaf->value.uint16; + const struct lyd_value *dvalue; + dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); + assert(dvalue->realtype->basetype == LY_TYPE_UINT16); + return dvalue->uint16; } uint16_t yang_get_default_uint16(const char *xpath_fmt, ...) @@ -609,23 +556,10 @@ struct yang_data *yang_data_new_uint32(const char *xpath, uint32_t value) uint32_t yang_dnode_get_uint32(const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - 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); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_UINT32); - return dleaf->value.uint32; + const struct lyd_value *dvalue; + dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); + assert(dvalue->realtype->basetype == LY_TYPE_UINT32); + return dvalue->uint32; } uint32_t yang_get_default_uint32(const char *xpath_fmt, ...) @@ -661,23 +595,10 @@ struct yang_data *yang_data_new_uint64(const char *xpath, uint64_t value) uint64_t yang_dnode_get_uint64(const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - 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); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_UINT64); - return dleaf->value.uint64; + const struct lyd_value *dvalue; + dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); + assert(dvalue->realtype->basetype == LY_TYPE_UINT64); + return dvalue->uint64; } uint64_t yang_get_default_uint64(const char *xpath_fmt, ...) @@ -707,44 +628,15 @@ struct yang_data *yang_data_new_string(const char *xpath, const char *value) const char *yang_dnode_get_string(const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - 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); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - return dleaf->value_str; + return YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); } void yang_dnode_get_string_buf(char *buf, size_t size, const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - 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); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - if (strlcpy(buf, dleaf->value_str, size) >= size) { + const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); + if (strlcpy(buf, canon, size) >= size) { char xpath[XPATH_MAXLEN]; yang_dnode_get_path(dnode, xpath, sizeof(xpath)); @@ -797,7 +689,7 @@ bool yang_dnode_get_empty(const struct lyd_node *dnode, const char *xpath_fmt, { va_list ap; char xpath[XPATH_MAXLEN]; - const struct lyd_node_leaf_list *dleaf; + const struct lyd_node_term *dleaf; assert(dnode); @@ -807,8 +699,8 @@ bool yang_dnode_get_empty(const struct lyd_node *dnode, const char *xpath_fmt, dnode = yang_dnode_get(dnode, xpath); if (dnode) { - dleaf = (const struct lyd_node_leaf_list *)dnode; - if (dleaf->value_type == LY_TYPE_EMPTY) + dleaf = (const struct lyd_node_term *)dnode; + if (dleaf->value.realtype->basetype == LY_TYPE_EMPTY) return true; } @@ -836,29 +728,16 @@ struct yang_data *yang_data_new_prefix(const char *xpath, void yang_dnode_get_prefix(struct prefix *prefix, const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - 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); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - + const char *canon; /* * Initialize prefix to avoid static analyzer complaints about * uninitialized memory. */ memset(prefix, 0, sizeof(*prefix)); - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_STRING); - (void)str2prefix(dleaf->value_str, prefix); + /* XXX ip_prefix is a native type now in ly2, leverage? */ + canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); + (void)str2prefix(canon, prefix); } void yang_get_default_prefix(union prefixptr var, const char *xpath_fmt, ...) @@ -895,23 +774,9 @@ struct yang_data *yang_data_new_ipv4(const char *xpath, void yang_dnode_get_ipv4(struct in_addr *addr, const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - 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); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_STRING); - (void)inet_pton(AF_INET, dleaf->value_str, addr); + /* XXX libyang2 IPv4 address is a native type now in ly2 */ + const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); + (void)inet_pton(AF_INET, canon, addr); } void yang_get_default_ipv4(struct in_addr *var, const char *xpath_fmt, ...) @@ -951,24 +816,10 @@ struct yang_data *yang_data_new_ipv4p(const char *xpath, void yang_dnode_get_ipv4p(union prefixptr prefix, const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; struct prefix_ipv4 *prefix4 = prefix.p4; - - assert(dnode); - 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); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_STRING); - (void)str2prefix_ipv4(dleaf->value_str, prefix4); + /* XXX libyang2: ipv4/6 address is a native type now in ly2 */ + const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); + (void)str2prefix_ipv4(canon, prefix4); } void yang_get_default_ipv4p(union prefixptr var, const char *xpath_fmt, ...) @@ -1005,23 +856,9 @@ struct yang_data *yang_data_new_ipv6(const char *xpath, void yang_dnode_get_ipv6(struct in6_addr *addr, const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - 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); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_STRING); - (void)inet_pton(AF_INET6, dleaf->value_str, addr); + /* XXX libyang2: IPv6 address is a native type now, leverage. */ + const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); + (void)inet_pton(AF_INET6, canon, addr); } void yang_get_default_ipv6(struct in6_addr *var, const char *xpath_fmt, ...) @@ -1061,24 +898,11 @@ struct yang_data *yang_data_new_ipv6p(const char *xpath, void yang_dnode_get_ipv6p(union prefixptr prefix, const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; struct prefix_ipv6 *prefix6 = prefix.p6; - assert(dnode); - 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); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_STRING); - (void)str2prefix_ipv6(dleaf->value_str, prefix6); + /* XXX IPv6 address is a native type now in ly2 -- can we leverage? */ + const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); + (void)str2prefix_ipv6(canon, prefix6); } void yang_get_default_ipv6p(union prefixptr var, const char *xpath_fmt, ...) @@ -1115,23 +939,9 @@ struct yang_data *yang_data_new_ip(const char *xpath, const struct ipaddr *addr) void yang_dnode_get_ip(struct ipaddr *addr, const struct lyd_node *dnode, const char *xpath_fmt, ...) { - const struct lyd_node_leaf_list *dleaf; - - assert(dnode); - 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); - YANG_DNODE_GET_ASSERT(dnode, xpath); - } - - dleaf = (const struct lyd_node_leaf_list *)dnode; - assert(dleaf->value_type == LY_TYPE_STRING); - (void)str2ipaddr(dleaf->value_str, addr); + /* XXX IPv4 address could be a plugin type now in ly2, leverage? */ + const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); + (void)str2ipaddr(canon, addr); } void yang_get_default_ip(struct ipaddr *var, const char *xpath_fmt, ...) |
