From 0d41d49fa9a21da8bc14aba77b52ddb9878b57f4 Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Fri, 16 Dec 2022 16:42:05 +0100 Subject: [PATCH] Moved with-defaults processing from get(-config) to xmldb_get when reading db With-defaults: fixed cornercase in xpath used in list pagination C-API: Added `with-defaults` parameter (default 0) to `xmldb_get0()` --- CHANGELOG.md | 1 + apps/backend/backend_commit.c | 12 +- apps/backend/backend_get.c | 229 +++++++++------------------ apps/backend/backend_plugin.c | 9 +- apps/backend/backend_startup.c | 2 +- apps/backend/clixon_backend_plugin.h | 2 +- example/main/example_backend.c | 2 +- lib/clixon/clixon_datastore.h | 4 +- lib/clixon/clixon_netconf_lib.h | 13 ++ lib/clixon/clixon_xml_map.h | 3 + lib/src/clixon_datastore.c | 1 + lib/src/clixon_datastore_read.c | 166 +++++++++++++++++-- lib/src/clixon_nacm.c | 2 +- lib/src/clixon_netconf_lib.c | 29 ++++ lib/src/clixon_xml.c | 2 +- lib/src/clixon_xml_map.c | 128 ++++++++++++++- lib/src/clixon_xml_sort.c | 2 +- lib/src/clixon_yang.c | 8 + test/test_yang_with_defaults.sh | 1 - 19 files changed, 420 insertions(+), 196 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb427d1f..b0bac0ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,7 @@ Developers may need to change their code * Added netconf ssh subsystem * Renamed from `clixon` built in `docker/base` * C-API + * Added `with-defaults` parameter (default 0) to `xmldb_get0()` * Added `sock_flags` parameter to `clixon_proc_socket()` ### Minor features diff --git a/apps/backend/backend_commit.c b/apps/backend/backend_commit.c index 51a4dbdc..c1a41aea 100644 --- a/apps/backend/backend_commit.c +++ b/apps/backend/backend_commit.c @@ -180,7 +180,7 @@ startup_common(clicon_handle h, * It is done below, later in this function */ if (clicon_option_bool(h, "CLICON_XMLDB_UPGRADE_CHECKOLD")){ - if ((ret = xmldb_get0(h, db, YB_MODULE, NULL, "/", 0, &xt, msdiff, &xerr)) < 0) + if ((ret = xmldb_get0(h, db, YB_MODULE, NULL, "/", 0, 0, &xt, msdiff, &xerr)) < 0) goto done; if (ret == 0){ /* ret should not be 0 */ /* Print upgraded db: -q backend switch for debugging/ showing upgraded config only */ @@ -197,7 +197,7 @@ startup_common(clicon_handle h, } } else { - if (xmldb_get0(h, db, YB_NONE, NULL, "/", 0, &xt, msdiff, &xerr) < 0) + if (xmldb_get0(h, db, YB_NONE, NULL, "/", 0, 0, &xt, msdiff, &xerr) < 0) goto done; } if (msdiff && msdiff->md_status == 0){ // Possibly check for CLICON_XMLDB_MODSTATE @@ -488,7 +488,7 @@ validate_common(clicon_handle h, goto done; } /* This is the state we are going to */ - if ((ret = xmldb_get0(h, db, YB_MODULE, NULL, "/", 0, &td->td_target, NULL, xret)) < 0) + if ((ret = xmldb_get0(h, db, YB_MODULE, NULL, "/", 0, 0, &td->td_target, NULL, xret)) < 0) goto done; if (ret == 0) goto fail; @@ -497,7 +497,7 @@ validate_common(clicon_handle h, (void*)(XML_FLAG_MARK|XML_FLAG_CHANGE)); /* 2. Parse xml trees * This is the state we are going from */ - if ((ret = xmldb_get0(h, "running", YB_MODULE, NULL, "/", 0, &td->td_src, NULL, xret)) < 0) + if ((ret = xmldb_get0(h, "running", YB_MODULE, NULL, "/", 0, 0, &td->td_src, NULL, xret)) < 0) goto done; if (ret == 0) goto fail; @@ -960,7 +960,7 @@ from_client_restart_one(clicon_handle h, if ((td = transaction_new()) == NULL) goto done; /* This is the state we are going to */ - if (xmldb_get0(h, "running", YB_MODULE, NULL, "/", 0, &td->td_target, NULL, NULL) < 0) + if (xmldb_get0(h, "running", YB_MODULE, NULL, "/", 0, 0, &td->td_target, NULL, NULL) < 0) goto done; if ((ret = xml_yang_validate_all_top(h, td->td_target, &xerr)) < 0) goto done; @@ -970,7 +970,7 @@ from_client_restart_one(clicon_handle h, goto fail; } /* This is the state we are going from */ - if (xmldb_get0(h, db, YB_MODULE, NULL, "/", 0, &td->td_src, NULL, NULL) < 0) + if (xmldb_get0(h, db, YB_MODULE, NULL, "/", 0, 0, &td->td_src, NULL, NULL) < 0) goto done; /* 3. Compute differences */ diff --git a/apps/backend/backend_get.c b/apps/backend/backend_get.c index 7d92c455..8af3c507 100644 --- a/apps/backend/backend_get.c +++ b/apps/backend/backend_get.c @@ -180,16 +180,18 @@ client_get_streams(clicon_handle h, * @param[in] h Clicon handle * @param[in] xpath XPath selection, may be used to filter early * @param[in] nsc XML Namespace context for xpath + * @param[in] wdef With-defaults parameter, see RFC 6243 * @param[in,out] xret Existing XML tree, merge x into this * @retval -1 Error (fatal) * @retval 0 Statedata callback failed (clicon_err called) * @retval 1 OK */ static int -get_client_statedata(clicon_handle h, - char *xpath, - cvec *nsc, - cxobj **xret) +get_client_statedata(clicon_handle h, + char *xpath, + cvec *nsc, + withdefaults_type wdef, + cxobj **xret) { int retval = -1; yang_stmt *yspec; @@ -258,16 +260,63 @@ get_client_statedata(clicon_handle h, goto fail; } /* Use plugin state callbacks */ - if ((ret = clixon_plugin_statedata_all(h, yspec, nsc, xpath, xret)) < 0) + if ((ret = clixon_plugin_statedata_all(h, yspec, nsc, xpath, wdef, xret)) < 0) goto done; if (ret == 0) goto fail; - /* Add default state to config if present */ - if (xml_default_recurse(*xret, 1) < 0) - goto done; - /* Add default global state */ - if (xml_global_defaults(h, *xret, nsc, xpath, yspec, 1) < 0) - goto done; + switch (wdef){ + case WITHDEFAULTS_REPORT_ALL: + case WITHDEFAULTS_EXPLICIT: + /* Add global defaults. */ + if (xml_global_defaults(h, *xret, nsc, xpath, yspec, 1) < 0) + goto done; + /* Apply default values */ + if (xml_default_recurse(*xret, 1) < 0) + goto done; + break; + case WITHDEFAULTS_TRIM: + /* Mark and remove nodes having schema default values */ + if (xml_apply((*xret), CX_ELMNT, (xml_applyfn_t*) xml_flag_state_default_value, (void*) XML_FLAG_MARK) < 0) + goto done; + if (xml_tree_prune_flags((*xret), XML_FLAG_MARK, XML_FLAG_MARK) + < 0) + goto done; + if (xml_defaults_nopresence((*xret), 1) < 0) + goto done; + break; + case WITHDEFAULTS_REPORT_ALL_TAGGED:{ + cxobj *xc; + char *ns; + /* Add global defaults. */ + if (xml_global_defaults(h, *xret, nsc, xpath, yspec, 1) < 0) + goto done; + /* Apply default values */ + if (xml_default_recurse(*xret, 1) < 0) + goto done; + xc = NULL; + while ((xc = xml_child_each((*xret), xc, CX_ELMNT)) != NULL){ + /* Check if exists */ + ns = NULL; + if (xml2ns(xc, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, &ns) < 0) + goto done; + if (ns == NULL){ + if (xmlns_set(xc, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, IETF_NETCONF_WITH_DEFAULTS_ATTR_NAMESPACE) < 0) + goto done; + } + else if (strcmp(ns, IETF_NETCONF_WITH_DEFAULTS_ATTR_NAMESPACE) != 0){ + /* XXX: Assume if namespace is set that it is withdefaults otherwise just ignore? */ + continue; + } + } + /* Mark nodes having default schema values */ + if (xml_apply(*xret, CX_ELMNT, (xml_applyfn_t*) xml_flag_state_default_value, (void*) XML_FLAG_MARK) < 0) + goto done; + /* Add tag attributes to default nodes */ + if (xml_apply(*xret, CX_ELMNT, (xml_applyfn_t*) xml_add_default_tag, (void*) (XML_FLAG_DEFAULT | XML_FLAG_MARK)) < 0) + goto done; + break; + } + } /* switch wdef */ retval = 1; /* OK */ done: clicon_debug(1, "%s %d", __FUNCTION__, retval); @@ -416,141 +465,6 @@ element2value(clicon_handle h, return 1; } -/*! Set flag on node having schema default value. - * @param[in] x XML node - * @param[in] flag Flag to be used - * @retval 0 OK - */ -static int -xml_flag_default_value(cxobj *x, - uint16_t flag) -{ - yang_stmt *y; - cg_var *cv; - char *yv; - char *xv; - - xml_flag_reset(x, flag); /* Assume not default value */ - if ((xv = xml_body(x)) == NULL) - goto done; - if ((y = xml_spec(x)) == NULL) - goto done; - if ((cv = yang_cv_get(y)) == NULL) - goto done; - if ((cv = yang_cv_get(y)) == NULL) - goto done; - if (cv_name_get(cv) == NULL) - goto done; - if ((yv = cv2str_dup(cv)) == NULL) - goto done; - if (strcmp(xv, yv) == 0) - xml_flag_set(x, flag); /* Actual value same as default value */ - free(yv); - - done: - return 0; -} - -/*! Add default attribute to node with default value. - * @param[in] x XML node - * @param[in] flags Flags indicatiing default nodes - * @retval 0 OK - * @retval -1 Error - */ -static int -xml_add_default_tag(cxobj *x, - uint16_t flags) -{ - int retval = -1; - cxobj *xattr; - - if (xml_flag(x, flags)) { - /* set default attribute */ - if ((xattr = xml_new("default", x, CX_ATTR)) == NULL) - goto done; - if (xml_value_set(xattr, "true") < 0) - goto done; - if (xml_prefix_set(xattr, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX) < 0) - goto done; - } - retval = 0; - done: - return retval; -} - -/*! Update XML return tree according to RFC6243: with-defaults - * @param[in] xe Request: - * @param[in] xret XML return tree to be updated - * @retval 0 OK - * @retval -1 Error - */ -static int -with_defaults(cxobj *xe, - cxobj *xret) -{ - int retval = -1; - cxobj *xfind; - char *mode; - cxobj *x; - - if ((xfind = xml_find(xe, "with-defaults")) != NULL) { - if ((mode = xml_find_value(xfind, "body")) == NULL) - goto done; - - if (strcmp(mode, "explicit") == 0) { - /* Clear marked nodes */ - if (xml_apply(xret, CX_ELMNT, (xml_applyfn_t*) xml_flag_reset,(void*) XML_FLAG_MARK) < 0) - goto done; - /* Mark state nodes */ - if (xml_non_config_data(xret, NULL) < 0) - goto done; - /* Remove default configuration nodes */ - if (xml_tree_prune_flags(xret, XML_FLAG_DEFAULT, XML_FLAG_MARK | XML_FLAG_DEFAULT) < 0) - goto done; - /* Remove empty containers */ - if (xml_defaults_nopresence(xret, 1) < 0) - goto done; - goto ok; - } - else if (strcmp(mode, "trim") == 0) { - /* Remove default nodes from XML */ - if (xml_tree_prune_flags(xret, XML_FLAG_DEFAULT, XML_FLAG_DEFAULT) < 0) - goto done; - /* Mark and remove nodes having schema default values */ - if (xml_apply(xret, CX_ELMNT, (xml_applyfn_t*) xml_flag_default_value, (void*) XML_FLAG_MARK) < 0) - goto done; - if (xml_tree_prune_flags(xret, XML_FLAG_MARK, XML_FLAG_MARK) - < 0) - goto done; - /* Remove empty containers */ - if (xml_defaults_nopresence(xret, 1) < 0) - goto done; - goto ok; - } - else if (strcmp(mode, "report-all-tagged") == 0) { - x = NULL; - while ((x = xml_child_each(xret, x, CX_ELMNT)) != NULL) - if (xmlns_set(x, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, IETF_NETCONF_WITH_DEFAULTS_ATTR_NAMESPACE) < 0) - goto done; - /* Mark nodes having default schema values */ - if (xml_apply(xret, CX_ELMNT, (xml_applyfn_t*) xml_flag_default_value, (void*) XML_FLAG_MARK) < 0) - goto done; - /* Add tag attributes to default nodes */ - if (xml_apply(xret, CX_ELMNT, (xml_applyfn_t*) xml_add_default_tag, (void*) (XML_FLAG_DEFAULT | XML_FLAG_MARK)) < 0) - goto done; - goto ok; - } - else if (strcmp(mode, "report-all") == 0) { - /* Accept mode, do nothing */ - goto ok; - } - } - ok: - retval = 0; - done: - return retval; -} - /*! Extract offset and limit from get/list-pagination * * @param[in] h Clicon handle @@ -592,6 +506,8 @@ list_pagination_hdr(clicon_handle h, * @param[in] db Database name * @param[in] xpath XPath point to object to get * @param[in] nsc Namespace context of xpath + * @param[in] username + * @param[in] wdef With-defaults parameter, see RFC 6243 * @param[out] cbret Return xml tree, eg ..., cache + * @param[in] wdef With-defaults parameter, see RFC 6243 * @param[out] xret Single return XML tree. Free with xml_free() * @param[out] msdiff If set, return modules-state differences (upgrade code) * @param[out] xerr XML error if retval is 0 @@ -1077,7 +1214,7 @@ xmldb_get(clicon_handle h, * @code * cxobj *xt; * cxobj *xerr = NULL; - * if (xmldb_get0(h, "running", YB_MODULE, nsc, "/interface[name="eth"]", 0, &xt, NULL, &xerr) < 0) + * if (xmldb_get0(h, "running", YB_MODULE, nsc, "/interface[name="eth"]", 0, 0, &xt, NULL, &xerr) < 0) * err; * if (ret == 0){ # Not if YB_NONE * # Error handling @@ -1098,18 +1235,19 @@ xmldb_get(clicon_handle h, * And a db content: * 1 * With the following call: - * xmldb_get0(h, "running", NULL, NULL, "/c[x=0]", 1, &xt, NULL, NULL) + * xmldb_get0(h, "running", NULL, NULL, "/c[x=0]", 1, 0, &xt, NULL, NULL) * which result in a miss (there is no c with x=0), but when the returned xt is printed * (the existing tree is discarded), the default (empty) xml tree is: * 0 */ int -xmldb_get0(clicon_handle h, +xmldb_get0(clicon_handle h, const char *db, yang_bind yb, cvec *nsc, const char *xpath, int copy, + withdefaults_type wdef, cxobj **xret, modstate_diff_t *msdiff, cxobj **xerr) @@ -1122,7 +1260,7 @@ xmldb_get0(clicon_handle h, * Add default values in copy * Copy deleted by xmldb_free */ - retval = xmldb_get_nocache(h, db, yb, nsc, xpath, xret, msdiff, xerr); + retval = xmldb_get_nocache(h, db, yb, nsc, xpath, wdef, xret, msdiff, xerr); break; case DATASTORE_CACHE_ZEROCOPY: /* Get cache (file if empty) mark xpath match in original tree @@ -1130,7 +1268,7 @@ xmldb_get0(clicon_handle h, * Default values and markings removed in xmldb_clear */ if (!copy){ - retval = xmldb_get_zerocopy(h, db, yb, nsc, xpath, xret, msdiff, xerr); + retval = xmldb_get_zerocopy(h, db, yb, nsc, xpath, wdef, xret, msdiff, xerr); break; } /* fall through */ @@ -1139,7 +1277,7 @@ xmldb_get0(clicon_handle h, * Add default values in copy, return copy * Copy deleted by xmldb_free */ - retval = xmldb_get_cache(h, db, yb, nsc, xpath, xret, msdiff, xerr); + retval = xmldb_get_cache(h, db, yb, nsc, xpath, wdef, xret, msdiff, xerr); break; } return retval; diff --git a/lib/src/clixon_nacm.c b/lib/src/clixon_nacm.c index b57df23d..9bb44ee2 100644 --- a/lib/src/clixon_nacm.c +++ b/lib/src/clixon_nacm.c @@ -1216,7 +1216,7 @@ nacm_access_pre(clicon_handle h, goto done; } else if (strcmp(mode, "internal")==0){ - if (xmldb_get0(h, "running", YB_MODULE, nsc, "nacm", 1, &xnacm0, NULL, NULL) < 0) + if (xmldb_get0(h, "running", YB_MODULE, nsc, "nacm", 1, 0, &xnacm0, NULL, NULL) < 0) goto done; } else{ diff --git a/lib/src/clixon_netconf_lib.c b/lib/src/clixon_netconf_lib.c index 5fa4b94f..51fd6b73 100644 --- a/lib/src/clixon_netconf_lib.c +++ b/lib/src/clixon_netconf_lib.c @@ -77,6 +77,35 @@ #include "clixon_netconf_lib.h" +/* Mapping between RFC6243 withdefaults strings <--> ints + */ +static const map_str2int wdmap[] = { + {"report-all", WITHDEFAULTS_REPORT_ALL}, + {"trim", WITHDEFAULTS_TRIM}, + {"explicit", WITHDEFAULTS_EXPLICIT}, + {"report-all-tagged", WITHDEFAULTS_REPORT_ALL_TAGGED} +}; + +/*! Map from with-defaults ints to strings + * @param[in] int Integer representation of withdefaults values + * @retval str String representation of withdefaults values + */ +char * +withdefaults_int2str(int keyword) +{ + return (char*)clicon_int2str(wdmap, keyword); +} + +/*! Map from with-defaults strings to ints + * @param[in] str String representation of withdefaults values + * @retval int Integer representation of withdefaults values + */ +int +withdefaults_str2int(char *str) +{ + return clicon_str2int(wdmap, str); +} + /*! Create Netconf in-use error XML tree according to RFC 6241 Appendix A * * The request requires a resource that already is in use. diff --git a/lib/src/clixon_xml.c b/lib/src/clixon_xml.c index 4bc37ea2..dd74bba2 100644 --- a/lib/src/clixon_xml.c +++ b/lib/src/clixon_xml.c @@ -1725,7 +1725,7 @@ xml_find_type_value(cxobj *xt, * @code * cxobj *x = xml_find_type(x, "prefix", "name", CX_ATTR); * @endcode - * @see xml_find which finds any child given name + * @see xml_find which finds any child given name (and no prefix) * @see xml_find_value where a body can be found as well */ cxobj * diff --git a/lib/src/clixon_xml_map.c b/lib/src/clixon_xml_map.c index e9e903f8..b7bf260a 100644 --- a/lib/src/clixon_xml_map.c +++ b/lib/src/clixon_xml_map.c @@ -781,12 +781,14 @@ xml_default_create(yang_stmt *y, /*! Try to see if intermediate nodes are necessary for default values, create if so * * @param[in] yt Yang container (no-presence) + * @param[in] state Set if global state, otherwise config * @param[out] createp Need to create XML container * @retval 0 OK * @retval -1 Error */ static int xml_nopresence_try(yang_stmt *yt, + int state, int *createp) { int retval = -1; @@ -801,9 +803,14 @@ xml_nopresence_try(yang_stmt *yt, while ((y = yn_each(yt, y)) != NULL) { switch (yang_keyword_get(y)){ case Y_LEAF: - if (!cv_flag(yang_cv_get(y), V_UNSET)){ /* Default value exists */ - /* Need to create container */ - *createp = 1; + /* Default value exists */ + if (!cv_flag(yang_cv_get(y), V_UNSET)){ + /* Want to add state defaults, but this is config */ + if (state && yang_config_ancestor(y)) + ; + else + /* Need to create container */ + *createp = 1; goto ok; } break; @@ -812,7 +819,7 @@ xml_nopresence_try(yang_stmt *yt, /* If this is non-presence, (and it does not exist in xt) call recursively * and create nodes if any default value exist first. Then continue and populate? */ - if (xml_nopresence_try(y, createp) < 0) + if (xml_nopresence_try(y, state, createp) < 0) goto done; if (*createp) goto ok; @@ -837,6 +844,8 @@ xml_nopresence_try(yang_stmt *yt, * @param[in] state Set if global state, otherwise config * @retval 0 OK * @retval -1 Error + * XXX If state, should not add config defaults + * if (state && yang_config(yc)) */ static int xml_default1(yang_stmt *yt, @@ -867,10 +876,14 @@ xml_default1(yang_stmt *yt, case Y_OUTPUT: yc = NULL; while ((yc = yn_each(yt, yc)) != NULL) { + /* If config parameter and local is config false */ if (!state && !yang_config(yc)) continue; switch (yang_keyword_get(yc)){ case Y_LEAF: + /* Want to add state defaults, but this is config */ + if (state && yang_config_ancestor(yc)) + break; if ((cv = yang_cv_get(yc)) == NULL){ clicon_err(OE_YANG,0, "Internal error: yang leaf %s not populated with cv as it should", yang_argument_get(yc)); @@ -903,7 +916,7 @@ xml_default1(yang_stmt *yt, */ if (xml_find_type(xt, NULL, yang_argument_get(yc), CX_ELMNT) == NULL){ /* No such container exist, recursively try if needed */ - if (xml_nopresence_try(yc, &create) < 0) + if (xml_nopresence_try(yc, state, &create) < 0) goto done; if (create){ /* Retval shows there is a default value need to create the @@ -2342,3 +2355,108 @@ purge_tagged_nodes(cxobj *xn, done: return retval; } + +/*! Add default attribute to node with default value. + * + * Used in with-default code for report-all-tagged + * @param[in] x XML node + * @param[in] flags Flags indicatiing default nodes + * @retval 0 OK + * @retval -1 Error + */ +int +xml_add_default_tag(cxobj *x, + uint16_t flags) +{ + int retval = -1; + cxobj *xattr; + + if (xml_flag(x, flags)) { + /* set default attribute */ + if ((xattr = xml_new("default", x, CX_ATTR)) == NULL) + goto done; + if (xml_value_set(xattr, "true") < 0) + goto done; + if (xml_prefix_set(xattr, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX) < 0) + goto done; + } + retval = 0; + done: + return retval; +} + +/*! Set flag on node having schema default value. (non-config) + * + * Used in with-default code for trim/report-all-tagged + * @param[in] x XML node + * @param[in] flag Flag to be used + * @retval 0 OK + * @see xml_flag_default_value for config default value + */ +int +xml_flag_state_default_value(cxobj *x, + uint16_t flag) +{ + yang_stmt *y; + cg_var *cv; + char *yv; + char *xv; + + xml_flag_reset(x, flag); /* Assume not default value */ + if ((xv = xml_body(x)) == NULL) + goto done; + if ((y = xml_spec(x)) == NULL) + goto done; + if (yang_config_ancestor(y) == 1) + goto done; + if ((cv = yang_cv_get(y)) == NULL) + goto done; + if ((cv = yang_cv_get(y)) == NULL) + goto done; + if (cv_name_get(cv) == NULL) + goto done; + if ((yv = cv2str_dup(cv)) == NULL) + goto done; + if (strcmp(xv, yv) == 0) + xml_flag_set(x, flag); /* Actual value same as default value */ + free(yv); + done: + return 0; +} + +/*! Set flag on node having schema default value. (config) + * + * Used in with-default code for trim and report-all-tagged + * @param[in] x XML node + * @param[in] flag Flag to be used + * @retval 0 OK + * @see xml_flag_state_default_value for non-config default value + */ +int +xml_flag_default_value(cxobj *x, + uint16_t flag) +{ + yang_stmt *y; + cg_var *cv; + char *yv; + char *xv; + + xml_flag_reset(x, flag); /* Assume not default value */ + if ((xv = xml_body(x)) == NULL) + goto done; + if ((y = xml_spec(x)) == NULL) + goto done; + if ((cv = yang_cv_get(y)) == NULL) + goto done; + if ((cv = yang_cv_get(y)) == NULL) + goto done; + if (cv_name_get(cv) == NULL) + goto done; + if ((yv = cv2str_dup(cv)) == NULL) + goto done; + if (strcmp(xv, yv) == 0) + xml_flag_set(x, flag); /* Actual value same as default value */ + free(yv); + done: + return 0; +} diff --git a/lib/src/clixon_xml_sort.c b/lib/src/clixon_xml_sort.c index 6321c688..9f3be0eb 100644 --- a/lib/src/clixon_xml_sort.c +++ b/lib/src/clixon_xml_sort.c @@ -1501,7 +1501,7 @@ xml_find_index_yang(cxobj *xp, * if (clixon_xml_find_index(xp, yp, NULL, "a", ns, cvk, xv) < 0) * err; * for (i=0; ieth11500\ eth29000\ eth31500\ -edvdv\ " new "rfc8040 4.3. RESTCONF GET json"