- Print
- PDF
Accessing Provider Connective Assurance with gNMI
The Cisco Provider Connectivity Assurance solution supports gNMI for data queries and export, allowing for seamless integration with both Cisco and non-Cisco telemetry data. This solution enables proactive assurance of business-critical networks, services, and applications through synthetic network and service testing, user experience monitoring, and AI-powered issue detection.
Accessing the Provider Connectivity Assurance platform using gNMI gNMI enhances network visibility, reliability, and operational efficiency, ensuring secure access with multiple authentication methods, which protects sensitive data. It also enables automation, increasing efficiency and reducing errors.
For details about the Provider Connectivity Assurance Solution, see: Provider Connectivity Assurance Solution
This article will help you understand how to authenticate and use gNMI (gRPC Network Management Interface) with Provider Connective Assurance to optimize your network management and monitoring.
Getting Started: Authentication
Provider Connective Assurance supports the following three authentication methods:
• Credentials: Use your Provider Connective Assurance login details.
• JWT (JSON Web Token): A long-lived token created via the Provider Connectivity Assurance API.
• Bearer Token: A short-lived token obtained from the Provider Connectivity Assurance login.
Using Credentials
You can connect to gNMI using your Provider Connective Assurance username and password. Here's some example commands using gnmic, a gNMI client:
gnmic -a cisco-cnc.dhuscisco-dev.analytics.accedian.io:443 --format protojson -u admin@datahub.com -p <passwd> subscribe --path '/object-type/twamp-sf/monitored-objects/monitored-object[meta/data/name/usage=europe-east]/metrics' --mode stream
gnmi_cli (Openconfig reference implementation)
gnmi_cli -a cisco-cnc.dhuscisco-dev.analytics.accedian.io:443 -tls_skip_verify -display_type p -query_type s -t '/gnmi.gNMI/' -q /object-type/twamp-sf/monitored-objects/monitored-object[meta/data/name/usage=europe-east]/metrics -with_per_rpc_auth -with_user_pass
💡Queries for username and password
gnmicli
Accedian flavoured version of openconfig gnmi client, supports JWT and Baerer Auth (see below)
gnmicli --addr cisco-cnc.dhuscisco-dev.analytics.accedian.io:443 --auth credentials --username admin@datahub.com --password <password> --insecureTls --query /accedian:session/object-type/twamp-sf/monitored-objects/monitored-object[meta/data/name/usage=europe-east]/metrics
JWT
Authentication is done using a long lived JWT (JSON Web Token). The JWT is created via corresponding Provider Connectivity Assurance API. When a gNMI subscription request is issued, the JWT has to be included in the gRPC metadata under the Authorization
key.
- Login to Provider Connectivity Assurance as tenant-admin
- Issue request to
{{baseUrl}}/api/v1/auth/tokens
{
"data": {
"attributes" : {
"aud": "accedian",
"iss": "accedian",
"sub": "user@datahub.com",
"tenantURL": "{{baseUrl}}",
"exp" : 35683279714
},
"type": "tokens"
}
}
Copy the create JWT
eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhY2NlZGlhbiIsInN1YiI6ImFkbWluQGRhdGFodWIuY29tIiwiZXhdwIjozNTY4MzI3OTcxNCwtilXVkIjoiYWNjZWRpYW4iLCJ0b2tlbklEIjoyOTIsInRlbmFudElEIjoiZTE5MTYwYjctMTBrararlZC00YmZiLTlkZDctMjYwMjM0NTQ5NzgzIiwidGVuYW50VVJMIjoiaHR0cHM6Ly90rZW5hbnQxLmJlcGVyZi5ucGD2LmFjY2VkaWFuLm5ldCJ9.cKmhYJbYBjSrsf9l-NlzuQ8781chGUjTnhfRzclQ2IY
Add to gRPC metadata with key:
Authorization
💡The Accedian gNMI client supports the JWT auth ($AUTH_TOKEN
is a JWT token string)
Example:
./gnmicli --addr cisco-cnc.dhuscisco-dev.analytics.accedian.io:443 --query /object-type/twamp-sf/monitored-objects/monitored-object[meta/data/name/usage=europe-east]/metrics/jitter-p95 --auth token --insecureTls --authToken $AUTH_TOKEN
Bearer Token
You can also use the Bearer token returned by the Provider Connectivity Assurance login and add that to the gRPC metadata Authorization
header. Note however, that these tokens are short lived.
Bearer MTY2ODQzNzI0MHxkRFlFSmQ5Y3JUak9heEg1amRIMUNPSl9yYmdmMkZORm5pOU1IY3d3YXc1Vk1PbUVteFctbS1ZaW9TTTlHcEdMUy1UNnE5QVNIV2F1aXVqZVZzbl85eWhlczlqOW5PWTBrQ09nMDdacEhrMjZIN1dHcU50RVRoZ2pRMklxV0p4d1jdsbmRfcHRMdmcxYm5YUndCNlNpZU5zalltTVZ0bkhTU2hZUG9qc0p5RUVTZXpQeUd1UUx6OTBJd0c0dFNiVDA5RVRKVHZzcUtMZFB2UWQ5cldaMVVUTm5IZ1hXUmRsN0EtNWJfajZMdkItMmFpMW9rY3V5UmV0N2c0Qk0pPV1l4UFBacG1objdTVi15cENPU3R2Q2x6YWxWNDJSRUxQS3NzZHlZajhmTkJPb250TGxVZ1V6aXBmSTVURDVQM1VDMG1JblVGT3JDak1rUHA2NkV1U3ZqZWY1VkdZaDlMTzlweTlalalalQZEFrVVM1TWQ1dTYwODBmaW5XN3VrQ1pONURLNHMzV2VWWWJOTktxME0yNUl5RlNFSncxR0wzUlVxcXFhbFAtOVViR1pjNW82T1pham9PUDcwLXdmM0V3SnZHdThQYnJ3d0d4RGZOUkF1bHpWZHMtSEFqM1JURFM2Wmt1US1DRjM5NDZGc1ZKSlRjeWtaQWJReTd6Nmk3NF9BanNPSUlZREQ3TEt2WnpLbXp0YXNoSnJlQjVHQkkzQ3RHUGZaTnZPeEg2RFR5bWhqZlpueGJGRWRlV1VmeE5vblJCbWtzMlMwbXplSm80N3FwRWJibkN6TTdWUS1nekx1cjRwa3UyN0p4SXJNanJld0NES1EzMzI4OHg1Q25XNDZrRXdlMzFEaF9xcHZ2WFhUaW9ZRTZEaVBRSmlnc19hVlhKT3lBZkJQVXhSZW9TdkZZMUdxSHA0bWw5ZXVhV0tMOHZWXzNJR1V5dXpBYzh3cGFLVTdBa0xvYnJkNjhQcHJEQkRja3p3aGl1S3RwaFZBUmNYYmRTNTVuQXRnR2FoRmVnQ3ZVNk9qWVdTTVc0T2xleFltYVVneldMZmdIUjFXdlRyS2p1LTFuN2tUSUd5aEljd2ptUzRfMzBVZWZEendJY3plZTh1enJiLTF6VUhqRmszYjN4LTdzT3VTWnpiU0ZjOVpzSTl2WTNvZmsyZy1yRmlXOEp1Rnz4yMZO3BDMzI3V6JIspPYE3rKqs0P7I0Y9NQVFXukNkQ==
💡The Accedian gNMI client supports Bearer token auth ($AUTH_TOKEN
is a Bearer token string, without the prefix: Bearer)
./gnmicli --addr cisco-cnc.dhuscisco-dev.analytics.accedian.io:443 --query /object-type/twamp-sf/monitored-objects/monitored-object[meta/data/name/usage=europe-east]/metrics/jitter-p95 --auth token --insecureTls --authToken $AUTH_TOKEN
Subscriptions
Subscriptions currently only support STREAM in ON_CHANGE mode. Whenever a session reports new values, it is considered a CHANGE, even if the value did not change since the last report. When a subscription is established, session data is transferred starting from that point in time. Synchronization is currently not implemented, meaning that no session data that was received prior to the subscription, is transferred over the gNMI.
Subscription Paths:
The primary subscription paths are:
• All data available about the session
• Session metrics only
• Specific session metrics
All metrics and metadata
/object-type/twamp-sf/monitored-objects/monitored-object[meta/data/name/usage=europe-east]
All metrics
/object-type/twamp-sf/monitored-objects/monitored-object[meta/data/name/usage=europe-east]/metrics
All metrics with multiple values for category
/object-type/twamp-sf/monitored-objects/monitored-object[meta/data/name/usage=europe-east|europe-west]/metrics
All metrics with multiple categories
/object-type/twamp-sf/monitored-objects/monitored-object[meta/data/name/usage=europe-east;meta/data/name/service=abc]/metrics
Specific metric (leaf)
/object-type/twamp-sf/monitored-objects/monitored-object[meta/data/name/usage=europe-east]/metrics/jitter-p95
Reporting Interval
The gNMI interface delivers data in real-time as it is received, because the Provider Connectivity Assurance-streamer is designed to operate without maintaining any state. Consequently, you cannot set a specific reporting interval when you subscribe.
As a result, the data is reported at approximately the same intervals as the session reports its data. For instance, if a subscribed session reports every 30 seconds, you will receive updates approximately every 30 seconds.
YANG model
The following YANG model defines the structure for monitored objects in the Cisco Provider Connectivity Assurance solution. This model specifies the containers and groupings necessary for effective network data management, focusing on metrics and metadata essential for network assurance.
yang-version "1";
namespace "http://accedian.com/ns/yang/session";
prefix "accedian";
organization "Accedian";
description
"This YANG module contains the monitored object definition";
revision 2022-10-18 {
description
"Network Direction Update";
reference "1.1.0";
}
container object-type {
description "Monitored Object type";
config false;
container twamp-sf {
container monitored-objects {
list monitored-object {
key "monitored-object-id monitored-object-name direction service-id";
uses properties-grouping;
container location {
container source-location {
uses location-grouping;
}
container destination-location {
uses location-grouping;
}
}
container metrics {
uses metrics-grouping;
}
container meta {
uses meta-grouping;
}
}
}
}
}
grouping properties-grouping {
leaf monitored-object-id {
type string;
description "Monitored Object unique identifier";
}
leaf session-id {
type string;
description "Session ID";
}
leaf monitored-object-name {
type string;
description "Monitored object name";
}
leaf direction {
type network-direction;
description "Direction";
}
leaf-list Topology {
type string;
description "Topology";
}
leaf service-id {
type string;
description "Service ID";
}
}
grouping metrics-grouping {
leaf bytes-received {
type decimal64 {
fraction-digits 5;
}
description "Bytes Received";
}
leaf delay-avg {
type decimal64 {
fraction-digits 5;
}
description "Delay average";
}
leaf sync-quality {
type int64;
description "sync quality";
}
leaf sync-state {
type int64;
description "sync state";
}
leaf delay-max {
type decimal64 {
fraction-digits 5;
}
description "Delay max";
}
leaf delay-min {
type decimal64 {
fraction-digits 5;
}
description "Delay min";
}
leaf delay-p25 {
type decimal64 {
fraction-digits 5;
}
description "Delay p25";
}
leaf delay-p50 {
type decimal64 {
fraction-digits 5;
}
description "Delay P50";
}
leaf delay-p75 {
type decimal64 {
fraction-digits 5;
}
description "Delay P75";
}
leaf delay-p95 {
type decimal64 {
fraction-digits 5;
}
description "Delay P95";
}
leaf delay-phi {
type decimal64 {
fraction-digits 5;
}
description "Delay PHi";
}
leaf delay-plo {
type decimal64 {
fraction-digits 5;
}
description "Delay PLo";
}
leaf delay-pmi {
type decimal64 {
fraction-digits 5;
}
description "Delay PMi";
}
leaf delay-std-dev-avg {
type decimal64 {
fraction-digits 5;
}
description "Delay standard deviation average";
}
leaf delay-var-avg {
type decimal64 {
fraction-digits 5;
}
description "Delay var avg";
}
leaf delay-var-max {
type decimal64 {
fraction-digits 5;
}
description "Delay var max";
}
leaf delay-var-min {
type decimal64 {
fraction-digits 5;
}
description "Delay var min";
}
leaf delay-var-p25 {
type decimal64 {
fraction-digits 5;
}
description "Delay var P25";
}
leaf delay-var-p50 {
type decimal64 {
fraction-digits 5;
}
description "Delay var P50";
}
leaf delay-var-p75 {
type decimal64 {
fraction-digits 5;
}
description "Delay var P75";
}
leaf delay-var-p95 {
type decimal64 {
fraction-digits 5;
}
description "Delay var P95";
}
leaf delay-var-phi {
type decimal64 {
fraction-digits 5;
}
description "Delay var PHi";
}
leaf delay-var-plo {
type decimal64 {
fraction-digits 5;
}
description "Delay var PLo";
}
leaf delay-var-pmi {
type decimal64 {
fraction-digits 5;
}
description "Delay var PMi";
}
leaf duration {
type decimal64 {
fraction-digits 5;
}
description "Duration";
}
leaf ip-tos-max {
type decimal64 {
fraction-digits 5;
}
description "IP TOS Max";
}
leaf ip-tos-min {
type decimal64 {
fraction-digits 5;
}
description "IP TOS Min";
}
leaf jitter-avg {
type decimal64 {
fraction-digits 5;
}
description "Jitter Average";
}
leaf jitter-max {
type decimal64 {
fraction-digits 5;
}
description "Jitter Max";
}
leaf jitter-min {
type decimal64 {
fraction-digits 5;
}
description "Jitter Min";
}
leaf jitter-p25 {
type decimal64 {
fraction-digits 5;
}
description "Jitter P25";
}
leaf jitter-p50 {
type decimal64 {
fraction-digits 5;
}
description "Jitter P50";
}
leaf jitter-p75 {
type decimal64 {
fraction-digits 5;
}
description "Jitter P75";
}
leaf jitter-p95 {
type decimal64 {
fraction-digits 5;
}
description "Jitter P95";
}
leaf jitter-phi {
type decimal64 {
fraction-digits 5;
}
description "Jitter PHi";
}
leaf jitter-plo {
type decimal64 {
fraction-digits 5;
}
description "Jitter PLo";
}
leaf jitter-pmi {
type decimal64 {
fraction-digits 5;
}
description "Jitter PMi";
}
leaf jitter-std-dev {
type decimal64 {
fraction-digits 5;
}
description "Jitter Std Dev";
}
leaf lost-burst-max {
type decimal64 {
fraction-digits 5;
}
description "Lost Burst Max";
}
leaf lost-burst-min {
type decimal64 {
fraction-digits 5;
}
description "Lost burst min";
}
leaf mos {
type decimal64 {
fraction-digits 5;
}
description "MOS";
}
leaf packets-lost {
type decimal64 {
fraction-digits 5;
}
description "Packets lost";
}
leaf packets-lost-pct {
type decimal64 {
fraction-digits 5;
}
description "Packets lost pct";
}
leaf packets-duplicated {
type decimal64 {
fraction-digits 5;
}
description "Packets duplicated";
}
leaf packets-misordered {
type decimal64 {
fraction-digits 5;
}
description "Packets misordered";
}
leaf packets-received {
type decimal64 {
fraction-digits 5;
}
description "Packets received";
}
leaf packets-too-late {
type decimal64 {
fraction-digits 5;
}
description "Packets too late";
}
leaf periods-lost {
type decimal64 {
fraction-digits 5;
}
description "Periods lost";
}
leaf rvalue {
type decimal64 {
fraction-digits 5;
}
description "RValue";
}
leaf ttl-max {
type decimal64 {
fraction-digits 5;
}
description "TTL Max";
}
leaf ttl-min {
type decimal64 {
fraction-digits 5;
}
description "TTL Min";
}
leaf vlan-pbit-min {
type decimal64 {
fraction-digits 5;
}
description "VLAN PBit Min";
}
leaf vlan-pbit-max {
type decimal64 {
fraction-digits 5;
}
description "VLAN PBit Max";
}
}
grouping location-grouping {
leaf lat {
type decimal64 {
fraction-digits 7;
}
description "latitude";
}
leaf lon {
type decimal64 {
fraction-digits 7;
}
description "longitude";
}
}
grouping meta-grouping {
list data {
key name;
leaf name {
type string;
}
leaf val {
type string;
}
}
}
typedef network-direction {
type enumeration {
enum -1 {
description
"NON: No Direction";
}
enum 0 {
description
"SD: Source to Destination - metrics with this directionality represents the packet stats seen as they arrive at the destination";
}
enum 1 {
description
"DS: Destination to Source - metrics with this directionality represents the packet stats seen starting from the destination back to the source";
}
enum 2 {
description
"RT: Round Trip - metrics with this directionality represent the packet stats seen between the source back to itself";
}
}
}
}
Cisco gNMI Client
We provide a test client, based on the openconfig gNMI framework, to connect to the Cisco Provider Connectivity Assurance gNMI and verify data is flowing.
Usage: gnmicli --addr ADDR --query QUERY [--target TARGET] [--tenantId TENANTID] [--auth AUTH] [--authToken AUTHTOKEN] [--insecureTls] [--username USERNAME] [--password PASSWORD]
Options:
--addr ADDR, -a ADDR Address of the gNMI server
--query QUERY, -q QUERY
gNMI subscription query path
--target TARGET Target of the gNMI endpoint [default: /gnmi.gNMI/]
--tenantId TENANTID, -t TENANTID
Required for NoAuth [--auth none]
--auth AUTH Authentication type: [token], [credentials] or [none] [default: none]
--authToken AUTHTOKEN
Token for authentication. Required for [token] authentication
--insecureTls Adds insecure TLS (skip verify) [default: false]
--username USERNAME Username for credentials auth
--password PASSWORD Password for credentials auth
--help, -h display this help and exit
Example usage:
./gnmicli --addr cisco-cnc.dhuscisco-dev.analytics.accedian.io:443 --query /object-type/twamp-sf/monitored-objects/monitored-object[meta/data/name/usage=europe-east]/metrics/jitter-p95 --auth token --insecureTls --authToken $AUTH_TOKEN
Postman Setup
This section guides you through setting up Postman to interact with the gNMI interface of the Cisco Provider Connectivity Assurance solution. By following these steps, you can configure Postman to test and verify gNMI queries and subscriptions, enabling efficient network monitoring and data analysis.
- Download/Clone gnmi.proto and gnmi_ext.proto from openconfig on github to your local machine.
https://github.com/openconfig/gnmi/tree/master/proto - In postman by the workspace click “new” and then select gRPC request
- Navigate to the service definition tab of the request, select “Import a .proto file”
Chose gnmi.proto as the proto file
Add your path to the gnmi_ext.proto file as an import path. Make sure that the postman import path is relative to the import path defined in the gnmi.proto (Which is: github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext.proto).
Hit “Next”
In “Import as API”, type a name for your API, Provider-Connectivity-Assurance-gNMI for example. Then in the dropdown, select “Create new api” to save your custom name. Finally click the “Import as API” button to save.
Click the lock, to the left of the URL, to enable TLS
Add the server URL to the request (ex. cisco.dhuscisco.analytics.accedian.io/)
Next to the URL, select the gRPC method Subscribe
- Navigate to the Authorization tab of the request, select bearer token as type and then add your token to the appropriate section. The token can be either the JSON Web Token (JWT) you created, or a Bearer token you obtained by logging in to Provider Connectivity Assurance (as in the following screenshot).
Navigate to the Message tab, add your subscription request
Ex.{ "subscribe": { "mode": "STREAM", "prefix": { "origin": "accedian:session", "elem": [ { "name": "object-type" }, { "name": "twamp-sf" }, { "name": "monitored-objects" } ] }, "subscription": [ { "path": { "origin": "accedian:session", "elem": [ { "name": "monitored-object", "key" : { "meta/data/name/state" : "texas" } }, { "name": "metrics" }, { "name": "delay-p75" } ] } }, { "path": { "elem": [ { "name": "monitored-object", "key" : { "meta/data/name/state" : "colorado" } }, { "name": "metrics" } ] } } ] } }
Click the Invoke button to initiate the gRPC stream connection
Click the Send button to pass initiate your subscription streaming
Performance Testing gNMI Server
Performance testing is conducted using a Docker image of our internal gNMI CLI client. You can create custom Docker Compose files to quickly scale gNMI subscriptions with specific metadata filters. During testing, we observed that running more than 100 containers on a single Docker node can be challenging. For over 100 subscriptions, it's advisable to distribute connections across multiple virtual machines. After completing the tests, use docker system prune to clean up the environment efficiently.
Note: The test uses the --perfTesting flag, which implements a NOOP (no operation) for message handling. While this prevents messages from being logged to the console, it enhances server performance.
version: "3.3"
services:
worker-1:
image: gcr.io/npav-172917/analytics-streamer:gnmi-cli
deploy:
placement:
constraints:
- node.labels.oaf == true
command: ./gnmicli --perfTesting --addr ${ADDR} --insecureTls --auth "token" --authToken ${TOKEN} --query ${BASEQUERY}"[meta/data/name/region=east;meta/data/name/source_city=ottawa]/metrics"
worker-2:
image: gcr.io/npav-172917/analytics-streamer:gnmi-cli
deploy:
placement:
constraints:
- node.labels.oaf == true
command: ./gnmicli --perfTesting --addr ${ADDR} --insecureTls --auth "token" --authToken ${TOKEN} --query ${BASEQUERY}"[meta/data/name/region=west]"
Once you configure Docker in swarm mode, ensure that a node in the swarm has the label you set up.
docker node update --label-add oaf=true dnocita1-worker-123
Use the following simple script to stand up the environment with three arguments provided:
./start-test.sh 1 tenant1.beperf.npav.accedian.net:443 $BePerfToken
Argument | Name | Description | Example |
---|---|---|---|
1 | Deployments | The number of replicas to standup of the compose file, useful to scale connections with minimal subscription configurations | 1 |
2 | Address | gRPC address and port for the tenant | tenant1.beperf.npav.accedian.net:443 |
3 | Token | API token for the tenant, it can be generated by sending a POST call to /api/v1/auth/tokens |
#!/bin/bash
if [ $# -eq 0 ]; then
echo "No arguments provided"
exit 1
fi
# Varriables
DEPLOYMENTS=$1
ADDR=$2
TOKEN=$3
BASEQUERY="/accedian:session/object-type/twamp-sf/monitored-objects/monitored-object"
# Start files
printf '%.0s\n' {1..3}
echo "~~~ Starting Performance Containers ~~~"
printf '%.0s\n' {1}
for i in $(seq $DEPLOYMENTS)
do
echo "Starting Performance$i"
ADDR=$ADDR TOKEN=$TOKEN BASEQUERY=$BASEQUERY docker stack deploy --compose-file performance-docker-compose.yml Performance$i
done
printf '%.0s\n' {1..3}
echo "~~~ Starting Performance Containers Complete ~~~"
printf '%.0s\n' {1}
Use the following script to clean up the environment. Simply provide the same Deployments argument that you used when starting the environment.
./stop-test.sh 1
#!/bin/bash
if [ $# -eq 0 ]; then
echo "No arguments provided"
exit 1
fi
# Varriables
DEPLOYMENTS=$1
printf '%.0s\n' {1..3}
echo "~~~ Stopping Previous Performance Containers ~~~"
printf '%.0s\n' {1}
for i in $(seq $DEPLOYMENTS)
do
echo "Stopping Performance$i"
docker stack rm Performance$i
done
printf '%.0s\n' {1..3}
echo "~~~ Stopping Previous Performance Containers Complete ~~~"
printf '%.0s\n' {1}
© 2025 Cisco and/or its affiliates. All rights reserved.
For more information about trademarks, please visit: Cisco trademarks
For more information about legal terms, please visit: Cisco legal terms
For legal information about Accedian Skylight products, please visit: Accedian legal terms and tradmarks