Preview
Rate this lesson

Table of Contents

netconf subtree filter is the second filter method to limit the output of configuration or statistics to only show interesting section.

Subtree filters must be supported by every netconf implementation, but xpath filters, discussed in the previous section, may not be supported.

Netconf Subtree and XPath Filter

In the previous sections, we learned how to find the Yang data model related to any part of the configuration or statistics.

In the XPath filter we have to specify the path to reach the interesting part, but in the Subtree filter we have to specify the XML skeleton section to reach the interesting part of the configuration or statistics.

These are the sample xpath and subtree filters for getting BGP configuration and incoming interface statistics.

netconf sample xpath and subtree filters
netconf sample xpath and subtree filters

If we know which yang data model is used for each part of configuration or statistic, then it is very easy to get xpath or subtree filter.

In the previous sections, we learned how to find the appropriate configuration yang data model and also the statistics yang data model.

Netconf Subtree Filter

There are usually two methods for extracting subtree filters as we also saw with the xpath filter.

usual procedure to get xpath and subtree filter for configuration and statistics
usual procedure to get xpath and subtree filter for configuration and statistics

We’ll return the entire configuration of an example network device, including that specific part of the configuration, and then grep the output to include a keyword in our interesting part of the configuration.

The other method is to find subtree filter based on the sample XML skeleton of the Yang data model. This method is often used to get the statistics.

In the following we will demonstrate two examples. Subtree filter with “netconf_get_config” to filter configuration output and subtree filter with “netconf_get” to filter statistic output.

Netconf Subtree Configuration Filter Example

This is the first script to use subtree to filter configuration output.

majid@ubuntu2204tls:~/devnet/pyhton_nornir/2023/12.netconf$ cat 12.4.netconf_subtree_filter_get_config.py
from nornir import InitNornir
from nornir_scrapli.tasks import netconf_get_config
#from nornir_netconf.plugins.tasks import netconf_get_config
from nornir_utils.plugins.functions import print_result

nr = InitNornir(config_file="config.yaml")

filter1 = """
  <interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
  </interfaces>
"""

filter2 = """
    <native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
      <router>
      </router>
    </native>
"""

filter3 = """
    <native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
      <router>
        <router-ospf xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-ospf">
        </router-ospf>
      </router>
    </native>
"""

filter4 = """
    <network-instances xmlns="http://openconfig.net/yang/network-instance">
      <network-instance>
        <protocols>
          <protocol>
            <bgp>
            </bgp>
          </protocol>
        </protocols>
      </network-instance>
    </network-instances>
"""

filter5 = """
    <native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
      <router>
        <bgp xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-bgp">
        </bgp>
      </router>
    </native>
"""


def netconf_subtree_get_config(task):
    task.run(task=netconf_get_config, source="running", filter_type="subtree", filter_=filter5)
#    task.run(task=netconf_get_config, source="running", xmldict="false", filter_type="subtree", path=filter3)

results = nr.run(task=netconf_subtree_get_config)
print_result(results)

The task “netconf_get_config” from “nornir_scrapli” or “nornir_netconf” is used to get the configuration.

The “filter_type” parameter is configured as a subtree and the “filter_” or “path” parameter is used to filter the configuration output.

Here I have listed five subtree filter as examples.

The first filter from “ietf-interfaces” yang data model is used to filter interface configuration.

<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
</interfaces>

The second filter from “Cisco-IOS-XE-native” yang data model display routing protocol configuration of network devices.

<native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
  <router>
  </router>
</native>

The third filter from “Cisco-IOS-XE-native” yang data model is to limit the output to the OSPF configuration.

<native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
  <router>
    <router-ospf xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-ospf">
    </router-ospf>
  </router>
</native>

Both the fourth and fifth filters are used to filter the output to the BGP configuration, but the fourth from “openconfig-network-instance” Yang data model and the fifth from “Cisco-IOS-XE-native” Yang data model.

<network-instances xmlns="http://openconfig.net/yang/network-instance">
  <network-instance>
    <protocols>
      <protocol>
        <bgp>
        </bgp>
      </protocol>
    </protocols>
  </network-instance>
</network-instances>
<native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
  <router>
    <bgp xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-bgp">
    </bgp>
  </router>
</native>

But the question is, how can I extract these subtree filters for the configuration output?

I will get the entire configuration using the script that we discussed in the previous sections and save the output in a text file.

Then I grep the output text file to look for the lines that contain the keyword for an interesting part of configuration and also a few lines before that, using the “-B” option in the grep command.

In our example I want to filter the BGP configuration and therefore use the BGP AS number “65500” as the keyword to search in the output file.

[email protected]:~/devnet/pyhton_nornir/2023/12.netconf$ python3 12.1.netconf_get_config.py > output.txt
[email protected]:~/devnet/pyhton_nornir/2023/12.netconf$ grep 65500 -B 5 output.txt
          </trustpoint>
        </pki>
      </crypto>
      <router>
        <bgp xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-bgp">
          <id>65500</id>
--
          </table>
        </tables>
        <protocols>
          <protocol>
            <identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:BGP</identifier>
            <name>65500</name>
            <config>
              <identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:BGP</identifier>
              <name>65500</name>
            </config>
            <bgp>
              <global>
                <config>
                  <as>65500</as>

Based on the grep command output I can now find some useful XML tags to search in the output text file to find the subtree filter structure.

Let’s run the script once with filter 4 and once with filter 5 to see the result.

Filter 4:

<network-instances xmlns="http://openconfig.net/yang/network-instance">
  <network-instance>
    <protocols>
      <protocol>
        <bgp>
        </bgp>
      </protocol>
    </protocols>
  </network-instance>
</network-instances>
[email protected]:~/devnet/pyhton_nornir/2023/12.netconf$ python3 12.4.netconf_subtree_filter_get_config.py
netconf_subtree_get_config******************************************************
* R1 ** changed : False ********************************************************
vvvv netconf_subtree_get_config ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
---- netconf_get_config ** changed : False ------------------------------------- INFO
<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
  <data>
    <network-instances xmlns="http://openconfig.net/yang/network-instance">
      <network-instance>
        <protocols>
          <protocol>
            <bgp>
              <global>
                <config>
                  <as>65500</as>
                  <router-id>1.1.1.1</router-id>
                </config>
                <graceful-restart>
                  <config>
                    <enabled>false</enabled>
                  </config>
                </graceful-restart>
                <route-selection-options>
                  <config>
                    <always-compare-med>false</always-compare-med>
                    <external-compare-router-id>true</external-compare-router-id>
                  </config>
                </route-selection-options>
              </global>
              <neighbors>
                <neighbor>
                  <neighbor-address>2.2.2.2</neighbor-address>
                  <config>
                    <neighbor-address>2.2.2.2</neighbor-address>
                    <peer-as>65501</peer-as>
                  </config>
                  <timers>
                    <config>
                      <hold-time>180.0</hold-time>
                      <keepalive-interval>60.0</keepalive-interval>
                    </config>
                  </timers>
                  <ebgp-multihop>
                    <config>
                      <enabled>false</enabled>
                    </config>
                  </ebgp-multihop>
                </neighbor>
              </neighbors>
            </bgp>
          </protocol>
        </protocols>
      </network-instance>
    </network-instances>
  </data>
</rpc-reply>

^^^^ END netconf_subtree_get_config ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Filter 5:

<native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
  <router>
    <bgp xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-bgp">
    </bgp>
  </router>
</native>
[email protected]:~/devnet/pyhton_nornir/2023/12.netconf$ python3 12.4.netconf_subtree_filter_get_config.py
netconf_subtree_get_config******************************************************
* R1 ** changed : False ********************************************************
vvvv netconf_subtree_get_config ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
---- netconf_get_config ** changed : False ------------------------------------- INFO
<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
  <data>
    <native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
      <router>
        <bgp xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-bgp">
          <id>65500</id>
          <bgp>
            <log-neighbor-changes>true</log-neighbor-changes>
            <router-id>
              <ip-id>1.1.1.1</ip-id>
            </router-id>
          </bgp>
          <neighbor>
            <id>2.2.2.2</id>
            <remote-as>65501</remote-as>
          </neighbor>
        </bgp>
      </router>
    </native>
  </data>
</rpc-reply>

^^^^ END netconf_subtree_get_config ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Netconf Subtree Statistical Filter Example

This is the another script to use subtree to filter statistical output.

majid@ubuntu2204tls:~/devnet/pyhton_nornir/2023/12.netconf$ cat 12.5.netconf_subtree_filter_get.py
from nornir import InitNornir
from nornir_scrapli.tasks import netconf_get
#from nornir_netconf.plugins.tasks import netconf_get
from nornir_utils.plugins.functions import print_result

nr = InitNornir(config_file="config.yaml")

filter1 = """
  <interfaces xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-interfaces-oper">
  </interfaces>
"""

filter2 = """
  <interfaces xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-interfaces-oper">
    <interface>
      <statistics>
      </statistics>
    </interface>
  </interfaces>
"""

filter3 = """
  <interfaces xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-interfaces-oper">
    <interface>
      <statistics>
          <in-octets>
          </in-octets>
      </statistics>
    </interface>
  </interfaces>
"""

filter4 = """
  <interfaces xmlns="http://openconfig.net/yang/interfaces">
      <interface>
        <state>
          <name>
          </name>
          <counters>
            <in-octets>
            </in-octets
          </counters>
        </state>
      </interface>
  </interfaces>
"""

def netconf_subtree_get(task):
    task.run(task=netconf_get, filter_type="subtree", filter_=filter4)
#    task.run(task=netconf_get, xmldict="false", filter_type="subtree", path=filter4)

results = nr.run(task=netconf_subtree_get)
print_result(results)

The task “netconf_get” from “nornir_scrapli” or “nornir_netconf” is used to mostly to get the statistics.

The “filter_type” parameter is configured as a subtree and the “filter_” or “path” parameter is used to filter the statistics output.

Here I have listed four subtree filter as examples.

In the first and second filter all interface statistics from “Cisco-IOS-XE-interfaces-oper” yang data model will be displayed.

<interfaces xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-interfaces-oper">
</interfaces>
<interfaces xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-interfaces-oper">
  <interface>
    <statistics>
    </statistics>
  </interface>
</interfaces>

In the third and fourth filter, incoming interface statistics from “Cisco-IOS-XE-interfaces-oper” and “openconfig-interfaces” yang data model will be displayed.

<interfaces xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-interfaces-oper">
  <interface>
    <statistics>
        <in-octets>
        </in-octets>
    </statistics>
  </interface>
</interfaces>
<interfaces xmlns="http://openconfig.net/yang/interfaces">
    <interface>
      <state>
        <name>
        </name>
        <counters>
          <in-octets>
          </in-octets>
        </counters>
      </state>
    </interface>
</interfaces>

How extract Subtree Filters?

The question is how I could extract subtree filters for these statistics?

In the previous section, we learned that the Cisco statistical yang data models differ from the configuration but with the same name as the configuration yang data model with an “-oper” at the end of the name.

configuration and statistics data modeling in cisco ietf and openconfig
configuration and statistics data modeling in cisco ietf and openconfig

We also learned that the IETF and openconfig statistical yang models are the same as the configuration yang data models, but with different XML tags inside the yang file.

Now that we know the name of the Yang data model, we know that for IETF and openconfig, when we get the entire configuration, statistical information is also included in it.

But for the Cisco statistical Yang data model, we can simply use the sample XML skeleton to find the related XML tag for each statistic and XML data structure to filter the output.

As an example let’s check sample XML skeleton of “Cisco-IOS-XE-interfaces-oper” yang data model which keeps statistical information of interfaces.

[email protected]:~/yang/vendor/cisco/xe/1791$ pyang -f sample-xml-skeleton Cisco-IOS-XE-interfaces-oper.yang
<?xml version='1.0' encoding='UTF-8'?>
<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <interfaces xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-interfaces-oper">
    <interface>
      <name/>
      <interface-type/>
      <admin-status/>
      <oper-status/>
      <last-change/>
      <if-index/>
      <phys-address/>
	  ...
      <speed/>
      <statistics>
        <discontinuity-time/>
        <in-octets/>
...

Now let’s run the script for filter 3 and filter 4 to see the result of incoming interface statistics.

Filter3:

<interfaces xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-interfaces-oper">
  <interface>
    <statistics>
        <in-octets>
        </in-octets>
    </statistics>
  </interface>
</interfaces>
[email protected]:~/devnet/pyhton_nornir/2023/12.netconf$ python3 12.5.netconf_subtree_filter_get.py
netconf_subtree_get*************************************************************
* R1 ** changed : False ********************************************************
vvvv netconf_subtree_get ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
---- netconf_get ** changed : False -------------------------------------------- INFO
<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
  <data>
    <interfaces xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-interfaces-oper">
      <interface>
        <statistics>
          <in-octets>0</in-octets>
        </statistics>
      </interface>
      <interface>
        <statistics>
          <in-octets>2765799</in-octets>
        </statistics>
      </interface>
      <interface>
        <statistics>
          <in-octets>0</in-octets>
        </statistics>
      </interface>
      <interface>
        <statistics>
          <in-octets>0</in-octets>
        </statistics>
      </interface>
      <interface>
        <statistics>
          <in-octets>0</in-octets>
        </statistics>
      </interface>
    </interfaces>
  </data>
</rpc-reply>

^^^^ END netconf_subtree_get ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Filter 4:

<interfaces xmlns="http://openconfig.net/yang/interfaces">
    <interface>
      <state>
        <name>
        </name>
        <counters>
          <in-octets>
          </in-octets>
        </counters>
      </state>
    </interface>
</interfaces>
[email protected]:~/devnet/pyhton_nornir/2023/12.netconf$ python3 12.5.netconf_subtree_filter_get.py
netconf_subtree_get*************************************************************
* R1 ** changed : False ********************************************************
vvvv netconf_subtree_get ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
---- netconf_get ** changed : False -------------------------------------------- INFO
<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
  <data>
    <interfaces xmlns="http://openconfig.net/yang/interfaces">
      <interface>
        <state>
          <name>GigabitEthernet1</name>
          <counters>
            <in-octets>2801762</in-octets>
          </counters>
        </state>
      </interface>
      <interface>
        <state>
          <name>GigabitEthernet2</name>
          <counters>
            <in-octets>0</in-octets>
          </counters>
        </state>
      </interface>
      <interface>
        <state>
          <name>GigabitEthernet3</name>
          <counters>
            <in-octets>0</in-octets>
          </counters>
        </state>
      </interface>
      <interface>
        <state>
          <name>Loopback100</name>
          <counters>
            <in-octets>0</in-octets>
          </counters>
        </state>
      </interface>
    </interfaces>
  </data>
</rpc-reply>

^^^^ END netconf_subtree_get ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

For each interface the number of bytes coming to the interface is displayed.

Netconf subtree code examples can be downloaded from this links:

Back to: YANG based Network Automation using NETCONF RESTCONF gNMI (in Progress) > Network Automation using NETCONF

Leave a Reply

Your email address will not be published. Required fields are marked *

Post comment