clixon/example
Olof hagsand ae1af8da9e * NACM extension (RFC8341)
* NACM module support (RFC8341 A1+A2)
   * Recovery user "_nacm_recovery" added.
     * Example use is restconf PUT when NACM edit-config is permitted, then automatic commit and discard are permitted using recovery user.
   * Example user changed adm1 to andy to comply with RFC8341 example

 * Yang code upgrade (RFC7950)
   * RPC method input parameters validated
     * see https://github.com/clicon/clixon/issues/4
* Correct XML namespace handling
   * XML multiple modules was based on "loose" semantics so that yang modules were found by iterating thorugh namespaces until a match was made. This did not adhere to proper [XML namespace handling](https://www.w3.org/TR/2009/REC-xml-names-20091208), and causes problems with overlapping names and false positives. Below see XML accepted (but wrong), and correct namespace declaration:
```
      <rpc><my-own-method></rpc> # Wrong but accepted
      <rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> # Correct
        <my-own-method xmlns="http://example.net/me/my-own/1.0">
      </rpc>
```
   * To keep old loose semantics set config option CLICON_XML_NS_ITERATE (true by default)
   * XML to JSON translator support for mapping xmlns attribute to module name prefix.
   * Default namespace is still "urn:ietf:params:xml:ns:netconf:base:1.0"
   * See https://github.com/clicon/clixon/issues/49
* Changed all make tags --> make TAGS
* Keyvalue datastore removed (it has been disabled since 3.3.3)
* debug rpc added in example application (should be in clixon-config).
2018-12-16 19:49:19 +01:00
..
systemd Added systemd example files under example/systemd 2018-07-13 13:13:11 +02:00
Dockerfile deprecated readdir_r with readdir 2018-08-05 16:34:45 +02:00
example.xml * Yang Support of submodule, include and belongs-to. 2018-12-01 18:17:42 +01:00
example.yang * NACM extension (RFC8341) 2018-12-16 19:49:19 +01:00
example_backend.c Backward compatible testing w streams. Nchan manual tests. 2018-11-04 16:56:56 +01:00
example_backend_nacm.c * Generilized top-level yang parsing functions 2018-10-07 11:04:33 +02:00
example_cli.c * NACM extension (RFC8341) 2018-12-16 19:49:19 +01:00
example_cli.cli * Yang Configure options changed 2018-12-03 21:16:35 +01:00
example_netconf.c * Experimental NACM RFC8341 Network Configuration Access Control Model. 2018-04-19 22:44:15 +02:00
example_restconf.c * NACM extension (RFC8341) 2018-12-16 19:49:19 +01:00
iana-if-type@2014-05-08.yang * Support for YANG identity and identityref according to RFC 7950 Sec 7.18 and 9.10 2018-06-03 15:36:05 +02:00
ietf-inet-types@2013-07-15.yang Inital commit 2016-02-22 22:17:30 +01:00
ietf-interfaces@2014-05-08.yang Inital commit 2016-02-22 22:17:30 +01:00
ietf-ip@2014-06-16.yang Generic map_str2int generic mapping tables; Removed vector return values from xmldb_get() 2017-06-21 21:02:09 +02:00
ietf-ipsec@2016-03-09.yang order lists according to yang order 2016-12-27 17:31:30 +01:00
ietf-ipv4-unicast-routing@2014-10-26.yang Inital commit 2016-02-22 22:17:30 +01:00
ietf-ipv6-unicast-routing@2014-10-26.yang Inital commit 2016-02-22 22:17:30 +01:00
ietf-routing@2014-10-26.yang Inital commit 2016-02-22 22:17:30 +01:00
ietf-yang-types@2013-07-15.yang Inital commit 2016-02-22 22:17:30 +01:00
Makefile.in * Set access/subscribe base URL with: CLICON_STREAM_URL_PREFIX (default https\ 2018-10-15 22:08:38 +02:00
README.md * NACM extension (RFC8341) 2018-12-16 19:49:19 +01:00

Clixon example

This directory contains a Clixon example which includes a simple example. It contains the following files:

  • example.xml The configuration file. See yang/clixon-config@.yang for all available fields.
  • example.yang The yang spec of the example. It mainly includes ietf routing and IP modules.
  • example_cli.cli CLIgen specification.
  • example_cli.c CLI callback plugin containing functions called in the cli file above: a generic callback (mycallback) and an RPC (fib_route_rpc).
  • example_backend.c Backend callback plugin including example of:
    • transaction callbacks (validate/commit),
    • notification,
    • rpc handler
    • state-data handler, ie non-config data
  • example_backend_nacm.c Secondary backend plugin. Plugins are loaded alphabetically.
  • example_restconf.c Restconf callback plugin containing an HTTP basic authentication callback
  • example_netconf.c Netconf callback plugin
  • Makefile.in Example makefile where plugins are built and installed

Compile and run

Before you start,

    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

Setting data example using netconf

<rpc><edit-config><target><candidate/></target><config>
      <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"><configuration><interfaces><interface><ipv4/></interface></interfaces></configuration></filter></get-config></rpc>]]>]]>
<rpc><get-config><source><candidate/></source><filter type="xpath" select="/interfaces/interface/ipv4"/></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><stream>EXAMPLE</stream></create-subscription></rpc>]]>]]>
<rpc-reply><ok/></rpc-reply>]]>]]>
<notification><event>Routing notification</event></notification>]]>]]>
<notification><event>Routing notification</event></notification>]]>]]>
...

This can also be triggered via the CLI:

cli> notify 
cli> Routing notification
Routing notification
...

Restconf support is also supported, see [../apps/restconf/README.md].

Initializing a plugin

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 */
}

Operation data

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:

cli> rpc ipv4
<rpc-reply>
   <ok/>
</rpc-reply>

The example works by creating a netconf rpc call and sending it to the backend: (see the fib_route_rpc() function).

  <rpc>
    <fib-route>
      <routing-instance-name>ipv4</routing-instance-name>
    </fib-route>
   </rpc>

In the backend, a callback is registered (fib_route()) which handles the RPC.

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><ok/></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, in contrast to config data. p In YANG state data is specified with "config false;". In the example, interface-state is state data.

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 files

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