Very large commit for upcoming 4.4 release

Major New features

* New and updated search functions using xpath, api-path and instance-id
  * New search functions using api-path and instance_id:
    * C search functions: `clixon_find_instance_id()` and `clixon_find_api_path()`
  * Binary search optimization in lists for indexed leafs in all three formats.
    * This improves search performance to O(logN) which is drastical improvements for large lists.
  * You can also register explicit indexes for making binary search (not only list keys)
  * For more info, see docs at [paths](https://clixon-docs.readthedocs.io/en/latest/paths.html) and
[search](https://clixon-docs.readthedocs.io/en/latest/xml.html#searching-in-xml)

API changes on existing features (you may need to change your code)
* On failed validation of leafrefs, error message changed from: `No such leaf` to `No leaf <name> matching path <path>`.
* CLI Error message (clicon_rpc_generate_error()) changed when backend returns netconf error to be more descriptive:
  * Original: `Config error: Validate failed. Edit and try again or discard changes: Invalid argument`
  * New (example): `Netconf error: application operation-failed Identityref validation failed, undefined not derived from acl-base . Validate failed. Edit and try again or discard changes"

Minor changes

* Test framework
  * Added `-- -S <file>` command-line to main example to be able to return any state to main example.
  * Added `test/cicd` test scripts for running on a set of other hosts
* C-code restructuring
  * clixon_yang.c partitioned and moved code into clixon_yang_parse_lib.c and clixon_yang_module.c and move back some code from clixon_yang_type.c.
    * partly to reduce size, but most important to limit code that accesses internal yang structures, only clixon_yang.c does this now.
This commit is contained in:
Olof hagsand 2020-02-02 15:52:30 +01:00
parent e8ae628d06
commit 19e21be0bc
132 changed files with 6241 additions and 2332 deletions

View file

@ -2,7 +2,8 @@
*
***** BEGIN LICENSE BLOCK *****
Copyright (C) 2009-2019 Olof Hagsand and Benny Holmgren
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
Copyright (C) 2017-2020 Olof Hagsand
This file is part of CLIXON.
@ -73,6 +74,7 @@
#include <clixon/clixon_file.h>
#include <clixon/clixon_xml.h>
#include <clixon/clixon_xml_sort.h>
#include <clixon/clixon_yang_parse_lib.h>
#include <clixon/clixon_yang_module.h>
#include <clixon/clixon_stream.h>
#include <clixon/clixon_proto.h>
@ -82,7 +84,7 @@
#include <clixon/clixon_options.h>
#include <clixon/clixon_data.h>
#include <clixon/clixon_regex.h>
#include <clixon/clixon_api_path.h>
#include <clixon/clixon_path.h>
#include <clixon/clixon_xml_map.h>
#include <clixon/clixon_validate.h>
#include <clixon/clixon_datastore.h>

View file

@ -2,7 +2,8 @@
*
***** BEGIN LICENSE BLOCK *****
Copyright (C) 2009-2019 Olof Hagsand and Benny Holmgren
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
Copyright (C) 2017-2020 Olof Hagsand
This file is part of CLIXON.
@ -58,9 +59,10 @@
enum clicon_err{
/* 0 means error not set) */
OE_DB = 1, /* database registries */
OE_DAEMON, /* demons: pidfiles, etc */
OE_DAEMON, /* demons: pidfiles, etc */
OE_EVENTS, /* events, filedescriptors, timeouts */
OE_CFG, /* configuration */
OE_NETCONF, /* Netconf error */
OE_PROTO, /* config/client communication */
OE_REGEX, /* Regexp error */
OE_UNIX, /* unix/linux syscall error */

View file

@ -2,7 +2,8 @@
*
***** BEGIN LICENSE BLOCK *****
Copyright (C) 2009-2019 Olof Hagsand and Benny Holmgren
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
Copyright (C) 2017-2020 Olof Hagsand
This file is part of CLIXON.
@ -31,6 +32,8 @@
***** END LICENSE BLOCK *****
* "Instance-identifier" is a subset of XML Xpaths and defined in Yang, used in NACM for example.
* and defined in RF7950 Sections 9.13 and 14.
*
* "api-path" is "URI-encoded path expression" definition in RFC8040 3.5.3
* BNF:
@ -44,8 +47,29 @@
* <identifier> := (<ALPHA> | "_") (<ALPHA> | <DIGIT> | "_" | "-" | ".")
*/
#ifndef _CLIXON_API_PATH_H_
#define _CLIXON_API_PATH_H_
#ifndef _CLIXON_PATH_H_
#define _CLIXON_PATH_H_
/*
* Types
*/
/* Internal path structure. Somewhat more general than api-path, much less than xpath
* about the same as yang instance-identifier
* Not that cp_cvk api-paths do not specifiy key-names, so cp_cvk is just a list of
* (NULL:value)*, which means that names must be added using api_path_check() based on
* yang.
* Other formats (eg xpath) have the names given in the format.
*/
typedef struct {
qelem_t cp_qelem; /* List header */
char *cp_prefix; /* Prefix or module name, should be resolved + id to cp_yang */
char *cp_id; /* Identifier */
cvec *cp_cvk; /* Key values: list of (name:value) pairs alt (NULL:value)
* Can also be single uint32, if so positional eg x/y[42]
* This seems kludgy but follows RFC 7950 Sec 9.13
*/
yang_stmt *cp_yang; /* Corresponding yang spec (after XML match - ie resolved) */
} clixon_path;
/*
* Prototypes
@ -60,5 +84,14 @@ int api_path2xml(char *api_path, yang_stmt *yspec, cxobj *xtop,
yang_class nodeclass, int strict,
cxobj **xpathp, yang_stmt **ypathp, cxobj **xerr);
int xml2api_path_1(cxobj *x, cbuf *cb);
#if defined(__GNUC__) && __GNUC__ >= 3
int clixon_xml_find_api_path(cxobj *xcur, yang_stmt *yt, cxobj ***vec, size_t *veclen, char *format,
...) __attribute__ ((format (printf, 5, 6)));;
int clixon_xml_find_instance_id(cxobj *xcur, yang_stmt *yt, cxobj ***vec, size_t *veclen, char *format,
...) __attribute__ ((format (printf, 5, 6)));;
#else
int clixon_xml_find_api_path(cxobj *xcur, yang_stmt *yt, cxobj ***vec, size_t *veclen, char *format,o ...);
int clixon_xml_find_instance_id(cxobj *xcur, yang_stmt *yt, cxobj ***vec, size_t *veclen, char *format, ...);
#endif
#endif /* _CLIXON_API_PATH_H_ */
#endif /* _CLIXON_PATH_H_ */

View file

@ -2,7 +2,8 @@
*
***** BEGIN LICENSE BLOCK *****
Copyright (C) 2009-2019 Olof Hagsand and Benny Holmgren
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
Copyright (C) 2017-2020 Olof Hagsand
This file is part of CLIXON.
@ -151,7 +152,6 @@ int xml_spec_set(cxobj *x, yang_stmt *spec);
cg_var *xml_cv(cxobj *x);
int xml_cv_set(cxobj *x, cg_var *cv);
cxobj *xml_find(cxobj *xn_parent, char *name);
int xml_addsub(cxobj *xp, cxobj *xc);
cxobj *xml_wrap_all(cxobj *xp, char *tag);
cxobj *xml_wrap(cxobj *xc, char *tag);
@ -193,6 +193,7 @@ cxobj *xml_dup(cxobj *x0);
int cxvec_dup(cxobj **vec0, size_t len0, cxobj ***vec1, size_t *len1);
int cxvec_append(cxobj *x, cxobj ***vec, size_t *len);
int cxvec_prepend(cxobj *x, cxobj ***vec, size_t *len);
int xml_apply(cxobj *xn, enum cxobj_type type, xml_applyfn_t fn, void *arg);
int xml_apply0(cxobj *xn, enum cxobj_type type, xml_applyfn_t fn, void *arg);
int xml_apply_ancestor(cxobj *xn, xml_applyfn_t fn, void *arg);

View file

@ -2,7 +2,8 @@
*
***** BEGIN LICENSE BLOCK *****
Copyright (C) 2009-2019 Olof Hagsand and Benny Holmgren
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
Copyright (C) 2017-2020 Olof Hagsand
This file is part of CLIXON.
@ -40,11 +41,13 @@
* Prototypes
*/
int xml_child_spec(cxobj *x, cxobj *xp, yang_stmt *yspec, yang_stmt **yp);
int xml_cmp(cxobj *x1, cxobj *x2, int enm);
int xml_cmp(cxobj *x1, cxobj *x2, int same, int skip1);
int xml_sort(cxobj *x0, void *arg);
int xml_insert(cxobj *xp, cxobj *xc, enum insert_type ins, char *key_val, cvec *nsckey);
int xml_sort_verify(cxobj *x, void *arg);
int match_base_child(cxobj *x0, cxobj *x1c, yang_stmt *yc, cxobj **x0cp);
int xml_binsearch(cxobj *xp, yang_stmt *yc, cvec *cvk, cxobj **xretp);
int clixon_xml_find_index(cxobj *xp, yang_stmt *yp, char *namespace, char *name,
cvec *cvk, cxobj ***xvec, size_t *xlen);
int clixon_xml_find_pos(cxobj *xp, yang_stmt *yc, uint32_t pos, cxobj ***xvec, size_t *xlen);
#endif /* _CLIXON_XML_SORT_H */

View file

@ -2,7 +2,8 @@
*
***** BEGIN LICENSE BLOCK *****
Copyright (C) 2009-2019 Olof Hagsand
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
Copyright (C) 2017-2020 Olof Hagsand
This file is part of CLIXON.
@ -55,8 +56,9 @@ enum xp_objtype{
XT_STRING
};
/* Expression evaluation occurs with respect to a context. XSLT and XPointer specify how the context is
* determined for XPath expressions used in XSLT and XPointer respectively. The context consists of:
/* Expression evaluation occurs with respect to a context. XSLT and XPointer specify how the
* context is determined for XPath expressions used in XSLT and XPointer respectively. The
* context consists of:
* a node (the context node)
* a pair of non-zero positive integers (the context position and the context size)
* a set of variable bindings

View file

@ -2,7 +2,7 @@
*
***** BEGIN LICENSE BLOCK *****
Copyright (C) 2009-2019 Olof Hagsand
Copyright (C) 2009-2020 Olof Hagsand
This file is part of CLIXON.
@ -39,7 +39,22 @@
#ifndef _CLIXON_YANG_H_
#define _CLIXON_YANG_H_
/*
* Clixon-specific cligen variable (cv) flags
* CLIgen flags defined are in the range 0x01 -0x0f
* An application can use any flags above that
* @see cv_flag
*/
#define V_UNSET 0x10 /* Used by XML code to denote a value is not default */
/*
* Yang flags used in
*/
#define YANG_FLAG_MARK 0x01 /* (Dynamic) marker for dynamic algorithms, eg expand */
#ifdef XML_EXTRA_INDEX
#define YANG_FLAG_INDEX 0x02 /* This yang node under list is (extra) index. --> you can access
* list elements using this index with binary search */
#endif
/*
* Types
@ -146,12 +161,20 @@ typedef int (yang_applyfn_t)(yang_stmt *ys, void *arg);
* Prototypes
*/
/* Access functions */
int yang_len_get(yang_stmt *ys);
yang_stmt *yang_child_i(yang_stmt *ys, int i);
yang_stmt *yang_parent_get(yang_stmt *ys);
enum rfc_6020 yang_keyword_get(yang_stmt *ys);
char *yang_argument_get(yang_stmt *ys);
int yang_argument_set(yang_stmt *ys, char *arg);
cg_var *yang_cv_get(yang_stmt *ys);
cvec *yang_cvec_get(yang_stmt *ys);
int yang_cvec_set(yang_stmt *ys, cvec *cvv);
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);
/* Other functions */
yang_stmt *yspec_new(void);
@ -169,10 +192,6 @@ int ys_module_by_xml(yang_stmt *ysp, struct xml *xt, yang_stmt **ymodp);
yang_stmt *ys_module(yang_stmt *ys);
yang_stmt *ys_real_module(yang_stmt *ys);
yang_stmt *ys_spec(yang_stmt *ys);
yang_stmt *yang_find_module_by_prefix(yang_stmt *ys, char *prefix);
yang_stmt *yang_find_module_by_prefix_yspec(yang_stmt *yspec, char *prefix);
yang_stmt *yang_find_module_by_namespace(yang_stmt *yspec, char *namespace);
yang_stmt *yang_find_module_by_name(yang_stmt *yspec, char *name);
yang_stmt *yang_find(yang_stmt *yn, int keyword, const char *argument);
int yang_match(yang_stmt *yn, int keyword, char *argument);
yang_stmt *yang_find_datanode(yang_stmt *yn, char *argument);
@ -186,8 +205,7 @@ int yang_print(FILE *f, yang_stmt *yn);
int yang_print_cbuf(cbuf *cb, yang_stmt *yn, int marginal);
int if_feature(yang_stmt *yspec, char *module, char *feature);
int ys_populate(yang_stmt *ys, void *arg);
yang_stmt *yang_parse_file(int fd, const char *name, yang_stmt *ysp);
yang_stmt *yang_parse_filename(const char *filename, yang_stmt *ysp);
int ys_populate2(yang_stmt *ys, void *arg);
int yang_apply(yang_stmt *yn, enum rfc_6020 key, yang_applyfn_t fn,
void *arg);
int yang_datanode(yang_stmt *ys);
@ -196,17 +214,16 @@ int yang_abs_schema_nodeid(yang_stmt *yspec, yang_stmt *ys,
enum rfc_6020 keyword, yang_stmt **yres);
int yang_desc_schema_nodeid(yang_stmt *yn, char *schema_nodeid,
enum rfc_6020 keyword, yang_stmt **yres);
int ys_parse_date_arg(char *datearg, uint32_t *dateint);
cg_var *ys_parse(yang_stmt *ys, enum cv_type cvtype);
int ys_parse_sub(yang_stmt *ys, char *extra);
int yang_mandatory(yang_stmt *ys);
int yang_config(yang_stmt *ys);
int yang_spec_parse_module(clicon_handle h, const char *module,
const char *revision, yang_stmt *yspec);
int yang_spec_parse_file(clicon_handle h, char *filename, yang_stmt *yspec);
int yang_spec_load_dir(clicon_handle h, char *dir, yang_stmt *yspec);
int yang_features(clicon_handle h, yang_stmt *yt);
cvec *yang_arg2cvec(yang_stmt *ys, char *delimi);
int yang_key_match(yang_stmt *yn, char *name);
int yang_type_cache_regexp_set(yang_stmt *ytype, int rxmode, cvec *regexps);
int yang_type_cache_get(yang_stmt *ytype, yang_stmt **resolved, int *options,
cvec **cvv, cvec *patterns, int *rxmode, cvec *regexps, uint8_t *fraction);
int yang_type_cache_set(yang_stmt *ys, yang_stmt *resolved, int options, cvec *cvv,
cvec *patterns, uint8_t fraction);
#endif /* _CLIXON_YANG_H_ */

View file

@ -2,7 +2,7 @@
*
***** BEGIN LICENSE BLOCK *****
Copyright (C) 2009-2019 Olof Hagsand
Copyright (C) 2009-2020 Olof Hagsand
This file is part of CLIXON.
@ -66,7 +66,10 @@ char *yang_modules_revision(clicon_handle h);
int yang_modules_state_get(clicon_handle h, yang_stmt *yspec, char *xpath,
cvec *nsc, int brief, cxobj **xret);
int clixon_module_upgrade(clicon_handle h, cxobj *xt, modstate_diff_t *msd, cbuf *cb);
yang_stmt *yang_find_module_by_prefix(yang_stmt *ys, char *prefix);
yang_stmt *yang_find_module_by_prefix_yspec(yang_stmt *yspec, char *prefix);
yang_stmt *yang_find_module_by_namespace(yang_stmt *yspec, char *namespace);
yang_stmt *yang_find_module_by_name(yang_stmt *yspec, char *name);
#endif /* _CLIXON_YANG_MODULE_H_ */

View file

@ -0,0 +1,64 @@
/*
*
***** BEGIN LICENSE BLOCK *****
Copyright (C) 2009-2020 Olof Hagsand
This file is part of CLIXON.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 3 or later (the "GPL"),
in which case the provisions of the GPL are applicable instead
of those above. If you wish to allow use of your version of this file only
under the terms of the GPL, and not to allow others to
use your version of this file under the terms of Apache License version 2,
indicate your decision by deleting the provisions above and replace them with
the notice and other provisions required by the GPL. If you do not delete
the provisions above, a recipient may use your version of this file under
the terms of any one of the Apache License version 2 or the GPL.
***** END LICENSE BLOCK *****
* CALLING ORDER OF YANG PARSE FILES
* =================================
* yang_spec_parse_module
* | |
* v v v
* yang_spec_parse_file-> yang_parse_post->yang_parse_recurse->yang_parse_module
* \ / v
* yang_spec_load_dir ------------------------------------> yang_parse_filename
* v
* yang_parse_file
* v
* yang_parse_str
*/
#ifndef _CLIXON_YANG_PARSE_LIB_H_
#define _CLIXON_YANG_PARSE_LIB_H_
/*
* Prototypes
*/
yang_stmt *yang_parse_file(int fd, const char *name, yang_stmt *ysp);
yang_stmt *yang_parse_filename(const char *filename, yang_stmt *ysp);
int yang_spec_parse_module(clicon_handle h, const char *module,
const char *revision, yang_stmt *yspec);
int yang_spec_parse_file(clicon_handle h, char *filename, yang_stmt *yspec);
int yang_spec_load_dir(clicon_handle h, char *dir, yang_stmt *yspec);
int ys_parse_date_arg(char *datearg, uint32_t *dateint);
cg_var *ys_parse(yang_stmt *ys, enum cv_type cvtype);
int ys_parse_sub(yang_stmt *ys, char *extra);
#endif /* _CLIXON_YANG_LIB_H_ */

View file

@ -2,7 +2,7 @@
*
***** BEGIN LICENSE BLOCK *****
Copyright (C) 2009-2019 Olof Hagsand
Copyright (C) 2009-2020 Olof Hagsand
This file is part of CLIXON.
@ -54,8 +54,6 @@ typedef struct yang_type_cache yang_type_cache;
/*
* Prototypes
*/
int yang_type_cache_cp(yang_type_cache **ycnew, yang_type_cache *ycold);
int yang_type_cache_free(yang_type_cache *ycache);
int ys_resolve_type(yang_stmt *ys, void *arg);
int yang2cv_type(char *ytype, enum cv_type *cv_type);
char *cv2yang_type(enum cv_type cv_type);