This lesson will show you how to build and install a Server Instrumentation Library (SIL) created from a YANG module.


Pre-Requisites


You should have completed YumaPro Installation Guide,  Prepare a YANG module and YANG and SIL Module Components.


YumaPro built-in ietf-interfaces YANG module example


Implementation details:

  - The example is based on RFC 7223, NOT the newer RFC 8343

  - The interface configuration is not implemented. The /interfaces subtree will be empty and configuring interfaces does not do anything

  - The /interfaces-state subtree is implemented and should show interfaces on the linux system

  - No plans at this time to update to NMDA version


Before we start to modify the SIL code for your ietf-interfaces YANG module it would be useful to see how the real SIL code may look like, the code that is filled in with an instrumentation to retrieve the interfaces counters.


YumaPro SDK provides a pre-built implementation of the ietf-interfaces SIL with sample instrumentation for the operational state data in the library libietf-interfaces.so. Note that this library is only for Linux systems. To use the library you need the YANG modules required for the instrumentation to be loaded into the server. You can accomplish this by running the server with the command:


NOTE: YANG module iana-if-type must be loaded as well as ietf-interfaces module in order to provide definitions to interface->type leaf. With out this module you will not be able to modify the interface list entry.


mydir> netconfd-pro --log-level=debug4 --access-control=off  \
    --module=iana-if-type --module=ietf-interfaces


In a second terminal window start yangcli-pro and connect to the server. You can now display the live data from the system interfaces. By executing “sget /interfaces-state/interface/statistics” multiple times. You will see the YANG leaf counters updating that will look something like this:


mydir> yangcli-pro log-level=debug4
> connect server=localhost user=john password=pass
john@localhost> sget /interfaces-state/interface/statistics

Filling container /interfaces-state/interface/statistics:
RPC Data Reply 1 for session 4 [default]:

rpc-reply {
  data {
    interfaces-state {
      interface lo {
        name lo
        statistics {
          in-octets 7027687
          in-unicast-pkts 78233
          in-multicast-pkts 0
          in-discards 0
          in-errors 0
          out-octets 7027687
          out-unicast-pkts 78233
          out-discards 0
          out-errors 0
        }
      }
      interface enp0s3 {
        name enp0s3
        statistics {
          in-octets 261979910
          in-unicast-pkts 223539
          in-multicast-pkts 73300
          in-discards 0
          in-errors 0
          out-octets 10326048
          out-unicast-pkts 119365
          out-discards 0
          out-errors 0
        }
      }
    }
  }
}


The pre-built library includes support for standard Linux interfaces. You can compare the values (they may be a little off depending on how close the two samples are and the data rate) from the pre-built library with the Linux system by using the command ifconfig:

mydir> ifconfig
  enp0s3 Link encap:Ethernet HWaddr 07:c3:1a:98:d2:34
  inet addr:192.168.0.89 Bcast:192.168.0.255 Mask:255.255.255.0
  inet6 addr: fe70::5d61:963d:b802:35e/64 Scope:Link
  inet6 addr: 2305:e000:7b92:3f00:f068:d9b8:28a1:fe81/64 Scope:Global
  inet6 addr: 2305:e000:7b92:3f00:5a9e:57cd:7d8b:f8ca/64 Scope:Global
  UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
  RX packets:298724 errors:0 dropped:0 overruns:0 frame:0
  TX packets:120206 errors:0 dropped:0 overruns:0 carrier:0
  collisions:0 txqueuelen:1000
  RX bytes:262341941 (262.3 MB) TX bytes:10422964 (10.4 MB)

  lo Link encap:Local Loopback
  inet addr:127.0.0.1 Mask:255.0.0.0
  inet6 addr: ::1/128 Scope:Host
  UP LOOPBACK RUNNING MTU:65536 Metric:1
  RX packets:79452 errors:0 dropped:0 overruns:0 frame:0
  TX packets:79452 errors:0 dropped:0 overruns:0 carrier:0
  collisions:0 txqueuelen:1
  RX bytes:7177588 (7.1 MB) TX bytes:7177588 (7.1 MB)


You will see while yangcli-pro is displaying the operational data, in the terminal window that netconfd-pro is running in the logging output displays the messages between the yangcli-pro client and server. The response message includes the ietf-interfaces statistics RPC reply is something like:


yuma-netconf:input {
  filter {
    ietf-interfaces:interfaces-state {
    interface {
      statistics
    }
  }
  filter.metaQ
  yuma-ncx:type subtree
  }
}

...

<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply message-id="1"
  xmlns:ncx="http://netconfcentral.org/ns/yuma-ncx"
  ncx:last-modified="2018-02-01T01:54:29Z" ncx:etag="57380"
  xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <data>
    <interfaces-state xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
    <interface>
      <name>lo</name>
      <statistics>
        <in-octets>7027687</in-octets>
        <in-unicast-pkts>78233</in-unicast-pkts>
        <in-multicast-pkts>0</in-multicast-pkts>
        <in-discards>0</in-discards>
        <in-errors>0</in-errors>
        <out-octets>7027687</out-octets>
        <out-unicast-pkts>78233</out-unicast-pkts>
        <out-discards>0</out-discards>
        <out-errors>0</out-errors>
      </statistics>
    </interface>
    <interface>
      <name>enp0s3</name>
        ...

    </interface>
  </interfaces-state>
</data>
</rpc-reply>
agt_cb: Enter run_command_complete
ses_msg: free msg 0x1eb5f20 for session 4


Refer to the attachment archive with YumaPro modified SIL code for the ietf-interfaces YANG module (libietf-interfaces-yumapro).


Edit, Build and Install stub SIL code for ietf-interfaces YANG module example


Now, you can experiment and modify your own stub SIL code library for your ietf-interfaces YANG module that was generated in previous steps (articles). Refer to the attached archive that has some custom modifications that illustrates how to add instrumentation to the stub code (ietf-interfaces-modified). In this example, we will add some hardwire values to a single interfaces with some hardwired counters values.


First, in your editor search for the /interfaces/interface GET2 callback u_ietf_interfaces_interfaces_state_interface_get to hardwire a list interface key value and some other leafs values. For example, the key configurations may look as follows:

    /***** ADD RETURN KEYS AND REMOVE THIS COMMENT ****/


    /* Pretend there is only one interface entry with name vlan1
     * This is just a simpified example.
     */
    obj_template_t *name_obj =
        obj_find_child(obj,
                       y_ietf_interfaces_M_ietf_interfaces,
                       (const xmlChar *)"name");

    val_value_t *retval =
        val_make_simval_obj(name_obj,
                            (const xmlChar *)"vlan1",
                            &res);
    if (retval) {
        if (name_fixed) {
            VAL_SET_FIXED_VALUE(retval);
        }
        getcb_add_return_key(get2cb, retval);
    }

    if (GETCB_GET2_FIRST_RETURN_KEY(get2cb) == NULL) {
        return ERR_NCX_NO_INSTANCE;
    }

    /* For GETNEXT, set the more_data flag to TRUE
     * This will be just a single entry in the list so set
     * more_data to FALSE.
     */
    GETCB_GET2_MORE_DATA(get2cb) = FALSE;


As you may noticed the API to generate a return val_value value is val_make_simval_obj(). This is the easiest and most universal API to generate val_value value. It accepts string as a value for easier usage. It can be used for any data type, all you need to know is the object template for this val_value and the actual value that you want to use for the val_value.


Now, add the log_debug line below and also some hardwired value for the interface list entry type leaf node.


        log_debug("\n\n ****** HERE IS SOME TEXT THAT STANDS OUT! ******\n");

        /* Retrieve the value of this terminal node and
         * add with getcb_add_return_val */

        if (!xml_strcmp(name, y_ietf_interfaces_N_type)) {
            /* leaf type (identityref) */

            retval =
                val_make_simval_obj(childobj,
                                    (const xmlChar *)"ianaift:l2vlan",
                                    &res);
            if (retval) {
                getcb_add_return_val(get2cb, retval);
            }


Then, search for the /interfaces-state/interface/statistics GET2 callback u_ietf_interfaces_interfaces_state_interface_statistics_get to hardwire some counters to the statistics container of the list interface. For example, the counters configurations may look as follows:


        /* Retrieve the value of this terminal node and
         * add with getcb_add_return_val */

        if (!xml_strcmp(name, y_ietf_interfaces_N_discontinuity_time)) {
            /* leaf discontinuity-time (string) */

        } else if (!xml_strcmp(name, y_ietf_interfaces_N_in_octets)) {
            /* leaf in-octets (uint64) */

            retval =
                val_make_simval_obj(childobj,
                                    (const xmlChar *)"1000",
                                    &res);
            if (retval) {
                getcb_add_return_val(get2cb, retval);
            }


Save your change and exit your editor. Change directory to the root directory for the library and rebuild and install the SIL code:


src> cd ..
ietf-interfaces> make
ietf-interfaces> sudo make install


Now when you run the server and yangcli-pro again as before, entering “sget /interfaces-state/interface/statistics” in yangcli-pro, you will see the new log message you created to be output in the server log output and output for a new hardwired interface entry.


mydir> netconfd-pro --log-level=debug4 --access-control=off  \
    --module=iana-if-type --module=ietf-interfaces


Note, that since you build your own SIL code for ietf-interfaces YANG module this build will overwrite build-in YumaPro SIL code and after you start the server, it will load a newly built SIL code that you just modified.

In order to enable built-in YumaPro code again rebuild the server or if you have an access to the sources rebuild as follows:


> cd <yumapro_source>/libietf-interfaces
libietf-interfaces> make
libietf-interfaces> sudo make install


As a conclusion, after you send SGET request from the yangcli-pro client you will see a new log message you created  and output for a new hardwired interface entry processing and an actual RPC reply message as follows:


agt_util_validate_filter:
nc:input {
  filter {
    if:interfaces-state 
  }
  ysys:depth unbounded
}
agt_rpc: sending data <rpc-reply> for ses 3 msg '2'

xml_wr: skip xmlns duplicate (9=http://netconfcentral.org/ns/yuma-ncx)
Output with xml_wr obj for node 'interfaces-state'
getcb: process_get2_child_obj for 'interfaces-state' in normal API mode
getcb: skip GET2 callback for NP-con 'interfaces-state' no terminals
getcb: process_get2_child_obj for 'interface' in normal API mode
getcb: start GET_VALUE for 'interface'

 ****** HERE IS SOME TEXT THAT STANDS OUT! ******

getcb: end GET_VALUE for 'interface', status (ok)
getcb: process_get2_child_obj for 'statistics' in normal API mode
getcb: GETNEXT transfer name from parent_return_keyQ to keyQ add node
getcb: start GET_VALUE for 'statistics'
getcb: end GET_VALUE for 'statistics', status (ok)
ses_msg: send 1.1 buff:663 for s:3

trace_buff:

#653
<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply message-id="2"
 xmlns:ncx="http://netconfcentral.org/ns/yuma-ncx"
 ncx:last-modified="2020-03-05T22:28:35Z" ncx:etag="13"
 xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
 <data>
  <interfaces-state xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
   <interface>
    <name>vlan1</name>
    <type
     xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type">ianaift:l2vlan</type>
    <admin-status>up</admin-status>
    <speed>500</speed>
    <statistics>
     <in-octets>1000</in-octets>
     <out-octets>0</out-octets>
    </statistics>
   </interface>
  </interfaces-state>
 </data>
</rpc-reply>


In yangcli-pro you may see something as follows:


RPC Data Reply 2 for session 3 [default]: 

yuma-netconf:rpc-reply {
  data {
    ietf-interfaces:interfaces-state {
      interface  vlan1 {
        name vlan1
        type ianaift:l2vlan
        admin-status up
        speed 500
        statistics {
          in-octets 1000
          out-octets 0
        }
      }
    }
  }
}

Start inbound <rpc-reply> validation for 'yuma-netconf:get'
Inbound <rpc-reply> validation PASSED for 'yuma-netconf:get'
Reply for session 'default' state: 'rpc-reply-wait' errors: no

etag: 13 

yangcli: exit reply handler for SCB 1 REQ '2'
user@localhost> 




Next Lesson:
Operational Data