[Phase 1] Explore available YANG models (OpenConfig vs Native Arista) #2

Closed
opened 2025-12-20 15:39:48 +00:00 by Damien · 5 comments
Owner

Description

Explore and document available YANG models on Arista EOS 4.35.0F, understanding the distinction between OpenConfig and native Arista models.

Tasks

  • Use gNMI Capabilities to list supported models
  • Clone Arista YANG repo: https://github.com/aristanetworks/yang/tree/master/EOS-4.35.0F
  • Identify which models are OpenConfig vs Arista-native
  • Map which model covers each feature (VLAN, BGP, VXLAN, MLAG, etc.)
  • Note any gaps where OpenConfig doesn't cover EVPN-VXLAN features

Key Questions to Answer

  1. Does OpenConfig fully support EVPN configuration?
  2. Which paths are needed for VXLAN VNI mappings?
  3. How is MLAG represented in YANG?
  4. What's the path structure for BGP EVPN address-family?

Expected Findings

  • OpenConfig covers: interfaces, VLANs, basic BGP
  • Arista-native needed for: EVPN, VXLAN, MLAG specifics

Resources

## Description Explore and document available YANG models on Arista EOS 4.35.0F, understanding the distinction between OpenConfig and native Arista models. ## Tasks - [x] Use gNMI Capabilities to list supported models - [x] Clone Arista YANG repo: https://github.com/aristanetworks/yang/tree/master/EOS-4.35.0F - [x] Identify which models are OpenConfig vs Arista-native - [x] Map which model covers each feature (VLAN, BGP, VXLAN, MLAG, etc.) - [x] Note any gaps where OpenConfig doesn't cover EVPN-VXLAN features ## Key Questions to Answer 1. Does OpenConfig fully support EVPN configuration? 2. Which paths are needed for VXLAN VNI mappings? 3. How is MLAG represented in YANG? 4. What's the path structure for BGP EVPN address-family? ## Expected Findings - OpenConfig covers: interfaces, VLANs, basic BGP - Arista-native needed for: EVPN, VXLAN, MLAG specifics ## Resources - https://github.com/aristanetworks/yang/tree/master/EOS-4.35.0F - https://github.com/openconfig/public
Damien added the phase-1-yang-discoveryresearch labels 2025-12-20 15:39:52 +00:00
Author
Owner

🔬 Key Discovery: Path Prefix Matters for ON_CHANGE Subscriptions

During testing, we discovered an important difference in gNMI Subscribe behavior on cEOS:

OpenConfig prefixed paths - ON_CHANGE doesn't work

gnmic subscribe \
  --path "/openconfig-interfaces:interfaces/interface/state/oper-status" \
  --mode stream --stream-mode on-change
  • Receives initial sync only
  • No updates when interface state changes

Native paths (without module prefix) - ON_CHANGE works!

gnmic subscribe \
  --path "/interfaces/interface[name=Port-Channel1]/state/oper-status" \
  --path "/interfaces/interface[name=Port-Channel1]/state/admin-status" \
  --mode stream --stream-mode on-change
  • Receives initial sync ✓
  • Receives real-time updates when state changes ✓

Test Results

Subscription active, then shutdown / no shutdown on Port-Channel1:

// Initial sync shows DOWN (after shutdown)
{"Path": "interfaces/interface[name=Port-Channel1]/state/admin-status", "values": {"admin-status": "DOWN"}}
{"Path": "interfaces/interface[name=Port-Channel1]/state/oper-status", "values": {"oper-status": "DOWN"}}
{"sync-response": true}

// Real-time update when "no shutdown" executed
{"Path": "interfaces/interface[name=Port-Channel1]/state/admin-status", "values": {"admin-status": "UP"}}
{"Path": "interfaces/interface[name=Port-Channel1]/state/oper-status", "values": {"oper-status": "LOWER_LAYER_DOWN"}}

// Then when LAG members come up
{"Path": "interfaces/interface[name=Port-Channel1]/state/oper-status", "values": {"oper-status": "UP"}}

Implications for the Orchestrator

Use Case Path Style Mode
Drift detection (real-time) Native: /interfaces/... ON_CHANGE
Config retrieval Either works GET
Metrics/counters Either works SAMPLE

SAMPLE Mode - Always Works (Fallback)

Both path styles work with SAMPLE mode:

gnmic subscribe \
  --path "/openconfig-interfaces:interfaces/interface[name=Port-Channel1]/state/oper-status" \
  --mode stream --stream-mode sample --sample-interval 5s

This can be used as a fallback for paths where ON_CHANGE isn't supported.

## 🔬 Key Discovery: Path Prefix Matters for ON_CHANGE Subscriptions During testing, we discovered an important difference in gNMI Subscribe behavior on cEOS: ### ❌ OpenConfig prefixed paths - ON_CHANGE doesn't work ```bash gnmic subscribe \ --path "/openconfig-interfaces:interfaces/interface/state/oper-status" \ --mode stream --stream-mode on-change ``` - Receives initial sync only - No updates when interface state changes ### ✅ Native paths (without module prefix) - ON_CHANGE works! ```bash gnmic subscribe \ --path "/interfaces/interface[name=Port-Channel1]/state/oper-status" \ --path "/interfaces/interface[name=Port-Channel1]/state/admin-status" \ --mode stream --stream-mode on-change ``` - Receives initial sync ✓ - Receives real-time updates when state changes ✓ ### Test Results Subscription active, then `shutdown` / `no shutdown` on Port-Channel1: ```json // Initial sync shows DOWN (after shutdown) {"Path": "interfaces/interface[name=Port-Channel1]/state/admin-status", "values": {"admin-status": "DOWN"}} {"Path": "interfaces/interface[name=Port-Channel1]/state/oper-status", "values": {"oper-status": "DOWN"}} {"sync-response": true} // Real-time update when "no shutdown" executed {"Path": "interfaces/interface[name=Port-Channel1]/state/admin-status", "values": {"admin-status": "UP"}} {"Path": "interfaces/interface[name=Port-Channel1]/state/oper-status", "values": {"oper-status": "LOWER_LAYER_DOWN"}} // Then when LAG members come up {"Path": "interfaces/interface[name=Port-Channel1]/state/oper-status", "values": {"oper-status": "UP"}} ``` ### Implications for the Orchestrator | Use Case | Path Style | Mode | |----------|-----------|------| | Drift detection (real-time) | Native: `/interfaces/...` | ON_CHANGE | | Config retrieval | Either works | GET | | Metrics/counters | Either works | SAMPLE | ### SAMPLE Mode - Always Works (Fallback) Both path styles work with SAMPLE mode: ```bash gnmic subscribe \ --path "/openconfig-interfaces:interfaces/interface[name=Port-Channel1]/state/oper-status" \ --mode stream --stream-mode sample --sample-interval 5s ``` This can be used as a fallback for paths where ON_CHANGE isn't supported.
Author
Owner

📍 Discovered YANG Paths: Interfaces & BGP

Interfaces

Model: openconfig-interfaces (v3.8.0)

Operation Path
All interfaces state /interfaces/interface/state
Specific interface /interfaces/interface[name=Ethernet1]/state
Oper/Admin status /interfaces/interface[name=X]/state/oper-status

Subscribe ON_CHANGE: Works (verified state transitions: UP → DOWN → LOWER_LAYER_DOWN → UP)


BGP

Model: openconfig-bgp (v9.9.1) + arista-bgp-augments

Operation Path
Global state (AS, router-id) /network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/global/state
All neighbors .../bgp/neighbors/neighbor/state
Specific neighbor .../bgp/neighbors/neighbor[neighbor-address=10.0.1.2]/state
Session state only .../neighbor[neighbor-address=X]/state/session-state

Subscribe ON_CHANGE: Works (verified: ESTABLISHED → IDLE → ACTIVE → OPENSENT → ESTABLISHED)

Key fields: session-state, peer-as, peer-group, peer-type, neighbor-router-id, messages/received, messages/sent

## 📍 Discovered YANG Paths: Interfaces & BGP ### Interfaces **Model**: `openconfig-interfaces` (v3.8.0) | Operation | Path | |-----------|------| | All interfaces state | `/interfaces/interface/state` | | Specific interface | `/interfaces/interface[name=Ethernet1]/state` | | Oper/Admin status | `/interfaces/interface[name=X]/state/oper-status` | **Subscribe ON_CHANGE**: ✅ Works (verified state transitions: UP → DOWN → LOWER_LAYER_DOWN → UP) --- ### BGP **Model**: `openconfig-bgp` (v9.9.1) + `arista-bgp-augments` | Operation | Path | |-----------|------| | Global state (AS, router-id) | `/network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/global/state` | | All neighbors | `.../bgp/neighbors/neighbor/state` | | Specific neighbor | `.../bgp/neighbors/neighbor[neighbor-address=10.0.1.2]/state` | | Session state only | `.../neighbor[neighbor-address=X]/state/session-state` | **Subscribe ON_CHANGE**: ✅ Works (verified: ESTABLISHED → IDLE → ACTIVE → OPENSENT → ESTABLISHED) **Key fields**: `session-state`, `peer-as`, `peer-group`, `peer-type`, `neighbor-router-id`, `messages/received`, `messages/sent`
Author
Owner

📍 Discovered YANG Paths: VXLAN

Model: arista-exp-eos-vxlan (augments openconfig-interfaces)

Note: Arista EOS only allows one Vxlan1 interface - all VNI mappings are configured under it.

Operation Path
Full VXLAN config/state /interfaces/interface[name=Vxlan1]/arista-vxlan
VTEP settings /interfaces/interface[name=Vxlan1]/arista-vxlan/state
L2 VNI mappings (VLAN→VNI) /interfaces/interface[name=Vxlan1]/arista-vxlan/vlan-to-vnis
L3 VNI mappings (VRF→VNI) /interfaces/interface[name=Vxlan1]/arista-vxlan/vrf-to-vnis

Key fields returned:

{
  "config": {
    "src-ip-intf": "Loopback1",
    "udp-port": 4789,
    "mac-learn-mode": "LEARN_FROM_ANY"
  },
  "vlan-to-vnis": {
    "vlan-to-vni": [
      { "vlan": 40, "vni": 110040 }
    ]
  }
}
## 📍 Discovered YANG Paths: VXLAN **Model**: `arista-exp-eos-vxlan` (augments `openconfig-interfaces`) **Note**: Arista EOS only allows one `Vxlan1` interface - all VNI mappings are configured under it. | Operation | Path | |-----------|------| | Full VXLAN config/state | `/interfaces/interface[name=Vxlan1]/arista-vxlan` | | VTEP settings | `/interfaces/interface[name=Vxlan1]/arista-vxlan/state` | | L2 VNI mappings (VLAN→VNI) | `/interfaces/interface[name=Vxlan1]/arista-vxlan/vlan-to-vnis` | | L3 VNI mappings (VRF→VNI) | `/interfaces/interface[name=Vxlan1]/arista-vxlan/vrf-to-vnis` | **Key fields returned**: ```json { "config": { "src-ip-intf": "Loopback1", "udp-port": 4789, "mac-learn-mode": "LEARN_FROM_ANY" }, "vlan-to-vnis": { "vlan-to-vni": [ { "vlan": 40, "vni": 110040 } ] } } ```
Author
Owner

📍 Discovered YANG Paths: MLAG & EVPN

MLAG

Model: arista-exp-eos-mlag (experimental)

Operation Path
Full MLAG config /arista/eos/mlag
Config only /arista/eos/mlag/config

Key fields: domain-id, local-intf, peer-address, peer-link-intf, dual-primary-action, heartbeat-peer-address

⚠️ Limitation: Operational state (peer status, role, negotiation status) is NOT exposed via gNMI. Query with --type state returns empty. Use eAPI/CLI (show mlag) for state.


EVPN

Model: arista-exp-eos-evpn (experimental)

Operation Path
All EVPN instances /arista/eos/evpn
EVPN instances list /arista/eos/evpn/evpn-instances

Key fields: name, route-distinguisher, redistribute, route-target/import, route-target/export, vlans

⚠️ Limitation: Operational state (learned routes, MACs) is NOT exposed via gNMI. Query with --type state returns empty. Use eAPI/CLI (show bgp evpn) for state.


Validation Method

# Config returns data
gnmic get --path "/arista/eos/mlag" --type config  # ✅ Returns config
gnmic get --path "/arista/eos/evpn" --type config  # ✅ Returns config

# State returns empty
gnmic get --path "/arista/eos/mlag" --type state   # ❌ Returns {}
gnmic get --path "/arista/eos/evpn" --type state   # ❌ Returns {}
## 📍 Discovered YANG Paths: MLAG & EVPN ### MLAG **Model**: `arista-exp-eos-mlag` (experimental) | Operation | Path | |-----------|------| | Full MLAG config | `/arista/eos/mlag` | | Config only | `/arista/eos/mlag/config` | **Key fields**: `domain-id`, `local-intf`, `peer-address`, `peer-link-intf`, `dual-primary-action`, `heartbeat-peer-address` ⚠️ **Limitation**: Operational state (peer status, role, negotiation status) is **NOT exposed via gNMI**. Query with `--type state` returns empty. Use eAPI/CLI (`show mlag`) for state. --- ### EVPN **Model**: `arista-exp-eos-evpn` (experimental) | Operation | Path | |-----------|------| | All EVPN instances | `/arista/eos/evpn` | | EVPN instances list | `/arista/eos/evpn/evpn-instances` | **Key fields**: `name`, `route-distinguisher`, `redistribute`, `route-target/import`, `route-target/export`, `vlans` ⚠️ **Limitation**: Operational state (learned routes, MACs) is **NOT exposed via gNMI**. Query with `--type state` returns empty. Use eAPI/CLI (`show bgp evpn`) for state. --- ### Validation Method ```bash # Config returns data gnmic get --path "/arista/eos/mlag" --type config # ✅ Returns config gnmic get --path "/arista/eos/evpn" --type config # ✅ Returns config # State returns empty gnmic get --path "/arista/eos/mlag" --type state # ❌ Returns {} gnmic get --path "/arista/eos/evpn" --type state # ❌ Returns {} ```
Author
Owner

VXLAN Subscribe ON_CHANGE Verified

gnmic subscribe \
  --path "/interfaces/interface[name=Vxlan1]/arista-vxlan/vlan-to-vnis" \
  --mode stream --stream-mode on-change

Tested: Add/remove VNI mapping → Real-time updates received including delete notifications.


📊 Final Summary

Feature Model Config State Subscribe ON_CHANGE
Interfaces openconfig-interfaces
BGP openconfig-bgp
VXLAN arista-exp-eos-vxlan
MLAG arista-exp-eos-mlag N/A
EVPN arista-exp-eos-evpn N/A

Key Findings

  1. Path prefix matters: Use native paths (without openconfig-*: prefix) for ON_CHANGE subscriptions
  2. MLAG/EVPN limitation: Experimental models expose config only, use eAPI for operational state
  3. VXLAN: Single Vxlan1 interface contains all VNI mappings (L2 and L3)
## ✅ VXLAN Subscribe ON_CHANGE Verified ```bash gnmic subscribe \ --path "/interfaces/interface[name=Vxlan1]/arista-vxlan/vlan-to-vnis" \ --mode stream --stream-mode on-change ``` **Tested**: Add/remove VNI mapping → Real-time updates received including delete notifications. --- ## 📊 Final Summary | Feature | Model | Config | State | Subscribe ON_CHANGE | |---------|-------|--------|-------|---------------------| | **Interfaces** | `openconfig-interfaces` | ✅ | ✅ | ✅ | | **BGP** | `openconfig-bgp` | ✅ | ✅ | ✅ | | **VXLAN** | `arista-exp-eos-vxlan` | ✅ | ✅ | ✅ | | **MLAG** | `arista-exp-eos-mlag` | ✅ | ❌ | N/A | | **EVPN** | `arista-exp-eos-evpn` | ✅ | ❌ | N/A | ### Key Findings 1. **Path prefix matters**: Use native paths (without `openconfig-*:` prefix) for ON_CHANGE subscriptions 2. **MLAG/EVPN limitation**: Experimental models expose config only, use eAPI for operational state 3. **VXLAN**: Single `Vxlan1` interface contains all VNI mappings (L2 and L3)
Sign in to join this conversation.