Technology: YANG

1. Introduction to YANG (RFC 7950)

YANG, which stands for "Yet Another Next Generation," is a data modeling language defined in RFC 7950 by the Internet Engineering Task Force (IETF). It is designed to model configuration and state data manipulated by the Network Configuration Protocol (NETCONF), as well as other network management protocols such as RESTCONF Protocol and CoAP Management Interface (CORECONF). YANG provides a standardized way to model the operational and configuration data of network devices, enabling more efficient and consistent network management.

1.1. Purpose and Scope

The primary purpose of YANG is to provide a formalized language for defining the structure of network data. This includes configuration data, state data, Remote Procedure Calls (RPCs), and notifications. By using YANG, network operators and developers can create data models that are both human-readable and machine-processable, facilitating automation and reducing the potential for errors in network management.

1.2. Key Features

  1. Hierarchical Data Modeling: YANG models data in a tree structure, which mirrors the hierarchical nature of network configurations. This makes it intuitive to represent complex configurations and relationships between different network elements.

  2. Extensibility: YANG supports the definition of modules, allowing for modular and reusable data models. Modules can even augment data into other modules. This extensibility ensures that YANG can adapt to evolving network technologies and requirements.

  3. Data Types and Constraints: YANG provides a rich set of built-in data types, such as integers, strings, and enumerations, as well as the ability to define custom types. It also supports constraints like range limits and pattern matching, ensuring data validity and consistency.

  4. RPCs and Notifications: YANG allows the definition of RPCs for executing operations on network devices and notifications for asynchronous event reporting. This capability is crucial for dynamic and real-time network management.

  5. Interoperability: YANG is designed to work seamlessly with NETCONF, a protocol for network configuration and management. However, it is also compatible with other protocols, such as CORECONF, making it versatile for various network management scenarios.

1.3. Structure of YANG Modules

A YANG module is a self-contained data model that defines a specific set of data and operations. Each module consists of several key components:

  • Namespace: A unique identifier for the module, ensuring no conflicts with other modules.

  • Prefix: A shorthand reference for the module, used within the module and by other modules that import it.

  • Data Nodes: Elements that represent configuration and state data, organized hierarchically.

  • Typedefs: Custom data types defined within the module.

  • Groupings: Reusable sets of data nodes that can be included in multiple places within the module or other modules.

  • RPCs and Notifications: Definitions for operations and event reporting.

1.4. Benefits of Using YANG

  • Consistency: YANG provides a standardized way to model network data, ensuring consistency across different devices and vendors.

  • Automation: The machine-readable nature of YANG models facilitates automation in network configuration and management, reducing manual intervention and the risk of human error.

  • Interoperability: By adhering to a common modeling language, YANG promotes interoperability between different network management tools and devices.

  • Scalability: The modular and extensible design of YANG allows it to scale with the growing complexity of modern networks.

In conclusion, YANG (RFC 7950) is a powerful and versatile data modeling language that plays a crucial role in modern network management. Its ability to provide a standardized, extensible, and interoperable framework for modeling network data makes it an essential tool for network operators and developers aiming to achieve efficient and reliable network operations.

A YANG file uses the filename extension .yang.

2. YANG Deviations

YANG deviations are a mechanism in the YANG data modeling language that allows a module to specify modifications to the definitions in another YANG module. This is particularly useful when a device or implementation does not fully comply with the standard definitions provided in a base YANG module. Deviations enable vendors or network operators to document and manage these differences in a standardized way.

Key aspects of YANG deviations include:

  1. Deviation Statement: This is used within a YANG module to indicate that it is deviating from another module. The deviation statement specifies the target module and the specific nodes within that module that are being altered.

  2. Deviation Types: Common types of deviations include:

    • Not-supported: Indicates that a particular node defined in the base module is not supported by the implementation.

    • Add: Adds new constraints or properties to an existing node.

    • Replace: Replaces existing properties or constraints of a node with new ones.

    • Delete: Removes certain properties or constraints from a node.

  3. Use Cases: Deviations are used in scenarios where:

    • A device does not support certain features or capabilities defined in a standard YANG module.

    • A vendor needs to extend or modify standard YANG models to fit their specific implementation.

    • Customizations are required for specific deployments or operational environments.

  4. Documentation and Management: By using deviations, vendors and network operators can clearly document the differences between their implementation and the standard YANG models. This helps in maintaining consistency, understanding the capabilities and limitations of devices, and ensuring interoperability.

An example of a deviation might look like this:

deviation /example-module:container/example-leaf {
    deviate not-supported;
}

In this example, the deviation indicates that the example-leaf node within the example-module is not supported by the implementation.

Overall, YANG deviations provide a structured way to handle variations and ensure that these differences are well-documented and managed within the network management ecosystem.

Deviation files in VelocityDRIVE-SP follow the following conventions:

  • One deviation file per YANG file.

  • In VelocityDRIVE-SP, the deviation filename is constructed by adding -dev after the basename.

I.e. the deviation filename for example-interfaces.yang becomes example-interfaces-dev.yang.

3. YANG Tree

A YANG tree is a hierarchical representation of the data model defined by a YANG module. It visually depicts the structure of the data, including the organization of containers, lists, leaf nodes, and other elements. This tree structure helps users understand the relationships and dependencies between different parts of the data model.

The YANG tree is defined in RFC 8340 - 'YANG Tree Diagrams'.

Key components of a YANG tree include:

  1. Root Node: The top-level node of the tree, which typically represents the module itself or a top-level container within the module.

  2. Containers: These are organizational nodes that can group related data nodes together. Containers can contain other containers, lists, leaf nodes, and other elements.

  3. Lists: These are ordered collections of entries, where each entry is a complex type that can contain multiple data nodes. Lists are used to represent repeating elements, such as interfaces or routes.

  4. Leaf Nodes: These are the actual data elements that hold values. Leaf nodes are the endpoints of the tree and do not contain other nodes. They can be of various data types, such as integers, strings, or booleans.

  5. Leaf-Lists: These are similar to lists but contain simple data types rather than complex structures. A leaf-list is an unordered collection of leaf nodes.

  6. Choices and Cases: These are used to define conditional structures within the data model. A choice node represents a decision point, and each case node represents a possible option.

  7. Augmentations: These allow additional nodes to be added to an existing data model, extending its structure.

Here’s an example of a simple YANG tree for a module that models network interfaces:

module: example-interfaces
  +--rw interfaces
     +--rw interface* [name]
        +--rw name          string
        +--rw description?  string
        +--rw type          identityref
        +--rw enabled?      boolean
        +--ro oper-status   enumeration
        +--ro last-change?  yang:date-and-time

In this example:

  • The root node is the example-interfaces module.

  • The interfaces container groups all interface-related data.

  • The interface list represents multiple interface entries, each identified by a name.

  • Each interface entry contains several leaf nodes, such as name, description, type, enabled, oper-status, and last-change.

  • Configuration data nodes are prefixed with rw (read-write) and status/state data nodes are prefixed with ro (read-only).

The full description of the node representation can be found here.

The YANG tree provides a clear and organized way to visualize the structure of the data model, making it easier for developers and network operators to understand and work with the data.

A YANG tree file uses the filename extension .tree and shows the resulting tree after any deviations have been applied.

4. YANG SID Files

A YANG SID (Schema Item Identifier) file is a JSON-formatted file that maps YANG schema nodes to unique numeric identifiers called SIDs. These identifiers are used in protocols like CoAP (Constrained Application Protocol) and CBOR (Concise Binary Object Representation) to efficiently represent YANG data models in constrained environments.

Key aspects of a YANG SID file include:

  1. SID Allocation: Each YANG schema node (e.g., modules, containers, lists, leafs) is assigned a unique SID. This helps in reducing the size of the data representation by using numeric identifiers instead of long textual names.
    As many of the YANG modules we use in VelocityDRIVE-SP have not yet been assigned a permanent SID range, the current allocations are expected to change going forward.

  2. JSON Structure: The SID file is structured in JSON format, making it easy to parse and use in various applications. The file typically includes mappings for all nodes in a YANG module.

  3. Fields in a SID File:

    • assignment-ranges: Starting point and number of allocated SIDs for this module.

    • module-name: The name of the YANG module.

    • module-revision: The revision date of the YANG module.

    • items: An array of objects, each representing a schema node with its corresponding SID.

  4. Example: Here is an example of a YANG SID file corresponding to the YANG tree in the previous section:

    {
      "assignment-ranges": [
        {
          "entry-point": 1000,
          "size": 50
        }
      ],
      "module-name": "example-interfaces",
      "module-revision": "2025-01-01",
      "items": [
        {
          "namespace": "module",
          "identifier": "example-interfaces",
          "status": "unstable",
          "sid": 1000
        },
        {
          "namespace": "data",
          "identifier": "/example-interfaces:interfaces",
          "status": "unstable",
          "sid": 1005
        },
        {
          "namespace": "data",
          "identifier": "/example-interfaces:interfaces/interface",
          "status": "unstable",
          "sid": 1006
        },
        {
          "namespace": "data",
          "identifier": "/example-interfaces:interfaces/interface/description",
          "status": "unstable",
          "sid": 1007
        },
        {
          "namespace": "data",
          "identifier": "/example-interfaces:interfaces/interface/enabled",
          "status": "unstable",
          "sid": 1008
        },
        {
          "namespace": "data",
          "identifier": "/example-interfaces:interfaces/interface/last-change",
          "status": "unstable",
          "sid": 1009
        },
        {
          "namespace": "data",
          "identifier": "/example-interfaces:interfaces/interface/name",
          "status": "unstable",
          "sid": 1010
        },
        {
          "namespace": "data",
          "identifier": "/example-interfaces:interfaces/interface/oper-status",
          "status": "unstable",
          "sid": 1011
        },
        {
          "namespace": "data",
          "identifier": "/example-interfaces:interfaces/interface/type",
          "status": "unstable",
          "sid": 1012
        }
      ]
    }
    In this example:
    - The `module-name` is "example-interfaces".
    - The `module-revision` is "2025-01-01".
    - The `items` array contains mappings of schema nodes to their SIDs.
  5. Usage: SIDs are used in constrained environments to optimize the encoding and transmission of YANG-modeled data. By using numeric identifiers, the data size is reduced, which is crucial for devices with limited resources.

  6. Management: SIDs are typically managed by a central authority or registry to ensure uniqueness and avoid conflicts. This ensures that each SID is globally unique and can be reliably used across different implementations and devices.

In summary, a YANG SID file provides a compact and efficient way to represent YANG schema nodes using numeric identifiers, facilitating the use of YANG data models in resource-constrained environments.

A YANG SID file uses the filename extension .sid and includes the module revision as part of the basename. The SID file name for example-interfaces.yang then becomes example-interfaces@2025-01-01.sid.

5. YANG Catalog

The term "YANG Catalog" refers to a repository or database that contains YANG data models.

See here for more information about "YANG Catalog" in VelocityDRIVE-SP.

6. YANG and JSON/YAML

Although using payload encoded as binary CBOR is useful and necessary in a constrained environment, it is not especially user-friendly.

It is possible to use CBOR Diagnostic Notation towards the user and let the client tool handle the conversion from CBOR Diagnostic Notation to binary CBOR and vice versa. This approach has the disadvantage that the user will need to know the numerical SIDs and must be mentally capable of connecting these numbers to a YANG model.

To make it easier for the user, Microchip has developed a few CLI tools that enable the user to query and configure a VelocityDRIVE-SP device using JSON or YAML encoded data as payload:

  • mvdct - CLI part of the VelocityDRIVE-CT package - supports JSON only

  • mup1cc - part of this package - supports both JSON and YAML

Both of these tools make use of the YANG Catalog in order to convert between JSON/YAML and CBOR.

The connection between JSON and YANG is defined in RFC 7951 - 'JSON Encoding of Data Modeled with YANG', and because YAML is considered to be a superset of JSON, it is possible to use YAML as long as YAML is supported by the client tool.

How to encode YANG data to CBOR is defined in RFC 9254 - 'Encoding of Data Modeled with YANG in the Concise Binary Object Representation (CBOR)'. Note that this only covers the data syntax and not how requests and responses should look. See the Examples below on how to use YAML in requests and responses.

Here is an example of using YAML versus CBOR Diagnostic Notation to specify a YANG instance identifier to get the type of interface "1" using a CoAP FETCH method.

YAML request:

- "/ietf-interfaces:interfaces/interface[name='1']/type"

YAML response:

---
- "/ietf-interfaces:interfaces/interface/type": iana-if-type:ethernetCsmacd

CBOR Diagnostic Notation request:

[_ 2061, "1"]

CBOR Diagnostic Notation response:

{_ 2061: 3088}

It should be pretty obvious to see which of the formats that are most oriented towards the YANG model.

6.1. Examples of YAML requests and responses

These examples are intended to show how to create a valid YAML request for different CoAP methods, and not to explain what a specific request will do on a VelocityDRIVE-SP device.

For information about the different features in a VelocityDRIVE-SP device, please see the Configuration Guides section.

In YAML it is possible to break a string over multiple lines by ending a line with '\' and continue on the next line. This is used in the examples to prevent the need for a horizontal scrollbar.

The FETCH and iPATCH methods support multiple requests in a single method and this is why a request must always be specified as a YAML sequence (aka array), even if there is only a single request. A YAML sequence starts with a dash and space ("- ").

The FETCH and iPATCH methods use instance identifiers as specified in RFC7951-6.11.

All parent keys must be present in an instance identifier.

The examples use YANG objects from ieee802-dot1q-bridge.tree and ietf-interfaces.tree

6.1.1. FETCH

A FETCH request consists of an instance identifier that includes all parent keys.

FETCH request of a YANG list with two parent keys 'b0' and 'c0':
- "/ieee802-dot1q-bridge:bridges/bridge[name='b0']/component[name='c0']/\
   filtering-database/vlan-registration-entry"
FETCH response:
---
- "/ieee802-dot1q-bridge:bridges/bridge/component/filtering-database/\
   vlan-registration-entry":
  - database-id: 0
    vids: '1'
    entry-type: static
    port-map:
    - port-ref: 1
      static-vlan-registration-entries:
        vlan-transmitted: untagged
    - port-ref: 2
      static-vlan-registration-entries:
        vlan-transmitted: tagged
  - database-id: 0
    vids: '10'
    entry-type: static
    port-map:
    - port-ref: 3
      static-vlan-registration-entries:
        vlan-transmitted: untagged
    - port-ref: 4
      static-vlan-registration-entries:
        vlan-transmitted: tagged

Note that the response consists of a sequence of two entries. When fetching a list without including the list’s own keys, a sequence of all entries is returned.

FETCH request of YANG list as above, but now also including the list’s own keys:
- "/ieee802-dot1q-bridge:bridges/bridge[name='b0']/component[name='c0']/\
   filtering-database/vlan-registration-entry[database-id='0'][vids='1']"
FETCH response:
---
- "/ieee802-dot1q-bridge:bridges/bridge/component/filtering-database/\
   vlan-registration-entry":
    database-id: 0
    vids: '1'
    entry-type: static
    port-map:
    - port-ref: 1
      static-vlan-registration-entries:
        vlan-transmitted: untagged
    - port-ref: 2
      static-vlan-registration-entries:
        vlan-transmitted: tagged

Note that the response consists of a single entry. When fetching a list and including the list’s own keys, only a single entry is returned.

6.1.2. iPATCH

An iPATCH request consists of an instance identifier that includes all parent keys and a value.

We use complex keys in all examples as we think they are more readable.

A complex key is preceded by a question mark and space ("? ") and the corresponding value is defined on the next line and preceded by a colon and space (": ").

Example of a YAML object using a complex key:
- ? "key"
  : "value"

The YANG object, specified by the instance identifier, is deleted if the value is empty or null.

Deleting is supported on containers and lists but not on leaves and leaf-lists.

iPATCH request for deleting a specific entry in a YANG list:
- ? "/ieee802-dot1q-bridge:bridges/bridge[name='b0']/component[name='c0']/\
     filtering-database/vlan-registration-entry[database-id='0'][vids='1']"
  :

Note that the list’s own keys are specified in the instance identifier. The only place where the list’s own keys are allowed in the instance identifier is in a delete operation like this. Also note that the value is empty.

iPATCH request for deleting all entries in a YANG list:
- ? "/ieee802-dot1q-bridge:bridges/bridge[name='b0']/component[name='c0']/\
     filtering-database/vlan-registration-entry"
  :

Note that none of the list’s own keys are specified in the instance identifier.

iPATCH request for deleting a YANG container:
- ? "/ieee802-dot1q-bridge:bridges/bridge[name='b0']/component[name='c0']/\
     filtering-database"
  :

Note that in most circumstances it makes no sense to delete a container, as it will only be reset to a system-defined default content.

iPATCH request for creating a vlan-registration-entry:
- ? "/ieee802-dot1q-bridge:bridges/bridge[name='b0']/component[name='c0']/\
     filtering-database/vlan-registration-entry"
  : database-id: 0
    vids: '1'
    entry-type: static
    port-map:
    - port-ref: 1
      static-vlan-registration-entries:
        vlan-transmitted: untagged
    - port-ref: 2
      static-vlan-registration-entries:
        vlan-transmitted: tagged

Note that none of the list’s own keys must be specified in the instance identifier. Also note that the value is a YAML map which corresponds to a YANG container. When a container is added to a list, only the container is added (or replaced). Previous entries in the list are left as they were before the iPATCH operation.

iPATCH request for creating a vlan-registration-entry:
- ? "/ieee802-dot1q-bridge:bridges/bridge[name='b0']/component[name='c0']/\
     filtering-database/vlan-registration-entry"
  : - database-id: 0
      vids: '10'
      entry-type: static
      port-map:
      - port-ref: 3
        static-vlan-registration-entries:
          vlan-transmitted: untagged
      - port-ref: 4
        static-vlan-registration-entries:
          vlan-transmitted: tagged
    - database-id: 0
      vids: '11'
      entry-type: static
      port-map:
      - port-ref: 1
        static-vlan-registration-entries:
          vlan-transmitted: untagged
      - port-ref: 2
        static-vlan-registration-entries:
          vlan-transmitted: tagged

Note that none of the list’s own keys must be specified in the instance identifier. Also note that the value is a YAML sequence (aka array), which corresponds to a YANG list. When a list is added to a list, the original list is replaced with the new list. Previous entries in the list are now gone.

iPATCH request for setting a single leaf, vlan-transmitted, to tagged:
- ? "/ieee802-dot1q-bridge:bridges/bridge[name='b0']/component[name='c0']/\
     filtering-database/vlan-registration-entry[database-id='0'][vids='1']/\
     port-map[port-ref='1']/static-vlan-registration-entries/vlan-transmitted"
  : tagged

Note that all parent keys must be specified in the instance identifier.