diff --git a/apps/cli/clicon_cli.h b/apps/cli/clicon_cli.h index 39e10ec8..d07c79c0 100644 --- a/apps/cli/clicon_cli.h +++ b/apps/cli/clicon_cli.h @@ -25,8 +25,8 @@ #include -#/* Common code (API and clicon_cli) */ -include +/* Common code (API and clicon_cli) */ +#include /*! Clicon Cli plugin callbacks: use these in your cli plugin code */ diff --git a/doc/FAQ.txt b/doc/FAQ.txt new file mode 100644 index 00000000..4719f5d4 --- /dev/null +++ b/doc/FAQ.txt @@ -0,0 +1,86 @@ +Frequently Asked Questions - Clixon +=================================== + +Q: What is the best way of understanding Clixon? +A: Run the ietf yang routing example. + +Q: How do you build and install Clixon (and the example)? +A: Clixon: ./configure; make; sudo make install; sudo make install-include +Example: cd example; make; sudo make install + +Q: Is there any reference documentation? +A: Clixon uses Doxygen for reference documentation. +Build using 'make doc' and aim your browser at doc/html/index.html + +Q: How do you run the example? +A: Start a backend server: 'clicon_backend -Ff /usr/local/etc/routing.conf' +Start a cli session: clicon_cli -f /usr/local/etc/routing.conf +Start a netconf session: clicon_netconf -f /usr/local/etc/routing.conf + +Q: How does Clixon differ from Clicon? +A: Clixon is a fork of Clicon focussing on Yang specification and XML +database. The yang support in clicon was grown out of a key-based +scheme that was complex since it had to translate between +formats. Clixon uses only XML. A simplified commit transaction +mechanism has been added to. But Clixon is not backward compliant with +key-based Clicon applications, such as ROST. + +Q: In the example, how can you alter its semantics? +- routing.conf.local - Override default settings +- The yang specifications - Alter accepted XML, database format and the configuration part of the CLI commands that are generated. +- routing_cli.cli - Change the fixed part of the CLI commands +- routing_cli.c - New cli commands may need to write a new C-funtion. +- routing_backend.c - What happens at commit. +- routing_netconf.c - Modify semantics of netconf commands. + +Q: How do you check what is in a database? +clicon_dbctrl -d -p +The name of the running or candidate databases are found in the +configuration file, eg /usr/local/var/routing/candidate_db +Example: + /interfaces/interface/eth0/ipv4 + /interfaces/interface/eth0/type bgp + /interfaces/interface/eth0 + /interfaces/interface/eth0/name eth0 +Each line corresponds to a database entry (node in an XML tree). If +the node is a leaf, the value appears as the second entry. + +Q: How do you write a commit rule in the example? +A: You write a commit function in routing_backend.c. +Every time a commit is made, transaction_commit() is called in the +backend. It has a 'transaction_data td' argument which is used to fetch +information on added, deleted and changed entries. You access this +information using access functions as defined in clicon_backend_transaction.h + +Q: How do you check what has changed on commit? +A: You use XPATHs on the XML trees in the transaction commit callback. +Suppose you want to print all added interfaces: + cxobj *target = transaction_target(td); # wanted XML tree + # Get all added i/fs + cxobj **vec = xpath_vec_flag(target, "//interface", &len, XML_FLAG_ADD); + for (i=0; i("This is a variable"), mycallback("myarg"); +Then define a function in routing_cli.c + mycallback(clicon_handle h, cvec *cvv, cg_var *arg) +where 'cvv' contains the value of the variable and 'arg' contains the +function parameter 'myarg'. + +Q: What are cg_var and cvec used in CLI callbacks? +Those are 'CLIgen variables' and vector of CLOgen +variables. Documented in CLIgen documentation. Some examples on usage is found in the +routing_cli.c + +Q: How do you write a validation rule? +Similar to a commit rule, but instead write the transaction_validate() function. +Check for consitencies in the XML trees and if they fail, make an clicon_err() call. + clicon_err(OE_PLUGIN, 0, "Route %s lacks ipv4 addr", name); + return -1; +The validation or commit will then be aborted. diff --git a/doc/Makefile.in b/doc/Makefile.in index cd2f34c5..ae1da462 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -32,8 +32,7 @@ SUBDIRS = .PHONY: clean all $(SUBDIRS) -all: $(SUBDIRS) - echo "Build doxygen docs: make doc" +all: $(SUBDIRS) doc echo "Build doxygen doc and graphs: make graphs" # Regular doxygen documentation diff --git a/example/Makefile.in b/example/Makefile.in index aba66963..46b35335 100644 --- a/example/Makefile.in +++ b/example/Makefile.in @@ -48,7 +48,7 @@ all: $(PLUGINS) $(APPNAME).conf CLISPECS = routing_cli.cli -YANGSPECS = $(APPNAME).yang +#YANGSPECS = $(APPNAME).yang YANGSPECS += ietf-yang-types@2013-07-15.yang YANGSPECS += ietf-inet-types@2013-07-15.yang YANGSPECS += ietf-interfaces@2014-05-08.yang diff --git a/example/routing_cli.c b/example/routing_cli.c index 43493d3b..8f48aef0 100644 --- a/example/routing_cli.c +++ b/example/routing_cli.c @@ -55,3 +55,31 @@ plugin_init(clicon_handle h) return 0; } +/*! Example cli function */ +int +mycallback(clicon_handle h, cvec *cvv, cg_var *arg) +{ + int retval = -1; + cxobj *xt = NULL; + yang_spec *yspec; + cg_var *myvar; + + /* Access cligen callback variables */ + myvar = cvec_find(cvv, "var"); /* get a cligen variable from vector */ + cli_output(stderr, "%s: %d\n", __FUNCTION__, cv_int32_get(myvar)); /* get int value */ + cli_output(stderr, "arg = %s\n", cv_string_get(arg)); /* get string value */ + + /* Show eth0 interfaces config using XPATH */ + yspec = clicon_dbspec_yang(h); + if (xmldb_get(clicon_candidate_db(h), + "/interfaces/interface[name=eth0]", + yspec, + &xt) < 0) + goto done; + clicon_xml2file(stdout, xt, 0, 1); + retval = 0; + done: + if (xt) + xml_free(xt); + return retval; +} diff --git a/example/routing_cli.cli b/example/routing_cli.cli index c8b3156c..b0ca59eb 100644 --- a/example/routing_cli.cli +++ b/example/routing_cli.cli @@ -2,6 +2,7 @@ # Common CLI syntax for both server and PMNode operatio mode CLICON_MODE="routing"; CLICON_PROMPT="%U@%H> "; +CLICON_PLUGIN="routing_cli"; # Note, when switching to PT, change datamodel to only @datamodel #set @datamodel:ietf-routing, cli_merge(); @@ -43,3 +44,4 @@ load("Load configuration from XML file") ("Filename (local file replace("Replace candidate with file contents"), load_config_file("filename replace"); merge("Merge file with existent candidate"), load_config_file("filename merge"); } +example("This is a comment") ("Just a random number"), mycallback("myarg"); \ No newline at end of file diff --git a/lib/clicon/clicon_xml.h b/lib/clicon/clicon_xml.h index 6a43c31a..f08d723a 100644 --- a/lib/clicon/clicon_xml.h +++ b/lib/clicon/clicon_xml.h @@ -50,7 +50,10 @@ typedef int (xml_applyfn_t)(cxobj *yn, void *arg); /* * xml_flag() flags: */ -#define XML_FLAG_MARK 0x01 /* Marker for dynamic algorithms, eg expand */ +#define XML_FLAG_MARK 0x01 /* Marker for dynamic algorithms, eg expand */ +#define XML_FLAG_ADD 0x02 /* Node is added (commits) */ +#define XML_FLAG_DEL 0x04 /* Node is deleted (commits) */ +#define XML_FLAG_CHANGE 0x08 /* Node is changed (commits) */ /* * Prototypes