Network Automation ramblings by Kristian Larsson

Posts tagged "YANG":

29 Jan 2020

Convert XML to JSON

Any network device that has a NETCONF interface will send data using XML. NETCONF interfaces are typically YANG modeled. If you prefer JSON or YAML, you can easily convert YANG modeled data from an XML representation.

This is a hands on guide. Read on to the end if you want to understand why this can only be correctly done for YANG modeled data or why it's otherwise difficult and why you need the YANG model.

We'll use yanglint. yanglint comes as a part of libyang. Install libyang and you'll get yanglint.

Feed the XML together with the YANG model(s) describing the data into yanglint and ask for a conversion of the data by using --format json. yanglint will also validate the XML data according to YANG model.

kll@minemacs:~/yang-test$ yanglint --strict tubecats.yang data1.xml --format json 
{
  "tubecats:internet": {
    "cat": [
      {
        "name": "jingles"
      },
      {
        "name": "fluffy"
      }
    ]
  }
}

kll@minemacs:~/yang-test$ echo $?

The output is a JSON document. You can pipe it to a file or use -o FILE to specify the output filename.

The output was converted from this input XML:

<ns0:data xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0">
    <tc:internet xmlns:tc="http://plajjan.github.io/ns/yang/tubecats">
        <tc:cat>
            <tc:name>jingles</tc:name>
        </tc:cat>
        <tc:cat>
            <tc:name>fluffy</tc:name>
        </tc:cat>
    </tc:internet>
</ns0:data>

And here is the YANG module that defines the schema for the data:

module tubecats {
    namespace "http://plajjan.github.io/ns/yang/tubecats";
    prefix tc;

    revision 2017-03-15 {
        description "First and only version";
    }

    container internet {
        list cat {
            key name;
            leaf name {
                type string;
            }
        }
    }
}

Conversion to and from YAML

As there is no standardized representation of YANG modeled data for YAML, yanglint does not support YAML as an input or output format. However, as the encoding of data in YAML has the same concepts as JSON, it is trivial to convert from JSON to YAML or vice versa with standard tools. Here is an example Python script that will do the conversion:

#!/usr/bin/env python3
import json
import sys
import yaml

jf = open(sys.argv[1])

print(yaml.dump(json.load(jf)))

and similarly in the reverse direction:

#!/usr/bin/env python3
import json
import sys
import yaml

yf = open(sys.argv[1])

print(json.dumps(yaml.load(yf)))

To use it, we pipe the output from our XML to JSON conversion on to the Python script that does JSON to YAML conversion. Behold:

kll@minemacs:~/yang-test$ yanglint --strict tubecats.yang data1.xml --format json | ./j2y.py /dev/stdin
tubecats:internet:
cat:
- {name: jingles}
- {name: fluffy}

kll@minemacs:~/yang-test$

And again, for the reverse direction we pipe it yet another time to the YAML to JSON Python script and end up with JSON data again.

kll@minemacs:~/yang-test$ yanglint --strict tubecats.yang data1.xml --format json | ./j2y.py /dev/stdin | ./y2j.py /dev/stdin | jq
{
    "tubecats:internet": {
        "cat": [
            {
                "name": "jingles"
            },
            {
                "name": "fluffy"
            }
        ]
    }
}

I wrote the program to read a file and not stdin so when piping we give it the file /dev/stdin which then accomplishes the same thing. I also run jq at the end to nicely format the JSON output as json.dumps just writes the whole JSON string on one line.

Why is it difficult to convert XML to JSON?

XML is a markup language to express nodes. A node can be contained within another node and there can be sibling nodes. There are no constructs for things like lists (arrays) or associative lists (hashes/dicts). JSON or YAML on the other hand has constructs for lists - it is embedded in the format itself. When converting to JSON we must know if something is a list but that information is simply not contained within XML, thus there is no generic conversion that produces a standardized output.

However, with YANG we have two standardized representations with XML and JSON. These standards define what, for example a YANG list, looks like in XML or JSON. With the support of a YANG schema we can thus convert in a precise and lossless fashion between the two formats.

Tags: XML JSON YAML YANG
11 Nov 2019

What's the use of presence containers in YANG?

I got the question on what presence containers are good for - what makes them useful?

P-containers is often used a short term for presence containers, meaning a container that has a presence statement in under in. In contract there are also NP-containers, or non-presence containers, which are really just plain containers without a presence statement but sometimes it's easier being explicit what the container is about.

YANG is a rather neat data modeling language. It is simple yet expressive enough to often allow something to be modeled in multiple different ways. While we are de facto defining a model when we write something in YANG, I think of it more as describing something already existing. Like how you have a thought in your mind and when you speak it out aloud, all you do is dress it with words from the English (or some other) language. There are many ways in which you can express something in English and the meaning you convey will differ ever so slightly, yet that thought in your mind isn't shaped by the words you use to describe it. The words are there to describe the thought, not the other way around. Similarly with YANG, you have an object, something that exists in reality or in thought and now you must model it. It will very likely be a simplified model and lack some of the detail of the original but nonetheless it will be a model.

A container, in its most basic shape and form, offer nothing besides acting as a container - something that contains other things. Adding the presence statement to a container in YANG allows the presence of the container in the configuration to mean something.

Let's do a simple example. For the sake of brevity, I'm skipping various required nodes like namespace etc.

module router {
  container bgp {
    leaf asn {
      type uint32;
      description "AS number of this router";
    }
    leaf router-id {
      type uint32;
      description "router-id of this router";
    }
  }
}

On this router we can configure the AS number to be used for its BGP daemon through the configuration leaf asn. Similarly, we have the leaf router-id which can be set to the router-id of the device. The bgp container is a standard container, or NP-container, meaning that it only exists when a child node of it exists. If neither asn nor router-id is set, the bgp container won't show up in the configuration whereas if either asn or router-id is set, the bgp container will show up. Its presence or not does not carry any meaning beyond containing the asn and router-id leaf.

Now let's say we want to refine our model a bit. It's not possible to run a BGP daemon without having the asn and router-id configured, thus we make the two leaves mandatory!

module router {
  container bgp {
    leaf asn {
      type uint32;
      description "AS number of this router";
      mandatory true;
    }
    leaf router-id {
      type uint32;
      description "router-id of this router";
      mandatory true;
    }
  }
}

However, this raises the next problem. Now you always have to configure both asn and router-id, even when you don't want to run BGP! How do we fix this? We could add an enabled leaf under BGP, conveying whether BGP is enabled or not and only if it is enabled then must asn and router-id be set!

module router {
  container bgp {
    leaf enabled {
      type boolean;
      description "Enable BGP";
      default false;
    }
    leaf asn {
      type uint32;
      description "AS number of this router";
      mandatory true;
      when "../enabled='true'";
    }
    leaf router-id {
      type uint32;
      description "router-id of this router";
      mandatory true;
      when "../enabled='true'";
    }
  }
}

We also add a when statement to the asn and router-id leaves so they only show up after enabled has been set. The mandatory statement only has effect when the when statement evaluates to true. This works… but it's not natural. Remember how we aren't really defining the thing we are modeling? We are just observing it and then expressing what we see through the YANG model. There are occasions for when this when statement in combination with a mandatory true is the right solution but this is not it. I think the natural way of modeling this is by making the bgp container into a presence container!

module router {
  container bgp {
    presence bgp;
    leaf asn {
      type uint32;
      description "AS number of this router";
      mandatory true;
    }
    leaf router-id {
      type uint32;
      description "router-id of this router";
      mandatory true;
    }
  }
}

Now it becomes possible to explicitly configure the bgp container node itself. As soon as we have created the bgp node, the mandatory statements in under asn and router-id force us to also enter values for them, but without having set the bgp node, like when we simply don't want to run BGP, then we also are not required to enter the asn and router-id.

Even with bgp as a P-container, there's a reason to keep the enabled leaf; we might want to be able to configure BGP but not enable it. At least for a human, to shut down the BGP daemon, it is a lot easier to flip a single enabled leaf than it is to remove the entire BGP configuration. Having an enabled leaf allows this.

module router {
  container bgp {
    presence bgp;
    leaf enabled {
      type boolean;
      description "Enable BGP";
      default true;
    }
    leaf asn {
      type uint32;
      description "AS number of this router";
      mandatory true;
    }
    leaf router-id {
      type uint32;
      description "router-id of this router";
      mandatory true;
    }
  }
}

While my example is somewhat contrived I think it brings the point of across of what an elegant model might look like and when a P-container helps us achieve that goal. Happy modeling!

Tags: YANG
30 Oct 2017

YANG validation in the real world

Some time ago I wrote an [introductory post on how to validate data using YANG](/validating-data-with-YANG). A simple example as it were, it can be difficult to apply to the real world as there are some blanks to fill in. This time around we'll follow up and use the same tools to validate if the NETCONF / YANG interface of a Huawei router is sound and adheres to standards.

Evaluating whether NETCONF / YANG interfaces are RFC compliant is something I do on a rather frequent basis. Unfortunately I can't share all the YANG models or our configuration as both are secret or private in one way or another. I could perhaps have censored but that would likely have required much more time than I was willing to spend on this post.

The Huawei router is running a software build that is compiled for us (TeraStream) so you can't currently download or get your hands on this (unless you ask Huawei nicely to compile one for you too, I guess).

I got the YANG models separately from Huawei;

kll@lingloi:~/vrp-netconf/yang$ ls
huawei-aaa-action.yang
huawei-aaa-lam-action.yang
huawei-aaa-lam-type.yang
huawei-aaa-lam.yang
huawei-aaa-type.yang
huawei-aaa.yang
huawei-acl-action.yang
huawei-acl-type.yang
huawei-acl.yang
huawei-bfd-action.yang
huawei-bfd-type.yang
huawei-bfd.yang
huawei-bgp-action.yang
huawei-bgp-bgpcomm-action.yang
huawei-bgp-bgpcomm.yang
huawei-bgp-bgpmultiinstcomm.yang
huawei-bgp-type.yang
huawei-bgp.yang
huawei-dcn-action.yang
huawei-dcn-dscpremark.yang
huawei-dcn-type.yang
huawei-dcn.yang
huawei-devm-action.yang
huawei-devm-type.yang
huawei-devm.yang
huawei-dgmp-type.yang
huawei-dgmp.yang
huawei-dhcpv6-action.yang
huawei-dhcpv6-relay-action.yang
huawei-dhcpv6-relay-type.yang
huawei-dhcpv6-relay.yang
huawei-dhcpv6-server-action.yang
huawei-dhcpv6-server-type.yang
huawei-dhcpv6-server.yang
huawei-dhcpv6-type.yang
huawei-dhcpv6.yang
huawei-dns-action.yang
huawei-dns-type.yang
huawei-dns.yang
huawei-ethernet-action.yang
huawei-ethernet-stacking.yang
huawei-ethernet-type.yang
huawei-ethernet.yang
huawei-extension.yang
huawei-hwtacacs-action.yang
huawei-hwtacacs-type.yang
huawei-hwtacacs.yang
huawei-ifm-action.yang
huawei-ifmatm-type.yang
huawei-ifmatm.yang
huawei-ifmbundle-type.yang
huawei-ifmbundle.yang
huawei-ifmcpostrunk-type.yang
huawei-ifmcpostrunk.yang
huawei-ifm-flowalarm.yang
huawei-ifm-fr-type.yang
huawei-ifm-fr.yang
huawei-ifm-hdlc-type.yang
huawei-ifm-hdlc.yang
huawei-ifmima-type.yang
huawei-ifmima.yang
huawei-ifmlag-action.yang
huawei-ifmlag-type.yang
huawei-ifmlag.yang
huawei-ifmmp-type.yang
huawei-ifmmp.yang
huawei-ifmpostrunk-type.yang
huawei-ifmpostrunk.yang
huawei-ifm-pppbase-type.yang
huawei-ifm-pppbase.yang
huawei-ifmtrunk-action.yang
huawei-ifmtrunk-type.yang
huawei-ifmtrunk.yang
huawei-ifm-type.yang
huawei-ifm.yang
huawei-ipsec-action.yang
huawei-ipsec-ike-action.yang
huawei-ipsec-ike-type.yang
huawei-ipsec-ike.yang
huawei-ipsec-type.yang
huawei-ipsec.yang
huawei-isiscomm-action.yang
huawei-isiscomm-type.yang
huawei-isiscomm.yang
huawei-l2tpv3-action.yang
huawei-l2tpv3-type.yang
huawei-l2tpv3.yang
huawei-l3vpn-action.yang
huawei-l3vpn-l3vpncomm-type.yang
huawei-l3vpn-l3vpncomm.yang
huawei-l3vpn-mpls-type.yang
huawei-l3vpn-mpls.yang
huawei-l3vpn-netslice.yang
huawei-l3vpn-qos-action.yang
huawei-l3vpn-qos-type.yang
huawei-l3vpn-qos.yang
huawei-l3vpn-staticfrr.yang
huawei-l3vpn-tnl-type.yang
huawei-l3vpn-tnl.yang
huawei-l3vpn-type.yang
huawei-l3vpn.yang
huawei-mcastbase-type.yang
huawei-mcastbase.yang
huawei-nd-action.yang
huawei-nd-type.yang
huawei-nd.yang
huawei-netconf-authorization-type.yang
huawei-netconf-authorization.yang
huawei-netconf-notification-type.yang
huawei-netconf-notification.yang
huawei-netconf-type.yang
huawei-netconf.yang
huawei-ntp-type.yang
huawei-ntp.yang
huawei-pim-pimafspro-type.yang
huawei-pim-pimafspro.yang
huawei-pim-type.yang
huawei-pim.yang
huawei-pub-type.yang
huawei-qos-action.yang
huawei-qos-cbqos-type.yang
huawei-qos-cbqos.yang
huawei-qos-hqos-type.yang
huawei-qos-hqos.yang
huawei-qos-type.yang
huawei-qos-vllpipe.yang
huawei-qos-wred.yang
huawei-qos.yang
huawei-rm-action.yang
huawei-rm-l3vpn-labelstack.yang
huawei-rm-rmbase-type.yang
huawei-rm-rmbase.yang
huawei-rm.yang
huawei-rsa-type.yang
huawei-rsa.yang
huawei-rtp-action.yang
huawei-rtp-type.yang
huawei-rtp.yang
huawei-snmp-action.yang
huawei-snmp-type.yang
huawei-snmp.yang
huawei-sshc-action.yang
huawei-sshc-type.yang
huawei-sshc.yang
huawei-sshs-action.yang
huawei-sshs-type.yang
huawei-sshs.yang
huawei-staticrt-staticmrt-type.yang
huawei-staticrt-staticmrt.yang
huawei-staticrt-staticrtbase-type.yang
huawei-staticrt-staticrtbase.yang
huawei-staticrt.yang
huawei-syslog-action.yang
huawei-syslog-type.yang
huawei-syslog.yang
huawei-system-action.yang
huawei-system-type.yang
huawei-system.yang
huawei-timerange-type.yang
huawei-timerange.yang
huawei-tty-type.yang
huawei-tty.yang
huawei-vlan-action.yang
huawei-vlan-type.yang
huawei-vlan.yang
huawei-vty-action.yang
huawei-vty-type.yang
huawei-vty.yang
huawei-wdm-type.yang
huawei-wdm.yang
huawei-y1731-action.yang
huawei-y1731-dtools-action.yang
huawei-y1731-dtools-type.yang
huawei-y1731-dtools.yang
huawei-y1731-type.yang
huawei-y1731.yang
ietf-inet-types.yang
ietf-yang-types.yang

Quite a few models!

Before this point we've had numerous issues with the NETCONF server but most of them seem to have been resolved so that we can get the config using NETCONFs get-config RPC. We use netconf-console to do this but you can use whatever NETCONF client you might have handy, like ncclient (which is kinda a personal favourite of mine).

kll@lingloi:~/vrp-netconf$ netconf-console -u test -p secr3tpassw0rd --proto ssh --port 830 --host my-vrp-lab-router --get-config > config-from-netconf
kll@lingloi:~/vrp-netconf$ wc -l config-from-netconf
205780 config-from-netconf

Gulp. That's a lot. The config on the router isn't very large at all so something seems off.

Just reading the file I find 141523 lines from the huawei-fib model. It starts with:

  <fib xmlns="http://www.huawei.com/netconf/vrp/huawei-fib">
    <uniAfs>
      <uniAf>
        <fibRoutes>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
        </fibRoutes>
        <fibStatisticss>
          <fibStatistics>
          </fibStatistics>
        </fibStatisticss>
      </uniAf>
      <uniAf>
        <fibRoutes>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
        </fibRoutes>
        <fibStatisticss>
          <fibStatistics>
          </fibStatistics>
        </fibStatisticss>
      </uniAf>
      <uniAf>
        <fibRoutes>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
          <fibRoute>
          </fibRoute>
...

and continues like that. This is clearly some bug. We are seeing a long list of entries but there is no data populated in each entry. We don't have 141k routes configured on this router (more like 1 static) and so I suspect that I'm getting back operational data, despite only asking for config data with get-config. This has happened with Huawei before so I find it entirely possible it is happening again.

If we ignore that though we can see if we can validate the rest of the data using the same principles as in the previous post. Using yang2dsdl, that is:

kll@lingloi:~/vrp-netconf/yang$ yang2dsdl -v ../config-from-netconf *.yang
huawei-pub-type.yang:75: warning: the escape sequence "\." is unsafe in double quoted strings - pass the flag --lax-quote-checks to avoid this warning
huawei-pub-type.yang:75: warning: the escape sequence "\." is unsafe in double quoted strings - pass the flag --lax-quote-checks to avoid this warning
huawei-pub-type.yang:146: warning: the escape sequence "\d" is unsafe in double quoted strings - pass the flag --lax-quote-checks to avoid this warning
huawei-pub-type.yang:146: warning: the escape sequence "\d" is unsafe in double quoted strings - pass the flag --lax-quote-checks to avoid this warning
huawei-pub-type.yang:271: warning: the escape sequence "\s" is unsafe in double quoted strings - pass the flag --lax-quote-checks to avoid this warning
huawei-pub-type.yang:271: warning: the escape sequence "\s" is unsafe in double quoted strings - pass the flag --lax-quote-checks to avoid this warning
huawei-pub-type.yang:434: warning: the escape sequence "\s" is unsafe in double quoted strings - pass the flag --lax-quote-checks to avoid this warning
huawei-pub-type.yang:434: warning: the escape sequence "\-" is unsafe in double quoted strings - pass the flag --lax-quote-checks to avoid this warning
huawei-pub-type.yang:434: warning: the escape sequence "\." is unsafe in double quoted strings - pass the flag --lax-quote-checks to avoid this warning
huawei-pub-type.yang:434: warning: the escape sequence "\(" is unsafe in double quoted strings - pass the flag --lax-quote-checks to avoid this warning
huawei-pub-type.yang:434: warning: the escape sequence "\)" is unsafe in double quoted strings - pass the flag --lax-quote-checks to avoid this warning
huawei-pub-type.yang:434: warning: the escape sequence "\s" is unsafe in double quoted strings - pass the flag --lax-quote-checks to avoid this warning
huawei-pub-type.yang:434: warning: the escape sequence "\-" is unsafe in double quoted strings - pass the flag --lax-quote-checks to avoid this warning
huawei-pub-type.yang:434: warning: the escape sequence "\." is unsafe in double quoted strings - pass the flag --lax-quote-checks to avoid this warning
huawei-pub-type.yang:434: warning: the escape sequence "\(" is unsafe in double quoted strings - pass the flag --lax-quote-checks to avoid this warning
huawei-pub-type.yang:434: warning: the escape sequence "\)" is unsafe in double quoted strings - pass the flag --lax-quote-checks to avoid this warning
huawei-pub-type.yang:449: warning: the escape sequence "\d" is unsafe in double quoted strings - pass the flag --lax-quote-checks to avoid this warning
huawei-pub-type.yang:449: warning: the escape sequence "\s" is unsafe in double quoted strings - pass the flag --lax-quote-checks to avoid this warning
huawei-pub-type.yang:449: warning: the escape sequence "\d" is unsafe in double quoted strings - pass the flag --lax-quote-checks to avoid this warning
huawei-pub-type.yang:449: warning: the escape sequence "\s" is unsafe in double quoted strings - pass the flag --lax-quote-checks to avoid this warning
huawei-pub-type.yang:464: warning: the escape sequence "\d" is unsafe in double quoted strings - pass the flag --lax-quote-checks to avoid this warning
huawei-pub-type.yang:464: warning: the escape sequence "\d" is unsafe in double quoted strings - pass the flag --lax-quote-checks to avoid this warning
huawei-pub-type.yang:472: warning: the escape sequence "\d" is unsafe in double quoted strings - pass the flag --lax-quote-checks to avoid this warning
huawei-pub-type.yang:472: warning: the escape sequence "\d" is unsafe in double quoted strings - pass the flag --lax-quote-checks to avoid this warning
Cannot translate submodules
kll@lingloi:~/vrp-netconf/yang$

Okay, a bunch of warnings and then an error at the end. I don't like seeing warnings (sometimes they later lead to errors) so let's start with those. Line 75 of huawei-pub-type.yang is the pattern line:

typedef ipv4Address {
  type string {
    length "0..255";
    pattern "((([1-9]?[0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([1-9]?[0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]))";
  }
  description
    "An IPV4 address in dotted decimal notation";
}

\. is used in the middle to mean a literal .. This is fine but as the warning messages tells us, doing escapes in a double quoted string is not safe. Simply changing the pattern to use single quotes removes the warning and stays true to the intent of the pattern.

With that fixed we are left with the error about submodules which is simply because we are telling yang2dsdl to validate an instance data document using a submodule. That's simply wrong and not valid. The correct thing to do is to validate using the module which naturally includes the submodule, thus we need to filter our submodules. All submodules include the statement belongs-to to point out which module they belong to.

This grep will thus yield all the submodules in the directory (-l displays files with matches but not the matching line itself):

kll@lingloi:~/vrp-netconf/yang$ grep -l belongs-to *.yang

What we are looking for is all modules that are NOT submodules, thus we list everything and then do a inverse grep on that, like this:

kll@lingloi:~/vrp-netconf/yang$ ls *.yang | grep -vf <(grep -l belongs-to *.yang)

grep -f takes a file as input for things to grep after and so we use a bash trick using <() to let the output of a sub-shell look like a file to the current command. The -v is to invert the match. This yields the list of files we want, now we give it to yang2dsdl by using a sub-shell for expansion:

kll@lingloi:~/vrp-netconf/yang$ yang2dsdl -v ../config-from-netconf $(ls *.yang | grep -vf <(grep -l belongs-to *))
/usr/bin/yang2dsdl: 243: /usr/bin/yang2dsdl: xsltproc: not found
== Generating RELAX NG schema './-data.rng'
/usr/bin/yang2dsdl: 76: /usr/bin/yang2dsdl: xsltproc: not found
kll@lingloi:~/vrp-netconf/yang$ xsltproc
The program 'xsltproc' is currently not installed. You can install it by typing:
sudo apt install xsltproc
kll@lingloi:~/vrp-netconf/yang$ sudo apt install xsltproc

Whops! I'm normally validating YANG etc on a computer in our lab but I'm now using the same computer which I'm writing this post on and I'm apparently missing some tools. I'll include it since you are likely to run into the same problem. Just install xsltproc and try again

kll@lingloi:~/vrp-netconf/yang$ yang2dsdl -v ../config-from-netconf $(ls *.yang | grep -vf <(grep -l belongs-to *))
warning: failed to load external entity "/usr/local/share/yang/xslt/basename.xsl"
cannot parse /usr/local/share/yang/xslt/basename.xsl
== Generating RELAX NG schema './-data.rng'
warning: failed to load external entity "schema-dir"
cannot parse schema-dir

My yang2dsdl is looking in /usr/local/share instad of /usr/share. Dunno why. Don't think I saw problem this on my other computer. Anyway, I just copied those files:

kll@lingloi:~/vrp-netconf/yang$ sudo cp -a /usr/share/yang /usr/local/share/yang

And run again:

kll@lingloi:~/vrp-netconf/yang$ yang2dsdl -v ../config-from-netconf $(ls *.yang | grep -vf <(grep -l belongs-to *))
== Generating RELAX NG schema './huawei-aaa_huawei-acl_huawei-bfd_huawei-bgp_huawei-dcn_huawei-devm_huawei-dgmp_huawei-dhcpv6_huawei-dns_huawei-ethernet_huawei-extension_huawei-hwtacacs_huawei-ifmatm_huawei-ifmbundle_huawei-ifmcpostrunk_huawei-ifmima_huawei-ifmlag_huawei-ifmmp_huawei-ifmpostrunk_huawei-ifmtrunk_huawei-ifm_huawei-ipsec_huawei-isiscomm_huawei-l2tpv3_huawei-l3vpn_huawei-mcastbase_huawei-nd_huawei-netconf_huawei-ntp_huawei-pim_huawei-pub-type_huawei-qos_huawei-rm_huawei-rsa_huawei-rtp_huawei-snmp_huawei-sshc_huawei-sshs_huawei-staticrt_huawei-syslog_huawei-system_huawei-timerange_huawei-tty_huawei-vlan_huawei-vty_huawei-wdm_huawei-y1731_ietf-inet-types_ietf-yang-types-data.rng'
I/O error : Filename too long
I/O error : Filename too long
kll@lingloi:~/vrp-netconf/yang$

Blargh. Okay, too many modules which yields too long of a name since yang2dsdl per default concatenates the names of all the modules in its intermediate output (it writes a single large schema file that is then used for validation). We can specify a basename to use with -b:

kll@lingloi:~/vrp-netconf/yang$ yang2dsdl -b hejohoj -v ../config-from-netconf $(ls *.yang | grep -vf <(grep -l belongs-to *))                                                                                                                                                                                                                                                                                                                                                                
== Generating RELAX NG schema './hejohoj-data.rng'
Done.

== Generating Schematron schema './hejohoj-data.sch'
Done.

== Generating DSRL schema './hejohoj-data.dsrl'
Done.

== Validating grammar and datatypes ...
/usr/bin/yang2dsdl: 103: /usr/bin/yang2dsdl: xmllint: not found

Okay, install xmllint too!

kll@lingloi:~/vrp-netconf/yang$ xmllint
The program 'xmllint' is currently not installed. You can install it by typing:
sudo apt install libxml2-utils
kll@lingloi:~/vrp-netconf/yang$ sudo apt-get install -qy libxml2-utils
Reading package lists...
Building dependency tree...
...

And now!

kll@lingloi:~/vrp-netconf/yang$ yang2dsdl -b hejohoj -v ../config-from-netconf $(ls *.yang | grep -vf <(grep -l belongs-to *))
== Generating RELAX NG schema './hejohoj-data.rng'
Done.

== Generating Schematron schema './hejohoj-data.sch'
Done.

== Generating DSRL schema './hejohoj-data.dsrl'
Done.

== Validating grammar and datatypes ...
../config-from-netconf:2: element rpc-reply: Relax-NG validity error : Expecting element data, got rpc-reply
../config-from-netconf fails to validate

Not quite :/ yang2dsdl defaults to assuming it's a "data" file we want to validate but this is the response from a get-config query and so the "data" element is wrapped inside a rpc-reply. We can inform yang2dsdl with -t that it is a get-config-reply:

kll@lingloi:~/vrp-netconf/yang$ yang2dsdl -t get-config-reply -b hejohoj -v ../config-from-netconf $(ls *.yang | grep -vf <(grep -l belongs-to *))                                                                                                                                                                                                                                                                                                                                                      
== Generating RELAX NG schema './hejohoj-get-config-reply.rng'
Done.

== Generating Schematron schema './hejohoj-get-config-reply.sch'
Done.

== Generating DSRL schema './hejohoj-get-config-reply.dsrl'
Done.

== Validating grammar and datatypes ...
../config-from-netconf:1976: element mac: Relax-NG validity error : Element data has extra content: mac
../config-from-netconf fails to validate
kll@lingloi:~/vrp-netconf/yang$

Now we are getting somewhere. We found a data inconsistency on line 1976 which tells us that at least 1975 lines actuallt passed validation! What's on line 1976?

<mac xmlns="http://www.huawei.com/netconf/vrp/huawei-mac">
  <globalAttribute>
    <macAgingTime>300</macAgingTime>
    <macAgeTimeEnable>enable</macAgeTimeEnable>
    <macSynchronize>
      <synenable>false</synenable>
    </macSynchronize>
  </globalAttribute>
  <macUsages>
    <macUsage>
      <slot>0</slot>
      <macThreshold>90</macThreshold>
    </macUsage>
    <macUsage>
      <slot>1</slot>
      <macThreshold>90</macThreshold>
    </macUsage>
    <macUsage>
      <slot>3</slot>
      <macThreshold>90</macThreshold>
    </macUsage>
  </macUsages>
</mac>

Looking at our YANG modules, there is none that define a namespace of huawei-mac:

kll@lingloi:~/vrp-netconf/yang$ grep huawei-mac *
kll@lingloi:~/vrp-netconf/yang$

this isn't wrong per se as NETCONF allows the return of data that we don't have YANG model for and thus can't validate. The NETCONF client should just ignore this data. This might seem strange and first but this is actually how upgrades are handled, i.e. if a client is using an older YANG model or simply doesn't understand all YANG models supported by the device, that is ok, since we just ignore the data. However, the yang2dsdl tool is a little more strict and complains about it. For the sake of progress, I'll remove that part and continue. After this, I actually found eight other namespaces that I did not have YANG models for and thus just removed the corresponding instance data for the sake of progressing with my testing.

Next error we run into is related to the qos config:

kll@lingloi:~/vrp-netconf/yang$ yang2dsdl -t get-config-reply -b hejohoj -v ../config-from-netconf $(ls *.yang | grep -vf <(grep -l belongs-to *))
== Generating RELAX NG schema './hejohoj-get-config-reply.rng'
Done.

== Generating Schematron schema './hejohoj-get-config-reply.sch'
Done.

== Generating DSRL schema './hejohoj-get-config-reply.dsrl'
Done.

== Validating grammar and datatypes ...
Relax-NG validity error : Extra element qos in interleave
../config-from-netconf:5156: element qos: Relax-NG validity error : Element data failed to validate content
../config-from-netconf fails to validate

The validation is achieved by parsing the YANG models and producing a RelaxNG schema which in turn is used to validate the data. This means that at validation we no longer have an understanding of YANG, which I presume (I don't know that much about RelaxNG) leads to a loss of data. Unfortunately this results in an overly sparse error message.

Fortunately I have some experience in reading YANG models and after reading through a bit of the huawei-qos.yang model and its sub-modules I find that instances of non-presence containers containing mandatory leaf nodes. This is quite the anti-pattern of YANG module writing and this isn't the first time I've seen it.

There are two flavours of containers in YANG; presence and non-presence containers. Non-presence containers are the default and these containers do not themselves carry any explicit meaning and are used merely to organise data by providing structure. By adding the presence keyword under a container we can turn it into a presence container which means the existance of the container itself carries meaning.

Let's take a short example:

container foo {
  leaf bar {
    type string;
    mandatory true;
  }
}

With this model, the foo container, which is a non-presence container, MUST exist and there MUST be a bar leaf in it, since mandatory is set. I've seen this pattern in a lot of cases where the intention is to make the leaf bar mandatory but only when the container foo is present as a consequence of enabling the "foo" feature. To achieve that, we can use a presence container, like so:

container foo {
  presence "Enables feature foo";
  leaf bar {
    type string;
    mandatory true;
  }
}

Now the presence of the whole container foo is optional but if it exists then the bar leaf MUST be set (again, due to the mandatory statement).

Huawei's YANG models contain a bunch of places where they have rather deep nesting of containers and finally we find a leaf with mandatory true. When all of this data is missing in the instance data the validation fails with that extremely sparse message. I modified the YANG modules and added in presence statements on a couple of containers to make them optional, again to be able to make progress with my evaluation.

This type of problem is in fact so widespread that I had to find a better way of finding problematic instances. By looking at the output of pyang -f tree and then filtering this I could quickly find mandatory leaf nodes under containers. I started by removing all read-only data. I do this with vi and :g/+--ro /d. Second I can remove all leaves that are optional with :g/+--rw [A-Za-z0-9]\+?/d. We are now down to containers, lists and mandatory leaves. Here's an exceprt from the routing policy model:

module: huawei-rtp
    +--rw rtp
       +--rw asPathFilters
       |  +--rw asPathFilter* [index]
       |     +--rw index                string
       |     +--rw asPathFilterNodes
       |        +--rw asPathFilterNode* [nodeSequence]
       |           +--rw nodeSequence    uint32
       |           +--rw matchMode       rtpMatchMode
       |           +--rw regular         string

We can see how asPathFilters is a container that holds a single list, "index" is the key of that list and nex to it we find another container and in it a second list which wholds the members of the filter. That inner list is keyed on nodeSequence, which is fine and the matchMode and regular seems fine too, I guess the regular is the actual value and it's called "regular" because it's a regular expression. This structure seems fine.

However, if we move on down we get to the route policies themselves:

+--rw routePolicys
|  +--rw routePolicy* [name]
|     +--rw name                string
|     +--rw routePolicyNodes
|        +--rw routePolicyNode* [nodeSequence]
|           +--rw nodeSequence      uint32
|           +--rw matchMode         rtpMatchMode
|           +--rw matchCondition
|           |  +--rw matchCosts
|           |  |  +--rw matchCost
|           |  |     +--rw costValue    uint32
|           |  +--rw matchInterfaces
|           |  |  +--rw matchInterface* [ifName]
|           |  |     +--rw ifName    pub-type:ifName
|           |  +--rw matchRouteTypes
|           |  |  +--rw matchRouteType* [routeType]
|           |  |     +--rw routeType    rtpMchRtType
|           |  +--rw matchTags
|           |  |  +--rw matchTag
|           |  |     +--rw tagValue    uint32
|           |  +--rw matchMplsLabels
|           |  |  +--rw matchMplsLabel
|           |  |     +--rw mplsLabel    boolean
...

the model continues for another 150 lines just for the routePlicy list but I won't list it all here. We can see how there are a bunch of mandatory leaves here and they are tucked into two containers, like matchCosts/matchCost is a container in a container and inside we have the leaf costValue which is mandatory. The way the model is written it means pretty much all potential ways of matching things in the policy are mandatory. That can't be right!

As far as I've understood, Huawei generates their models from an internal representation so while I've found a whole bunch of instances with the same type of error, it doesn't actually mean fixing it is very hard. All they need to do is patch the logic that outputs the YANG model and all faulty occurences can be fixed in one swift go.

I found a couple of other instances of bugs but won't bore you with all the details as they are conceptually the same. I've brought it all up with Huawei who are committed to resolving them and improve the quality of their NETCONF / YANG interface.

I would like to thank Huawei for providing us with early access software and working with us on improving their NETCONF / YANG support as well as for the opportunity to publish this post and show how some of these things work.

Reach out to me on Twitter (see footer) if you have questions!

Tags: YANG
15 Mar 2017

Validating data with YANG

Every now and then I hear about how difficult it is to use YANG to actually validate any data (we call this instance data). Since we in the TeraStream team do this quite a lot I thought I'd share how it can be done. This is using a process that we also employ in our CI pipeline.

Let's first write a simple YANG model:

module tubecats {
    namespace "http://plajjan.github.io/ns/yang/tubecats";
    prefix tc;

    revision 2017-03-15 {
        description "First and only version";
    }

    container internet {
        list cat {
            key name;
            leaf name {
                type string;
            }
        }
    }
}

We all know the Internet is full of cats so I created a list under the internet container so we can fill it up with cats. The only valid leaf value of each cat list entry is its name.

Let's start off by actually making sure that our YANG model is valid. We can use the tool called pyang to do this. If you don't have pyang installed you can install it with pip install pyang.

kll@kll:~/yang-test$ pyang tubecats.yang
kll@kll:~/yang-test$ pyang --ietf tubecats.yang
tubecats.yang:1: warning: RFC 6087: 4.1: the module name should start with one of the strings "ietf-" or "iana-"
tubecats.yang:1: error: RFC 6087: 4.7: statement "module" must have a "contact" substatement
tubecats.yang:1: error: RFC 6087: 4.7: statement "module" must have a "organization" substatement
tubecats.yang:1: error: RFC 6087: 4.7: statement "module" must have a "description" substatement
tubecats.yang:2: warning: RFC 6087: 4.8: namespace value should be "urn:ietf:params:xml:ns:yang:tubecats"
tubecats.yang:5: error: RFC 6087: 4.7: statement "revision" must have a "reference" substatement
tubecats.yang:9: error: RFC 6087: 4.12: statement "container" must have a "description" substatement
tubecats.yang:10: error: RFC 6087: 4.12: statement "list" must have a "description" substatement
tubecats.yang:12: error: RFC 6087: 4.12: statement "leaf" must have a "description" substatement

The --ietf argument makes pyang a little more strict and adheres to a bunch of IETF guidelines on how to write YANG models. Since we aren't writing an IETF model and don't have an IETF namespace for it, we'll get some warnings and errors. Anyway, our model is sound since it succeeded without --ietf.

Ok, so we have a valid model, let's write some data that adheres to it:

<ns0:data xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0">
    <tc:internet xmlns:tc="http://plajjan.github.io/ns/yang/tubecats">
        <tc:cat>
            <tc:name>jingles</tc:name>
        </tc:cat>
        <tc:cat>
            <tc:name>fluffy</tc:name>
        </tc:cat>
    </tc:internet>
</ns0:data>

And now, to validate we use yang2dsdl which is shipped together with pyang:

kll@kll:~/yang-test$ /usr/bin/yang2dsdl -v data.xml tubecats.yang
== Generating RELAX NG schema './tubecats-data.rng'
Done.

== Generating Schematron schema './tubecats-data.sch'
Done.

== Generating DSRL schema './tubecats-data.dsrl'
Done.

== Validating grammar and datatypes ...
data.xml validates

== Adding default values... done.

== Validating semantic constraints ...
No errors found.
kll@kll:~/yang-test$

To make sure that our toolchain is working here we'll introduce an error in our data file, namely a second node under one of the cat list entries:

<ns0:data xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0">
    <tc:internet xmlns:tc="http://plajjan.github.io/ns/yang/tubecats">
        <tc:cat>
            <tc:name>jingles</tc:name>
        </tc:cat>
        <tc:cat>
            <tc:name>fluffy</tc:name>
            <tc:foo>bar</tc:foo>
        </tc:cat>
    </tc:internet>
</ns0:data>

lo and behold as this time around it complains loudly:

kll@kll:~/yang-test$ /usr/bin/yang2dsdl -v data.xml tubecats.yang
== Generating RELAX NG schema './tubecats-data.rng'
Done.

== Generating Schematron schema './tubecats-data.sch'
Done.

== Generating DSRL schema './tubecats-data.dsrl'
Done.

== Validating grammar and datatypes ...
data.xml:8: element foo: Relax-NG validity error : Did not expect element foo there
data.xml fails to validate
kll@kll:~/yang-test$

So that's how you can validate your instance data with a YANG model!

The <data> tag at the root of the XML document is part of many NETCONF commands. It's also possible to ask it to validate data that is wrapped in other nodes like edit-config, get-reply etc. If you are just trying to write some data on your own and don't want to think about NETCONF you do still have to add that extra <data> tag at the root to get validation to complete… it is a bit NETCONF centric after all.

Tags: YANG
04 Jul 2016

YANG versioning and backwards (in)compatibility

A suggestion for how to handle backwards compatibility in a YANG modeled world.

YANG comes with a fairly strict set of rules for allowed modifications between model revision, so how do you make changes to your API while abiding to these rules?

If you've written YANG models yourself you might have ended up in the situation that you wanted to make backwards incompatible changes. If you are a user of YANG models you might have been bitten by someone else, like a vendor, producing YANG models with backwards incompatible changes between revision.

How do you keep a backwards compatible YANG modeled API while allowing for changes?

1 YANG revision compatibility rules

YANG is defined in RFC6020, which has a section on what changes are allowed between revisions of a YANG model.

The whole idea with having a model describing data is to leave a sort of "contract" to another party on what data is accepted. The rules in RFC6020 are defined such that you cannot break that contract.

For example, the first revision of model foo has the leaf /bar. If we realise this leaf isn't actually needed we cannot remove it in the second revision of the model since anyone with the first revision of the model might try to set a value for the /bar leaf. Deleting the leaf would break the "contract".

I won't list all the rules here but they essentially boil down to only allowing additions. You cannot remove nodes or make changes that reduce the value space for a leaf.

2 Offenders

I think one of the more clear examples of YANG compatibility breakage is Cisco's IOS XR as can be witnessed by the XR YANG models published on GitHub.

Cisco doesn't even try to hide that they are breaking YANG rules (kudos for that, I suppose), in fact there is a section in the README file of each subdirectory that reads:

It should be noted that some of the modules released in
IOX-XR 6.0.1 break the backwards compatibility guidelines
defined in RFC 6020 when compared to the same modules
released in IOS-XR 6.0.1. This is because the "native" YANG
modules for IOS-XR are generated from internal schema files
that are an integral part of the implementation, and, as
such, these can change in ways that break backwards
compatibility per RFC 6020 guidelines when new features are
introduced or when bugs are fixed. Thus, while we rigorously
review the changes that impact the external YANG schema,
Cisco cannot guarantee full backwards compatibility of these
modules across releases.

However, when new versions of the native models are
released, the check-models.sh script, in conjunction with
pyang 1.6, can be used to determine what technically
incompatible changes have occurred. Please run check.sh from
this directory with pyang 1.5 or greater on your path thus:

If you run the suggested commands you will see that there are incompatible changes between the majority of revisions:

  • 5.3.0 -> 5.3.1 fails
  • 5.3.1 -> 5.3.2 fails
  • 5.3.2 -> 5.3.3 fails
  • 5.3.3 -> 6.0.0 fails
  • 6.0.0 -> 6.0.1 works ok, I'm guessing because they didn't make any (or much) changes to the models at all

If you happen to be using Cisco NSO (formerly Tail-F NCS) you might have noticed that you can't load the same module / namespace multiple times. You are supposed to load the latest revision, which will work (to a certain extent) with older models, or if you are using an older revision of the model you are still able to work with the leaves it contains. However, this only holds true if you stick to the YANG revision compatibility rules, which Cisco aren't.

With NSO you compile the YANG models into .fxs files which are then loaded by NSO. ncsc is the NSO compiler that takes care of the compilation step and it actually has an option relevant to this, namely --lax-revision-merge;

--lax-revision-merge    When we have multiple revisions of
  the same module, the ncsc command to import the module
  will fail if a YANG module does not follow the YANG
  module upgrade rules. See RFC 6020. This option makes
  ncsc ignore those strict rules. Use with extreme care,
  the end result may be that NCS is incompatible with the
  managed devices.

However, in the case of merging XR 5.1 and XR 5.3 models, it does not work as warned by the man page.

It's rather ironic how two Cisco products aren't compatible with each other while other products, such as JUNOS, works great together with Cisco NSO, even across different versions. Never buy more than one product from Cisco? ;)

3 Solution?

The simple solution is of course that Cisco stops breaking YANG rules. However, I can understand it's difficult with their development process and sometimes you just have to make backwards incompatible changes. Besides, it's an industry wide problem and not just related to Cisco.

Let's first look at semver and then how we might merge the concept of semver with YANG versioning scheme that allows for backwards incompatibility.

4 Semantic versioning

Semantic versioning (semver for short) is a fairly widely accepted versioning scheme where the version is described as MAJOR.MINOR.PATCH. In essence, increment the:

  • MAJOR version when you make incompatible API changes,
  • MINOR version when you add functionality in a backwards-compatible manner, and
  • PATCH version when you make backwards-compatible bug fixes.

YANG however doesn't follow semver but I believe the same concept can be applied.

5 YANG + semver = <3 ?

The suggestion is simple:

Let the MAJOR version form part of the model name and namespace and let the revisions of a YANG model represent the MINOR and PATCH versions.

Following semver this means all the backwards compatible changes are made within the same YANG model with the addition of new revisions. Backwards incompatible changes however results in the MAJOR version being bumped and as the MAJOR version is part of the model name and namespace it means we effectively create a new YANG model.

  • for backwards compatible changes
    • keep MAJOR version, thus:
      • we keep the YANG module name & namespace
    • bump MINOR or PATCH version, thus:
      • add new revision in current YANG module
  • for backwards incompatible changes
    • bump MAJOR version, thus:
      • create a new YANG module name & namespace based on new MAJOR version
    • add a new revision to the new YANG module
    • let the old YANG module remain with the older MAJOR version, thus maintaining backwards compatibility

6 An example

Let's say we have a module we wish to name foo. The first public release of it, keeping in line with semver, is v1.0.0. The module would thus be called foo-v1 and with a namespace that also includes the -v1 part, like http://example.com/ns/yang/foo-v1.

A bug fix is made, fixing a regexp for one of the leaves, but keeping inline with RFC6020 rules it does not decrease the allowed value space. Since it's a bug fix, we increase to semver v1.0.1. The YANG module will still be called foo-v1 but we add a revision explaining the bug fix.

Similarly if we add a leaf, it is classified as a minor feature, thus bumping the semver MINOR version to v1.1.0. We still keep the module name foo-v1 and add a revision, just as for the bug fix.

Now, if we decide to completely restructure a part of the module, including removing some containers and their leaves, we have made a backwards incompatible change and must bump the MAJOR version. The module will now be v2.0.0 and thus the name changes to foo-v2 and the same change is reflected in the namespace. For the sake of clarity we can keep all the revisions from the v1 "line" of the module. We now have two modules; foo-v1 and foo-v2.

Further bug fixes and minor feature additions can be made to both, or if you choose to only one (likely the v2). The v1 line will eventuelly be deprecated and the exact timeline for that is mosty the result of how long your organisation can or want to maintain multiple versions in parallel.

7 YANG revision label

The "label" used in the revision statement in YANG models is an ISO 8601 date. This could potentially be replaced with a semver version but I don't believe it obviates the need to put the major version in the model name. If a backwards incompatible change is made we might want to support both MAJOR version 1 and 2 at the same time and thus need to load two versions of the model. How are we to do that if both versions have the same name? How do we store two different YANG modules on disk if the filename doesn't reflect the MAJOR version?

8 Thoughts?

There are probably more aspects to consider associated with this suggestion. For example, YANG models can refer to each other, through imports or submodules. If a large number of models are "intertwined" through reference it might not be apparent which of these models can or should be upgraded in a MAJOR version bump.

Do you have any thoughts? Don't hesitate in reaching out to me (contact details in the page footer).

Incidentally, just a few days after I wrote the first draft of this post I noticed that Brocade had put a -v1 in the name of their YANG models. I'm not sure about their rationale but I suspect it is rather similar to what I've outlined here.

Tags: YANG
19 Dec 2015

Cisco IOS XR 6.0 and YANG

IOS XR has featured a NETCONF interface for quite some time but it was only with the 5.3.0 release that Cisco coupled it with proper YANG modeled configuration and operational data. Before that they used XML Schema Definition (XSD) to describe the data transported over the XML agent / NETCONF interface.

To be honest the difference between what Cisco calls XML agent and their NETCONF server is still a bit unclear to me. Maybe I'll dig through that sometime but I'm all focused on NETCONF/YANG and we know Cisco is headed in that direction so looking at the XML agent would be merely to satisfy my curiosity.

Unlike JUNOS, which features one massive YANG model (it's over 250k lines), Cisco has opted to split the configuration into many smaller YANG models. When YANG models were introduced in 5.3.0 they shipped it with 61 models, totalling 12451 lines. Naturally the number of models or lines in those models doesn't give an exact figure on coverage of configurational or operational data but I hope it gives a hint at least. The coverage of these 61 models was actually rather poor so in practice it wasn't usable for anything.

5.3.1 bumped the number to 24812 lines over 99 models. Obviously an improvement but still pretty far from usable. For example, neither 5.3.0 or 5.3.1 featured any configuration of routing protocols. You could configure interfaces, IP addresses, some system settings and so forth but far from being usable to configure an entire router.

5.3.2 brought along BGP, policy configuration, some file system stuff as well as a number of updates. The number of models only increased from 99 to 106 but lines went from 24812 to 45775 of which the lions share are from the BGP models and in particular the BGP operational model. Progress after all!

There is a YangModels repository on GitHub, where you can conveniently browse the models available in XR up to 5.3.2.

I work with the TeraStream project within Deutsche Telekom and we have been an early adopter of NETCONF and YANG. In fact, it's one of the foundational pillars of the network architecture. Everything MUST (RFC2119) support NETCONF/YANG. We have worked with Cisco for years and have private builds of XR featuring loads of YANG models (142575 lines spread over 242 models). As I spend a lot of time with NETCONF & YANG in my every day work, a lot of people ask me about the state of the implementations and how they can use it. The conversations usually go down with me saying something like "NETCONF/YANG works great on XR… bla bla … as long as you have a private build with all YANG models". Unlike TeraStream, which is in some form of pilot state, most people run actual production networks and just want working solutions. Running a private test build isn't for them.

Cisco released XR 6.0 yesterday and I downloaded a demo of XRv today to have a look at the coverage of YANG models. Have a look at this (and sorry for the long output):

kll@lab $ ssh 1.3.3.7 -p 830 -s netconf

IMPORTANT:  READ CAREFULLY
Welcome to the Demo Version of Cisco IOS XRv (the "Software").
The Software is subject to and governed by the terms and conditions
of the End User License Agreement and the Supplemental End User
License Agreement accompanying the product, made available at the
time of your order, or posted on the Cisco website at
www.cisco.com/go/terms (collectively, the "Agreement").
As set forth more fully in the Agreement, use of the Software is
strictly limited to internal use in a non-production environment
solely for demonstration and evaluation purposes.  Downloading,
installing, or using the Software constitutes acceptance of the
Agreement, and you are binding yourself and the business entity
that you represent to the Agreement.  If you do not agree to all
of the terms of the Agreement, then Cisco is unwilling to license
the Software to you and (a) you may not download, install or use the
Software, and (b) you may return the Software as more fully set forth
in the Agreement.


Please login with any configured user/password, or cisco/cisco

kll@1.3.3.7's password:
<hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
 <capabilities>
  <capability>urn:ietf:params:netconf:base:1.1</capability>
  <capability>urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring</capability>
  <capability>urn:ietf:params:netconf:capability:candidate:1.0</capability>
  <capability>urn:ietf:params:netconf:capability:rollback-on-error:1.0</capability>
  <capability>urn:ietf:params:netconf:capability:validate:1.1</capability>
  <capability>urn:ietf:params:netconf:capability:confirmed-commit:1.1</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-aaa-locald-admin-cfg?module=Cisco-IOS-XR-aaa-locald-admin-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-aaa-locald-cfg?module=Cisco-IOS-XR-aaa-locald-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-aaa-locald-oper?module=Cisco-IOS-XR-aaa-locald-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-aaa-protocol-radius-cfg?module=Cisco-IOS-XR-aaa-protocol-radius-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-aaa-protocol-radius-oper?module=Cisco-IOS-XR-aaa-protocol-radius-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-aaa-tacacs-cfg?module=Cisco-IOS-XR-aaa-tacacs-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-aaa-tacacs-oper?module=Cisco-IOS-XR-aaa-tacacs-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-bundlemgr-cfg?module=Cisco-IOS-XR-bundlemgr-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-bundlemgr-oper?module=Cisco-IOS-XR-bundlemgr-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-cdp-cfg?module=Cisco-IOS-XR-cdp-cfg&amp;revision=2015-07-30</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-cdp-oper?module=Cisco-IOS-XR-cdp-oper&amp;revision=2015-01-07</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-clns-isis-cfg?module=Cisco-IOS-XR-clns-isis-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-clns-isis-datatypes?module=Cisco-IOS-XR-clns-isis-datatypes&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-clns-isis-oper?module=Cisco-IOS-XR-clns-isis-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-common-acl-datatypes?module=Cisco-IOS-XR-common-acl-datatypes&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-config-mda-cfg?module=Cisco-IOS-XR-config-mda-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-config-mibs-cfg?module=Cisco-IOS-XR-config-mibs-cfg&amp;revision=2015-01-07</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-controller-optics-cfg?module=Cisco-IOS-XR-controller-optics-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-controller-optics-oper?module=Cisco-IOS-XR-controller-optics-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-controller-otu-cfg?module=Cisco-IOS-XR-controller-otu-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-controller-otu-oper?module=Cisco-IOS-XR-controller-otu-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-crypto-sam-cfg?module=Cisco-IOS-XR-crypto-sam-cfg&amp;revision=2015-01-07</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-crypto-sam-oper?module=Cisco-IOS-XR-crypto-sam-oper&amp;revision=2015-01-07</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-crypto-ssh-cfg?module=Cisco-IOS-XR-crypto-ssh-cfg&amp;revision=2015-07-30</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-crypto-ssh-oper?module=Cisco-IOS-XR-crypto-ssh-oper&amp;revision=2015-06-02</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-drivers-media-eth-cfg?module=Cisco-IOS-XR-drivers-media-eth-cfg&amp;revision=2015-07-30</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-drivers-media-eth-oper?module=Cisco-IOS-XR-drivers-media-eth-oper&amp;revision=2015-10-14</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ethernet-cfm-cfg?module=Cisco-IOS-XR-ethernet-cfm-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ethernet-cfm-datatypes?module=Cisco-IOS-XR-ethernet-cfm-datatypes&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ethernet-cfm-oper?module=Cisco-IOS-XR-ethernet-cfm-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ethernet-link-oam-cfg?module=Cisco-IOS-XR-ethernet-link-oam-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ethernet-link-oam-oper?module=Cisco-IOS-XR-ethernet-link-oam-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ethernet-lldp-cfg?module=Cisco-IOS-XR-ethernet-lldp-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ethernet-lldp-oper?module=Cisco-IOS-XR-ethernet-lldp-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-fib-common-oper?module=Cisco-IOS-XR-fib-common-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ha-eem-cfg?module=Cisco-IOS-XR-ha-eem-cfg&amp;revision=2015-07-30</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ha-eem-oper?module=Cisco-IOS-XR-ha-eem-oper&amp;revision=2015-01-07</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-icpe-infra-cfg?module=Cisco-IOS-XR-icpe-infra-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-icpe-infra-oper?module=Cisco-IOS-XR-icpe-infra-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg?module=Cisco-IOS-XR-ifmgr-cfg&amp;revision=2015-07-30</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-oper?module=Cisco-IOS-XR-ifmgr-oper&amp;revision=2015-07-30</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-infra-alarm-logger-cfg?module=Cisco-IOS-XR-infra-alarm-logger-cfg&amp;revision=2015-07-30</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-infra-alarm-logger-datatypes?module=Cisco-IOS-XR-infra-alarm-logger-datatypes&amp;revision=2015-01-07</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-infra-alarm-logger-oper?module=Cisco-IOS-XR-infra-alarm-logger-oper&amp;revision=2015-01-07</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-infra-ceredundancymib-cfg?module=Cisco-IOS-XR-infra-ceredundancymib-cfg&amp;revision=2015-01-07</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-infra-dumper-cfg?module=Cisco-IOS-XR-infra-dumper-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-infra-infra-clock-cfg?module=Cisco-IOS-XR-infra-infra-clock-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-infra-infra-locale-cfg?module=Cisco-IOS-XR-infra-infra-locale-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-infra-objmgr-cfg?module=Cisco-IOS-XR-infra-objmgr-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-infra-objmgr-oper?module=Cisco-IOS-XR-infra-objmgr-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-infra-policymgr-oper?module=Cisco-IOS-XR-infra-policymgr-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-infra-rmf-oper?module=Cisco-IOS-XR-infra-rmf-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-infra-rsi-cfg?module=Cisco-IOS-XR-infra-rsi-cfg&amp;revision=2015-07-30</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-infra-rsi-oper?module=Cisco-IOS-XR-infra-rsi-oper&amp;revision=2015-01-07</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-infra-sla-cfg?module=Cisco-IOS-XR-infra-sla-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-infra-sla-datatypes?module=Cisco-IOS-XR-infra-sla-datatypes&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-infra-sla-oper?module=Cisco-IOS-XR-infra-sla-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-infra-statsd-cfg?module=Cisco-IOS-XR-infra-statsd-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-infra-statsd-oper?module=Cisco-IOS-XR-infra-statsd-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-infra-syslog-cfg?module=Cisco-IOS-XR-infra-syslog-cfg&amp;revision=2015-10-08</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-infra-syslog-oper?module=Cisco-IOS-XR-infra-syslog-oper&amp;revision=2015-12-01</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-infra-systemmib-cfg?module=Cisco-IOS-XR-infra-systemmib-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ip-bfd-cfg?module=Cisco-IOS-XR-ip-bfd-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ip-bfd-oper?module=Cisco-IOS-XR-ip-bfd-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ip-domain-cfg?module=Cisco-IOS-XR-ip-domain-cfg&amp;revision=2015-05-13</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ip-domain-oper?module=Cisco-IOS-XR-ip-domain-oper&amp;revision=2015-09-29</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ip-iarm-datatypes?module=Cisco-IOS-XR-ip-iarm-datatypes&amp;revision=2015-01-07</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ip-iep-cfg?module=Cisco-IOS-XR-ip-iep-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ip-iep-oper?module=Cisco-IOS-XR-ip-iep-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ip-ntp-admin-oper?module=Cisco-IOS-XR-ip-ntp-admin-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ip-ntp-cfg?module=Cisco-IOS-XR-ip-ntp-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ip-ntp-oper?module=Cisco-IOS-XR-ip-ntp-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ip-pfilter-cfg?module=Cisco-IOS-XR-ip-pfilter-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ip-pfilter-oper?module=Cisco-IOS-XR-ip-pfilter-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ip-rib-cfg?module=Cisco-IOS-XR-ip-rib-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ip-rib-ipv4-oper?module=Cisco-IOS-XR-ip-rib-ipv4-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ip-rib-ipv6-oper?module=Cisco-IOS-XR-ip-rib-ipv6-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ip-rsvp-cfg?module=Cisco-IOS-XR-ip-rsvp-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ip-rsvp-oper?module=Cisco-IOS-XR-ip-rsvp-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ip-static-cfg?module=Cisco-IOS-XR-ip-static-cfg&amp;revision=2015-09-10</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ip-tcp-cfg?module=Cisco-IOS-XR-ip-tcp-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ip-tcp-oper?module=Cisco-IOS-XR-ip-tcp-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ip-udp-cfg?module=Cisco-IOS-XR-ip-udp-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ip-udp-oper?module=Cisco-IOS-XR-ip-udp-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv4-acl-cfg?module=Cisco-IOS-XR-ipv4-acl-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv4-acl-datatypes?module=Cisco-IOS-XR-ipv4-acl-datatypes&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv4-acl-oper?module=Cisco-IOS-XR-ipv4-acl-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv4-arp-cfg?module=Cisco-IOS-XR-ipv4-arp-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv4-arp-oper?module=Cisco-IOS-XR-ipv4-arp-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv4-bgp-cfg?module=Cisco-IOS-XR-ipv4-bgp-cfg&amp;revision=2015-08-27</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv4-bgp-datatypes?module=Cisco-IOS-XR-ipv4-bgp-datatypes&amp;revision=2015-08-27</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv4-bgp-oper?module=Cisco-IOS-XR-ipv4-bgp-oper&amp;revision=2015-08-27</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv4-io-cfg?module=Cisco-IOS-XR-ipv4-io-cfg&amp;revision=2015-07-30</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv4-io-oper?module=Cisco-IOS-XR-ipv4-io-oper&amp;revision=2015-10-20</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv4-ma-cfg?module=Cisco-IOS-XR-ipv4-ma-cfg&amp;revision=2015-07-30</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv4-ma-oper?module=Cisco-IOS-XR-ipv4-ma-oper&amp;revision=2015-10-20</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv4-ospf-cfg?module=Cisco-IOS-XR-ipv4-ospf-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv4-ospf-oper?module=Cisco-IOS-XR-ipv4-ospf-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv4-telnet-cfg?module=Cisco-IOS-XR-ipv4-telnet-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv4-telnet-mgmt-cfg?module=Cisco-IOS-XR-ipv4-telnet-mgmt-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv6-acl-cfg?module=Cisco-IOS-XR-ipv6-acl-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv6-acl-datatypes?module=Cisco-IOS-XR-ipv6-acl-datatypes&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv6-acl-oper?module=Cisco-IOS-XR-ipv6-acl-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv6-io-cfg?module=Cisco-IOS-XR-ipv6-io-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv6-io-oper?module=Cisco-IOS-XR-ipv6-io-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv6-ma-cfg?module=Cisco-IOS-XR-ipv6-ma-cfg&amp;revision=2015-07-30</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv6-ma-oper?module=Cisco-IOS-XR-ipv6-ma-oper&amp;revision=2015-10-20</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv6-nd-cfg?module=Cisco-IOS-XR-ipv6-nd-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv6-nd-oper?module=Cisco-IOS-XR-ipv6-nd-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv6-new-dhcpv6d-oper?module=Cisco-IOS-XR-ipv6-new-dhcpv6d-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv6-ospfv3-cfg?module=Cisco-IOS-XR-ipv6-ospfv3-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-ipv6-ospfv3-oper?module=Cisco-IOS-XR-ipv6-ospfv3-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-l2-eth-infra-cfg?module=Cisco-IOS-XR-l2-eth-infra-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-l2-eth-infra-datatypes?module=Cisco-IOS-XR-l2-eth-infra-datatypes&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-l2-eth-infra-oper?module=Cisco-IOS-XR-l2-eth-infra-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-l2vpn-cfg?module=Cisco-IOS-XR-l2vpn-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-l2vpn-oper?module=Cisco-IOS-XR-l2vpn-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-lib-keychain-cfg?module=Cisco-IOS-XR-lib-keychain-cfg&amp;revision=2015-07-30</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-lib-keychain-oper?module=Cisco-IOS-XR-lib-keychain-oper&amp;revision=2015-01-07</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-lib-mpp-cfg?module=Cisco-IOS-XR-lib-mpp-cfg&amp;revision=2015-07-30</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-lib-mpp-oper?module=Cisco-IOS-XR-lib-mpp-oper&amp;revision=2015-01-07</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-lpts-lib-cfg?module=Cisco-IOS-XR-lpts-lib-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-lpts-pre-ifib-cfg?module=Cisco-IOS-XR-lpts-pre-ifib-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-man-netconf-cfg?module=Cisco-IOS-XR-man-netconf-cfg&amp;revision=2015-07-30</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-man-xml-ttyagent-cfg?module=Cisco-IOS-XR-man-xml-ttyagent-cfg&amp;revision=2015-07-30</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-man-xml-ttyagent-oper?module=Cisco-IOS-XR-man-xml-ttyagent-oper&amp;revision=2015-10-29</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-mpls-ldp-cfg-datatypes?module=Cisco-IOS-XR-mpls-ldp-cfg-datatypes&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-mpls-ldp-cfg?module=Cisco-IOS-XR-mpls-ldp-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-mpls-ldp-oper-datatypes?module=Cisco-IOS-XR-mpls-ldp-oper-datatypes&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-mpls-ldp-oper?module=Cisco-IOS-XR-mpls-ldp-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-mpls-lsd-cfg?module=Cisco-IOS-XR-mpls-lsd-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-mpls-lsd-oper?module=Cisco-IOS-XR-mpls-lsd-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-mpls-oam-cfg?module=Cisco-IOS-XR-mpls-oam-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-mpls-static-cfg?module=Cisco-IOS-XR-mpls-static-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-mpls-static-oper?module=Cisco-IOS-XR-mpls-static-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-mpls-te-cfg?module=Cisco-IOS-XR-mpls-te-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-mpls-te-datatypes?module=Cisco-IOS-XR-mpls-te-datatypes&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-mpls-te-oper?module=Cisco-IOS-XR-mpls-te-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-nto-misc-shprocmem-oper?module=Cisco-IOS-XR-nto-misc-shprocmem-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-parser-cfg?module=Cisco-IOS-XR-parser-cfg&amp;revision=2015-06-02</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-pfi-im-cmd-oper?module=Cisco-IOS-XR-pfi-im-cmd-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-plat-chas-invmgr-oper?module=Cisco-IOS-XR-plat-chas-invmgr-oper&amp;revision=2015-01-07</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-pmengine-cfg?module=Cisco-IOS-XR-pmengine-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-pmengine-oper?module=Cisco-IOS-XR-pmengine-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-policy-repository-cfg?module=Cisco-IOS-XR-policy-repository-cfg&amp;revision=2015-08-27</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-policy-repository-oper?module=Cisco-IOS-XR-policy-repository-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-qos-ma-oper?module=Cisco-IOS-XR-qos-ma-oper&amp;revision=2015-01-07</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-rgmgr-cfg?module=Cisco-IOS-XR-rgmgr-cfg&amp;revision=2015-07-30</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-rgmgr-oper?module=Cisco-IOS-XR-rgmgr-oper&amp;revision=2015-01-07</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-segment-routing-ms-cfg?module=Cisco-IOS-XR-segment-routing-ms-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-segment-routing-ms-oper?module=Cisco-IOS-XR-segment-routing-ms-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-shellutil-cfg?module=Cisco-IOS-XR-shellutil-cfg&amp;revision=2015-10-12</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-shellutil-filesystem-oper?module=Cisco-IOS-XR-shellutil-filesystem-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-shellutil-oper?module=Cisco-IOS-XR-shellutil-oper&amp;revision=2015-01-07</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-snmp-agent-cfg?module=Cisco-IOS-XR-snmp-agent-cfg&amp;revision=2015-10-27</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-snmp-agent-oper?module=Cisco-IOS-XR-snmp-agent-oper&amp;revision=2015-10-08</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-snmp-entitymib-cfg?module=Cisco-IOS-XR-snmp-entitymib-cfg&amp;revision=2015-01-07</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-snmp-entstatemib-cfg?module=Cisco-IOS-XR-snmp-entstatemib-cfg&amp;revision=2015-07-27</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-snmp-frucontrolmib-cfg?module=Cisco-IOS-XR-snmp-frucontrolmib-cfg&amp;revision=2015-01-07</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-snmp-ifmib-cfg?module=Cisco-IOS-XR-snmp-ifmib-cfg&amp;revision=2015-05-14</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-snmp-ifmib-oper?module=Cisco-IOS-XR-snmp-ifmib-oper&amp;revision=2015-01-07</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-snmp-syslogmib-cfg?module=Cisco-IOS-XR-snmp-syslogmib-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-traffmon-netflow-cfg?module=Cisco-IOS-XR-traffmon-netflow-cfg&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-tty-management-cfg?module=Cisco-IOS-XR-tty-management-cfg&amp;revision=2015-09-25</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-tty-management-cmd-oper?module=Cisco-IOS-XR-tty-management-cmd-oper&amp;revision=2015-11-09</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-tty-management-datatypes?module=Cisco-IOS-XR-tty-management-datatypes&amp;revision=2015-01-07</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-tty-management-oper?module=Cisco-IOS-XR-tty-management-oper&amp;revision=2015-01-07</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-tty-server-cfg?module=Cisco-IOS-XR-tty-server-cfg&amp;revision=2015-07-30</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-tty-server-oper?module=Cisco-IOS-XR-tty-server-oper&amp;revision=2015-07-30</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-tty-vty-cfg?module=Cisco-IOS-XR-tty-vty-cfg&amp;revision=2015-01-07</capability>
  <capability>http://cisco.com/ns/yang/cisco-xr-types?module=Cisco-IOS-XR-types&amp;revision=2015-06-29</capability>
  <capability>http://cisco.com/ns/yang/Cisco-IOS-XR-wd-cfg?module=Cisco-IOS-XR-wd-cfg&amp;revision=2015-11-09</capability>
  <capability>urn:ietf:params:xml:ns:yang:ietf-inet-types?module=ietf-inet-types&amp;revision=2013-07-15</capability>
  <capability>urn:ietf:params:xml:ns:yang:ietf-yang-types?module=ietf-yang-types&amp;revision=2013-07-15</capability>
  <capability>http://openconfig.net/yang/bgp?module=bgp&amp;revision=2015-05-15&amp;deviation=cisco-xr-bgp-deviations</capability>
  <capability>http://openconfig.net/yang/bgp-multiprotocol?module=bgp-multiprotocol&amp;revision=2015-05-15</capability>
  <capability>http://openconfig.net/yang/bgp-operational?module=bgp-operational&amp;revision=2015-05-15</capability>
  <capability>http://openconfig.net/yang/bgp-policy?module=bgp-policy&amp;revision=2015-05-15&amp;deviation=cisco-xr-bgp-policy-deviations</capability>
  <capability>http://openconfig.net/yang/bgp-types?module=bgp-types&amp;revision=2015-05-15</capability>
  <capability>http://openconfig.net/yang/routing-policy?module=routing-policy&amp;revision=2015-05-15&amp;deviation=cisco-xr-routing-policy-deviations</capability>
  <capability>http://openconfig.net/yang/policy-types?module=policy-types&amp;revision=2015-05-15</capability>
  <capability>http://cisco.com/ns/yang/cisco-xr-bgp-deviations?module=cisco-xr-bgp-deviations&amp;revision=2015-09-16</capability>
  <capability>http://cisco.com/ns/yang/cisco-xr-bgp-policy-deviations?module=cisco-xr-bgp-policy-deviations&amp;revision=2015-09-16</capability>
  <capability>http://cisco.com/ns/yang/cisco-xr-routing-policy-deviations?module=cisco-xr-routing-policy-deviations&amp;revision=2015-09-16</capability>
 </capabilities>
 <session-id>2506367397</session-id>
</hello>
]]>]]>

Would you look at that! 184 models. I haven't fetched the models from the box just yet but I recognize a few from our private build, like clns-isis for IS-IS config. At the end of the output you can see that Cisco has included a few OpenConfig models as well! They have previously announced this, both privately and publically but it's always nice to see it actually happen, especially as I am involved in the OpenConfig working group, representing the interests of DT/TeraStream.

I'll be trying this out and comparing it to our private builds but I think it's safe to say that Cisco has finally included enough YANG models to make it possible to use NETCONF & YANG as the primary interface to configure and operate your XR box!

Tags: XR, YANG
Other posts