diff --git a/CHANGELOG.md b/CHANGELOG.md index ad0067a2..420059b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,11 @@ Users may have to change how they access the system * Removed default of `CLICON_RESTCONF_INSTALLDIR` * The default behaviour is changed to use the config $(sbindir) to locate `clixon_restconf` when starting restconf internally +### Minor features + +* Added linenumbers to all YANG symbols for better debug and errors + * Improved error messages for YANG identityref:s and leafref:s by adding original line numbers + ### Corrected Bugs * Fixed: The auto-cli identityref did not expand identities in grouping/usecases properly. diff --git a/lib/clixon/clixon_yang.h b/lib/clixon/clixon_yang.h index 437318a7..879e6b8c 100644 --- a/lib/clixon/clixon_yang.h +++ b/lib/clixon/clixon_yang.h @@ -212,6 +212,10 @@ char *yang_when_xpath_get(yang_stmt *ys); int yang_when_xpath_set(yang_stmt *ys, char *xpath); cvec *yang_when_nsc_get(yang_stmt *ys); int yang_when_nsc_set(yang_stmt *ys, cvec *nsc); +const char *yang_filename_get(yang_stmt *ys); +int yang_filename_set(yang_stmt *ys, const char *filename); +int yang_linenum_get(yang_stmt *ys); +int yang_linenum_set(yang_stmt *ys, int linenum); /* Other functions */ yang_stmt *yspec_new(void); diff --git a/lib/src/clixon_validate.c b/lib/src/clixon_validate.c index 48070400..8923dfe6 100644 --- a/lib/src/clixon_validate.c +++ b/lib/src/clixon_validate.c @@ -119,7 +119,14 @@ validate_leafref(cxobj *xt, if ((leafrefbody = xml_body(xt)) == NULL) goto ok; if ((ypath = yang_find(ytype, Y_PATH, NULL)) == NULL){ - if (xret && netconf_missing_element_xml(xret, "application", yang_argument_get(ytype), "Leafref requires path statement") < 0) + if ((cberr = cbuf_new()) == NULL){ + clicon_err(OE_UNIX, errno, "cbuf_new"); + goto done; + } + cprintf(cberr, "Leafref requires path statement"); + if (xret && netconf_missing_element_xml(xret, "application", + yang_argument_get(ytype), + cbuf_get(cberr)) < 0) goto done; goto fail; } @@ -142,7 +149,11 @@ validate_leafref(cxobj *xt, goto done; } ymod = ys_module(ys); - cprintf(cberr, "Leafref validation failed: No leaf %s matching path %s in module %s", leafrefbody, path, yang_argument_get(ymod)); + cprintf(cberr, "Leafref validation failed: No leaf %s matching path %s in %s.yang:%d", + leafrefbody, + path, + yang_argument_get(ymod), + yang_linenum_get(ys)); if (xret && netconf_bad_element_xml(xret, "application", leafrefbody, cbuf_get(cberr)) < 0) goto done; goto fail; @@ -241,8 +252,11 @@ validate_identityref(cxobj *xt, #endif } if (ymod == NULL){ - cprintf(cberr, "Identityref validation failed, %s not derived from %s", - node, yang_argument_get(ybaseid)); + cprintf(cberr, "Identityref validation failed, %s not derived from %s in %s.yang:%d", + node, + yang_argument_get(ybaseid), + yang_argument_get(ys_module(ybaseid)), + yang_linenum_get(ybaseid)); if (xret && netconf_operation_failed_xml(xret, "application", cbuf_get(cberr)) < 0) goto done; goto fail; @@ -254,8 +268,11 @@ validate_identityref(cxobj *xt, */ idrefvec = yang_cvec_get(ybaseid); if (cvec_find(idrefvec, idref) == NULL){ - cprintf(cberr, "Identityref validation failed, %s not derived from %s", - node, yang_argument_get(ybaseid)); + cprintf(cberr, "Identityref validation failed, %s not derived from %s in %s.yang:%d", + node, + yang_argument_get(ybaseid), + yang_argument_get(ys_module(ybaseid)), + yang_linenum_get(ybaseid)); if (xret && netconf_operation_failed_xml(xret, "application", cbuf_get(cberr)) < 0) goto done; goto fail; diff --git a/lib/src/clixon_yang.c b/lib/src/clixon_yang.c index c90fe4ae..7234fd09 100644 --- a/lib/src/clixon_yang.c +++ b/lib/src/clixon_yang.c @@ -416,6 +416,61 @@ yang_when_nsc_set(yang_stmt *ys, return retval; } +/*! Get yang filename for error/debug purpose + * + * @param[in] ys Yang statement + * @retval filename + * @note there maye not always be a "filename" in case the yang is read from memory + */ +const char * +yang_filename_get(yang_stmt *ys) +{ + return ys->ys_filename; +} + +/*! Set yang filename for error/debug purpose + * + * @param[in] ys Yang statement + * @param[in] filename + * @retval 0 OK + * @retval -1 Error + * @note there maye not always be a "filename" in case the yang is read from memory + */ +int +yang_filename_set(yang_stmt *ys, + const char *filename) +{ + if ((ys->ys_filename = strdup(filename)) == NULL){ + clicon_err(OE_UNIX, errno, "strdup"); + return -1; + } + return 0; +} + +/*! Get line number of yang filename for error/debug purpose + * + * @param[in] ys Yang statement + * @retval linenum + */ +int +yang_linenum_get(yang_stmt *ys) +{ + return ys->ys_linenum; +} + +/*! Set line number of yang filename for error/debug purpose + * + * @param[in] ys Yang statement + * @param[in] linenum + */ +int +yang_linenum_set(yang_stmt *ys, + int linenum) +{ + ys->ys_linenum = linenum; + return 0; +} + /* End access functions */ /*! Create new yang specification @@ -498,6 +553,8 @@ ys_free1(yang_stmt *ys, cvec_free(ys->ys_when_nsc); if (ys->ys_stmt) free(ys->ys_stmt); + if (ys->ys_filename) + free(ys->ys_filename); if (self) free(ys); return 0; diff --git a/lib/src/clixon_yang_internal.h b/lib/src/clixon_yang_internal.h index d14e98ac..a1af0679 100644 --- a/lib/src/clixon_yang_internal.h +++ b/lib/src/clixon_yang_internal.h @@ -93,7 +93,8 @@ struct yang_stmt{ char *ys_when_xpath; /* Special conditional for a "when"-associated augment/uses xpath */ cvec *ys_when_nsc; /* Special conditional for a "when"-associated augment/uses namespace ctx */ int _ys_vector_i; /* internal use: yn_each */ - + char *ys_filename; /* For debug/errors: filename (only (sub)modules) */ + int ys_linenum; /* For debug/errors: line number (in ys_filename) */ }; diff --git a/lib/src/clixon_yang_parse.y b/lib/src/clixon_yang_parse.y index 6c44b2b9..3c144dcf 100644 --- a/lib/src/clixon_yang_parse.y +++ b/lib/src/clixon_yang_parse.y @@ -318,6 +318,7 @@ ysp_add(clixon_yang_yacc *yy, goto err; if (ys_parse_sub(ys, extra) < 0) /* Check statement-specific syntax */ goto err2; /* dont free since part of tree */ + yang_linenum_set(ys, yy->yy_linenum); /* For error/debugging */ // done: return ys; err: @@ -662,7 +663,7 @@ yin_element_stmt1 : K_YIN_ELEMENT bool_str stmtend {free($2);} /* Identity */ identity_stmt : K_IDENTITY identifier_str ';' - { if (ysp_add(_yy, Y_IDENTITY, $2, NULL) == NULL) _YYERROR("identity_stmt"); + { if (ysp_add(_yy, Y_IDENTITY, $2, NULL) == NULL) _YYERROR("identity_stmt"); _PARSE_DEBUG("identity-stmt -> IDENTITY string ;"); } | K_IDENTITY identifier_str diff --git a/lib/src/clixon_yang_parse_lib.c b/lib/src/clixon_yang_parse_lib.c index c472f292..28c52d68 100644 --- a/lib/src/clixon_yang_parse_lib.c +++ b/lib/src/clixon_yang_parse_lib.c @@ -773,6 +773,9 @@ yang_parse_str(char *str, goto done; } ymod = yy.yy_module; + /* Add filename for debugging and errors, see also ys_linenum on (each symbol?) */ + if (yang_filename_set(ymod, name) < 0) + goto done; done: ystack_pop(&yy); if (yy.yy_stack) diff --git a/test/test_identity.sh b/test/test_identity.sh index bd9d3b9f..3e900669 100755 --- a/test/test_identity.sh +++ b/test/test_identity.sh @@ -64,7 +64,7 @@ module example-crypto-base { EOF cat < $dir/example-des.yang - module example-des { +module example-des { yang-version 1.1; namespace "urn:example:des"; prefix "des"; @@ -81,7 +81,7 @@ cat < $dir/example-des.yang base "crypto:symmetric-key"; description "Triple DES crypto algorithm."; } - } +} EOF cat < $fyang @@ -252,7 +252,7 @@ new "Set crypto to foo:bar" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLOfoo:bar]]>]]>" "^]]>]]>$" new "netconf validate (expect fail)" -expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^applicationoperation-failederrorIdentityref validation failed, foo:bar not derived from crypto-alg]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^applicationoperation-failederrorIdentityref validation failed, foo:bar not derived from crypto-alg in example-crypto-base.yang:[0-9]*]]>]]>$" new "cli set crypto to mc:aes" expectpart "$($clixon_cli -1 -f $cfg -l o set crypto mc:aes)" 0 "^$" @@ -282,7 +282,7 @@ new "Netconf set undefined acl-type" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLOxundefined]]>]]>" "^]]>]]>$" new "netconf validate fail" -expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^applicationoperation-failederrorIdentityref validation failed, undefined not derived from acl-base]]>]]>" +expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^applicationoperation-failederrorIdentityref validation failed, undefined not derived from acl-base in example-my-crypto.yang:[0-9]*]]>]]>" new "netconf discard-changes" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" diff --git a/test/test_leafref.sh b/test/test_leafref.sh index b425f61e..a86e411d 100755 --- a/test/test_leafref.sh +++ b/test/test_leafref.sh @@ -140,7 +140,7 @@ new "leafref add non-existing ref" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLOeth3
10.0.4.6
]]>]]>" "^]]>]]>$" new "leafref validate" -expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^applicationbad-elementeth3errorLeafref validation failed: No leaf eth3 matching path /if:interfaces/if:interface/if:name in module example]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^applicationbad-elementeth3errorLeafref validation failed: No leaf eth3 matching path /if:interfaces/if:interface/if:name in example.yang:[0-9]*]]>]]>$" #new "leafref wrong ref" #expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLOeth3
10.0.4.6
]]>]]>" "^]]>]]>$" @@ -170,7 +170,7 @@ new "leafref delete leaf" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLOeth0]]>]]>" "^" new "leafref validate (should fail)" -expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^applicationbad-elementeth0errorLeafref validation failed: No leaf eth0 matching path /if:interfaces/if:interface/if:name in module example]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^applicationbad-elementeth0errorLeafref validation failed: No leaf eth0 matching path /if:interfaces/if:interface/if:name in example.yang:[0-9]*]]>]]>$" new "leafref discard-changes" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" diff --git a/test/test_leafref_augment.sh b/test/test_leafref_augment.sh index c6472be9..4c5032a2 100755 --- a/test/test_leafref_augment.sh +++ b/test/test_leafref_augment.sh @@ -209,7 +209,7 @@ new "leafref augment+leafref config wrong ref" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO$XML]]>]]>" "^]]>]]>$" new "leafref augment+leafref validate wrong ref" -expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^applicationbad-elementxxxerrorLeafref validation failed: No leaf xxx matching path /ex:sender/ex:name in module augment]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^applicationbad-elementxxxerrorLeafref validation failed: No leaf xxx matching path /ex:sender/ex:name in augment.yang:[0-9]*]]>]]>$" new "netconf discard-changes" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" diff --git a/test/test_leafref_state.sh b/test/test_leafref_state.sh index feb4032e..31ce8cd5 100755 --- a/test/test_leafref_state.sh +++ b/test/test_leafref_state.sh @@ -168,10 +168,10 @@ expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^applicationoperation-failedxerrorLeafref validation failed: No leaf x matching path /ex:sender-config/ex:name in module leafref. Internal error, state callback returned invalid XML]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^applicationoperation-failedxerrorLeafref validation failed: No leaf x matching path /ex:sender-config/ex:name in leafref.yang:[0-9]*. Internal error, state callback returned invalid XML]]>]]>$" new "netconf get / state-only should fail" -expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^applicationoperation-failedxerrorLeafref validation failed: No leaf x matching path /ex:sender-config/ex:name in module leafref. Internal error, state callback returned invalid XML]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^applicationoperation-failedxerrorLeafref validation failed: No leaf x matching path /ex:sender-config/ex:name in leafref.yang:[0-9]*. Internal error, state callback returned invalid XML]]>]]>$" new "netconf get / config-only ok" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^y]]>]]>$"