Using YANG Deviations
YANG deviations change the effective schema of another module in the server.
They describe how a particular implementation differs from the published
module, without editing that module's source file. The compiler applies the
deviation statements when it loads the target module. For example, a
server can declare a container unsupported or replace a leaf's default value.
Clients need these changes to understand the server's actual schema. The server advertises the deviation module so that clients can apply the same changes to their own schema view. See RFC 7950, section 7.20.3, for the YANG deviation rules.
The source module stays unchanged; the compiled schema reflects deviations.
Write a Deviation Module
Use this naming pattern for a separate module:
<organization>-<deviated-module>-dev.yang
For example, Acme's deviations for ietf-interfaces
would be defined in acme-ietf-interfaces-dev.yang.
Apart from the module header, imports, and descriptive metadata, it is
recommended to keep the module limited to deviation statements.
Do not put regular definitions such as containers, leafs,
RPCs, typedefs, or groupings in it, even though this is allowed
by RFC 7950. The --deviation loading mode collects
deviations for later application;
it is not a substitute for loading regular module definitions.
Example: ietf-interfaces module
For this tutorial, use ietf-interfaces.yang, revision
date 2018-02-20.
Remove the deprecated
/interfaces-statecontainerChange the default of the
/interfaces/interface/enabledleaf
Save the following as acme-ietf-interfaces-dev.yang in a working directory:
module acme-ietf-interfaces-dev {
yang-version 1.1;
namespace "urn:acme:params:xml:ns:yang:acme-ietf-interfaces-dev";
prefix acme-if-dev;
import ietf-interfaces {
prefix if;
revision-date 2018-02-20;
}
organization "Acme";
description
"Example deviations for the Acme implementation of ietf-interfaces.";
revision 2026-09-17 {
description "Initial example.";
}
deviation "/if:interfaces-state" {
description "The legacy state container is not implemented.";
deviate not-supported;
}
deviation "/if:interfaces/if:interface/if:enabled" {
description "Interfaces are disabled by default on this platform.";
deviate replace {
default "false";
}
}
}
The import prefix if identifies nodes in ietf-interfaces. Each
deviation uses an absolute schema node path, including a prefix on each
node in these examples. The import's revision-date pins the tutorial to
the revision whose schema was checked.
Make a Data Node Unsupported
The first deviation uses deviate not-supported. The compiler removes
/interfaces-state and its descendants from the effective schema. Clients
must no longer treat that subtree as implemented. This does not remove the
separate /interfaces container or its state data in this module revision.
Change a Default Value
The second deviation uses deviate replace to change the existing
enabled default from true to false. Use replace when the
property already exists; use deviate add to introduce a default when the
node has none, provided the resulting schema permits it.
This changes the schema default used when a value is absent and the YANG
default rules apply. It does not overwrite an explicitly configured
enabled value. The new value must remain valid for the leaf's type.
Two deviations change the same module's effective schema.
Inspect the Compiler Result
Check the effective schema before starting the server. Run the commands below
from the directory containing acme-ietf-interfaces-dev.yang. The target
module and its imports must be on the module search path; use --modpath
if they are not in the installed SDK module directories.
First validate the original module:
yangdump-pro --no-config --module=ietf-interfaces@2018-02-20
Then validate the target with the deviation module and enable compiler tracing with --log-level:
yangdump-pro --no-config \
--deviation=acme-ietf-interfaces-dev \
--module=ietf-interfaces@2018-02-20 --log-level=debug3
The debug output includes these messages (other messages are omitted):
apply_dev: mark target obj ietf-interfaces:interfaces-state for removal
apply_dev: replacing default in target obj ietf-interfaces:enabled
Rechecking ietf-interfaces:enabled after applying deviation(s)
Deviation caused deletion of object ietf-interfaces:interfaces-state
Check that compilation finishes without errors or warnings. These messages
show that the compiler applied the statements to the target and rechecked
the changed leaf. The replacement value is false, as specified in the
deviate replace statement. --no-config prevents a default
yangdump-pro configuration file from adding unrelated compiler options.
Target |
Before |
After |
|---|---|---|
|
Container and descendants |
Not supported; subtree absent |
|
|
|
Make Sure the SIL or SIL-SA Code Does Not Register Unsupported Objects
The SIL or SIL-SA code may need to be modified if any objects are changed to be 'not-supported'.
If the YumaPro libietf-interfaces.so is loaded,
the following error messages will be seen:
Deviation caused deletion of object ietf-interfaces:interfaces-state
...
Invoking load module callback 0
agt_cb: got new module 'ietf-interfaces', rev '2018-02-20'
yang_parse: Finish module 'ietf-interfaces@2018-02-20' OK
Error: sil init function failed for module ietf-interfaces (definition not found)
The deviation causes the interfaces-state container to be deleted from the
schema tree, which results in the 'definition not found' error.
The source code in y_ietf-interfaces.c contains a commented
out #define for the NO_INTERFACES_STATE constant.
If this is defined then no SIL registrations will be done
for the /interfaces-state subtree.
After this is done, the server should load correctly.
Start the Server with the Deviations
Install the deviation module on the server's module search path along with
the target module and its imports. In a development setup, start
netconfd-pro from the directory containing the deviation file:
netconfd-pro --deviation=acme-ietf-interfaces-dev \
--module=ietf-interfaces@2018-02-20 --module=iana-if-type
The --deviation option makes the deviations available before the target
module is compiled. The --module option loads the target module as an
implemented module. Loading a deviations-only module with --module alone
is not a replacement for --deviation. iana-if-type supplies interface
type identities and is also explicitly loaded in this example.
Alternatively, add these entries to the existing netconfd-pro block in
your server configuration file and restart the server:
netconfd-pro {
deviation acme-ietf-interfaces-dev
module ietf-interfaces@2018-02-20
module iana-if-type
}
Use either the command-line entries or the configuration entries for this example. Keep the server's normal instrumentation and other required startup settings. Deviations describe schema differences; they do not implement the remaining interface operations or replace the SIL code.
After startup, inspect the server's YANG library. With the current YANG library
structure, the ietf-interfaces entry under
/yang-library/module-set/module should name acme-ietf-interfaces-dev
in its deviation leaf-list. The deviation module should also be listed.
For details, see Using the YANG Library.
A client uses this information to obtain the original module and its
deviations and reconstruct the effective schema. Do not expect retrieval of
the original YANG source to return a flattened, modified module.
If a client sends a retrieval request for this subtree, then an
empty data container should be returned by the server.
agt_tree: pre-process prune 'interfaces-state' unknown name or namespace
agt_tree: pre_process empty return
agt_tree: process_val empty return
ses_msg: send 1.1 buff:260 for s:3
trace_buff:
#250
<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply message-id="4"
xmlns:ncx="http://netconfcentral.org/ns/yuma-ncx"
ncx:last-modified="2026-09-30T18:47:52Z" ncx:etag="687"
xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<data></data>
</rpc-reply>
The sget command in yangcli-pro should show:
andy@localhost> sget /interfaces-state
RPC Data Reply 3 for session 3 [default]:
rpc-reply {
data {
}
}
Make IF-MIB Objects Writable
The SDK's netconf/modules/mib/IF-MIB.yang is post-processed: the
top-level IF-MIB container has config true, selected controls and
their list key are configuration data, and state nodes have explicit
config false statements. This tutorial instead targets the raw
smidump output, before the SDK's mib-config.py post-processing.
Do not use the checked-in SDK module as the target for this example: several
of its explicit config false statements would conflict with the
deviations below.
The following example shows how to change the effective YANG module so that
selected SNMP read-write objects become YANG configuration data. Generate
IF-MIB.yang with smidump in a separate working directory, and ensure
the compiler or server resolves that raw file as the target module. Do not
run mib-config.py on it. The example retains the generated source and
advertises the changes in a separate acme-IF-MIB-dev.yang module. The
target module name is case-sensitive, so the deviation filename preserves
IF-MIB.
Why the Converter Produces Read-Only Data
The standard SMIv2-to-YANG mapping intentionally makes all data config
false, including SNMP read-write and read-create objects. SNMP
writability alone does not establish NETCONF datastore persistence or edit
semantics. RFC 6643, section 11, describes using deviations for selected
objects whose implementation can provide compatible configuration behavior.
The open-source libsmi smidump tool performs the conversion:
smidump -f yang IF-MIB > IF-MIB.yang
Run this in a separate working directory with the SMIv2 IF-MIB and its imports
on the libsmi MIB search path. Retain the generated file as the base module.
SMIv2 metadata such as smiv2:max-access preserves the original SNMP
access information; it does not generate config true.
See also Creating MIB Instrumentation.
The upstream smidump YANG converter has no option to map SNMP read-write
objects automatically to config true. Its conversion implementation
sets config false on the generated top-level container. An
application-specific generator could produce a deviation module,
but it still needs a reviewed selection of writable objects, key handling,
and persistence rules. Open-source yanglint, supplied by libyang, can validate and display the resulting
schema as shown below; it does not infer those implementation decisions.
Change Ancestors and Preserve State Data
In the raw smidump output, IF-MIB is explicitly config false and
its descendants inherit that setting. Setting config true only on
ifAdminStatus is invalid while its ancestor is state data. Conversely,
changing only the top-level container to config true would make counters
and other state objects inherit configuration status too.
For this example, expose four controls under IF-MIB/ifTable/ifEntry:
ifAdminStatus, ifLinkUpDownTrapEnable, ifPromiscuousMode, and
ifAlias.
Download the complete
acme-IF-MIB-dev.yangexample.
It makes these coordinated changes:
Replace the root's explicit
config falsewithconfig true.ifTable,ifEntry, itsifIndexkey, and the selected controls inheritconfig true.Add
config falseto the completeinterfaces,ifMIBObjects,ifStackTable, andifRcvAddressTablesubtrees.Add
config falseto every remaining non-key leaf inifEntry, including leafs contributed by theifXEntryandifTestEntryaugments. This preserves counters, operational status, and all other unselected objects as state data.
These excerpts illustrate the changes; use the complete download so that no unselected state leaf accidentally becomes configuration:
deviation "/if-mib:IF-MIB" {
deviate replace {
config true;
}
}
deviation "/if-mib:IF-MIB/if-mib:interfaces" {
deviate add { config false; }
}
deviation "/if-mib:IF-MIB/if-mib:ifTable/if-mib:ifEntry"
+ "/if-mib:ifOperStatus" {
deviate add { config false; }
}
Use replace for the root's existing statement and add where the
original node has no explicit config statement. No extra statement is
needed on the four controls because they inherit true. The effect is
equivalent to changing the root's source statement and adding the state
statements at the selected boundaries, while leaving the generated file
unchanged.
The list key requires special care: ifIndex is SNMP read-only but must
have the same YANG config value as ifEntry. Keeping it config
false would make this configuration list invalid. Its role as a
configuration key identifies the row; it does not mean an existing
interface index can be renamed. Instrumentation must enforce which
interface rows can be created or deleted and how keys map to real devices.
This example deliberately leaves the stack and receive-address tables and
the deprecated test controls read-only, including their SNMP-writable
objects. Promoting RowStatus or action-like test controls requires
additional decisions about row lifecycle and edit semantics. Do not promote
every read-write or read-create object without reviewing those rules.
Validate and Inspect the Changed Module
Put the downloaded deviation file, the raw IF-MIB.yang generated by
smidump, and its YANG imports on the module search path. Ensure that the
SDK's post-processed IF-MIB.yang does not shadow the raw file. From that
working directory, validate with the server's compiler:
yangdump-pro --no-config --deviation=acme-IF-MIB-dev \
--module=IF-MIB --log-level=debug3
To see the effective read/write classification with the open-source
yanglint tool, compare these two commands. Replace yang-modules with
the directory containing the imported YANG modules; add more -p options
if needed:
yanglint -p yang-modules -f tree IF-MIB.yang
yanglint -p yang-modules -f tree IF-MIB.yang acme-IF-MIB-dev.yang
In the original tree, all IF-MIB data nodes are ro. After loading the
deviations, the following selected nodes have these classifications
(other nodes omitted):
module: IF-MIB
+--rw IF-MIB
+--ro interfaces
| +--ro ifNumber
+--rw ifTable
+--rw ifEntry* [ifIndex]
+--rw ifIndex
+--rw ifAdminStatus
+--ro ifOperStatus
+--ro ifInOctets
+--rw ifLinkUpDownTrapEnable
+--rw ifPromiscuousMode
+--rw ifAlias
Here rw means YANG configuration data and ro means state data;
these markers are not a report of SNMP MAX-ACCESS permissions.
Start a server that has instrumentation for the changed schema with:
netconfd-pro --deviation=acme-IF-MIB-dev --module=IF-MIB
Load this as a deviation, not an annotation: clients must learn which nodes are now configuration. Generate or adapt the SIL code using the same deviations, and implement edit validation, application, rollback, and persistence. Changing the schema alone does not add write callbacks to the supplied IF-MIB example SIL or enable SNMP SET support. Check the yp-snmp Features for the supported SNMP operations.
Choose Deviations or Annotations
YumaPro also supports server-side annotation modules loaded with
--annotation. They use deviation syntax to attach extensions to another
module, but are not advertised to clients or shown in the YANG library.
Here, an annotation module means this server startup mechanism, not an
RFC 7952 md:annotation definition for protocol metadata.
Choose the mechanism according to who needs the information:
Use an annotation to add an extension that only server instrumentation needs, such as a callback-ordering hint. The client does not need that implementation detail.
Use a deviation for any schema change that clients must see, including unsupported nodes, changed defaults, types, or constraints. Hiding such changes leaves clients with an incorrect schema.
Use a deviation for extension usage from which a client might benefit. Check that the extension permits the intended deviation and that the client can obtain the module defining the extension.
For an annotation example using deviate add with a server-only extension,
see --annotation. Do not load this tutorial's module as an annotation:
both of its changes need to be visible to clients.
Usage Guidelines
Deviations need to be used carefully, and the SIL or SIL-SA callback code needs to be aligned with any deviations used.
Note
Some deviations are quite dangerous if done incorrectly.
Changing the type of a data node (e.g. string to uint32) will cause a callback to crash if the SIL or SIL-SA code is not updated to expect the new data type.
Keep deviations in a dedicated module named for the organization and the module being deviated. Retain the original target module unchanged, and distribute the deviation module to clients that need it.
Keep only deviation statements as the module's functional content. Use imports for target prefixes and extension definitions, and descriptions to explain each implementation difference.
Validate against the exact target revision and the complete set of modules, features, and deviations used in the deployment. Removing a subtree can invalidate references to it from other modules.
Keep the resulting schema valid and avoid deviations that conflict or depend on application order. Recheck compiler validation after changing any deviation or upgrading the target module.
Align instrumentation and existing configuration with the effective schema. A changed default affects clients that previously relied on the original default, even if they never explicitly configured that leaf.
SIL bundles can include deviations when their code is generated and built.
The make_sil_bundle and make_sil_sa_bundle helpers accept --deviation options, and generated initialization code loads those deviations before loading the target modules.
Check the bundle's build options before adding deviations in the server configuration.
Repeating or conflicting with bundled deviations can cause compilation failures or make the effective schema inconsistent with the generated instrumentation.
Keep bundle generation and server configuration coordinated, and validate the combined deviation set rather than assuming the configuration overrides the bundle.
Hard-wired deviations should not be mixed with deviations from the command line or config file.