diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b6362bd..94b26b3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,10 @@ Planned: April 2025 * New `clixon-restconf@2025-02-01.yang` revision * Added timeout parameter +### Corrected Bugs + +* Fixed: [Templates with nc:operation "merge" causes bad diffs to be shows](https://github.com/clicon/clixon-controller/issues/187) + ## 7.3.0 30 January 2025 diff --git a/apps/backend/backend_client.c b/apps/backend/backend_client.c index 2927e285..f3a2dafb 100644 --- a/apps/backend/backend_client.c +++ b/apps/backend/backend_client.c @@ -655,7 +655,8 @@ from_client_edit_config(clixon_handle h, goto done; goto ok; } - /* Must do before duplicate check */ + /* Must do before duplicate check, + * should probably be done before minmax check above */ if (xml_sort_recurse(xc) < 0) goto done; /* Disable duplicate check in NETCONF messages. */ diff --git a/doc/LINKS.md b/doc/LINKS.md index fd2e7b0c..35abdd86 100644 --- a/doc/LINKS.md +++ b/doc/LINKS.md @@ -4,7 +4,5 @@ A collection of community links to usages of clixon. Please notify of changes or Links: - * https://github.com/MontaVista-OpenSourceTechnology/clixon + * https://github.com/MontaVista-OpenSourceTechnology/clixon-backend-helper * https://github.com/brunorijsman/yang-tutorial/tree/main/clixon - - diff --git a/lib/src/clixon_validate_minmax.c b/lib/src/clixon_validate_minmax.c index a54be2dd..82172751 100644 --- a/lib/src/clixon_validate_minmax.c +++ b/lib/src/clixon_validate_minmax.c @@ -91,8 +91,8 @@ */ struct vec_order { cxobj *vo_xml; - char **vo_strvec; - size_t vo_slen; /* length of vo_strvec (is actually global to vector) */ + char **vo_strvec; /* vector of keys, 1 element if leaf-list, NULL if non-list */ + size_t vo_slen; /* Length of vo_strvec (is actually global to vector) */ }; /*! New element last in list, check if already exists if so return -1 @@ -877,9 +877,10 @@ remove_duplicates_list(yang_stmt *y, int *nr, cxobj **xret) { - int retval = -1; - int v; - int i; + int retval = -1; + cvec *cvk; + int v; + int i; if (nr) *nr = 0; @@ -896,7 +897,7 @@ remove_duplicates_list(yang_stmt *y, (*nr)++; } else{ - cvec *cvk = NULL; + cvk = NULL; if (yang_keyword_get(y) == Y_LEAF_LIST){ if ((cvk = cvec_new(0)) == NULL){ clixon_err(OE_UNIX, errno, "cvec_new"); @@ -922,6 +923,48 @@ remove_duplicates_list(yang_stmt *y, goto done; } +/*! Remove duplicates container or leaf + * + * @param[in] vec Ordered vector of string vectors + * @param[in] vlen Length of vec + * @param[in] rm 0: return 0 on first duplicate, 1: remove all duplicates + * @param[in] cvv Vector of keys (for error) + * @param[out] xret Error XML tree. Free with xml_free after use + * @retval 0 OK + * @retval -1 Error + */ +static int +remove_duplicates_single(yang_stmt *y, + struct vec_order *vec, + size_t vlen, + int rm, + int *nr, + cxobj **xret) +{ + int retval = -1; + cxobj *x; + int v; + + if (nr) + *nr = 0; + for (v=1; v 1){ + if (remove_duplicates_single(y, vec, vlen, rm, &nr, xret) < 0) + goto done; + } + break; + default: + break; } if (x && nr) xml_vector_decrement(x, nr); @@ -1016,12 +1072,28 @@ xml_duplicate_detect1(cxobj *xt, } keyw = yang_keyword_get(y); switch (keyw){ + case Y_CONTAINER: + case Y_LEAF: + if (vlen > 0 && slen0 != 0){ /* Sanity check */ + clixon_err(OE_YANG, 0, "Container vector mismatch %lu != 0", slen0); + goto done; + } + if ((vec = realloc(vec, (vlen+1)*sizeof(*vec))) == NULL){ + clixon_err(OE_UNIX, errno, "cvec_new"); + goto done; + } + vec[vlen].vo_slen = 0; + vec[vlen].vo_strvec = NULL; + vec[vlen].vo_xml = x; + vlen++; + slen0 = 0; + break; case Y_LIST: if ((cvk = yang_cvec_get(y)) == NULL) continue; if ((clen = cvec_len(cvk)) == 0) continue; - if (vec>0 && slen0 != clen){ /* Sanity check */ + if (vlen > 0 && slen0 != clen){ /* Sanity check */ clixon_err(OE_YANG, 0, "List key vector mismatch %lu != %lu", slen0, clen); goto done; } @@ -1063,7 +1135,7 @@ xml_duplicate_detect1(cxobj *xt, goto fail; break; case Y_LEAF_LIST: - if (vec>0 && slen0 != 1){ /* Sanity check */ + if (vlen > 0 && slen0 != 1){ /* Sanity check */ clixon_err(OE_YANG, 0, "Leaf-list key vector mismatch %lu != 1", slen0); goto done; } diff --git a/test/test_netconf_duplicate.sh b/test/test_netconf_duplicate.sh index 9c3e0687..8b18cf20 100755 --- a/test/test_netconf_duplicate.sh +++ b/test/test_netconf_duplicate.sh @@ -29,9 +29,9 @@ EOF # Example (the list server part) from RFC7950 Sec 7.8.3.1 w changed types cat < $fyang module unique{ - yang-version 1.1; - namespace "urn:example:clixon"; - prefix un; + yang-version 1.1; + namespace "urn:example:clixon"; + prefix un; container c{ presence "trigger"; // force presence container to trigger error list server { @@ -63,6 +63,8 @@ module unique{ type string; } } + container d{ + } } EOF @@ -79,7 +81,7 @@ if [ $BE -ne 0 ]; then start_backend -s init -f $cfg fi -new "wait backend" +new "Wait backend 1" wait_backend new "Add list entry" @@ -326,6 +328,24 @@ expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" " new "Check mix w empty" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "aaafoofoobbbcccCCCBBBAAA" +new "netconf discard-changes" +expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "" + +# Note both unordered and duplicate +new "Container dups" +expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "replace + + aaa + + + + bbb + +" "" "" + +new "Check no container duplicates" +expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "bbb" + if [ $BE -ne 0 ]; then new "Kill backend" # Check if premature kill