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 *****
- Empty yang type. Relaxed yang types for unions, eg two strings with different length.
Dec 2016: Dual license: both GPLv3 and APLv2
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"
* arg = "/interfaces/interface/%s/type"
* op: OP_MERGE
* @see cli_callback_xmlkeyfmt_generate where arg is generated
* @see cli_callback_generate where arg is generated
*/
static int
cli_dbxml(clicon_handle h,
@ -508,17 +508,20 @@ cli_dbxml(clicon_handle h,
char *xkfmt; /* xml key format */
char *xk = NULL; /* xml key */
cg_var *cval;
char *val = NULL;
int len;
xkfmt = cv_string_get(arg);
if (xmlkeyfmt2key(xkfmt, cvv, &xk) < 0)
goto done;
cval = cvec_i(cvv, cvec_len(cvv)-1);
if ((val = cv2str_dup(cval)) == NULL){
clicon_err(OE_UNIX, errno, "cv2str_dup");
goto done;
len = cvec_len(cvv);
if (len > 1){
cval = cvec_i(cvv, len-1);
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;
if (clicon_autocommit(h)) {
if (clicon_rpc_commit(h, "candidate", "running", 0, 0) < 0)

View file

@ -72,104 +72,31 @@
/*=====================================================================
* YANG generate CLI
*=====================================================================*/
#if 0 /* examples/ntp */
ntp("Network Time Protocol"),cli_set("ntp");{
logging("Configure NTP message logging"),cli_set("ntp.logging");{
status (<status:bool>),cli_set("ntp.logging $status:bool");
}
server("Configure NTP Server") (<ipv4addr:ipv4addr>("IPv4 address of peer")),cli_set("ntp.server[] $!ipv4addr:ipv4addr");
}
#endif
#if 0 /* examples/datamodel */
WITH COMPLETION:
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;
/*
This is an example yang module:
module m {
container x {
list m1 {
key "a";
leaf a {
type string;
}
leaf b {
type string;
}
}
return len;
}
}
/*! Print max value of a CLIgen variable type as string
*
* The string should be freed after use.
* @param[in] type CLIgen variable type
* @retval str Malloced string containing value. Should be freed after use.
* @see cvtype_max2str
*/
static char *
cvtype_max2str_dup(enum cv_type type)
You can see which CLISPEC it generates via clixon_cli -D 1:
Jan 2 11:17:58: yang2cli: buf
} x,cli_set("/x");{
m1 (<a:string>|<a:string expand_dbvar("candidate /x/m1/%s/a")>),cli_set("/x/m1/%s");
{
int len;
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 */
b (<b:string>|<b:string expand_dbvar("candidate /x/m1/%s/b")>),cli_set("/x/m1/%s/b");
}
}
*/
/*! Create cligen variable expand entry with xmlkey format string as argument
* @param[in] h clicon handle

View file

@ -377,6 +377,9 @@ main(int argc, char **argv)
/* Join rest of argv to a single command */
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
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'
* 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] 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] arg Argument given at the callback "<db> <xmlkeyfmt>"
* @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__);
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){
clicon_err(OE_PLUGIN, errno, "clicon_strsplit");
goto done;

View file

@ -170,7 +170,8 @@ Q: How do you 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.
Example:
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
3. string: name of database to change (eg "running")
4. string: key
5. string: value
5. string: value (can be NULL)
*/
CLICON_MSG_XMLPUT, /* Send database entries as XML to backend daemon
1. uint32: operation: LV_SET/LV_DELETE

View file

@ -200,7 +200,7 @@ clicon_rpc_change(clicon_handle h,
op,
key,
val,
strlen(val)+1,
val?strlen(val)+1:0,
__FUNCTION__)) == NULL)
goto done;
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);
p = 0;
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){
clicon_err(OE_PROTO, errno, "%s: chunk", __FUNCTION__);
return NULL;
@ -221,8 +223,10 @@ clicon_msg_change_encode(char *db,
p += strlen(db)+1;
strncpy(msg->op_body+p, key, len-p-hdrlen);
p += strlen(key)+1;
memcpy(msg->op_body+p, str, str_len);
p += str_len;
if (str_len){
memcpy(msg->op_body+p, str, str_len);
p += str_len;
}
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[out] xk XML key, eg /aaa/17. Free after use
* @note first and last elements of cvv are not used,..
* @see cli_dbxml where this function is called
*/
int
xmlkeyfmt2key(char *xkfmt,
@ -247,7 +248,7 @@ xmlkeyfmt2key(char *xkfmt,
j,
cvec_len(cvv),
cv_string_get(cvec_i(cvv, 0)));
// goto done;
goto done;
}
#endif
if ((cb = cbuf_new()) == NULL){
@ -1689,7 +1690,7 @@ xmldb_put_xkey_local(clicon_handle h,
case OP_MERGE:
case OP_REPLACE:
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;
}
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 *****

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 *****

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 *****

View file

@ -104,7 +104,7 @@ static const struct map_str2int ytmap[] = {
{"uint16", CGV_UINT16},
{"uint32", CGV_UINT32},
{"uint64", CGV_UINT64},
{"union", CGV_VOID}, /* Is replaced by actual type */
{"union", CGV_REST}, /* Is replaced by actual type */
{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__);
goto done;
}
/* XXX: here we seem to have some problems if type is union */
type = ytype_id(ytype);
if (origtype)
*origtype = type;