diff options
| -rw-r--r-- | configure.ac | 7 | ||||
| -rw-r--r-- | lib/northbound_oper.c | 5 | ||||
| -rw-r--r-- | lib/vty.c | 85 | ||||
| -rw-r--r-- | lib/yang.c | 176 | ||||
| -rw-r--r-- | lib/yang.h | 21 | ||||
| -rw-r--r-- | mgmtd/mgmt_txn.c | 5 | 
6 files changed, 163 insertions, 136 deletions
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 <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 --------------- 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; @@ -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)  | 
