YANG optimization: move "when" and "mymodule" to external maps

This commit is contained in:
Olof hagsand 2024-08-10 17:38:12 +02:00
parent 275cefbae7
commit c08dac2e5d
13 changed files with 247 additions and 314 deletions

View file

@ -116,6 +116,7 @@ backend_terminate(clixon_handle h)
if ((yspec = clicon_dbspec_yang(h)) != NULL){
ys_free(yspec);
}
yang_exit(h);
if ((yspec = clicon_config_yang(h)) != NULL)
ys_free(yspec);
if ((yspec = clicon_nacm_ext_yang(h)) != NULL)

View file

@ -180,6 +180,7 @@ cli_terminate(clixon_handle h)
clicon_rpc_close_session(h);
if ((yspec = clicon_dbspec_yang(h)) != NULL)
ys_free(yspec);
yang_exit(h);
if ((yspec = clicon_config_yang(h)) != NULL)
ys_free(yspec);
if ((nsctx = clicon_nsctx_global_get(h)) != NULL)

View file

@ -588,6 +588,7 @@ netconf_terminate(clixon_handle h)
ys_free(yspec);
if ((yspec = clicon_config_yang(h)) != NULL)
ys_free(yspec);
yang_exit(h);
if ((nsctx = clicon_nsctx_global_get(h)) != NULL)
cvec_free(nsctx);
if ((x = clicon_conf_xml(h)) != NULL)

View file

@ -365,12 +365,12 @@ restconf_terminate(clixon_handle h)
close(fs);
/* Delete all plugins, and RPC callbacks */
clixon_plugin_module_exit(h);
clicon_rpc_close_session(h);
if ((yspec = clicon_dbspec_yang(h)) != NULL)
ys_free(yspec);
if ((yspec = clicon_config_yang(h)) != NULL)
ys_free(yspec);
yang_exit(h);
if ((nsctx = clicon_nsctx_global_get(h)) != NULL)
cvec_free(nsctx);
if ((x = clicon_conf_xml(h)) != NULL)

View file

@ -126,6 +126,7 @@ snmp_terminate(clixon_handle h)
ys_free(yspec);
if ((yspec = clicon_config_yang(h)) != NULL)
ys_free(yspec);
yang_exit(h);
if ((nsctx = clicon_nsctx_global_get(h)) != NULL)
cvec_free(nsctx);
if ((x = clicon_conf_xml(h)) != NULL)

View file

@ -90,8 +90,10 @@
* Set by yang_mount_set
* Read by ys_free1
*/
#define YANG_FLAG_WHEN 0x400 /* Use extended struct to access when-info for
#define YANG_FLAG_WHEN 0x400 /* Use external map to access when-info for
* augment/grouping */
#define YANG_FLAG_MYMODULE 0x800 /* Use external map to access my-module for
* UNKNOWNS and augment/grouping */
/*
* Types
@ -252,10 +254,10 @@ int yang_ref_dec(yang_stmt *ys);
uint16_t yang_flag_get(yang_stmt *ys, uint16_t flag);
int yang_flag_set(yang_stmt *ys, uint16_t flag);
int yang_flag_reset(yang_stmt *ys, uint16_t flag);
yang_stmt *yang_when_get(clixon_handle h, yang_stmt *ys);
int yang_when_set(clixon_handle h, yang_stmt *ys, yang_stmt *ywhen);
char *yang_when_xpath_get(yang_stmt *ys);
int yang_when_xpath_set(yang_stmt *ys, char *xpath);
cvec *yang_when_nsc_get(yang_stmt *ys);
int yang_when_nsc_set(yang_stmt *ys, cvec *nsc);
const char *yang_filename_get(yang_stmt *ys);
int yang_filename_set(yang_stmt *ys, const char *filename);
uint32_t yang_linenum_get(yang_stmt *ys);
@ -279,7 +281,6 @@ int ys_free(yang_stmt *ys);
int ys_cp_one(yang_stmt *nw, yang_stmt *old);
int ys_cp(yang_stmt *nw, yang_stmt *old);
yang_stmt *ys_dup(yang_stmt *old);
yang_stmt *yse_dup(yang_stmt *old);
int yn_insert(yang_stmt *ys_parent, yang_stmt *ys_child);
int yn_insert1(yang_stmt *ys_parent, yang_stmt *ys_child);
yang_stmt *yn_iter(yang_stmt *yparent, int *inext);
@ -326,10 +327,11 @@ int yang_type_cache_set2(yang_stmt *ys, yang_stmt *resolved, int options,
yang_stmt *yang_anydata_add(yang_stmt *yp, char *name);
int yang_extension_value(yang_stmt *ys, char *name, char *ns, int *exist, char **value);
int yang_sort_subelements(yang_stmt *ys);
int yang_init(clixon_handle h);
int yang_single_child_type(yang_stmt *ys, enum rfc_6020 subkeyw);
void *yang_action_cb_get(yang_stmt *ys);
int yang_action_cb_add(yang_stmt *ys, void *rc);
int ys_populate_feature(clixon_handle h, yang_stmt *ys);
int yang_init(clixon_handle h);
int yang_exit(clixon_handle h);
#endif /* _CLIXON_YANG_H_ */

View file

@ -324,6 +324,8 @@ check_when_condition(cxobj *x0p,
}
retval = 1;
done:
if (nsc)
cvec_free(nsc);
if (cberr)
cbuf_free(cberr);
return retval;

View file

@ -2089,7 +2089,6 @@ yang_check_when_xpath(cxobj *xn,
int nr = 0;
cvec *nsc = NULL;
int xmalloc = 0; /* ugly help variable to clean temporary object */
int nscmalloc = 0; /* ugly help variable to remove */
/* First variant */
if ((xpath = yang_when_xpath_get(yn)) != NULL){
@ -2111,7 +2110,6 @@ yang_check_when_xpath(cxobj *xn,
x = xn;
if (xml_nsctx_yang(yn, &nsc) < 0)
goto done;
nscmalloc++;
*hit = 1;
}
else
@ -2128,7 +2126,7 @@ yang_check_when_xpath(cxobj *xn,
done:
if (xmalloc)
xml_purge(x);
if (nsc && nscmalloc)
if (nsc)
xml_nsctx_free(nsc);
return retval;
}

View file

@ -174,6 +174,10 @@ static const map_str2int ykmap[] = {
{NULL, -1}
};
/* XXX: Global variables, should really be on handle but not available in some cases */
static map_ptr2ptr *_yang_when_map = NULL;
static map_ptr2ptr *_yang_mymodule_map = NULL;
/* Forward static */
static int yang_type_cache_free(yang_type_cache *ycache);
static int yang_type_cache_cp(yang_stmt *ynew, yang_stmt *yold);
@ -266,8 +270,6 @@ yang_argument_set(yang_stmt *ys,
yang_stmt *
yang_orig_get(yang_stmt *ys)
{
if (ys->ys_orig)
assert(ys->ys_orig->ys_orig == NULL);
return ys->ys_orig;
}
@ -283,7 +285,6 @@ yang_orig_set(yang_stmt *ys,
yang_stmt *y0)
{
if (y0->ys_orig){
assert(y0->ys_orig->ys_orig == NULL);
yang_orig_set(ys, y0->ys_orig);
}
else
@ -299,7 +300,6 @@ yang_orig_set(yang_stmt *ys,
cg_var*
yang_cv_get(yang_stmt *ys)
{
// assert(ys->ys_keyword == Y_FEATURE ||ys->ys_keyword == Y_LEAF || ys->ys_keyword == Y_LEAF_LIST || ys->ys_keyword == Y_CONFIG || ys->ys_keyword == Y_MANDATORY || ys->ys_keyword == Y_MAX_ELEMENTS|| ys->ys_keyword == Y_MIN_ELEMENTS || ys->ys_keyword == Y_REQUIRE_INSTANCE || ys->ys_keyword == Y_FRACTION_DIGITS || ys->ys_keyword == Y_REVISION || ys->ys_keyword == Y_REVISION_DATE || ys->ys_keyword == Y_UNKNOWN || ys->ys_keyword == Y_SPEC || ys->ys_keyword == Y_ENUM);
return ys->ys_cv;
}
@ -314,7 +314,6 @@ int
yang_cv_set(yang_stmt *ys,
cg_var *cv)
{
// assert(ys->ys_keyword == Y_FEATURE || ys->ys_keyword == Y_LEAF || ys->ys_keyword == Y_LEAF_LIST || ys->ys_keyword == Y_CONFIG || ys->ys_keyword == Y_MANDATORY || ys->ys_keyword == Y_MAX_ELEMENTS|| ys->ys_keyword == Y_MIN_ELEMENTS || ys->ys_keyword == Y_REQUIRE_INSTANCE || ys->ys_keyword == Y_FRACTION_DIGITS || ys->ys_keyword == Y_REVISION || ys->ys_keyword == Y_REVISION_DATE || ys->ys_keyword == Y_UNKNOWN || ys->ys_keyword == Y_SPEC || ys->ys_keyword == Y_ENUM);
if (cv != NULL && ys->ys_cv != NULL)
cv_free(ys->ys_cv);
ys->ys_cv = cv;
@ -330,7 +329,6 @@ yang_cv_set(yang_stmt *ys,
cvec*
yang_cvec_get(yang_stmt *ys)
{
// assert(ys->ys_keyword == Y_EXTENSION || ys->ys_keyword == Y_IDENTITY ||ys->ys_keyword == Y_LENGTH || ys->ys_keyword == Y_LIST ||ys->ys_keyword == Y_RANGE || ys->ys_keyword == Y_TYPE ||ys->ys_keyword == Y_UNIQUE ||ys->ys_keyword == Y_CONTAINER);
return ys->ys_cvec;
}
@ -345,7 +343,6 @@ int
yang_cvec_set(yang_stmt *ys,
cvec *cvv)
{
// assert(ys->ys_keyword == Y_EXTENSION || ys->ys_keyword == Y_IDENTITY ||ys->ys_keyword == Y_LENGTH || ys->ys_keyword == Y_LIST ||ys->ys_keyword == Y_RANGE || ys->ys_keyword == Y_TYPE ||ys->ys_keyword == Y_UNIQUE ||ys->ys_keyword == Y_CONTAINER);
if (ys->ys_cvec)
cvec_free(ys->ys_cvec);
ys->ys_cvec = cvv;
@ -368,7 +365,6 @@ yang_cvec_add(yang_stmt *ys,
cg_var *cv;
cvec *cvv;
// assert(ys->ys_keyword == Y_EXTENSION || ys->ys_keyword == Y_IDENTITY ||ys->ys_keyword == Y_LENGTH || ys->ys_keyword == Y_LIST ||ys->ys_keyword == Y_RANGE || ys->ys_keyword == Y_TYPE ||ys->ys_keyword == Y_UNIQUE ||ys->ys_keyword == Y_CONTAINER);
if ((cvv = yang_cvec_get(ys)) == NULL){
if ((cvv = cvec_new(0)) == NULL){
clixon_err(OE_YANG, errno, "cvec_new");
@ -470,6 +466,65 @@ yang_flag_reset(yang_stmt *ys,
return 0;
}
/*! Get Yang when statement from external map
*
* @param[in] h Clixon handle (may be NULL)
* @param[in] ys Yang statement
* @retval ywhen Yang when statement
* @retval NULL No yang when
* @note h may be NULL since may not be available by caller
*/
yang_stmt *
yang_when_get(clixon_handle h,
yang_stmt *ys)
{
map_ptr2ptr *mp = _yang_when_map;
if (mp == NULL){
clixon_log(h, LOG_WARNING, "when_map not defined, yang_init() not called?");
return NULL;
}
else {
if (yang_flag_get(ys, YANG_FLAG_WHEN) != 0x0 && mp != NULL)
return clixon_ptr2ptr(mp, ys);
}
return NULL;
}
/*! Set Yang when statement to external map
*
* @param[in] h Clixon handle
* @param[in] ys Yang statement
* @param[int] ywhen Yang when statement
* @retval 0 OK
* @retval -1 Error
*/
int
yang_when_set(clixon_handle h,
yang_stmt *ys,
yang_stmt *ywhen)
{
int retval = -1;
map_ptr2ptr *mp = _yang_when_map;
if (mp == NULL){
clixon_log(h, LOG_WARNING, "when_map not defined, yang_init() not called?");
goto done;
}
else {
if (clixon_ptr2ptr(mp, ys) != NULL) {
clixon_err(OE_YANG, 0, "when pointer already set");
goto done;
}
if (clixon_ptr2ptr_add(&_yang_when_map, ys, ywhen) < 0)
goto done;
yang_flag_set(ys, YANG_FLAG_WHEN);
}
retval = 0;
done:
return retval;
}
/*! Get yang xpath for "when"-associated augment
*
* Ie, for yang structures like: augment <path> { when <xpath>; ... }
@ -483,46 +538,11 @@ yang_flag_reset(yang_stmt *ys,
char*
yang_when_xpath_get(yang_stmt *ys)
{
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
yang_stmt *ywhen;
if ((ys->ys_flags & YANG_FLAG_WHEN) == 0x0)
if ((ywhen = yang_when_get(NULL, ys)) != NULL)
return yang_argument_get(ywhen);
return NULL;
else
return yse->yse_when_xpath;
}
/*! Set yang xpath and namespace context for "when"-associated augment
*
* Ie, for yang structures like: augment <path> { when <xpath>; ... }
* Will insert new yang nodes at <path> with this special "when" struct (not yang node)
* @param[in] ys Yang statement
* @param[in] xpath If set, this xpath should evaluate to true at validation, copied
* @retval 0 OK
* @retval -1 Error
*/
int
yang_when_xpath_set(yang_stmt *ys,
char *xpath)
{
int retval = -1;
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
if (xpath == NULL){
clixon_err(OE_YANG, EINVAL, "xpath is NULL");
goto done;
}
if ((ys->ys_flags & YANG_FLAG_WHEN) == 0x0){
clixon_err(OE_YANG, EINVAL, "Yang node %s %s must have flag YANG_FLAG_WHEN for this operation",
yang_key2str(ys->ys_keyword), ys->ys_argument);
goto done;
}
if ((yse->yse_when_xpath = strdup(xpath)) == NULL){
clixon_err(OE_YANG, errno, "strdup");
goto done;
}
retval = 0;
done:
return retval;
}
/*! Get yang namespace context for "when"-associated augment
@ -530,48 +550,20 @@ yang_when_xpath_set(yang_stmt *ys,
* Ie, for yang structures like: augment <path> { when <xpath>; ... }
* Will insert new yang nodes at <path> with this special "when" struct (not yang node)
* @param[in] ys Yang statement
* @retval nsc Namespace context
* @retval nsc Namespace context (caller frees with cvec_free)
* @note retval is direct pointer, may need to be copied
*/
cvec *
yang_when_nsc_get(yang_stmt *ys)
{
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
yang_stmt *ywhen;
cvec *wnsc = NULL;
if ((ys->ys_flags & YANG_FLAG_WHEN) == 0x0)
return NULL;
else
return yse->yse_when_nsc;
}
/*! Set yang namespace context for "when"-associated augment
*
* Ie, for yang structures like: augment <path> { when <xpath>; ... }
* Will insert new yang nodes at <path> with this special "when" struct (not yang node)
* @param[in] ys Yang statement
* @param[in] nsc Namespace context for when xpath
* @retval 0 OK
* @retval -1 Error
*/
int
yang_when_nsc_set(yang_stmt *ys,
cvec *nsc)
{
int retval = -1;
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
if ((ys->ys_flags & YANG_FLAG_WHEN) == 0x0){
clixon_err(OE_YANG, EINVAL, "Yang node %s %s must have flag YANG_FLAG_WHEN for this operation",
yang_key2str(ys->ys_keyword), ys->ys_argument);
return -1;
if ((ywhen = yang_when_get(NULL, ys)) != NULL) {
if (xml_nsctx_yang(ywhen, &wnsc) < 0)
wnsc = NULL;
}
if (nsc && (yse->yse_when_nsc = cvec_dup(nsc)) == NULL){
clixon_err(OE_YANG, errno, "cvec_dup");
goto done;
}
retval = 0;
done:
return retval;
return wnsc;
}
/*! Get yang filename for error/debug purpose (only modules)
@ -671,7 +663,16 @@ yang_typecache_set(yang_stmt *ys,
yang_stmt*
yang_mymodule_get(yang_stmt *ys)
{
return ys->ys_mymodule;
map_ptr2ptr *mp = _yang_mymodule_map;
if (mp == NULL){
clixon_log(NULL, LOG_WARNING, "mymodule_map not defined, yang_init() not called?");
return NULL;
}
else if (yang_flag_get(ys, YANG_FLAG_MYMODULE) == 0x0)
return NULL;
else
return clixon_ptr2ptr(mp, ys);
}
/*! Set mymodule
@ -686,8 +687,23 @@ int
yang_mymodule_set(yang_stmt *ys,
yang_stmt *ym)
{
ys->ys_mymodule = ym;
return 0;
int retval = -1;
map_ptr2ptr *mp = _yang_mymodule_map;
if (mp == NULL){
clixon_log(NULL, LOG_WARNING, "mymodule_map not defined, yang_init() not called?");
goto done;
}
else {
if (clixon_ptr2ptr(mp, ys) == NULL) {
if (clixon_ptr2ptr_add(&_yang_mymodule_map, ys, ym) < 0)
goto done;
}
}
yang_flag_set(ys, YANG_FLAG_MYMODULE);
retval = 0;
done:
return retval;
}
/* End access functions */
@ -721,22 +737,12 @@ yang_stats_one(yang_stmt *ys,
size_t sz = 0;
yang_type_cache *yc;
if (yang_flag_get(ys, YANG_FLAG_WHEN) == 0x0)
sz += sizeof(struct yang_stmt_extended);
else
sz += sizeof(struct yang_stmt);
sz += ys->ys_len*sizeof(struct yang_stmt*);
if (ys->ys_argument)
sz += strlen(ys->ys_argument) + 1;
if (ys->ys_cvec)
sz += cvec_size(ys->ys_cvec);
if (yang_flag_get(ys, YANG_FLAG_WHEN) != 0x0) {
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
if (yse->yse_when_xpath)
sz += strlen(yse->yse_when_xpath) + 1;
if (yse->yse_when_nsc)
sz += cvec_size(yse->yse_when_nsc);
}
switch (ys->ys_keyword) {
case Y_TYPE:
if ((yc = yang_typecache_get(ys)) != NULL){
@ -863,22 +869,6 @@ ys_new(enum rfc_6020 keyw)
return ys_new_sz(keyw, sizeof(struct yang_stmt));
}
/*! Create new extended yang node/statement
*
* @param[in] keyw Yang stmt keyword
* @retval ys New yang-stmt. Free with ys_free()
* @retval NULL Error
*/
static yang_stmt *
yse_new(enum rfc_6020 keyw)
{
yang_stmt *ys;
if ((ys = ys_new_sz(keyw, sizeof(struct yang_stmt_extended))) != NULL)
yang_flag_set(ys, YANG_FLAG_WHEN);
return ys;
}
/*! Free a single yang statement, dont remove children, called after children freed
*
* @param[in] ys Yang node to remove
@ -911,13 +901,6 @@ ys_free1(yang_stmt *ys,
free(ys->ys_argument);
ys->ys_argument = NULL;
}
if (yang_flag_get(ys, YANG_FLAG_WHEN) != 0x0) {
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
if (yse->yse_when_xpath)
free(yse->yse_when_xpath);
if (yse->yse_when_nsc)
cvec_free(yse->yse_when_nsc);
}
if (ys->ys_stmt)
free(ys->ys_stmt);
switch (ys->ys_keyword) { /* type-specifi union fields */
@ -1117,9 +1100,10 @@ uses_orig_ptr(enum rfc_6020 keyword)
|| keyword == Y_STATUS
|| keyword == Y_UNIQUE
|| keyword == Y_UNITS
|| keyword == Y_UNKNOWN
// || keyword == Y_UNKNOWN // NO (test_snmp_ifmib.sh)
|| keyword == Y_VALUE
|| keyword == Y_YIN_ELEMENT
|| keyword == Y_WHEN // children
;
}
#endif /* YANG_ORIG_PTR_SKIP */
@ -1188,6 +1172,8 @@ ys_cp_one(yang_stmt *ynew,
default:
break;
}
if (yang_flag_get(yold, YANG_FLAG_MYMODULE) != 0x0)
yang_mymodule_set(ynew, yang_mymodule_get(yold));
retval = 0;
done:
return retval;
@ -1261,42 +1247,6 @@ ys_dup(yang_stmt *old)
return nw;
}
/*! Create a new extdended yang node and copy the contents recursively from the original.
*/
yang_stmt *
yse_dup(yang_stmt *yold)
{
yang_stmt *ynew;
char *xpath;
cvec *cvv;
if ((ynew = yse_new(yold->ys_keyword)) == NULL)
return NULL;
if (ys_cp(ynew, yold) < 0){
ys_free(ynew);
return NULL;
}
yang_flag_set(ynew, YANG_FLAG_WHEN);
if (yang_flag_get(yold, YANG_FLAG_WHEN) != 0x0) {
if ((xpath = yang_when_xpath_get(yold)) != NULL){
if (yang_when_xpath_set(ynew, xpath) < 0)
goto done;
}
if ((cvv = yang_when_nsc_get(yold)) != NULL){
if (yang_when_nsc_set(ynew, cvv) < 0)
goto done;
}
}
ok:
return ynew;
done:
if (ynew){
ys_free(ynew);
ynew = NULL;
}
goto ok;
}
/*! Replace yold with ynew (insert ynew at the exact place of yold). Keep yold pointer as-is.
*
* @param[in] yorig Existing yang statement
@ -3927,7 +3877,7 @@ yang_key_match(yang_stmt *yn,
/*! Set type cache for yang type
*
* @param[in] rxmode Kludge to know which regexp engine is used
* @param[in] rxmode Which regexp engine to use, see enum regexp_mode
* @retval 0 OK
* @retval -1 Error
* @see yang_type_cache_regexp_set where cache is extended w compiled regexps
@ -3974,6 +3924,8 @@ yang_type_cache_set2(yang_stmt *ys,
/*! Extend yang type cache with compiled regexps
*
* Compiled Regexps are computed in validate code - after initial cache set
* @param[in] ytype YANG type statement
* @param[in] rxmode Which regexp engine to use, see enum regexp_mode
* @param[in] regexps
* @retval 0 OK
* @retval -1 Error
@ -3986,10 +3938,18 @@ yang_type_cache_regexp_set(yang_stmt *ytype,
int retval = -1;
yang_type_cache *ycache;
assert(regexps);
assert(yang_keyword_get(ytype) == Y_TYPE);
assert((ycache = ytype->ys_typecache) != NULL);
assert(ycache->yc_regexps == NULL);
if (regexps == NULL || yang_keyword_get(ytype) != Y_TYPE) {
clixon_err(OE_YANG, EINVAL, "regexps is NULL, or are already set, or ytype is not YTYPE");
goto done;
}
if ((ycache = ytype->ys_typecache) == NULL){
clixon_err(OE_YANG, 0, "Typecache is NULL");
goto done;
}
if (ycache->yc_regexps != NULL){
clixon_err(OE_YANG, 0, "regexp is already set");
goto done;
}
ycache->yc_rxmode = rxmode;
if ((ycache->yc_regexps = cvec_dup(regexps)) == NULL){
clixon_err(OE_UNIX, errno, "cvec_dup");
@ -4003,6 +3963,7 @@ yang_type_cache_regexp_set(yang_stmt *ytype,
/*! Get individual fields (direct/destructively) from yang type cache.
*
* @param[out] patterns Initialized cvec of regexp patterns strings
* @param[out] rxmode Which regexp engine to use, see enum regexp_mode
* @retval 1 OK
* @retval 0 No cache
* @retval -1 Error
@ -4288,17 +4249,6 @@ yang_sort_subelements(yang_stmt *ys)
#endif
}
/*! Init yang code
*
* @param[in] h Clixon handle
* @retval 0 OK
* @retval -1 Error
*/
int
yang_init(clixon_handle h)
{
return yang_cardinality_init(h);
}
#ifdef XML_EXPLICIT_INDEX
/*! Mark element as search_index in list
@ -4440,3 +4390,51 @@ yang_action_cb_add(yang_stmt *ys,
ADDQ(rc, ys->ys_action_cb);
return 0;
}
/*! Init yang code
*
* Add two external tables for YANGs
* @param[in] h Clixon handle
* @retval 0 OK
* @retval -1 Error
*/
int
yang_init(clixon_handle h)
{
int retval = -1;
map_ptr2ptr *mp;
if ((mp = calloc(1, sizeof(*mp))) == NULL){
clixon_err(OE_UNIX, errno, "calloc");
goto done;
}
_yang_when_map = mp;
if ((mp = calloc(1, sizeof(*mp))) == NULL){
clixon_err(OE_UNIX, errno, "calloc");
goto done;
}
_yang_mymodule_map = mp;
if (yang_cardinality_init(h) < 0)
goto done;
retval = 0;
done:
return retval;
}
/*! Exit yang code
*
* @param[in] h Clixon handle
*/
int
yang_exit(clixon_handle h)
{
if (_yang_when_map != NULL) {
free(_yang_when_map);
_yang_when_map = NULL;
}
if (_yang_mymodule_map != NULL) {
free(_yang_mymodule_map);
_yang_mymodule_map = NULL;
}
return 0;
}

View file

@ -46,17 +46,16 @@
* @note unions not cached
*/
struct yang_type_cache{
int yc_options; /* See YANG_OPTIONS_* that determines pattern/
uint8_t yc_options; /* See YANG_OPTIONS_* that determines pattern/
fraction fields. */
int yc_rxmode; /* need to store mode for freeing since handle may not be available
* see regexp_mode
*/
uint8_t yc_rxmode; /* Need to store mode for freeing since handle may not be
* available. See enum regexp_mode */
uint8_t yc_fraction; /* Fraction digits for decimal64 (if YANG_OPTIONS_FRACTION_DIGITS */
cvec *yc_cvv; /* Range and length restriction. (if YANG_OPTION_
LENGTH|RANGE. Can be a vector if multiple
ranges*/
cvec *yc_patterns; /* list of regexp, if cvec_len() > 0 */
cvec *yc_regexps; /* list of _compiled_ regexp, if cvec_len() > 0 */
ranges */
cvec *yc_patterns; /* List of regexp, if cvec_len() > 0 */
cvec *yc_regexps; /* List of _compiled_ regexp, if cvec_len() > 0 */
yang_stmt *yc_resolved; /* Resolved type object, can be NULL - note direct ptr */
};
typedef struct yang_type_cache yang_type_cache;
@ -65,8 +64,7 @@ typedef struct yang_type_cache yang_type_cache;
*
* This is an internal type, not exposed in the API
* The external type is "yang_stmt" defined in clixon_yang.h
* @see struct yang_stmt_extended for extended struct (same beginning)
* @note This struct MUST be identical in size to first part of yang_stmt_extended struct
* @note There is additional info in maps, yang_when_set and yang_mymodule_set
*/
struct yang_stmt {
/* On x86_64, the following three fields take 8 bytes */
@ -110,12 +108,6 @@ struct yang_stmt {
Y_UNIQUE: vector of descendant schema node ids
# Y_UNKNOWN: app-dep: yang-mount-points
*/
yang_stmt *ys_mymodule; /* Shortcut to "my" module. Used by:
* 1) Augmented nodes "belong" to the module where the
* augment is declared, which may be different from
* the direct ancestor module
* 2) Unknown nodes "belong" to where the extension is
* declared */
yang_stmt *ys_orig; /* Pointer to original (for uses/augment copies) */
union { /* Depends on ys_keyword */
rpc_callback_t *ysu_action_cb; /* Y_ACTION: Action callback list*/
@ -126,50 +118,6 @@ struct yang_stmt {
} u;
};
/*! An extended yang struct for use of extra fields that consumes more memory
*
* See end of struct. The fields that fit here are extended only fot the original object.,
* they may not be copied. Currently only tow WHEN fields.
* Cannot fit this into the ysu union because keyword is unknown (or at least a set)
* @see struct yang_stmt for the original struct
* @note First part of this struct MUST resemble yang_stmt fields (in memory).
*/
struct yang_stmt_extended {
/* On x86_64, the following four fields take 16 bytes */
enum rfc_6020 ys_keyword:16; /* YANG keyword */
uint16_t ys_flags; /* Flags according to YANG_FLAG_MARK and others */
uint32_t ys_len; /* Number of children */
#ifdef YANG_SPEC_LINENR
uint32_t ys_linenum; /* For debug/errors: line number (in ys_filename) */
#endif
struct yang_stmt **ys_stmt; /* Vector of children statement pointers */
struct yang_stmt *ys_parent; /* Backpointer to parent: yang-stmt or yang-spec */
char *ys_argument; /* String / argument depending on keyword */
cg_var *yse_cv; /* cligen variable. See ys_populate() */
cvec *yse_cvec; /* List of stmt-specific variables */
yang_stmt *yse_mymodule; /* Shortcut to "my" module. Used by:
* 1) Augmented nodes "belong" to the module where the
* augment is declared, which may be different from
* the direct ancestor module
* 2) Unknown nodes "belong" to where the extension is
* declared */
yang_stmt *yse_orig; /* Pointer to original (for uses/augment copies) */
union { /* depends on ys_keyword */
rpc_callback_t *ysu_action_cb; /* Y_ACTION: Action callback list*/
char *ysu_filename; /* Y_MODULE/Y_SUBMODULE: For debug/errors: filename */
yang_type_cache *ysu_typecache; /* Y_TYPE: cache all typedef data except unions */
int ysu_ref; /* Y_SPEC: Reference count for free: 0 means
* no sharing, 1: two references */
} ue;
/* The following fields are only in extended
* -----------------------------------------
*/
char *yse_when_xpath; /* Special conditional for a "when"-associated augment/uses XPath */
cvec *yse_when_nsc; /* Special conditional for a "when"-associated augment/uses namespace ctx */
};
typedef struct yang_stmt_extended yang_stmt_extended;
/* Access macros */
#define ys_action_cb u.ysu_action_cb
#define ys_filename u.ysu_filename

View file

@ -644,7 +644,7 @@ yang_find_module_by_namespace_revision(yang_stmt *yspec,
const char *ns,
const char *rev)
{
yang_stmt *ymod;
yang_stmt *ymod = NULL;
yang_stmt *yrev;
char *rev1;
int inext;
@ -682,7 +682,7 @@ yang_find_module_by_name_revision(yang_stmt *yspec,
const char *name,
const char *rev)
{
yang_stmt *ymod;
yang_stmt *ymod = NULL;
yang_stmt *yrev;
char *rev1;
int inext;

View file

@ -106,7 +106,7 @@
#define BUFLEN 1024
/* Forward */
static int yang_expand_grouping(yang_stmt *yn);
static int yang_expand_grouping(clixon_handle h, yang_stmt *yn);
/*! Resolve a grouping name from a module, includes looking in submodules
*/
@ -253,6 +253,7 @@ ys_add_orig_ptr(yang_stmt *yp0,
* @note If the augment has a when statement, which is commonplace, the when statement is not
* copied as datanodes are, since it should not apply to the target node. Instead it is added as
* a special "when" struct to the yang statements being inserted.
* @see yang_expand_uses_node similar but for uses/grouping
*/
static int
yang_augment_node(clixon_handle h,
@ -265,8 +266,7 @@ yang_augment_node(clixon_handle h,
yang_stmt *yc;
yang_stmt *ymod;
yang_stmt *ywhen = NULL;
char *wxpath; /* xpath of when statement */
cvec *wnsc = NULL; /* namespace context of when statement */
yang_stmt *ywhen0;
enum rfc_6020 targetkey;
enum rfc_6020 childkey;
int inext;
@ -308,11 +308,7 @@ yang_augment_node(clixon_handle h,
goto ok;
/* Find when statement, if present */
if ((ywhen = yang_find(ys, Y_WHEN, NULL)) != NULL){
wxpath = yang_argument_get(ywhen);
if (xml_nsctx_yang(ywhen, &wnsc) < 0)
goto done;
}
ywhen = yang_find(ys, Y_WHEN, NULL);
/* Extend ytarget with ys' schemanode children */
inext = 0;
while ((yc0 = yn_iter(ys, &inext)) != NULL) {
@ -388,16 +384,7 @@ yang_augment_node(clixon_handle h,
break;
}
/* If expanded by uses / when */
if (yang_flag_get(yc0, YANG_FLAG_WHEN) != 0x0){
if ((yc = yse_dup(yc0)) == NULL)
goto done;
}
/* If augment when */
else if (ywhen) {
if ((yc = yse_dup(yc0)) == NULL) /* Extended */
goto done;
}
else if ((yc = ys_dup(yc0)) == NULL)
if ((yc = ys_dup(yc0)) == NULL)
goto done;
#ifdef YANG_GROUPING_AUGMENT_SKIP
/* cornercase: always expand uses under augment */
@ -413,10 +400,19 @@ yang_augment_node(clixon_handle h,
/* If there is an associated when statement, add a special when struct to the yang
* see xml_yang_validate_all
*/
if (ywhen){
if (yang_when_xpath_set(yc, wxpath) < 0)
/* ywhen of uses node (already present) */
if ((ywhen0 = yang_when_get(h, yc0)) != NULL) {
if (yang_when_set(h, yc, ywhen0) < 0)
goto done;
if (yang_when_nsc_set(yc, wnsc) < 0)
}
/* ywhen of augmented node
* Note: double whens not supported
*/
if (ywhen){
if (ywhen0 != NULL)
clixon_log(h, LOG_WARNING, "Warning: Double when statement, both augment and existing (uses) not supported in %s",
yang_argument_get(ys_module(ys)));
if (yang_when_set(h, yc, ywhen) < 0)
goto done;
}
/* Note: ys_populate2 called as a special case here since the inserted child is
@ -430,8 +426,6 @@ yang_augment_node(clixon_handle h,
ok:
retval = 0;
done:
if (wnsc)
cvec_free(wnsc);
return retval;
}
@ -574,14 +568,17 @@ ys_iskey(yang_stmt *y,
/*! Helper function to yang_expand_grouping
*
* @param[in] h Clixon handle
* @param[in] yn Yang parent node of uses ststement
* @param[in] ys Uses statement
* @param[in] i
* @param[in] i ys is i:th element of yn:s children
* @retval 0 OK
* @retval -1 Error
* @see yang_augment_node similar but for augment
*/
static int
yang_expand_uses_node(yang_stmt *yn,
yang_expand_uses_node(clixon_handle h,
yang_stmt *yn,
yang_stmt *ys,
int i)
{
@ -599,8 +596,6 @@ yang_expand_uses_node(yang_stmt *yn,
int j;
int k;
yang_stmt *ywhen;
char *wxpath = NULL; /* xpath of when statement */
cvec *wnsc = NULL; /* namespace context of when statement */
int inext;
/* Split argument into prefix and name */
@ -643,15 +638,11 @@ yang_expand_uses_node(yang_stmt *yn,
* A mark could be completely normal (several uses) or it could be a recursion.
*/
yang_flag_set(ygrouping, YANG_FLAG_GROUPING); /* Mark as (being) expanded */
if (yang_expand_grouping(ygrouping) < 0)
if (yang_expand_grouping(h, ygrouping) < 0)
goto done;
}
/* Find when statement, if present */
if ((ywhen = yang_find(ys, Y_WHEN, NULL)) != NULL) {
wxpath = yang_argument_get(ywhen);
if (xml_nsctx_yang(ywhen, &wnsc) < 0)
goto done;
}
ywhen = yang_find(ys, Y_WHEN, NULL);
/* Make a copy of the grouping, then make refinements to this copy
* Note this ygrouping2 object does not have a parent and does not work in many
* functions which assume a full hierarchy, use the original ygrouping in those cases.
@ -669,14 +660,8 @@ yang_expand_uses_node(yang_stmt *yn,
for (i=0; i<ygrouping2->ys_len; i++){
yco = ygrouping->ys_stmt[i];
if (ywhen != NULL) {
if ((ycn = yse_dup(yco)) == NULL)
goto done;
}
else {
if ((ycn = ys_dup(yco)) == NULL)
goto done;
}
ygrouping2->ys_stmt[i] = ycn;
ycn->ys_parent = ygrouping2;
}
@ -770,9 +755,7 @@ yang_expand_uses_node(yang_stmt *yn,
);
goto done;
}
if (yang_when_xpath_set(yg, wxpath) < 0)
goto done;
if (yang_when_nsc_set(yg, wnsc) < 0)
if (yang_when_set(h, yg, ywhen) < 0)
goto done;
}
/* This is for extensions that allow list keys to be optional, see restconf_main_extension_cb */
@ -788,8 +771,6 @@ yang_expand_uses_node(yang_stmt *yn,
ys_free(ygrouping2);
retval = 0;
done:
if (wnsc)
cvec_free(wnsc);
if (prefix)
free(prefix);
if (id)
@ -807,12 +788,14 @@ yang_expand_uses_node(yang_stmt *yn,
* until the contents of the grouping are added to the schema tree via a
* "uses" statement that does not appear inside a "grouping" statement,
* at which point they are bound to the namespace of the current module.
* @param[in] h Clixon handle (may be NULL)
* @param[in] yn Yang node for recursive iteration
* @retval 0 OK
* @retval -1 Error
*/
static int
yang_expand_grouping(yang_stmt *yn)
yang_expand_grouping(clixon_handle h,
yang_stmt *yn)
{
int retval = -1;
yang_stmt *ys = NULL;
@ -825,7 +808,7 @@ yang_expand_grouping(yang_stmt *yn)
switch (yang_keyword_get(ys)){
case Y_USES:
if (yang_flag_get(ys, YANG_FLAG_GROUPING) == 0){
if (yang_expand_uses_node(yn, ys, i) < 0)
if (yang_expand_uses_node(h, yn, ys, i) < 0)
goto done;
yang_flag_set(ys, YANG_FLAG_GROUPING);
}
@ -846,14 +829,12 @@ yang_expand_grouping(yang_stmt *yn)
*/
if (yang_flag_get(ys, YANG_FLAG_GROUPING) == 0){
yang_flag_set(ys, YANG_FLAG_GROUPING); /* Mark as (being) expanded */
if (yang_expand_grouping(ys) < 0)
if (yang_expand_grouping(h, ys) < 0)
goto done;
}
}
else
{
if (yang_expand_grouping(ys) < 0)
else {
if (yang_expand_grouping(h, ys) < 0)
goto done;
}
}
@ -1591,7 +1572,7 @@ yang_parse_post(clixon_handle h,
* This alters the original YANG: after this all YANG uses have been expanded
*/
for (i=0; i<ylen; i++){
if (yang_expand_grouping(ylist[i]) < 0)
if (yang_expand_grouping(h, ylist[i]) < 0)
goto done;
}
/* 7: Top-level augmentation of all modules.

View file

@ -46,7 +46,7 @@
* | yang2cli_var | yang2cli_var_union_one
* ys_cv_validate---+ ys_cv_validate_union_one
* | \ /
* | \ / yang_type_cache_regex_set
* | \ / yang_type_cache_regexp_set
* ys_populate_leaf, +--> compile_pattern2regexp (compile regexps)
* xml_cv_cache (NULL) +--> cv_validate1 --> cv_validate_pattern (exec regexps)
* yang_type2cv (simplified)
@ -223,11 +223,11 @@ compile_pattern2regexp(clixon_handle h,
/*! Resolve types: populate type caches
*
* Typically only called once when loading the yang type system.
* @param[in] ys This is a type statement
* @param[in] arg Not used
* @retval 0 OK
* @retval -1 Error
* Typically only called once when loading the yang type system.
* @note unions not cached
*/
int