Module state upgrade: RFC7895 to RFC 8525

Changes to clixon-config:
  * Added option: 'CLICON_YANG_LIBRARY`
  * Changed default value: `CLICON_MODULE_LIBRARY_RFC7895` to false
Datastore modstate is backward compatible
Tests upgraded to RFC8525
This commit is contained in:
Olof hagsand 2022-03-07 10:56:54 +01:00
parent dd4e2be25c
commit dd2ac56af8
61 changed files with 710 additions and 198 deletions

View file

@ -51,7 +51,6 @@
#include <stdlib.h>
#include <stdint.h>
#include <syslog.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
@ -658,7 +657,6 @@ clicon_modst_cache_set(clicon_handle h,
xml_free(x);
if (xms == NULL)
goto ok;
assert(strcmp(xml_name(xms),"modules-state")==0);
if ((x = xml_dup(xms)) == NULL)
return -1;
if (clicon_hash_add(cdat, brief?"modst_brief":"modst_full", &x, sizeof(x))==NULL)

View file

@ -276,6 +276,8 @@ text_read_modstate(clicon_handle h,
{
int retval = -1;
cxobj *xmodfile = NULL; /* modstate of system (loaded yang modules in runtime) */
cxobj *xyanglib = NULL;
cxobj *xmodcache;
cxobj *xmodsystem = NULL; /* modstate of file, eg startup */
cxobj *xf = NULL; /* xml modstate in file */
cxobj *xf2; /* copy */
@ -284,30 +286,45 @@ text_read_modstate(clicon_handle h,
char *name; /* module name */
char *frev; /* file revision */
char *srev; /* system revision */
int rfc7895=0; /* backward-compatible: old version */
/* Read module-state as computed at startup, see startup_module_state() */
xmodsystem = clicon_modst_cache_get(h, 1);
if ((xmodfile = xml_find_type(xt, NULL, "modules-state", CX_ELMNT)) == NULL){
/* 1) There is no modules-state info in the file */
}
else if (xmodsystem && msdiff){
if ((xmodcache = clicon_modst_cache_get(h, 1)) != NULL)
xmodsystem = xml_find_type(xmodcache, NULL, "module-set", CX_ELMNT);
xyanglib = xml_find_type(xt, NULL, "yang-library", CX_ELMNT);
if ((xmodfile = xpath_first(xt, NULL, "yang-library/module-set")) != NULL)
;
else if ((xmodfile = xml_find_type(xt, NULL, "modules-state", CX_ELMNT)) != NULL)
rfc7895++;
if (xmodfile && xmodsystem && msdiff){
msdiff->md_status = 1; /* There is module state in the file */
/* Create modstate tree for this file */
if (clixon_xml_parse_string("<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\"/>",
if (clixon_xml_parse_string("<module-set xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\"/>",
YB_MODULE, yspec, &msdiff->md_diff, NULL) < 0)
goto done;
if (xml_rootchild(msdiff->md_diff, 0, &msdiff->md_diff) < 0)
goto done;
/* 3) For each module state m in the file */
xf = NULL;
while ((xf = xml_child_each(xmodfile, xf, CX_ELMNT)) != NULL) {
if (strcmp(xml_name(xf), "module-set-id") == 0){
if (xml_body(xf) && (msdiff->md_set_id = strdup(xml_body(xf))) == NULL){
if (!rfc7895){
if ((xf = xpath_first(xt, NULL, "yang-library/content-id")) != NULL){
if (xml_body(xf) && (msdiff->md_content_id = strdup(xml_body(xf))) == NULL){
clicon_err(OE_UNIX, errno, "strdup");
goto done;
}
continue;
}
}
/* 3) For each module state m in the file */
xf = NULL;
while ((xf = xml_child_each(xmodfile, xf, CX_ELMNT)) != NULL) {
if (rfc7895){
if (strcmp(xml_name(xf), "module-set-id") == 0){
if (xml_body(xf) && (msdiff->md_content_id = strdup(xml_body(xf))) == NULL){
clicon_err(OE_UNIX, errno, "strdup");
goto done;
}
continue;
}
}
if (strcmp(xml_name(xf), "module"))
continue; /* ignore other tags, such as module-set-id */
@ -358,10 +375,15 @@ text_read_modstate(clicon_handle h,
* in all cases, whether CLICON_XMLDB_MODSTATE is on or not.
* Clixon systems with CLICON_XMLDB_MODSTATE disabled ignores it
*/
if (xmodfile){
if (xml_purge(xmodfile) < 0)
goto done;
if (rfc7895){
if (xmodfile){
if (xml_purge(xmodfile) < 0)
goto done;
}
}
else if (xyanglib)
if (xml_purge(xyanglib) < 0)
goto done;
retval = 0;
done:
return retval;
@ -516,9 +538,12 @@ xmldb_readfile(clicon_handle h,
if (clicon_option_bool(h, "CLICON_XMLDB_MODSTATE"))
if ((msdiff = modstate_diff_new()) == NULL)
goto done;
if ((x = xml_find_type(x0, NULL, "modules-state", CX_ELMNT)) != NULL)
/* First try RFC8525, but also backward compatible RFC7895 */
if ((x = xpath_first(x0, NULL, "yang-library/module-set")) != NULL ||
(x = xml_find_type(x0, NULL, "modules-state", CX_ELMNT)) != NULL){
if ((xmodfile = xml_dup(x)) == NULL)
goto done;
}
/* Datastore files may contain module-state defining
* which modules are used in the file.
* Strip module-state, analyze it with CHANGE/ADD/RM and return msdiff

View file

@ -100,8 +100,8 @@ modstate_diff_free(modstate_diff_t *md)
{
if (md == NULL)
return 0;
if (md->md_set_id)
free(md->md_set_id);
if (md->md_content_id)
free(md->md_content_id);
if (md->md_diff)
xml_free(md->md_diff);
free(md);
@ -121,11 +121,11 @@ yang_modules_init(clicon_handle h)
yang_stmt *yspec;
yspec = clicon_dbspec_yang(h);
if (!clicon_option_bool(h, "CLICON_MODULE_LIBRARY_RFC7895"))
if (!clicon_option_bool(h, "CLICON_YANG_LIBRARY"))
goto ok;
/* Ensure module-set-id is set */
if (!clicon_option_exists(h, "CLICON_MODULE_SET_ID")){
clicon_err(OE_CFG, ENOENT, "CLICON_MODULE_SET_ID must be defined when CLICON_MODULE_LIBRARY_RFC7895 is enabled");
clicon_err(OE_CFG, ENOENT, "CLICON_MODULE_SET_ID must be defined when CLICON_YANG_LIBRARY is enabled");
goto done;
}
/* Ensure revision exists is set */
@ -165,8 +165,11 @@ yang_modules_revision(clicon_handle h)
return revision;
}
/*! Actually build the yang modules state XML tree
* @see RFC7895
/*! Actually build the yang modules state XML tree according to RFC8525
*
* This assumes CLICON_YANG_LIBRARY is enabled
* If also CLICON_MODULE_LIBRARY_RFC7895 is set, module-state is built according to RFC7895 instead
* @see RFC8525
*/
static int
yms_build(clicon_handle h,
@ -196,9 +199,15 @@ yms_build(clicon_handle h,
goto done;
}
cprintf(cb,"<modules-state xmlns=\"%s\">", yang_argument_get(yns));
cprintf(cb,"<module-set-id>%s</module-set-id>", msid);
if (clicon_option_bool(h, "CLICON_MODULE_LIBRARY_RFC7895")){
cprintf(cb,"<modules-state xmlns=\"%s\">", yang_argument_get(yns));
cprintf(cb,"<module-set-id>%s</module-set-id>", msid);
}
else { /* RFC 8525 */
cprintf(cb,"<yang-library xmlns=\"%s\">", yang_argument_get(yns));
cprintf(cb,"<content-id>%s</content-id>", msid);
cprintf(cb,"<module-set><name>default</name>");
}
ymod = NULL;
while ((ymod = yn_each(yspec, ymod)) != NULL) {
if (yang_keyword_get(ymod) != Y_MODULE)
@ -230,7 +239,8 @@ yms_build(clicon_handle h,
break;
}
}
cprintf(cb, "<conformance-type>implement</conformance-type>");
if (clicon_option_bool(h, "CLICON_MODULE_LIBRARY_RFC7895"))
cprintf(cb, "<conformance-type>implement</conformance-type>");
}
yinc = NULL;
while ((yinc = yn_each(ymod, yinc)) != NULL) {
@ -249,7 +259,12 @@ yms_build(clicon_handle h,
}
cprintf(cb,"</module>");
}
cprintf(cb,"</modules-state>");
if (clicon_option_bool(h, "CLICON_MODULE_LIBRARY_RFC7895")){
cprintf(cb,"</modules-state>");
}
else{
cprintf(cb,"</module-set></yang-library>");
}
retval = 0;
done:
return retval;
@ -302,7 +317,7 @@ yang_modules_state_get(clicon_handle h,
size_t xlen;
int i;
msid = clicon_option_str(h, "CLICON_MODULE_SET_ID");
msid = clicon_option_str(h, "CLICON_MODULE_SET_ID"); /* In RFC 8525 changed to "content-id" */
if ((xc = clicon_modst_cache_get(h, brief)) != NULL){
cxobj *xw; /* tmp top wrap object */
/* xc is here: <modules-state>...