* For backward compatibility, load of startup and running set CLICON_XML_NS_STRICT to false temporarily. * Added three-valued return values for several validate functions where -1 is fatal error, 0 is validation failed and 1 is validation OK. * This includes: `xmldb_put`, `xml_yang_validate_all`, `xml_yang_validate_add`, `xml_yang_validate_rpc`, `api_path2xml`, `api_path2xpath` * Added new xml functions for specific types: `xml_child_nr_notype`, `xml_child_nr_notype`, `xml_child_i_type`, `xml_find_type`. |
||
|---|---|---|
| .. | ||
| systemd | ||
| Dockerfile | ||
| example.xml | ||
| example.yang | ||
| example_backend.c | ||
| example_backend_nacm.c | ||
| example_cli.c | ||
| example_cli.cli | ||
| example_netconf.c | ||
| example_restconf.c | ||
| iana-if-type@2014-05-08.yang | ||
| ietf-inet-types@2013-07-15.yang | ||
| ietf-interfaces@2014-05-08.yang | ||
| ietf-ip@2014-06-16.yang | ||
| ietf-ipsec@2016-03-09.yang | ||
| ietf-ipv4-unicast-routing@2014-10-26.yang | ||
| ietf-ipv6-unicast-routing@2014-10-26.yang | ||
| ietf-routing@2014-10-26.yang | ||
| ietf-yang-types@2013-07-15.yang | ||
| Makefile.in | ||
| README.md | ||
Clixon example
- Content
- Compile and run
- Using the CLI
- Using netconf
- Streams
- RPC Operations
- State data
- Authentication and NACM
- Systemd
- Docker
- Plugins
Content
This directory contains a Clixon example which includes a simple example. It contains the following files:
example.xmlThe configuration file. See (yang/clixon-config@.yang)[../yang/clixon-config@2018-10-21.yang] for the documentation of all available fields.example.yangThe yang spec of the example. It mainly includes ietf routing and IP modules.example_cli.cliCLIgen specification.example_cli.cCLI callback plugin containing functions called in the cli file above: a generic callback (mycallback) and an RPC (fib_route_rpc).example_backend.cBackend callback plugin including example of:- transaction callbacks (validate/commit),
- notification,
- rpc handler
- state-data handler, ie non-config data
example_backend_nacm.cSecondary backend plugin. Plugins are loaded alphabetically.example_restconf.cRestconf callback plugin containing an HTTP basic authentication callbackexample_netconf.cNetconf callback pluginMakefile.inExample makefile where plugins are built and installed
Compile and run
Before you start,
- Make group setup
- Setup restconf
cd example
make && sudo make install
Start backend:
sudo clixon_backend -f /usr/local/etc/example.xml -s init
Edit cli:
clixon_cli -f /usr/local/etc/example.xml
Send netconf command:
clixon_netconf -f /usr/local/etc/example.xml
Start clixon restconf daemon
sudo su -c "/www-data/clixon_restconf -f /usr/local/etc/example.xml " -s /bin/sh www-data
Send restconf command
curl -G http://127.0.0.1/restconf/data
Using the CLI
The example CLI allows you to modify and view the data model using set, delete and show via generated code.
There are also many other commands available as examples. View the source file (example_cli.cli)[example_cli.cli] for more details.
The following example shows how to add an interface in candidate, validate and commit it to running, then look at it (as xml) and finally delete it.
clixon_cli -f /usr/local/etc/example.xml
cli> set interfaces interface eth9 ?
description enabled ipv4
ipv6 link-up-down-trap-enable type
cli> set interfaces interface eth9 type ex:eth
cli> validate
cli> commit
cli> show configuration xml
<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
<interface>
<name>eth9</name>
<type>ex:eth</type>
<enabled>true</enabled>
</interface>
</interfaces>
cli> delete interfaces interface eth9
Using Netconf
The following example shows how to set data using netconf:
<rpc><edit-config><target><candidate/></target><config>
<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
<interface>
<name>eth1</name>
<enabled>true</enabled>
<ipv4>
<address>
<ip>9.2.3.4</ip>
<prefix-length>24</prefix-length>
</address>
</ipv4>
</interface>
</interfaces>
</config></edit-config></rpc>]]>]]>
Getting data using netconf
<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>
<rpc><get-config><source><candidate/></source><filter/></get-config></rpc>]]>]]>
<rpc><get-config><source><candidate/></source><filter type="xpath"/></get-config></rpc>]]>]]>
<rpc><get-config><source><candidate/></source><filter type="subtree"><data><interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"><interface><name>eth9</name><type>ex:eth</type></interface></interfaces></data></filter></get-config></rpc>]]>]]>
<rpc><get-config><source><candidate/></source><filter type="xpath" select="/interfaces/interface"/></get-config></rpc>]]>]]>
<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>
Streams
The example has an EXAMPLE stream notification triggering every 5s. To start a notification stream in the session using netconf, create a subscription:
<rpc><create-subscription xmlns="urn:ietf:params:xml:ns:netmod:notification"><stream>EXAMPLE</stream></create-subscription></rpc>]]>]]>
<rpc-reply><ok/></rpc-reply>]]>]]>
<notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0"><eventTime>2019-01-02T10:20:05.929272</eventTime><event><event-class>fault</event-class><reportingEntity><card>Ethernet0</card></reportingEntity><severity>major</severity></event></notification>]]>]]>
...
This can also be triggered via the CLI:
clixon_cli -f /usr/local/etc/example.xml
cli> notify
cli> event-class fault;
reportingEntity {
card Ethernet0;
}
severity major;
...
cli> no notify
cli>
Restconf support is also supported, see (restc)[../apps/restconf/README.md].
RPC Operations
Clixon implements Yang RPC operations by an extension mechanism. The extension mechanism enables you to add application-specific operations. It works by adding user-defined callbacks for added netconf operations. It is possible to use the extension mechanism independent of the yang rpc construct, but it is recommended. The example includes an example:
Example using CLI:
cli> rpc ipv4
rpc-reply {
route {
address-family ipv4;
next-hop {
next-hop-list 2.3.4.5;
}
source-protocol static;
}
}
Netconf:
<rpc><fib-route xmlns="urn:ietf:params:xml:ns:yang:ietf-routing"><routing-instance-name>ipv4</routing-instance-name></fib-route></rpc>]]>]]>
<rpc-reply><route xmlns="urn:ietf:params:xml:ns:yang:ietf-routing"><address-family>ipv4</address-family><next-hop><next-hop-list>2.3.4.5</next-hop-list></next-hop><source-protocol>static</source-protocol></route></rpc-reply>]]>]]>
Restconf:
curl -X POST http://localhost/restconf/operations/ietf-routing:fib-route -d '{"ietf-routing:input":{"routing-instance-name":"ipv4"}}'
Details
The example works by creating a netconf rpc call and sending it to the backend: (see the fib_route_rpc() function in example_cli.c).
In the (example_backend.c)[example_backend.c], a callback is registered (fib_route()) which handles the RPC (this is just dummy data):
static int
fib_route(clicon_handle h,
cxobj *xe, /* Request: <rpc><xn></rpc> */
cbuf *cbret, /* Reply eg <rpc-reply>... */
void *arg, /* Client session */
void *regarg) /* Argument given at register */
{
cprintf(cbret, "<rpc-reply><route xmlns=\"urn:ietf:params:xml:ns:yang:ietf-routing\">"
"<address-family>ipv4</address-family>"
"<next-hop><next-hop-list>2.3.4.5</next-hop-list></next-hop>"
"<source-protocol>static</source-protocol>"
"</route></rpc-reply>");
return 0;
}
int
clixon_plugin_init(clicon_handle h)
{
...
rpc_callback_register(h, fib_route, NULL, "fib-route");
...
}
State data
Netconf and restconf GET also returns state data(not only configuration data).
In YANG state data is specified with config false;. In the example,
state is state data, see (example.yang)[example.yang]
To return state data, you need to write a backend state data callback with the name "plugin_statedata" where you return an XML tree with state. This is then merged with config data by the system.
A static example of returning state data is in the example. Note that a real example would poll or get the interface counters via a system call, as well as use the "xpath" argument to identify the requested state data.
Authentication and NACM
The example contains some stubs for authorization according to RFC8341(NACM):
- A basic auth HTTP callback, see: example_restconf_credentials() containing three example users: andy, wilma, and guest, according to the examples in Appendix A in RFC8341.
- A NACM backend plugin reporting the mandatory NACM state variables.
Systemd
Example systemd files for backend and restconf daemons are found under the systemd directory. Install them under /etc/systemd/system for example.
Docker
Run the example as a docker container and access it from a host CLI as follows:
ID=$(sudo docker run -td olofhagsand/clixon_example)
IP=$(sudo docker inspect -f '{{.NetworkSettings.IPAddress }}' $ID)
clixon_cli -a IPv4 -u $IP -f ./example.xml
Build the container and push yourself: First change the IMAGE variable in Makefile (eg to "you/clixon_example). Then build and push:
make docker
make push
sudo docker run -ti --rm you/clixon_example
Note that the configuration database is internal in the container, so
it is deleted if the container is restarted. To make the configuration
database persistent, you need to mount running_db using -v
Plugins
The example includes a restonf, netconf, CLI and two backend plugins. Each plugin is initiated with an API struct followed by a plugin init function. The content of the API struct is different depending on what kind of plugin it is. The plugin init function may also include registering RPC functions, see below is for a backend.
static clixon_plugin_api api = {
"example", /* name */
clixon_plugin_init,
plugin_start,
plugin_exit,
.ca_reset=plugin_reset,/* reset */
.ca_statedata=plugin_statedata, /* statedata */
.ca_trans_begin=NULL, /* trans begin */
.ca_trans_validate=transaction_validate,/* trans validate */
.ca_trans_complete=NULL, /* trans complete */
.ca_trans_commit=transaction_commit, /* trans commit */
.ca_trans_end=NULL, /* trans end */
.ca_trans_abort=NULL /* trans abort */
};
clixon_plugin_api *
clixon_plugin_init(clicon_handle h)
{
/* Optional callback registration for RPC calls */
rpc_callback_register(h, fib_route, NULL, "fib-route");
/* Return plugin API */
return &api; /* Return NULL on error */
}