forked from Mirror/frr
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 <chopps@labn.net>
This commit is contained in:
parent
cf67a7e265
commit
1e4229fc1f
|
@ -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 <libyang/libyang.h>]])
|
||||
|
||||
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 ---------------
|
||||
|
|
|
@ -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;
|
||||
|
|
85
lib/vty.c
85
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:
|
||||
|
|
176
lib/yang.c
176
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
|
||||
}
|
||||
|
|
21
lib/yang.h
21
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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue