* Added sorting of YANG statements
* Some openconfig specs seem to have use/when before a "config" which it depends on. This leads to XML encoding being in the "wrong order. * When parsing, clixon now sorts container/list statements so that sub-statements with WHEN are put last. * See [Statements given in "load set" are order dependent](https://github.com/clicon/clixon/issues/287) * Fixed: [Statements given in "load set" are order dependent](https://github.com/clicon/clixon/issues/287)
This commit is contained in:
parent
a64464beda
commit
acc9c083a4
11 changed files with 181 additions and 39 deletions
|
|
@ -207,6 +207,12 @@ check_body_namespace(cxobj *x0,
|
|||
*
|
||||
* Check if there is a when condition. First try it on the new request (x1), then on the
|
||||
* existing (x0).
|
||||
* This is according to RFC 7950 8.3.2 NETCONF <edit-config> Processing
|
||||
* During this processing [of edit-config] :
|
||||
* o Modification requests for nodes tagged with "when", and the "when"
|
||||
* condition evaluates to "false". In this case, the server MUST
|
||||
* reply with an "unknown-element" <error-tag> in the <rpc-error>.
|
||||
* This is somewhat strange since this is different from checking "when" at validation
|
||||
* @param[in] x0p Parent of x0
|
||||
* @param[in] x1 XML tree which modifies base
|
||||
* @param[in] y0 Yang spec corresponding to xml-node x0. NULL if x0 is NULL
|
||||
|
|
|
|||
|
|
@ -766,7 +766,6 @@ ys_dup(yang_stmt *old)
|
|||
*
|
||||
* @param[in] yorig Existing yang statement
|
||||
* @param[in] yfrom New empty (but created) yang statement
|
||||
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
* @code
|
||||
|
|
@ -1346,7 +1345,7 @@ order1(yang_stmt *yp,
|
|||
else {
|
||||
if (!yang_datanode(ys))
|
||||
continue;
|
||||
if (ys==y)
|
||||
if (ys == y)
|
||||
return 1;
|
||||
(*index)++;
|
||||
}
|
||||
|
|
@ -1373,6 +1372,7 @@ yang_order(yang_stmt *y)
|
|||
|
||||
if (y == NULL)
|
||||
return -1;
|
||||
|
||||
/* Some special handling if yp is choice (or case)
|
||||
* if so, the real parent (from an xml point of view) is the parents
|
||||
* parent.
|
||||
|
|
@ -3631,6 +3631,53 @@ yang_extension_value(yang_stmt *ys,
|
|||
return retval;
|
||||
}
|
||||
|
||||
#ifdef YANG_ORDERING_WHEN_LAST
|
||||
/* Sort substatements with when:s last */
|
||||
static int
|
||||
yang_sort_subelements_fn(const void* arg1,
|
||||
const void* arg2)
|
||||
{
|
||||
yang_stmt *ys1 = *(yang_stmt **)arg1;
|
||||
yang_stmt *ys2 = *(yang_stmt **)arg2;
|
||||
int w1; /* ys1 has when substatement */
|
||||
int w2;
|
||||
|
||||
w1 = yang_find(ys1, Y_WHEN, NULL) != NULL;
|
||||
w2 = yang_find(ys2, Y_WHEN, NULL) != NULL;
|
||||
if (w1 == w2)
|
||||
return 0;
|
||||
if (w1)
|
||||
return 1;
|
||||
if (w2)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*! 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.
|
||||
* with some exceptions, eg rpc/action input/output or list key elements
|
||||
*
|
||||
* Clixon by default encodes them in yang order. But this function can change that.
|
||||
* For example, openconfig-network-instances.yang requires subelements with "when" statements last.
|
||||
*/
|
||||
int
|
||||
yang_sort_subelements(yang_stmt *ys)
|
||||
{
|
||||
int retval = -1;
|
||||
|
||||
#ifdef YANG_ORDERING_WHEN_LAST
|
||||
if ((yang_keyword_get(ys) == Y_CONTAINER ||
|
||||
yang_keyword_get(ys) == Y_LIST)){
|
||||
qsort(ys->ys_stmt, ys->ys_len, sizeof(ys), yang_sort_subelements_fn);
|
||||
}
|
||||
#endif
|
||||
retval = 0;
|
||||
// done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef XML_EXPLICIT_INDEX
|
||||
/*! Mark element as search_index in list
|
||||
* @retval 0 OK
|
||||
|
|
|
|||
|
|
@ -249,12 +249,14 @@ yang_parse_exit(clixon_yang_yacc *yy)
|
|||
int
|
||||
ystack_pop(clixon_yang_yacc *yy)
|
||||
{
|
||||
struct ys_stack *ystack;
|
||||
struct ys_stack *ystack;
|
||||
|
||||
if ((ystack = yy->yy_stack) == NULL){
|
||||
clicon_err(OE_YANG, 0, "ystack is NULL");
|
||||
return -1;
|
||||
}
|
||||
if (yang_sort_subelements(ystack->ys_node) < 0)
|
||||
return -1;
|
||||
yy->yy_stack = ystack->ys_next;
|
||||
free(ystack);
|
||||
return 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue