openconfig/ygnmi: Compiling the Network

How type-safe path generation replaces fragile string queries with compiler-enforced network state.

8 min read · openconfig/ygnmi

A large server rack where cables are rigid steel I-beams, representing type-safe structural guarantees.
Replacing flexible, error-prone string connections with rigid, structural compile-time guarantees.
Key Takeaways

The Fragility of String-Based Telemetry

Network automation has a stringly-typed problem. Engineers query routers and switches using fragile, manually constructed XPaths. A single typo in a path string causes a runtime panic during a production deployment.

The gNMI (gRPC Network Management Interface) protocol is powerful. It allows operators to stream telemetry and configure devices at scale. However, interacting with it usually means writing long, error-prone path strings and manually unmarshaling Protobuf responses using reflection.

// The old, fragile way (raw strings)
path := "/interfaces/interface[name=eth0]/state/counters/in-octets"
// Fails at runtime if the path is misspelled or the device schema changes.

// The ygnmi way (fluent, compiled API)
query := ocpath.Root().Interface("eth0").State().Counters().InOctets().State()
// Fails at compile time if the path is invalid.

Code Generation as an API

The openconfig/ygnmi library solves this by turning network schemas into statically typed, compiled Go code. It acts as a metaprogramming layer for network infrastructure. The goal is moving the failure domain from runtime to compile time.

The architecture splits into two distinct phases. First, a CLI generator consumes YANG modules using the ygot toolkit. This produces standard Go structs and a custom Path Library. Second, the runtime client uses these generated paths to execute subscriptions and set operations.

A horizontal flow diagram showing the metaprogramming pipeline of ygnmi. It starts on the left with a document icon labeled "YANG Schema". An arrow points to a gear icon labeled "ygot Parser". This flows into a factory icon labeled "ygnmi Generator". The output splits into two distinct code blocks: one labeled "PathStruct API" and the other "Go Compiler Shield". A user interaction shows a raw string path ("/interfaces/interface[name=eth0]") entering the factory and emerging as a chained Go method ("oc.Interface('eth0').State()"). Hovering over the Go method reveals the underlying Protobuf output.

Anatomy of a Type-Safe Query

The magic happens inside ygnmi/types.go. This file defines the core structural types that represent queries. It bridges raw YANG schema paths and concrete Go types.

By leveraging Go generics, the library ensures that a query for a Maximum Transmission Unit (MTU) returns a uint16. A query for a description returns a string. There is no need for type assertions or interface casting.

The ExtractFn[T] closure solves the deep-nesting problem inherent to YANG models. In OpenConfig, a leaf is often nested inside several containers. The extraction function knows exactly how to traverse the resulting GoStruct to find the specific field.

A heavy steel vault door with a perfectly machined puzzle piece slot, representing exact type matching at compile time.
ExtractFn[T] and Go generics ensure exact type matching before the code ever runs.

Shadow Paths and the Compliance Gap

Network operators know that intended configuration rarely matches applied state perfectly. A device might be configured for a specific MTU, but the operational state could reflect a negotiation fallback.

The generator handles this reality through shadow paths. By enforcing a prefer_operational_state flag during generation, the API automatically pivots between config leaves and state leaves. Telemetry queries default to the actual operational state of the device.

"The library supports querying telemetry and unmarshaling it into generated structs and setting config. Only gnmi.Subscribe and gnmi.Set RPC are supported by this library."

Source: openconfig/ygnmi README, Project Documentation

Unlike clients that simply fail on unmarshaling errors, this library categorizes noncompliance. It separates errors into Path, Type, and Value noncompliance. This allows users to inspect exactly why a device response diverges from the YANG model.

The Tooling Divide

The gNMI ecosystem is diverse. Choosing the right tool depends entirely on the persona and the deployment context.

While tools like gNMIc dominate the CLI and telemetry collection space, ygnmi is the developer choice for building robust Go applications. It eliminates the string-path fragility that plagues automation scripts. It operates less like a general-purpose collector and more like a specialized scalpel for engineers building complex controllers.

Tool Language Typing Primary Persona
ygnmi Go (Library) Static (Generated) Developer / SDET
gNMIc Go (CLI/Collector) Dynamic Operator / SRE
pygnmi Python (Library) Dynamic Scripter / Automation

Sources: