Fixed: [SNMP: snmpwalk is slow and can timeout #404 ](https://github.com/clicon/clixon/issues/404)

Optimized yang_extension_value
This commit is contained in:
Olof hagsand 2023-02-01 14:57:51 +01:00
parent 91034e5361
commit af1f5a037d
6 changed files with 66 additions and 13 deletions

View file

@ -105,6 +105,7 @@ Developers may need to change their code
### Corrected Bugs
* Fixed: [SNMP: snmpwalk is slow and can timeout #404 ](https://github.com/clicon/clixon/issues/404)
* Fixed: [SNMP accepts only u32 & u64 #405](https://github.com/clicon/clixon/issues/405)
* Fixed: [Yang leaves without smiv2:oid directive are not shown well in snmpwalk #398](https://github.com/clicon/clixon/issues/398)
* Fixed: [Netconf commit confirm session-id mismatch #407](https://github.com/clicon/clixon/issues/407)

View file

@ -149,7 +149,7 @@ snmp_scalar_return(cxobj *xs,
/* SMI default value, How is this different from yang defaults?
*/
if (yang_extension_value(ys, "defval", IETF_YANG_SMIV2_NS, NULL, &defaultval) < 0)
if (yang_extension_value_opt(ys, "smiv2:defval", NULL, &defaultval) < 0)
goto done;
if (xs != NULL && (body = xml_body(xs)) != NULL){
if ((ret = type_xml2snmp_pre(body, ys, &xmlstr)) < 0) // XXX <---
@ -887,7 +887,7 @@ snmp_table_get(clicon_handle h,
}
/* SMI default value, How is this different from yang defaults?
*/
if (yang_extension_value(ys, "defval", IETF_YANG_SMIV2_NS, NULL, &defaultval) < 0)
if (yang_extension_value_opt(ys, "smiv2:defval", NULL, &defaultval) < 0)
goto done;
/* Create xpath with right keys from later part of OID
@ -1033,7 +1033,7 @@ snmp_table_set(clicon_handle h,
char *modes_str = NULL;
int modes;
if (yang_extension_value(ys, "max-access", IETF_YANG_SMIV2_NS, NULL, &modes_str) < 0)
if (yang_extension_value_opt(ys, "smiv2:max-access", NULL, &modes_str) < 0)
goto done;
if (modes_str){
modes = snmp_access_str2int(modes_str);

View file

@ -335,6 +335,56 @@ snmp_yang_type_get(yang_stmt *ys,
return retval;
}
/*! Specialized and optimized variant of yang_extension_value
*
* In this optimized version, "id" on the form "<prefix>:<name>" is hardcoded
* and not derived from "name" and "namespace" in the original version.
* @param[in] ys Yang statement where unknown statement may occur referencing to extension
* @param[out] exist The extension exists.
* @param[out] value clispec operator (hide/none) - direct pointer into yang, dont free
* @retval 0 OK: Look in exist and value for return value
* @retval -1 Error
*
* @note This optimizatoin may not work if the unknown statements are augmented in ys.
* @see yang_extension_value for the generic function
*/
int
yang_extension_value_opt(yang_stmt *ys,
char *id,
int *exist,
char **value)
{
int retval = -1;
yang_stmt *yext;
cg_var *cv;
if (ys == NULL){
clicon_err(OE_YANG, EINVAL, "ys is NULL");
goto done;
}
if (exist)
*exist = 0;
yext = NULL; /* This loop gets complicated in the case the extension is augmented */
while ((yext = yn_each(ys, yext)) != NULL) {
if (yang_keyword_get(yext) != Y_UNKNOWN)
continue;
if (strcmp(yang_argument_get(yext), id) != 0)
continue;
break;
}
if (yext != NULL){ /* Found */
if (exist)
*exist = 1;
if (value &&
(cv = yang_cv_get(yext)) != NULL)
*value = cv_string_get(cv);
}
retval = 0;
done:
return retval;
}
/*! Given a YANG node, return SMIv2 oid extension as OID
* @param[in] yn Yang node
* @param[out] objid OID vector, assume allocated with MAX_OID_LEN > oidlen
@ -361,8 +411,8 @@ yangext_oid_get(yang_stmt *yn,
}
else
yref = yn;
/* Get OID from table /list */
if (yang_extension_value(yref, "oid", IETF_YANG_SMIV2_NS, &exist, &oidstr) < 0)
/* Get OID from table /list */
if (yang_extension_value_opt(yref, "smiv2:oid", &exist, &oidstr) < 0)
goto done;
if (exist == 0 || oidstr == NULL){
clicon_debug(1, "OID not found as SMIv2 yang extension of %s", yang_argument_get(yref));
@ -382,20 +432,19 @@ yangext_oid_get(yang_stmt *yn,
goto done;
}
/*! Given a YANG node, return 1 if leaf has oid directive in it, otherwise 0
* @param[in] yn Yang node
* @retval 1 found
* @retval 0 not found
*/
int yangext_is_oid_exist(yang_stmt *yn) {
int
yangext_is_oid_exist(yang_stmt *yn) {
int exist = 0;
char *oidstr = NULL;
if ((yang_keyword_get(yn) != Y_LEAF) ||
(yang_extension_value(yn, "oid", IETF_YANG_SMIV2_NS, &exist, &oidstr) < 0) ||
(yang_extension_value_opt(yn, "smiv2:oid", &exist, &oidstr) < 0) ||
(exist == 0) ||
(oidstr == NULL)) {
return 0;
@ -495,8 +544,9 @@ type_yang2asn1(yang_stmt *ys,
yang_stmt *yrp;
char *display_hint = NULL;
yrp = yang_parent_get(yrestype);
if (yang_extension_value(yrp, "display-hint", IETF_YANG_SMIV2_NS, NULL, &display_hint) < 0)
if (yang_extension_value_opt(yrp, "smiv2:display-hint", NULL, &display_hint) < 0)
goto done;
/* RFC2578/2579 but maybe all strings with display-hint should use this, eg exist>0? */
if (display_hint &&
(strcmp(display_hint, "255a")==0 ||

View file

@ -86,6 +86,7 @@ int oid_append(const oid *objid0, size_t *objid0len, const oid *objid1, size_
int oid_cbuf(cbuf *cb, const oid *objid, size_t objidlen);
int oid_print(FILE *f, const oid *objid, size_t objidlen);
int snmp_yang_type_get(yang_stmt *ys, yang_stmt **yrefp, char **origtypep, yang_stmt **yrestypep, char **restypep);
int yang_extension_value_opt(yang_stmt *ys, char *id, int *exist, char **value);
int yangext_oid_get(yang_stmt *yn, oid *objid, size_t *objidlen, char **objidstr);
int yangext_is_oid_exist(yang_stmt *yn);
int snmp_access_str2int(char *modes_str);

View file

@ -127,7 +127,7 @@ mibyang_leaf_register(clicon_handle h,
/* Check if already registered */
if (clixon_snmp_api_oid_find(oid1, oid1len) == 1)
goto ok;
if (yang_extension_value(ys, "max-access", IETF_YANG_SMIV2_NS, NULL, &modes_str) < 0)
if (yang_extension_value_opt(ys, "smiv2:max-access", NULL, &modes_str) < 0)
goto done;
/* Only for sanity check of types initially to fail early */
if (type_yang2asn1(ys, NULL, 0) < 0)
@ -141,9 +141,8 @@ mibyang_leaf_register(clicon_handle h,
/* SMI default value, How is this different from yang defaults?
*/
if (yang_extension_value(ys, "defval", IETF_YANG_SMIV2_NS, NULL, &default_str) < 0)
if (yang_extension_value_opt(ys, "smiv2:defval", NULL, &default_str) < 0)
goto done;
name = yang_argument_get(ys);
/* Stateless function, just returns ptr */
if ((handler = netsnmp_create_handler(name, clixon_snmp_scalar_handler)) == NULL){

View file

@ -3734,6 +3734,7 @@ yang_anydata_add(yang_stmt *yp,
* }
* @endcode
* @see ys_populate_unknown Called when parsing YANG
* XXX consider optimizing, the call to yang_find_prefix_by_namespace may be slow
*/
int
yang_extension_value(yang_stmt *ys,
@ -3766,6 +3767,7 @@ yang_extension_value(yang_stmt *ys,
continue;
if ((ymod = ys_module(yext)) == NULL)
continue;
/* XXX this is slow */
if ((ret = yang_find_prefix_by_namespace(ymod, ns, &prefix)) < 0)
goto done;
if (ret == 0) /* not found (this may happen in augment and maybe should be treated otherwise) */