1.1 Telemetry vs. SNMP: A Paradigm Shift
SNMP's request-response model creates three deep structural problems that MDT solves by reversing the data flow entirely — devices push data to collectors rather than waiting to be polled.
SNMP Polling (Pull)
- NMS sends GET every 5–10 minutes
- NMS becomes scaling bottleneck
- Short spikes invisible between polls
- Static MIBs — hard to extend
- UDP transport (v1/v2c), BER encoding
MDT (Push)
- Device pushes on schedule or on-change
- Distributed collectors, no bottleneck
- Sub-second granularity achievable
- Dynamic YANG models — extensible
- gRPC / NETCONF, KV-GPB / JSON / XML
flowchart LR
subgraph SNMP ["SNMP Polling Model"]
direction LR
NMS["NMS\n(poller)"]
D1["Device 1"]
D2["Device 2"]
D3["Device N"]
NMS -->|"GET every 5 min"| D1
NMS -->|"GET every 5 min"| D2
NMS -->|"GET every 5 min"| D3
D1 -->|"Response"| NMS
D2 -->|"Response"| NMS
D3 -->|"Response"| NMS
end
subgraph MDT ["Model-Driven Telemetry"]
direction LR
C["Collector\n(Telegraf)"]
R1["Router 1"]
R2["Router 2"]
R3["Router N"]
R1 -->|"Push every 10 s\ngRPC / KV-GPB"| C
R2 -->|"Push every 10 s\ngRPC / KV-GPB"| C
R3 -->|"Push every 10 s\ngRPC / KV-GPB"| C
end
1.2 The Five Components of an MDT Subscription
| Component | Purpose | Example Value |
| Subscription ID | Unique integer; used for management and verification | 101 |
| Stream | Data stream type; IOS XE uses yang-push (RFC 8641) | yang-push |
| XPath Filter | Path into the YANG data tree specifying which data to stream | /process-cpu-ios-xe-oper:cpu-usage/cpu-utilization/five-seconds |
| Update Policy | Periodic (every N centiseconds) or on-change (only when value changes) | periodic 6000 (= 60 sec) |
| Receiver | Destination IP, port, and protocol for dial-out subscriptions | 10.28.35.45 57555 grpc-tcp |
1.3 Encoding Options
KV-GPB is the only encoding permitted with gRPC transport. This is a hard constraint on IOS XE — not a recommendation.
| Encoding | Transport | Format | Efficiency |
| encode-kvgpb | gRPC only | Binary protobuf (Key-Value) | Highest |
| encode-json | RESTCONF / TCP | JSON text | Medium |
| encode-xml | NETCONF / TCP | XML text | Lowest |
2.1 Dial-In vs. Dial-Out
flowchart LR
subgraph DI ["Dial-In (Dynamic)"]
direction LR
COL1["Collector\n(ncclient / gNMI)"]
DEV1["IOS XE\nDevice"]
COL1 -->|"1. Initiates NETCONF session"| DEV1
COL1 -->|"2. establish-subscription RPC"| DEV1
DEV1 -->|"3. Streams data (session-scoped)"| COL1
end
subgraph DO ["Dial-Out (Configured)"]
direction LR
DEV2["IOS XE\nDevice"]
COL2["Collector\n(Telegraf :57000)"]
DEV2 -->|"1. Reads running-config"| DEV2
DEV2 -->|"2. Initiates gRPC connection"| COL2
DEV2 -->|"3. Streams KV-GPB continuously"| COL2
DEV2 -->|"4. Auto-reconnects on drop"| COL2
end
2.2 CLI Dial-Out Configuration
The CLI writes the subscription to running-config. IOS XE 16.10+ and netconf-yang must be enabled (the DMI subsystem requires it).
! Periodic memory stats, gRPC every 60 seconds
telemetry ietf subscription 101
encoding encode-kvgpb
filter xpath /memory-ios-xe-oper:memory-statistics/memory-statistic
stream yang-push
update-policy periodic 6000
source-vrf Mgmt-intf
receiver ip address 10.28.35.45 57555 protocol grpc-tcp
! On-change: only fires when interface oper-status changes
telemetry ietf subscription 102
encoding encode-kvgpb
filter xpath /if:interfaces/interface/oper-status
stream yang-push
update-policy on-change
receiver ip address 10.28.35.45 57555 protocol grpc-tcp
2.3 NETCONF RPC Configuration
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="1">
<edit-config>
<target><running/></target>
<config>
<mdt-config-data xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-mdt-cfg">
<mdt-subscription>
<subscription-id>201</subscription-id>
<base>
<stream>yang-push</stream>
<encoding>encode-kvgpb</encoding>
<period>3000</period> <!-- 30 seconds -->
<xpath>/if:interfaces-state/interface/statistics</xpath>
</base>
<mdt-receivers>
<address>192.168.1.100</address>
<port>57000</port>
<protocol>grpc-tcp</protocol>
</mdt-receivers>
</mdt-subscription>
</mdt-config-data>
</config>
</edit-config>
</rpc>
2.4 Common XPath Reference
| Use Case | XPath Filter | YANG Module |
| 5-sec CPU utilization | /process-cpu-ios-xe-oper:cpu-usage/cpu-utilization/five-seconds | Cisco-IOS-XE-process-cpu-oper |
| Memory statistics | /memory-ios-xe-oper:memory-statistics/memory-statistic | Cisco-IOS-XE-memory-oper |
| Interface counters | /if:interfaces/interface/statistics | ietf-interfaces |
| Interface oper-status | /if:interfaces/interface/oper-status | ietf-interfaces |
| BGP neighbor state | /bgp-ios-xe-oper:bgp-state/neighbors/neighbor | Cisco-IOS-XE-bgp-oper |
| Environmental sensors | /environment-ios-xe-oper:environment-sensors/environment-sensor | Cisco-IOS-XE-environment-oper |
2.5 Verification
show telemetry ietf subscription all
show telemetry ietf subscription 101 detail
show telemetry ietf subscription 101 receiver ! Look for State = Connected
show telemetry internal connection
debug telemetry all ! Caution in production
| Receiver State | Likely Cause |
| Connected | Data is flowing normally |
| Connecting | Receiver not reachable or not listening on configured port |
| Disconnected | Previous connection dropped; device is retrying |
| Not configured | Subscription exists but no receiver has been defined |
3.1 The TIG Stack
Telegraf, InfluxDB, and Grafana form the industry-standard open-source pipeline for MDT collection, storage, and visualization.
flowchart LR
subgraph Devices ["Network Devices"]
direction TB
R1["IOS XE Router"]
SW1["IOS XE Switch"]
end
subgraph TIG ["TIG Stack"]
direction LR
T["Telegraf\ncisco_telemetry_mdt\n:57000 gRPC listener\nDecodes KV-GPB"]
I["InfluxDB\nTime-series DB\nMeasurements / Tags / Fields"]
G["Grafana\nDashboards\nThreshold Alerts"]
T -->|"Line Protocol writes\nHTTP :8086"| I
I -->|"Flux / InfluxQL queries"| G
end
subgraph Notify ["Notification Targets"]
SL["Slack"]
PD["PagerDuty"]
WH["Webhook"]
end
R1 -->|"gRPC dial-out\nKV-GPB :57000"| T
SW1 -->|"gRPC dial-out\nKV-GPB :57000"| T
G -->|"Alert"| SL & PD & WH
3.2 Component Roles
| Component | Role | Key Detail |
| Telegraf | Collection agent / gRPC server | Stateless; decodes KV-GPB via cisco_telemetry_mdt plugin; writes InfluxDB line protocol |
| InfluxDB | Time-series database | Measurements (like tables), tags (indexed metadata), fields (numeric values); supports InfluxQL and Flux |
| Grafana | Visualization and alerting | Connects to InfluxDB as data source; threshold alerts can page PagerDuty, Slack, or downstream webhooks |
3.3 Telegraf Configuration Snippet
[[inputs.cisco_telemetry_mdt]]
transport = "grpc"
service_address = ":57000"
# For TLS: tls_cert / tls_key paths here
[[outputs.influxdb]]
urls = ["http://influxdb:8086"]
database = "mdt_db"
username = "admin"
password = "admin"
Telegraf auto-names InfluxDB measurements from the YANG XPath. Interface statistics from /if:interfaces/interface/statistics become the measurement Cisco-IOS-XE-interfaces-oper:interfaces/interface/statistics. YANG leaf names (in-octets, out-octets) become fields; device hostname becomes a tag.
4.1 What Is a Webhook?
Webhooks are HTTP POST callbacks. A platform sends a structured JSON body to your registered URL the instant a network event occurs — no polling, no wasted API quota, no latency.
Polling Model
- Your app sends GET every 30 seconds
- Fires whether or not anything changed
- Wastes API quota
- Polling lag before detection
Webhook Model
- Platform sends POST when event fires
- Zero resources consumed at rest
- Near real-time notification
- No quota impact between events
4.2 Platform Comparison
| Platform | Key Payload Field | Auth / Validation | Notable Feature |
| Catalyst Center | eventId | Basic / Token auth | Event Simulator for dev/test |
| Meraki | alertType | HMAC-SHA256 signature header | Liquid payload templates; IoT sensor & camera events |
| SD-WAN Manager | eventname | Basic auth (username/password) | Native Slack/Webex routing since 20.15.1 |
4.3 Catalyst Center Webhook Event Flow
sequenceDiagram
participant Net as Network Device
participant CC as Catalyst Center
participant EM as Event Management
participant RX as Webhook Receiver
Net->>CC: Device becomes unreachable
CC->>EM: Internal event bus publishes NETWORK-DEVICES-3-506
EM->>EM: Match subscriptions (eventId / category / severity)
EM->>RX: HTTP POST {eventId, name, severity, details}
RX-->>EM: HTTP 200 OK
RX->>RX: Parse payload, route to automation
Note over RX: Create ticket, trigger Ansible, page engineer
4.4 Meraki Signature Validation
Always validate the X-Cisco-Meraki-Signature header before acting on a Meraki webhook payload:
import hmac, hashlib
def validate_meraki_webhook(secret: str, body: bytes, signature: str) -> bool:
computed = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
return hmac.compare_digest(computed, signature)
4.5 Unified Webhook Receiver Routing Logic
sequenceDiagram
participant CC as Catalyst Center
participant MK as Meraki Dashboard
participant SD as SD-WAN Manager
participant RX as Flask Receiver
participant RT as Payload Router
participant OUT as Automation
CC->>RX: HTTP POST {eventId, name, severity}
MK->>RX: HTTP POST {alertType, deviceName} + Meraki-Signature header
SD->>RX: HTTP POST {eventname, severity, devices}
RX->>RT: Inspect payload keys
Note over RT: alertType → Meraki\neventId → Catalyst Center\neventname → SD-WAN
RT->>OUT: handle_meraki / handle_catalyst_center / handle_sdwan
OUT-->>RX: Action triggered
RX-->>CC: HTTP 200 OK
RX-->>MK: HTTP 200 OK
RX-->>SD: HTTP 200 OK
4.6 MDT vs. Webhooks — Choosing the Right Tool
| Dimension | Model-Driven Telemetry | Webhooks |
| Data type | Continuous metric streams | Discrete state-change events |
| Frequency | Every few seconds (configurable) | On event occurrence only |
| Source | Network devices (IOS XE, XR, NX-OS) | Management platforms (Catalyst Center, Meraki, SD-WAN) |
| Storage need | Time-series DB (InfluxDB) | Event log or ticketing system |
| Best for | Capacity planning, performance trending | Incident response, automation triggers |
| Example | CPU utilization graph over 30 days | "Device unreachable — open ticket" |