The MIMIC gNMI Simulator is an optional facility that simulates the OpenConfig gNMI specification as detailed in this page . The GNMI service defines a gRPC-based protocol for retrieval and modification of device configuration, and the control and generation of telemetry streams from a managed device to a data collection system.
This management protocol is found on Cisco Nexus switches, Arista EOS, Juniper JUNOS and others.
For this proof-of-concept the gNMI Simulator is a standalone server application.
MIMIC gNMI Simulator currently has the following limitations:
Compatibility with various clients and applications is documented in the section below.
Install the GNMI Simulator package with the Update Wizard in the MIMICview graphical user interface.
Once the gNMI server is started with a configured data model, it will be able to respond to requests from clients.
The gNMI server accepts following command line arguments.
-h,--help Show this help message -u,--username USERNAME Define connection username -p,--password PASSWORD Define connection password -f,--force-insecure No TLS connection, no password authentication -k,--priv-key KEY_PATH Path to server PEM private key -c,--cert-chain CERT_PATH Path to server PEM certificate chain -s,--sim SIM_NAME Name of the simulation to load -a,--server-addr ADDR IP Address to bind to for gNMI server, default 0.0.0.0 -t,--server-port PORT Port to listen on for gNMI requests, default 50051 -A,--agent AGENT_NUM MIMIC agent to associate with -M,--mimic-host HOST MIMIC ip-address or hostname, default 127.0.0.1 -T,--mimic-port PORT MIMIC management port, default 9797
-s/--sim and -A/--agent are required arguments.
To start the server, change current directory to mimic-shared-area/bin and execute the following command.
./gnmi-start -f -s simulation-name -A agent-number
e.g.
./gnmi-start -f -s veos -A 1
This will start the gNMI server, load the veos simulation from scripts/gnmi/veos directory and associate it with agent 1 for MIMIC instance running on localhost.
gNMI responses to be returned by the simulated server are specified by the gNMI simulation located in the scripts/gnmi/ directory in the MIMIC directory hierarchy. Each simulation is contained in a subdirectory under this location.
Each simulation is comprised of three JSON formatted ASCII text files.
Any TCL scripts referred in the simulation configuration file also need to be in this same directory.
The configuration information is encoded as JSON.
The information under the subtrees identified by xpath /get and /subscribe affects the behavior of the simulator and should not be altered.
The information under the subtree identified by xpath /capabilities is used to respond to the capabilities RPC.
The information under the subtree identified by xpath /rules is used to customize the responses for get and subscribe RPCs.
The get and subscribe RPCs take one or more paths as arguments to retrieve information. Failure to resolve the specified path will result in gNMI error.
The /rules subtree is collection of JSON objects, each object containing zero or more simulation rules arranged as JSON array.
In each of the rules (see example below), xpath and script are necessary fields. Rules for get and subscribe RPC are triggered when the value of xpath field is matched with the path specified in the RPC.
Here is an example of devconfig.json.
{ "rules": { "startup": [ { "description": "set system-priority to 500", "name": "Startup Script 1", "xpath": "/lacp/config/system-priority", "script": "startup1.tcl" }, { "description": "get interfaces from agent", "name": "Startup Script 2", "xpath": "/interfaces", "script": "init-interfaces.tcl" } ], "animate": [ { "description": "double value of system-priority every 10 second", "name": "Animate Script 1", "every": 10000, "xpath": "/lacp/config/system-priority", "script": "animate1.tcl" }, { "description": "toggle value of enable twice every min i.e. every 500 msec", "name": "Animate Script 2", "rate": 2, "timeunit": "min", "xpath": "/lldp/config/enabled", "script": "animate2.tcl" } ], "get": [ { "description": "get hostname (.iso.org.dod.internet.mgmt.mib-2.system.sysName) of asociated mimic agent", "name": "GET Script for /system/state/hostname", "xpath": "/system/state/hostname", "script": "get-hostname.tcl" }, { "description": "get updated interface counters from associated mimic agent", "name": "GET Script for /interfaces/interface/state/counters", "xpath": "/interfaces/interface/state/counters", "script": "get-interface-counters.tcl" } ], "sub": [ { "description": "get updated interface counters from associated mimic agent", "name": "GET Script for /interfaces/interface/state/counters", "xpath": "/interfaces/interface/state/counters", "script": "get-interface-counters.tcl" } ] } }
Any Tcl procedure invoked will have a predefined set of global variables passed to it which identify the current environment.
This variable holds the MIMIC hostname/IP.
This variable holds the MIMIC management port.
This variable holds the MIMIC Agent number associated with the simulation instance.
This variable holds stringified JSON copy of the rule as specified in the device config JSON. The value is parsed as a DOM object and made available as a tcl global variable _rule_dom.
This variable holds the stringified JSON copy of subtree extracted from the simulation datatree. The extraction criteria is the xpath specified in the rule. The value is parsed as a DOM object and made available as a Tcl global variable _dataset_in.
MIMIC gNMI Simulator ships with few samples of simulated gNMI devices as part of its library of simulations.
The general process of creating a gNMI simulation involves
The 'capabilities' RPC is handled seperately using information provided in the device configuration file. Here is a snippet from the file.
"capabilities": { "models": [ [ "openconfig-if-ip", "OpenConfig working group", "2.3.0" ], [ "arista-rpol-deviations", "Arista Networks, Inc.", "" ], ... ] }
Contact Gambit Support team for any queries/guidance about the above process.
The gNMI Simulator package includes two samples of the gNMI Devices.
The purpose of the simulation samples provided is to
NOTE: No claim is made that sample simulations provided are a true and complete representation of the actual devices.
Here are some details about the sample gNMI simulations.
The open-source gnmic command returns this when run against a GNMI simulation of the first agent of the default lab:
% gnmic -u admin -p admin --insecure -a 45.10.11.1:6030 get --path "/lacp/config/system-priority" [ { "timestamp": 1639752772122189783, "time": "2021-12-17T09:52:52.122189783-05:00", "updates": [ { "Path": "lacp/config/system-priority", "values": { "lacp/config/system-priority": 1010 } } ] } ] % gnmic -u admin -p admin --insecure -a 45.10.11.1:6030 get --path "/lacp/config/system-priority" [ { "timestamp": 1639752778301540826, "time": "2021-12-17T09:52:58.301540826-05:00", "updates": [ { "Path": "lacp/config/system-priority", "values": { "lacp/config/system-priority": 1120 } } ] } ]
Notice the changing system-priority value.
The subscribe command returns a sequence of values:
% gnmic -u admin -p admin --insecure -a 45.10.11.1:6030 sub --path "/lacp/config/system-priority" --stream-mode sample --sample-interval 2s { "source": "45.10.11.1:6030", "subscription-name": "default-1639753280", "timestamp": 1639753280844912601, "time": "2021-12-17T10:01:20.844912601-05:00", "updates": [ { "Path": "lacp/config/system-priority", "values": { "lacp/config/system-priority": 5620 } } ] } { "source": "45.10.11.1:6030", "subscription-name": "default-1639753280", "timestamp": 1639753282846568862, "time": "2021-12-17T10:01:22.846568862-05:00", "updates": [ { "Path": "lacp/config/system-priority", "values": { "lacp/config/system-priority": 5720 } } ] } { "source": "45.10.11.1:6030", "subscription-name": "default-1639753280", "timestamp": 1639753284847797280, "time": "2021-12-17T10:01:24.84779728-05:00", "updates": [ { "Path": "lacp/config/system-priority", "values": { "lacp/config/system-priority": 5720 } } ] } { "source": "45.10.11.1:6030", "subscription-name": "default-1639753280", "timestamp": 1639753286849044976, "time": "2021-12-17T10:01:26.849044976-05:00", "updates": [ { "Path": "lacp/config/system-priority", "values": { "lacp/config/system-priority": 5720 } } ] } { "source": "45.10.11.1:6030", "subscription-name": "default-1639753280", "timestamp": 1639753288850428558, "time": "2021-12-17T10:01:28.850428558-05:00", "updates": [ { "Path": "lacp/config/system-priority", "values": { "lacp/config/system-priority": 5720 } } ] } { "source": "45.10.11.1:6030", "subscription-name": "default-1639753280", "timestamp": 1639753290851603731, "time": "2021-12-17T10:01:30.851603731-05:00", "updates": [ { "Path": "lacp/config/system-priority", "values": { "lacp/config/system-priority": 5720 } } ] } { "source": "45.10.11.1:6030", "subscription-name": "default-1639753280", "timestamp": 1639753292852920489, "time": "2021-12-17T10:01:32.852920489-05:00", "updates": [ { "Path": "lacp/config/system-priority", "values": { "lacp/config/system-priority": 5820 } } ] } { "source": "45.10.11.1:6030", "subscription-name": "default-1639753280", "timestamp": 1639753294854281347, "time": "2021-12-17T10:01:34.854281347-05:00", "updates": [ { "Path": "lacp/config/system-priority", "values": { "lacp/config/system-priority": 5820 } } ] } ^C received signal 'interrupt'. terminating...
Notice the value increments by 100 every 10 seconds, as configured in the simulation. Of course you can customize it to your requirements.
Of course, entire sub-trees can be retrieved, eg. try
% gnmic -u admin -p admin --insecure -a 45.10.11.1:6030 get --path "/interfaces/interface/state/counters" [ { "timestamp": 1639762215561673945, "time": "2021-12-17T12:30:15.561673945-05:00", "updates": [ { "Path": "interfaces/interface[name=MgmtEth0/RSP0/CPU0/0]/state/counters" , "values": { "interfaces/interface/state/counters": { "openconfig-interfaces:in-broadcast-pkts": "0", "openconfig-interfaces:in-discards": "112011", "openconfig-interfaces:in-errors": "112010", "openconfig-interfaces:in-multicast-pkts": "0", "openconfig-interfaces:in-octets": "112011", "openconfig-interfaces:in-unicast-pkts": "17279708", "openconfig-interfaces:out-broadcast-pkts": "1167", "openconfig-interfaces:out-discards": "112011", "openconfig-interfaces:out-errors": "112011", "openconfig-interfaces:out-multicast-pkts": "58457", "openconfig-interfaces:out-octets": "14949037", "openconfig-interfaces:out-unicast-pkts": "17266784" } } }, { "Path": "interfaces/interface[name=MgmtEth0/RSP0/CPU0/1]/state/counters" , "values": { "interfaces/interface/state/counters": { "openconfig-interfaces:in-broadcast-pkts": "0", "openconfig-interfaces:in-discards": "0", "openconfig-interfaces:in-errors": "0", "openconfig-interfaces:in-multicast-pkts": "0", "openconfig-interfaces:in-octets": "0", "openconfig-interfaces:in-unicast-pkts": "0", "openconfig-interfaces:out-broadcast-pkts": "1167", "openconfig-interfaces:out-discards": "0", "openconfig-interfaces:out-errors": "0", "openconfig-interfaces:out-multicast-pkts": "58457", "openconfig-interfaces:out-octets": "0", "openconfig-interfaces:out-unicast-pkts": "0" } } },
and 1500 more lines.
The following simple pipeline keeps updating a single statistical value:
% gnmic -u admin -p admin --insecure -a 45.10.11.1:6030 sub --path "/interfaces/interface/state/counters" --stream-mode sample --sample-interval 2s | awk -f single-interface.awk "2021-12-17T12:27:11.709145386-05:00", "interfaces/interface[name=GigabitEthernet101/0/0/38]/state/counters/out-octets", "69241402" "2021-12-17T12:27:14.80406031-05:00", "interfaces/interface[name=GigabitEthernet101/0/0/38]/state/counters/out-octets", "69293628" "2021-12-17T12:27:16.888229365-05:00", "interfaces/interface[name=GigabitEthernet101/0/0/38]/state/counters/out-octets", "69329061" "2021-12-17T12:27:18.986085317-05:00", "interfaces/interface[name=GigabitEthernet101/0/0/38]/state/counters/out-octets", "69363823" "2021-12-17T12:27:21.073823536-05:00", "interfaces/interface[name=GigabitEthernet101/0/0/38]/state/counters/out-octets", "69399256" "2021-12-17T12:27:23.161293852-05:00", "interfaces/interface[name=GigabitEthernet101/0/0/38]/state/counters/out-octets", "69434185" ^C % cat single-interface.awk /"time":/ {time=$2} /name=GigabitEthernet101\/0\/0\/38\]\/state\/counters\/out-octets/ {doprint=1; interface=$2} /interfaces\/interface\/state\/counters\/out-octets/ {if (doprint) { print time, interface,$2 }; doprint=0}
The Telegraf collector has a plugin to collect gNMI telemetry. We followed their documentation to produce this 2-minute Youtube video of Telegraf collecting interface statistics via gNMI and graphing with Grafana through the InfluxDB dashboard.