From: Christian Hopps Date: Sat, 6 Jan 2024 11:06:38 +0000 (+0000) Subject: lib: use libyang functions if they are present X-Git-Tag: base_10.0~137^2~1 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=1e4229fc1f843f88e9c9bc6ec4700489a455e6cf;p=matthieu%2Ffrr.git lib: use libyang functions if they are present Add configure.ac tests for libyang functions, if not present supply the functionality ourselves in yang.[ch] Signed-off-by: Christian Hopps --- diff --git a/configure.ac b/configure.ac index a3b0370ec0..00cf6451fa 100644 --- a/configure.ac +++ b/configure.ac @@ -1968,6 +1968,13 @@ AC_CHECK_MEMBER([struct lyd_node.priv], [], [ Instructions for this are included in the build documentation for your platform at http://docs.frrouting.org/projects/dev-guide/en/latest/building.html]) ]) ], [[#include ]]) + +AC_CHECK_LIB([yang],[lyd_find_xpath3],[],[AC_MSG_ERROR([m4_normalize([ +libyang missing lyd_find_xpath3])])]) +dnl -- don't add lyd_new_list3 to this list unless bug is fixed upstream +dnl -- https://github.com/CESNET/libyang/issues/2149 +AC_CHECK_FUNCS([ly_strerrcode ly_strvecode lyd_trim_xpath]) + CFLAGS="$ac_cflags_save" dnl --------------- diff --git a/lib/northbound_oper.c b/lib/northbound_oper.c index 4e131154e7..78106e4e45 100644 --- a/lib/northbound_oper.c +++ b/lib/northbound_oper.c @@ -1409,11 +1409,8 @@ static enum nb_error __walk(struct nb_op_yield_state *ys, bool is_resume) */ if (!node) { - /* NOTE: can also use lyd_new_list2 here when available */ err = yang_lyd_new_list(ni[-1].inner, sib, - &ni->keys, - (struct lyd_node_inner * - *)&node); + &ni->keys, &node); if (err) { darr_pop(ys->node_infos); ret = NB_ERR_RESOURCE; diff --git a/lib/vty.c b/lib/vty.c index a08a3c8735..0ee610e3aa 100644 --- a/lib/vty.c +++ b/lib/vty.c @@ -3688,88 +3688,9 @@ static void vty_out_yang_error(struct vty *vty, LYD_FORMAT format, else if (ei->level == LY_LLWRN) severity = "warning"; - switch (ei->no) { - case LY_SUCCESS: - ecode = "ok"; - break; - case LY_EMEM: - ecode = "out of memory"; - break; - case LY_ESYS: - ecode = "system error"; - break; - case LY_EINVAL: - ecode = "invalid value given"; - break; - case LY_EEXIST: - ecode = "item exists"; - break; - case LY_ENOTFOUND: - ecode = "item not found"; - break; - case LY_EINT: - ecode = "operation interrupted"; - break; - case LY_EVALID: - ecode = "validation failed"; - break; - case LY_EDENIED: - ecode = "access denied"; - break; - case LY_EINCOMPLETE: - ecode = "incomplete"; - break; - case LY_ERECOMPILE: - ecode = "compile error"; - break; - case LY_ENOT: - ecode = "not"; - break; - default: - case LY_EPLUGIN: - case LY_EOTHER: - ecode = "other"; - break; - } - - if (err == LY_EVALID) { - switch (ei->vecode) { - case LYVE_SUCCESS: - evalid = NULL; - break; - case LYVE_SYNTAX: - evalid = "syntax"; - break; - case LYVE_SYNTAX_YANG: - evalid = "yang-syntax"; - break; - case LYVE_SYNTAX_YIN: - evalid = "yin-syntax"; - break; - case LYVE_REFERENCE: - evalid = "reference"; - break; - case LYVE_XPATH: - evalid = "xpath"; - break; - case LYVE_SEMANTICS: - evalid = "semantics"; - break; - case LYVE_SYNTAX_XML: - evalid = "xml-syntax"; - break; - case LYVE_SYNTAX_JSON: - evalid = "json-syntax"; - break; - case LYVE_DATA: - evalid = "data"; - break; - default: - case LYVE_OTHER: - evalid = "other"; - break; - } - } + ecode = yang_ly_strerrcode(err); + if (err == LY_EVALID && ei->vecode != LYVE_SUCCESS) + evalid = yang_ly_strvecode(ei->vecode); switch (format) { case LYD_XML: diff --git a/lib/yang.c b/lib/yang.c index b2cc71b309..2860108d64 100644 --- a/lib/yang.c +++ b/lib/yang.c @@ -999,86 +999,109 @@ int yang_get_node_keys(struct lyd_node *node, struct yang_list_keys *keys) return NB_OK; } +/* + * ------------------------ + * Libyang Future Functions + * ------------------------ + * + * All these functions are implemented in libyang versions (perhaps unreleased) + * beyond what we require currently so we must supply the functionality. + */ + +/* + * Safe to remove after libyang v2.1.xxx is required (.144 has a bug so + * something > .144) https://github.com/CESNET/libyang/issues/2149 + */ LY_ERR yang_lyd_new_list(struct lyd_node_inner *parent, const struct lysc_node *snode, const struct yang_list_keys *list_keys, - struct lyd_node_inner **node) + struct lyd_node **node) { +#if defined(HAVE_LYD_NEW_LIST3) && 0 + LY_ERR err; + const char *keys[LIST_MAXKEYS]; + + assert(list_keys->num <= LIST_MAXKEYS); + for (int i = 0; i < list_keys->num; i++) + keys[i] = list_keys->key[i]; + + err = lyd_new_list3(&parent->node, snode->module, snode->name, keys, + NULL, 0, node); + return err; +#else struct lyd_node *pnode = &parent->node; - struct lyd_node **nodepp = (struct lyd_node **)node; const char(*keys)[LIST_MAXKEYLEN] = list_keys->key; - /* - * When - * https://github.com/CESNET/libyang/commit/2c1e327c7c2dd3ba12d466a4ebcf62c1c44116c4 - * is released in libyang we should add a configure.ac check for the - * lyd_new_list3 function and use it here. - */ + assert(list_keys->num <= 8); switch (list_keys->num) { case 0: return lyd_new_list(pnode, snode->module, snode->name, false, - nodepp); + node); case 1: return lyd_new_list(pnode, snode->module, snode->name, false, - nodepp, keys[0]); + node, keys[0]); case 2: return lyd_new_list(pnode, snode->module, snode->name, false, - nodepp, keys[0], keys[1]); + node, keys[0], keys[1]); case 3: return lyd_new_list(pnode, snode->module, snode->name, false, - nodepp, keys[0], keys[1], keys[2]); + node, keys[0], keys[1], keys[2]); case 4: return lyd_new_list(pnode, snode->module, snode->name, false, - nodepp, keys[0], keys[1], keys[2], keys[3]); + node, keys[0], keys[1], keys[2], keys[3]); case 5: return lyd_new_list(pnode, snode->module, snode->name, false, - nodepp, keys[0], keys[1], keys[2], keys[3], + node, keys[0], keys[1], keys[2], keys[3], keys[4]); case 6: return lyd_new_list(pnode, snode->module, snode->name, false, - nodepp, keys[0], keys[1], keys[2], keys[3], + node, keys[0], keys[1], keys[2], keys[3], keys[4], keys[5]); case 7: return lyd_new_list(pnode, snode->module, snode->name, false, - nodepp, keys[0], keys[1], keys[2], keys[3], + node, keys[0], keys[1], keys[2], keys[3], keys[4], keys[5], keys[6]); case 8: return lyd_new_list(pnode, snode->module, snode->name, false, - nodepp, keys[0], keys[1], keys[2], keys[3], + node, keys[0], keys[1], keys[2], keys[3], keys[4], keys[5], keys[6], keys[7]); } _Static_assert(LIST_MAXKEYS == 8, "max key mismatch in switch unroll"); /*NOTREACHED*/ return LY_EINVAL; +#endif } -int yang_trim_tree(struct lyd_node *root, const char *xpath) +/* + * Safe to remove after libyang v2.1.144 is required + */ +LY_ERR yang_lyd_trim_xpath(struct lyd_node **root, const char *xpath) { - enum nb_error ret = NB_OK; LY_ERR err; -#if 0 - err = lyd_trim_xpath(&root, xpath, NULL); +#ifdef HAVE_LYD_TRIM_XPATH + err = lyd_trim_xpath(root, xpath, NULL); if (err) { flog_err_sys(EC_LIB_LIBYANG, - "cannot obtain specific result for xpath \"%s\"", - xpath); - return NB_ERR; + "cannot obtain specific result for xpath \"%s\": %s", + xpath, yang_ly_strerrcode(err)); + return err; } - return NB_OK; + return LY_SUCCESS; #else struct lyd_node *node; struct lyd_node **remove = NULL; struct ly_set *set = NULL; uint32_t i; - err = lyd_find_xpath3(NULL, root, xpath, NULL, &set); + *root = lyd_first_sibling(*root); + + err = lyd_find_xpath3(NULL, *root, xpath, NULL, &set); if (err) { flog_err_sys(EC_LIB_LIBYANG, - "cannot obtain specific result for xpath \"%s\"", - xpath); - ret = NB_ERR; - goto done; + "cannot obtain specific result for xpath \"%s\": %s", + xpath, yang_ly_strerrcode(err)); + return err; } /* * Mark keepers and sweep deleting non-keepers. @@ -1100,7 +1123,7 @@ int yang_trim_tree(struct lyd_node *root, const char *xpath) } darr_ensure_cap(remove, 128); - LYD_TREE_DFS_BEGIN (root, node) { + LYD_TREE_DFS_BEGIN (*root, node) { /* * If this is a direct matching node then include it's subtree * which won't be marked and would otherwise be removed. @@ -1108,19 +1131,100 @@ int yang_trim_tree(struct lyd_node *root, const char *xpath) if (node->priv == (void *)2) LYD_TREE_DFS_continue = 1; else if (!node->priv) { - LYD_TREE_DFS_continue = 1; *darr_append(remove) = node; + LYD_TREE_DFS_continue = 1; } - LYD_TREE_DFS_END(root, node); + LYD_TREE_DFS_END(*root, node); } - darr_foreach_i (remove, i) + darr_foreach_i (remove, i) { + if (remove[i] == *root) + *root = (*root)->next; lyd_free_tree(remove[i]); + } darr_free(remove); -done: if (set) ly_set_free(set, NULL); - return ret; + return LY_SUCCESS; +#endif +} + +/* + * Safe to remove after libyang v2.1.128 is required + */ +const char *yang_ly_strerrcode(LY_ERR err) +{ +#ifdef HAVE_LY_STRERRCODE + return ly_strerrcode(err); +#else + switch (err) { + case LY_SUCCESS: + return "ok"; + case LY_EMEM: + return "out of memory"; + case LY_ESYS: + return "system error"; + case LY_EINVAL: + return "invalid value given"; + case LY_EEXIST: + return "item exists"; + case LY_ENOTFOUND: + return "item not found"; + case LY_EINT: + return "operation interrupted"; + case LY_EVALID: + return "validation failed"; + case LY_EDENIED: + return "access denied"; + case LY_EINCOMPLETE: + return "incomplete"; + case LY_ERECOMPILE: + return "compile error"; + case LY_ENOT: + return "not"; + case LY_EPLUGIN: + case LY_EOTHER: + return "other"; + default: + return "unknown"; + } +#endif +} + +/* + * Safe to remove after libyang v2.1.128 is required + */ +const char *yang_ly_strvecode(LY_VECODE vecode) +{ +#ifdef HAVE_LY_STRVECODE + return ly_strvecode(vecode); +#else + switch (vecode) { + case LYVE_SUCCESS: + return ""; + case LYVE_SYNTAX: + return "syntax"; + case LYVE_SYNTAX_YANG: + return "yang-syntax"; + case LYVE_SYNTAX_YIN: + return "yin-syntax"; + case LYVE_REFERENCE: + return "reference"; + case LYVE_XPATH: + return "xpath"; + case LYVE_SEMANTICS: + return "semantics"; + case LYVE_SYNTAX_XML: + return "xml-syntax"; + case LYVE_SYNTAX_JSON: + return "json-syntax"; + case LYVE_DATA: + return "data"; + case LYVE_OTHER: + return "other"; + default: + return "unknown"; + } #endif } diff --git a/lib/yang.h b/lib/yang.h index 75dcab2d2a..dbb7f7163b 100644 --- a/lib/yang.h +++ b/lib/yang.h @@ -719,11 +719,6 @@ extern int yang_get_key_preds(char *s, const struct lysc_node *snode, /* Get YANG keys from an existing dnode */ extern int yang_get_node_keys(struct lyd_node *node, struct yang_list_keys *keys); -/* Create a new list lyd_node using `yang_list_keys` */ -extern LY_ERR yang_lyd_new_list(struct lyd_node_inner *parent, - const struct lysc_node *snode, - const struct yang_list_keys *keys, - struct lyd_node_inner **node); /** * yang_resolve_snodes() - Resolve an XPath to matching schema nodes. * @ly_ctx: libyang context to operate on. @@ -744,14 +739,16 @@ extern LY_ERR yang_lyd_new_list(struct lyd_node_inner *parent, extern LY_ERR yang_resolve_snode_xpath(struct ly_ctx *ly_ctx, const char *xpath, struct lysc_node ***snodes, bool *simple); -/** - * yang_trim_tree() - trim the data tree to the given xpath - * @root: the data tree - * @xpath: the xpath to trim @root to. - * - * Return: enum nb_error.. +/* + * Libyang future functions */ -extern int yang_trim_tree(struct lyd_node *root, const char *xpath); +extern const char *yang_ly_strerrcode(LY_ERR err); +extern const char *yang_ly_strvecode(LY_VECODE vecode); +extern LY_ERR yang_lyd_new_list(struct lyd_node_inner *parent, + const struct lysc_node *snode, + const struct yang_list_keys *keys, + struct lyd_node **nodes); +extern LY_ERR yang_lyd_trim_xpath(struct lyd_node **rootp, const char *xpath); #ifdef __cplusplus } diff --git a/mgmtd/mgmt_txn.c b/mgmtd/mgmt_txn.c index 1c64445631..297482f015 100644 --- a/mgmtd/mgmt_txn.c +++ b/mgmtd/mgmt_txn.c @@ -1278,8 +1278,9 @@ static int txn_get_tree_data_done(struct mgmt_txn_ctx *txn, /* * We have a complex query so Filter results by the xpath query. */ - ret = yang_trim_tree(get_tree->client_results, - txn_req->req.get_tree->xpath); + if (yang_lyd_trim_xpath(&get_tree->client_results, + txn_req->req.get_tree->xpath)) + ret = NB_ERR; } if (ret == NB_OK)