Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ stages:
DIFF_COVER_WORKING_DIRECTORY: $(System.DefaultWorkingDirectory)/sonic-gnmi

container:
image: sonicdev-microsoft.azurecr.io:443/sonic-slave-bookworm:latest
image: sonicdev-microsoft.azurecr.io:443/sonic-slave-bookworm:202505

steps:
- checkout: self
Expand Down
141 changes: 138 additions & 3 deletions doc/grpc_telemetry.md

Large diffs are not rendered by default.

357 changes: 320 additions & 37 deletions gnmi_server/server_test.go

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion sonic_data_client/db_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import (
"bytes"
"encoding/json"
"fmt"
log "github.com/golang/glog"
"net"
"reflect"
"strconv"
"strings"
"sync"
"time"

log "github.com/golang/glog"

"github.com/Workiva/go-datastructures/queue"
"github.com/go-redis/redis"
gnmipb "github.com/openconfig/gnmi/proto/gnmi"
Expand Down Expand Up @@ -659,6 +660,10 @@ func populateDbtablePath(prefix, path *gnmipb.Path, pathG2S *map[*gnmipb.Path][]
if err != nil {
return err
}
err = initCountersPGNameMap()
if err != nil {
return err
}
err = initAliasMap()
if err != nil {
return err
Expand Down
155 changes: 135 additions & 20 deletions sonic_data_client/virtual_db.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ package client

import (
"fmt"
log "github.com/golang/glog"
"os"
"strings"

log "github.com/golang/glog"
)

// virtual db is to Handle
Expand Down Expand Up @@ -35,6 +36,9 @@ var (
// Queue name to oid map in COUNTERS table of COUNTERS_DB
countersQueueNameMap = make(map[string]string)

// SONiC interface name to priority group indices and then to oid (from COUNTERS table of COUNTERS_DB)
countersPGNameMap = make(map[string]map[string]string)

// Alias translation: from vendor port name to sonic interface name
alias2nameMap = make(map[string]string)
// Alias translation: from sonic interface name to vendor port name
Expand Down Expand Up @@ -66,6 +70,9 @@ var (
}, { // stats for one or all Fabric ports
path: []string{"COUNTERS_DB", "COUNTERS", "PORT*"},
transFunc: v2rTranslate(v2rFabricPortStats),
}, { // Periodic PG watermarks for one or all Ethernet ports
path: []string{"COUNTERS_DB", "PERIODIC_WATERMARKS", "Ethernet*", "PriorityGroups"},
transFunc: v2rTranslate(v2rEthPortPGPeriodicWMs),
}, { // COUNTER_DB RATES Ethernet*
path: []string{"COUNTERS_DB", "RATES", "Ethernet*"},
transFunc: v2rTranslate(v2rEthPortStats),
Expand Down Expand Up @@ -99,6 +106,27 @@ func initCountersQueueNameMap() error {
return nil
}

func initCountersPGNameMap() error {
if len(countersPGNameMap) == 0 {
pgOidMap, err := getCountersMap("COUNTERS_PG_NAME_MAP")
if err != nil {
return err
}
for pg, oid := range pgOidMap {
// pg is in format of "Ethernet64:7"
pg_parts := strings.Split(pg, ":")
if len(pg_parts) != 2 {
return fmt.Errorf("invalid pg name %v", pg)
}
if _, ok := countersPGNameMap[pg_parts[0]]; !ok {
countersPGNameMap[pg_parts[0]] = make(map[string]string)
}
countersPGNameMap[pg_parts[0]][pg_parts[1]] = oid
}
}
return nil
}

func initCountersPortNameMap() error {
var err error
if len(countersPortNameMap) == 0 {
Expand Down Expand Up @@ -600,14 +628,29 @@ func v2rEthPortPfcwdStats(paths []string) ([]tablePath, error) {
return tblPaths, nil
}

func buildTablePath(namespace, dbName, tableName, tableKey, separator, field, jsonTableName, jsonTableKey, jsonField string) tablePath {
return tablePath{
dbNamespace: namespace,
dbName: dbName,
tableName: tableName,
tableKey: tableKey,
delimitor: separator,
field: field,
jsonTableName: jsonTableName,
jsonTableKey: jsonTableKey,
jsonField: jsonField,
}
}

// Populate real data paths from paths like
// [COUNTER_DB COUNTERS Ethernet* Queues] or [COUNTER_DB COUNTERS Ethernet68 Queues]
// [COUNTERS_DB COUNTERS Ethernet* Queues] or [COUNTERS_DB COUNTERS Ethernet68 Queues]
func v2rEthPortQueStats(paths []string) ([]tablePath, error) {
// paths[DbIdx] = "COUNTERS_DB"
separator, _ := GetTableKeySeparator(paths[DbIdx], "")
field := "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES"
var tblPaths []tablePath
if strings.HasSuffix(paths[KeyIdx], "*") { // queues on all Ethernet ports
for que, oid := range countersQueueNameMap {
// que is in format of "Internal_Ethernet:12"
names := strings.Split(que, separator)
var oname string
if alias, ok := name2aliasMap[names[0]]; ok {
Expand All @@ -621,14 +664,17 @@ func v2rEthPortQueStats(paths []string) ([]tablePath, error) {
return nil, fmt.Errorf("%v does not have namespace associated", names[0])
}
que = strings.Join([]string{oname, names[1]}, separator)
tblPath := tablePath{
dbNamespace: namespace,
dbName: paths[DbIdx],
tableName: paths[TblIdx],
tableKey: oid,
delimitor: separator,
jsonTableKey: que,
}
// que is in format of "Internal_Ethernet:12"
tblPath := buildTablePath(namespace, paths[DbIdx], paths[TblIdx], oid, separator, "", "", que, "")
tblPaths = append(tblPaths, tblPath)
/*
* Adding the field "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES" from the PERIODIC_WATERMARKS table
* to the virtual path.
*/
periodic_que := strings.Join([]string{que, "periodic"}, separator)
// periodic_que is in format of "Internal_Ethernet:12:periodic"
tblPath = buildTablePath(namespace, paths[DbIdx], "PERIODIC_WATERMARKS", oid, separator,
field, paths[TblIdx], periodic_que, field)
tblPaths = append(tblPaths, tblPath)
}
} else { //queues on single port
Expand All @@ -642,27 +688,96 @@ func v2rEthPortQueStats(paths []string) ([]tablePath, error) {
return nil, fmt.Errorf("%v does not have namespace associated", name)
}
for que, oid := range countersQueueNameMap {
//que is in format of "Ethernet64:12"
names := strings.Split(que, separator)
if name != names[0] {
continue
}
que = strings.Join([]string{alias, names[1]}, separator)
tblPath := tablePath{
dbNamespace: namespace,
dbName: paths[DbIdx],
tableName: paths[TblIdx],
tableKey: oid,
delimitor: separator,
jsonTableKey: que,
}
//que is in format of "Ethernet64:12"
tblPath := buildTablePath(namespace, paths[DbIdx], paths[TblIdx], oid, separator, "", "", que, "")
tblPaths = append(tblPaths, tblPath)
/*
* Adding the field "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES" from the PERIODIC_WATERMARKS table
* to the virtual path.
*/
periodic_que := strings.Join([]string{que, "periodic"}, separator)
//periodic_que is in format of "Ethernet64:12:periodic"
tblPath = buildTablePath(namespace, paths[DbIdx], "PERIODIC_WATERMARKS", oid, separator,
field, paths[TblIdx], periodic_que, field)
tblPaths = append(tblPaths, tblPath)
}
}
log.V(6).Infof("v2rEthPortQueStats: %v", tblPaths)
return tblPaths, nil
}

func getVendorPortName(port string) string {
// Get vendor port name from name2aliasMap
if alias, ok := name2aliasMap[port]; ok {
return alias
}
log.V(2).Infof(" %v does not have a vendor alias", port)
return port
}

func getSonicPortName(port string) string {
// Get sonic port name from alias2nameMap
if sonic_name, ok := alias2nameMap[port]; ok {
return sonic_name
}
return port
}

func getPortNamespace(port string) (string, error) {
// Get namespace from port2namespaceMap
namespace, ok := port2namespaceMap[port]
if !ok {
return "", fmt.Errorf("%v does not have an associated namespace", port)
}
return namespace, nil
}

// Populate real data paths from paths like
// [COUNTERS_DB PERIODIC_WATERMARKS Ethernet* PriorityGroups] or
// [COUNTERS_DB PERIODIC_WATERMARKS Ethernet64 PriorityGroups]
func v2rEthPortPGPeriodicWMs(paths []string) ([]tablePath, error) {
// paths[DbIdx] = "COUNTERS_DB"
separator, _ := GetTableKeySeparator(paths[DbIdx], "")
var tblPaths []tablePath
if strings.HasSuffix(paths[KeyIdx], "*") { // priority groups on all Ethernet ports
for port, pg_index_to_oid := range countersPGNameMap {
vendor_port := getVendorPortName(port)
namespace, err := getPortNamespace(port)
if err != nil {
return nil, err
}
for pg_index, oid := range pg_index_to_oid {
pg := strings.Join([]string{vendor_port, pg_index}, separator)
// pg is in format of "Internal_Ethernet:7"
tblPath := buildTablePath(namespace, paths[DbIdx], paths[TblIdx], oid, separator, "", "", pg, "")
tblPaths = append(tblPaths, tblPath)
}
}
} else { // priority groups on a single port
port := getSonicPortName(paths[KeyIdx])
namespace, err := getPortNamespace(port)
if err != nil {
return nil, err
}
if _, ok := countersPGNameMap[port]; !ok {
return nil, fmt.Errorf("No priority groups associated with %v", port)
}
for pg_index, oid := range countersPGNameMap[port] {
pg := strings.Join([]string{paths[KeyIdx], pg_index}, separator)
// pg is in format of "Ethernet64:7" or "Ethernet64/1:7"
tblPath := buildTablePath(namespace, paths[DbIdx], paths[TblIdx], oid, separator, "", "", pg, "")
tblPaths = append(tblPaths, tblPath)
}
}
log.V(6).Infof("v2rEthPortPGPeriodicWMs: %v", tblPaths)
return tblPaths, nil
}

func lookupV2R(paths []string) ([]tablePath, error) {
n, ok := v2rTrie.Find(paths)
if ok {
Expand Down
8 changes: 6 additions & 2 deletions testdata/COUNTERS:Ethernet68:Queues.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"SAI_QUEUE_STAT_BYTES": "0",
"SAI_QUEUE_STAT_DROPPED_BYTES": "0",
"SAI_QUEUE_STAT_DROPPED_PACKETS": "0",
"SAI_QUEUE_STAT_PACKETS": "0"
"SAI_QUEUE_STAT_PACKETS": "0",
"SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "64"
},
"Ethernet68:10": {},
"Ethernet68:11": {},
Expand Down Expand Up @@ -55,5 +56,8 @@
"Ethernet68:6": {},
"Ethernet68:7": {},
"Ethernet68:8": {},
"Ethernet68:9": {}
"Ethernet68:9": {},
"Ethernet68:1:periodic": {
"SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "192"
}
}
8 changes: 6 additions & 2 deletions testdata/COUNTERS:Ethernet68:Queues_alias.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"SAI_QUEUE_STAT_BYTES": "0",
"SAI_QUEUE_STAT_DROPPED_BYTES": "0",
"SAI_QUEUE_STAT_DROPPED_PACKETS": "0",
"SAI_QUEUE_STAT_PACKETS": "0"
"SAI_QUEUE_STAT_PACKETS": "0",
"SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "64"
},
"Ethernet68/1:10": {},
"Ethernet68/1:11": {},
Expand Down Expand Up @@ -55,5 +56,8 @@
"Ethernet68/1:6": {},
"Ethernet68/1:7": {},
"Ethernet68/1:8": {},
"Ethernet68/1:9": {}
"Ethernet68/1:9": {},
"Ethernet68/1:1:periodic": {
"SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "192"
}
}
28 changes: 28 additions & 0 deletions testdata/COUNTERS:Ethernet7:Queues.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"Ethernet7:0": {},
"Ethernet7:1": {},
"Ethernet7:10": {},
"Ethernet7:11": {},
"Ethernet7:12": {},
"Ethernet7:13": {},
"Ethernet7:14": {},
"Ethernet7:15": {},
"Ethernet7:16": {},
"Ethernet7:17": {},
"Ethernet7:18": {},
"Ethernet7:19": {},
"Ethernet7:2": {},
"Ethernet7:3": {},
"Ethernet7:4": {},
"Ethernet7:5": {
"SAI_QUEUE_STAT_BYTES": "0",
"SAI_QUEUE_STAT_DROPPED_BYTES": "0",
"SAI_QUEUE_STAT_DROPPED_PACKETS": "0",
"SAI_QUEUE_STAT_PACKETS": "0",
"SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "100"
},
"Ethernet7:6": {},
"Ethernet7:7": {},
"Ethernet7:8": {},
"Ethernet7:9": {}
}
28 changes: 28 additions & 0 deletions testdata/COUNTERS:Ethernet7:Queues_alias.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"Ethernet7/1:0": {},
"Ethernet7/1:1": {},
"Ethernet7/1:10": {},
"Ethernet7/1:11": {},
"Ethernet7/1:12": {},
"Ethernet7/1:13": {},
"Ethernet7/1:14": {},
"Ethernet7/1:15": {},
"Ethernet7/1:16": {},
"Ethernet7/1:17": {},
"Ethernet7/1:18": {},
"Ethernet7/1:19": {},
"Ethernet7/1:2": {},
"Ethernet7/1:3": {},
"Ethernet7/1:4": {},
"Ethernet7/1:5": {
"SAI_QUEUE_STAT_BYTES": "0",
"SAI_QUEUE_STAT_DROPPED_BYTES": "0",
"SAI_QUEUE_STAT_DROPPED_PACKETS": "0",
"SAI_QUEUE_STAT_PACKETS": "0",
"SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "100"
},
"Ethernet7/1:6": {},
"Ethernet7/1:7": {},
"Ethernet7/1:8": {},
"Ethernet7/1:9": {}
}
16 changes: 13 additions & 3 deletions testdata/COUNTERS:Ethernet_wildcard_Queues.txt
Original file line number Diff line number Diff line change
Expand Up @@ -984,7 +984,8 @@
"SAI_QUEUE_STAT_BYTES": "0",
"SAI_QUEUE_STAT_DROPPED_BYTES": "0",
"SAI_QUEUE_STAT_DROPPED_PACKETS": "0",
"SAI_QUEUE_STAT_PACKETS": "0"
"SAI_QUEUE_STAT_PACKETS": "0",
"SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "64"
},
"Ethernet68:10": {},
"Ethernet68:11": {},
Expand Down Expand Up @@ -1039,7 +1040,13 @@
"Ethernet7:2": {},
"Ethernet7:3": {},
"Ethernet7:4": {},
"Ethernet7:5": {},
"Ethernet7:5": {
"SAI_QUEUE_STAT_BYTES": "0",
"SAI_QUEUE_STAT_DROPPED_BYTES": "0",
"SAI_QUEUE_STAT_DROPPED_PACKETS": "0",
"SAI_QUEUE_STAT_PACKETS": "0",
"SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "100"
},
"Ethernet7:6": {},
"Ethernet7:7": {},
"Ethernet7:8": {},
Expand Down Expand Up @@ -1083,6 +1090,9 @@
"Ethernet9:6": {},
"Ethernet9:7": {},
"Ethernet9:8": {},
"Ethernet9:9": {}
"Ethernet9:9": {},
"Ethernet68:1:periodic": {
"SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES": "192"
}
}

Loading
Loading