The core components used in streaming policy-based telemetry data are:
A telemetry policy file is defined by the user to specify the kind of telemetry data that is generated and pushed to the receiver. The policy must be stored in a text file with a .policy extension. Multiple policy files can be defined and installed in the /telemetry/policies/ folder in the router file system.
Contains one or more collection groups; a collection group includes different types of data to be streamed at different intervals
Includes a period in seconds for each group
Contains one or more paths for each group
Includes metadata that contains version, description, and other details about the policy
Policy file syntax
{ "Name": "NameOfPolicy", "Metadata": { "Version": 25, "Description": "This is a sample policy to demonstrate the syntax", "Comment": "This is the first draft", "Identifier": "<data that may be sent by the encoder to the mgmt stn" }, "CollectionGroups": { "FirstGroup": { "Period": 10, "Paths": [ "RootOper.MemorySummary.Node", "RootOper.RIB.VRF", "..." ] }, "SecondGroup": { "Period": 300, "Paths": [ "RootOper.Interfaces.Interface" ] } } }
Name the name of the policy. In the previous example, the policy is stored in a file named NameOfPolicy.policy. The name of the policy must match the filename (without the .policy extension). It can contain uppercase alphabets, lower-case alphabets, and numbers. The policy name is case sensitive.
CollectionGroups an encoder object that maps the group names to information about them. The name of the collection group can contain uppercase alphabets, lowercase alphabets, and numbers. The group name is case sensitive.
Period the cadence for each collection group. The period specifies the frequency in seconds at which data is queried and sent to the receiver. The value must be within the range of 5 and 86400 seconds.
Paths one or more schema paths, allowed list entries or native YANG paths (for a container) for the data to be streamed and sent to the receiver. For example,
RootOper.InfraStatistics.Interface(*).Latest.GenericCounters
/Cisco-IOS-XR-infra-statsd-oper:infra-statistics/interfaces/interface=*/latest/generic-counters
"RootOper.Interfaces.Interface(*)": { "IncludeFields": ["State"] }
A schema path is used to specify where the telemetry data is collected. A few paths are listed in the following table for your reference:
Operation |
Path |
---|---|
Interface Operational data |
RootOper.Interfaces.Interface(*) |
Packet/byte counters |
RootOper.InfraStatistics.Interface(*).Latest.GenericCounters |
Packet/byte rates |
RootOper.InfraStatistics.Interface(*).Latest.DataRate |
IPv4 packet/byte counters |
RootOper.InfraStatistics.Interface(*).Latest.Protocol(['IPV4_UNICAST']) |
MPLS stats |
|
QOS Stats |
|
BGP Data |
RootOper.BGP.Instance({'InstanceName': 'default'}).InstanceActive.DefaultVRF.Neighbor([*]) |
Inventory data |
RootOper.PlatformInventory.Rack(*).Attributes.BasicInfo RootOper.PlatformInventory.Rack(*).Slot(*).Card(*).Sensor(*).Attributes.BasicInfo |
The telemetry encoder encapsulates the generated data into the desired format and transmits to the receiver.
JavaScript Object Notation (JSON) encoder
This encoder is packaged with the IOS XR software and provides the default method of streaming telemetry data. It can be configured by CLI and XML to register for specific policies. Configuration is grouped into policy groups, with each policy group containing one or more policies and one or more destinations. JSON encoding is supported over only TCP transport service.
Google Protocol Buffers (GPB) encoder
This encoder provides an alternative encoding mechanism, streaming the data in GPB format over UDP or TCP. It can be configured by CLI and XML and uses the same policy files as those of JSON. Additionally, a GPB encoder requires metadata in the form of compiled .proto files to translate the data into GPB format.
Compact encoding stores data in a compact GPB structure that is specific to the policy that is streamed. This format is available over both UDP and TCP transport services. A .proto file must be generated for each path in the policy file to be used by the receiver to decode the resulting data.
Key-value encoding stores data in a generic key-value format using a single .proto file. The encoding is self-describing as the keys are contained in the message. This format is available over TCP transport service. A .proto file is not required for each policy file because the receiver can interpret the data.
Streaming data over a TCP connection either with a JSON or a GPB encoder and having it optionally compressed by zlib ensures that the stream is flushed at the end of each batch of data. This helps the receiver to decompress the data received. If data is compressed using zlib, the compression is done at the policy group level. The compressor resets when a new connection is established from the receiver because the decompressor at the receiver has an empty initial state.
Type |
Flags |
Length |
Message |
---|---|---|---|
4 bytes |
4 bytes |
4 bytes |
Variable |
Type of messages:
Type |
Name |
Length |
Value |
---|---|---|---|
1 |
Reset Compressor |
0 |
No value |
2 |
JSON Message |
Variable |
JSON message (any format) |
3 |
GPB compact |
Variable |
GPB message in compact format |
4 |
GPB key-value |
Variable |
GPB message in key-value format |
JSON messages are sent over TCP and use the header message described in TCP Header.
{ "Policy": "<name-of-policy>", "Version": "<policy-version>", "Identifier": "<data from policy file>" "CollectionID": <id>, "Path": <Policy Path>, "CollectionStartTime": <timestamp>, "Data": { … object as above … }, "CollectionEndTime": <timestamp>, }where:
Policy, Version and Identifier are specified in the policy file.
CollectionID is an integer that allows messages to be grouped together if data for a single path is split over multiple messages.
Path is the base path of the corresponding data as specified in the policy file.
CollectionStartTime and CollectionEndTime are the timestamps that indicate when the data was collected
Each container maps to a JSON object. The keys are strings that represent the schema names of the nodes; the values represent the values of the nodes.
Interfaces(*).Counters.Protocols(“IPv4”)This has two naming parameters - the interface name and the protocol name - and represents a container holding leaf nodes which are packet and byte counters. This would be represented as follows:
{ "Interfaces": [ { "Name": "GigabitEthernet0/0/0/1" "Counters": { "Protocols": [ { "ProtoName": "IPv4", "CollectionTime": 12345678, "InputPkts": 100, "InputBytes": 200, } ] } },{ "Name": "GigabitEthernet0/0/0/2" "Counters": { "Protocols": [ { "ProtoName": "IPv4", "CollectionTime": 12345678, "InputPkts": 400, "InputBytes": 500, } ] } } ] }
{ "Foo": { "Destination": [ { "IPAddress": 1.1.1.1, "Port": 2000, "CollectionTime": 12345678, "Leaf1": 100, } ] } }
{ "Interfaces": { "GigabitEthernet0/0/0/1": { "Counters": { "Protocols": { "IPv4": { "CollectionTime": 12345678, "InputPkts": 100, "InputBytes": 200, } } } }, "GigabitEthernet0/0/0/2": { "Counters": { "Protocols": { "IPv4": { "CollectionTime": 12345678, "InputPkts": 400, "InputBytes": 500, } } } } } } }A naming parameter with multiple keys, for example Foo.Destination(IPAddress=1.1.1.1, Port=2000), would be represented by nesting each key in order:
{ "Foo": { "Destination": { 1.1.1.1: { 2000: { Leaf1": 100, } } } ] } }
The output of the GPB encoder consists entirely of GPBs and allows multiple tables in a single packet for scalability.
GPB (Google Protocol Buffer) encoder requires metadata in the form of compiled .proto files. A .proto file describes the GPB message format, which is used to stream data.
Compact GPB format stores data in a compressed and non-self-describing format. A .proto file must be generated for each path in the policy file to be used by the receiver to decode the resulting data.
Key-value GPB format uses a single .proto file to encode data in a self-describing format. This encoding does not require a .proto file for each path. The data on the wire is much larger because key names are included.
telemetry policy-driven encoder gpb policy group alpha policy foo destination ipv4 192.168.1.1 port 1234 destination ipv4 10.0.0.1 port 9876 policy group beta policy bar policy whizz destination ipv4 10.20.30.40 port 3333 transport tcp compression zlib policy group gamma policy bang destination ipv4 11.1.1.1 port 4444 transport tcp encoding-format gpb-compact
![]() Note | The tables can be split over multiple packets but fragmenting a row is not supported. If a row in the table is too large to fit in a single UDP frame, it cannot be streamed. Instead either switch to TCP, increase the MTU, or modify the .proto file. |
message TelemetryHeader { optional uint32 encoding = 1 optional string policy_name = 2; optional string version = 3; optional string identifier = 4; optional uint64 start_time = 5; optional uint64 end_time = 6; repeated TelemetryTable tables = 7; } message TelemetryTable { optional string policy_path = 1; repeated bytes row = 2; }
encoding is used by receivers to verify that the packet is valid.
policy name, version and identifier are metadata taken from the policy file.
start time and end time indicate the duration when the data is collected.
tables is a list of tables within the packet. This format indicates that it is possible to receive results for multiple schema paths in a single packet.
The self-describing key-value GPB format uses a generic .proto file. This file encodes data as a sequence of key-value pairs. The field names are included in the output for the receiver to interpret the data.
message Telemetry { uint64 collection_id = 1; string base_path = 2; string subscription_identifier = 3; string model_version = 4; uint64 collection_start_time = 5; uint64 msg_timestamp = 6; repeated TelemetryField fields = 14; uint64 collection_end_time = 15; } message TelemetryField { uint64 timestamp = 1; string name = 2; bool augment_data = 3; oneof value_by_type { bytes bytes_value = 4; string string_value = 5; bool bool_value = 6; uint32 uint32_value = 7; uint64 uint64_value = 8; sint32 sint32_value = 9; sint64 sint64_value = 10; double double_value = 11; float float_value = 12; } repeated TelemetryField fields = 15; }
collection_id, base_path, collection_start_time and collection_end_time provide streaming details.
subscription_identifier is a fixed value for cadence-driven telemetry. This is used to distinguish from event-driven data.
model_version contains a string used for the version of the data model, as applicable.
A telemetry receiver is used as a destination to store streamed data.
A sample receiver that handles both JSON and GPB encodings is available at https://github.com/cisco/bigmuddy-network-telemetry-collector.
A copy of the cisco.proto file is required to compile code for a GPB receiver. The cisco.proto file is available at http://github.com/cisco/logstash-codec-bigmuddy-network-telemetry-gpb/tree/master/resources/xr6.0.0.
protoc --python_out . -I=/sw/packages/protoc/current/google/include/:. generic_counters.proto ipv4_counters.proto
--python_out <out_dir> specifies the location of the resulting generated files. These files are of the form <name>_pb2.py.
-I <import_path> specifies the path to look for imports. This must include the location of descriptor.proto from Google. (in /sw/packages) and cisco.proto and the .proto files that are compiled.
All files shown in the above example are located in the local directory.