From: Christian Hopps Date: Thu, 4 Jan 2024 06:33:04 +0000 (+0000) Subject: lib: remove unused/replaced oper-state iteration code X-Git-Tag: base_10.0~157^2 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=refs%2Fpull%2F15086%2Fhead;p=mirror%2Ffrr.git lib: remove unused/replaced oper-state iteration code Signed-off-by: Christian Hopps --- diff --git a/lib/northbound.c b/lib/northbound.c index bf5cc912b5..18d65e47f1 100644 --- a/lib/northbound.c +++ b/lib/northbound.c @@ -70,12 +70,6 @@ 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 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 lyd_node *pdnode); static int nb_node_check_config_only(const struct lysc_node *snode, void *arg) { @@ -1811,540 +1805,6 @@ static void nb_transaction_apply_finish(struct nb_transaction *transaction, } } -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 lyd_node *pdnode) -{ - const struct lysc_node *child; - - LY_LIST_FOR (lysc_node_child(snode), child) { - int ret; - - ret = nb_oper_data_iter_node(child, xpath, list_entry, - list_keys, translator, false, - flags, cb, arg, pdnode); - if (ret != NB_OK) - return ret; - } - - return NB_OK; -} - -static int nb_oper_data_iter_leaf(const struct nb_node *nb_node, - const char *xpath, const void *list_entry, - const struct yang_list_keys *list_keys, - struct yang_translator *translator, - uint32_t flags, nb_oper_data_cb cb, void *arg, - struct lyd_node *pdnode) -{ - const struct lysc_node *snode = nb_node->snode; - struct yang_data *data; - LY_ERR err = LY_SUCCESS; - - - if (CHECK_FLAG(snode->flags, LYS_CONFIG_W)) - return NB_OK; - - /* Ignore list keys. */ - if (lysc_is_key(snode)) - return NB_OK; - - data = nb_callback_get_elem(nb_node, xpath, list_entry); - if (data == NULL) - /* Leaf of type "empty" is not present. */ - return NB_OK; - - /* - * Add a dnode to our tree - */ - err = lyd_new_term(pdnode, snode->module, snode->name, data->value, - false, NULL); - if (err) - return NB_ERR_RESOURCE; - - if (cb) - return (*cb)(nb_node->snode, translator, data, arg); - return NB_OK; -} - -static int nb_oper_data_iter_container(const struct nb_node *nb_node, - const char *xpath, bool first, - const void *list_entry, - const struct yang_list_keys *list_keys, - struct yang_translator *translator, - uint32_t flags, nb_oper_data_cb cb, - void *arg, struct lyd_node *pdnode) -{ - const struct lysc_node *snode = nb_node->snode; - struct lyd_node *cnode = NULL; - bool presence = false; - LY_ERR err; - int ret; - - if (CHECK_FLAG(nb_node->flags, F_NB_NODE_CONFIG_ONLY)) - return NB_OK; - - if (pdnode->schema == snode) - assert(first); - else - assert(!first); - - /* Read-only presence containers. */ - if (nb_node->cbs.get_elem) { - struct yang_data *data; - int ret; - - presence = true; - data = nb_callback_get_elem(nb_node, xpath, list_entry); - if (data == NULL) - /* Presence container is not present. */ - return NB_OK; - - if (!first) { - err = lyd_new_inner(pdnode, snode->module, snode->name, - false, &cnode); - if (err) - return NB_ERR_RESOURCE; - } - - if (cb) { - ret = (*cb)(snode, translator, data, arg); - if (ret != NB_OK) - return ret; - } - } - - if (first) - cnode = pdnode; - else if (!cnode) { - /* Add a node in for this container in-case we have children. */ - err = lyd_new_inner(pdnode, snode->module, snode->name, false, - &cnode); - if (err) - return NB_ERR_RESOURCE; - } - - /* Iterate over the child nodes. */ - ret = nb_oper_data_iter_children(snode, xpath, list_entry, list_keys, - translator, false, flags, cb, arg, - cnode); - - /* TODO: here we are freeing only if we created; however, we may want to - * also free if pdnode was cnode on entry to cleanup the data tree - */ - /* If we aren't presence container and we gained no children remove */ - if (!presence && !first && !lyd_child(cnode)) - lyd_free_tree(cnode); - - return ret; -} - -static int -nb_oper_data_iter_leaflist(const struct nb_node *nb_node, const char *xpath, - const void *parent_list_entry, - const struct yang_list_keys *parent_list_keys, - struct yang_translator *translator, uint32_t flags, - nb_oper_data_cb cb, void *arg, - struct lyd_node *pdnode) -{ - const struct lysc_node *snode = nb_node->snode; - const void *list_entry = NULL; - LY_ERR err; - - if (CHECK_FLAG(snode->flags, LYS_CONFIG_W)) - return NB_OK; - - do { - struct yang_data *data; - int ret; - - list_entry = nb_callback_get_next(nb_node, parent_list_entry, - list_entry); - if (!list_entry) - /* End of the list. */ - break; - - data = nb_callback_get_elem(nb_node, xpath, list_entry); - if (data == NULL) - continue; - - /* - * Add a dnode to our tree - */ - err = lyd_new_term(pdnode, snode->module, snode->name, - data->value, false, NULL); - if (err) - return NB_ERR_RESOURCE; - - if (cb) { - ret = (*cb)(nb_node->snode, translator, data, arg); - if (ret != NB_OK) - return ret; - } - } while (list_entry); - - return NB_OK; -} - -static int nb_oper_data_iter_list(const struct nb_node *nb_node, - const char *xpath_list, - const void *parent_list_entry, - const struct yang_list_keys *parent_list_keys, - struct yang_translator *translator, - uint32_t flags, nb_oper_data_cb cb, void *arg, - struct lyd_node *pdnode) -{ - char xpath[XPATH_MAXLEN * 2]; - const struct lysc_node *snode = nb_node->snode; - const void *list_entry = NULL; - struct lyd_node *list_node = NULL; - const char *key_preds = NULL; - uint32_t position = 1; - LY_ERR err; - - if (CHECK_FLAG(nb_node->flags, F_NB_NODE_CONFIG_ONLY)) - return NB_OK; - - /* Iterate over all list entries. */ - do { - struct yang_list_keys list_keys = {}; - int len, ret; - - /* Obtain list entry. */ - list_entry = nb_callback_get_next(nb_node, parent_list_entry, - list_entry); - if (!list_entry) - /* End of the list. */ - break; - - if (!CHECK_FLAG(nb_node->flags, F_NB_NODE_KEYLESS_LIST)) { - /* Obtain the list entry keys. */ - if (nb_callback_get_keys(nb_node, list_entry, - &list_keys) - != NB_OK) { - flog_warn(EC_LIB_NB_CB_STATE, - "%s: failed to get list keys", - __func__); - return NB_ERR; - } - - /* Build XPath of the list entry. */ - strlcpy(xpath, xpath_list, sizeof(xpath)); - len = strlen(xpath); - key_preds = &xpath[len]; - - uint n = yang_get_key_preds(xpath + len, snode, - &list_keys, - sizeof(xpath) - len); - assert(n == list_keys.num); - - } else { - /* - * Keyless list - build XPath using a positional index. - */ - snprintf(xpath, sizeof(xpath), "%s[%u]", xpath_list, - position); - position++; - } - - /* - * `pdnode` needs to point at lib - and it does for - * "/frr-vrf:lib/vrf" need to test "/frr-vrf:lib" too though - */ - err = lyd_new_list2(pdnode, snode->module, snode->name, - key_preds, false, &list_node); - if (err) - return NB_ERR_RESOURCE; - - /* Iterate over the child nodes. */ - ret = nb_oper_data_iter_children(nb_node->snode, xpath, - list_entry, &list_keys, - translator, false, flags, cb, - arg, list_node); - if (ret != NB_OK) - return ret; - } while (list_entry); - - return NB_OK; -} - -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, - struct yang_translator *translator, bool first, - uint32_t flags, nb_oper_data_cb cb, void *arg, - struct lyd_node *pdnode) -{ - struct nb_node *nb_node; - char xpath[XPATH_MAXLEN]; - int ret = NB_OK; - - if (!first && CHECK_FLAG(flags, NB_OPER_DATA_ITER_NORECURSE) - && CHECK_FLAG(snode->nodetype, LYS_CONTAINER | LYS_LIST)) - return NB_OK; - - /* - * would be nice to just be building a libyang data tree here as well - */ - - /* Update XPath. */ - strlcpy(xpath, xpath_parent, sizeof(xpath)); - if (!first && snode->nodetype != LYS_USES) { - struct lysc_node *parent; - - /* Get the real parent. */ - parent = snode->parent; - - /* - * When necessary, include the namespace of the augmenting - * module. - */ - if (parent && parent->module != snode->module) - snprintf(xpath + strlen(xpath), - sizeof(xpath) - strlen(xpath), "/%s:%s", - snode->module->name, snode->name); - else - snprintf(xpath + strlen(xpath), - sizeof(xpath) - strlen(xpath), "/%s", - snode->name); - } - - nb_node = snode->priv; - switch (snode->nodetype) { - case LYS_CONTAINER: - /* does something, then walks children */ - ret = nb_oper_data_iter_container(nb_node, xpath, first, - list_entry, list_keys, - translator, flags, cb, arg, - pdnode); - - break; - case LYS_LEAF: - /* does something then returns */ - ret = nb_oper_data_iter_leaf(nb_node, xpath, list_entry, - list_keys, translator, flags, cb, - arg, pdnode); - break; - case LYS_LEAFLIST: - /* walks leaf list doing things and returns */ - ret = nb_oper_data_iter_leaflist(nb_node, xpath, list_entry, - list_keys, translator, flags, - cb, arg, pdnode); - break; - case LYS_LIST: - /* walks children */ - ret = nb_oper_data_iter_list(nb_node, xpath, list_entry, - list_keys, translator, flags, cb, - arg, pdnode); - break; - case LYS_USES: - /* walks children */ - ret = nb_oper_data_iter_children(snode, xpath, list_entry, - list_keys, translator, false, - flags, cb, arg, pdnode); - break; - default: - break; - } - - return ret; -} - -static int nb_xpath_dirname(char *xpath) -{ - int len = strlen(xpath); - bool abs = xpath[0] == '/'; - char *slash; - - /* "//" or "/" => NULL */ - if (abs && (len == 1 || (len == 2 && xpath[1] == '/'))) - return NB_ERR_NOT_FOUND; - slash = (char *)frrstr_back_to_char(xpath, '/'); - /* "/foo/bar/" or "/foo/bar//" => "/foo " */ - if (slash && slash == &xpath[len - 1]) { - xpath[--len] = 0; - slash = (char *)frrstr_back_to_char(xpath, '/'); - if (slash && slash == &xpath[len - 1]) { - xpath[--len] = 0; - slash = (char *)frrstr_back_to_char(xpath, '/'); - } - } - if (!slash) - return NB_ERR_NOT_FOUND; - *slash = 0; - return NB_OK; -} - -static int nb_oper_data_xpath_to_tree(const char *xpath_in, - struct lyd_node **dnode, - bool is_top_node_list) -{ - /* Eventually this function will loop until it finds a concrete path */ - char *xpath; - LY_ERR err; - int ret; - - err = lyd_new_path2(NULL, ly_native_ctx, xpath_in, NULL, 0, 0, - LYD_NEW_PATH_UPDATE, NULL, dnode); - if (err == LY_SUCCESS) - return NB_OK; - if (!is_top_node_list) - return NB_ERR_NOT_FOUND; - - xpath = XSTRDUP(MTYPE_TMP, xpath_in); - ret = nb_xpath_dirname(xpath); - if (ret != NB_OK) - goto done; - - err = lyd_new_path2(NULL, ly_native_ctx, xpath, NULL, 0, 0, - LYD_NEW_PATH_UPDATE, NULL, dnode); - if (err != LY_SUCCESS) - ret = NB_ERR_NOT_FOUND; -done: - XFREE(MTYPE_TMP, xpath); - return ret; -} - -int nb_oper_data_iterate(const char *xpath, struct yang_translator *translator, - uint32_t flags, nb_oper_data_cb cb, void *arg, - struct lyd_node **tree) -{ - struct nb_node *nb_node; - const void *list_entry = NULL; - struct yang_list_keys list_keys; - struct list *list_dnodes; - struct lyd_node *dnode, *dn; - struct listnode *ln; - int ret; - - nb_node = nb_node_find(xpath); - if (!nb_node) { - flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH, - "%s: unknown data path: %s", __func__, xpath); - return NB_ERR; - } - - /* For now this function works only with containers and lists. */ - if (!CHECK_FLAG(nb_node->snode->nodetype, LYS_CONTAINER | LYS_LIST)) { - flog_warn( - EC_LIB_NB_OPERATIONAL_DATA, - "%s: can't iterate over YANG leaf or leaf-list [xpath %s]", - __func__, xpath); - return NB_ERR; - } - - /* - * Create a data tree from the XPath so that we can parse the keys of - * all YANG lists (if any). - */ - - ret = nb_oper_data_xpath_to_tree(xpath, &dnode, - nb_node->snode->nodetype == LYS_LIST); - if (ret) { - flog_warn(EC_LIB_LIBYANG, - "%s: can't instantiate concrete path using xpath: %s", - __func__, xpath); - return ret; - } - assert(dnode); - - /* - * Create a linked list to sort the data nodes starting from the root. - */ - list_dnodes = list_new(); - for (dn = dnode; dn; dn = lyd_parent(dn)) - if (dn->schema->nodetype == LYS_LIST) - listnode_add_head(list_dnodes, dn); - - /* - * Use the northbound callbacks to find list entry pointer corresponding - * to the given XPath. - */ - for (ALL_LIST_ELEMENTS_RO(list_dnodes, ln, dn)) { - struct lyd_node *child; - struct nb_node *nn; - unsigned int n = 0; - - /* Obtain the list entry keys. */ - memset(&list_keys, 0, sizeof(list_keys)); - 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 != yang_snode_num_keys(dn->schema)) { - flog_warn( - EC_LIB_NB_OPERATIONAL_DATA, - "%s: internal list entry '%s' missing required key values predicates in xpath: %s", - __func__, dn->schema->name, xpath); - list_delete(&list_dnodes); - yang_dnode_free(dnode); - return NB_ERR_NOT_FOUND; - } - - /* Find the list entry pointer. */ - nn = dn->schema->priv; - if (!nn->cbs.lookup_entry) { - flog_warn( - EC_LIB_NB_OPERATIONAL_DATA, - "%s: data path doesn't support iteration over operational data: %s", - __func__, xpath); - list_delete(&list_dnodes); - yang_dnode_free(dnode); - return NB_ERR; - } - - /* NOTE: To add support for multiple levels of unspecified keys - * we need to loop here using the list entry's get_next to work - * with each "existing in the data" list entry. It will be a bit - * tricky b/c we are inside a loop here. - */ - list_entry = - nb_callback_lookup_entry(nn, list_entry, &list_keys); - if (list_entry == NULL) { - list_delete(&list_dnodes); - yang_dnode_free(dnode); - return NB_ERR_NOT_FOUND; - } - } - - /* If a list entry was given with keys as the last node in the path, - * iterate over that list entry only. - */ - if (dnode->schema->nodetype == LYS_LIST && lyd_child(dnode) - && dnode->schema == nb_node->snode) - ret = nb_oper_data_iter_children(nb_node->snode, xpath, - list_entry, &list_keys, - translator, true, flags, cb, - arg, dnode); - else - ret = nb_oper_data_iter_node(nb_node->snode, xpath, list_entry, - &list_keys, translator, true, - flags, cb, arg, dnode); - - list_delete(&list_dnodes); - while (lyd_parent(dnode)) - dnode = lyd_parent(dnode); - - if (tree && ret == NB_OK) - *tree = dnode; - else { - lyd_free_all(dnode); - if (tree) - *tree = NULL; - } - - return ret; -} - bool nb_operation_is_valid(enum nb_operation operation, const struct lysc_node *snode) { diff --git a/lib/northbound.h b/lib/northbound.h index 850397d221..018d09fac7 100644 --- a/lib/northbound.h +++ b/lib/northbound.h @@ -1295,11 +1295,6 @@ extern int nb_running_unlock(enum nb_client client, const void *user); */ extern int nb_running_lock_check(enum nb_client client, const void *user); -extern int nb_oper_data_iterate(const char *xpath, - struct yang_translator *translator, - uint32_t flags, nb_oper_data_cb cb, void *arg, - struct lyd_node **tree); - /* * Iterate over operational data -- deprecated. * @@ -1333,7 +1328,7 @@ extern enum nb_error nb_oper_iterate_legacy(const char *xpath, void *arg, struct lyd_node **tree); /** - * nb_op_walk() - walk the schema building operational state. + * nb_oper_walk() - walk the schema building operational state. * @xpath - * @translator - * @flags - @@ -1351,7 +1346,7 @@ extern void *nb_oper_walk(const char *xpath, struct yang_translator *translator, void *finish_arg); /** - * nb_op_iterate_yielding_cancel() - cancel the in progress walk. + * nb_oper_cancel_walk() - cancel the in progress walk. * @walk - value returned from nb_op_iterate_yielding() * * Should only be called on an in-progress walk. It is invalid to cancel and