From c08dac2e5d9e586e6b8564884f74605f5262cc3c Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Sat, 10 Aug 2024 17:38:12 +0200 Subject: [PATCH] YANG optimization: move "when" and "mymodule" to external maps --- apps/backend/backend_main.c | 1 + apps/cli/cli_main.c | 1 + apps/netconf/netconf_main.c | 1 + apps/restconf/restconf_lib.c | 2 +- apps/snmp/snmp_main.c | 1 + lib/clixon/clixon_yang.h | 14 +- lib/src/clixon_datastore_write.c | 2 + lib/src/clixon_xml_map.c | 4 +- lib/src/clixon_yang.c | 356 +++++++++++++++---------------- lib/src/clixon_yang_internal.h | 66 +----- lib/src/clixon_yang_module.c | 4 +- lib/src/clixon_yang_parse_lib.c | 101 ++++----- lib/src/clixon_yang_type.c | 8 +- 13 files changed, 247 insertions(+), 314 deletions(-) diff --git a/apps/backend/backend_main.c b/apps/backend/backend_main.c index 219ea6c3..008807b4 100644 --- a/apps/backend/backend_main.c +++ b/apps/backend/backend_main.c @@ -116,6 +116,7 @@ backend_terminate(clixon_handle h) if ((yspec = clicon_dbspec_yang(h)) != NULL){ ys_free(yspec); } + yang_exit(h); if ((yspec = clicon_config_yang(h)) != NULL) ys_free(yspec); if ((yspec = clicon_nacm_ext_yang(h)) != NULL) diff --git a/apps/cli/cli_main.c b/apps/cli/cli_main.c index 2148e48c..c9e36d8f 100644 --- a/apps/cli/cli_main.c +++ b/apps/cli/cli_main.c @@ -180,6 +180,7 @@ cli_terminate(clixon_handle h) clicon_rpc_close_session(h); if ((yspec = clicon_dbspec_yang(h)) != NULL) ys_free(yspec); + yang_exit(h); if ((yspec = clicon_config_yang(h)) != NULL) ys_free(yspec); if ((nsctx = clicon_nsctx_global_get(h)) != NULL) diff --git a/apps/netconf/netconf_main.c b/apps/netconf/netconf_main.c index caec9f97..53349478 100644 --- a/apps/netconf/netconf_main.c +++ b/apps/netconf/netconf_main.c @@ -588,6 +588,7 @@ netconf_terminate(clixon_handle h) ys_free(yspec); if ((yspec = clicon_config_yang(h)) != NULL) ys_free(yspec); + yang_exit(h); if ((nsctx = clicon_nsctx_global_get(h)) != NULL) cvec_free(nsctx); if ((x = clicon_conf_xml(h)) != NULL) diff --git a/apps/restconf/restconf_lib.c b/apps/restconf/restconf_lib.c index 8cff2f99..5cd57bb0 100644 --- a/apps/restconf/restconf_lib.c +++ b/apps/restconf/restconf_lib.c @@ -365,12 +365,12 @@ restconf_terminate(clixon_handle h) close(fs); /* Delete all plugins, and RPC callbacks */ clixon_plugin_module_exit(h); - clicon_rpc_close_session(h); if ((yspec = clicon_dbspec_yang(h)) != NULL) ys_free(yspec); if ((yspec = clicon_config_yang(h)) != NULL) ys_free(yspec); + yang_exit(h); if ((nsctx = clicon_nsctx_global_get(h)) != NULL) cvec_free(nsctx); if ((x = clicon_conf_xml(h)) != NULL) diff --git a/apps/snmp/snmp_main.c b/apps/snmp/snmp_main.c index 8ec4eeb0..b9df58f5 100644 --- a/apps/snmp/snmp_main.c +++ b/apps/snmp/snmp_main.c @@ -126,6 +126,7 @@ snmp_terminate(clixon_handle h) ys_free(yspec); if ((yspec = clicon_config_yang(h)) != NULL) ys_free(yspec); + yang_exit(h); if ((nsctx = clicon_nsctx_global_get(h)) != NULL) cvec_free(nsctx); if ((x = clicon_conf_xml(h)) != NULL) diff --git a/lib/clixon/clixon_yang.h b/lib/clixon/clixon_yang.h index c4680c14..c9b4ded5 100644 --- a/lib/clixon/clixon_yang.h +++ b/lib/clixon/clixon_yang.h @@ -90,8 +90,10 @@ * Set by yang_mount_set * Read by ys_free1 */ -#define YANG_FLAG_WHEN 0x400 /* Use extended struct to access when-info for - * augment/grouping */ +#define YANG_FLAG_WHEN 0x400 /* Use external map to access when-info for + * augment/grouping */ +#define YANG_FLAG_MYMODULE 0x800 /* Use external map to access my-module for + * UNKNOWNS and augment/grouping */ /* * Types @@ -252,10 +254,10 @@ int yang_ref_dec(yang_stmt *ys); uint16_t yang_flag_get(yang_stmt *ys, uint16_t flag); int yang_flag_set(yang_stmt *ys, uint16_t flag); int yang_flag_reset(yang_stmt *ys, uint16_t flag); +yang_stmt *yang_when_get(clixon_handle h, yang_stmt *ys); +int yang_when_set(clixon_handle h, yang_stmt *ys, yang_stmt *ywhen); 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); uint32_t yang_linenum_get(yang_stmt *ys); @@ -279,7 +281,6 @@ int ys_free(yang_stmt *ys); int ys_cp_one(yang_stmt *nw, yang_stmt *old); int ys_cp(yang_stmt *nw, yang_stmt *old); yang_stmt *ys_dup(yang_stmt *old); -yang_stmt *yse_dup(yang_stmt *old); int yn_insert(yang_stmt *ys_parent, yang_stmt *ys_child); int yn_insert1(yang_stmt *ys_parent, yang_stmt *ys_child); yang_stmt *yn_iter(yang_stmt *yparent, int *inext); @@ -326,10 +327,11 @@ int yang_type_cache_set2(yang_stmt *ys, yang_stmt *resolved, int options, yang_stmt *yang_anydata_add(yang_stmt *yp, char *name); int yang_extension_value(yang_stmt *ys, char *name, char *ns, int *exist, char **value); int yang_sort_subelements(yang_stmt *ys); -int yang_init(clixon_handle h); int yang_single_child_type(yang_stmt *ys, enum rfc_6020 subkeyw); void *yang_action_cb_get(yang_stmt *ys); int yang_action_cb_add(yang_stmt *ys, void *rc); int ys_populate_feature(clixon_handle h, yang_stmt *ys); +int yang_init(clixon_handle h); +int yang_exit(clixon_handle h); #endif /* _CLIXON_YANG_H_ */ diff --git a/lib/src/clixon_datastore_write.c b/lib/src/clixon_datastore_write.c index 78781db0..1e35c0d5 100644 --- a/lib/src/clixon_datastore_write.c +++ b/lib/src/clixon_datastore_write.c @@ -324,6 +324,8 @@ check_when_condition(cxobj *x0p, } retval = 1; done: + if (nsc) + cvec_free(nsc); if (cberr) cbuf_free(cberr); return retval; diff --git a/lib/src/clixon_xml_map.c b/lib/src/clixon_xml_map.c index 28df5734..592d98bb 100644 --- a/lib/src/clixon_xml_map.c +++ b/lib/src/clixon_xml_map.c @@ -2089,7 +2089,6 @@ yang_check_when_xpath(cxobj *xn, int nr = 0; cvec *nsc = NULL; int xmalloc = 0; /* ugly help variable to clean temporary object */ - int nscmalloc = 0; /* ugly help variable to remove */ /* First variant */ if ((xpath = yang_when_xpath_get(yn)) != NULL){ @@ -2111,7 +2110,6 @@ yang_check_when_xpath(cxobj *xn, x = xn; if (xml_nsctx_yang(yn, &nsc) < 0) goto done; - nscmalloc++; *hit = 1; } else @@ -2128,7 +2126,7 @@ yang_check_when_xpath(cxobj *xn, done: if (xmalloc) xml_purge(x); - if (nsc && nscmalloc) + if (nsc) xml_nsctx_free(nsc); return retval; } diff --git a/lib/src/clixon_yang.c b/lib/src/clixon_yang.c index 9a7b50c1..d6e3b4ef 100644 --- a/lib/src/clixon_yang.c +++ b/lib/src/clixon_yang.c @@ -174,6 +174,10 @@ static const map_str2int ykmap[] = { {NULL, -1} }; +/* XXX: Global variables, should really be on handle but not available in some cases */ +static map_ptr2ptr *_yang_when_map = NULL; +static map_ptr2ptr *_yang_mymodule_map = NULL; + /* Forward static */ static int yang_type_cache_free(yang_type_cache *ycache); static int yang_type_cache_cp(yang_stmt *ynew, yang_stmt *yold); @@ -266,8 +270,6 @@ yang_argument_set(yang_stmt *ys, yang_stmt * yang_orig_get(yang_stmt *ys) { - if (ys->ys_orig) - assert(ys->ys_orig->ys_orig == NULL); return ys->ys_orig; } @@ -283,7 +285,6 @@ yang_orig_set(yang_stmt *ys, yang_stmt *y0) { if (y0->ys_orig){ - assert(y0->ys_orig->ys_orig == NULL); yang_orig_set(ys, y0->ys_orig); } else @@ -299,7 +300,6 @@ yang_orig_set(yang_stmt *ys, cg_var* yang_cv_get(yang_stmt *ys) { - // assert(ys->ys_keyword == Y_FEATURE ||ys->ys_keyword == Y_LEAF || ys->ys_keyword == Y_LEAF_LIST || ys->ys_keyword == Y_CONFIG || ys->ys_keyword == Y_MANDATORY || ys->ys_keyword == Y_MAX_ELEMENTS|| ys->ys_keyword == Y_MIN_ELEMENTS || ys->ys_keyword == Y_REQUIRE_INSTANCE || ys->ys_keyword == Y_FRACTION_DIGITS || ys->ys_keyword == Y_REVISION || ys->ys_keyword == Y_REVISION_DATE || ys->ys_keyword == Y_UNKNOWN || ys->ys_keyword == Y_SPEC || ys->ys_keyword == Y_ENUM); return ys->ys_cv; } @@ -314,7 +314,6 @@ int yang_cv_set(yang_stmt *ys, cg_var *cv) { - // assert(ys->ys_keyword == Y_FEATURE || ys->ys_keyword == Y_LEAF || ys->ys_keyword == Y_LEAF_LIST || ys->ys_keyword == Y_CONFIG || ys->ys_keyword == Y_MANDATORY || ys->ys_keyword == Y_MAX_ELEMENTS|| ys->ys_keyword == Y_MIN_ELEMENTS || ys->ys_keyword == Y_REQUIRE_INSTANCE || ys->ys_keyword == Y_FRACTION_DIGITS || ys->ys_keyword == Y_REVISION || ys->ys_keyword == Y_REVISION_DATE || ys->ys_keyword == Y_UNKNOWN || ys->ys_keyword == Y_SPEC || ys->ys_keyword == Y_ENUM); if (cv != NULL && ys->ys_cv != NULL) cv_free(ys->ys_cv); ys->ys_cv = cv; @@ -330,7 +329,6 @@ yang_cv_set(yang_stmt *ys, cvec* yang_cvec_get(yang_stmt *ys) { - // assert(ys->ys_keyword == Y_EXTENSION || ys->ys_keyword == Y_IDENTITY ||ys->ys_keyword == Y_LENGTH || ys->ys_keyword == Y_LIST ||ys->ys_keyword == Y_RANGE || ys->ys_keyword == Y_TYPE ||ys->ys_keyword == Y_UNIQUE ||ys->ys_keyword == Y_CONTAINER); return ys->ys_cvec; } @@ -345,7 +343,6 @@ int yang_cvec_set(yang_stmt *ys, cvec *cvv) { - // assert(ys->ys_keyword == Y_EXTENSION || ys->ys_keyword == Y_IDENTITY ||ys->ys_keyword == Y_LENGTH || ys->ys_keyword == Y_LIST ||ys->ys_keyword == Y_RANGE || ys->ys_keyword == Y_TYPE ||ys->ys_keyword == Y_UNIQUE ||ys->ys_keyword == Y_CONTAINER); if (ys->ys_cvec) cvec_free(ys->ys_cvec); ys->ys_cvec = cvv; @@ -368,7 +365,6 @@ yang_cvec_add(yang_stmt *ys, cg_var *cv; cvec *cvv; - // assert(ys->ys_keyword == Y_EXTENSION || ys->ys_keyword == Y_IDENTITY ||ys->ys_keyword == Y_LENGTH || ys->ys_keyword == Y_LIST ||ys->ys_keyword == Y_RANGE || ys->ys_keyword == Y_TYPE ||ys->ys_keyword == Y_UNIQUE ||ys->ys_keyword == Y_CONTAINER); if ((cvv = yang_cvec_get(ys)) == NULL){ if ((cvv = cvec_new(0)) == NULL){ clixon_err(OE_YANG, errno, "cvec_new"); @@ -470,6 +466,65 @@ yang_flag_reset(yang_stmt *ys, return 0; } +/*! Get Yang when statement from external map + * + * @param[in] h Clixon handle (may be NULL) + * @param[in] ys Yang statement + * @retval ywhen Yang when statement + * @retval NULL No yang when + * @note h may be NULL since may not be available by caller + */ +yang_stmt * +yang_when_get(clixon_handle h, + yang_stmt *ys) +{ + map_ptr2ptr *mp = _yang_when_map; + + if (mp == NULL){ + clixon_log(h, LOG_WARNING, "when_map not defined, yang_init() not called?"); + return NULL; + } + else { + if (yang_flag_get(ys, YANG_FLAG_WHEN) != 0x0 && mp != NULL) + return clixon_ptr2ptr(mp, ys); + } + return NULL; +} + +/*! Set Yang when statement to external map + * + * @param[in] h Clixon handle + * @param[in] ys Yang statement + * @param[int] ywhen Yang when statement + * @retval 0 OK + * @retval -1 Error + */ +int +yang_when_set(clixon_handle h, + yang_stmt *ys, + yang_stmt *ywhen) +{ + int retval = -1; + map_ptr2ptr *mp = _yang_when_map; + + if (mp == NULL){ + clixon_log(h, LOG_WARNING, "when_map not defined, yang_init() not called?"); + goto done; + } + else { + if (clixon_ptr2ptr(mp, ys) != NULL) { + clixon_err(OE_YANG, 0, "when pointer already set"); + goto done; + } + if (clixon_ptr2ptr_add(&_yang_when_map, ys, ywhen) < 0) + goto done; + yang_flag_set(ys, YANG_FLAG_WHEN); + } + retval = 0; + done: + return retval; +} + /*! Get yang xpath for "when"-associated augment * * Ie, for yang structures like: augment { when ; ... } @@ -477,52 +532,17 @@ yang_flag_reset(yang_stmt *ys, * @param[in] ys Yang statement * @retval xpath xpath should evaluate to true at validation * @retval NULL Not set - * @note xpath context is PARENT which is different from when actual when child which is + * @note xpath context is PARENT which is different from when actual when child which is * child itself */ char* yang_when_xpath_get(yang_stmt *ys) { - yang_stmt_extended *yse = (yang_stmt_extended *)ys; + yang_stmt *ywhen; - if ((ys->ys_flags & YANG_FLAG_WHEN) == 0x0) - return NULL; - else - return yse->yse_when_xpath; -} - -/*! Set yang xpath and namespace context for "when"-associated augment - * - * Ie, for yang structures like: augment { when ; ... } - * Will insert new yang nodes at with this special "when" struct (not yang node) - * @param[in] ys Yang statement - * @param[in] xpath If set, this xpath should evaluate to true at validation, copied - * @retval 0 OK - * @retval -1 Error - */ -int -yang_when_xpath_set(yang_stmt *ys, - char *xpath) -{ - int retval = -1; - yang_stmt_extended *yse = (yang_stmt_extended *)ys; - - if (xpath == NULL){ - clixon_err(OE_YANG, EINVAL, "xpath is NULL"); - goto done; - } - if ((ys->ys_flags & YANG_FLAG_WHEN) == 0x0){ - clixon_err(OE_YANG, EINVAL, "Yang node %s %s must have flag YANG_FLAG_WHEN for this operation", - yang_key2str(ys->ys_keyword), ys->ys_argument); - goto done; - } - if ((yse->yse_when_xpath = strdup(xpath)) == NULL){ - clixon_err(OE_YANG, errno, "strdup"); - goto done; - } - retval = 0; - done: - return retval; + if ((ywhen = yang_when_get(NULL, ys)) != NULL) + return yang_argument_get(ywhen); + return NULL; } /*! Get yang namespace context for "when"-associated augment @@ -530,48 +550,20 @@ yang_when_xpath_set(yang_stmt *ys, * Ie, for yang structures like: augment { when ; ... } * Will insert new yang nodes at with this special "when" struct (not yang node) * @param[in] ys Yang statement - * @retval nsc Namespace context + * @retval nsc Namespace context (caller frees with cvec_free) * @note retval is direct pointer, may need to be copied */ cvec * yang_when_nsc_get(yang_stmt *ys) { - yang_stmt_extended *yse = (yang_stmt_extended *)ys; + yang_stmt *ywhen; + cvec *wnsc = NULL; - if ((ys->ys_flags & YANG_FLAG_WHEN) == 0x0) - return NULL; - else - return yse->yse_when_nsc; -} - -/*! Set yang namespace context for "when"-associated augment - * - * Ie, for yang structures like: augment { when ; ... } - * Will insert new yang nodes at with this special "when" struct (not yang node) - * @param[in] ys Yang statement - * @param[in] nsc Namespace context for when xpath - * @retval 0 OK - * @retval -1 Error - */ -int -yang_when_nsc_set(yang_stmt *ys, - cvec *nsc) -{ - int retval = -1; - yang_stmt_extended *yse = (yang_stmt_extended *)ys; - - if ((ys->ys_flags & YANG_FLAG_WHEN) == 0x0){ - clixon_err(OE_YANG, EINVAL, "Yang node %s %s must have flag YANG_FLAG_WHEN for this operation", - yang_key2str(ys->ys_keyword), ys->ys_argument); - return -1; + if ((ywhen = yang_when_get(NULL, ys)) != NULL) { + if (xml_nsctx_yang(ywhen, &wnsc) < 0) + wnsc = NULL; } - if (nsc && (yse->yse_when_nsc = cvec_dup(nsc)) == NULL){ - clixon_err(OE_YANG, errno, "cvec_dup"); - goto done; - } - retval = 0; - done: - return retval; + return wnsc; } /*! Get yang filename for error/debug purpose (only modules) @@ -671,7 +663,16 @@ yang_typecache_set(yang_stmt *ys, yang_stmt* yang_mymodule_get(yang_stmt *ys) { - return ys->ys_mymodule; + map_ptr2ptr *mp = _yang_mymodule_map; + + if (mp == NULL){ + clixon_log(NULL, LOG_WARNING, "mymodule_map not defined, yang_init() not called?"); + return NULL; + } + else if (yang_flag_get(ys, YANG_FLAG_MYMODULE) == 0x0) + return NULL; + else + return clixon_ptr2ptr(mp, ys); } /*! Set mymodule @@ -686,8 +687,23 @@ int yang_mymodule_set(yang_stmt *ys, yang_stmt *ym) { - ys->ys_mymodule = ym; - return 0; + int retval = -1; + map_ptr2ptr *mp = _yang_mymodule_map; + + if (mp == NULL){ + clixon_log(NULL, LOG_WARNING, "mymodule_map not defined, yang_init() not called?"); + goto done; + } + else { + if (clixon_ptr2ptr(mp, ys) == NULL) { + if (clixon_ptr2ptr_add(&_yang_mymodule_map, ys, ym) < 0) + goto done; + } + } + yang_flag_set(ys, YANG_FLAG_MYMODULE); + retval = 0; + done: + return retval; } /* End access functions */ @@ -721,22 +737,12 @@ yang_stats_one(yang_stmt *ys, size_t sz = 0; yang_type_cache *yc; - if (yang_flag_get(ys, YANG_FLAG_WHEN) == 0x0) - sz += sizeof(struct yang_stmt_extended); - else - sz += sizeof(struct yang_stmt); + sz += sizeof(struct yang_stmt); sz += ys->ys_len*sizeof(struct yang_stmt*); if (ys->ys_argument) sz += strlen(ys->ys_argument) + 1; if (ys->ys_cvec) sz += cvec_size(ys->ys_cvec); - if (yang_flag_get(ys, YANG_FLAG_WHEN) != 0x0) { - yang_stmt_extended *yse = (yang_stmt_extended *)ys; - if (yse->yse_when_xpath) - sz += strlen(yse->yse_when_xpath) + 1; - if (yse->yse_when_nsc) - sz += cvec_size(yse->yse_when_nsc); - } switch (ys->ys_keyword) { case Y_TYPE: if ((yc = yang_typecache_get(ys)) != NULL){ @@ -863,22 +869,6 @@ ys_new(enum rfc_6020 keyw) return ys_new_sz(keyw, sizeof(struct yang_stmt)); } -/*! Create new extended yang node/statement - * - * @param[in] keyw Yang stmt keyword - * @retval ys New yang-stmt. Free with ys_free() - * @retval NULL Error - */ -static yang_stmt * -yse_new(enum rfc_6020 keyw) -{ - yang_stmt *ys; - - if ((ys = ys_new_sz(keyw, sizeof(struct yang_stmt_extended))) != NULL) - yang_flag_set(ys, YANG_FLAG_WHEN); - return ys; -} - /*! Free a single yang statement, dont remove children, called after children freed * * @param[in] ys Yang node to remove @@ -911,13 +901,6 @@ ys_free1(yang_stmt *ys, free(ys->ys_argument); ys->ys_argument = NULL; } - if (yang_flag_get(ys, YANG_FLAG_WHEN) != 0x0) { - yang_stmt_extended *yse = (yang_stmt_extended *)ys; - if (yse->yse_when_xpath) - free(yse->yse_when_xpath); - if (yse->yse_when_nsc) - cvec_free(yse->yse_when_nsc); - } if (ys->ys_stmt) free(ys->ys_stmt); switch (ys->ys_keyword) { /* type-specifi union fields */ @@ -1117,9 +1100,10 @@ uses_orig_ptr(enum rfc_6020 keyword) || keyword == Y_STATUS || keyword == Y_UNIQUE || keyword == Y_UNITS - || keyword == Y_UNKNOWN + // || keyword == Y_UNKNOWN // NO (test_snmp_ifmib.sh) || keyword == Y_VALUE || keyword == Y_YIN_ELEMENT + || keyword == Y_WHEN // children ; } #endif /* YANG_ORIG_PTR_SKIP */ @@ -1188,6 +1172,8 @@ ys_cp_one(yang_stmt *ynew, default: break; } + if (yang_flag_get(yold, YANG_FLAG_MYMODULE) != 0x0) + yang_mymodule_set(ynew, yang_mymodule_get(yold)); retval = 0; done: return retval; @@ -1261,42 +1247,6 @@ ys_dup(yang_stmt *old) return nw; } -/*! Create a new extdended yang node and copy the contents recursively from the original. - */ -yang_stmt * -yse_dup(yang_stmt *yold) -{ - yang_stmt *ynew; - char *xpath; - cvec *cvv; - - if ((ynew = yse_new(yold->ys_keyword)) == NULL) - return NULL; - if (ys_cp(ynew, yold) < 0){ - ys_free(ynew); - return NULL; - } - yang_flag_set(ynew, YANG_FLAG_WHEN); - if (yang_flag_get(yold, YANG_FLAG_WHEN) != 0x0) { - if ((xpath = yang_when_xpath_get(yold)) != NULL){ - if (yang_when_xpath_set(ynew, xpath) < 0) - goto done; - } - if ((cvv = yang_when_nsc_get(yold)) != NULL){ - if (yang_when_nsc_set(ynew, cvv) < 0) - goto done; - } - } - ok: - return ynew; - done: - if (ynew){ - ys_free(ynew); - ynew = NULL; - } - goto ok; -} - /*! Replace yold with ynew (insert ynew at the exact place of yold). Keep yold pointer as-is. * * @param[in] yorig Existing yang statement @@ -3927,7 +3877,7 @@ yang_key_match(yang_stmt *yn, /*! Set type cache for yang type * - * @param[in] rxmode Kludge to know which regexp engine is used + * @param[in] rxmode Which regexp engine to use, see enum regexp_mode * @retval 0 OK * @retval -1 Error * @see yang_type_cache_regexp_set where cache is extended w compiled regexps @@ -3974,6 +3924,8 @@ yang_type_cache_set2(yang_stmt *ys, /*! Extend yang type cache with compiled regexps * * Compiled Regexps are computed in validate code - after initial cache set + * @param[in] ytype YANG type statement + * @param[in] rxmode Which regexp engine to use, see enum regexp_mode * @param[in] regexps * @retval 0 OK * @retval -1 Error @@ -3983,13 +3935,21 @@ yang_type_cache_regexp_set(yang_stmt *ytype, int rxmode, cvec *regexps) { - int retval = -1; - yang_type_cache *ycache; + int retval = -1; + yang_type_cache *ycache; - assert(regexps); - assert(yang_keyword_get(ytype) == Y_TYPE); - assert((ycache = ytype->ys_typecache) != NULL); - assert(ycache->yc_regexps == NULL); + if (regexps == NULL || yang_keyword_get(ytype) != Y_TYPE) { + clixon_err(OE_YANG, EINVAL, "regexps is NULL, or are already set, or ytype is not YTYPE"); + goto done; + } + if ((ycache = ytype->ys_typecache) == NULL){ + clixon_err(OE_YANG, 0, "Typecache is NULL"); + goto done; + } + if (ycache->yc_regexps != NULL){ + clixon_err(OE_YANG, 0, "regexp is already set"); + goto done; + } ycache->yc_rxmode = rxmode; if ((ycache->yc_regexps = cvec_dup(regexps)) == NULL){ clixon_err(OE_UNIX, errno, "cvec_dup"); @@ -4003,12 +3963,13 @@ yang_type_cache_regexp_set(yang_stmt *ytype, /*! Get individual fields (direct/destructively) from yang type cache. * * @param[out] patterns Initialized cvec of regexp patterns strings - * @retval 1 OK - * @retval 0 No cache - * @retval -1 Error + * @param[out] rxmode Which regexp engine to use, see enum regexp_mode + * @retval 1 OK + * @retval 0 No cache + * @retval -1 Error */ int -yang_type_cache_get2(yang_stmt *ytype, +yang_type_cache_get2(yang_stmt *ytype, yang_stmt **resolved, int *options, cvec **cvv, @@ -4288,17 +4249,6 @@ yang_sort_subelements(yang_stmt *ys) #endif } -/*! Init yang code - * - * @param[in] h Clixon handle - * @retval 0 OK - * @retval -1 Error - */ -int -yang_init(clixon_handle h) -{ - return yang_cardinality_init(h); -} #ifdef XML_EXPLICIT_INDEX /*! Mark element as search_index in list @@ -4440,3 +4390,51 @@ yang_action_cb_add(yang_stmt *ys, ADDQ(rc, ys->ys_action_cb); return 0; } + +/*! Init yang code + * + * Add two external tables for YANGs + * @param[in] h Clixon handle + * @retval 0 OK + * @retval -1 Error + */ +int +yang_init(clixon_handle h) +{ + int retval = -1; + map_ptr2ptr *mp; + + if ((mp = calloc(1, sizeof(*mp))) == NULL){ + clixon_err(OE_UNIX, errno, "calloc"); + goto done; + } + _yang_when_map = mp; + if ((mp = calloc(1, sizeof(*mp))) == NULL){ + clixon_err(OE_UNIX, errno, "calloc"); + goto done; + } + _yang_mymodule_map = mp; + if (yang_cardinality_init(h) < 0) + goto done; + retval = 0; + done: + return retval; +} + +/*! Exit yang code + * + * @param[in] h Clixon handle + */ +int +yang_exit(clixon_handle h) +{ + if (_yang_when_map != NULL) { + free(_yang_when_map); + _yang_when_map = NULL; + } + if (_yang_mymodule_map != NULL) { + free(_yang_mymodule_map); + _yang_mymodule_map = NULL; + } + return 0; +} diff --git a/lib/src/clixon_yang_internal.h b/lib/src/clixon_yang_internal.h index ae72342d..d6dec489 100644 --- a/lib/src/clixon_yang_internal.h +++ b/lib/src/clixon_yang_internal.h @@ -46,17 +46,16 @@ * @note unions not cached */ struct yang_type_cache{ - int yc_options; /* See YANG_OPTIONS_* that determines pattern/ + uint8_t yc_options; /* See YANG_OPTIONS_* that determines pattern/ fraction fields. */ - int yc_rxmode; /* need to store mode for freeing since handle may not be available - * see regexp_mode - */ + uint8_t yc_rxmode; /* Need to store mode for freeing since handle may not be + * available. See enum regexp_mode */ uint8_t yc_fraction; /* Fraction digits for decimal64 (if YANG_OPTIONS_FRACTION_DIGITS */ cvec *yc_cvv; /* Range and length restriction. (if YANG_OPTION_ LENGTH|RANGE. Can be a vector if multiple - ranges*/ - cvec *yc_patterns; /* list of regexp, if cvec_len() > 0 */ - cvec *yc_regexps; /* list of _compiled_ regexp, if cvec_len() > 0 */ + ranges */ + cvec *yc_patterns; /* List of regexp, if cvec_len() > 0 */ + cvec *yc_regexps; /* List of _compiled_ regexp, if cvec_len() > 0 */ yang_stmt *yc_resolved; /* Resolved type object, can be NULL - note direct ptr */ }; typedef struct yang_type_cache yang_type_cache; @@ -65,8 +64,7 @@ typedef struct yang_type_cache yang_type_cache; * * This is an internal type, not exposed in the API * The external type is "yang_stmt" defined in clixon_yang.h - * @see struct yang_stmt_extended for extended struct (same beginning) - * @note This struct MUST be identical in size to first part of yang_stmt_extended struct + * @note There is additional info in maps, yang_when_set and yang_mymodule_set */ struct yang_stmt { /* On x86_64, the following three fields take 8 bytes */ @@ -110,12 +108,6 @@ struct yang_stmt { Y_UNIQUE: vector of descendant schema node ids # Y_UNKNOWN: app-dep: yang-mount-points */ - yang_stmt *ys_mymodule; /* Shortcut to "my" module. Used by: - * 1) Augmented nodes "belong" to the module where the - * augment is declared, which may be different from - * the direct ancestor module - * 2) Unknown nodes "belong" to where the extension is - * declared */ yang_stmt *ys_orig; /* Pointer to original (for uses/augment copies) */ union { /* Depends on ys_keyword */ rpc_callback_t *ysu_action_cb; /* Y_ACTION: Action callback list*/ @@ -126,50 +118,6 @@ struct yang_stmt { } u; }; -/*! An extended yang struct for use of extra fields that consumes more memory - * - * See end of struct. The fields that fit here are extended only fot the original object., - * they may not be copied. Currently only tow WHEN fields. - * Cannot fit this into the ysu union because keyword is unknown (or at least a set) - * @see struct yang_stmt for the original struct - * @note First part of this struct MUST resemble yang_stmt fields (in memory). - */ -struct yang_stmt_extended { - /* On x86_64, the following four fields take 16 bytes */ - enum rfc_6020 ys_keyword:16; /* YANG keyword */ - uint16_t ys_flags; /* Flags according to YANG_FLAG_MARK and others */ - uint32_t ys_len; /* Number of children */ -#ifdef YANG_SPEC_LINENR - uint32_t ys_linenum; /* For debug/errors: line number (in ys_filename) */ -#endif - struct yang_stmt **ys_stmt; /* Vector of children statement pointers */ - struct yang_stmt *ys_parent; /* Backpointer to parent: yang-stmt or yang-spec */ - char *ys_argument; /* String / argument depending on keyword */ - cg_var *yse_cv; /* cligen variable. See ys_populate() */ - cvec *yse_cvec; /* List of stmt-specific variables */ - yang_stmt *yse_mymodule; /* Shortcut to "my" module. Used by: - * 1) Augmented nodes "belong" to the module where the - * augment is declared, which may be different from - * the direct ancestor module - * 2) Unknown nodes "belong" to where the extension is - * declared */ - yang_stmt *yse_orig; /* Pointer to original (for uses/augment copies) */ - union { /* depends on ys_keyword */ - rpc_callback_t *ysu_action_cb; /* Y_ACTION: Action callback list*/ - char *ysu_filename; /* Y_MODULE/Y_SUBMODULE: For debug/errors: filename */ - yang_type_cache *ysu_typecache; /* Y_TYPE: cache all typedef data except unions */ - int ysu_ref; /* Y_SPEC: Reference count for free: 0 means - * no sharing, 1: two references */ - } ue; - - /* The following fields are only in extended - * ----------------------------------------- - */ - char *yse_when_xpath; /* Special conditional for a "when"-associated augment/uses XPath */ - cvec *yse_when_nsc; /* Special conditional for a "when"-associated augment/uses namespace ctx */ -}; -typedef struct yang_stmt_extended yang_stmt_extended; - /* Access macros */ #define ys_action_cb u.ysu_action_cb #define ys_filename u.ysu_filename diff --git a/lib/src/clixon_yang_module.c b/lib/src/clixon_yang_module.c index 6acb7aa0..1ec4de35 100644 --- a/lib/src/clixon_yang_module.c +++ b/lib/src/clixon_yang_module.c @@ -644,7 +644,7 @@ yang_find_module_by_namespace_revision(yang_stmt *yspec, const char *ns, const char *rev) { - yang_stmt *ymod; + yang_stmt *ymod = NULL; yang_stmt *yrev; char *rev1; int inext; @@ -682,7 +682,7 @@ yang_find_module_by_name_revision(yang_stmt *yspec, const char *name, const char *rev) { - yang_stmt *ymod; + yang_stmt *ymod = NULL; yang_stmt *yrev; char *rev1; int inext; diff --git a/lib/src/clixon_yang_parse_lib.c b/lib/src/clixon_yang_parse_lib.c index 2f0413df..2d9f95bc 100644 --- a/lib/src/clixon_yang_parse_lib.c +++ b/lib/src/clixon_yang_parse_lib.c @@ -106,7 +106,7 @@ #define BUFLEN 1024 /* Forward */ -static int yang_expand_grouping(yang_stmt *yn); +static int yang_expand_grouping(clixon_handle h, yang_stmt *yn); /*! Resolve a grouping name from a module, includes looking in submodules */ @@ -253,6 +253,7 @@ ys_add_orig_ptr(yang_stmt *yp0, * @note If the augment has a when statement, which is commonplace, the when statement is not * copied as datanodes are, since it should not apply to the target node. Instead it is added as * a special "when" struct to the yang statements being inserted. + * @see yang_expand_uses_node similar but for uses/grouping */ static int yang_augment_node(clixon_handle h, @@ -265,8 +266,7 @@ yang_augment_node(clixon_handle h, yang_stmt *yc; yang_stmt *ymod; yang_stmt *ywhen = NULL; - char *wxpath; /* xpath of when statement */ - cvec *wnsc = NULL; /* namespace context of when statement */ + yang_stmt *ywhen0; enum rfc_6020 targetkey; enum rfc_6020 childkey; int inext; @@ -308,11 +308,7 @@ yang_augment_node(clixon_handle h, goto ok; /* Find when statement, if present */ - if ((ywhen = yang_find(ys, Y_WHEN, NULL)) != NULL){ - wxpath = yang_argument_get(ywhen); - if (xml_nsctx_yang(ywhen, &wnsc) < 0) - goto done; - } + ywhen = yang_find(ys, Y_WHEN, NULL); /* Extend ytarget with ys' schemanode children */ inext = 0; while ((yc0 = yn_iter(ys, &inext)) != NULL) { @@ -388,16 +384,7 @@ yang_augment_node(clixon_handle h, break; } /* If expanded by uses / when */ - if (yang_flag_get(yc0, YANG_FLAG_WHEN) != 0x0){ - if ((yc = yse_dup(yc0)) == NULL) - goto done; - } - /* If augment when */ - else if (ywhen) { - if ((yc = yse_dup(yc0)) == NULL) /* Extended */ - goto done; - } - else if ((yc = ys_dup(yc0)) == NULL) + if ((yc = ys_dup(yc0)) == NULL) goto done; #ifdef YANG_GROUPING_AUGMENT_SKIP /* cornercase: always expand uses under augment */ @@ -413,10 +400,19 @@ yang_augment_node(clixon_handle h, /* If there is an associated when statement, add a special when struct to the yang * see xml_yang_validate_all */ - if (ywhen){ - if (yang_when_xpath_set(yc, wxpath) < 0) + /* ywhen of uses node (already present) */ + if ((ywhen0 = yang_when_get(h, yc0)) != NULL) { + if (yang_when_set(h, yc, ywhen0) < 0) goto done; - if (yang_when_nsc_set(yc, wnsc) < 0) + } + /* ywhen of augmented node + * Note: double whens not supported + */ + if (ywhen){ + if (ywhen0 != NULL) + clixon_log(h, LOG_WARNING, "Warning: Double when statement, both augment and existing (uses) not supported in %s", + yang_argument_get(ys_module(ys))); + if (yang_when_set(h, yc, ywhen) < 0) goto done; } /* Note: ys_populate2 called as a special case here since the inserted child is @@ -430,8 +426,6 @@ yang_augment_node(clixon_handle h, ok: retval = 0; done: - if (wnsc) - cvec_free(wnsc); return retval; } @@ -574,16 +568,19 @@ ys_iskey(yang_stmt *y, /*! Helper function to yang_expand_grouping * - * @param[in] yn Yang parent node of uses ststement - * @param[in] ys Uses statement - * @param[in] i - * @retval 0 OK - * @retval -1 Error + * @param[in] h Clixon handle + * @param[in] yn Yang parent node of uses ststement + * @param[in] ys Uses statement + * @param[in] i ys is i:th element of yn:s children + * @retval 0 OK + * @retval -1 Error + * @see yang_augment_node similar but for augment */ static int -yang_expand_uses_node(yang_stmt *yn, - yang_stmt *ys, - int i) +yang_expand_uses_node(clixon_handle h, + yang_stmt *yn, + yang_stmt *ys, + int i) { int retval = -1; char *id = NULL; @@ -599,8 +596,6 @@ yang_expand_uses_node(yang_stmt *yn, int j; int k; yang_stmt *ywhen; - char *wxpath = NULL; /* xpath of when statement */ - cvec *wnsc = NULL; /* namespace context of when statement */ int inext; /* Split argument into prefix and name */ @@ -643,15 +638,11 @@ yang_expand_uses_node(yang_stmt *yn, * A mark could be completely normal (several uses) or it could be a recursion. */ yang_flag_set(ygrouping, YANG_FLAG_GROUPING); /* Mark as (being) expanded */ - if (yang_expand_grouping(ygrouping) < 0) + if (yang_expand_grouping(h, ygrouping) < 0) goto done; } /* Find when statement, if present */ - if ((ywhen = yang_find(ys, Y_WHEN, NULL)) != NULL) { - wxpath = yang_argument_get(ywhen); - if (xml_nsctx_yang(ywhen, &wnsc) < 0) - goto done; - } + ywhen = yang_find(ys, Y_WHEN, NULL); /* Make a copy of the grouping, then make refinements to this copy * Note this ygrouping2 object does not have a parent and does not work in many * functions which assume a full hierarchy, use the original ygrouping in those cases. @@ -669,14 +660,8 @@ yang_expand_uses_node(yang_stmt *yn, for (i=0; iys_len; i++){ yco = ygrouping->ys_stmt[i]; - if (ywhen != NULL) { - if ((ycn = yse_dup(yco)) == NULL) - goto done; - } - else { - if ((ycn = ys_dup(yco)) == NULL) - goto done; - } + if ((ycn = ys_dup(yco)) == NULL) + goto done; ygrouping2->ys_stmt[i] = ycn; ycn->ys_parent = ygrouping2; } @@ -770,9 +755,7 @@ yang_expand_uses_node(yang_stmt *yn, ); goto done; } - if (yang_when_xpath_set(yg, wxpath) < 0) - goto done; - if (yang_when_nsc_set(yg, wnsc) < 0) + if (yang_when_set(h, yg, ywhen) < 0) goto done; } /* This is for extensions that allow list keys to be optional, see restconf_main_extension_cb */ @@ -788,8 +771,6 @@ yang_expand_uses_node(yang_stmt *yn, ys_free(ygrouping2); retval = 0; done: - if (wnsc) - cvec_free(wnsc); if (prefix) free(prefix); if (id) @@ -807,12 +788,14 @@ yang_expand_uses_node(yang_stmt *yn, * until the contents of the grouping are added to the schema tree via a * "uses" statement that does not appear inside a "grouping" statement, * at which point they are bound to the namespace of the current module. + * @param[in] h Clixon handle (may be NULL) * @param[in] yn Yang node for recursive iteration * @retval 0 OK * @retval -1 Error */ static int -yang_expand_grouping(yang_stmt *yn) +yang_expand_grouping(clixon_handle h, + yang_stmt *yn) { int retval = -1; yang_stmt *ys = NULL; @@ -825,7 +808,7 @@ yang_expand_grouping(yang_stmt *yn) switch (yang_keyword_get(ys)){ case Y_USES: if (yang_flag_get(ys, YANG_FLAG_GROUPING) == 0){ - if (yang_expand_uses_node(yn, ys, i) < 0) + if (yang_expand_uses_node(h, yn, ys, i) < 0) goto done; yang_flag_set(ys, YANG_FLAG_GROUPING); } @@ -846,14 +829,12 @@ yang_expand_grouping(yang_stmt *yn) */ if (yang_flag_get(ys, YANG_FLAG_GROUPING) == 0){ yang_flag_set(ys, YANG_FLAG_GROUPING); /* Mark as (being) expanded */ - if (yang_expand_grouping(ys) < 0) + if (yang_expand_grouping(h, ys) < 0) goto done; } } - else - - { - if (yang_expand_grouping(ys) < 0) + else { + if (yang_expand_grouping(h, ys) < 0) goto done; } } @@ -1591,7 +1572,7 @@ yang_parse_post(clixon_handle h, * This alters the original YANG: after this all YANG uses have been expanded */ for (i=0; i yang_type_cache_set - * (called at parse) | + * +--> yang_type_cache_set + * (called at parse) | * ys_resolve_type --+ ys_populate_range, yang_enum_int_value(NULL) * \ | cml * v v v @@ -46,7 +46,7 @@ * | yang2cli_var | yang2cli_var_union_one * ys_cv_validate---+ ys_cv_validate_union_one * | \ / - * | \ / yang_type_cache_regex_set + * | \ / yang_type_cache_regexp_set * ys_populate_leaf, +--> compile_pattern2regexp (compile regexps) * xml_cv_cache (NULL) +--> cv_validate1 --> cv_validate_pattern (exec regexps) * yang_type2cv (simplified) @@ -223,11 +223,11 @@ compile_pattern2regexp(clixon_handle h, /*! Resolve types: populate type caches * + * Typically only called once when loading the yang type system. * @param[in] ys This is a type statement * @param[in] arg Not used * @retval 0 OK * @retval -1 Error - * Typically only called once when loading the yang type system. * @note unions not cached */ int