GoStruct shadow paths refer to shadow-path annotations currently generated via
the flag -ignore_shadow_schema_paths:
// Interface represents the /openconfig-interfaces/interfaces/interface YANG schema element.
type Interface struct {
Description *string `path:"state/description" module:"openconfig-interfaces/openconfig-interfaces" shadow-path:"config/description" shadow-module:"openconfig-interfaces/openconfig-interfaces"`
Enabled *bool `path:"state/enabled" module:"openconfig-interfaces/openconfig-interfaces" shadow-path:"config/enabled" shadow-module:"openconfig-interfaces/openconfig-interfaces"`
Mtu *uint16 `path:"state/mtu" module:"openconfig-interfaces/openconfig-interfaces" shadow-path:"config/mtu" shadow-module:"openconfig-interfaces/openconfig-interfaces"`
Name *string `path:"state/name|name" module:"openconfig-interfaces/openconfig-interfaces|openconfig-interfaces" shadow-path:"config/name|name" shadow-module:"openconfig-interfaces/openconfig-interfaces|openconfig-interfaces"`
OperStatus E_Interface_OperStatus `path:"state/oper-status" module:"openconfig-interfaces/openconfig-interfaces"`
}The aim of this document is to clarify what shadow paths are and why they exist as a generation option.
https://datatracker.ietf.org/doc/html/draft-openconfig-netmod-opstate-01#section-2
contains a diagram of the relationship between intended config (/config) and
applied config (/state) leaves:
+---------+
| | transition intended
|intended | to applied
| config +---------+
| | |
+---------+ |
^ | config: true
+----------|------------------------------------+
| | config: false
| |
| |
| +-----------------------------+
| | | operational state |
| | +----v----+ +-----------+ |
| | | | | | |
+ | | applied | | derived | | operational:true
same +------>| config | | state |<-------+
leaves | | | | | |
| | | | | |
| +---------+ +-----------+ |
+-----------------------------+
In this diagram, applied config are "config false", or /state leaves that
mirror intended config leaves, which are "config true", or /config leaves. Per
design.md, one of these are compressed
out depending on the value of the -prefer_operational_state generation flag.
Shadow paths are relevant only for compressed GoStructs, and indicate the
compressed-out /config or /state YANG leaf nodes.
Path compression leads to the GoStruct that ygot generates not being able to represent both intended config and applied config at the same time. This leads to two problems:
- When subscribing to a non-leaf path, some gNMI clients want to silently ignore the compressed-out paths rather than erroring out due to an unrecognized path.
- Some use cases (e.g. ygnmi) use the same compressed GoStruct for representing either the "config view" (intended config+derived state) combination, or the "state view" (applied config+derived state) combination of leaves. We want to allow switching between "config views" and "state views" for certain ygot utilities (e.g. marshalling/unmarshalling).
ygot address these issues by,
- Always ignoring paths that match a
shadow-pathtag when doing unmarshalling. For example, if a gNMI update for/interfaces/interface[name="foo"]/config/mtuis unmarshalled into theInterfaceGoStruct at the beginning of this documentation, then the field will not be populated since it is a shadow path. - Supporting a
PreferShadowPathoption for some utilities (see section below).PreferShadowPathmeans that the "shadow" path will be used in preference to the "primary" path annotation.
PreferShadowPath is behavioural option used to describe utilities preferring
the shadow-path tag instead of the path tag in the generated GoStructs when
they both exist on a field, and is therefore used to switch the meaning of the
GoStruct from a "config view" (intended config+derived state) to a "state view"
(applied config+derived state) or vice-versa (depending on the value of the
-prefer_operational_state generation flag).
For example, say we're using the utility ytypes.SetNode to unmarshal a gNMI
update for /interfaces/interface[name="foo"]/config/mtu. Recall that this
update is ignored when unmarshalled into the Interface GoStruct at the
beginning of this documentation. This is because ygot sees that it is a shadow
path (or alternatively, it does not exist in the "state view" of the YANG
subtree corresponding to the GoStruct). However, if the ygot.PreferShadowPath
option is used, then ytypes.SetNode will now populate the field using this
update since it prefers the shadow path (or alternatively, it exists in the
"config view" which ygot.PreferShadowPath indicated).