Empty yang type. Relaxed yang types for unions, eg two strings with different length.

This commit is contained in:
Olof hagsand 2017-01-09 21:26:50 +01:00
parent bc2b606167
commit 319e7707d8
14 changed files with 64 additions and 113 deletions

View file

@ -29,6 +29,8 @@
# #
# ***** END LICENSE BLOCK ***** # ***** END LICENSE BLOCK *****
- Empty yang type. Relaxed yang types for unions, eg two strings with different length.
Dec 2016: Dual license: both GPLv3 and APLv2 Dec 2016: Dual license: both GPLv3 and APLv2
Feb 2016: Forked new clixon repository from clicon Feb 2016: Forked new clixon repository from clicon

View file

@ -495,7 +495,7 @@ compare_dbs(clicon_handle h, cvec *cvv, cg_var *arg)
* cvv[2] = "bgp" * cvv[2] = "bgp"
* arg = "/interfaces/interface/%s/type" * arg = "/interfaces/interface/%s/type"
* op: OP_MERGE * op: OP_MERGE
* @see cli_callback_xmlkeyfmt_generate where arg is generated * @see cli_callback_generate where arg is generated
*/ */
static int static int
cli_dbxml(clicon_handle h, cli_dbxml(clicon_handle h,
@ -508,17 +508,20 @@ cli_dbxml(clicon_handle h,
char *xkfmt; /* xml key format */ char *xkfmt; /* xml key format */
char *xk = NULL; /* xml key */ char *xk = NULL; /* xml key */
cg_var *cval; cg_var *cval;
char *val = NULL; int len;
xkfmt = cv_string_get(arg); xkfmt = cv_string_get(arg);
if (xmlkeyfmt2key(xkfmt, cvv, &xk) < 0) if (xmlkeyfmt2key(xkfmt, cvv, &xk) < 0)
goto done; goto done;
cval = cvec_i(cvv, cvec_len(cvv)-1); len = cvec_len(cvv);
if ((val = cv2str_dup(cval)) == NULL){ if (len > 1){
clicon_err(OE_UNIX, errno, "cv2str_dup"); cval = cvec_i(cvv, len-1);
goto done; if ((str = cv2str_dup(cval)) == NULL){
clicon_err(OE_UNIX, errno, "cv2str_dup");
goto done;
}
} }
if (clicon_rpc_change(h, "candidate", op, xk, val) < 0) if (clicon_rpc_change(h, "candidate", op, xk, str) < 0)
goto done; goto done;
if (clicon_autocommit(h)) { if (clicon_autocommit(h)) {
if (clicon_rpc_commit(h, "candidate", "running", 0, 0) < 0) if (clicon_rpc_commit(h, "candidate", "running", 0, 0) < 0)

View file

@ -72,104 +72,31 @@
/*===================================================================== /*=====================================================================
* YANG generate CLI * YANG generate CLI
*=====================================================================*/ *=====================================================================*/
#if 0 /* examples/ntp */ /*
ntp("Network Time Protocol"),cli_set("ntp");{ This is an example yang module:
logging("Configure NTP message logging"),cli_set("ntp.logging");{ module m {
status (<status:bool>),cli_set("ntp.logging $status:bool"); container x {
} list m1 {
server("Configure NTP Server") (<ipv4addr:ipv4addr>("IPv4 address of peer")),cli_set("ntp.server[] $!ipv4addr:ipv4addr"); key "a";
} leaf a {
#endif type string;
#if 0 /* examples/datamodel */ }
leaf b {
WITH COMPLETION: type string;
a (<x:number>|<x:number expand_dbvar_auto("candidate a[] $!x")>),cli_set("a[] $!x");{ }
b,cli_set("a[].b $!x");{
y (<y:string>|<y:string expand_dbvar_auto("candidate a[].b $!x $y")>),cli_set("a[].b $!x $y");
}
z (<z:string>|<z:string expand_dbvar_auto("candidate a[] $!x $z")>),cli_set("a[] $!x $z");
}
#endif
#ifndef HAVE_CLIGEN_MAX2STR /* XXX cligen 3.6 feature */
/*! Print max value of a CLIgen variable type as string
* @param[in] type CLIgen variable type
* @param[out] str Max value printed in this string
* @param[in] size Length of 'str'
* @retval len How many bytes printed
* @see cvtype_max2str_dup
* You can use str=NULL to get the expected length.
* The number of (potentially if str=NULL) written bytes is returned.
*/
static int
cvtype_max2str(enum cv_type type, char *str, size_t size)
{
int len = 0;
switch (type){
case CGV_INT8:
len = snprintf(str, size, "%" PRId8, INT8_MAX);
break;
case CGV_INT16:
len = snprintf(str, size, "%" PRId16, INT16_MAX);
break;
case CGV_INT32:
len = snprintf(str, size, "%" PRId32, INT32_MAX);
break;
case CGV_INT64:
len = snprintf(str, size, "%" PRId64, INT64_MAX);
break;
case CGV_UINT8:
len = snprintf(str, size, "%" PRIu8, UINT8_MAX);
break;
case CGV_UINT16:
len = snprintf(str, size, "%" PRIu16, UINT16_MAX);
break;
case CGV_UINT32:
len = snprintf(str, size, "%" PRIu32, UINT32_MAX);
break;
case CGV_UINT64:
len = snprintf(str, size, "%" PRIu64, UINT64_MAX);
break;
case CGV_DEC64:
len = snprintf(str, size, "%" PRId64 ".0", INT64_MAX);
break;
case CGV_BOOL:
len = snprintf(str, size, "true");
break;
default:
break;
} }
return len; }
} }
/*! Print max value of a CLIgen variable type as string You can see which CLISPEC it generates via clixon_cli -D 1:
* Jan 2 11:17:58: yang2cli: buf
* The string should be freed after use. } x,cli_set("/x");{
* @param[in] type CLIgen variable type m1 (<a:string>|<a:string expand_dbvar("candidate /x/m1/%s/a")>),cli_set("/x/m1/%s");
* @retval str Malloced string containing value. Should be freed after use.
* @see cvtype_max2str
*/
static char *
cvtype_max2str_dup(enum cv_type type)
{ {
int len; b (<b:string>|<b:string expand_dbvar("candidate /x/m1/%s/b")>),cli_set("/x/m1/%s/b");
char *str; }
}
if ((len = cvtype_max2str(type, NULL, 0)) < 0) */
return NULL;
if ((str = (char *)malloc (len+1)) == NULL)
return NULL;
memset (str, '\0', len+1);
if ((cvtype_max2str(type, str, len+1)) < 0){
free(str);
return NULL;
}
return str;
}
#endif /* HAVE_CLIGEN_MAX2STR */
/*! Create cligen variable expand entry with xmlkey format string as argument /*! Create cligen variable expand entry with xmlkey format string as argument
* @param[in] h clicon handle * @param[in] h clicon handle

View file

@ -377,6 +377,9 @@ main(int argc, char **argv)
/* Join rest of argv to a single command */ /* Join rest of argv to a single command */
restarg = clicon_strjoin(argc, argv, " ", __FUNCTION__); restarg = clicon_strjoin(argc, argv, " ", __FUNCTION__);
/* If several cligen object variables match same preference, select first */
cligen_match_cgvar_same(1);
/* Call start function in all plugins before we go interactive /* Call start function in all plugins before we go interactive
Pass all args after the standard options to plugin_start Pass all args after the standard options to plugin_start
*/ */

View file

@ -81,9 +81,9 @@ static int xml2csv(FILE *f, cxobj *x, cvec *cvv);
* Returns an expand-type list of commands as used by cligen 'expand' * Returns an expand-type list of commands as used by cligen 'expand'
* functionality. * functionality.
* *
* Assume callback given in a cligen spec: a <x:int expand_dbvar_auto("arg") * Assume callback given in a cligen spec: a <x:int expand_dbvar("arg")
* @param[in] h clicon handle * @param[in] h clicon handle
* @param[in] name Name of this function (eg "expand_dbvar-auto") * @param[in] name Name of this function (eg "expand_dbvar")
* @param[in] cvv The command so far. Eg: cvec [0]:"a 5 b"; [1]: x=5; * @param[in] cvv The command so far. Eg: cvec [0]:"a 5 b"; [1]: x=5;
* @param[in] arg Argument given at the callback "<db> <xmlkeyfmt>" * @param[in] arg Argument given at the callback "<db> <xmlkeyfmt>"
* @param[out] len len of return commands & helptxt * @param[out] len len of return commands & helptxt
@ -121,7 +121,7 @@ expand_dbvar(void *h,
clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__); clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__);
goto done; goto done;
} }
/* In the example, str = "candidate a[].b[] $!x $!y" */ /* In the example, str = "candidate /x/m1/%s/b" */
if ((vec = clicon_strsplit(str, " ", &nvec, __FUNCTION__)) == NULL){ if ((vec = clicon_strsplit(str, " ", &nvec, __FUNCTION__)) == NULL){
clicon_err(OE_PLUGIN, errno, "clicon_strsplit"); clicon_err(OE_PLUGIN, errno, "clicon_strsplit");
goto done; goto done;

View file

@ -170,7 +170,8 @@ Q: How do you use netconf?
-------------------------- --------------------------
As an alternative to cli configuration, you can use netconf As an alternative to cli configuration, you can use netconf
directly. Easiesty is to just pipe netconf commands to the directly. Easiest is to just pipe netconf commands to the
clixon_netconf application. clixon_netconf application.
Example: Example:
echo "<rpc><get-config><source><candidate/></source><configuration/></get-config></rpc>]]>]]>" | clixon_netconf -f /usr/local/etc/routing.conf echo "<rpc><get-config><source><candidate/></source><configuration/></get-config></rpc>]]>]]>" | clixon_netconf -f /usr/local/etc/routing.conf

View file

@ -63,7 +63,7 @@ enum clicon_msg_type{
2. uint32: length of value string 2. uint32: length of value string
3. string: name of database to change (eg "running") 3. string: name of database to change (eg "running")
4. string: key 4. string: key
5. string: value 5. string: value (can be NULL)
*/ */
CLICON_MSG_XMLPUT, /* Send database entries as XML to backend daemon CLICON_MSG_XMLPUT, /* Send database entries as XML to backend daemon
1. uint32: operation: LV_SET/LV_DELETE 1. uint32: operation: LV_SET/LV_DELETE

View file

@ -200,7 +200,7 @@ clicon_rpc_change(clicon_handle h,
op, op,
key, key,
val, val,
strlen(val)+1, val?strlen(val)+1:0,
__FUNCTION__)) == NULL) __FUNCTION__)) == NULL)
goto done; goto done;
if (clicon_rpc_msg(h, msg, NULL, NULL, NULL, __FUNCTION__) < 0) if (clicon_rpc_msg(h, msg, NULL, NULL, NULL, __FUNCTION__) < 0)

View file

@ -199,7 +199,9 @@ clicon_msg_change_encode(char *db,
op, str_len, db, key); op, str_len, db, key);
p = 0; p = 0;
len = sizeof(*msg) + 2*sizeof(uint32_t) + strlen(db) + 1 + len = sizeof(*msg) + 2*sizeof(uint32_t) + strlen(db) + 1 +
strlen(key) + 1 + str_len; strlen(key) + str_len;
if (str_len)
len++; /* if str not null add end of string */
if ((msg = (struct clicon_msg *)chunk(len, label)) == NULL){ if ((msg = (struct clicon_msg *)chunk(len, label)) == NULL){
clicon_err(OE_PROTO, errno, "%s: chunk", __FUNCTION__); clicon_err(OE_PROTO, errno, "%s: chunk", __FUNCTION__);
return NULL; return NULL;
@ -221,8 +223,10 @@ clicon_msg_change_encode(char *db,
p += strlen(db)+1; p += strlen(db)+1;
strncpy(msg->op_body+p, key, len-p-hdrlen); strncpy(msg->op_body+p, key, len-p-hdrlen);
p += strlen(key)+1; p += strlen(key)+1;
memcpy(msg->op_body+p, str, str_len); if (str_len){
p += str_len; memcpy(msg->op_body+p, str, str_len);
p += str_len;
}
return msg; return msg;
} }

View file

@ -221,6 +221,7 @@ yang2xmlkeyfmt(yang_stmt *ys,
* @param[in] cvv cligen variable vector, one for every wildchar in xkfmt * @param[in] cvv cligen variable vector, one for every wildchar in xkfmt
* @param[out] xk XML key, eg /aaa/17. Free after use * @param[out] xk XML key, eg /aaa/17. Free after use
* @note first and last elements of cvv are not used,.. * @note first and last elements of cvv are not used,..
* @see cli_dbxml where this function is called
*/ */
int int
xmlkeyfmt2key(char *xkfmt, xmlkeyfmt2key(char *xkfmt,
@ -247,7 +248,7 @@ xmlkeyfmt2key(char *xkfmt,
j, j,
cvec_len(cvv), cvec_len(cvv),
cv_string_get(cvec_i(cvv, 0))); cv_string_get(cvec_i(cvv, 0)));
// goto done; goto done;
} }
#endif #endif
if ((cb = cbuf_new()) == NULL){ if ((cb = cbuf_new()) == NULL){
@ -1689,7 +1690,7 @@ xmldb_put_xkey_local(clicon_handle h,
case OP_MERGE: case OP_MERGE:
case OP_REPLACE: case OP_REPLACE:
if (y->ys_keyword == Y_LEAF || y->ys_keyword == Y_LEAF_LIST){ if (y->ys_keyword == Y_LEAF || y->ys_keyword == Y_LEAF_LIST){
if (db_set(filename, xk, val, strlen(val)+1) < 0) if (db_set(filename, xk, val, val?strlen(val)+1:0) < 0)
goto done; goto done;
} }
else else

View file

@ -1,4 +1,7 @@
/* /*
* Yang 1.0 parser according to RFC6020.
* It is hopefully useful but not complete
* RFC7950 defines Yang version 1.1
* *
***** BEGIN LICENSE BLOCK ***** ***** BEGIN LICENSE BLOCK *****

View file

@ -1,4 +1,7 @@
/* /*
* Yang 1.0 parser according to RFC6020.
* It is hopefully useful but not complete
* RFC7950 defines Yang version 1.1
* *
***** BEGIN LICENSE BLOCK ***** ***** BEGIN LICENSE BLOCK *****

View file

@ -1,4 +1,7 @@
/* /*
* Yang 1.0 parser according to RFC6020.
* It is hopefully useful but not complete
* RFC7950 defines Yang version 1.1
* *
***** BEGIN LICENSE BLOCK ***** ***** BEGIN LICENSE BLOCK *****

View file

@ -104,7 +104,7 @@ static const struct map_str2int ytmap[] = {
{"uint16", CGV_UINT16}, {"uint16", CGV_UINT16},
{"uint32", CGV_UINT32}, {"uint32", CGV_UINT32},
{"uint64", CGV_UINT64}, {"uint64", CGV_UINT64},
{"union", CGV_VOID}, /* Is replaced by actual type */ {"union", CGV_REST}, /* Is replaced by actual type */
{NULL, -1} {NULL, -1}
}; };
@ -912,6 +912,7 @@ yang_type_get(yang_stmt *ys,
clicon_err(OE_DB, 0, "%s: mandatory type object is not found", __FUNCTION__); clicon_err(OE_DB, 0, "%s: mandatory type object is not found", __FUNCTION__);
goto done; goto done;
} }
/* XXX: here we seem to have some problems if type is union */
type = ytype_id(ytype); type = ytype_id(ytype);
if (origtype) if (origtype)
*origtype = type; *origtype = type;