* Notification event streams enhancements

* Yang 1.1 notification support
  * Event stream discovery support according to RFC 5277 Sec 3.2.5.1 (netconf) and RFC 8040 (restconf)
This commit is contained in:
Olof hagsand 2018-09-18 22:49:29 +02:00
parent f37fdb954f
commit 0631be19cb
16 changed files with 502 additions and 34 deletions

View file

@ -68,6 +68,7 @@
#include <clixon/clixon_queue.h>
#include <clixon/clixon_hash.h>
#include <clixon/clixon_handle.h>
#include <clixon/clixon_stream.h>
#include <clixon/clixon_yang.h>
#include <clixon/clixon_yang_type.h>
#include <clixon/clixon_event.h>

View file

@ -74,4 +74,9 @@ clicon_hash_t *clicon_options(clicon_handle h);
/* Return internal clicon data (hash-array) given a handle.*/
clicon_hash_t *clicon_data(clicon_handle h);
/* Return internal stream hash-array given a handle.*/
struct event_stream *clicon_stream(clicon_handle h);
struct event_stream;
int clicon_stream_append(clicon_handle h, struct event_stream *es);
#endif /* _CLIXON_HANDLE_H_ */

View file

@ -274,6 +274,7 @@ int yang_mandatory(yang_stmt *ys);
int yang_config(yang_stmt *ys);
yang_spec *yang_spec_netconf(clicon_handle h);
yang_spec *yang_spec_main(clicon_handle h);
int yang_spec_append(clicon_handle h, char *yang_dir, char *yang_module, char *yang_revision);
cvec *yang_arg2cvec(yang_stmt *ys, char *delimi);
int yang_key_match(yang_node *yn, char *name);

View file

@ -73,7 +73,7 @@ SRC = clixon_sig.c clixon_log.c clixon_err.c clixon_event.c \
clixon_hash.c clixon_options.c clixon_plugin.c \
clixon_proto.c clixon_proto_client.c \
clixon_xpath.c clixon_xpath_ctx.c clixon_sha1.c \
clixon_xml_db.c clixon_netconf_lib.c
clixon_xml_db.c clixon_netconf_lib.c clixon_stream.c
YACCOBJS := lex.clixon_xml_parse.o clixon_xml_parse.tab.o \
lex.clixon_yang_parse.o clixon_yang_parse.tab.o \

View file

@ -53,6 +53,8 @@
#include "clixon_log.h"
#include "clixon_err.h"
#include "clixon_yang.h"
#include "clixon_xml.h"
#include "clixon_stream.h"
#include "clixon_options.h"
#define CLICON_MAGIC 0x99aafabe
@ -65,9 +67,10 @@
* @see struct backend_handle
*/
struct clicon_handle {
int ch_magic; /* magic (HDR) */
clicon_hash_t *ch_copt; /* clicon option list (HDR) */
clicon_hash_t *ch_data; /* internal clicon data (HDR) */
int ch_magic; /* magic (HDR) */
clicon_hash_t *ch_copt; /* clicon option list (HDR) */
clicon_hash_t *ch_data; /* internal clicon data (HDR) Unclear why two? */
event_stream_t *ch_stream; /* notification streams, see clixon_stream.[ch] */
};
/*! Internal call to allocate a CLICON handle.
@ -133,6 +136,7 @@ clicon_handle_exit(clicon_handle h)
hash_free(copt);
if ((data = clicon_data(h)) != NULL)
hash_free(data);
stream_free(clicon_stream(h));
free(ch);
return 0;
}
@ -172,3 +176,26 @@ clicon_data(clicon_handle h)
return ch->ch_data;
}
/*! Return stream hash-array given a clicon handle.
* @param[in] h Clicon handle
*/
event_stream_t *
clicon_stream(clicon_handle h)
{
struct clicon_handle *ch = handle(h);
return ch->ch_stream;
}
int
clicon_stream_append(clicon_handle h,
event_stream_t *es)
{
struct clicon_handle *ch = handle(h);
event_stream_t **ep;
for (ep = &ch->ch_stream; (*ep); ep=&(*ep)->es_next);
*ep = es;
return 0;
}

View file

@ -1914,7 +1914,7 @@ ys_schemanode_check(yang_stmt *ys,
* @param[in] yang_dir Directory where all YANG module files reside (except mainfile)
* @param[in] mainmod Name of main YANG module. Or absolute file name.
* @param[in] revision Main module revision date string or NULL
* @param[out] ysp Yang specification. Should ave been created by caller using yspec_new
* @param[out] ysp Yang specification. Should have been created by caller using yspec_new
* @retval 0 Everything OK
* @retval -1 Error encountered
* The database symbols are inserted in alphabetical order.
@ -2388,7 +2388,9 @@ yang_config(yang_stmt *ys)
return 1;
}
/*! Parse netconf yang spec, used by netconf client and as internal protocol */
/*! Parse netconf yang spec, used by netconf client and as internal protocol
* @note not used yet - unfinnisshed code
*/
yang_spec *
yang_spec_netconf(clicon_handle h)
{
@ -2405,18 +2407,16 @@ yang_spec_netconf(clicon_handle h)
return yspec;
}
/*! Read, parse and save application yang specification as option
/*! Parse yang specification and its dependencies recursively and return
* @param[in] h clicon handle
* @param[in] f file to print to (if printspec enabled)
* @param[in] printspec print database (YANG) specification as read from file
*/
yang_spec*
yang_spec_main(clicon_handle h)
{
yang_spec *yspec = NULL;
char *yang_dir;
char *yang_module;
char *yang_revision;
char *yang_dir;
if ((yang_dir = clicon_yang_dir(h)) == NULL){
clicon_err(OE_FATAL, 0, "CLICON_YANG_DIR option not set");
@ -2439,6 +2439,46 @@ yang_spec_main(clicon_handle h)
return yspec;
}
/*! Parse yang specification, its dependencies, and append to default yang spec
* yang_spec_main should have been called first.
* @param[in] h clicon handle
* @param[in] yang_dir Directory, either system-wide or application-specific
* @param[in] yang_module Name of module
* @param[in] yang_revision Revision, or NULL
* @see yang_spec_main
*/
int
yang_spec_append(clicon_handle h,
char *yang_dir,
char *yang_module,
char *yang_revision)
{
int retval = -1;
yang_spec *yspec;
yang_spec *yspec0;
yang_stmt *ym = NULL; /* module */
if ((yspec0 = clicon_dbspec_yang(h)) == NULL){
clicon_err(OE_YANG, ENOENT, "yang spec not found");
goto done;
}
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;
}
while ((ym = yn_each((yang_node*)yspec, ym)) != NULL)
if (yn_insert((yang_node*)yspec0, ym) < 0)
goto done;
yspec->yp_len = 0;
retval = 0;
done:
if (yspec)
yspec_free(yspec);
return retval;
}
/*! Given a yang node, translate the argument string to a cv vector
*
* @param[in] ys Yang statement

View file

@ -485,6 +485,7 @@ body_stmt : extension_stmt { clicon_debug(2,"body-stmt -> extension-st
| data_def_stmt { clicon_debug(2,"body-stmt -> data-def-stmt");}
| augment_stmt { clicon_debug(2,"body-stmt -> augment-stmt");}
| rpc_stmt { clicon_debug(2,"body-stmt -> rpc-stmt");}
| notification_stmt { clicon_debug(2,"body-stmt -> notification-stmt");}
;
data_def_stmt : container_stmt { clicon_debug(2,"data-def-stmt -> container-stmt");}
@ -521,7 +522,8 @@ container_substmt : when_stmt { clicon_debug(2,"container-substmt -> when-
| reference_stmt { clicon_debug(2,"container-substmt -> reference-stmt"); }
| typedef_stmt { clicon_debug(2,"container-substmt -> typedef-stmt"); }
| grouping_stmt { clicon_debug(2,"container-substmt -> grouping-stmt"); }
| data_def_stmt { clicon_debug(2,"container-substmt -> data-def-stmt");}
| data_def_stmt { clicon_debug(2,"container-substmt -> data-def-stmt");}
| notification_stmt { clicon_debug(2,"container-substmt -> notification-stmt");}
| unknown_stmt { clicon_debug(2,"container-substmt -> unknown-stmt");}
| { clicon_debug(2,"container-substmt ->");}
;
@ -619,6 +621,7 @@ list_substmt : when_stmt { clicon_debug(2,"list-substmt -> when-stmt
| typedef_stmt { clicon_debug(2,"list-substmt -> typedef-stmt"); }
| grouping_stmt { clicon_debug(2,"list-substmt -> grouping-stmt"); }
| data_def_stmt { clicon_debug(2,"list-substmt -> data-def-stmt"); }
| notification_stmt { clicon_debug(2,"list-substmt -> notification-stmt"); }
| unknown_stmt { clicon_debug(2,"list-substmt -> unknown-stmt");}
| { clicon_debug(2,"list-substmt -> "); }
;
@ -792,7 +795,8 @@ augment_substmt : when_stmt { clicon_debug(2,"augment-substmt -> when-s
| description_stmt { clicon_debug(2,"augment-substmt -> description-stmt"); }
| reference_stmt { clicon_debug(2,"augment-substmt -> reference-stmt"); }
| data_def_stmt { clicon_debug(2,"augment-substmt -> data-def-stmt"); }
| case_stmt { clicon_debug(2,"augment-substmt -> case-stmt");}
| case_stmt { clicon_debug(2,"augment-substmt -> case-stmt");}
| notification_stmt { clicon_debug(2,"augment-substmt -> notification-stmt");}
| { clicon_debug(2,"augment-substmt -> "); }
;
@ -875,6 +879,34 @@ output_stmt : K_OUTPUT /* XXX reuse input-substatements since they are same */
;
/* notification */
notification_stmt : K_NOTIFICATION id_arg_str ';'
{ if (ysp_add(_yy, Y_NOTIFICATION, $2, NULL) == NULL) _YYERROR("46");
clicon_debug(2,"notification-stmt -> NOTIFICATION id-arg-str ;"); }
| K_NOTIFICATION id_arg_str
{ if (ysp_add_push(_yy, Y_NOTIFICATION, $2) == NULL) _YYERROR("47"); }
'{' notification_substmts '}'
{ if (ystack_pop(_yy) < 0) _YYERROR("48");
clicon_debug(2,"notification-stmt -> NOTIFICATION id-arg-str { notification-substmts }"); }
;
notification_substmts : notification_substmts notification_substmt
{ clicon_debug(2,"notification-substmts -> notification-substmts notification-substmt"); }
| notification_substmt
{ clicon_debug(2,"notification-substmts -> notification-substmt"); }
;
notification_substmt : if_feature_stmt { clicon_debug(2,"notification-substmt -> if-feature-stmt"); }
| must_stmt { clicon_debug(2,"notification-substmt -> must-stmt"); }
| status_stmt { clicon_debug(2,"notification-substmt -> status-stmt"); }
| description_stmt { clicon_debug(2,"notification-substmt -> description-stmt"); }
| reference_stmt { clicon_debug(2,"notification-substmt -> reference-stmt"); }
| typedef_stmt { clicon_debug(2,"notification-substmt -> typedef-stmt"); }
| grouping_stmt { clicon_debug(2,"notification-substmt -> grouping-stmt"); }
| data_def_stmt { clicon_debug(2,"notification-substmt -> data-def-stmt"); }
| { clicon_debug(2,"notification-substmt -> "); }
;
/* Typedef */
typedef_stmt : K_TYPEDEF id_arg_str
{ if (ysp_add_push(_yy, Y_TYPEDEF, $2) == NULL) _YYERROR("46"); }
@ -964,6 +996,7 @@ grouping_substmt : status_stmt { clicon_debug(2,"grouping-substmt -> st
| typedef_stmt { clicon_debug(2,"grouping-substmt -> typedef-stmt"); }
| grouping_stmt { clicon_debug(2,"grouping-substmt -> grouping-stmt"); }
| data_def_stmt { clicon_debug(2,"grouping-substmt -> data-def-stmt"); }
| notification_stmt { clicon_debug(2,"grouping-substmt -> notification-stmt"); }
| { clicon_debug(2,"grouping-substmt -> "); }
;