YANG Constraints Explained

YANG constraints are rules within a YANG model that automatically validate configuration data to ensure it is consistent and allowed. All YANG constraints are checked before a configuration change can take effect, preventing invalid configurations from being applied.

YANG defines three main types of constraints:

  • Must statements - to enforce arbitrary conditions (often used for referential integrity or value relationships).

  • When statements - to conditionally include or exclude parts of the data model based on other data (conditional presence of nodes).

  • Leafref types - to create references between data nodes (cross-references), ensuring that values correspond to existing nodes elsewhere.

These three types are the primary constraint mechanisms that rely on XPath, as described in RFC 7950.

Each of these plays a different role in data validation. Below are explanations of each type in detail with examples, followed by a demonstration of how they work together in a YANG model.

Note

Constraint Enforcement - YANG constraints (must/when/leafref) are enforced by NETCONF/RESTCONF servers or YANG tooling. If a constraint is violated, the configuration is rejected or an error is raised, ensuring the datastore never enters an invalid state.

Must Statements

A must statement defines an XPath expression that must evaluate to true for the data node (and its sub-tree) to be considered valid. A must statement acts as an assertion or rule that the configuration must satisfy. The must condition can refer to the node's value or other nodes in the data model.

Typical uses of must statements include:

  • Enforcing relationships between values (e.g., one value must be greater than another, or one must be set if another is set).

  • Referential integrity within a model (e.g., if a value references something, some property of that something must have a certain value).

  • Complex validation that cannot be captured by simple data types or innate constraints.

A must-stmt usually refers to descendant nodes (or self), but it can refer to any nodes. If multiple leafs are being checked (e.g., min-size <= max-size), then the must-stmt is often placed in the parent of these leafs.

A must-stmt only applies to nodes that exist. They do not apply to default leafs.

Example of a must statement:

Suppose there are two configuration leaves, 'min-age' and 'max-age'. To ensure that 'min-age' is always less than or equal to 'max-age', a must constraint is applied to their parent container:

container top {
  must "min-age <= max-age";

  leaf min-age {
    type uint16;
    mandatory true;
  }

  leaf max-age {
    type uint16;
    mandatory true;
  }
}

In this example, the must expression "min-age <= max-age" checks that the value of 'min-age' is less than or equal to 'max-age'. If a configuration is submitted where 'min-age' is greater than 'max-age', the must constraint will be violated and the configuration rejected.

A must constraint can also ensure referential integrity. For instance, in a networking scenario, a list of interfaces may be defined, and another leaf may reference an interface name. A must constraint can be applied to ensure that, if a certain feature is enabled, the referenced interface satisfies a required condition. (See the Combined Example below.)

Note

Multiple must statements: More than one must constraint may be applied to a node. All must expressions must evaluate to true for the node to be considered valid.

For the formal definition, see RFC 7950 Section 7.5.3.

When Statements

A when statement in YANG is used to conditionally present a data node or a set of nodes. It attaches a boolean XPath expression to a data definition (such as a leaf, container, list, or case in a choice), and the node is only present when the expression evaluates to true.

Key points about when statements:

  • A when condition does not have to be true; it only determines whether the node can appear. If the condition is false, attempts to configure the node will fail, and the server returns an error.

  • When is often used in augmentations or choice/case statements to introduce configuration that applies in specific contexts.

  • The expression in a when condition may refer to other values in the data tree.

A when-stmt MUST NOT refer to any descendant nodes or to itself. It MUST refer only to nodes outside of the node that contains the when-stmt.

Example of a when statement:

Consider a scenario where an interface has an optional 'vlan-tagging' boolean leaf that should only be present for Ethernet interface types. This can be modeled with a when condition:

leaf type {
  type identityref {
    base interface-type;
  }
}
leaf vlan-tagging {
  type boolean;
  default "false";
  when "derived-from-or-self(../type, 'ethernet')" {
    description "Present only for Ethernet interface types";
  }
}

In this example, the 'vlan-tagging' leaf is present only when the sibling 'type' is equal to or derived from the identity 'ethernet'.

Note

When vs. Must - A when condition controls the presence of a node, meaning it determines whether the node is part of the schema at a given time. A must condition, by contrast, applies to a node that is already present and checks whether a rule about its value (or other values) is satisfied. In short, when is a gating condition, while must is a validation rule.

A when-stmt applies only if its parent is present. A missing node affects the XPath result but is not itself an error.

For the formal definition, see RFC 7950 Section 7.21.5.

Leafref Type (Cross-References)

A leafref is a special YANG type used to create a reference to another leaf (or leaf-list) in the data model. Instead of defining an independent value space, a leafref reuses the value space of another node. This creates a logical link between two parts of the configuration: the leafref's value must match the value of a target leaf that exists in the data tree.

The leafref type is defined using the 'path' sub-statement, which contains an XPath expression identifying the target node in the schema tree. For example, a leafref might refer to the name of an interface in a list, or to a VLAN ID in a defined VLAN list. The value space of the leafref mirrors that of the target leaf, including any type restrictions.

By default, a leafref also requires that an actual instance of the target exists with the referenced value. This is controlled by the 'require-instance' property:

  • If 'require-instance' is "true" (default for configuration data), then the referenced value must exist. The reference must not be dangling.

  • If 'require-instance' is "false", the leafref does not require an actual target node to exist. The value is still constrained by type but may not appear in the current configuration. This mode is sometimes used in state or operational data.

Example of a leafref type:

Suppose a list of users is defined, each with a unique username. A separate leaf may reference a user by name using a leafref:

list user {
  key "username";
  leaf username {
    type string;
  }
  ...  /* other user details */
}

leaf current-operator {
  type leafref {
    path "/user/username";
    require-instance "true";
  }
  description "Username of the current operator (must exist in user list)";
}

In this example, the 'current-operator' leafref points to '/user/username'. Its value must match one of the usernames defined in the user list. With 'require-instance "true"', validation fails if the referenced username does not exist. This ensures referential integrity.

Setting 'require-instance "false"' would allow values not currently present in the user list. However, this looser reference is uncommon in configuration models and mostly applies to dynamic or state data.

Note

Leafref vs. Must for references – A leafref provides both type inheritance and referential integrity. In older models, a string leaf combined with a must statement might be used to validate external references. A leafref simplifies this by combining both checks into one construct.

For the formal definition, see RFC 7950 Section 9.9.

For practical usage with RESTCONF, yangcli-pro, and DB-API, see How to Work with Leafref Data Type.

Combined Example

Below are examples illustrating how "must", "when", and "leafref" constraints work together in a realistic YANG model scenario. The examples use the standard "ietf-interface" YANG module defined in RFC 7223, augmented by the module "ex-vlan.yang" from RFC 7223 Appendix C.

Initially, consider a simple scenario with two interfaces defined ("eth0" and "vlan1"):

ietf-interface.yang basic scenario

The module "ex-vlan.yang" augments this basic interface definition by adding a "vlan-tagging" leaf. This leaf is only present if the interface type is Ethernet ("ethernetCsmacd"):

ex-vlan.yang augment with when for vlan-tagging

This example illustrates the "when" constraint. The "vlan-tagging" leaf is conditionally added based on the interface type. If the condition is not met, the leaf is not included.

Next, the module augments the interface again to conditionally include the "base-interface" leaf if the interface type is "l2vlan":

ex-vlan.yang augment with when for base-interface

Here the "base-interface" leaf only appears when the interface type is "l2vlan".

Finally, a "must" constraint and a "leafref" are combined for the "base-interface" leaf, enforcing that the "base-interface" points to an Ethernet interface with "vlan-tagging" set to true:

ex-vlan.yang augment with leafref and must

In this augmentation:

  • The "base-interface" leaf uses a leafref to reference the "eth0" interface.

  • A "must" statement ensures that the referenced Ethernet interface has "vlan-tagging" enabled. If not, the configuration is rejected.

After applying all these constraints, the complete validated "ietf-interface" YANG module looks like this:

ietf-interface.yang final structure after constraints

The final YANG tree structure after applying all the constraints is:

+--rw interfaces
   |  +--rw interface* [name]
   |     +--rw name                        string
   |     +--rw description?                string
   |     +--rw type                        identityref
   |     +--rw enabled?                    boolean
   |     +--rw link-up-down-trap-enable?   enumeration

Via augments:
   |     +--rw vlan-tagging?               boolean
   |     +--rw base-interface?             leafref
   |     +--rw vlan-id?                    uint16

To see how YumaPro performs processing YANG Constraints compared to Open Source, check out our Transaction Performance page.