Skip to main content

Cisco MDT

Synopsis​

The Cisco MDT device (type: cisco_mdt) takes the model-driven telemetry that Cisco IOS XR, IOS XE and NX-OS routers stream when they dial out: the router connects to Director and sends a telemetry message every time a subscription's interval comes, or when something changes for an event-driven one. Every row of a message is written as a record. Interface counters, CPU, memory, BGP, QoS, optics and the rest of a platform's operational state arrive this way. It is Telegraf's cisco_telemetry_mdt input.

The router pushes, and nothing is polled. Director needs no credentials of the router. For the other direction, where Director subscribes to a router's gNMI server, use the gNMI device.

The device reads three transports:

transportPlatformsEncryption
grpc (default)IOS XR 6.1 and later (64-bit), IOS XE 16.10 and later, NX-OS 7.x and laterTLS, with the routers' own certificates when the device asks for them
tcpIOS XR 6.1 and later (32- and 64-bit)None
udpIOS XR (protocol udp), NX-OS (protocol UDP)None

The encodings the device reads are self-describing GPB (GPB-KV) and IOS XR's JSON (encoding json). The compact GPB encoding needs the model's own .proto file to decode, and a row sent in it is left out with a warning — see Records; so are NX-OS's JSON and XML over UDP.

note

The Cisco MDT device needs Director 2.3.1 or later. With no Director or cluster at that version selected, the wizard shows Cisco MDT devices are unavailable on directors or clusters below version 2.3.1 and the device cannot be created.

Schema​

- id: <numeric>
name: <string>
description: <string>
type: cisco_mdt
tags: <string[]>
pipelines: <pipeline[]>
status: <boolean>
properties:
address: <string>
port: <numeric>
transport: <string>
tls:
status: <boolean>
cert_name: <string>
key_name: <string>
passphrase: <string>
client_ca_name: <string>
client_auth_required: <boolean>
min_tls_version: <string>
max_tls_version: <string>
max_message_size: <numeric>
aliases: <object>
reuse: <boolean>

Configuration​

The following fields are used to define the device:

Device​

FieldRequiredDefaultDescription
idY-Unique numeric identifier
nameY-Device name
descriptionN-Optional description
typeY-Must be cisco_mdt
tagsN-Optional tags
pipelinesN-Optional pre-processor pipelines
statusNtrueEnable/disable the device

Listener​

FieldRequiredDefaultDescription
addressN0.0.0.0The address to listen on
portN57000The port the routers' destination group names, from 1 to 65535: a TCP port, or a UDP port for udp. The device binds it, so no other device on the Director can take it
transportNgrpcHow the routers dial out: grpc, tcp, or udp. See How a Router Dials Out
max_message_sizeN4194304The largest telemetry message taken, in bytes, from 65536 (64 KiB) to 67108864 (64 MiB). The default is 4 MiB. A message NX-OS sends in parts is measured whole. It bounds nothing over udp
aliasesN-An object of table names and the encoding paths they stand for. See Tables

TLS​

TLS goes with the gRPC transport alone. TCP and UDP dial-out are not encrypted, and a device with transport: tcp or udp and tls.status: true is refused.

FieldRequiredDefaultDescription
tls.statusNfalseTake the routers' gRPC dial-out over TLS. Requires tls.cert_name and tls.key_name
tls.cert_nameY*-The certificate the listener presents. A router's destination names its host (tls-hostname on IOS XR) and trusts its CA
tls.key_nameY*-The certificate's private key
tls.passphraseN-Passphrase for an encrypted private key
tls.client_ca_nameN-The CA that signed the routers' own certificates
tls.client_auth_requiredN**falseRequire every router to present a certificate of its own, signed by tls.client_ca_name
tls.min_tls_versionN-Minimum accepted TLS version (tls1.0, tls1.1, tls1.2, tls1.3)
tls.max_tls_versionN-Maximum accepted TLS version

* = Required when tls.status is true.
** = Requires tls.client_ca_name.

note

TLS material fields (cert_name, key_name, ca_name, client_ca_name) accept any of the following:

  • File name — resolved relative to the service root directory. Nested paths such as certs/prod/server.pem are supported.
  • Absolute path — honored only if it resolves inside the service root. Any path that escapes the root is refused.
  • Inline PEM content — used verbatim when the value contains -----BEGIN.
  • Environment variable — ${ENV_VAR}.
  • Vault reference — $secret{id=...} or $secret{store=...,ref=...}.

Advanced Configuration​

FieldRequiredDefaultDescription
reuseNtrueShare the port with a listener that is still closing when the device starts again, so a restart is not refused

A configuration that cannot run stops the device with Configuration error and says why: a transport that is none of grpc, tcp and udp, TLS with the TCP or UDP transport or without its certificate or key, a message size out of its bounds, an address that is not valid, or an alias that names no valid table or no encoding path.

How a Router Dials Out​

A router is configured with three things:

  • a destination group: this Director's address and port, the transport, and encoding self-describing-gpb;
  • a sensor group: the paths;
  • a subscription that ties them together with an interval.

A minimal IOS XR one, over gRPC with TLS:

telemetry model-driven
destination-group VM
address-family ipv4 192.0.2.10 port 57000
encoding self-describing-gpb
protocol grpc tls-hostname mdt.example.com
sensor-group interfaces
sensor-path Cisco-IOS-XR-infra-statsd-oper:infra-statistics/interfaces/interface/latest/generic-counters
subscription interfaces
sensor-group-id interfaces sample-interval 30000
destination-id VM

protocol grpc no-tls dials out without TLS, protocol tcp uses the TCP transport, and protocol udp the UDP one (its packetsize, 1,472 bytes by default, bounds a datagram). encoding json sends IOS XR's JSON.

IOS XE and NX-OS take the same three things in their own syntax. A minimal IOS XE subscription, which dials out over gRPC without TLS (grpc-tcp), so the device it sends to has tls.status off. protocol grpc-tls profile <name> dials out over TLS instead:

telemetry ietf subscription 101
encoding encode-kvgpb
filter xpath /process-cpu-ios-xe-oper:cpu-usage/cpu-utilization
source-address 192.0.2.21
stream yang-push
update-policy periodic 3000
receiver ip address 192.0.2.10 57000 protocol grpc-tcp

A minimal NX-OS one:

feature telemetry
telemetry
destination-group 1
ip address 192.0.2.10 port 57000 protocol gRPC encoding GPB
sensor-group 1
path sys/intf depth unbounded
subscription 1
dst-grp 1
snsr-grp 1 sample-interval 30000

On IOS XE, encode-kvgpb is the self-describing encoding. On NX-OS, encoding GPB is self-describing; GPB-compact is not read. Over UDP, configure NX-OS with encoding GPB.

gRPC​

The router calls MdtDialout of Cisco's gRPCMdtDialout service and keeps the stream open: every message on it is a telemetry message. The listener answers nothing, which is what a router expects.

  • NX-OS sends a large message in parts. The parts are joined, and a message larger than max_message_size is left out with a warning.
  • A message larger than the device takes, sent whole, closes the stream with RESOURCE_EXHAUSTED, and the router dials out again.
  • A router that ends its stream with an error text, such as a subscription removed, has it logged.
  • Keepalives need no setting. The listener takes a ping as often as every five seconds, with or without a call in flight. gRPC's own rule would cut off a client that pings more often than every five minutes, which IOS XE does.
  • A message compressed with gzip, zstd, snappy or lz4 is decompressed.

TCP​

Every message comes behind a twelve-byte header that says what the frame holds, how the message is encoded, and its length.

  • A heartbeat is read and skipped.
  • A message the header says is JSON is read as IOS XR's JSON — see JSON.
  • A compressed frame, which neither Cisco's own collector nor Telegraf reads, closes the connection with a warning. So does a header that claims a message larger than max_message_size.

A problem with what a router sends — a message that cannot be read, a row nested past the limits, compact rows, a datagram that cannot be read — is logged once for as long as its connection lasts, since a router sends the same thing at every interval. Over UDP, which has no connection, it is logged once per router.

UDP​

Every message comes whole in a datagram of its own, behind a header: IOS XR's is the twelve-byte header of the TCP transport, NX-OS's a six-byte header of its own. A datagram is one message, and nothing joins a message sent in parts.

  • IOS XR: a heartbeat is skipped, and JSON is read as over TCP.
  • NX-OS: a message of GPB is read. NX-OS's JSON and XML are left out with a warning that says to configure encoding GPB.
  • A compressed datagram, one shorter than the message its header claims, and one that begins with neither header — NX-OS's secure UDP among them — are left out with a warning, once per router, and the next datagram is read.

JSON​

IOS XR's JSON (encoding json) is one JSON object per message, its rows under data_json, each an object of its timestamp, its keys and its content. A row of it is the same record the same row of GPB-KV makes — see Records. No deletion is read from it.

Records​

A telemetry message says which encoding path its rows are of, which router sent them, the subscription, and the collection's id, start and end. Each row has a time, its keys (the list entry it is, such as an interface's name) and its content (the values). Every row is one ECS record:

{
"@timestamp": "2026-09-21T14:13:20.123Z",
"ecs": { "version": "8.11.0" },
"event": { "module": "cisco_mdt", "dataset": "cisco_mdt.telemetry", "kind": "metric", "category": ["host"], "type": ["info"] },
"observer": { "vendor": "VirtualMetric", "product": "Cisco MDT", "name": "cisco-mdt", "hostname": "director-01" },
"network": { "protocol": "grpc", "transport": "tcp" },
"client": { "ip": "192.0.2.21", "port": 40112 },
"host": { "name": "pe-ams-01" },
"cisco_mdt": {
"telemetry": {
"table": "ifstats",
"path": "Cisco-IOS-XR-infra-statsd-oper:infra-statistics/interfaces/interface/latest/generic-counters",
"subscription": "interfaces",
"collection": { "id": 77, "start": "2026-09-21T14:13:20.1Z", "end": "2026-09-21T14:13:20.3Z" },
"keys": { "interface_name": "HundredGigE0/0/0/0" }
},
"ifstats": { "packets_received": 5, "bytes_received": 5000, "input_errors": 2, "last_data_time": 17 }
}
}
  • The content is under cisco_mdt.<table> — see Tables.
  • What the row is — its table, encoding path, subscription, collection and keys — is under cisco_mdt.telemetry. The keys keep the types the router sent, a number as a number.
  • The router is host.name, by the name it gives itself. Where its connection came from is client.ip and client.port. The listener is the observer.
  • The transport is network.transport: tcp over gRPC and TCP, udp over UDP. network.protocol is grpc over gRPC only.
  • Field names are the model's, with an underscore for every hyphen and dot: packets-received is packets_received. Case is the model's, so NX-OS's operSt stays operSt.
  • The tree is kept. A field that holds fields is an object of them, and fields that share a name, or that have no name, as a router writes the entries of a list, are a list. A field that holds nothing is left out.
  • Values are written as the router types them: text, bytes in base64, a switch, a whole number (signed or not, 64 bits), or a number. A NaN or an infinity, which JSON cannot hold, is left out.
  • Time. A record is dated by its row's time, else its message's, else when it arrived.
  • A deletion. A row the router says was deleted is a deletion event (event.type: deletion, event.action: delete) with its keys, cisco_mdt.telemetry.deleted: true, and no content.
  • Compact GPB rows are counted and left out, with a warning that names the path. The self-describing rows of the same message are written.
  • Limits. A row nests at most 128 levels, and the rows of one message hold at most 1,048,576 fields in all. A row past either is left out with a warning; past the second, so is the rest of its message.

Records are written under definition ID 859, as network log records.

Tables​

A table named in aliases holds the rows of its encoding path:

aliases:
ifstats: "Cisco-IOS-XR-infra-statsd-oper:infra-statistics/interfaces/interface/latest/generic-counters"

An encoding path with no table gets one made of the path, in lower case, with an underscore for every run of characters a field name cannot hold. Cisco-IOS-XR-infra-statsd-oper:infra-statistics/interfaces/interface/latest/generic-counters is cisco_ios_xr_infra_statsd_oper_infra_statistics_interfaces_interface_latest_generic_counters, and show interface is show_interface. A path that would make telemetry makes telemetry_.

A table name in aliases:

  • begins with a letter or an underscore, and holds letters, digits and underscores;
  • is at most 64 characters;
  • is not telemetry, which every record already has.

An encoding path is at most 1024 characters and has one table, and a device names at most 256.

Connection States​

  • Connected: the configuration is read and the port can be bound. Over UDP, Connected says only that the port is bound.
  • Connection error: the port cannot be bound.
  • Configuration error: a configuration that cannot run — see Advanced Configuration.

When the device stops, every router's stream or connection is closed. What is being written of a message at that moment is cut off; the router sends the next one when it dials out again. A message waits for room in the device's buffer, and the router's stream waits with it. Over UDP the router does not wait: datagrams wait in the socket's buffer, and are lost once it is full.

Every node of a cluster runs the device. A router sends to the node its destination group names, or to a load balancer in front of the nodes.

Migrating from Telegraf​

Where the device departs from Telegraf's cisco_telemetry_mdt input:

TelegrafThis device
transport, tcp or grpctransport, grpc, tcp, or udp
Self-describing GPB alone: a message of JSON cannot be readIOS XR's JSON too, over every transport
A metric per row, its fields flattened into /-joined namesA record per row, its content kept as a tree under cisco_mdt.<table>
aliases, a measurement name per encoding pathaliases, a table name per encoding path. Without one, the table is made of the path
embedded_tags, to tell list entries apartNo counterpart: a list is a list in the record
dmes, to convert the types of NX-OS valuesNo counterpart: a record keeps the type the router sent, and the pipeline converts types
include_delete_fieldNo counterpart: a deleted row is always written, as a deletion event
source_field_name, to rename a key called sourceNo counterpart: the router is host.name and the keys are under keys, so nothing clashes
grpc_enforcement_policyNo counterpart: keepalive needs no setting
max_msg_size on gRPC; 1 MiB on TCP unless setmax_message_size on gRPC and TCP, 4 MiB by default
service_address, tls_cert, tls_key, tls_allowed_cacertsaddress and port, and tls

Console​

In the console, go to Fleet Management > Devices and choose Cisco MDT, under Protocols beside gNMI. The wizard's steps after General settings are:

  1. Protocol settings: Listen address (Optional), Port, and Transport — gRPC, TCP, or UDP. For gRPC, TLS settings follow: the TLS encryption switch, and enabled, the certificate and its private key, the passphrase, the routers' own certificates and their CA, and the minimum and maximum TLS version. The step's description names what a router needs: a destination group with this Director's address and port, the transport, and the self-describing-gpb encoding, and a subscription that sends its sensor paths there.
  2. Advanced settings:
    • Tables: a list of Table name and Encoding path rows, with Add table. With none, every encoding path's rows are written under a table made of the path.
    • Maximum message size (Optional), not shown with UDP.
    • Socket address reuse: lets the listener bind its port while the one it replaces is still closing, so a restart is not refused.
    • The Simulation section.

Simulation​

The device can be simulated as the other listeners are — see Device Simulation. The cisco_mdt_telemetry sample generates rows of IOS XR interface counters and memory, and IOS XE CPU utilization, in the shape Records shows.

Examples​

gRPC with Router Certificates​

Taking IOS XR, IOS XE and NX-OS telemetry over gRPC, with TLS and a certificate required of every router, and two tables named...

devices:
- id: 512400500
name: cisco-mdt
description: Interface, memory and CPU telemetry of the core routers
type: cisco_mdt
status: true
properties:
address: "0.0.0.0"
port: 57000
transport: grpc
tls:
status: true
cert_name: "mdt.example.com.crt"
key_name: "mdt.example.com.key"
client_ca_name: "routers-ca.crt"
client_auth_required: true
max_message_size: 4194304
aliases:
ifstats: "Cisco-IOS-XR-infra-statsd-oper:infra-statistics/interfaces/interface/latest/generic-counters"
memory: "Cisco-IOS-XR-nto-misc-oper:memory-summary/nodes/node/summary"

IOS XR over TCP​

Taking the telemetry of IOS XR edge routers over the TCP transport, which has no TLS...

devices:
- id: 512400501
name: cisco-mdt-tcp
description: Telemetry of the IOS XR edge routers, over TCP
type: cisco_mdt
status: true
properties:
address: "0.0.0.0"
port: 57500
transport: tcp

IOS XR and NX-OS over UDP​

Taking the telemetry of IOS XR and NX-OS edge routers over UDP, a datagram per message, which has no TLS...

devices:
- id: 512400502
name: cisco-mdt-udp
description: Telemetry of the IOS XR and NX-OS edge routers, over UDP
type: cisco_mdt
status: true
properties:
address: "0.0.0.0"
port: 57501
transport: udp