Yang 'refine' feature supported, According to RFC 7950 7.13.2
This commit is contained in:
parent
3dba0b5370
commit
dc45600074
4 changed files with 239 additions and 74 deletions
|
|
@ -16,6 +16,8 @@
|
||||||
* Added clixon_util_regexp utility function
|
* Added clixon_util_regexp utility function
|
||||||
* Added extensive regexp test [test/test_pattern.sh] for both posix and libxml2
|
* Added extensive regexp test [test/test_pattern.sh] for both posix and libxml2
|
||||||
* Added regex cache to type resolution
|
* Added regex cache to type resolution
|
||||||
|
* Yang "refine" feature supported
|
||||||
|
* According to RFC 7950 7.13.2
|
||||||
* Yang "min-element" and "max-element" feature supported
|
* Yang "min-element" and "max-element" feature supported
|
||||||
* According to RFC 7950 7.7.4 and 7.7.5
|
* According to RFC 7950 7.7.4 and 7.7.5
|
||||||
* See (tests)[test/test_minmax.sh]
|
* See (tests)[test/test_minmax.sh]
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ Clixon follows:
|
||||||
However, the following YANG syntax modules are not implemented (reference to RFC7950 in parenthesis):
|
However, the following YANG syntax modules are not implemented (reference to RFC7950 in parenthesis):
|
||||||
- deviation (7.20.3)
|
- deviation (7.20.3)
|
||||||
- action (7.15)
|
- action (7.15)
|
||||||
- refine (7.13.2)
|
- augment in a uses sub-clause (7.17) (module-level augment is implemented)
|
||||||
- status (7.21.2)
|
- status (7.21.2)
|
||||||
- extension (7.19)
|
- extension (7.19)
|
||||||
- YIN (13)
|
- YIN (13)
|
||||||
|
|
|
||||||
|
|
@ -301,7 +301,38 @@ ys_free1(yang_stmt *ys)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Free a tree of yang statements recursively */
|
/*! Remove child i from parent yp (dont free)
|
||||||
|
* @param[in] yp Parent node
|
||||||
|
* @param[in] i Order of child to remove
|
||||||
|
* @retval NULL No such node, nothing done
|
||||||
|
* @retval yc returned orphaned yang node
|
||||||
|
* @see ys_free Deallocate yang node
|
||||||
|
* @note Do not call this in a loop of yang children (unless you know what you are doing)
|
||||||
|
*/
|
||||||
|
static yang_stmt *
|
||||||
|
ys_prune(yang_stmt *yp,
|
||||||
|
int i)
|
||||||
|
{
|
||||||
|
size_t size;
|
||||||
|
yang_stmt *yc = NULL;
|
||||||
|
|
||||||
|
if (i >= yp->ys_len)
|
||||||
|
goto done;
|
||||||
|
size = (yp->ys_len - i - 1)*sizeof(struct yang_stmt *);
|
||||||
|
yc = yp->ys_stmt[i];
|
||||||
|
memmove(&yp->ys_stmt[i],
|
||||||
|
&yp->ys_stmt[i+1],
|
||||||
|
size);
|
||||||
|
yc = yp->ys_stmt[yp->ys_len--] = NULL;;
|
||||||
|
done:
|
||||||
|
return yc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Free a yang statement tree recursively
|
||||||
|
* @param[in] ys Yang node to remove and all its children recursively
|
||||||
|
* @note does not remove yang node from tree
|
||||||
|
* @see ys_prune Remove from parent
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
ys_free(yang_stmt *ys)
|
ys_free(yang_stmt *ys)
|
||||||
{
|
{
|
||||||
|
|
@ -1363,7 +1394,6 @@ ys_populate_leaf(clicon_handle h,
|
||||||
/* 3b. If not default value, indicate empty cv. */
|
/* 3b. If not default value, indicate empty cv. */
|
||||||
cv_flag_set(cv, V_UNSET); /* no value (no default) */
|
cv_flag_set(cv, V_UNSET); /* no value (no default) */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 4. Check if leaf is part of list, if key exists mark leaf as key/unique */
|
/* 4. Check if leaf is part of list, if key exists mark leaf as key/unique */
|
||||||
if (yparent && yparent->ys_keyword == Y_LIST){
|
if (yparent && yparent->ys_keyword == Y_LIST){
|
||||||
if ((ret = yang_key_match(yparent, ys->ys_argument)) < 0)
|
if ((ret = yang_key_match(yparent, ys->ys_argument)) < 0)
|
||||||
|
|
@ -1822,9 +1852,16 @@ ys_populate_unknown(clicon_handle h,
|
||||||
|
|
||||||
/*! Populate with cligen-variables, default values, etc. Sanity checks on complete tree.
|
/*! Populate with cligen-variables, default values, etc. Sanity checks on complete tree.
|
||||||
*
|
*
|
||||||
* We do this in 2nd pass after complete parsing to be sure to have a complete parse-tree
|
* @param[in] ys Yang statement
|
||||||
* See ys_parse_sub for first pass and what can be assumed
|
* @param[in] h Clicon handle
|
||||||
|
* Preferably run this command using yang_apply
|
||||||
|
* Done in 2nd pass after complete parsing to be sure to have a complete
|
||||||
|
* parse-tree
|
||||||
|
|
||||||
* After this pass, cv:s are set for LEAFs and LEAF-LISTs
|
* After this pass, cv:s are set for LEAFs and LEAF-LISTs
|
||||||
|
* @see ys_parse_sub for first pass and what can be assumed
|
||||||
|
* @see ys_populate2 for after grouping expand and augment
|
||||||
|
* (there may be more functions (all?) that may be moved to ys_populate2)
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
ys_populate(yang_stmt *ys,
|
ys_populate(yang_stmt *ys,
|
||||||
|
|
@ -1834,11 +1871,6 @@ ys_populate(yang_stmt *ys,
|
||||||
clicon_handle h = (clicon_handle)arg;
|
clicon_handle h = (clicon_handle)arg;
|
||||||
|
|
||||||
switch(ys->ys_keyword){
|
switch(ys->ys_keyword){
|
||||||
case Y_LEAF:
|
|
||||||
case Y_LEAF_LIST:
|
|
||||||
if (ys_populate_leaf(h, ys) < 0)
|
|
||||||
goto done;
|
|
||||||
break;
|
|
||||||
case Y_LIST:
|
case Y_LIST:
|
||||||
if (ys_populate_list(h, ys) < 0)
|
if (ys_populate_list(h, ys) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1851,11 +1883,6 @@ ys_populate(yang_stmt *ys,
|
||||||
if (ys_populate_length(h, ys) < 0)
|
if (ys_populate_length(h, ys) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
break;
|
break;
|
||||||
case Y_MANDATORY: /* call yang_mandatory() to check if set */
|
|
||||||
case Y_CONFIG:
|
|
||||||
if (ys_parse(ys, CGV_BOOL) == NULL)
|
|
||||||
goto done;
|
|
||||||
break;
|
|
||||||
case Y_TYPE:
|
case Y_TYPE:
|
||||||
if (ys_populate_type(h, ys) < 0)
|
if (ys_populate_type(h, ys) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1880,8 +1907,41 @@ ys_populate(yang_stmt *ys,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Run after grouping expand and augment
|
||||||
|
* @see ys_populate run before grouping expand and augment
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
ys_populate2(yang_stmt *ys,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
clicon_handle h = (clicon_handle)arg;
|
||||||
|
|
||||||
|
switch(ys->ys_keyword){
|
||||||
|
case Y_LEAF:
|
||||||
|
case Y_LEAF_LIST:
|
||||||
|
if (ys_populate_leaf(h, ys) < 0)
|
||||||
|
goto done;
|
||||||
|
break;
|
||||||
|
case Y_MANDATORY: /* call yang_mandatory() to check if set */
|
||||||
|
case Y_CONFIG:
|
||||||
|
if (ys_parse(ys, CGV_BOOL) == NULL)
|
||||||
|
goto done;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Resolve a grouping name from a point in the yang tree
|
/*! Resolve a grouping name from a point in the yang tree
|
||||||
* @retval 0 OK, but ygrouping determines if a grouping was resolved or not
|
* @param[in] ys Yang statement of "uses" statement doing the lookup
|
||||||
|
* @param[in] prefix Prefix of grouping to look for
|
||||||
|
* @param[in] name Name of grouping to look for
|
||||||
|
* @param[out] ygrouping0 A found grouping yang structure as result
|
||||||
|
* @retval 0 OK, ygrouping may be NULL
|
||||||
* @retval -1 Error, with clicon_err called
|
* @retval -1 Error, with clicon_err called
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
|
|
@ -1999,23 +2059,94 @@ yang_augment_spec(yang_stmt *ysp,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Macro expansion of grouping/uses done in step 2 of yang parsing
|
/*! Given a refine node, perform the refinement action on the target refine node
|
||||||
NOTE
|
* The RFC is somewhat complicate in the rules for refine.
|
||||||
RFC6020 says this:
|
* Most nodes will be replaced, but some are added
|
||||||
Identifiers appearing inside the grouping are resolved relative to the scope in which the
|
* @param[in] yr Refine node
|
||||||
grouping is defined, not where it is used. Prefix mappings, type names, grouping
|
* @param[in] yt Refine target node (will be modified)
|
||||||
names, and extension usage are evaluated in the hierarchy where the
|
* @see RFC7950 Sec 7.13.2
|
||||||
"grouping" statement appears.
|
* There may be some missed cornercases
|
||||||
But it will be very difficult to generate keys etc with this semantics. So for now I
|
*/
|
||||||
macro-expand them
|
|
||||||
*/
|
|
||||||
static int
|
static int
|
||||||
yang_expand(yang_stmt *yn)
|
ys_do_refine(yang_stmt *yr,
|
||||||
|
yang_stmt *yt)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
yang_stmt *yrc; /* refine child */
|
||||||
|
yang_stmt *yrc1;
|
||||||
|
yang_stmt *ytc; /* target child */
|
||||||
|
enum rfc_6020 keyw;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Loop through refine node children. First if remove do that first
|
||||||
|
* In some cases remove a set of nodes.
|
||||||
|
*/
|
||||||
|
yrc = NULL;
|
||||||
|
while ((yrc = yn_each(yr, yrc)) != NULL) {
|
||||||
|
keyw = yang_keyword_get(yrc);
|
||||||
|
switch (keyw){
|
||||||
|
case Y_DEFAULT: /* remove old, add new */
|
||||||
|
case Y_DESCRIPTION:
|
||||||
|
case Y_REFERENCE:
|
||||||
|
case Y_CONFIG:
|
||||||
|
case Y_MANDATORY:
|
||||||
|
case Y_PRESENCE:
|
||||||
|
case Y_MIN_ELEMENTS:
|
||||||
|
case Y_MAX_ELEMENTS:
|
||||||
|
case Y_EXTENSION:
|
||||||
|
/* Remove old matching, dont increment due to prune in loop */
|
||||||
|
for (i=0; i<yt->ys_len; ){
|
||||||
|
ytc = yt->ys_stmt[i];
|
||||||
|
if (keyw != yang_keyword_get(ytc)){
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ys_prune(yt, i);
|
||||||
|
ys_free(ytc);
|
||||||
|
}
|
||||||
|
/* fall through and add if not found */
|
||||||
|
case Y_MUST: /* keep old, add new */
|
||||||
|
case Y_IF_FEATURE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Second, add the node(s) */
|
||||||
|
yrc = NULL;
|
||||||
|
while ((yrc = yn_each(yr, yrc)) != NULL) {
|
||||||
|
keyw = yang_keyword_get(yrc);
|
||||||
|
/* Make copy */
|
||||||
|
if ((yrc1 = ys_dup(yrc)) == NULL)
|
||||||
|
goto done;
|
||||||
|
if (yn_insert(yt, yrc1) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Macro expansion of grouping/uses done in step 2 of yang parsing
|
||||||
|
* RFC7950:
|
||||||
|
* Identifiers appearing inside the grouping are resolved
|
||||||
|
* relative to the scope in which the grouping is defined, not where it is
|
||||||
|
* used. Prefix mappings, type names, grouping names, and extension usage are
|
||||||
|
* evaluated in the hierarchy where the "grouping" statement appears.
|
||||||
|
* The identifiers defined in the grouping are not bound to a namespace
|
||||||
|
* until the contents of the grouping are added to the schema tree via a
|
||||||
|
* "uses" statement that does not appear inside a "grouping" statement,
|
||||||
|
* at which point they are bound to the namespace of the current module.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
yang_expand_grouping(yang_stmt *yn)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
yang_stmt *ys = NULL;
|
yang_stmt *ys = NULL;
|
||||||
yang_stmt *ygrouping;
|
yang_stmt *ygrouping; /* grouping original */
|
||||||
yang_stmt *yg;
|
yang_stmt *ygrouping2; /* grouping copy */
|
||||||
|
yang_stmt *yg; /* grouping child */
|
||||||
|
yang_stmt *yr; /* refinement */
|
||||||
int glen;
|
int glen;
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
|
|
@ -2034,20 +2165,21 @@ yang_expand(yang_stmt *yn)
|
||||||
prefix = yarg_prefix(ys); /* And this its prefix */
|
prefix = yarg_prefix(ys); /* And this its prefix */
|
||||||
if (ys_grouping_resolve(ys, prefix, name, &ygrouping) < 0)
|
if (ys_grouping_resolve(ys, prefix, name, &ygrouping) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
if (prefix){
|
||||||
|
free(prefix);
|
||||||
|
prefix = NULL;
|
||||||
|
}
|
||||||
if (ygrouping == NULL){
|
if (ygrouping == NULL){
|
||||||
clicon_log(LOG_NOTICE, "%s: Yang error : grouping \"%s\" not found in module \"%s\"",
|
clicon_log(LOG_NOTICE, "%s: Yang error : grouping \"%s\" not found in module \"%s\"",
|
||||||
__FUNCTION__, ys->ys_argument, ys_module(ys)->ys_argument);
|
__FUNCTION__, ys->ys_argument, ys_module(ys)->ys_argument);
|
||||||
goto done;
|
goto done;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (prefix)
|
|
||||||
free(prefix); /* XXX move up */
|
|
||||||
/* Check mark flag to see if this grouping (itself) has been expanded
|
/* Check mark flag to see if this grouping (itself) has been expanded
|
||||||
If not, this needs to be done before we can insert it into
|
If not, this needs to be done before we can insert it into
|
||||||
the 'uses' place */
|
the 'uses' place */
|
||||||
if ((ygrouping->ys_flags & YANG_FLAG_MARK) == 0){
|
if ((ygrouping->ys_flags & YANG_FLAG_MARK) == 0){
|
||||||
if (yang_expand(ygrouping) < 0)
|
if (yang_expand_grouping(ygrouping) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
ygrouping->ys_flags |= YANG_FLAG_MARK; /* Mark as expanded */
|
ygrouping->ys_flags |= YANG_FLAG_MARK; /* Mark as expanded */
|
||||||
}
|
}
|
||||||
|
|
@ -2072,14 +2204,41 @@ yang_expand(yang_stmt *yn)
|
||||||
&yn->ys_stmt[i+1],
|
&yn->ys_stmt[i+1],
|
||||||
size);
|
size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make a copy of the while grouping making it easier to
|
||||||
|
* refine it */
|
||||||
|
if ((ygrouping2 = ys_dup(ygrouping)) == NULL)
|
||||||
|
goto done;
|
||||||
|
/* Iterate through refinments and modify grouping copy
|
||||||
|
* See RFC 7950 7.13.2 yrt is the refine target node
|
||||||
|
*/
|
||||||
|
yr = NULL;
|
||||||
|
while ((yr = yn_each(ys, yr)) != NULL) {
|
||||||
|
yang_stmt *yrt; /* refine target node */
|
||||||
|
if (yang_keyword_get(yr) != Y_REFINE)
|
||||||
|
continue;
|
||||||
|
/* Find a node */
|
||||||
|
if (yang_desc_schema_nodeid(ygrouping2,
|
||||||
|
yang_argument_get(yr),
|
||||||
|
-1,
|
||||||
|
&yrt) < 0)
|
||||||
|
goto done;
|
||||||
|
/* Not found, try next */
|
||||||
|
if (yrt == NULL)
|
||||||
|
continue;
|
||||||
|
/* Do the actual refinement */
|
||||||
|
if (ys_do_refine(yr, yrt) < 0)
|
||||||
|
goto done;
|
||||||
|
/* RFC: The argument is a string that identifies a node in the
|
||||||
|
* grouping. I interpret that as only one node --> break */
|
||||||
|
break;
|
||||||
|
}
|
||||||
/* Then copy and insert each child element */
|
/* Then copy and insert each child element */
|
||||||
for (j=0; j<glen; j++){
|
for (j=0; j<glen; j++){
|
||||||
if ((yg = ys_dup(ygrouping->ys_stmt[j])) == NULL)
|
yg = ygrouping2->ys_stmt[j]; /* Child of refined copy */
|
||||||
goto done;
|
|
||||||
yn->ys_stmt[i+j] = yg;
|
yn->ys_stmt[i+j] = yg;
|
||||||
yg->ys_parent = yn;
|
yg->ys_parent = yn;
|
||||||
}
|
}
|
||||||
/* XXX: refine */
|
|
||||||
/* Remove 'uses' node */
|
/* Remove 'uses' node */
|
||||||
ys_free(ys);
|
ys_free(ys);
|
||||||
break; /* Note same child is re-iterated since it may be changed */
|
break; /* Note same child is re-iterated since it may be changed */
|
||||||
|
|
@ -2091,7 +2250,7 @@ yang_expand(yang_stmt *yn)
|
||||||
/* Second pass since length may have changed */
|
/* Second pass since length may have changed */
|
||||||
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 (yang_expand(ys) < 0)
|
if (yang_expand_grouping(ys) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -2609,15 +2768,20 @@ yang_parse_post(clicon_handle h,
|
||||||
|
|
||||||
/* 6: Macro expansion of all grouping/uses pairs. Expansion needs marking */
|
/* 6: Macro expansion of all grouping/uses pairs. Expansion needs marking */
|
||||||
for (i=modnr; i<yspec->ys_len; i++){
|
for (i=modnr; i<yspec->ys_len; i++){
|
||||||
if (yang_expand(yspec->ys_stmt[i]) < 0)
|
if (yang_expand_grouping(yspec->ys_stmt[i]) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
yang_apply(yspec->ys_stmt[i], -1, ys_flag_reset, (void*)YANG_FLAG_MARK);
|
yang_apply(yspec->ys_stmt[i], -1, ys_flag_reset, (void*)YANG_FLAG_MARK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 7: Top-level augmentation of all modules XXX: only new modules? */
|
/* 7: Top-level augmentation of all modules. (Augment also in uses) */
|
||||||
if (yang_augment_spec(yspec, modnr) < 0)
|
if (yang_augment_spec(yspec, modnr) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
/* 4: Go through parse tree and do 2nd step populate (eg default) */
|
||||||
|
for (i=modnr; i<yspec->ys_len; i++)
|
||||||
|
if (yang_apply(yspec->ys_stmt[i], -1, ys_populate2, (void*)h) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
/* 8: sanity check of schemanode references, need more here */
|
/* 8: sanity check of schemanode references, need more here */
|
||||||
for (i=modnr; i<yspec->ys_len; i++)
|
for (i=modnr; i<yspec->ys_len; i++)
|
||||||
if (yang_apply(yspec->ys_stmt[i], -1, ys_schemanode_check, NULL) < 0)
|
if (yang_apply(yspec->ys_stmt[i], -1, ys_schemanode_check, NULL) < 0)
|
||||||
|
|
@ -2829,19 +2993,13 @@ yang_spec_load_dir(clicon_handle h,
|
||||||
* This is a failsafe in case anything else fails
|
* This is a failsafe in case anything else fails
|
||||||
*/
|
*/
|
||||||
if (revm && rev0){
|
if (revm && rev0){
|
||||||
int size;
|
|
||||||
if (revm > rev0) /* Loaded module is older or eq -> remove ym */
|
if (revm > rev0) /* Loaded module is older or eq -> remove ym */
|
||||||
ym = ym0;
|
ym = ym0;
|
||||||
for (j=0; j<yspec->ys_len; j++)
|
for (j=0; j<yspec->ys_len; j++)
|
||||||
if (yspec->ys_stmt[j] == ym)
|
if (yspec->ys_stmt[j] == ym)
|
||||||
break;
|
break;
|
||||||
size = (yspec->ys_len - j - 1)*sizeof(struct yang_stmt *);
|
ys_prune(yspec, j);
|
||||||
memmove(&yspec->ys_stmt[j],
|
|
||||||
&yspec->ys_stmt[j+1],
|
|
||||||
size);
|
|
||||||
ys_free(ym);
|
ys_free(ym);
|
||||||
yspec->ys_len--;
|
|
||||||
yspec->ys_stmt[yspec->ys_len] = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (yang_parse_post(h, yspec, modnr) < 0)
|
if (yang_parse_post(h, yspec, modnr) < 0)
|
||||||
|
|
@ -3101,7 +3259,7 @@ yang_abs_schema_nodeid(yang_stmt *yspec,
|
||||||
* @param[out] yres First yang node matching schema nodeid
|
* @param[out] yres First yang node matching schema nodeid
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error, with clicon_err called
|
* @retval -1 Error, with clicon_err called
|
||||||
* @see yang_schema_nodeid
|
* @see yang_abs_schema_nodeid
|
||||||
* Used in yang: unique, refine, uses augment
|
* Used in yang: unique, refine, uses augment
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ cat <<EOF > $cfg
|
||||||
<CLICON_FEATURE>a:test</CLICON_FEATURE>
|
<CLICON_FEATURE>a:test</CLICON_FEATURE>
|
||||||
<CLICON_YANG_DIR>$dir</CLICON_YANG_DIR>
|
<CLICON_YANG_DIR>$dir</CLICON_YANG_DIR>
|
||||||
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||||
|
<CLICON_YANG_MAIN_FILE>$fyang</CLICON_YANG_MAIN_FILE>
|
||||||
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||||
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||||
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
||||||
|
|
@ -66,11 +67,11 @@ module ietf-interfaces {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
grouping endpoint {
|
grouping endpoint {
|
||||||
description "A reusable endpoint group.";
|
description "A reusable endpoint group. From rf7950 Sec 7.12.2";
|
||||||
leaf mip {
|
leaf ip {
|
||||||
type string;
|
type string;
|
||||||
}
|
}
|
||||||
leaf mport {
|
leaf port {
|
||||||
type uint16;
|
type uint16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -98,12 +99,14 @@ module example-augment {
|
||||||
identity you {
|
identity you {
|
||||||
base my-type;
|
base my-type;
|
||||||
}
|
}
|
||||||
grouping mypoint {
|
grouping localgroup {
|
||||||
description "A reusable endpoint group.";
|
description "Local grouping defining lid and lport";
|
||||||
leaf ip {
|
leaf lid {
|
||||||
|
description "this will be kept as-is";
|
||||||
type string;
|
type string;
|
||||||
}
|
}
|
||||||
leaf port {
|
leaf lport {
|
||||||
|
description "this will be refined";
|
||||||
type uint16;
|
type uint16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -124,12 +127,14 @@ module example-augment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uses if:endpoint {
|
uses if:endpoint {
|
||||||
|
description "Use an external grouping defining ip and port";
|
||||||
refine port {
|
refine port {
|
||||||
default 80;
|
default 80;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uses mypoint {
|
uses localgroup {
|
||||||
refine mport {
|
description "Use a local grouping defining lip and lport";
|
||||||
|
refine lport {
|
||||||
default 8080;
|
default 8080;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -137,37 +142,35 @@ module example-augment {
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
new "test params: -f $cfg -y $fyang"
|
new "test params: -f $cfg"
|
||||||
|
|
||||||
if [ $BE -ne 0 ]; then
|
if [ $BE -ne 0 ]; then
|
||||||
new "kill old backend"
|
new "kill old backend"
|
||||||
sudo clixon_backend -zf $cfg -y $fyang
|
sudo clixon_backend -zf $cfg
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
err
|
err
|
||||||
fi
|
fi
|
||||||
new "start backend -s init -f $cfg -y $fyang"
|
new "start backend -s init -f $cfg"
|
||||||
start_backend -s init -f $cfg -y $fyang
|
start_backend -s init -f $cfg
|
||||||
|
|
||||||
new "waiting"
|
new "waiting"
|
||||||
sleep $RCWAIT
|
sleep $RCWAIT
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# mandatory-leaf See RFC7950 Sec 7.17
|
# mandatory-leaf See RFC7950 Sec 7.17
|
||||||
# Error1: the xml should have xmlns for "mymod"
|
|
||||||
# XMLNS_YANG_ONLY must be undeffed
|
|
||||||
new "netconf set interface with augmented type and mandatory leaf"
|
new "netconf set interface with augmented type and mandatory leaf"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
|
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
|
||||||
<interface xmlns:mymod="urn:example:augment">
|
<interface xmlns:mymod="urn:example:augment">
|
||||||
<name>e1</name>
|
<name>e1</name>
|
||||||
<type>mymod:some-new-iftype</type>
|
<type>mymod:some-new-iftype</type>
|
||||||
<mymod:mandatory-leaf>true</mymod:mandatory-leaf>
|
<mymod:mandatory-leaf>true</mymod:mandatory-leaf>
|
||||||
</interface></interfaces></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
</interface></interfaces></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf validate ok"
|
new "netconf verify get with refined ports"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '^<rpc-reply><data><interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"><interface xmlns:mymod="urn:example:augment"><name>e1</name><type>mymod:some-new-iftype</type><mandatory-leaf>true</mandatory-leaf><port>80</port><lport>8080</lport></interface></interfaces></data></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
new "netconf set identity defined in other"
|
new "netconf set identity defined in other"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
|
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
|
||||||
<interface xmlns:mymod="urn:example:augment">
|
<interface xmlns:mymod="urn:example:augment">
|
||||||
<name>e2</name>
|
<name>e2</name>
|
||||||
<type>fddi</type>
|
<type>fddi</type>
|
||||||
|
|
@ -176,10 +179,10 @@ expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><can
|
||||||
</interface></interfaces></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
</interface></interfaces></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf validate ok"
|
new "netconf validate ok"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
new "netconf set identity defined in main"
|
new "netconf set identity defined in main"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
|
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
|
||||||
<interface xmlns:mymod="urn:example:augment">
|
<interface xmlns:mymod="urn:example:augment">
|
||||||
<name>e3</name>
|
<name>e3</name>
|
||||||
<type>fddi</type>
|
<type>fddi</type>
|
||||||
|
|
@ -188,9 +191,11 @@ expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><can
|
||||||
</interface></interfaces></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
</interface></interfaces></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf validate ok"
|
new "netconf validate ok"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
|
new "discard"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
|
||||||
|
|
||||||
if [ $BE -eq 0 ]; then
|
if [ $BE -eq 0 ]; then
|
||||||
exit # BE
|
exit # BE
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue