YANG optimize, add orig pointer for derived trees
Skip some yang objects in derived trees Add function to remove USES in augment/grouping trees
This commit is contained in:
parent
ca786da156
commit
781c9d9d27
11 changed files with 294 additions and 118 deletions
|
|
@ -521,7 +521,7 @@ usage(clixon_handle h,
|
||||||
"\t-h \t\tHelp\n"
|
"\t-h \t\tHelp\n"
|
||||||
"\t-V \t\tPrint version and exit\n"
|
"\t-V \t\tPrint version and exit\n"
|
||||||
"\t-D <level> \tDebug level (see available levels below)\n"
|
"\t-D <level> \tDebug level (see available levels below)\n"
|
||||||
"\t-f <file> \tConfig-file (mandatory)\n"
|
"\t-f <file> \tConfig-file\n"
|
||||||
"\t-E <dir> \tExtra configuration file directory\n"
|
"\t-E <dir> \tExtra configuration file directory\n"
|
||||||
"\t-l <s|e|o|n|f<file>> \tLog on (s)yslog, std(e)rr, std(o)ut, (n)one or (f)ile (stderr is default)\n"
|
"\t-l <s|e|o|n|f<file>> \tLog on (s)yslog, std(e)rr, std(o)ut, (n)one or (f)ile (stderr is default)\n"
|
||||||
"\t-C <format>\tDump configuration options on stdout after loading. Format is xml|json|text\n"
|
"\t-C <format>\tDump configuration options on stdout after loading. Format is xml|json|text\n"
|
||||||
|
|
|
||||||
|
|
@ -204,3 +204,9 @@
|
||||||
* If not set, reduces memory with 8 bytes per yang-stmt.
|
* If not set, reduces memory with 8 bytes per yang-stmt.
|
||||||
*/
|
*/
|
||||||
#undef YANG_SPEC_LINENR
|
#undef YANG_SPEC_LINENR
|
||||||
|
|
||||||
|
/*! Use ref origin pointer to skip as many derived yang nodes as possible
|
||||||
|
*
|
||||||
|
* If set, do not copy some YANG nodes to derived trees (ie augmented or grouped trees)
|
||||||
|
*/
|
||||||
|
#define YANG_ORIG_PTR_SKIP
|
||||||
|
|
|
||||||
|
|
@ -90,9 +90,8 @@
|
||||||
* 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
|
#define YANG_FLAG_WHEN 0x400 /* Use extended struct to access when-info for
|
||||||
* Memory optimization
|
* augment/grouping */
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Types
|
* Types
|
||||||
|
|
@ -240,6 +239,8 @@ yang_stmt *yang_parent_get(yang_stmt *ys);
|
||||||
enum rfc_6020 yang_keyword_get(yang_stmt *ys);
|
enum rfc_6020 yang_keyword_get(yang_stmt *ys);
|
||||||
char *yang_argument_get(yang_stmt *ys);
|
char *yang_argument_get(yang_stmt *ys);
|
||||||
int yang_argument_set(yang_stmt *ys, char *arg);
|
int yang_argument_set(yang_stmt *ys, char *arg);
|
||||||
|
yang_stmt *yang_orig_get(yang_stmt *ys);
|
||||||
|
int yang_orig_set(yang_stmt *ys, yang_stmt *y0);
|
||||||
cg_var *yang_cv_get(yang_stmt *ys);
|
cg_var *yang_cv_get(yang_stmt *ys);
|
||||||
int yang_cv_set(yang_stmt *ys, cg_var *cv);
|
int yang_cv_set(yang_stmt *ys, cg_var *cv);
|
||||||
cvec *yang_cvec_get(yang_stmt *ys);
|
cvec *yang_cvec_get(yang_stmt *ys);
|
||||||
|
|
@ -271,7 +272,6 @@ int yang_stats(yang_stmt *y, enum rfc_6020 keyw, uint64_t *nrp, size_t *s
|
||||||
/* 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);
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ int yang_file_find_match(clixon_handle h, const char *module, const char
|
||||||
yang_stmt *yang_parse_filename(clixon_handle h, const char *filename, yang_stmt *ysp);
|
yang_stmt *yang_parse_filename(clixon_handle h, const char *filename, yang_stmt *ysp);
|
||||||
yang_stmt *yang_parse_module(clixon_handle h, const char *module, const char *revision, yang_stmt *yspec, char *origname);
|
yang_stmt *yang_parse_module(clixon_handle h, const char *module, const char *revision, yang_stmt *yspec, char *origname);
|
||||||
int yang_parse_post(clixon_handle h, yang_stmt *yspec, int modmin);
|
int yang_parse_post(clixon_handle h, yang_stmt *yspec, int modmin);
|
||||||
|
int yang_parse_optimize_uses(clixon_handle h, yang_stmt *yspec);
|
||||||
int yang_spec_parse_module(clixon_handle h, const char *module,
|
int yang_spec_parse_module(clixon_handle h, const char *module,
|
||||||
const char *revision, yang_stmt *yspec);
|
const char *revision, yang_stmt *yspec);
|
||||||
yang_stmt *yang_parse_str(char *str, const char *name, yang_stmt *yspec);
|
yang_stmt *yang_parse_str(char *str, const char *name, yang_stmt *yspec);
|
||||||
|
|
|
||||||
|
|
@ -796,17 +796,11 @@ xml_yang_validate_minmax(cxobj *xt,
|
||||||
goto fail;
|
goto fail;
|
||||||
if (presence && keyw == Y_CONTAINER &&
|
if (presence && keyw == Y_CONTAINER &&
|
||||||
yang_find(y, Y_PRESENCE, NULL) == NULL){
|
yang_find(y, Y_PRESENCE, NULL) == NULL){
|
||||||
yang_stmt *yc;
|
|
||||||
int inext;
|
|
||||||
|
|
||||||
inext = 0;
|
|
||||||
while ((yc = yn_iter(y, &inext)) != NULL) {
|
|
||||||
if ((ret = xml_yang_validate_minmax(x, presence, xret)) < 0)
|
if ((ret = xml_yang_validate_minmax(x, presence, xret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
yprev = y;
|
yprev = y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -255,6 +255,41 @@ yang_argument_set(yang_stmt *ys,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Get original back-pointer if node is grouping or augmented
|
||||||
|
*
|
||||||
|
* Defined only if this statement was created as part of a uses/grouping or augment expansion
|
||||||
|
* @param[in] ys Yang statement node
|
||||||
|
* @retval y0 Original yang statement node
|
||||||
|
* @retval NULL Not part of grouping
|
||||||
|
*/
|
||||||
|
yang_stmt *
|
||||||
|
yang_orig_get(yang_stmt *ys)
|
||||||
|
{
|
||||||
|
if (ys->ys_orig)
|
||||||
|
assert(ys->ys_orig->ys_orig == NULL);
|
||||||
|
return ys->ys_orig;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Set original back-pointer if any
|
||||||
|
*
|
||||||
|
* Will recursively evaluate to set to original node in case of chain of groupings
|
||||||
|
* @param[in] ys Yang statement node
|
||||||
|
* @param[in] y0 Original yang statement node
|
||||||
|
* @retval NULL Not part of grouping
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
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
|
||||||
|
ys->ys_orig = y0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Get yang statement CLIgen variable
|
/*! Get yang statement CLIgen variable
|
||||||
*
|
*
|
||||||
* See comment under ys_cv for how this is used
|
* See comment under ys_cv for how this is used
|
||||||
|
|
@ -449,7 +484,7 @@ yang_when_xpath_get(yang_stmt *ys)
|
||||||
{
|
{
|
||||||
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
|
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
|
||||||
|
|
||||||
if ((ys->ys_flags & YANG_FLAG_EXTENDED) == 0x0)
|
if ((ys->ys_flags & YANG_FLAG_WHEN) == 0x0)
|
||||||
return NULL;
|
return NULL;
|
||||||
else
|
else
|
||||||
return yse->yse_when_xpath;
|
return yse->yse_when_xpath;
|
||||||
|
|
@ -475,8 +510,8 @@ yang_when_xpath_set(yang_stmt *ys,
|
||||||
clixon_err(OE_YANG, EINVAL, "xpath is NULL");
|
clixon_err(OE_YANG, EINVAL, "xpath is NULL");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((ys->ys_flags & YANG_FLAG_EXTENDED) == 0x0){
|
if ((ys->ys_flags & YANG_FLAG_WHEN) == 0x0){
|
||||||
clixon_err(OE_YANG, EINVAL, "Yang node %s %s must have flag YANG_FLAG_EXTENDED for this operation",
|
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);
|
yang_key2str(ys->ys_keyword), ys->ys_argument);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -502,7 +537,7 @@ yang_when_nsc_get(yang_stmt *ys)
|
||||||
{
|
{
|
||||||
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
|
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
|
||||||
|
|
||||||
if ((ys->ys_flags & YANG_FLAG_EXTENDED) == 0x0)
|
if ((ys->ys_flags & YANG_FLAG_WHEN) == 0x0)
|
||||||
return NULL;
|
return NULL;
|
||||||
else
|
else
|
||||||
return yse->yse_when_nsc;
|
return yse->yse_when_nsc;
|
||||||
|
|
@ -524,8 +559,8 @@ yang_when_nsc_set(yang_stmt *ys,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
|
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
|
||||||
|
|
||||||
if ((ys->ys_flags & YANG_FLAG_EXTENDED) == 0x0){
|
if ((ys->ys_flags & YANG_FLAG_WHEN) == 0x0){
|
||||||
clixon_err(OE_YANG, EINVAL, "Yang node %s %s must have flag YANG_FLAG_EXTENDED for this operation",
|
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);
|
yang_key2str(ys->ys_keyword), ys->ys_argument);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -609,7 +644,6 @@ yang_linenum_set(yang_stmt *ys,
|
||||||
void *
|
void *
|
||||||
yang_typecache_get(yang_stmt *ys)
|
yang_typecache_get(yang_stmt *ys)
|
||||||
{
|
{
|
||||||
// assert(ys->ys_keyword == Y_TYPE);
|
|
||||||
return ys->ys_typecache;
|
return ys->ys_typecache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -623,7 +657,6 @@ int
|
||||||
yang_typecache_set(yang_stmt *ys,
|
yang_typecache_set(yang_stmt *ys,
|
||||||
void *ycache)
|
void *ycache)
|
||||||
{
|
{
|
||||||
// assert(ys->ys_keyword == Y_TYPE);
|
|
||||||
ys->ys_typecache = ycache;
|
ys->ys_typecache = ycache;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -637,12 +670,7 @@ yang_typecache_set(yang_stmt *ys,
|
||||||
yang_stmt*
|
yang_stmt*
|
||||||
yang_mymodule_get(yang_stmt *ys)
|
yang_mymodule_get(yang_stmt *ys)
|
||||||
{
|
{
|
||||||
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
|
return ys->ys_mymodule;
|
||||||
|
|
||||||
if ((ys->ys_flags & YANG_FLAG_EXTENDED) == 0x0)
|
|
||||||
return NULL;
|
|
||||||
else
|
|
||||||
return yse->yse_mymodule;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Set mymodule
|
/*! Set mymodule
|
||||||
|
|
@ -651,19 +679,13 @@ yang_mymodule_get(yang_stmt *ys)
|
||||||
* @param[in] ys YANG statement
|
* @param[in] ys YANG statement
|
||||||
* @param[in] ymod YANG module
|
* @param[in] ymod YANG module
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
yang_mymodule_set(yang_stmt *ys,
|
yang_mymodule_set(yang_stmt *ys,
|
||||||
yang_stmt *ym)
|
yang_stmt *ym)
|
||||||
{
|
{
|
||||||
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
|
ys->ys_mymodule = ym;
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -698,7 +720,7 @@ yang_stats_one(yang_stmt *ys,
|
||||||
size_t sz = 0;
|
size_t sz = 0;
|
||||||
yang_type_cache *yc;
|
yang_type_cache *yc;
|
||||||
|
|
||||||
if (yang_flag_get(ys, YANG_FLAG_EXTENDED) == 0x0)
|
if (yang_flag_get(ys, YANG_FLAG_WHEN) == 0x0)
|
||||||
sz += sizeof(struct yang_stmt_extended);
|
sz += sizeof(struct yang_stmt_extended);
|
||||||
else
|
else
|
||||||
sz += sizeof(struct yang_stmt);
|
sz += sizeof(struct yang_stmt);
|
||||||
|
|
@ -707,7 +729,7 @@ yang_stats_one(yang_stmt *ys,
|
||||||
sz += strlen(ys->ys_argument) + 1;
|
sz += strlen(ys->ys_argument) + 1;
|
||||||
if (ys->ys_cvec)
|
if (ys->ys_cvec)
|
||||||
sz += cvec_size(ys->ys_cvec);
|
sz += cvec_size(ys->ys_cvec);
|
||||||
if (yang_flag_get(ys, YANG_FLAG_EXTENDED) != 0x0) {
|
if (yang_flag_get(ys, YANG_FLAG_WHEN) != 0x0) {
|
||||||
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
|
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
|
||||||
if (yse->yse_when_xpath)
|
if (yse->yse_when_xpath)
|
||||||
sz += strlen(yse->yse_when_xpath) + 1;
|
sz += strlen(yse->yse_when_xpath) + 1;
|
||||||
|
|
@ -837,18 +859,7 @@ ys_new_sz(enum rfc_6020 keyw,
|
||||||
yang_stmt *
|
yang_stmt *
|
||||||
ys_new(enum rfc_6020 keyw)
|
ys_new(enum rfc_6020 keyw)
|
||||||
{
|
{
|
||||||
size_t sz;
|
return ys_new_sz(keyw, sizeof(struct yang_stmt));
|
||||||
yang_stmt *ys;
|
|
||||||
|
|
||||||
if (keyw == Y_UNKNOWN)
|
|
||||||
sz = sizeof(struct yang_stmt_extended);
|
|
||||||
else
|
|
||||||
sz = sizeof(*ys);
|
|
||||||
if ((ys = ys_new_sz(keyw, sz)) != NULL &&
|
|
||||||
keyw == Y_UNKNOWN){
|
|
||||||
yang_flag_set(ys, YANG_FLAG_EXTENDED);
|
|
||||||
}
|
|
||||||
return ys;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Create new extended yang node/statement
|
/*! Create new extended yang node/statement
|
||||||
|
|
@ -857,13 +868,13 @@ ys_new(enum rfc_6020 keyw)
|
||||||
* @retval ys New yang-stmt. Free with ys_free()
|
* @retval ys New yang-stmt. Free with ys_free()
|
||||||
* @retval NULL Error
|
* @retval NULL Error
|
||||||
*/
|
*/
|
||||||
yang_stmt *
|
static yang_stmt *
|
||||||
yse_new(enum rfc_6020 keyw)
|
yse_new(enum rfc_6020 keyw)
|
||||||
{
|
{
|
||||||
yang_stmt *ys;
|
yang_stmt *ys;
|
||||||
|
|
||||||
if ((ys = ys_new_sz(keyw, sizeof(struct yang_stmt_extended))) != NULL)
|
if ((ys = ys_new_sz(keyw, sizeof(struct yang_stmt_extended))) != NULL)
|
||||||
yang_flag_set(ys, YANG_FLAG_EXTENDED);
|
yang_flag_set(ys, YANG_FLAG_WHEN);
|
||||||
return ys;
|
return ys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -899,7 +910,7 @@ ys_free1(yang_stmt *ys,
|
||||||
free(ys->ys_argument);
|
free(ys->ys_argument);
|
||||||
ys->ys_argument = NULL;
|
ys->ys_argument = NULL;
|
||||||
}
|
}
|
||||||
if (yang_flag_get(ys, YANG_FLAG_EXTENDED) != 0x0) {
|
if (yang_flag_get(ys, YANG_FLAG_WHEN) != 0x0) {
|
||||||
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
|
yang_stmt_extended *yse = (yang_stmt_extended *)ys;
|
||||||
if (yse->yse_when_xpath)
|
if (yse->yse_when_xpath)
|
||||||
free(yse->yse_when_xpath);
|
free(yse->yse_when_xpath);
|
||||||
|
|
@ -1067,22 +1078,77 @@ yn_realloc(yang_stmt *yn)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef YANG_ORIG_PTR_SKIP
|
||||||
|
/*! Return 1 if yang stmt should be skipped in derived trees
|
||||||
|
*
|
||||||
|
* @param[in] keyword YANG keyword
|
||||||
|
* @retval 1 Yes, use orig-ptr if exists to fetch original object
|
||||||
|
* @retval 0 No, use existing object
|
||||||
|
* Comments includes for:
|
||||||
|
* - nodes that could not be skipped and the failed test
|
||||||
|
* - nodes that have children in turn
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
uses_orig_ptr(enum rfc_6020 keyword)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
// keyword == Y_CONFIG // NO (test_openconfig.sh)
|
||||||
|
// keyword == Y_DEFAULT // NO (test_augment.sh)
|
||||||
|
keyword == Y_DESCRIPTION
|
||||||
|
|| keyword == Y_ENUM // children
|
||||||
|
|| keyword == Y_ERROR_APP_TAG
|
||||||
|
|| keyword == Y_ERROR_MESSAGE
|
||||||
|
|| keyword == Y_FRACTION_DIGITS
|
||||||
|
// || keyword == Y_KEY // NO
|
||||||
|
|| keyword == Y_LENGTH // children
|
||||||
|
|| keyword == Y_MANDATORY
|
||||||
|
|| keyword == Y_MAX_ELEMENTS
|
||||||
|
|| keyword == Y_MIN_ELEMENTS
|
||||||
|
|| keyword == Y_MODIFIER
|
||||||
|
|| keyword == Y_ORDERED_BY
|
||||||
|
|| keyword == Y_PATH
|
||||||
|
|| keyword == Y_PATTERN // children
|
||||||
|
|| keyword == Y_POSITION
|
||||||
|
|| keyword == Y_PREFIX
|
||||||
|
|| keyword == Y_PRESENCE
|
||||||
|
|| keyword == Y_RANGE // children
|
||||||
|
|| keyword == Y_REQUIRE_INSTANCE
|
||||||
|
|| keyword == Y_STATUS
|
||||||
|
|| keyword == Y_UNIQUE
|
||||||
|
|| keyword == Y_UNITS
|
||||||
|
|| keyword == Y_UNKNOWN
|
||||||
|
|| keyword == Y_VALUE
|
||||||
|
|| keyword == Y_YIN_ELEMENT
|
||||||
|
;
|
||||||
|
}
|
||||||
|
#endif /* YANG_ORIG_PTR_SKIP */
|
||||||
|
|
||||||
|
/*! Copy single yang statement no children
|
||||||
|
*
|
||||||
|
* @param[in] ynew New empty (but created) yang statement (to)
|
||||||
|
* @param[in] yold Old existing yang statement (from)
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
|
* @code
|
||||||
|
* yang_stmt *new = ys_new(Y_LEAF);
|
||||||
|
* if (ys_cp_one(new, old) < 0)
|
||||||
|
* err;
|
||||||
|
* @endcode
|
||||||
|
* @see ys_cp for recursive copy
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
ys_cp_one(yang_stmt *ynew,
|
ys_cp_one(yang_stmt *ynew,
|
||||||
yang_stmt *yold)
|
yang_stmt *yold)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *xpath;
|
|
||||||
cvec *cvv;
|
cvec *cvv;
|
||||||
cg_var *cvn;
|
cg_var *cvn;
|
||||||
cg_var *cvo;
|
cg_var *cvo;
|
||||||
size_t sz;
|
size_t sz;
|
||||||
|
|
||||||
if (yang_flag_get(yold, YANG_FLAG_EXTENDED) != 0x0)
|
|
||||||
sz = sizeof(struct yang_stmt_extended);
|
|
||||||
else
|
|
||||||
sz = sizeof(*yold);
|
sz = sizeof(*yold);
|
||||||
memcpy(ynew, yold, sz);
|
memcpy(ynew, yold, sz);
|
||||||
|
yang_flag_reset(ynew, YANG_FLAG_WHEN); /* Dont inherit WHENs */
|
||||||
ynew->ys_parent = NULL;
|
ynew->ys_parent = NULL;
|
||||||
if (yold->ys_stmt)
|
if (yold->ys_stmt)
|
||||||
if ((ynew->ys_stmt = calloc(yold->ys_len, sizeof(yang_stmt *))) == NULL){
|
if ((ynew->ys_stmt = calloc(yold->ys_len, sizeof(yang_stmt *))) == NULL){
|
||||||
|
|
@ -1121,14 +1187,6 @@ ys_cp_one(yang_stmt *ynew,
|
||||||
default:
|
default:
|
||||||
break;
|
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;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
|
|
@ -1153,20 +1211,23 @@ ys_cp(yang_stmt *ynew,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
int i;
|
int i;
|
||||||
|
int j;
|
||||||
yang_stmt *ycn; /* new child */
|
yang_stmt *ycn; /* new child */
|
||||||
yang_stmt *yco; /* old child */
|
yang_stmt *yco; /* old child */
|
||||||
|
|
||||||
if (ys_cp_one(ynew, yold) < 0)
|
if (ys_cp_one(ynew, yold) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
for (i=0; i<ynew->ys_len; i++){
|
for (i=0,j=0; i<yold->ys_len; i++){
|
||||||
yco = yold->ys_stmt[i];
|
yco = yold->ys_stmt[i];
|
||||||
if (yang_flag_get(yco, YANG_FLAG_EXTENDED) != 0x0){
|
#ifdef YANG_ORIG_PTR_SKIP
|
||||||
if ((ycn = yse_dup(yco)) == NULL)
|
if (uses_orig_ptr(yang_keyword_get(yco))) {
|
||||||
goto done;
|
ynew->ys_len--;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else if ((ycn = ys_dup(yco)) == NULL)
|
#endif
|
||||||
|
if ((ycn = ys_dup(yco)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
ynew->ys_stmt[i] = ycn;
|
ynew->ys_stmt[j++] = ycn;
|
||||||
ycn->ys_parent = ynew;
|
ycn->ys_parent = ynew;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -1202,18 +1263,37 @@ ys_dup(yang_stmt *old)
|
||||||
/*! Create a new extdended yang node and copy the contents recursively from the original.
|
/*! Create a new extdended yang node and copy the contents recursively from the original.
|
||||||
*/
|
*/
|
||||||
yang_stmt *
|
yang_stmt *
|
||||||
yse_dup(yang_stmt *old)
|
yse_dup(yang_stmt *yold)
|
||||||
{
|
{
|
||||||
yang_stmt *nw;
|
yang_stmt *ynew;
|
||||||
|
char *xpath;
|
||||||
|
cvec *cvv;
|
||||||
|
|
||||||
if ((nw = yse_new(old->ys_keyword)) == NULL)
|
if ((ynew = yse_new(yold->ys_keyword)) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (ys_cp(nw, old) < 0){
|
if (ys_cp(ynew, yold) < 0){
|
||||||
ys_free(nw);
|
ys_free(ynew);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
yang_flag_set(nw, YANG_FLAG_EXTENDED);
|
yang_flag_set(ynew, YANG_FLAG_WHEN);
|
||||||
return nw;
|
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.
|
/*! Replace yold with ynew (insert ynew at the exact place of yold). Keep yold pointer as-is.
|
||||||
|
|
@ -1340,7 +1420,14 @@ yang_find(yang_stmt *yn,
|
||||||
char *name;
|
char *name;
|
||||||
yang_stmt *yspec;
|
yang_stmt *yspec;
|
||||||
yang_stmt *ym;
|
yang_stmt *ym;
|
||||||
|
#ifdef YANG_ORIG_PTR_SKIP
|
||||||
|
yang_stmt *yorig;
|
||||||
|
|
||||||
|
if ((yorig = yang_orig_get(yn)) != NULL) {
|
||||||
|
if (uses_orig_ptr(keyword))
|
||||||
|
return yang_find(yorig, keyword, argument);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
for (i=0; i<yn->ys_len; i++){
|
for (i=0; i<yn->ys_len; i++){
|
||||||
ys = yn->ys_stmt[i];
|
ys = yn->ys_stmt[i];
|
||||||
if (keyword == 0 || ys->ys_keyword == keyword){
|
if (keyword == 0 || ys->ys_keyword == keyword){
|
||||||
|
|
@ -1368,7 +1455,6 @@ yang_find(yang_stmt *yn,
|
||||||
return yret?yret:yretsub;
|
return yret?yret:yretsub;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Find child data node with matching argument (container, leaf, list, leaf-list)
|
/*! Find child data node with matching argument (container, leaf, list, leaf-list)
|
||||||
*
|
*
|
||||||
* @param[in] yn Yang node, current context node.
|
* @param[in] yn Yang node, current context node.
|
||||||
|
|
@ -2558,7 +2644,6 @@ ys_populate_list(clixon_handle h,
|
||||||
|
|
||||||
if ((ykey = yang_find(ys, Y_KEY, NULL)) == NULL)
|
if ((ykey = yang_find(ys, Y_KEY, NULL)) == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if ((cvv = yang_arg2cvec(ykey, " ")) == NULL)
|
if ((cvv = yang_arg2cvec(ykey, " ")) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
yang_cvec_set(ys, cvv);
|
yang_cvec_set(ys, cvv);
|
||||||
|
|
@ -4202,6 +4287,12 @@ yang_sort_subelements(yang_stmt *ys)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Init yang code
|
||||||
|
*
|
||||||
|
* @param[in] h Clixon handle
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
yang_init(clixon_handle h)
|
yang_init(clixon_handle h)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,14 @@ struct yang_stmt {
|
||||||
Y_UNIQUE: vector of descendant schema node ids
|
Y_UNIQUE: vector of descendant schema node ids
|
||||||
# Y_UNKNOWN: app-dep: yang-mount-points
|
# Y_UNKNOWN: app-dep: yang-mount-points
|
||||||
*/
|
*/
|
||||||
union { /* depends on ys_keyword */
|
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*/
|
rpc_callback_t *ysu_action_cb; /* Y_ACTION: Action callback list*/
|
||||||
char *ysu_filename; /* Y_MODULE/Y_SUBMODULE: For debug/errors: filename */
|
char *ysu_filename; /* Y_MODULE/Y_SUBMODULE: For debug/errors: filename */
|
||||||
yang_type_cache *ysu_typecache; /* Y_TYPE: cache all typedef data except unions */
|
yang_type_cache *ysu_typecache; /* Y_TYPE: cache all typedef data except unions */
|
||||||
|
|
@ -121,6 +128,8 @@ struct yang_stmt {
|
||||||
|
|
||||||
/*! An extended yang struct for use of extra fields that consumes more memory
|
/*! 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)
|
* Cannot fit this into the ysu union because keyword is unknown (or at least a set)
|
||||||
* @see struct yang_stmt for the original struct
|
* @see struct yang_stmt for the original struct
|
||||||
* @note First part of this struct MUST resemble yang_stmt fields (in memory).
|
* @note First part of this struct MUST resemble yang_stmt fields (in memory).
|
||||||
|
|
@ -138,6 +147,13 @@ struct yang_stmt_extended {
|
||||||
char *ys_argument; /* String / argument depending on keyword */
|
char *ys_argument; /* String / argument depending on keyword */
|
||||||
cg_var *yse_cv; /* cligen variable. See ys_populate() */
|
cg_var *yse_cv; /* cligen variable. See ys_populate() */
|
||||||
cvec *yse_cvec; /* List of stmt-specific variables */
|
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 */
|
union { /* depends on ys_keyword */
|
||||||
rpc_callback_t *ysu_action_cb; /* Y_ACTION: Action callback list*/
|
rpc_callback_t *ysu_action_cb; /* Y_ACTION: Action callback list*/
|
||||||
char *ysu_filename; /* Y_MODULE/Y_SUBMODULE: For debug/errors: filename */
|
char *ysu_filename; /* Y_MODULE/Y_SUBMODULE: For debug/errors: filename */
|
||||||
|
|
@ -145,16 +161,12 @@ struct yang_stmt_extended {
|
||||||
int ysu_ref; /* Y_SPEC: Reference count for free: 0 means
|
int ysu_ref; /* Y_SPEC: Reference count for free: 0 means
|
||||||
* no sharing, 1: two references */
|
* no sharing, 1: two references */
|
||||||
} ue;
|
} ue;
|
||||||
/* Following fields could be extended only for unknown, grouped and augmented nodes
|
|
||||||
|
/* The following fields are only in extended
|
||||||
|
* -----------------------------------------
|
||||||
*/
|
*/
|
||||||
char *yse_when_xpath; /* Special conditional for a "when"-associated augment/uses XPath */
|
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 */
|
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;
|
typedef struct yang_stmt_extended yang_stmt_extended;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -614,7 +614,7 @@ yang_stmt *
|
||||||
yang_find_module_by_namespace(yang_stmt *yspec,
|
yang_find_module_by_namespace(yang_stmt *yspec,
|
||||||
char *ns)
|
char *ns)
|
||||||
{
|
{
|
||||||
yang_stmt *ymod;
|
yang_stmt *ymod = NULL;
|
||||||
int inext;
|
int inext;
|
||||||
|
|
||||||
if (ns == NULL)
|
if (ns == NULL)
|
||||||
|
|
|
||||||
|
|
@ -204,6 +204,36 @@ ys_grouping_resolve(yang_stmt *yuses,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Recursively add pointer from derived node to original grouping
|
||||||
|
*
|
||||||
|
* Cannot use yang_apply since one needs to traverse two trees simultaneously
|
||||||
|
* @param[in] yp0 Original statement
|
||||||
|
* @param[in] yp1 Instantiated statement
|
||||||
|
* @retval 0 Ok
|
||||||
|
* @retval -1 Error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
ys_add_orig_ptr(yang_stmt *yp0,
|
||||||
|
yang_stmt *yp1)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
yang_stmt *y0;
|
||||||
|
yang_stmt *y1;
|
||||||
|
int inext;
|
||||||
|
|
||||||
|
inext = 0;
|
||||||
|
while ((y1 = yn_iter(yp1, &inext)) != NULL) {
|
||||||
|
if ((y0 = yang_find(yp0, yang_keyword_get(y1), yang_argument_get(y1))) == NULL)
|
||||||
|
continue;
|
||||||
|
yang_orig_set(y1, y0);
|
||||||
|
if (ys_add_orig_ptr(y0, y1) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*! This is an augment node, augment the original datamodel.
|
/*! This is an augment node, augment the original datamodel.
|
||||||
*
|
*
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
|
|
@ -233,8 +263,8 @@ yang_augment_node(clixon_handle h,
|
||||||
yang_stmt *yc0;
|
yang_stmt *yc0;
|
||||||
yang_stmt *yc;
|
yang_stmt *yc;
|
||||||
yang_stmt *ymod;
|
yang_stmt *ymod;
|
||||||
yang_stmt *ywhen;
|
yang_stmt *ywhen = NULL;
|
||||||
char *wxpath = NULL; /* xpath of when statement */
|
char *wxpath; /* xpath of when statement */
|
||||||
cvec *wnsc = NULL; /* namespace context of when statement */
|
cvec *wnsc = NULL; /* namespace context of when statement */
|
||||||
enum rfc_6020 targetkey;
|
enum rfc_6020 targetkey;
|
||||||
enum rfc_6020 childkey;
|
enum rfc_6020 childkey;
|
||||||
|
|
@ -356,13 +386,27 @@ yang_augment_node(clixon_handle h,
|
||||||
default:
|
default:
|
||||||
break;
|
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 */
|
if ((yc = yse_dup(yc0)) == NULL) /* Extended */
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
|
else if ((yc = ys_dup(yc0)) == NULL)
|
||||||
|
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
|
||||||
yang_mymodule_set(yc, ymod);
|
yang_mymodule_set(yc, ymod);
|
||||||
|
/* Add backpointer to orig. */
|
||||||
|
yang_orig_set(yc, yc0);
|
||||||
|
if (ys_add_orig_ptr(yc0, yc) < 0)
|
||||||
|
goto done;
|
||||||
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
|
||||||
|
|
@ -613,7 +657,6 @@ yang_expand_uses_node(yang_stmt *yn,
|
||||||
*/
|
*/
|
||||||
if ((ygrouping2 = ys_new(ygrouping->ys_keyword)) == 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){
|
if (ys_cp_one(ygrouping2, ygrouping) < 0){
|
||||||
ys_free(ygrouping2);
|
ys_free(ygrouping2);
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -699,6 +742,9 @@ yang_expand_uses_node(yang_stmt *yn,
|
||||||
/* Note: prune here to make dangling again after while loop */
|
/* Note: prune here to make dangling again after while loop */
|
||||||
if (ys_prune_self(ygrouping2) < 0)
|
if (ys_prune_self(ygrouping2) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
/* Add backpointer to orig. */
|
||||||
|
if (ys_add_orig_ptr(ygrouping, ygrouping2) < 0)
|
||||||
|
goto done;
|
||||||
/* Then copy and insert each child element from ygrouping2 to yn */
|
/* Then copy and insert each child element from ygrouping2 to yn */
|
||||||
k=0;
|
k=0;
|
||||||
for (j=0; j<yang_len_get(ygrouping2); j++){
|
for (j=0; j<yang_len_get(ygrouping2); j++){
|
||||||
|
|
@ -1588,6 +1634,39 @@ yang_parse_post(clixon_handle h,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Optimize yang-stmt parse-tree by recursively removing USES stmt in derived trees
|
||||||
|
*
|
||||||
|
* @param[in] h Clixon handle
|
||||||
|
* @param[in] yspec Yang spec tree
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
|
* @note This must be done after yang_parse_post (and yang2cli calls if CLI).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
yang_parse_optimize_uses(clixon_handle h,
|
||||||
|
yang_stmt *yt)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
yang_stmt *ys;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Dont increment due to prune in loop */
|
||||||
|
for (i=0; i<yang_len_get(yt); ){
|
||||||
|
ys = yang_child_i(yt, i);
|
||||||
|
if (yang_orig_get(ys) && yang_keyword_get(ys) == Y_USES){
|
||||||
|
ys_prune(yt, i);
|
||||||
|
ys_free(ys);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (yang_parse_optimize_uses(h, ys) < 0)
|
||||||
|
goto done;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Parse yang specification and its dependencies recursively given module
|
/*! Parse yang specification and its dependencies recursively given module
|
||||||
*
|
*
|
||||||
* @param[in] h clicon handle
|
* @param[in] h clicon handle
|
||||||
|
|
|
||||||
|
|
@ -166,14 +166,7 @@ new "Check entries"
|
||||||
expectpart "$(curl $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/clixon-client:table -H 'Accept: application/yang-data+xml')" 0 "HTTP/$HVER 200" "$XML"
|
expectpart "$(curl $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/clixon-client:table -H 'Accept: application/yang-data+xml')" 0 "HTTP/$HVER 200" "$XML"
|
||||||
|
|
||||||
new "Run $app"
|
new "Run $app"
|
||||||
# Extra test for some archs, eg ubuntu 18 that have problems with:
|
|
||||||
# Sorry, user <user> is not allowed to execute as <user>:clicon on <arch>
|
|
||||||
sudo -g ${CLICON_GROUP} $clixon_netconf 2> /dev/null
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
expectpart "$(sudo -g ${CLICON_GROUP} $app)" 0 '^42$'
|
expectpart "$(sudo -g ${CLICON_GROUP} $app)" 0 '^42$'
|
||||||
else
|
|
||||||
expectpart "$($app)" 0 '^42$'
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ $RC -ne 0 ]; then
|
if [ $RC -ne 0 ]; then
|
||||||
new "Kill restconf daemon"
|
new "Kill restconf daemon"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue