Skip to content
Log in Sign up My account

6.3 YANG Data Modeling

Blueprint 6.3: Describe the high-level principles and benefits of a data modeling language, such as YANG

  • What a data model is and why it beats CLI screen scraping
  • YANG building blocks: module, container, list (with key), leaf, leaf-list, typedef, grouping, augment, config false
  • Model families: IETF, OpenConfig, Cisco native and operational models
  • How one YANG model is carried by NETCONF (XML) and RESTCONF (XML or JSON)
  • Reading a model in tree form

The verb is describe. You will not write YANG modules on the exam. You will be asked what YANG is for, what a node type means, which statement about a model or tree is true, or how a model maps to an XML or JSON payload. Configuring NETCONF and RESTCONF themselves is objective 4.6 in the Network Assurance domain; this page covers the model they both carry.

Why a data model

For decades, automation meant sending CLI commands over SSH and parsing the text that came back. That works until the output format changes between releases, a column moves, or a platform words something differently. The CLI was built for people.

A data model describes, in a formal language, exactly what configuration and state a device has: the names of the nodes, their types, which are mandatory, which are lists, what range a value may take, and which data is configuration versus read-only state. Software on both sides reads the same model, so a client knows exactly how to build a request and parse a reply.

YANG (Yet Another Next Generation) is that language. YANG 1.0 is RFC 6020 and YANG 1.1 is RFC 7950.

Without a model (CLI scraping) With a YANG model
Output is free text, parsed with regular expressions Output is structured XML or JSON that a library parses
Format can change between releases and break scripts The model is versioned with revision statements
The device validates a command only when it is entered, one line at a time The server validates the whole change against the model before applying it
Partial failure can leave half a change applied NETCONF changes are transactional: all or nothing
Each vendor has its own syntax Standard models (IETF, OpenConfig) work across vendors
No difference between config and state in the text config true and config false separate them

Benefits to remember for the exam: vendor-neutral standard models, machine-readable structure, built-in validation (types, ranges, mandatory nodes), separation of configuration and operational data, transactional changes, and independence from the encoding and the transport.

Model, encoding, protocol, transport

YANG defines what the data looks like. It does not say how it is encoded or carried. The same model can be sent as XML over NETCONF or JSON over RESTCONF.

graph TB
  M["Content: YANG model<br/>for example ietf-interfaces"] --> E1["Encoding: XML"]
  M --> E2["Encoding: JSON"]
  E1 --> P1["Protocol: NETCONF<br/>RPCs: get, get-config, edit-config"]
  E1 --> P2["Protocol: RESTCONF<br/>HTTP GET, POST, PUT, PATCH, DELETE"]
  E2 --> P2
  P1 --> T1["Transport: SSH, TCP 830"]
  P2 --> T2["Transport: HTTPS, TCP 443"]
NETCONF RESTCONF
Standard RFC 6241 RFC 8040
Transport SSH, TCP 830 HTTPS, TCP 443
Encoding XML XML or JSON
Operations RPCs: <get>, <get-config>, <edit-config>, <lock>, <commit> HTTP methods
Datastores running, candidate, startup (if supported) Unified view of the datastore
Transactions Yes, with candidate and commit Each request stands alone
IOS XE command netconf-yang restconf plus ip http secure-server

gNMI, a gRPC-based protocol used mainly for streaming telemetry, also carries YANG-modelled data. It is mentioned here only so you recognise the name.

YANG building blocks

module example-vlans {
  yang-version 1.1;
  namespace "urn:example:vlans";
  prefix vl;

  import ietf-inet-types {
    prefix inet;
  }

  organization "CCNP Fast Track";
  description "A small VLAN table used to explain YANG.";

  revision 2026-10-01 {
    description "Initial revision.";
  }

  typedef vlan-id {
    type uint16 {
      range "1..4094";
    }
  }

  container vlans {
    list vlan {
      key "id";
      leaf id {
        type vlan-id;
      }
      leaf name {
        type string {
          length "1..32";
        }
        mandatory true;
      }
      leaf enabled {
        type boolean;
        default "true";
      }
      leaf gateway {
        type inet:ipv4-address;
      }
      leaf-list tagged-port {
        type string;
      }
      leaf state {
        type enumeration {
          enum active;
          enum suspended;
        }
        config false;
      }
    }
  }
}
Statement Meaning Becomes in JSON Becomes in XML
module The unit of definition, with a namespace and prefix Prefix on top-level names, such as example-vlans:vlans xmlns attribute
container Groups related nodes; appears once Object { } Element with children
list Multiple entries, each identified by its key leaf or leaves Array of objects [ {...}, {...} ] Repeated element
leaf One value of a given type "name": value <name>value</name>
leaf-list Several values of one type Array of values [ "a", "b" ] Repeated element with text
typedef A reusable derived type, such as vlan-id limited to 1 to 4094 Not visible in data Not visible in data
grouping / uses A reusable set of nodes, copied in where uses appears Not visible in data Not visible in data
augment Adds nodes into another module's tree Members prefixed with the augmenting module, such as ietf-ip:ipv4 Elements in the other namespace
config false Read-only operational state Returned by GET of operational data Returned by <get>, not <get-config>
rpc, action An operation, such as reload or clear counters Input and output parameters <rpc> payload
notification An event a device can send Notification body <notification>
deviation A vendor's statement that it does not support part of a model as written Not visible in data Not visible in data

Built-in types include string, boolean, int8 to int64, uint8 to uint64, decimal64, enumeration, identityref, leafref (a pointer to another leaf's value), union and empty. Restrictions such as range, length and pattern narrow a type, and the server rejects any value outside them.

Exam trap

Do not mix up list and leaf-list. A list holds entries that are themselves groups of leaves, and every entry needs its key. A leaf-list holds plain values of one type, such as several DNS server addresses. In JSON both are arrays, but a list is an array of objects and a leaf-list is an array of strings or numbers.

The same data three ways

One VLAN entry in the model above, as a client would send it.

{
  "example-vlans:vlans": {
    "vlan": [
      {
        "id": 10,
        "name": "USERS",
        "gateway": "10.10.10.1",
        "tagged-port": ["GigabitEthernet1/0/1", "GigabitEthernet1/0/2"]
      }
    ]
  }
}
<vlans xmlns="urn:example:vlans">
  <vlan>
    <id>10</id>
    <name>USERS</name>
    <gateway>10.10.10.1</gateway>
    <tagged-port>GigabitEthernet1/0/1</tagged-port>
    <tagged-port>GigabitEthernet1/0/2</tagged-port>
  </vlan>
</vlans>
vlan 10
 name USERS

enabled is omitted, so the server uses its default of true. state is config false, so a client never sends it; it only appears when reading operational data. The XML namespace comes from the module's namespace statement, while the JSON prefix uses the module name.

Reading a YANG tree

Modules are long. Engineers read them in tree form, generated by the open-source pyang tool (pyang -f tree module.yang) or browsed in Cisco YANG Suite. You may be shown a tree on the exam.

module: example-vlans
  +--rw vlans
     +--rw vlan* [id]
        +--rw id             vlan-id
        +--rw name           string
        +--rw enabled?       boolean
        +--rw gateway?       inet:ipv4-address
        +--rw tagged-port*   string
        +--ro state?         enumeration
Symbol Meaning
rw Configuration data (read-write)
ro State data (config false, read-only)
* A list or leaf-list (many)
[id] The list key
? Optional node
No ? on a leaf Mandatory (or the key)
-x / -n An rpc or action / a notification

Here is a trimmed tree of the standard ietf-interfaces model (RFC 8343) with the ietf-ip augmentation, which is the model used throughout this course:

module: ietf-interfaces
  +--rw interfaces
     +--rw interface* [name]
        +--rw name                 string
        +--rw description?         string
        +--rw type                 identityref
        +--rw enabled?             boolean
        +--ro oper-status          enumeration
        +--ro phys-address?        yang:phys-address
        +--ro statistics
        |  +--ro in-octets?        yang:counter64
        |  +--ro out-octets?       yang:counter64
        +--rw ip:ipv4!
           +--rw ip:enabled?       boolean
           +--rw ip:address* [ip]
              +--rw ip:ip          inet:ipv4-address-no-zone
              +--rw (subnet)
                 +--:(prefix-length)
                 |  +--rw ip:prefix-length?  uint8
                 +--:(netmask)
                    +--rw ip:netmask?        yang:dotted-quad

The ip: prefix shows nodes added by the ietf-ip module through augment, which is why JSON payloads contain "ietf-ip:ipv4". (subnet) is a choice: an address has either a prefix-length or a netmask, not both. IOS XE returns the netmask form. The ! after ipv4 marks a presence container, one whose existence carries meaning by itself.

Exam trap

The key of a list is mandatory, and the URL of a single list entry in RESTCONF uses it: .../interface=GigabitEthernet1. If a question asks how to address one entry of a list, the answer involves the key leaf named in square brackets in the tree.

Model families on IOS XE

graph TB
  Y["YANG models on IOS XE"] --> I["IETF standard<br/>ietf-interfaces, ietf-ip, ietf-routing"]
  Y --> O["OpenConfig<br/>openconfig-interfaces, openconfig-bgp"]
  Y --> N["Cisco native config<br/>Cisco-IOS-XE-native"]
  Y --> P["Cisco operational<br/>Cisco-IOS-XE-*-oper"]
  I --> V["Vendor neutral, limited coverage"]
  O --> V
  N --> C["Full CLI coverage, Cisco only"]
  P --> C
Family Written by Coverage Example path
IETF IETF working groups, published as RFCs Common features only ietf-interfaces:interfaces/interface=GigabitEthernet1
OpenConfig Group of network operators Common features, strong on telemetry openconfig-interfaces:interfaces
Cisco native Cisco, mirrors the IOS XE CLI Nearly everything you can configure Cisco-IOS-XE-native:native/hostname
Cisco operational Cisco Read-only state, like show commands Cisco-IOS-XE-interfaces-oper:interfaces

All three configuration families write the same running configuration. A loopback created with ietf-interfaces appears in show running-config and is also visible through Cisco-IOS-XE-native. Choose IETF or OpenConfig when you need multi-vendor scripts, and native when the feature is not in a standard model. The public YangModels repository on GitHub publishes the models each IOS XE release supports, and a device also advertises its models in its NETCONF <hello> capabilities.

Exam trap

YANG is not a protocol and not an encoding. If an option says "YANG transports configuration over SSH" or "YANG is a JSON-based format", it is wrong. YANG is the modeling language; NETCONF and RESTCONF are the protocols; XML and JSON are the encodings.

Datastores

NETCONF works on named datastores:

Datastore Contents IOS XE
running The active configuration Always present
startup Configuration loaded at boot copy running-config startup-config updates it
candidate A scratch copy that is committed to running in one step Optional, enabled with netconf-yang feature candidate-datastore
operational Configuration in use plus all state data (NMDA, RFC 8342) Read-only

The candidate datastore is what makes NETCONF transactional: a client locks it, makes several edits, validates, and commits all of them together, or discards them.

Lab: explore models on a Catalyst 8000v

Topology: AUTO (Ubuntu, 192.168.100.50) to R1 (C8000v, Gi1 192.168.100.1/24), as in the Python and JSON lab.

  1. Enable both programmable interfaces on R1:

    username admin privilege 15 secret Cisco123!
    ip http secure-server
    ip http authentication local
    restconf
    netconf-yang
    
  2. Verify NETCONF is listening, then open a NETCONF session from AUTO and read the capabilities the device sends in its <hello>:

    AUTO$ ssh -p 830 [email protected] -s netconf
    <?xml version="1.0" encoding="UTF-8"?>
    <hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
    <capabilities>
    <capability>urn:ietf:params:netconf:base:1.0</capability>
    <capability>urn:ietf:params:netconf:base:1.1</capability>
    ...
    <capability>urn:ietf:params:xml:ns:yang:ietf-interfaces?module=ietf-interfaces&amp;revision=...</capability>
    ...
    

    The list is several hundred lines long, one capability per supported module. Close the session with Ctrl+C.

  3. On R1, confirm the session appeared:

    R1# show netconf-yang sessions
    

    You should see one session of type netconf-ssh for user admin while step 2 is open.

  4. Read the same interface through two models from AUTO and compare the structure:

    curl -sk -u admin:Cisco123! -H "Accept: application/yang-data+json" \
      https://192.168.100.1/restconf/data/ietf-interfaces:interfaces/interface=GigabitEthernet1
    
    curl -sk -u admin:Cisco123! -H "Accept: application/yang-data+json" \
      https://192.168.100.1/restconf/data/Cisco-IOS-XE-native:native/interface/GigabitEthernet=1
    

    The IETF view returns "ietf-interfaces:interface" with name, type, enabled and an ietf-ip:ipv4 object. The native view returns "Cisco-IOS-XE-native:GigabitEthernet" keyed by the number "1", with the address under ip, mirroring the CLI hierarchy.

  5. Request the IETF view as XML by changing the header to Accept: application/yang-data+xml. Note that the data is identical; only the encoding changed.

  6. On recent IOS XE releases you can see the model view of your configuration directly on the router with show running-config | format restconf-json or | format netconf-xml. Run it and find the hostname leaf.
  7. Optional: on AUTO, install pyang with pip, download ietf-interfaces.yang from the YangModels repository, and run pyang -f tree ietf-interfaces.yang to produce the tree shown above.

Quick check

In a YANG tree, what does +--rw neighbor* [address] tell you?

neighbor is a list (the *) of configuration data (rw), and each entry is uniquely identified by its address key leaf.

A leaf is marked config false. Can a RESTCONF PATCH change it?

No. config false marks read-only operational state. It appears in GET responses for operational data, but the server rejects any attempt to write it.

Why does a RESTCONF JSON payload for an interface contain ietf-ip:ipv4 while the other members have no prefix?

The ipv4 container is added to the interface by the ietf-ip module through augment. In JSON (RFC 7951), a member defined in a different module from its parent carries that module's name as a prefix.

References