YANG primer

Quickstart on the most used parts of the management modeling language.

YANG is a language utilized for modeling the management functions of applications. The primary function of YANG files are to enable remote tools to comprehend a server’s management functions, enable servers to accurately provide defined management functions, and generate documentation for individuals seeking to understand a server’s management functions. As a software engineer who implements management functions, it is crucial to understand how to create YANG files. Although there are numerous books on the subject, this document will provide a high-level understanding. It is recommended to consult the YANG RFC for a comprehensive specification of the language.

If you are familiar with other interface definition languages such as gRPC or OpenAPI, you will find several similarities with YANG. However, YANG extends beyond these languages to account for management-specific aspects.

It is essential to note that YANG is not limited to RESTCONF and can be employed with other communication protocols, such as NETCONF or custom protocols.

If you familiar with YANF and RESTCONF already, some these responses might look different. See Compliance on how to control this.

Data Definitions

module

Every YANG file starts module {} statement. All further definitions are contained inside the {} brackets.

module car {
  prefix "c";
  namespace "yourcompany.com";
  revision 2023-03-11;

  // all further definitions here
}

There is always just a single module in a YANG file.

RFC reference

leaf

module car {
  leaf driver {
    type string;
  }
}

If a server used this YANG file, then possible response for requesting data via curl might be:

curl https://server/restconf/data/car:

{
 "driver": "joe"
}

While the base URL of /restconf/data/ is not strictly neccessary, it is pretty standard for all RESTCONF servers.

RFC reference

all possible leaf types

NameDescription
binaryAny binary data
bitsA set of bits or flags
boolean“true” or “false”
decimal6464-bit signed decimal number
emptyA leaf that does not have any value
enumerationOne of an enumerated set of strings
identityrefA reference to an abstract identity
instance-identifierA reference to a data tree node
int88-bit signed integer
int1616-bit signed integer
int3232-bit signed integer
int6464-bit signed integer
leafrefA reference to a leaf instance
stringA character string
uint88-bit unsigned integer
uint1616-bit unsigned integer
uint3232-bit unsigned integer
uint6464-bit unsigned integer
unionChoice of member types

RFC reference

container

module car {
  container engine {}
}

Possible request/responses:

curl https://server/restconf/data/car:

{
 "engine": {}
}

RFC reference

list

module car {
  list cylinders {
    leaf firingOrder {
      type int32;
    }
  }
}

Possible request/responses:

curl https://server/restconf/data/car:

{
  "cylinders":[
    {
      "firingOrder": 1
    }
    {
      "firingOrder": 4
    }
    {
      "firingOrder": 3
    }
    {
      "firingOrder": 2
    }
  ]
}

Most list will have a key when referencing a particular item in the list.

module car {
  list cylinders {
    key num;
    leaf num {
      type int32;
    }
    leaf firingOrder {
      type int32;
    }
  }
}
curl https://server/restconf/data/car:

{
  "cylinders":[
    {
      "num": 1,
      "firingOrder": 1
    }
    {
      "num": 2,
      "firingOrder": 4
    }
    {
      "num": 3,
      "firingOrder": 3
    }
    {
      "num": 4,
      "firingOrder": 2
    }
  ]
}

curl https://server/restconf/data/car:cylinders=1

{
  "num": 1,
  "firingOrder": 1
}

RFC reference

container/leaf

module car {
  leaf driver {
    type string;
  }
  container engine {
    leaf cylinders {
      type int32;
    }
  }
}

Possible request/responses:

curl https://server/restconf/data/car:

{
 "driver": "joe"
 "engine": {
  "cylinders": 6
 }
}

RFC reference

leaf-list

module car {
  leaf-list owners {
    type string;
  }
}

Possible request/responses:

curl https://server/restconf/data/car:

{
 "owners": ["joe","mary"]
}

leaf-lists can have all the same types as leaf, only it would container multiples of said type.

RFC reference

rpc

module car {
  rpc start {}
}

Possible request/responses:

curl -X POST https://server/restconf/data/car:start

# no response but car should start otherwise you'd get an error

RFC reference

rpc/input/output

module car {
  rpc drive {
    input {
      leaf throttle {
        type int32;
      }
    }
    output {
      leaf acceleration {
        type int32;
      }
    }
  }
}

Possible request/responses:

curl -X POST -d '{"throttle":32}' https://server/restconf/data/car:drive

{
  "acceleration": 30
}

RFC reference

container/action/input/output

For historical reasons, action is exactly like rpc except rpcs are only allowed inside module and action is used everywhere else.

module car {
  
  rpc drive {} // correct

  container engine {
    action start {} // correct
  }
}
module car {
  
  action drive {} // INCORRECT, only rpc here
  
  container engine {
    rpc start {} // INCORRECT, only action here
  }
}

RFC reference

notification

module car {
  notification flatTire {}   
}

Possible request/responses:

curl https://server/restconf/data/car:flatTire

data: {"notificaton":{"eventTime":"2013-12-21T00:01:00Z"}}

RFC reference

notification/leaf

module car {
  notification flatTire {
    leaf tireCount {
      type int32;
    }
  }   
}

Possible request/responses:

curl https://server/restconf/data/car:flatTire

data: {"notificaton":{"eventTime":"2013-12-21T00:01:00Z","event":{"tireCount":1}}}

RFC reference

anydata

module car {
  anydata glovebox;
}

Possible request/responses:

curl https://server/restconf/data/car:

{
  "glovebox" {
    "papers" : ["registration", "manual"],
    "napkinCount" : 30
  }
}

RFC reference

Organizational

group/uses

Grouping is simply a way to reuse a set of definitions

This YANG

module car {
  
  leaf driver {
    type string;
  }

  uses engineDef;

  grouping engineDef {
    container engine {
      leaf cylinders {
        type int32;
      }
    } 
  }
}

is equivalent to this YANG:

module car {
  
  leaf driver {
    type string;
  }

  container engine {
    leaf cylinders {
      type int32;
    }
  } 
}

RFC reference

choice/case

When you want to ensure there is just one of a number of definitions. If you are familiar with gRPC, this is like oneof. Some languages call this union:

module {
  choice nameDoesntMatter {
    leaf a {
      type string;
    }
    leaf b {
      type string;
    }
    leaf c {
      type string;
    }
  }
}

This means if a exists, then b and c cannot.

This you have multiple items in the option, you can wrap them with a case statement.

module {
  choice nameDoesntMatter {
    case nameAlsoDoesntMatter1 {
      leaf a {
        type string;
      }
      leaf aa {
        type string;
      }
    }
    leaf b {
      type string;
    }
    leaf c {
      type string;
    }
  }
}

This means if a and/or aa exist, then b and c cannot.

RFC reference

typedef

typedef are simply a way to reuse a leaf type

This YANG

module {
  leaf driver {
    type string;
  }
}

is equivalent to this YANG

module {
  
  typedef person {
    type string;
  }

  leaf driver {
    type person;
  }
}

This would be more useful then type has more definitions associated with it and more opportunities to reuse the typedef.

RFC reference

Metrics

Metrics are just definitions that are marked config false.

module {

  leaf speed {
    config false;  // <-- Metric HERE
    type int32;
  }

  leaf color {
    type string;
  }
}
module {

  container stats {
    config false;  // <-- children of a containers are metrics too
    leaf count {
      type int32;
    }
    leaf rate {
      type int32;
    }
  }
}

RFC reference

Constraints

There are a lot more types of contraints, but here are a few;

number types

module car {
  leaf cylinders {
    type int32 {
      range "1..12";
    }
  }
}

You can have any number of range items that you need.

RFC reference

string types

module car {
  leaf color {
    type string {
      pattern "[a-z]*"; // lowercase
    }
  }
}

You can have any number of pattern items that you need.

RFC reference

Extensions

You can customize YANG files with data that is specific to your application. Extensions will be ignored by any systems that do not support your customizations.

module car {
  prefix my;

  extension secret;

  leaf owner {
    type string;
    my:secret;
  }
}

extensions have have any number of arguments:

module car {
  prefix my;

  extension secret {
    argument "vault";
  }

  leaf owner {
    type string;
    my:secret "safe";
  }

  leaf history {
    type string;
    my:secret "jerry";
  }
}

RFC reference

More

Even this is not an exhaustive, but still more useful contructs:

  • import - pull in select YANG from another file. RFC reference
  • include - pull in all YANG from another file. RFC reference
  • default - value to use for leafs when no value is supplied. RFC reference
  • augment - used with grouping/uses to add definitions to a grouping. RFC reference
  • refine - also used with uses to alter specific definition including adding constraints. RFC reference
  • leafref - a reference to another leaf’s data that must exist. Kinda like a foreign key RFC reference
  • when - data definitions that only exist when certain data is true. RFC reference
  • must - a constraint that is tied to other leaf’s data. RFC reference
  • identity - system wide enum that can have heirarchies. RFC reference
  • feature - denote parts of the YANG that are only valid if a feeature it on. RFC reference
  • revision - track versions of your YANG. RFC reference
  • error-message - control the error messaging. RFC reference
  • ordered-by - control the order of lists. RFC reference

Example YANG files

  • toaster.yang - Used as the “hello world” or “TODOs” application for YANG. It demonstrates common YANG items.
  • fc-restconf.yang - If you use FreeCONF, this is the configuration of the RESTCONF service you’d be using to handle your RESTCONF interface.
  • ietf-inet-types.yang - IETF types are useful to import as common set of field types/