Added YANG_SPEC_LINENR compile-time option
This commit is contained in:
parent
aa4feee03e
commit
af29a0f974
14 changed files with 532 additions and 202 deletions
|
|
@ -16,6 +16,9 @@ Expected: October 2024
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
|
* Added YANG struct memory optimization
|
||||||
|
* Added union and extended struct for uncommon fields
|
||||||
|
* Removed per-object YANG linenr info
|
||||||
* New: [CLI simple alias](https://github.com/clicon/cligen/issues/112)
|
* New: [CLI simple alias](https://github.com/clicon/cligen/issues/112)
|
||||||
* See: https://clixon-docs.readthedocs.io/en/latest/cli.html#cli-aliases
|
* See: https://clixon-docs.readthedocs.io/en/latest/cli.html#cli-aliases
|
||||||
* List pagination: Added where, sort-by and direction parameter for configured data
|
* List pagination: Added where, sort-by and direction parameter for configured data
|
||||||
|
|
@ -26,6 +29,8 @@ Expected: October 2024
|
||||||
|
|
||||||
Users may have to change how they access the system
|
Users may have to change how they access the system
|
||||||
|
|
||||||
|
* Removed YANG line-number in error-messages for memory optimization
|
||||||
|
* Re-enable by setting `YANG_SPEC_LINENR` compile-time option
|
||||||
* NETCONF error returns of failed leafref references, see https://github.com/clicon/clixon/issues/536
|
* NETCONF error returns of failed leafref references, see https://github.com/clicon/clixon/issues/536
|
||||||
* List pagination of large lists
|
* List pagination of large lists
|
||||||
* For backward-compatibility, mark the list with extension cl:list-pagination-partial-state extension
|
* For backward-compatibility, mark the list with extension cl:list-pagination-partial-state extension
|
||||||
|
|
|
||||||
|
|
@ -1581,7 +1581,7 @@ yang2cli_grouping(clixon_handle h,
|
||||||
}
|
}
|
||||||
/* Parse the buffer using cligen parser. load cli syntax */
|
/* Parse the buffer using cligen parser. load cli syntax */
|
||||||
if (clispec_parse_str(cli_cligen(h), cbuf_get(cb), (char*)__FUNCTION__, NULL, pt, NULL) < 0){
|
if (clispec_parse_str(cli_cligen(h), cbuf_get(cb), (char*)__FUNCTION__, NULL, pt, NULL) < 0){
|
||||||
fprintf(stderr, "%s\n", cbuf_get(cb));
|
clixon_err(OE_PLUGIN, 0, "%s", cbuf_get(cb));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
clixon_debug(CLIXON_DBG_CLI, "Generated auto-cli for grouping:%s",
|
clixon_debug(CLIXON_DBG_CLI, "Generated auto-cli for grouping:%s",
|
||||||
|
|
|
||||||
|
|
@ -195,3 +195,12 @@
|
||||||
* This is a limitation of of the current implementation
|
* This is a limitation of of the current implementation
|
||||||
*/
|
*/
|
||||||
#define YANG_SCHEMA_MOUNT_YANG_LIB_FORCE
|
#define YANG_SCHEMA_MOUNT_YANG_LIB_FORCE
|
||||||
|
|
||||||
|
/*! For debug, YANG linenr shown in some YANG error-messages
|
||||||
|
*
|
||||||
|
* If set, report line-numbers in some error-messages (grouping/mandatory key),
|
||||||
|
* However, almost all parsing still reports linenr on error.
|
||||||
|
* Only exception is schema-nodeid sub-parsing
|
||||||
|
* If not set, reduces memory with 8 bytes per yang-stmt.
|
||||||
|
*/
|
||||||
|
#undef YANG_SPEC_LINENR
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,9 @@
|
||||||
* Set by yang_mount_set
|
* Set by yang_mount_set
|
||||||
* Read by ys_free1
|
* Read by ys_free1
|
||||||
*/
|
*/
|
||||||
|
#define YANG_FLAG_EXTENDED 0x400 /* Use extended struct to access uncommon fields
|
||||||
|
* Memory optimization
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Types
|
* Types
|
||||||
|
|
@ -254,22 +257,29 @@ cvec *yang_when_nsc_get(yang_stmt *ys);
|
||||||
int yang_when_nsc_set(yang_stmt *ys, cvec *nsc);
|
int yang_when_nsc_set(yang_stmt *ys, cvec *nsc);
|
||||||
const char *yang_filename_get(yang_stmt *ys);
|
const char *yang_filename_get(yang_stmt *ys);
|
||||||
int yang_filename_set(yang_stmt *ys, const char *filename);
|
int yang_filename_set(yang_stmt *ys, const char *filename);
|
||||||
int yang_linenum_get(yang_stmt *ys);
|
uint32_t yang_linenum_get(yang_stmt *ys);
|
||||||
int yang_linenum_set(yang_stmt *ys, int linenum);
|
int yang_linenum_set(yang_stmt *ys, uint32_t linenum);
|
||||||
|
void *yang_typecache_get(yang_stmt *ys);
|
||||||
|
int yang_typecache_set(yang_stmt *ys, void *ycache);
|
||||||
|
yang_stmt* yang_mymodule_get(yang_stmt *ys);
|
||||||
|
int yang_mymodule_set(yang_stmt *ys, yang_stmt *ym);
|
||||||
|
|
||||||
/* Stats */
|
/* Stats */
|
||||||
int yang_stats_global(uint64_t *nr);
|
int yang_stats_global(uint64_t *nr);
|
||||||
int yang_stats(yang_stmt *y, enum rfc_6020 keyw, uint64_t *nrp, size_t *szp);
|
int yang_stats(yang_stmt *y, enum rfc_6020 keyw, uint64_t *nrp, size_t *szp);
|
||||||
|
|
||||||
/* Other functions */
|
/* Other functions */
|
||||||
yang_stmt *yspec_new(void);
|
yang_stmt *yspec_new(void);
|
||||||
yang_stmt *ys_new(enum rfc_6020 keyw);
|
yang_stmt *ys_new(enum rfc_6020 keyw);
|
||||||
|
yang_stmt *yse_new(enum rfc_6020 keyw);
|
||||||
yang_stmt *ys_prune(yang_stmt *yp, int i);
|
yang_stmt *ys_prune(yang_stmt *yp, int i);
|
||||||
int ys_prune_self(yang_stmt *ys);
|
int ys_prune_self(yang_stmt *ys);
|
||||||
int ys_free1(yang_stmt *ys, int self);
|
int ys_free1(yang_stmt *ys, int self);
|
||||||
int ys_free(yang_stmt *ys);
|
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);
|
int ys_cp(yang_stmt *nw, yang_stmt *old);
|
||||||
yang_stmt *ys_dup(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_insert(yang_stmt *ys_parent, yang_stmt *ys_child);
|
||||||
int yn_insert1(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);
|
yang_stmt *yn_iter(yang_stmt *yparent, int *inext);
|
||||||
|
|
@ -309,9 +319,9 @@ int yang_features(clixon_handle h, yang_stmt *yt);
|
||||||
cvec *yang_arg2cvec(yang_stmt *ys, char *delimi);
|
cvec *yang_arg2cvec(yang_stmt *ys, char *delimi);
|
||||||
int yang_key_match(yang_stmt *yn, char *name, int *lastkey);
|
int yang_key_match(yang_stmt *yn, char *name, int *lastkey);
|
||||||
int yang_type_cache_regexp_set(yang_stmt *ytype, int rxmode, cvec *regexps);
|
int yang_type_cache_regexp_set(yang_stmt *ytype, int rxmode, cvec *regexps);
|
||||||
int yang_type_cache_get(yang_stmt *ytype, yang_stmt **resolved, int *options,
|
int yang_type_cache_get2(yang_stmt *ytype, yang_stmt **resolved, int *options,
|
||||||
cvec **cvv, cvec *patterns, int *rxmode, cvec *regexps, uint8_t *fraction);
|
cvec **cvv, cvec *patterns, int *rxmode, cvec *regexps, uint8_t *fraction);
|
||||||
int yang_type_cache_set(yang_stmt *ys, yang_stmt *resolved, int options, cvec *cvv,
|
int yang_type_cache_set2(yang_stmt *ys, yang_stmt *resolved, int options, cvec *cvv,
|
||||||
cvec *patterns, uint8_t fraction);
|
cvec *patterns, uint8_t fraction);
|
||||||
yang_stmt *yang_anydata_add(yang_stmt *yp, char *name);
|
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_extension_value(yang_stmt *ys, char *name, char *ns, int *exist, char **value);
|
||||||
|
|
|
||||||
|
|
@ -280,11 +280,13 @@ validate_identityref(cxobj *xt,
|
||||||
ymod = yang_find_module_by_prefix_yspec(ys_spec(ys), prefix);
|
ymod = yang_find_module_by_prefix_yspec(ys_spec(ys), prefix);
|
||||||
}
|
}
|
||||||
if (ymod == NULL){
|
if (ymod == NULL){
|
||||||
cprintf(cberr, "Identityref validation failed, %s not derived from %s in %s.yang:%d",
|
cprintf(cberr, "Identityref validation failed, %s not derived from %s in %s.yang",
|
||||||
node,
|
node,
|
||||||
yang_argument_get(ybaseid),
|
yang_argument_get(ybaseid),
|
||||||
yang_argument_get(ys_module(ybaseid)),
|
yang_argument_get(ys_module(ybaseid)));
|
||||||
yang_linenum_get(ybaseid));
|
#ifdef YANG_SPEC_LINENR
|
||||||
|
cprintf(cberr, ":%d", yang_linenum_get(ybaseid));
|
||||||
|
#endif
|
||||||
if (xret && netconf_operation_failed_xml(xret, "application", cbuf_get(cberr)) < 0)
|
if (xret && netconf_operation_failed_xml(xret, "application", cbuf_get(cberr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -296,11 +298,14 @@ validate_identityref(cxobj *xt,
|
||||||
*/
|
*/
|
||||||
idrefvec = yang_cvec_get(ybaseid);
|
idrefvec = yang_cvec_get(ybaseid);
|
||||||
if (cvec_find(idrefvec, idref) == NULL){
|
if (cvec_find(idrefvec, idref) == NULL){
|
||||||
cprintf(cberr, "Identityref validation failed, %s not derived from %s in %s.yang:%d",
|
|
||||||
|
cprintf(cberr, "Identityref validation failed, %s not derived from %s in %s.yang",
|
||||||
node,
|
node,
|
||||||
yang_argument_get(ybaseid),
|
yang_argument_get(ybaseid),
|
||||||
yang_argument_get(ys_module(ybaseid)),
|
yang_argument_get(ys_module(ybaseid)));
|
||||||
yang_linenum_get(ybaseid));
|
#ifdef YANG_SPEC_LINENR
|
||||||
|
cprintf(cberr, ":%d", yang_linenum_get(ybaseid));
|
||||||
|
#endif
|
||||||
if (xret && netconf_operation_failed_xml(xret, "application", cbuf_get(cberr)) < 0)
|
if (xret && netconf_operation_failed_xml(xret, "application", cbuf_get(cberr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -684,9 +689,11 @@ check_list_key(cxobj *xt,
|
||||||
}
|
}
|
||||||
ymod = ys_module(yt);
|
ymod = ys_module(yt);
|
||||||
keyw = yang_keyword_get(yt);
|
keyw = yang_keyword_get(yt);
|
||||||
cprintf(cb, "Mandatory key in '%s %s' in %s.yang:%d",
|
cprintf(cb, "Mandatory key in '%s %s' in %s.yang",
|
||||||
yang_key2str(keyw), xml_name(xt), yang_argument_get(ymod),
|
yang_key2str(keyw), xml_name(xt), yang_argument_get(ymod));
|
||||||
yang_linenum_get(yc));
|
#ifdef YANG_SPEC_LINENR
|
||||||
|
cprintf(cb, ":%d", yang_linenum_get(yc));
|
||||||
|
#endif
|
||||||
if (netconf_missing_element_xml(xret, "application", keyname, cbuf_get(cb)) < 0)
|
if (netconf_missing_element_xml(xret, "application", keyname, cbuf_get(cb)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
cbuf_free(cb);
|
cbuf_free(cb);
|
||||||
|
|
|
||||||
|
|
@ -263,6 +263,7 @@ yang_argument_set(yang_stmt *ys,
|
||||||
cg_var*
|
cg_var*
|
||||||
yang_cv_get(yang_stmt *ys)
|
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;
|
return ys->ys_cv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -277,6 +278,7 @@ int
|
||||||
yang_cv_set(yang_stmt *ys,
|
yang_cv_set(yang_stmt *ys,
|
||||||
cg_var *cv)
|
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)
|
if (cv != NULL && ys->ys_cv != NULL)
|
||||||
cv_free(ys->ys_cv);
|
cv_free(ys->ys_cv);
|
||||||
ys->ys_cv = cv;
|
ys->ys_cv = cv;
|
||||||
|
|
@ -292,6 +294,7 @@ yang_cv_set(yang_stmt *ys,
|
||||||
cvec*
|
cvec*
|
||||||
yang_cvec_get(yang_stmt *ys)
|
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;
|
return ys->ys_cvec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -306,6 +309,7 @@ int
|
||||||
yang_cvec_set(yang_stmt *ys,
|
yang_cvec_set(yang_stmt *ys,
|
||||||
cvec *cvv)
|
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)
|
if (ys->ys_cvec)
|
||||||
cvec_free(ys->ys_cvec);
|
cvec_free(ys->ys_cvec);
|
||||||
ys->ys_cvec = cvv;
|
ys->ys_cvec = cvv;
|
||||||
|
|
@ -328,6 +332,7 @@ yang_cvec_add(yang_stmt *ys,
|
||||||
cg_var *cv;
|
cg_var *cv;
|
||||||
cvec *cvv;
|
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 = yang_cvec_get(ys)) == NULL){
|
||||||
if ((cvv = cvec_new(0)) == NULL){
|
if ((cvv = cvec_new(0)) == NULL){
|
||||||
clixon_err(OE_YANG, errno, "cvec_new");
|
clixon_err(OE_YANG, errno, "cvec_new");
|
||||||
|
|
@ -354,6 +359,7 @@ yang_cvec_add(yang_stmt *ys,
|
||||||
int
|
int
|
||||||
yang_ref_get(yang_stmt *ys)
|
yang_ref_get(yang_stmt *ys)
|
||||||
{
|
{
|
||||||
|
// assert(ys->ys_keyword == Y_SPEC);
|
||||||
return ys->ys_ref;
|
return ys->ys_ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -365,6 +371,7 @@ yang_ref_get(yang_stmt *ys)
|
||||||
int
|
int
|
||||||
yang_ref_inc(yang_stmt *ys)
|
yang_ref_inc(yang_stmt *ys)
|
||||||
{
|
{
|
||||||
|
// assert(ys->ys_keyword == Y_SPEC);
|
||||||
ys->ys_ref++;
|
ys->ys_ref++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -380,6 +387,7 @@ yang_ref_dec(yang_stmt *ys)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
||||||
|
// assert(ys->ys_keyword == Y_SPEC);
|
||||||
if (ys->ys_ref > 0)
|
if (ys->ys_ref > 0)
|
||||||
ys->ys_ref--;
|
ys->ys_ref--;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -439,7 +447,12 @@ yang_flag_reset(yang_stmt *ys,
|
||||||
char*
|
char*
|
||||||
yang_when_xpath_get(yang_stmt *ys)
|
yang_when_xpath_get(yang_stmt *ys)
|
||||||
{
|
{
|
||||||
return ys->ys_when_xpath;
|
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
|
||||||
|
|
||||||
|
if ((ys->ys_flags & YANG_FLAG_EXTENDED) == 0x0)
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
return yse->yse_when_xpath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Set yang xpath and namespace context for "when"-associated augment
|
/*! Set yang xpath and namespace context for "when"-associated augment
|
||||||
|
|
@ -455,13 +468,19 @@ int
|
||||||
yang_when_xpath_set(yang_stmt *ys,
|
yang_when_xpath_set(yang_stmt *ys,
|
||||||
char *xpath)
|
char *xpath)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
|
||||||
|
|
||||||
if (xpath == NULL){
|
if (xpath == NULL){
|
||||||
clixon_err(OE_YANG, EINVAL, "xpath is NULL");
|
clixon_err(OE_YANG, EINVAL, "xpath is NULL");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((ys->ys_when_xpath = strdup(xpath)) == NULL){
|
if ((ys->ys_flags & YANG_FLAG_EXTENDED) == 0x0){
|
||||||
|
clixon_err(OE_YANG, EINVAL, "Yang node %s %s must have flag YANG_FLAG_EXTENDED 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");
|
clixon_err(OE_YANG, errno, "strdup");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -481,7 +500,12 @@ yang_when_xpath_set(yang_stmt *ys,
|
||||||
cvec *
|
cvec *
|
||||||
yang_when_nsc_get(yang_stmt *ys)
|
yang_when_nsc_get(yang_stmt *ys)
|
||||||
{
|
{
|
||||||
return ys->ys_when_nsc;
|
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
|
||||||
|
|
||||||
|
if ((ys->ys_flags & YANG_FLAG_EXTENDED) == 0x0)
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
return yse->yse_when_nsc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Set yang namespace context for "when"-associated augment
|
/*! Set yang namespace context for "when"-associated augment
|
||||||
|
|
@ -497,9 +521,15 @@ int
|
||||||
yang_when_nsc_set(yang_stmt *ys,
|
yang_when_nsc_set(yang_stmt *ys,
|
||||||
cvec *nsc)
|
cvec *nsc)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
|
||||||
|
|
||||||
if (nsc && (ys->ys_when_nsc = cvec_dup(nsc)) == NULL){
|
if ((ys->ys_flags & YANG_FLAG_EXTENDED) == 0x0){
|
||||||
|
clixon_err(OE_YANG, EINVAL, "Yang node %s %s must have flag YANG_FLAG_EXTENDED for this operation",
|
||||||
|
yang_key2str(ys->ys_keyword), ys->ys_argument);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (nsc && (yse->yse_when_nsc = cvec_dup(nsc)) == NULL){
|
||||||
clixon_err(OE_YANG, errno, "cvec_dup");
|
clixon_err(OE_YANG, errno, "cvec_dup");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -517,6 +547,7 @@ yang_when_nsc_set(yang_stmt *ys,
|
||||||
const char *
|
const char *
|
||||||
yang_filename_get(yang_stmt *ys)
|
yang_filename_get(yang_stmt *ys)
|
||||||
{
|
{
|
||||||
|
// assert(ys->ys_keyword == Y_MODULE || ys->ys_keyword == Y_SUBMODULE);
|
||||||
return ys->ys_filename;
|
return ys->ys_filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -532,6 +563,7 @@ int
|
||||||
yang_filename_set(yang_stmt *ys,
|
yang_filename_set(yang_stmt *ys,
|
||||||
const char *filename)
|
const char *filename)
|
||||||
{
|
{
|
||||||
|
// assert(ys->ys_keyword == Y_MODULE || ys->ys_keyword == Y_SUBMODULE);
|
||||||
if ((ys->ys_filename = strdup(filename)) == NULL){
|
if ((ys->ys_filename = strdup(filename)) == NULL){
|
||||||
clixon_err(OE_UNIX, errno, "strdup");
|
clixon_err(OE_UNIX, errno, "strdup");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -544,10 +576,14 @@ yang_filename_set(yang_stmt *ys,
|
||||||
* @param[in] ys Yang statement
|
* @param[in] ys Yang statement
|
||||||
* @retval linenum
|
* @retval linenum
|
||||||
*/
|
*/
|
||||||
int
|
uint32_t
|
||||||
yang_linenum_get(yang_stmt *ys)
|
yang_linenum_get(yang_stmt *ys)
|
||||||
{
|
{
|
||||||
|
#ifdef YANG_SPEC_LINENR
|
||||||
return ys->ys_linenum;
|
return ys->ys_linenum;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Set line number of yang filename for error/debug purpose
|
/*! Set line number of yang filename for error/debug purpose
|
||||||
|
|
@ -557,9 +593,77 @@ yang_linenum_get(yang_stmt *ys)
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
yang_linenum_set(yang_stmt *ys,
|
yang_linenum_set(yang_stmt *ys,
|
||||||
int linenum)
|
uint32_t linenum)
|
||||||
{
|
{
|
||||||
|
#ifdef YANG_SPEC_LINENR
|
||||||
ys->ys_linenum = linenum;
|
ys->ys_linenum = linenum;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Get type cache
|
||||||
|
*
|
||||||
|
* @param[in] ys Yang statement
|
||||||
|
* @retval ycache
|
||||||
|
*/
|
||||||
|
void *
|
||||||
|
yang_typecache_get(yang_stmt *ys)
|
||||||
|
{
|
||||||
|
// assert(ys->ys_keyword == Y_TYPE);
|
||||||
|
return ys->ys_typecache;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Set type cache
|
||||||
|
*
|
||||||
|
* @param[in] ys Yang statement
|
||||||
|
* @param[in] ycache Type cache
|
||||||
|
* @retval 0 OK
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
yang_typecache_set(yang_stmt *ys,
|
||||||
|
void *ycache)
|
||||||
|
{
|
||||||
|
// assert(ys->ys_keyword == Y_TYPE);
|
||||||
|
ys->ys_typecache = ycache;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Get mymodule
|
||||||
|
*
|
||||||
|
* Shortcut to "my" module. Used by augmented and unknown nodes
|
||||||
|
* @param[in] ys YANG statement
|
||||||
|
* @retval ymod YANG module
|
||||||
|
*/
|
||||||
|
yang_stmt*
|
||||||
|
yang_mymodule_get(yang_stmt *ys)
|
||||||
|
{
|
||||||
|
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
|
||||||
|
|
||||||
|
if ((ys->ys_flags & YANG_FLAG_EXTENDED) == 0x0)
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
return yse->yse_mymodule;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Set mymodule
|
||||||
|
*
|
||||||
|
* Shortcut to "my" module. Used by augmented and unknown nodes
|
||||||
|
* @param[in] ys YANG statement
|
||||||
|
* @param[in] ymod YANG module
|
||||||
|
* @retval 0 OK
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
yang_mymodule_set(yang_stmt *ys,
|
||||||
|
yang_stmt *ym)
|
||||||
|
{
|
||||||
|
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
|
||||||
|
|
||||||
|
if ((ys->ys_flags & YANG_FLAG_EXTENDED) == 0x0){
|
||||||
|
clixon_err(OE_YANG, EINVAL, "Yang node %s %s must have flag YANG_FLAG_EXTENDED for this operation",
|
||||||
|
yang_key2str(ys->ys_keyword), ys->ys_argument);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
yse->yse_mymodule = ym;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -588,35 +692,48 @@ yang_stats_global(uint64_t *nr)
|
||||||
* (baseline: )
|
* (baseline: )
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
yang_stats_one(yang_stmt *y,
|
yang_stats_one(yang_stmt *ys,
|
||||||
size_t *szp)
|
size_t *szp)
|
||||||
{
|
{
|
||||||
size_t sz = 0;
|
size_t sz = 0;
|
||||||
yang_type_cache *yc;
|
yang_type_cache *yc;
|
||||||
|
|
||||||
sz += sizeof(struct yang_stmt);
|
if (yang_flag_get(ys, YANG_FLAG_EXTENDED) == 0x0)
|
||||||
sz += y->ys_len*sizeof(struct yang_stmt*);
|
sz += sizeof(struct yang_stmt_extended);
|
||||||
if (y->ys_argument)
|
else
|
||||||
sz += strlen(y->ys_argument) + 1;
|
sz += sizeof(struct yang_stmt);
|
||||||
if (y->ys_cv)
|
sz += ys->ys_len*sizeof(struct yang_stmt*);
|
||||||
sz += cv_size(y->ys_cv);
|
if (ys->ys_argument)
|
||||||
if (y->ys_cvec)
|
sz += strlen(ys->ys_argument) + 1;
|
||||||
sz += cvec_size(y->ys_cvec);
|
if (ys->ys_cvec)
|
||||||
if ((yc = y->ys_typecache) != NULL){
|
sz += cvec_size(ys->ys_cvec);
|
||||||
sz += sizeof(struct yang_type_cache);
|
if (yang_flag_get(ys, YANG_FLAG_EXTENDED) != 0x0) {
|
||||||
if (yc->yc_cvv)
|
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
|
||||||
sz += cvec_size(yc->yc_cvv);
|
if (yse->yse_when_xpath)
|
||||||
if (yc->yc_patterns)
|
sz += strlen(yse->yse_when_xpath) + 1;
|
||||||
sz += cvec_size(yc->yc_patterns);
|
if (yse->yse_when_nsc)
|
||||||
if (yc->yc_regexps)
|
sz += cvec_size(yse->yse_when_nsc);
|
||||||
sz += cvec_size(yc->yc_regexps);
|
}
|
||||||
|
switch (ys->ys_keyword) {
|
||||||
|
case Y_TYPE:
|
||||||
|
if ((yc = yang_typecache_get(ys)) != NULL){
|
||||||
|
sz += sizeof(struct yang_type_cache);
|
||||||
|
if (yc->yc_cvv)
|
||||||
|
sz += cvec_size(yc->yc_cvv);
|
||||||
|
if (yc->yc_patterns)
|
||||||
|
sz += cvec_size(yc->yc_patterns);
|
||||||
|
if (yc->yc_regexps)
|
||||||
|
sz += cvec_size(yc->yc_regexps);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Y_MODULE:
|
||||||
|
case Y_SUBMODULE:
|
||||||
|
if (ys->ys_filename)
|
||||||
|
sz += strlen(ys->ys_filename) + 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (y->ys_when_xpath)
|
|
||||||
sz += strlen(y->ys_when_xpath) + 1;
|
|
||||||
if (y->ys_when_nsc)
|
|
||||||
sz += cvec_size(y->ys_when_nsc);
|
|
||||||
if (y->ys_filename)
|
|
||||||
sz += strlen(y->ys_filename) + 1;
|
|
||||||
if (szp)
|
if (szp)
|
||||||
*szp = sz;
|
*szp = sz;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -686,23 +803,67 @@ yspec_new(void)
|
||||||
return yspec;
|
return yspec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Create new yang node/statement given size
|
||||||
|
*
|
||||||
|
* Size parameter for variable size, eg extended YANG struct
|
||||||
|
* @param[in] keyw Yang stmt keyword
|
||||||
|
* @param[in] sz Size of created struct
|
||||||
|
* @retval ys New yang-stmt. Free with ys_free()
|
||||||
|
* @retval NULL Error
|
||||||
|
*/
|
||||||
|
static yang_stmt *
|
||||||
|
ys_new_sz(enum rfc_6020 keyw,
|
||||||
|
size_t sz)
|
||||||
|
{
|
||||||
|
yang_stmt *ys;
|
||||||
|
|
||||||
|
if ((ys = malloc(sz)) == NULL){
|
||||||
|
clixon_err(OE_YANG, errno, "malloc");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(ys, 0, sz);
|
||||||
|
ys->ys_keyword = keyw;
|
||||||
|
_stats_yang_nr++;
|
||||||
|
return ys;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Create new yang node/statement
|
/*! Create new yang node/statement
|
||||||
*
|
*
|
||||||
* @retval ys Free with ys_free()
|
* @param[in] keyw Yang stmt keyword
|
||||||
* @retval NULL Error
|
* @retval ys New yang-stmt. Free with ys_free()
|
||||||
|
* @retval NULL Error
|
||||||
|
* @note UNKNOWN nodes are always extended
|
||||||
*/
|
*/
|
||||||
yang_stmt *
|
yang_stmt *
|
||||||
ys_new(enum rfc_6020 keyw)
|
ys_new(enum rfc_6020 keyw)
|
||||||
{
|
{
|
||||||
|
size_t sz;
|
||||||
yang_stmt *ys;
|
yang_stmt *ys;
|
||||||
|
|
||||||
if ((ys = malloc(sizeof(*ys))) == NULL){
|
if (keyw == Y_UNKNOWN)
|
||||||
clixon_err(OE_YANG, errno, "malloc");
|
sz = sizeof(struct yang_stmt_extended);
|
||||||
return NULL;
|
else
|
||||||
|
sz = sizeof(*ys);
|
||||||
|
if ((ys = ys_new_sz(keyw, sz)) != NULL &&
|
||||||
|
keyw == Y_UNKNOWN){
|
||||||
|
yang_flag_set(ys, YANG_FLAG_EXTENDED);
|
||||||
}
|
}
|
||||||
memset(ys, 0, sizeof(*ys));
|
return ys;
|
||||||
ys->ys_keyword = keyw;
|
}
|
||||||
_stats_yang_nr++;
|
|
||||||
|
/*! Create new extended yang node/statement
|
||||||
|
*
|
||||||
|
* @param[in] keyw Yang stmt keyword
|
||||||
|
* @retval ys New yang-stmt. Free with ys_free()
|
||||||
|
* @retval NULL Error
|
||||||
|
*/
|
||||||
|
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_EXTENDED);
|
||||||
return ys;
|
return ys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -718,11 +879,11 @@ int
|
||||||
ys_free1(yang_stmt *ys,
|
ys_free1(yang_stmt *ys,
|
||||||
int self)
|
int self)
|
||||||
{
|
{
|
||||||
cg_var *cv;
|
|
||||||
rpc_callback_t *rc;
|
rpc_callback_t *rc;
|
||||||
|
cg_var *cv;
|
||||||
|
|
||||||
if ((cv = yang_cv_get(ys)) != NULL){
|
if ((cv = ys->ys_cv) != NULL){ // To not trigger asserts
|
||||||
yang_cv_set(ys, NULL); /* only frees on replace */
|
ys->ys_cv = NULL;
|
||||||
cv_free(cv);
|
cv_free(cv);
|
||||||
}
|
}
|
||||||
if (ys->ys_cvec){
|
if (ys->ys_cvec){
|
||||||
|
|
@ -738,25 +899,39 @@ ys_free1(yang_stmt *ys,
|
||||||
free(ys->ys_argument);
|
free(ys->ys_argument);
|
||||||
ys->ys_argument = NULL;
|
ys->ys_argument = NULL;
|
||||||
}
|
}
|
||||||
if (ys->ys_typecache){
|
if (yang_flag_get(ys, YANG_FLAG_EXTENDED) != 0x0) {
|
||||||
yang_type_cache_free(ys->ys_typecache);
|
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
|
||||||
ys->ys_typecache = NULL;
|
if (yse->yse_when_xpath)
|
||||||
|
free(yse->yse_when_xpath);
|
||||||
|
if (yse->yse_when_nsc)
|
||||||
|
cvec_free(yse->yse_when_nsc);
|
||||||
}
|
}
|
||||||
if (ys->ys_when_xpath)
|
|
||||||
free(ys->ys_when_xpath);
|
|
||||||
if (ys->ys_when_nsc)
|
|
||||||
cvec_free(ys->ys_when_nsc);
|
|
||||||
if (ys->ys_stmt)
|
if (ys->ys_stmt)
|
||||||
free(ys->ys_stmt);
|
free(ys->ys_stmt);
|
||||||
if (ys->ys_filename)
|
switch (ys->ys_keyword) { /* type-specifi union fields */
|
||||||
free(ys->ys_filename);
|
case Y_ACTION:
|
||||||
while((rc = ys->ys_action_cb) != NULL) {
|
while((rc = ys->ys_action_cb) != NULL) {
|
||||||
DELQ(rc, ys->ys_action_cb, rpc_callback_t *);
|
DELQ(rc, ys->ys_action_cb, rpc_callback_t *);
|
||||||
if (rc->rc_namespace)
|
if (rc->rc_namespace)
|
||||||
free(rc->rc_namespace);
|
free(rc->rc_namespace);
|
||||||
if (rc->rc_name)
|
if (rc->rc_name)
|
||||||
free(rc->rc_name);
|
free(rc->rc_name);
|
||||||
free(rc);
|
free(rc);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Y_TYPE:
|
||||||
|
if (ys->ys_typecache){
|
||||||
|
yang_type_cache_free(ys->ys_typecache);
|
||||||
|
ys->ys_typecache = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Y_MODULE:
|
||||||
|
case Y_SUBMODULE:
|
||||||
|
if (ys->ys_filename)
|
||||||
|
free(ys->ys_filename);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (self){
|
if (self){
|
||||||
free(ys);
|
free(ys);
|
||||||
|
|
@ -892,7 +1067,74 @@ yn_realloc(yang_stmt *yn)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Copy yang statement recursively from old to new
|
int
|
||||||
|
ys_cp_one(yang_stmt *ynew,
|
||||||
|
yang_stmt *yold)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
char *xpath;
|
||||||
|
cvec *cvv;
|
||||||
|
cg_var *cvn;
|
||||||
|
cg_var *cvo;
|
||||||
|
size_t sz;
|
||||||
|
|
||||||
|
if (yang_flag_get(yold, YANG_FLAG_EXTENDED) != 0x0)
|
||||||
|
sz = sizeof(struct yang_stmt_extended);
|
||||||
|
else
|
||||||
|
sz = sizeof(*yold);
|
||||||
|
memcpy(ynew, yold, sz);
|
||||||
|
ynew->ys_parent = NULL;
|
||||||
|
if (yold->ys_stmt)
|
||||||
|
if ((ynew->ys_stmt = calloc(yold->ys_len, sizeof(yang_stmt *))) == NULL){
|
||||||
|
clixon_err(OE_YANG, errno, "calloc");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (yold->ys_argument)
|
||||||
|
if ((ynew->ys_argument = strdup(yold->ys_argument)) == NULL){
|
||||||
|
clixon_err(OE_YANG, errno, "strdup");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if ((cvo = yold->ys_cv) != NULL){ // Note direct access to avoid wrappings
|
||||||
|
yang_cv_set(ynew, NULL);
|
||||||
|
if ((cvn = cv_dup(cvo)) == NULL){
|
||||||
|
clixon_err(OE_YANG, errno, "cv_dup");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
yang_cv_set(ynew, cvn);
|
||||||
|
}
|
||||||
|
if ((cvv = yold->ys_cvec) != NULL){ // Note direct access to avoid wrappings
|
||||||
|
ynew->ys_cvec = NULL; // Note direct access to avoid cvec_free
|
||||||
|
if ((cvv = cvec_dup(cvv)) == NULL){
|
||||||
|
clixon_err(OE_YANG, errno, "cvec_dup");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
yang_cvec_set(ynew, cvv);
|
||||||
|
}
|
||||||
|
switch (yold->ys_keyword) { /* type-specifi union fields */
|
||||||
|
case Y_TYPE:
|
||||||
|
if (yang_typecache_get(yold)){
|
||||||
|
yang_typecache_set(ynew, NULL);
|
||||||
|
if (yang_type_cache_cp(ynew, yold) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Copy yang statement recursively from old to new
|
||||||
*
|
*
|
||||||
* @param[in] ynew New empty (but created) yang statement (to)
|
* @param[in] ynew New empty (but created) yang statement (to)
|
||||||
* @param[in] yold Old existing yang statement (from)
|
* @param[in] yold Old existing yang statement (from)
|
||||||
|
|
@ -913,53 +1155,16 @@ ys_cp(yang_stmt *ynew,
|
||||||
int i;
|
int i;
|
||||||
yang_stmt *ycn; /* new child */
|
yang_stmt *ycn; /* new child */
|
||||||
yang_stmt *yco; /* old child */
|
yang_stmt *yco; /* old child */
|
||||||
cg_var *cvn;
|
|
||||||
cg_var *cvo;
|
|
||||||
|
|
||||||
memcpy(ynew, yold, sizeof(*yold));
|
if (ys_cp_one(ynew, yold) < 0)
|
||||||
ynew->ys_parent = NULL;
|
goto done;
|
||||||
if (yold->ys_stmt)
|
|
||||||
if ((ynew->ys_stmt = calloc(yold->ys_len, sizeof(yang_stmt *))) == NULL){
|
|
||||||
clixon_err(OE_YANG, errno, "calloc");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (yold->ys_argument)
|
|
||||||
if ((ynew->ys_argument = strdup(yold->ys_argument)) == NULL){
|
|
||||||
clixon_err(OE_YANG, errno, "strdup");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
yang_cv_set(ynew, NULL);
|
|
||||||
if ((cvo = yang_cv_get(yold)) != NULL){
|
|
||||||
if ((cvn = cv_dup(cvo)) == NULL){
|
|
||||||
clixon_err(OE_YANG, errno, "cv_dup");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
yang_cv_set(ynew, cvn);
|
|
||||||
}
|
|
||||||
if (yold->ys_cvec)
|
|
||||||
if ((ynew->ys_cvec = cvec_dup(yold->ys_cvec)) == NULL){
|
|
||||||
clixon_err(OE_YANG, errno, "cvec_dup");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (yold->ys_typecache){
|
|
||||||
ynew->ys_typecache = NULL;
|
|
||||||
if (yang_type_cache_cp(ynew, yold) < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (yold->ys_when_xpath)
|
|
||||||
if ((ynew->ys_when_xpath = strdup(yold->ys_when_xpath)) == NULL){
|
|
||||||
clixon_err(OE_YANG, errno, "strdup");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (yold->ys_when_nsc){
|
|
||||||
if ((ynew->ys_when_nsc = cvec_dup(yold->ys_when_nsc)) == NULL){
|
|
||||||
clixon_err(OE_YANG, errno, "cvec_dup");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (i=0; i<ynew->ys_len; i++){
|
for (i=0; i<ynew->ys_len; i++){
|
||||||
yco = yold->ys_stmt[i];
|
yco = yold->ys_stmt[i];
|
||||||
if ((ycn = ys_dup(yco)) == NULL)
|
if (yang_flag_get(yco, YANG_FLAG_EXTENDED) != 0x0){
|
||||||
|
if ((ycn = yse_dup(yco)) == NULL)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
else if ((ycn = ys_dup(yco)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
ynew->ys_stmt[i] = ycn;
|
ynew->ys_stmt[i] = ycn;
|
||||||
ycn->ys_parent = ynew;
|
ycn->ys_parent = ynew;
|
||||||
|
|
@ -987,10 +1192,6 @@ ys_dup(yang_stmt *old)
|
||||||
|
|
||||||
if ((nw = ys_new(old->ys_keyword)) == NULL)
|
if ((nw = ys_new(old->ys_keyword)) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (nw->ys_cvec){
|
|
||||||
cvec_free(nw->ys_cvec);
|
|
||||||
nw->ys_cvec = NULL;
|
|
||||||
}
|
|
||||||
if (ys_cp(nw, old) < 0){
|
if (ys_cp(nw, old) < 0){
|
||||||
ys_free(nw);
|
ys_free(nw);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -998,6 +1199,23 @@ ys_dup(yang_stmt *old)
|
||||||
return nw;
|
return nw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Create a new extdended yang node and copy the contents recursively from the original.
|
||||||
|
*/
|
||||||
|
yang_stmt *
|
||||||
|
yse_dup(yang_stmt *old)
|
||||||
|
{
|
||||||
|
yang_stmt *nw;
|
||||||
|
|
||||||
|
if ((nw = yse_new(old->ys_keyword)) == NULL)
|
||||||
|
return NULL;
|
||||||
|
if (ys_cp(nw, old) < 0){
|
||||||
|
ys_free(nw);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
yang_flag_set(nw, YANG_FLAG_EXTENDED);
|
||||||
|
return nw;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Replace yold with ynew (insert ynew at the exact place of yold). Keep yold pointer as-is.
|
/*! Replace yold with ynew (insert ynew at the exact place of yold). Keep yold pointer as-is.
|
||||||
*
|
*
|
||||||
* @param[in] yorig Existing yang statement
|
* @param[in] yorig Existing yang statement
|
||||||
|
|
@ -1786,8 +2004,8 @@ ys_module(yang_stmt *ys)
|
||||||
while (ys != NULL &&
|
while (ys != NULL &&
|
||||||
ys->ys_keyword != Y_MODULE &&
|
ys->ys_keyword != Y_MODULE &&
|
||||||
ys->ys_keyword != Y_SUBMODULE){
|
ys->ys_keyword != Y_SUBMODULE){
|
||||||
if (ys->ys_mymodule){ /* shortcut due to augment */
|
if (yang_mymodule_get(ys)){ /* shortcut due to augment */
|
||||||
ys = ys->ys_mymodule;
|
ys = yang_mymodule_get(ys);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
yn = ys->ys_parent;
|
yn = ys->ys_parent;
|
||||||
|
|
@ -2859,7 +3077,7 @@ ys_populate_unknown(clixon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* To find right binding eg after grouping/uses */
|
/* To find right binding eg after grouping/uses */
|
||||||
ys->ys_mymodule = ys_module(ys);
|
yang_mymodule_set(ys, ys_module(ys));
|
||||||
if ((yext = yang_find(ymod, Y_EXTENSION, id)) == NULL){
|
if ((yext = yang_find(ymod, Y_EXTENSION, id)) == NULL){
|
||||||
clixon_err(OE_YANG, ENOENT, "Extension \"%s:%s\" not found", prefix, id);
|
clixon_err(OE_YANG, ENOENT, "Extension \"%s:%s\" not found", prefix, id);
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -2886,12 +3104,10 @@ ys_populate_unknown(clixon_handle h,
|
||||||
*/
|
*/
|
||||||
if (clixon_plugin_extension_all(h, yext, ys) < 0)
|
if (clixon_plugin_extension_all(h, yext, ys) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
#if 1
|
|
||||||
/* Add unknown to vector in extension */
|
/* Add unknown to vector in extension */
|
||||||
if ((cv = yang_cvec_add(yext, CGV_VOID, yang_argument_get(ys))) == NULL)
|
if ((cv = yang_cvec_add(yext, CGV_VOID, yang_argument_get(ys))) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
cv_void_set(cv, ys);
|
cv_void_set(cv, ys);
|
||||||
#endif
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (prefix)
|
if (prefix)
|
||||||
|
|
@ -3631,25 +3847,25 @@ yang_key_match(yang_stmt *yn,
|
||||||
* @see yang_type_cache_regexp_set where cache is extended w compiled regexps
|
* @see yang_type_cache_regexp_set where cache is extended w compiled regexps
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
yang_type_cache_set(yang_stmt *ys,
|
yang_type_cache_set2(yang_stmt *ys,
|
||||||
yang_stmt *resolved,
|
yang_stmt *resolved,
|
||||||
int options,
|
int options,
|
||||||
cvec *cvv,
|
cvec *cvv,
|
||||||
cvec *patterns,
|
cvec *patterns,
|
||||||
uint8_t fraction)
|
uint8_t fraction)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
yang_type_cache *ycache;
|
yang_type_cache *ycache;
|
||||||
|
|
||||||
if (ys->ys_typecache != NULL){
|
if (yang_typecache_get(ys) != NULL){
|
||||||
clixon_err(OE_YANG, EEXIST, "yang type cache");
|
clixon_err(OE_YANG, EEXIST, "yang type cache");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((ys->ys_typecache = (yang_type_cache *)malloc(sizeof(*ycache))) == NULL){
|
if ((ycache = (yang_type_cache *)malloc(sizeof(*ycache))) == NULL){
|
||||||
clixon_err(OE_UNIX, errno, "malloc");
|
clixon_err(OE_UNIX, errno, "malloc");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
ycache = ys->ys_typecache;
|
yang_typecache_set(ys, ycache);
|
||||||
memset(ycache, 0, sizeof(*ycache));
|
memset(ycache, 0, sizeof(*ycache));
|
||||||
ycache->yc_resolved = resolved;
|
ycache->yc_resolved = resolved;
|
||||||
ycache->yc_options = options;
|
ycache->yc_options = options;
|
||||||
|
|
@ -3706,7 +3922,7 @@ yang_type_cache_regexp_set(yang_stmt *ytype,
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
yang_type_cache_get(yang_stmt *ytype,
|
yang_type_cache_get2(yang_stmt *ytype,
|
||||||
yang_stmt **resolved,
|
yang_stmt **resolved,
|
||||||
int *options,
|
int *options,
|
||||||
cvec **cvv,
|
cvec **cvv,
|
||||||
|
|
@ -3719,7 +3935,7 @@ yang_type_cache_get(yang_stmt *ytype,
|
||||||
cg_var *cv = NULL;
|
cg_var *cv = NULL;
|
||||||
yang_type_cache *ycache;
|
yang_type_cache *ycache;
|
||||||
|
|
||||||
ycache = ytype->ys_typecache;
|
ycache = yang_typecache_get(ytype);
|
||||||
if (ycache == NULL){ /* No cache return 0 */
|
if (ycache == NULL){ /* No cache return 0 */
|
||||||
retval = 0;
|
retval = 0;
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -3770,11 +3986,11 @@ yang_type_cache_cp(yang_stmt *ynew,
|
||||||
/* Note, regexps are not copied since they are voids, if they were, they
|
/* Note, regexps are not copied since they are voids, if they were, they
|
||||||
* could not be freed in a simple way since copies are made at augment/group
|
* could not be freed in a simple way since copies are made at augment/group
|
||||||
*/
|
*/
|
||||||
if ((ret = yang_type_cache_get(yold,
|
if ((ret = yang_type_cache_get2(yold,
|
||||||
&resolved, &options, &cvv, patterns, NULL, NULL, &fraction)) < 0)
|
&resolved, &options, &cvv, patterns, NULL, NULL, &fraction)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 1 &&
|
if (ret == 1 &&
|
||||||
yang_type_cache_set(ynew, resolved, options, cvv, patterns, fraction) < 0)
|
yang_type_cache_set2(ynew, resolved, options, cvv, patterns, fraction) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
|
@ -3955,6 +4171,7 @@ yang_sort_subelements_fn(const void* arg1,
|
||||||
else return ys1->_ys_vector_i - ys2->_ys_vector_i;
|
else return ys1->_ys_vector_i - ys2->_ys_vector_i;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*! Experimental code for sorting YANG children
|
/*! Experimental code for sorting YANG children
|
||||||
*
|
*
|
||||||
* RFC 7950 7.5.7 and 7.8.5 says that containers and list sub elements are encoded in any order.
|
* RFC 7950 7.5.7 and 7.8.5 says that containers and list sub elements are encoded in any order.
|
||||||
|
|
@ -4109,6 +4326,7 @@ yang_single_child_type(yang_stmt *ys,
|
||||||
void *
|
void *
|
||||||
yang_action_cb_get(yang_stmt *ys)
|
yang_action_cb_get(yang_stmt *ys)
|
||||||
{
|
{
|
||||||
|
assert(ys->ys_keyword == Y_ACTION);
|
||||||
return ys->ys_action_cb;
|
return ys->ys_action_cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4122,6 +4340,7 @@ yang_action_cb_add(yang_stmt *ys,
|
||||||
{
|
{
|
||||||
rpc_callback_t *rc = (rpc_callback_t *)arg;
|
rpc_callback_t *rc = (rpc_callback_t *)arg;
|
||||||
|
|
||||||
|
assert(ys->ys_keyword == Y_ACTION);
|
||||||
if (rc == NULL){
|
if (rc == NULL){
|
||||||
clixon_err(OE_YANG, EINVAL, "arg is NULL");
|
clixon_err(OE_YANG, EINVAL, "arg is NULL");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
||||||
|
|
@ -65,53 +65,103 @@ typedef struct yang_type_cache yang_type_cache;
|
||||||
*
|
*
|
||||||
* This is an internal type, not exposed in the API
|
* This is an internal type, not exposed in the API
|
||||||
* The external type is "yang_stmt" defined in clixon_yang.h
|
* 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
|
||||||
*/
|
*/
|
||||||
struct yang_stmt{
|
struct yang_stmt {
|
||||||
int ys_len; /* Number of children */
|
/* On x86_64, the following three fields take 8 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
|
||||||
|
/* Increases memory w 8 extra bytes on x86_64
|
||||||
|
* XXX: can we enable this when needed for schema nodeid sub-parsing? */
|
||||||
|
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_stmt; /* Vector of children statement pointers */
|
||||||
struct yang_stmt *ys_parent; /* Backpointer to parent: yang-stmt or yang-spec */
|
struct yang_stmt *ys_parent; /* Backpointer to parent: yang-stmt or yang-spec */
|
||||||
struct yang_stmt *ys_orig; /* Backpointer to grouping/augment original */
|
|
||||||
enum rfc_6020 ys_keyword; /* YANG keyword */
|
|
||||||
char *ys_argument; /* String / argument depending on keyword */
|
char *ys_argument; /* String / argument depending on keyword */
|
||||||
uint16_t ys_flags; /* Flags according to YANG_FLAG_MARK and others */
|
/* XXX: can we move this to union, No SPEC is already there */
|
||||||
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
|
|
||||||
*/
|
|
||||||
cg_var *ys_cv; /* cligen variable. See ys_populate()
|
cg_var *ys_cv; /* cligen variable. See ys_populate()
|
||||||
Following stmts have cv:s:
|
Following stmts have cv:s:
|
||||||
leaf: for default value
|
Y_FEATURE: boolean true or false
|
||||||
leaf-list,
|
Y_CONFIG: boolean true or false
|
||||||
config: boolean true or false
|
Y_LEAF: for default value
|
||||||
mandatory: boolean true or false
|
Y_LEAF_LIST,
|
||||||
require-instance: true or false
|
Y_MAX_ELEMENTS:
|
||||||
fraction-digits for fraction-digits
|
Y_MIN_ELEMENTS: inte
|
||||||
revision (uint32)
|
Y_MANDATORY: boolean true or false
|
||||||
unknown-stmt (optional argument)
|
Y_REQUIRE_INSTANCE: true or false
|
||||||
spec: mount-point xpath
|
Y_FRACTION_DIGITS for fraction-digits
|
||||||
enum: value
|
Y_REVISION (uint32)
|
||||||
|
Y_REVISION_DATE (uint32)
|
||||||
|
Y_UNKNOWN (optional argument)
|
||||||
|
Y_SPEC: mount-point xpath
|
||||||
|
Y_ENUM: value
|
||||||
*/
|
*/
|
||||||
cvec *ys_cvec; /* List of stmt-specific variables
|
cvec *ys_cvec; /* List of stmt-specific variables
|
||||||
Y_RANGE: range_min, range_max
|
Y_CONTAINER: XXX or U_UNKNOWN?
|
||||||
Y_LIST: vector of keys
|
|
||||||
Y_TYPE & identity: store all derived
|
|
||||||
types as <module>:<id> list
|
|
||||||
Y_UNIQUE: vector of descendant schema node ids
|
|
||||||
Y_EXTENSION: vector of instantiated UNKNOWNS
|
Y_EXTENSION: vector of instantiated UNKNOWNS
|
||||||
Y_UNKNOWN: app-dep: yang-mount-points
|
Y_IDENTITY: store all derived types as <module>:<id> list
|
||||||
|
Y_LENGTH: length_min, length_max
|
||||||
|
Y_LIST: vector of keys
|
||||||
|
Y_RANGE: range_min, range_max
|
||||||
|
Y_TYPE: store all derived types as <module>:<id> list
|
||||||
|
Y_UNIQUE: vector of descendant schema node ids
|
||||||
|
# Y_UNKNOWN: app-dep: yang-mount-points
|
||||||
*/
|
*/
|
||||||
int ys_ref; /* Reference count for free, only YS_SPEC: 0 means
|
union { /* depends on ys_keyword */
|
||||||
* no sharing, 1: two references
|
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 *ys_typecache; /* If ys_keyword==Y_TYPE, cache all typedef data except unions */
|
yang_type_cache *ysu_typecache; /* Y_TYPE: cache all typedef data except unions */
|
||||||
char *ys_when_xpath; /* Special conditional for a "when"-associated augment/uses xpath */
|
int ysu_ref; /* Y_SPEC: Reference count for free: 0 means
|
||||||
cvec *ys_when_nsc; /* Special conditional for a "when"-associated augment/uses namespace ctx */
|
* no sharing, 1: two references */
|
||||||
char *ys_filename; /* For debug/errors: filename (only (sub)modules) */
|
} u;
|
||||||
int ys_linenum; /* For debug/errors: line number (in ys_filename) */
|
|
||||||
rpc_callback_t *ys_action_cb; /* Action callback list, only for Y_ACTION */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*! An extended yang struct for use of extra fields that consumes more memory
|
||||||
|
*
|
||||||
|
* 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 */
|
||||||
|
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;
|
||||||
|
/* Following fields could be extended only for unknown, grouped and augmented nodes
|
||||||
|
*/
|
||||||
|
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 */
|
||||||
|
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 */
|
||||||
|
};
|
||||||
|
typedef struct yang_stmt_extended yang_stmt_extended;
|
||||||
|
|
||||||
|
/* Access macros */
|
||||||
|
#define ys_action_cb u.ysu_action_cb
|
||||||
|
#define ys_filename u.ysu_filename
|
||||||
|
#define ys_typecache u.ysu_typecache
|
||||||
|
#define ys_ref u.ysu_ref
|
||||||
|
|
||||||
#endif /* _CLIXON_YANG_INTERNAL_H_ */
|
#endif /* _CLIXON_YANG_INTERNAL_H_ */
|
||||||
|
|
|
||||||
|
|
@ -181,8 +181,8 @@ ys_grouping_resolve(yang_stmt *yuses,
|
||||||
else {
|
else {
|
||||||
ys = yuses; /* Check upwards in hierarchy for matching groupings */
|
ys = yuses; /* Check upwards in hierarchy for matching groupings */
|
||||||
while (1){
|
while (1){
|
||||||
if (ys->ys_mymodule){
|
if (yang_mymodule_get(ys)){
|
||||||
yp = ys->ys_mymodule;
|
yp = yang_mymodule_get(ys);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if ((yp = yang_parent_get(ys)) == NULL)
|
if ((yp = yang_parent_get(ys)) == NULL)
|
||||||
|
|
@ -356,13 +356,13 @@ yang_augment_node(clixon_handle h,
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((yc = ys_dup(yc0)) == NULL)
|
if ((yc = yse_dup(yc0)) == NULL) /* Extended */
|
||||||
goto done;
|
goto done;
|
||||||
#ifdef YANG_GROUPING_AUGMENT_SKIP
|
#ifdef YANG_GROUPING_AUGMENT_SKIP
|
||||||
/* cornercase: always expand uses under augment */
|
/* cornercase: always expand uses under augment */
|
||||||
yang_flag_reset(yc, YANG_FLAG_GROUPING);
|
yang_flag_reset(yc, YANG_FLAG_GROUPING);
|
||||||
#endif
|
#endif
|
||||||
yc->ys_mymodule = ymod;
|
yang_mymodule_set(yc, ymod);
|
||||||
if (yn_insert(ytarget, yc) < 0)
|
if (yn_insert(ytarget, yc) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* If there is an associated when statement, add a special when struct to the yang
|
/* If there is an associated when statement, add a special when struct to the yang
|
||||||
|
|
@ -564,10 +564,17 @@ yang_expand_uses_node(yang_stmt *yn,
|
||||||
if (ys_grouping_resolve(ys, prefix, id, &ygrouping) < 0)
|
if (ys_grouping_resolve(ys, prefix, id, &ygrouping) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ygrouping == NULL){
|
if (ygrouping == NULL){
|
||||||
if ((ym = ys_module(yn)) != NULL)
|
if ((ym = ys_module(yn)) != NULL){
|
||||||
clixon_err(OE_YANG, 0, "Yang error : grouping \"%s\" not found in module \"%s\" in file: %s:%d",
|
#ifdef YANG_SPEC_LINENR
|
||||||
|
clixon_err(OE_YANG, 0, "Yang error : grouping \"%s\" not found in module \"%s\" in file: %s:%u",
|
||||||
yang_argument_get(ys), yang_argument_get(ys_module(ys)),
|
yang_argument_get(ys), yang_argument_get(ys_module(ys)),
|
||||||
yang_filename_get(ym), yang_linenum_get(yn));
|
yang_filename_get(ym), yang_linenum_get(yn));
|
||||||
|
#else
|
||||||
|
clixon_err(OE_YANG, 0, "Yang error : grouping \"%s\" not found in module \"%s\" in file: %s",
|
||||||
|
yang_argument_get(ys), yang_argument_get(ys_module(ys)),
|
||||||
|
yang_filename_get(ym));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
else
|
else
|
||||||
clixon_err(OE_YANG, 0, "Yang error : grouping \"%s\" not found in module \"%s\"",
|
clixon_err(OE_YANG, 0, "Yang error : grouping \"%s\" not found in module \"%s\"",
|
||||||
yang_argument_get(ys), yang_argument_get(ys_module(ys)));
|
yang_argument_get(ys), yang_argument_get(ys_module(ys)));
|
||||||
|
|
@ -594,13 +601,42 @@ yang_expand_uses_node(yang_stmt *yn,
|
||||||
if (yang_expand_grouping(ygrouping) < 0)
|
if (yang_expand_grouping(ygrouping) < 0)
|
||||||
goto done;
|
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;
|
||||||
|
}
|
||||||
/* Make a copy of the grouping, then make refinements to this copy
|
/* 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
|
* 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.
|
* functions which assume a full hierarchy, use the original ygrouping in those cases.
|
||||||
*/
|
*/
|
||||||
if ((ygrouping2 = ys_dup(ygrouping)) == NULL)
|
if ((ygrouping2 = ys_new(ygrouping->ys_keyword)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
/* Use yse_new() etc for ygrouping2 CHILDREN IF ywhen is set */
|
||||||
|
if (ys_cp_one(ygrouping2, ygrouping) < 0){
|
||||||
|
ys_free(ygrouping2);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
yang_stmt *ycn; /* new child */
|
||||||
|
yang_stmt *yco; /* old child */
|
||||||
|
int i;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
/* Only replace data/schemanodes and unknowns:
|
/* Only replace data/schemanodes and unknowns:
|
||||||
* Compute the number of such nodes, and extend the child vector with that below
|
* Compute the number of such nodes, and extend the child vector with that below
|
||||||
*/
|
*/
|
||||||
|
|
@ -631,12 +667,6 @@ yang_expand_uses_node(yang_stmt *yn,
|
||||||
if (size)
|
if (size)
|
||||||
memmove(&yn->ys_stmt[i+glen+1], &yn->ys_stmt[i+1], size);
|
memmove(&yn->ys_stmt[i+glen+1], &yn->ys_stmt[i+1], size);
|
||||||
}
|
}
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
/* Note: yang_desc_schema_nodeid() requires ygrouping2 to be in yspec tree,
|
/* Note: yang_desc_schema_nodeid() requires ygrouping2 to be in yspec tree,
|
||||||
* due to correct module prefixes etc.
|
* due to correct module prefixes etc.
|
||||||
* cannot be dangling, insert into tree here and then prune immediately after while loop
|
* cannot be dangling, insert into tree here and then prune immediately after while loop
|
||||||
|
|
|
||||||
|
|
@ -263,7 +263,7 @@ ys_resolve_type(yang_stmt *ys,
|
||||||
/* Cache the type resolving locally. Only place where this is done.
|
/* Cache the type resolving locally. Only place where this is done.
|
||||||
* Why not do it in yang_type_resolve? (compile regexps needs clixon_handle)
|
* Why not do it in yang_type_resolve? (compile regexps needs clixon_handle)
|
||||||
*/
|
*/
|
||||||
if (yang_type_cache_set(ys, resolved, options, cvv,
|
if (yang_type_cache_set2(ys, resolved, options, cvv,
|
||||||
patterns, fraction) < 0)
|
patterns, fraction) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -1345,14 +1345,14 @@ yang_type_resolve(yang_stmt *yorig,
|
||||||
goto done;
|
goto done;
|
||||||
/* Cache does not work for eg string length 32? */
|
/* Cache does not work for eg string length 32? */
|
||||||
#if 1
|
#if 1
|
||||||
if ((ret = yang_type_cache_get(ytype, yrestype,
|
if ((ret = yang_type_cache_get2(ytype, yrestype,
|
||||||
options, cvv, patterns, NULL, regexps, fraction)) < 0)
|
options, cvv, patterns, NULL, regexps, fraction)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 1)
|
if (ret == 1)
|
||||||
goto ok;
|
goto ok;
|
||||||
#else
|
#else
|
||||||
if (ytype->ys_typecache != NULL){
|
if (yang_typecache_get(ytype) != NULL){
|
||||||
if (yang_type_cache_get(ytype, yrestype,
|
if (yang_type_cache_get2(ytype, yrestype,
|
||||||
options, cvv, patterns, NULL, regexps, fraction) < 0)
|
options, cvv, patterns, NULL, regexps, fraction) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
goto ok;
|
goto ok;
|
||||||
|
|
|
||||||
|
|
@ -292,7 +292,7 @@ new "Netconf set undefined acl-type"
|
||||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><acls xmlns=\"urn:example:my-crypto\"><acl><name>x</name><type>undefined</type></acl></acls></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><acls xmlns=\"urn:example:my-crypto\"><acl><name>x</name><type>undefined</type></acl></acls></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||||
|
|
||||||
new "netconf validate fail"
|
new "netconf validate fail"
|
||||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>operation-failed</error-tag><error-severity>error</error-severity><error-message>Identityref validation failed, undefined not derived from acl-base in example-my-crypto.yang:[0-9]*</error-message></rpc-error></rpc-reply>" ""
|
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>operation-failed</error-tag><error-severity>error</error-severity><error-message>Identityref validation failed, undefined not derived from acl-base in example-my-crypto.yang" ""
|
||||||
|
|
||||||
new "netconf discard-changes"
|
new "netconf discard-changes"
|
||||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><discard-changes/></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><discard-changes/></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||||
|
|
|
||||||
|
|
@ -227,7 +227,7 @@ new "Re-Delete eth/0/0 using none should generate error"
|
||||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><interfaces xmlns=\"urn:ietf:params:xml:ns:yang:ietf-interfaces\" xmlns:nc=\"${BASENS}\"><interface nc:operation=\"delete\"><name>eth/0/0</name><type>ex:eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>" "<rpc-reply $DEFAULTNS><rpc-error>" ""
|
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><interfaces xmlns=\"urn:ietf:params:xml:ns:yang:ietf-interfaces\" xmlns:nc=\"${BASENS}\"><interface nc:operation=\"delete\"><name>eth/0/0</name><type>ex:eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>" "<rpc-reply $DEFAULTNS><rpc-error>" ""
|
||||||
|
|
||||||
new "Add interface without key"
|
new "Add interface without key"
|
||||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><interfaces xmlns=\"urn:ietf:params:xml:ns:yang:ietf-interfaces\" xmlns:nc=\"${BASENS}\"><interface nc:operation=\"create\"><type>ex:eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>" "<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>missing-element</error-tag><error-info><bad-element>name</bad-element></error-info><error-severity>error</error-severity><error-message>Mandatory key in 'list interface' in ietf-interfaces.yang:[0-9]\+</error-message></rpc-error></rpc-reply>" ""
|
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><interfaces xmlns=\"urn:ietf:params:xml:ns:yang:ietf-interfaces\" xmlns:nc=\"${BASENS}\"><interface nc:operation=\"create\"><type>ex:eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>" "<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>missing-element</error-tag><error-info><bad-element>name</bad-element></error-info><error-severity>error</error-severity><error-message>Mandatory key in 'list interface' in ietf-interfaces.yang"
|
||||||
|
|
||||||
new "netconf discard-changes"
|
new "netconf discard-changes"
|
||||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><discard-changes/></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><discard-changes/></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ cfg=$dir/conf_yang.xml
|
||||||
new "openconfig"
|
new "openconfig"
|
||||||
if [ ! -d "$OPENCONFIG" ]; then
|
if [ ! -d "$OPENCONFIG" ]; then
|
||||||
# err "Hmm Openconfig dir does not seem to exist, try git clone https://github.com/openconfig/public?"
|
# err "Hmm Openconfig dir does not seem to exist, try git clone https://github.com/openconfig/public?"
|
||||||
echo "...skipped: OPENCONFIG not set"
|
echo "...skipped: OPENCONFIG not set or dir not exist"
|
||||||
rm -rf $dir
|
rm -rf $dir
|
||||||
if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,7 @@ new "wait restconf"
|
||||||
wait_restconf
|
wait_restconf
|
||||||
|
|
||||||
new "restconf POST tree without key"
|
new "restconf POST tree without key"
|
||||||
expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" -d '{"example:cont1":{"interface":{"type":"regular"}}}' $RCPROTO://localhost/restconf/data)" 0 "HTTP/$HVER 400" "{\"ietf-restconf:errors\":{\"error\":{\"error-type\":\"application\",\"error-tag\":\"missing-element\",\"error-info\":{\"bad-element\":\"name\"},\"error-severity\":\"error\",\"error-message\":\"Mandatory key in 'list interface' in example.yang:7\"}}}"
|
expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" -d '{"example:cont1":{"interface":{"type":"regular"}}}' $RCPROTO://localhost/restconf/data)" 0 "HTTP/$HVER 400" "{\"ietf-restconf:errors\":{\"error\":{\"error-type\":\"application\",\"error-tag\":\"missing-element\",\"error-info\":{\"bad-element\":\"name\"},\"error-severity\":\"error\",\"error-message\":\"Mandatory key in 'list interface' in example.yang"
|
||||||
|
|
||||||
new "restconf POST initial tree"
|
new "restconf POST initial tree"
|
||||||
expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" -d '{"example:cont1":{"interface":{"name":"local0","type":"regular"}}}' $RCPROTO://localhost/restconf/data)" 0 "HTTP/$HVER 201"
|
expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" -d '{"example:cont1":{"interface":{"name":"local0","type":"regular"}}}' $RCPROTO://localhost/restconf/data)" 0 "HTTP/$HVER 201"
|
||||||
|
|
@ -137,7 +137,7 @@ new "restconf POST interface without mandatory type"
|
||||||
expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/example:cont1 -d '{"example:interface":{"name":"TEST"}}')" 0 "HTTP/$HVER 400" '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"missing-element","error-info":{"bad-element":"type"},"error-severity":"error","error-message":"Mandatory variable of interface in module example"}}}'
|
expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/example:cont1 -d '{"example:interface":{"name":"TEST"}}')" 0 "HTTP/$HVER 400" '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"missing-element","error-info":{"bad-element":"type"},"error-severity":"error","error-message":"Mandatory variable of interface in module example"}}}'
|
||||||
|
|
||||||
new "restconf POST interface without mandatory key"
|
new "restconf POST interface without mandatory key"
|
||||||
expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/example:cont1 -d '{"example:interface":{"type":"regular"}}')" 0 "HTTP/$HVER 400" "{\"ietf-restconf:errors\":{\"error\":{\"error-type\":\"application\",\"error-tag\":\"missing-element\",\"error-info\":{\"bad-element\":\"name\"},\"error-severity\":\"error\",\"error-message\":\"Mandatory key in 'list interface' in example.yang:7\"}}}"
|
expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/example:cont1 -d '{"example:interface":{"type":"regular"}}')" 0 "HTTP/$HVER 400" "{\"ietf-restconf:errors\":{\"error\":{\"error-type\":\"application\",\"error-tag\":\"missing-element\",\"error-info\":{\"bad-element\":\"name\"},\"error-severity\":\"error\",\"error-message\":\"Mandatory key in 'list interface' in example.yang"
|
||||||
|
|
||||||
new "restconf POST interface"
|
new "restconf POST interface"
|
||||||
expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" -d '{"example:interface":{"name":"TEST","type":"eth0"}}' $RCPROTO://localhost/restconf/data/example:cont1)" 0 "HTTP/$HVER 201"
|
expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" -d '{"example:interface":{"name":"TEST","type":"eth0"}}' $RCPROTO://localhost/restconf/data/example:cont1)" 0 "HTTP/$HVER 201"
|
||||||
|
|
|
||||||
|
|
@ -347,8 +347,8 @@ new "netconf example rpc input list with key"
|
||||||
expecteof_netconf "$clixon_netconf -qef $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><example xmlns=\"urn:example:clixon\"><x>mandatory</x>$LIST</example></rpc>" "" "<rpc-reply $DEFAULTNS><x xmlns=\"urn:example:clixon\">mandatory</x><y xmlns=\"urn:example:clixon\">42</y>$LIST</rpc-reply>"
|
expecteof_netconf "$clixon_netconf -qef $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><example xmlns=\"urn:example:clixon\"><x>mandatory</x>$LIST</example></rpc>" "" "<rpc-reply $DEFAULTNS><x xmlns=\"urn:example:clixon\">mandatory</x><y xmlns=\"urn:example:clixon\">42</y>$LIST</rpc-reply>"
|
||||||
|
|
||||||
LIST='<u1 xmlns="urn:example:clixon"><uk>bar</uk><val>1</val></u1><u1 xmlns="urn:example:clixon"><val>2</val></u1>'
|
LIST='<u1 xmlns="urn:example:clixon"><uk>bar</uk><val>1</val></u1><u1 xmlns="urn:example:clixon"><val>2</val></u1>'
|
||||||
new "netconf example rpc input key list without key (should fail)"
|
new "netconf example rpc input key list without key (should fail) XXX"
|
||||||
expecteof_netconf "$clixon_netconf -qef $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><example xmlns=\"urn:example:clixon\"><x>mandatory</x>$LIST</example></rpc>" "" "<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>missing-element</error-tag><error-info><bad-element>uk</bad-element></error-info><error-severity>error</error-severity><error-message>Mandatory key in 'list u1' in clixon-example.yang:62</error-message></rpc-error></rpc-reply>"
|
expecteof_netconf "$clixon_netconf -qef $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><example xmlns=\"urn:example:clixon\"><x>mandatory</x>$LIST</example></rpc>" "<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>missing-element</error-tag><error-info><bad-element>uk</bad-element></error-info><error-severity>error</error-severity><error-message>Mandatory key in 'list u1' in clixon-example.yang"
|
||||||
|
|
||||||
LIST='<u1 xmlns="urn:example:clixon"><uk>bar</uk><val>1</val></u1><u1 xmlns="urn:example:clixon"><uk>bar</uk><val>2</val></u1>'
|
LIST='<u1 xmlns="urn:example:clixon"><uk>bar</uk><val>1</val></u1><u1 xmlns="urn:example:clixon"><uk>bar</uk><val>2</val></u1>'
|
||||||
new "netconf example rpc input list with non-unique keys (should fail)"
|
new "netconf example rpc input list with non-unique keys (should fail)"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue