The Magic of Multi-key Leafrefs in YANG

This post is a more of a reference note around some YANG modeling specifics. It has come up a couple of times so I thought I’d follow the DRY principle and document once and reference forever. I think the casual reader will enjoy the read (especially if interested in modeling stuff) but there are XPath predicates and NETCONF error tags ahead so be warned!

The YANG language provides a useful concept in the leafref statement. It is a way to reference a particular leaf instance in a data store. This is one of the semantic validation constructs that really adds tangible benefits above and beyond what’s available in e.g. SMI.

A common use case is to use a leafref to reference the network interface or IP address used for a particular purpose. Since leafrefs refer to instances, not nodes in the model, it also implies that there is valid configuration in place for that particular interface or IP address. Here’s an example from the CCAP YANG module:

leaf slot {
    type leafref {
        path "/ccap/chassis/slot/slot-number";
    }
 }

The slot leaf references an instance of a slot in a CCAP chassis identified by it’s slot number which is also the key in the slot list. This means that the referenced slot configuration (e.g. slot “1”) must exist in the configuration for the referencing leaf to be valid. Dangling pointers are not allowed. This is in contrast with e.g. how ifIndex is used in SNMP where there is no validation of whether the pointed-to object really exists.

Validation is performed by the server side and there is a specific error message defined for situations where a leafref would refer to a non-existing instance (from RFC 6020, Section 13.6):

error-tag: data-missing
error-app-tag: instance-required
error-path: Path to the leafref leaf.

This post wouldn’t be any fun if it didn’t introduce a challenge though; so here goes. The CCAP model introduced above obviously goes deeper than the ‘slot’ concept. Slots are expected to contain line cards of various types and there are ports sitting on the line card. A system can contain several slots. Each slot contains a single line card (that may or may not be present) and a line card hosts several ports.

So, in order to reference an instance of, say, a port. We need to traverse the following structure with our reference:

  • A list of slot/line-card pairs that each contain a;
  • list of ports

An example of such a reference could be:

<slot>2</slot>
<upstream-rf-port>4</upstream-rf-port>

Note that we need to specify two values (slot 2 and port 4) to uniquely identify a port instance. Note that since there is a 1:1 mapping between slot and line-card (a slot may only contain exactly 0 or 1 line-cards) there is no need for a key reference to the line-card.

A more mundane example of this is how certain router vendors identify interfaces in the CLI:

  • Juniper: ge-0/0/1 for gigabit ethernet port 1 in PIC 0 in slot 0
  • Cisco: FastEthernet0/0 for fast ethernet port 0 in slot 0

The numeric components of these interface names are examples of instance identifiers, meaning that they references keys (one per list traversed) to uniquely identify a specific leaf. Now if you remember the syntax of the path-statement above:

path "/ccap/chassis/slot/slot-number";

The XPath syntax in the path statements does not include a way to provide more than a single key (in this case slot-number), so as we go further down the path we would end up with something like:

path "/ccap/chassis/slot/line-card/rf-line-card/upstream-rf-port/port-number";

The path statement above looks deceptively simple and it is both. It only identifies port-number on value, meaning that if we have several RF line cards with the same identifier (say “0”), then we’ll get a match for all of those which is not what we would be looking for in a leafref. The qualifying parent keys are missing. This requires a pretty neat trick using XPath predicates in leafrefs.

Leafref path statements (described in RFC6020, Section 9.9.2) is a subset of XPath abbreviated syntax. This opens up for the use of XPath predicates that can be used to find specific node(s) that contain a specific value. The trick that we are going to look at uses the current() predicate to pin keys while traversing trees with multiple keys. The current() predicate is specific to YANG’s application of XPath (imported from XSLT) and is described like this in RFC 6020 Section 6.4.1:

The function library is the core function library defined in [XPATH], and a function “current()” that returns a node set with the initial context node.

Now, looking at the following extended snippet from the CCAP model:

grouping upstream-physical-channel-reference {
    leaf slot {
        type leafref {
            path "/ccap/chassis/slot/slot-number";
        }
    }
    leaf upstream-rf-port {
        type leafref {
            path "/ccap/chassis/slot[slot-number=current()/../slot]/line-card/rf-line-card/upstream-rf-port/port-number";
        }
    }
}

The upstream-physical-channel-reference grouping contains two leaves. The slot leaf is a leafref with a path referring to a slot. The upstream-rf-port leaf is where the fun starts. By using the current() function in a predicate we reference the list member that have the same slot-number value as the sibling slot leafref.

So, the combination of the slot and upstream-rf-port leafs uniquely identify an upstream port. And by collecting them into a grouping with a label upstream-physical-channel-reference, we’ve made it reusable. So anytime we need to refer to a physical channel interface we can instantiate it using uses. Except in notifications, but that’s for a separate blog post.

This, by the way, can’t be done in XML Schema. Which is unexpected. All evidence to the contrary would be much appreciated.

Advertisements
2 comments
  1. Muhammed Shafeeque K N said:

    how to create key-less yang list? any idea?

    • Comment said:

      use a leaf-list

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: