YANG is a modeling language designed to allow network operators to programmatically represent configuration and operational state data. With respect to the world of networking, YANG's premise is one of unification; a tool to allow programmatic interfaces to routing and switching hardware using modern transport layer protocols carrying structured data, as opposed to raw, unstructured, command line (CLI) data.
One of the primary benefits of YANG as a technology is that it allows a vendor-neutral approach to defining the objects, data types, and their relationships when mapping device operational and configuration data to usable programmatic entities.
YANG model definitions can be divided into two major categories; industry standard and vendor specific. Industry standard models can be defined by standards defining organizations (SDOs) such as the IETF, or another example is the set of models defined by a group composed of network operators called OpenConfig. These two examples of industry standard sets of models are commonly referred to as IEFT models and OpenConfig models respectively. The vendor specific models are commonly referred to as native models since they are native only to that vendor's network operating system; in the case with Cisco, operating systems. The goal of SDOs, such as IETF and OpenConfig, is to work toward vendor-neutral YANG models. Native YANG models will most likely continue to exist due to the limited support of current SDO YANG models and also due to potential vendor specific feature/functionality.
YANG models can be found on GitHub at https://github.com/YangModels/yang/. YANG models are defined hierarchically as a tree. Each element in the model is called a node. Each node has a name and value or name and child nodes. YANG is structured into modules, where in general, modules consist of three main elements; module-header statements, revision statements, and definition statements. Header statements, as one would expect, define the name of the module, the modules namespace on the network device, the module definition, or any modules imported from a different YANG model. The revision statement simply gives the history about the module. And finally, the most robust, the definition statement is actually the main body that defines the data model.
Many initial introductions to YANG go right into modules, leafs, nodes, and other elements that comprise the data structure. To help conceptually understand these terms, YANG can be likened to Python data structures, and to take it further, it is possible to convert YANG to JSON, and then JSON to YAML, and then YAML to Python. Functionally these are all just tools for representing data structures, so seeing how YANG elements map to Python is a useful exercise.
YANG Element Python Class
Container Dictionary
Container name Dictionary key
Leaf name Dictionary key
Leaf Dictionary value
List List
String String
Bool Bool
Integer Integer
Empty None
This should help you get a feel for how YANG data structures map to common entities in Python.
Throughout this section of the lab, the ietf-interfaces YANG model will be used as reference for examining what makes up a YANG data model. The ietf-interfaces YANG model can be found here for reference: ietf-interfaces.yang
The abbreviated output from the above mentioned ietf-interfaces.yang shows the header statement and the revision statement of the data model:
module ietf-interfaces {
namespace "urn:ietf:params:xml:ns:yang:ietf-interfaces";
prefix if;
import ietf-yang-types {
prefix yang;
}
organization
"IETF NETMOD (NETCONF Data Modeling Language) Working Group";
...
description
"This module contains a collection of YANG definitions for
managing network interfaces.
Copyright (c) 2014 IETF Trust and the persons identified as
authors of the code. All rights reserved.
Redistribution and use in source and binary forms, with or
without modification, is permitted pursuant to, and subject
to the license terms contained in, the Simplified BSD License
set forth in Section 4.c of the IETF Trust's Legal Provisions
Relating to IETF Documents
(http://trustee.ietf.org/license-info).
This version of this YANG module is part of RFC 7223; see
the RFC itself for full legal notices.";
revision 2014-05-08 {
description
"Initial revision.";
reference
"RFC 7223: A YANG Data Model for Interface Management";
}
...
Yang, per RFC6020, has defined four types of nodes used to define a given data model. These include:
A container node does not have a value itself; only a single argument identifier. A container is instead used to define the particulars of an interior data node in the schema tree which means to group related nodes. The group of related nodes are defined as a list and referred to as child nodes within the data tree. The subsequent substatements within the container make up how each child node is defined. Example substatements include container, description, leaf, leaf-list, list, amongst others. A single defined YANG model can have more than one container grouping like child nodes.
Ietf-interfaces.yang actually has two main containers defined; one for configuration data and the other for operational data. In the truncated output below, you can discern these two are called "interfaces" and "interfaces-state" containers respectively. Make note in the output below the "config false" in the "interfaces-state" container. This is highly important in YANG models as it determines if the object in the tree is a configuration object or to obtain state data. You may sometimes see this annotated as read-only (RO) for state data versus read-write (RW) for configuration data.
module ietf-interfaces {
...
/*
* Configuration data nodes
*/
container interfaces {
description
"Interface configuration parameters.";
...
/*
* Operational state data nodes
*/
container interfaces-state {
config false;
description
"Data nodes for the operational state of interfaces.";
...
Within each container, the next node type introduced is a list. Remember, a container is composed of like nodes in a list data structure. A list defines a sequence of list entries. A list can contain any number or type of elements including, but not limited to leafs, other lists, or even containers.
module ietf-interfaces {
...
/*
* Configuration data nodes
*/
container interfaces {
description
"Interface configuration parameters.";
list interface {
key "name";
description
"The list of configured interfaces on the device.
The operational state of an interface is available in the
/interfaces-state/interface list. If the configuration of a
system-controlled interface cannot be used by the system
(e.g., the interface hardware present does not match the
interface type), then the configuration is not applied to
the system-controlled interface shown in the
/interfaces-state/interface list. If the configuration
of a user-controlled interface cannot be used by the system,
the configured interface is not instantiated in the
/interfaces-state/interface list.";
...
/*
* Operational state data nodes
*/
container interfaces-state {
config false;
description
"Data nodes for the operational state of interfaces.";
list interface {
key "name";
description
"The list of interfaces on the device.
System-controlled interfaces created by the system are
always present in this list, whether they are configured or
not.";
...
As mentioned above, a list contains other node types. Continuing to use our ietf-interfaces.yang example, within each container's list exists a list of leaf nodes. Leaf nodes contain a value, but no additional child nodes. In just examining the "interfaces" container, you can notice several leaf node arguments representing different aspects of an interface and their respective data types. A few examples from below include the interface name and description that are strings or the enabled leaf that is a boolean defaulting to true for the interface to be enabled or disabled.
module ietf-interfaces {
...
/*
* Configuration data nodes
*/
container interfaces {
description
"Interface configuration parameters.";
list interface {
key "name";
leaf name {
type string;
...
}
leaf description {
type string;
...
}
leaf type {
type identityref {
base interface-type;
}
...
}
leaf enabled {
type boolean;
default "true";
...
}
...
This section will introduce a tool for your toolkit and knowledge for viewing YANG models and not necessarily meant to perform the actions. However, if you would like to try it in your Linux environment, then feel free to do so. You will need to pull the ietf-interfaces.yang file from GitHub and also install Pyang as mentioned below.
Pyang is YANG validator and code generator written in Python. Pyang can be pip installed like other packages you have worked with in this
lab using pip install pyang
then you would issue something like: pyang -f tree ietf-interfaces.yang
. The
-f
is a command line option for specifying the format of how you would like to view the YANG model. In this case, we make
use of the
tree
format. This outputs the YANG model like the Linux tree command. You could optionally output the YANG model like found
on GitHub using
yang
. The output using the
tree
format option would look like the below. With pyang, we can more quickly and easily perform the same steps as we did
above once we understand basic YANG nodes, i.e. containers, lists, and leaves.
YANG module hierarchy can be augmented or expanded through the insertion of additional nodes into the data model. These augmentations typically reside within another model that are also contained on the server side along with the base model. The augmentation model, will import the base model in the header as discussed above.
The augmentation is done through the use of an "augment" statement within YANG data model hierarchy where the new node(s) should be inserted. Additionally, the "when" statement is used to define conditional logic for when the new node(s) can be used.
Sticking with the same ietf-interfaces YANG model; lets now look at another YANG model, ietf-ip.yang, that provides augmentations. The output from the above mentioned ietf-ip.yang shows the header statement and the augment statement of the data model that provides the the ability to configure and retrieve IP address related information to the ietf-interfaces model:
module ietf-ip {
namespace "urn:ietf:params:xml:ns:yang:ietf-ip";
prefix ip;
import ietf-interfaces {
prefix if;
}
...
/*
* Configuration data nodes
*/
augment "/if:interfaces/if:interface" {
description
"Parameters for configuring IP on interfaces.
If an interface is not capable of running IP, the server
must not allow the client to configure these parameters.";
container ipv4 {
presence
"Enables IPv4 unless the 'enabled' leaf
(which defaults to 'true') is set to 'false'";
description
"Parameters for the IPv4 address family.";
...
Again, with pyang, you can more quickly and easily perform the same steps as above to view the augments and the respective containers, lists, and leaves that reside under the given augment.
In a perfect world, YANG models would be the same and supported identically by every vendor. However, as we know, it is not a perfect world, thus the RFC specifies a mechanism known as deviations that can reside within YANG models. Deviations can be what YANG models a platform supports, if a platform implements a YANG model differently, etc.
For example, per operating system release, there should exist deviation YANG models, such as the below:
deviation /if:interfaces/if:interface/ip:ipv4/ip:mtu {
deviate not-supported;
description "Not supported in IOS-XE 3.17 release.";
}
YANG is a great resource and tool to have the ability to interact with many network operating systems using the same tooling, as you will see in this section of the lab, but maybe not the same exact models. Throughout the lab, you will use a combination of the IETF, OpenConfig, and Native YANG model definitions to complete a task using different programmatic tooling. Remember, IETF and OpenConfig definitions have only had so much development done in the industry for feature/functionality support. Native YANG models can always be used to accomplish a task when there is a lack of IETF or OpenConfig support, which is most common.
The NXOS YANG model is derived from the DME, i.e. NX-API REST. For NXOS, the native YANG models per release can be found here: https://github.com/YangModels/yang/tree/master/vendor/cisco/nx
Now that you have a basic understanding of how YANG data models are structured and the node types that encompass the model, proceed to the next lab section to learn about Network Configuration Protocol, also known as NETCONF.