From 056b5c97dd9b788d4b65b07034a3a8587aa3dde7 Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Fri, 8 Dec 2017 19:37:09 +0100 Subject: [PATCH] experimental netconf yang spec --- CHANGELOG.md | 2 + apps/backend/backend_main.c | 11 +--- apps/cli/cli_main.c | 13 ++-- apps/netconf/netconf_main.c | 24 ++++---- apps/netconf/netconf_plugin.c | 30 +++++++--- apps/netconf/netconf_rpc.c | 109 ++++++++++++++++++++++------------ apps/restconf/restconf_main.c | 2 +- lib/clixon/clixon_options.h | 3 + lib/clixon/clixon_yang.h | 3 +- lib/src/clixon_options.c | 42 +++++++++++-- lib/src/clixon_xml_parse.y | 2 +- lib/src/clixon_yang.c | 44 +++++++++----- lib/src/clixon_yang_parse.y | 24 +++++--- test/test_netconf.sh | 85 +++++++++++++------------- test/test_yang.sh | 2 +- yang/Makefile.in | 1 + 16 files changed, 250 insertions(+), 147 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84a35ece..5b3c9516 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## 3.4.0 (Upcoming) +* experimental netconf yang rpc + * datastore/keyvalue/Makefile is left behind on make distclean. Fixed by conditional configure. Thanks renato@netgate.com. * Better semantic versioning, eg MAJOR/MINOR/PATCH, where increment in PATCH does not change API. diff --git a/apps/backend/backend_main.c b/apps/backend/backend_main.c index e7be22f5..022bcb81 100644 --- a/apps/backend/backend_main.c +++ b/apps/backend/backend_main.c @@ -74,9 +74,9 @@ /* Command line options to be passed to getopt(3) */ #ifdef BACKEND_STARTUP_COMPAT -#define BACKEND_OPTS "hD:f:d:b:Fzu:P:1s:c:IRCrg:py:x:" /* substitute s: for IRCc:r */ +#define BACKEND_OPTS "hD:f:d:b:Fzu:P:1s:c:IRCrg:y:x:" /* substitute s: for IRCc:r */ #else -#define BACKEND_OPTS "hD:f:d:b:Fzu:P:1s:c:g:py:x:" /* substitute s: for IRCc:r */ +#define BACKEND_OPTS "hD:f:d:b:Fzu:P:1s:c:g:y:x:" /* substitute s: for IRCc:r */ #endif /*! Terminate. Cannot use h after this */ @@ -148,7 +148,6 @@ usage(char *argv0, clicon_handle h) " -C\t\tCall plugin_reset() in plugins to reset system state in candidate db (use with -I)\n" " -r\t\tReload running database\n" #endif /* BACKEND_STARTUP_COMPAT */ - " -p \t\tPrint database yang specification\n" " -g \tClient membership required to this group (default: %s)\n" " -y \tOverride yang spec file (dont include .yang suffix)\n" " -x \tXMLDB plugin\n", @@ -611,7 +610,6 @@ main(int argc, char **argv) struct stat st; clicon_handle h; int help = 0; - int printspec = 0; int pid; char *pidfile; char *sock; @@ -736,9 +734,6 @@ main(int argc, char **argv) case 'g': /* config socket group */ clicon_option_str_set(h, "CLICON_SOCK_GROUP", optarg); break; - case 'p' : /* Print spec */ - printspec++; - break; case 'y' :{ /* Override yang module or absolute filename */ clicon_option_str_set(h, "CLICON_YANG_MODULE_MAIN", optarg); break; @@ -823,7 +818,7 @@ main(int argc, char **argv) if (xmldb_connect(h) < 0) goto done; /* Parse db spec file */ - if (yang_spec_main(h, stdout, printspec) < 0) + if (yang_spec_main(h) == NULL) goto done; /* Set options: database dir and yangspec (could be hidden in connect?)*/ diff --git a/apps/cli/cli_main.c b/apps/cli/cli_main.c index f03c5284..25343e99 100644 --- a/apps/cli/cli_main.c +++ b/apps/cli/cli_main.c @@ -242,9 +242,9 @@ main(int argc, char **argv) int logdst = CLICON_LOG_STDERR; char *restarg = NULL; /* what remains after options */ int dump_configfile_xml = 0; - + yang_spec *yspec; + /* Defaults */ - /* In the startup, logs to stderr & debug flag set later */ clicon_log_init(__PROGRAM__, LOG_INFO, logdst); /* Initiate CLICON handle */ @@ -397,20 +397,17 @@ main(int argc, char **argv) cv_exclude_keys(clicon_cli_varonly(h)); /* Parse db specification as cli*/ - if (yang_spec_main(h, stdout, printspec) < 0) + if ((yspec = yang_spec_main(h)) == NULL) goto done; + if (printspec) + yang_print(stdout, (yang_node*)yspec); /* Create tree generated from dataspec. If no other trees exists, this is * the only one. */ if (clicon_cli_genmodel(h)){ - yang_spec *yspec; /* yang spec */ parse_tree pt = {0,}; /* cli parse tree */ - if ((yspec = clicon_dbspec_yang(h)) == NULL){ - clicon_err(OE_FATAL, 0, "No YANG DB_SPEC"); - goto done; - } /* Create cli command tree from dbspec */ if (yang2cli(h, yspec, &pt, clicon_cli_genmodel_type(h)) < 0) goto done; diff --git a/apps/netconf/netconf_main.c b/apps/netconf/netconf_main.c index b7bbbeb9..3326c69d 100644 --- a/apps/netconf/netconf_main.c +++ b/apps/netconf/netconf_main.c @@ -98,7 +98,7 @@ process_incoming_packet(clicon_handle h, } str = str0; /* Parse incoming XML message */ - if (clicon_xml_parse_str(str, NULL, &xreq) < 0){ + if (clicon_xml_parse_str(str, NULL, &xreq) < 0){ if ((cbret = cbuf_new()) == NULL){ cprintf(cbret, "" "operation-failed" @@ -114,9 +114,8 @@ process_incoming_packet(clicon_handle h, goto done; } free(str0); - if ((xrpc=xpath_first(xreq, "//rpc")) != NULL){ + if ((xrpc=xpath_first(xreq, "//rpc")) != NULL) isrpc++; - } else if (xpath_first(xreq, "//hello") != NULL) ; @@ -215,9 +214,10 @@ netconf_input_cb(int s, buf[i], &xml_state)) { /* OK, we have an xml string from a client */ - if (process_incoming_packet(h, cb) < 0){ + /* Remove trailer */ + *(((char*)cbuf_get(cb)) + cbuf_len(cb) - strlen("]]>]]>")) = '\0'; + if (process_incoming_packet(h, cb) < 0) goto done; - } if (cc_closed) break; cbuf_reset(cb); @@ -268,7 +268,6 @@ netconf_terminate(clicon_handle h) { yang_spec *yspec; - clicon_rpc_close_session(h); if ((yspec = clicon_dbspec_yang(h)) != NULL) yspec_free(yspec); @@ -302,7 +301,8 @@ usage(clicon_handle h, } int -main(int argc, char **argv) +main(int argc, + char **argv) { char c; char *tmp; @@ -337,7 +337,6 @@ main(int argc, char **argv) use_syslog = 1; break; } - /* * Logs, error and debug to stderr or syslog, set debug level */ @@ -379,13 +378,18 @@ main(int argc, char **argv) argv += optind; /* Parse yang database spec file */ - if (yang_spec_main(h, stdout, 0) < 0) + if (yang_spec_main(h) == NULL) + goto done; + + /* Parse netconf yang spec file */ + if (yang_spec_netconf(h) == NULL) goto done; /* Initialize plugins group */ if (netconf_plugin_load(h) < 0) - return -1; + goto done; + /* Call start function is all plugins before we go interactive */ tmp = *(argv-1); *(argv-1) = argv0; diff --git a/apps/netconf/netconf_plugin.c b/apps/netconf/netconf_plugin.c index 64aa8e87..205d8124 100644 --- a/apps/netconf/netconf_plugin.c +++ b/apps/netconf/netconf_plugin.c @@ -196,7 +196,6 @@ catch: } return -1; } - /*! See if there is any callback registered for this tag * @@ -215,7 +214,7 @@ netconf_plugin_callbacks(clicon_handle h, { int retval = -1; netconf_reg_t *nreg; - yang_spec *yspec; + yang_spec *yspec = NULL; /* application yspec */ yang_stmt *yrpc; yang_stmt *yinput; yang_stmt *youtput; @@ -234,19 +233,32 @@ netconf_plugin_callbacks(clicon_handle h, nreg = NEXTQ(netconf_reg_t *, nreg); } while (nreg != deps); } - if ((yspec = clicon_dbspec_yang(h)) == NULL){ - clicon_err(OE_YANG, ENOENT, "No yang spec"); - goto done; - } + /* First check system / netconf RPC:s */ if ((cb = cbuf_new()) == NULL){ clicon_err(OE_UNIX, 0, "cbuf_new"); goto done; } /* create absolute path */ - cprintf(cb, "/%s:%s", xml_namespace(xn), xml_name(xn)); + if (xml_namespace(xn)) + cprintf(cb, "/%s:%s", xml_namespace(xn), xml_name(xn)); + else + cprintf(cb, "/nc:%s", xml_name(xn)); /* Hardcoded for netconf */ /* Find yang rpc statement, return yang rpc statement if found */ - if (yang_abs_schema_nodeid(yspec, cbuf_get(cb), &yrpc) < 0) - goto done; + if (yrpc == NULL){ + /* Then check application RPC */ + if ((yspec = clicon_dbspec_yang(h)) == NULL){ + clicon_err(OE_YANG, ENOENT, "No yang spec"); + goto done; + } + cbuf_reset(cb); + if (xml_namespace(xn)) + cprintf(cb, "/%s:%s", xml_namespace(xn), xml_name(xn)); + else + cprintf(cb, "/%s", xml_name(xn)); /* XXX not accepdted by below */ + /* Find yang rpc statement, return yang rpc statement if found */ + if (yang_abs_schema_nodeid(yspec, cbuf_get(cb), &yrpc) < 0) + goto done; + } /* Check if found */ if (yrpc != NULL){ if ((yinput = yang_find((yang_node*)yrpc, Y_INPUT, NULL)) != NULL){ diff --git a/apps/netconf/netconf_rpc.c b/apps/netconf/netconf_rpc.c index b002e0fd..7e2d86ba 100644 --- a/apps/netconf/netconf_rpc.c +++ b/apps/netconf/netconf_rpc.c @@ -856,51 +856,85 @@ netconf_create_subscription(clicon_handle h, * @param[in] h clicon handle * @param[in] xn Sub-tree (under xorig) at ... level. * @param[out] xret Return XML, error or OK + * @retval 0 OK, can also be netconf error + * @retval -1 Error, fatal */ int netconf_rpc_dispatch(clicon_handle h, cxobj *xn, cxobj **xret) { + int retval = -1; cxobj *xe; - int ret = 0; + yang_spec *yspec = NULL; + /* Check incoming RPC against system / netconf RPC:s */ + if ((yspec = clicon_netconf_yang(h)) == NULL){ + clicon_err(OE_YANG, ENOENT, "No netconf yang spec"); + goto done; + } xe = NULL; while ((xe = xml_child_each(xn, xe, CX_ELMNT)) != NULL) { - if (strcmp(xml_name(xe), "get-config") == 0) - return netconf_get_config(h, xe, xret); - else if (strcmp(xml_name(xe), "edit-config") == 0) - return netconf_edit_config(h, xe, xret); - else if (strcmp(xml_name(xe), "copy-config") == 0) - return netconf_copy_config(h, xe, xret); - else if (strcmp(xml_name(xe), "delete-config") == 0) - return netconf_delete_config(h, xe, xret); - else if (strcmp(xml_name(xe), "lock") == 0) - return netconf_lock(h, xe, xret); - else if (strcmp(xml_name(xe), "unlock") == 0) - return netconf_unlock(h, xe, xret); - else if (strcmp(xml_name(xe), "get") == 0) - return netconf_get(h, xe, xret); - else if (strcmp(xml_name(xe), "close-session") == 0) - return netconf_close_session(h, xe, xret); - else if (strcmp(xml_name(xe), "kill-session") == 0) - return netconf_kill_session(h, xe, xret); + if (strcmp(xml_name(xe), "get-config") == 0){ + if (netconf_get_config(h, xe, xret) < 0) + goto done; + } + else if (strcmp(xml_name(xe), "edit-config") == 0){ + if (netconf_edit_config(h, xe, xret) < 0) + goto done; + } + else if (strcmp(xml_name(xe), "copy-config") == 0){ + if (netconf_copy_config(h, xe, xret) < 0) + goto done; + } + else if (strcmp(xml_name(xe), "delete-config") == 0){ + if (netconf_delete_config(h, xe, xret) < 0) + goto done; + } + else if (strcmp(xml_name(xe), "lock") == 0) { + if (netconf_lock(h, xe, xret) < 0) + goto done; + } + else if (strcmp(xml_name(xe), "unlock") == 0){ + if (netconf_unlock(h, xe, xret) < 0) + goto done; + } + else if (strcmp(xml_name(xe), "get") == 0){ + if (netconf_get(h, xe, xret) < 0) + goto done; + } + else if (strcmp(xml_name(xe), "close-session") == 0){ + if (netconf_close_session(h, xe, xret) < 0) + goto done; + } + else if (strcmp(xml_name(xe), "kill-session") == 0) { + if (netconf_kill_session(h, xe, xret) < 0) + goto done; + } /* Validate capability :validate */ - else if (strcmp(xml_name(xe), "validate") == 0) - return netconf_validate(h, xe, xret); + else if (strcmp(xml_name(xe), "validate") == 0){ + if (netconf_validate(h, xe, xret) < 0) + goto done; + } /* Candidate configuration capability :candidate */ - else if (strcmp(xml_name(xe), "commit") == 0) - return netconf_commit(h, xe, xret); - else if (strcmp(xml_name(xe), "discard-changes") == 0) - return netconf_discard_changes(h, xe, xret); + else if (strcmp(xml_name(xe), "commit") == 0){ + if (netconf_commit(h, xe, xret) < 0) + goto done; + } + else if (strcmp(xml_name(xe), "discard-changes") == 0){ + if (netconf_discard_changes(h, xe, xret) < 0) + goto done; + } /* RFC 5277 :notification */ - else if (strcmp(xml_name(xe), "create-subscription") == 0) - return netconf_create_subscription(h, xe, xret); + else if (strcmp(xml_name(xe), "create-subscription") == 0){ + if (netconf_create_subscription(h, xe, xret) < 0) + goto done; + } /* Others */ - else{ - if ((ret = netconf_plugin_callbacks(h, xe, xret)) < 0) - return -1; - if (ret == 0){ /* not handled by callback */ + else { + if ((retval = netconf_plugin_callbacks(h, xe, xret)) < 0) + goto done; + if (retval == 0){ /* not handled by callback */ clicon_xml_parse(xret, NULL, "" "operation-failed" "rpc" @@ -908,10 +942,11 @@ netconf_rpc_dispatch(clicon_handle h, "%s" "Not recognized" "", xml_name(xe)); - return 0; - } - - } - } - return ret; + goto done; + } + } + } + retval = 0; + done: + return retval; } diff --git a/apps/restconf/restconf_main.c b/apps/restconf/restconf_main.c index 70201edd..8d2e899a 100644 --- a/apps/restconf/restconf_main.c +++ b/apps/restconf/restconf_main.c @@ -357,7 +357,7 @@ main(int argc, return -1; /* Parse yang database spec file */ - if (yang_spec_main(h, NULL, 0) < 0) + if (yang_spec_main(h) == NULL) goto done; if ((sockpath = clicon_option_str(h, "CLICON_RESTCONF_PATH")) == NULL){ diff --git a/lib/clixon/clixon_options.h b/lib/clixon/clixon_options.h index a94206a5..7ce66a19 100644 --- a/lib/clixon/clixon_options.h +++ b/lib/clixon/clixon_options.h @@ -167,6 +167,9 @@ int clicon_dbspec_yang_set(clicon_handle h, struct yang_spec *ys); char *clicon_dbspec_name(clicon_handle h); int clicon_dbspec_name_set(clicon_handle h, char *name); +yang_spec *clicon_netconf_yang(clicon_handle h); +int clicon_netconf_yang_set(clicon_handle h, struct yang_spec *ys); + plghndl_t clicon_xmldb_plugin_get(clicon_handle h); int clicon_xmldb_plugin_set(clicon_handle h, plghndl_t handle); diff --git a/lib/clixon/clixon_yang.h b/lib/clixon/clixon_yang.h index d62cfabe..1fdf88e0 100644 --- a/lib/clixon/clixon_yang.h +++ b/lib/clixon/clixon_yang.h @@ -223,7 +223,8 @@ cg_var *ys_parse(yang_stmt *ys, enum cv_type cvtype); int ys_parse_sub(yang_stmt *ys); int yang_mandatory(yang_stmt *ys); int yang_config(yang_stmt *ys); -int yang_spec_main(clicon_handle h, FILE *f, int printspec); +yang_spec *yang_spec_netconf(clicon_handle h); +yang_spec *yang_spec_main(clicon_handle h); cvec *yang_arg2cvec(yang_stmt *ys, char *delimi); int yang_key_match(yang_node *yn, char *name); diff --git a/lib/src/clixon_options.c b/lib/src/clixon_options.c index 89247bfa..fb912b3f 100644 --- a/lib/src/clixon_options.c +++ b/lib/src/clixon_options.c @@ -382,8 +382,6 @@ clicon_options_main(clicon_handle h) /* Read configfile */ if (clicon_option_readfile_xml(copt, configfile, yspec) < 0) goto done; - if (yspec) - yspec_free(yspec); } else { #ifdef CONFIG_COMPAT @@ -402,6 +400,9 @@ clicon_options_main(clicon_handle h) } retval = 0; done: + if (yspec) /* The clixon yang-spec is not used after this */ + yspec_free(yspec); + return retval; } @@ -704,7 +705,7 @@ clicon_quiet_mode_set(clicon_handle h, int val) return clicon_option_int_set(h, "CLICON_QUIET", val); } -/*! Get YANG specification +/*! Get YANG specification for application * Must use hash functions directly since they are not strings. */ yang_spec * @@ -719,7 +720,7 @@ clicon_dbspec_yang(clicon_handle h) return NULL; } -/*! Set yang database specification +/*! Set yang specification for application * ys must be a malloced pointer */ int @@ -736,6 +737,39 @@ clicon_dbspec_yang_set(clicon_handle h, return 0; } +/*! Get YANG NETCONF specification + * Must use hash functions directly since they are not strings. + */ +yang_spec * +clicon_netconf_yang(clicon_handle h) +{ + clicon_hash_t *cdat = clicon_data(h); + size_t len; + void *p; + + if ((p = hash_value(cdat, "netconf_yang", &len)) != NULL) + return *(yang_spec **)p; + return NULL; +} + +/*! Set yang netconf specification + * ys must be a malloced pointer + */ +int +clicon_netconf_yang_set(clicon_handle h, + struct yang_spec *ys) +{ + clicon_hash_t *cdat = clicon_data(h); + + /* It is the pointer to ys that should be copied by hash, + so we send a ptr to the ptr to indicate what to copy. + */ + if (hash_add(cdat, "netconf_yang", &ys, sizeof(ys)) == NULL) + return -1; + return 0; +} + + /*! Get dbspec name as read from spec. Can be used in CLI '@' syntax. * XXX: this we muśt change,... */ diff --git a/lib/src/clixon_xml_parse.y b/lib/src/clixon_xml_parse.y index c97d594e..f4eef6d4 100644 --- a/lib/src/clixon_xml_parse.y +++ b/lib/src/clixon_xml_parse.y @@ -136,7 +136,7 @@ xml_parse_qname(struct xml_parse_yacc_arg *ya, { int retval = -1; cxobj *x; - yang_stmt *y=NULL; /* yang node */ + yang_stmt *y = NULL; /* yang node */ cxobj *xp; /* xml parent */ xp = ya->ya_xparent; diff --git a/lib/src/clixon_yang.c b/lib/src/clixon_yang.c index 5e609d13..145cae44 100644 --- a/lib/src/clixon_yang.c +++ b/lib/src/clixon_yang.c @@ -1527,7 +1527,7 @@ yang_parse_recurse(clicon_handle h, if ((nr = yang_parse_find_match(h, yang_dir, module, fbuf)) < 0) goto done; if (nr == 0){ - clicon_err(OE_YANG, errno, "No matching %s yang files found (expected modulenameor absolute filename)", module); + clicon_err(OE_YANG, errno, "No matching %s yang files found (expected module name or absolute filename)", module); goto done; } } @@ -1820,7 +1820,6 @@ yang_abs_schema_nodeid(yang_spec *yspec, yang_stmt *ymod; char *id; char *prefix = NULL; - yang_stmt *yprefix; /* check absolute schema_nodeid */ @@ -2024,24 +2023,36 @@ yang_config(yang_stmt *ys) return 1; } -/*! Utility function for handling yang parsing and translation to key format +/*! Parse netconf yang spec, used by netconf client and as internal protocol */ +yang_spec * +yang_spec_netconf(clicon_handle h) +{ + yang_spec *yspec = NULL; + + if ((yspec = yspec_new()) == NULL) + goto done; + if (yang_parse(h, CLIXON_DATADIR, "ietf-netconf", NULL, yspec) < 0){ + yspec_free(yspec); yspec = NULL; + goto done; + } + clicon_netconf_yang_set(h, yspec); + done: + return yspec; +} + +/*! Read, parse and save application yang specification as option * @param h clicon handle * @param f file to print to (if printspec enabled) * @param printspec print database (YANG) specification as read from file */ -int -yang_spec_main(clicon_handle h, - FILE *f, - int printspec) +yang_spec* +yang_spec_main(clicon_handle h) { - yang_spec *yspec; + yang_spec *yspec = NULL; char *yang_dir; char *yang_module; char *yang_revision; - int retval = -1; - if ((yspec = yspec_new()) == NULL) - goto done; if ((yang_dir = clicon_yang_dir(h)) == NULL){ clicon_err(OE_FATAL, 0, "CLICON_YANG_DIR option not set"); goto done; @@ -2052,14 +2063,15 @@ yang_spec_main(clicon_handle h, goto done; } yang_revision = clicon_yang_module_revision(h); - if (yang_parse(h, yang_dir, yang_module, yang_revision, yspec) < 0) + if ((yspec = yspec_new()) == NULL) goto done; + if (yang_parse(h, yang_dir, yang_module, yang_revision, yspec) < 0){ + yspec_free(yspec); yspec = NULL; + goto done; + } clicon_dbspec_yang_set(h, yspec); - if (printspec) - yang_print(f, (yang_node*)yspec); - retval = 0; done: - return retval; + return yspec; } /*! Given a yang node, translate the argument string to a cv vector diff --git a/lib/src/clixon_yang_parse.y b/lib/src/clixon_yang_parse.y index 73b8dc12..448b3d46 100644 --- a/lib/src/clixon_yang_parse.y +++ b/lib/src/clixon_yang_parse.y @@ -184,7 +184,8 @@ clicon_yang_debug(int d) also called from yacc generated code * */ void -clixon_yang_parseerror(void *_yy, char *s) +clixon_yang_parseerror(void *_yy, + char *s) { clicon_err(OE_YANG, 0, "%s on line %d: %s at or before: '%s'", _YY->yy_name, @@ -195,7 +196,8 @@ clixon_yang_parseerror(void *_yy, char *s) } int -yang_parse_init(struct clicon_yang_yacc_arg *yy, yang_spec *ysp) +yang_parse_init(struct clicon_yang_yacc_arg *yy, + yang_spec *ysp) { return 0; } @@ -219,7 +221,8 @@ ystack_pop(struct clicon_yang_yacc_arg *yy) } struct ys_stack * -ystack_push(struct clicon_yang_yacc_arg *yy, yang_node *yn) +ystack_push(struct clicon_yang_yacc_arg *yy, + yang_node *yn) { struct ys_stack *ystack; @@ -240,8 +243,8 @@ ystack_push(struct clicon_yang_yacc_arg *yy, yang_node *yn) */ static yang_stmt * ysp_add(struct clicon_yang_yacc_arg *yy, - enum rfc_6020 keyword, - char *argument) + enum rfc_6020 keyword, + char *argument) { struct ys_stack *ystack = yy->yy_stack; yang_stmt *ys = NULL; @@ -272,7 +275,9 @@ ysp_add(struct clicon_yang_yacc_arg *yy, /*! combination of ysp_add and ysp_push for sub-modules */ static yang_stmt * -ysp_add_push(struct clicon_yang_yacc_arg *yy, int keyword, char *argument) +ysp_add_push(struct clicon_yang_yacc_arg *yy, + int keyword, + char *argument) { yang_stmt *ys; @@ -286,7 +291,8 @@ ysp_add_push(struct clicon_yang_yacc_arg *yy, int keyword, char *argument) /* identifier-ref-arg-str has a [prefix :] id and prefix_id joins the id with an optional prefix into a single string */ static char* -prefix_id_join(char *prefix, char *id) +prefix_id_join(char *prefix, + char *id) { char *str; int len; @@ -333,7 +339,7 @@ module_stmt : K_MODULE id_arg_str } '{' module_substmts '}' { if (ystack_pop(_yy) < 0) _YYERROR("2"); - clicon_debug(2,"module -> id-arg-str { module-substmts }");} + clicon_debug(2,"module_stmt -> id-arg-str { module-substmts }");} ; module_substmts : module_substmts module_substmt @@ -693,7 +699,7 @@ anyxml_substmt : when_stmt { clicon_debug(2,"anyxml-substmt -> when-st | status_stmt { clicon_debug(2,"anyxml-substmt -> status-stmt"); } | description_stmt { clicon_debug(2,"anyxml-substmt -> description-stmt"); } | reference_stmt { clicon_debug(2,"anyxml-substmt -> reference-stmt"); } - | ustring ':' ustring ';' { clicon_debug(2,"anyxml-substmt -> anyxml extension"); } + | ustring ':' ustring ';' { free($1); free($3); clicon_debug(2,"anyxml-substmt -> anyxml extension"); } ; /* uses */ diff --git a/test/test_netconf.sh b/test/test_netconf.sh index 67889412..0f9bef6d 100755 --- a/test/test_netconf.sh +++ b/test/test_netconf.sh @@ -3,136 +3,137 @@ # include err() and new() functions . ./lib.sh +clixon_cf="-f /usr/local/etc/routing.xml" # For memcheck -# clixon_netconf="valgrind --leak-check=full --show-leak-kinds=all clixon_netconf" +#clixon_netconf="valgrind --leak-check=full --show-leak-kinds=all clixon_netconf" clixon_netconf=clixon_netconf +echo "clixon_backend -z $clixon_cf" # kill old backend (if any) new "kill old backend" -sudo clixon_backend -zf $clixon_cf +sudo clixon_backend -z $clixon_cf if [ $? -ne 0 ]; then err fi new "start backend" # start new backend -sudo clixon_backend -s init -f $clixon_cf +sudo clixon_backend -s init $clixon_cf if [ $? -ne 0 ]; then err fi new "netconf tests" -new "netconf get empty config" -expecteof "$clixon_netconf -qf $clixon_cf" ']]>]]>' '^]]>]]>$' +expecteof "$clixon_netconf -q $clixon_cf" ']]>]]>' '^]]>]]>$' new "Add subtree eth/0/0 using none which should not change anything" -expecteof "$clixon_netconf -qf $clixon_cf" "noneeth/0/0]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" "noneeth/0/0]]>]]>" "^]]>]]>$" new "Check nothing added" -expecteof "$clixon_netconf -qf $clixon_cf" ']]>]]>' '^]]>]]>$' +expecteof "$clixon_netconf -q $clixon_cf" ']]>]]>' '^]]>]]>$' new "Add subtree eth/0/0 using none and create which should add eth/0/0" -expecteof "$clixon_netconf -qf $clixon_cf" 'eth/0/0ethnone ]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" 'eth/0/0ethnone ]]>]]>' "^]]>]]>$" new "Check eth/0/0 added using xpath" -expecteof "$clixon_netconf -qf $clixon_cf" ']]>]]>' "^eth/0/0ethtrue]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" ']]>]]>' "^eth/0/0ethtrue]]>]]>$" new "Re-create same eth/0/0 which should generate error" -expecteof "$clixon_netconf -qf $clixon_cf" 'eth/0/0ethnone ]]>]]>' "^" +expecteof "$clixon_netconf -q $clixon_cf" 'eth/0/0ethnone ]]>]]>' "^" new "Delete eth/0/0 using none config" -expecteof "$clixon_netconf -qf $clixon_cf" 'eth/0/0ethnone ]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" 'eth/0/0ethnone ]]>]]>' "^]]>]]>$" new "Check deleted eth/0/0 (non-presence container)" -expecteof "$clixon_netconf -qf $clixon_cf" ']]>]]>' '^]]>]]>$' +expecteof "$clixon_netconf -q $clixon_cf" ']]>]]>' '^]]>]]>$' new "Re-Delete eth/0/0 using none should generate error" -expecteof "$clixon_netconf -qf $clixon_cf" 'eth/0/0ethnone ]]>]]>' "^" +expecteof "$clixon_netconf -q $clixon_cf" 'eth/0/0ethnone ]]>]]>' "^" new "netconf edit config" -expecteof "$clixon_netconf -qf $clixon_cf" "eth/0/0eth1true
9.2.3.424
]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" "eth/0/0eth1true
9.2.3.424
]]>]]>" "^]]>]]>$" new "netconf get config xpath" -expecteof "$clixon_netconf -qf $clixon_cf" ']]>]]>' "^eth1true]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" ']]>]]>' "^eth1true]]>]]>$" new "netconf get config xpath parent" -expecteof "$clixon_netconf -qf $clixon_cf" ']]>]]>' "^eth/0/0trueeth1truetruefalse
9.2.3.424
]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" ']]>]]>' "^eth/0/0trueeth1truetruefalse
9.2.3.424
]]>]]>$" new "netconf validate missing type" -expecteof "$clixon_netconf -qf $clixon_cf" "]]>]]>" "^" +expecteof "$clixon_netconf -q $clixon_cf" "]]>]]>" "^" new "netconf discard-changes" -expecteof "$clixon_netconf -qf $clixon_cf" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" "]]>]]>" "^]]>]]>$" new "netconf get empty config2" -expecteof "$clixon_netconf -qf $clixon_cf" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" "]]>]]>" "^]]>]]>$" new "netconf edit extra xml" -expecteof "$clixon_netconf -qf $clixon_cf" "]]>]]>" "^" +expecteof "$clixon_netconf -q $clixon_cf" "]]>]]>" "^" new "netconf discard-changes" -expecteof "$clixon_netconf -qf $clixon_cf" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" "]]>]]>" "^]]>]]>$" new "netconf edit config eth1" -expecteof "$clixon_netconf -qf $clixon_cf" "eth1eth]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" "eth1eth]]>]]>" "^]]>]]>$" new "netconf validate" -expecteof "$clixon_netconf -qf $clixon_cf" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" "]]>]]>" "^]]>]]>$" new "netconf commit" -expecteof "$clixon_netconf -qf $clixon_cf" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" "]]>]]>" "^]]>]]>$" new "netconf edit config replace XXX is merge?" -expecteof "$clixon_netconf -qf $clixon_cf" "eth2ethmerge]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" "eth2ethmerge]]>]]>" "^]]>]]>$" new "netconf get replaced config" -expecteof "$clixon_netconf -qf $clixon_cf" "]]>]]>" "^eth1ethtrueeth2ethtrue]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" "]]>]]>" "^eth1ethtrueeth2ethtrue]]>]]>$" new "netconf discard-changes" -expecteof "$clixon_netconf -qf $clixon_cf" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" "]]>]]>" "^]]>]]>$" new "netconf edit state operation should fail" -expecteof "$clixon_netconf -qf $clixon_cf" "eth1eth]]>]]>" "^invalid-value" +expecteof "$clixon_netconf -q $clixon_cf" "eth1eth]]>]]>" "^invalid-value" new "netconf get state operation" -expecteof "$clixon_netconf -qf $clixon_cf" "]]>]]>" "^eth0eth42]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" "]]>]]>" "^eth0eth42]]>]]>$" new "netconf lock/unlock" -expecteof "$clixon_netconf -qf $clixon_cf" "]]>]]>]]>]]>" "^]]>]]>]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" "]]>]]>]]>]]>" "^]]>]]>]]>]]>$" new "netconf lock/lock" -expecteof "$clixon_netconf -qf $clixon_cf" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" "]]>]]>" "^]]>]]>$" new "netconf lock" -expecteof "$clixon_netconf -qf $clixon_cf" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" "]]>]]>" "^]]>]]>$" new "close-session" -expecteof "$clixon_netconf -qf $clixon_cf" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" "]]>]]>" "^]]>]]>$" new "kill-session" -expecteof "$clixon_netconf -qf $clixon_cf" "44]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" "44]]>]]>" "^]]>]]>$" new "copy startup" -expecteof "$clixon_netconf -qf $clixon_cf" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" "]]>]]>" "^]]>]]>$" new "netconf get startup" -expecteof "$clixon_netconf -qf $clixon_cf" "]]>]]>" "^eth1ethtrue]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" "]]>]]>" "^eth1ethtrue]]>]]>$" new "netconf delete startup" -expecteof "$clixon_netconf -qf $clixon_cf" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" "]]>]]>" "^]]>]]>$" new "netconf check empty startup" -expecteof "$clixon_netconf -qf $clixon_cf" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -q $clixon_cf" "]]>]]>" "^]]>]]>$" new "netconf rpc" -expecteof "$clixon_netconf -qf $clixon_cf" "ipv4ipv4]]>]]>" "^ipv4" +expecteof "$clixon_netconf -q $clixon_cf" "ipv4ipv4]]>]]>" "^ipv4" new "netconf rpc w/o namespace" -expecteof "$clixon_netconf -qf $clixon_cf" "ipv4ipv4]]>]]>" "^ipv4" +expecteof "$clixon_netconf -q $clixon_cf" "ipv4ipv4]]>]]>" "^ipv4" new "netconf subscription" -expectwait "$clixon_netconf -qf $clixon_cf" "ROUTING]]>]]>" "^]]>]]>Routing notification]]>]]>$" 30 +expectwait "$clixon_netconf -q $clixon_cf" "ROUTING]]>]]>" "^]]>]]>Routing notification]]>]]>$" 30 new "Kill backend" # Check if still alive @@ -141,7 +142,7 @@ if [ -z "$pid" ]; then err "backend already dead" fi # kill backend -sudo clixon_backend -zf $clixon_cf +sudo clixon_backend -z $clixon_cf if [ $? -ne 0 ]; then err "kill backend" fi diff --git a/test/test_yang.sh b/test/test_yang.sh index 47f1131c..68123b6a 100755 --- a/test/test_yang.sh +++ b/test/test_yang.sh @@ -12,7 +12,7 @@ clixon_cli=clixon_cli cat < /tmp/conf_yang.xml - /tmp/test_yang.xml + /tmp/conf_yang.xml /usr/local/share/routing/yang example /usr/local/lib/routing/clispec diff --git a/yang/Makefile.in b/yang/Makefile.in index cd99bda0..11b1ae2f 100644 --- a/yang/Makefile.in +++ b/yang/Makefile.in @@ -40,6 +40,7 @@ datarootdir = @datarootdir@ YANGSPECS = clixon-config@2017-12-03.yang YANGSPECS += ietf-netconf@2011-06-01.yang +YANGSPECS += ietf-inet-types@2013-07-15.yang APPNAME = clixon # subdir ehere these files are installed