Skip to content

Commit

Permalink
Support GNMI native write with origin
Browse files Browse the repository at this point in the history
  • Loading branch information
ganglyu committed Nov 24, 2022
1 parent 5b43489 commit 81700b4
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 177 deletions.
84 changes: 50 additions & 34 deletions gnmi_server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,26 @@ func (s *Server) checkEncodingAndModel(encoding gnmipb.Encoding, models []*gnmip
return nil
}

func ParseOrigin(origin string, paths []*gnmipb.Path) (string, error) {
if len(paths) == 0 {
return origin, nil
}
for i, path := range paths {
if origin == "" {
if i == 0 {
origin = path.Origin
}
} else if origin != path.Origin {
return "", status.Error(codes.Unimplemented, "Origin conflict in path")
}
}
return origin, nil
}

func IsNativeOrigin(origin string) bool {
return origin == "sonic-db" || origin == "sonic-yang"
}

// Get implements the Get RPC in gNMI spec.
func (s *Server) Get(ctx context.Context, req *gnmipb.GetRequest) (*gnmipb.GetResponse, error) {
common_utils.IncCounter(common_utils.GNMI_GET)
Expand All @@ -296,17 +316,10 @@ func (s *Server) Get(ctx context.Context, req *gnmipb.GetRequest) (*gnmipb.GetRe
return nil, status.Error(codes.Unimplemented, err.Error())
}

var target string
target := ""
prefix := req.GetPrefix()
if prefix == nil {
common_utils.IncCounter(common_utils.GNMI_GET_FAIL)
return nil, status.Error(codes.Unimplemented, "No target specified in prefix")
} else {
if prefix != nil {
target = prefix.GetTarget()
if target == "" {
common_utils.IncCounter(common_utils.GNMI_GET_FAIL)
return nil, status.Error(codes.Unimplemented, "Empty target data not supported yet")
}
}

paths := req.GetPath()
Expand All @@ -318,13 +331,19 @@ func (s *Server) Get(ctx context.Context, req *gnmipb.GetRequest) (*gnmipb.GetRe

if target == "OTHERS" {
dc, err = sdc.NewNonDbClient(paths, prefix)
} else if target == "MIXED" {
dc, err = sdc.NewMixedDbClient(paths, prefix)
} else if _, ok, _, _ := sdc.IsTargetDb(target); ok {
dc, err = sdc.NewDbClient(paths, prefix)
} else {
/* If no prefix target is specified create new Transl Data Client . */
dc, err = sdc.NewTranslClient(prefix, paths, ctx, extensions)
origin := ""
origin, err = ParseOrigin(origin, paths)
if err != nil {
return nil, err
}
if check := IsNativeOrigin(origin); check {
dc, err = sdc.NewMixedDbClient(paths, prefix, origin)
} else {
dc, err = sdc.NewTranslClient(prefix, paths, ctx, extensions)
}
}

if err != nil {
Expand Down Expand Up @@ -355,7 +374,7 @@ func (s *Server) Get(ctx context.Context, req *gnmipb.GetRequest) (*gnmipb.GetRe

func (s *Server) Set(ctx context.Context, req *gnmipb.SetRequest) (*gnmipb.SetResponse, error) {
common_utils.IncCounter(common_utils.GNMI_SET)
if s.config.EnableTranslibWrite == false {
if s.config.EnableTranslibWrite == false && s.config.EnableNativeWrite == false {
common_utils.IncCounter(common_utils.GNMI_SET_FAIL)
return nil, grpc.Errorf(codes.Unimplemented, "GNMI is in read-only mode")
}
Expand All @@ -368,33 +387,31 @@ func (s *Server) Set(ctx context.Context, req *gnmipb.SetRequest) (*gnmipb.SetRe

/* Fetch the prefix. */
prefix := req.GetPrefix()
var target string
if prefix == nil {
common_utils.IncCounter(common_utils.GNMI_SET_FAIL)
return nil, status.Error(codes.Unimplemented, "No target specified in prefix")
} else {
target = prefix.GetTarget()
}
extensions := req.GetExtension()

var dc sdc.Client
if target == "MIXED" {
origin := ""
paths := req.GetDelete()
for _, path := range req.GetReplace() {
paths = append(paths, path.GetPath())
}
for _, path := range req.GetUpdate() {
paths = append(paths, path.GetPath())
}
origin, err = ParseOrigin(origin, paths)
if err != nil {
return nil, err
}
if check := IsNativeOrigin(origin); check {
if s.config.EnableNativeWrite == false {
common_utils.IncCounter(common_utils.GNMI_SET_FAIL)
return nil, grpc.Errorf(codes.Unimplemented, "Mixed schema is disabled")
return nil, grpc.Errorf(codes.Unimplemented, "GNMI native write is disabled")
}
paths := req.GetDelete()
for _, path := range req.GetReplace() {
paths = append(paths, path.GetPath())
}
for _, path := range req.GetUpdate() {
paths = append(paths, path.GetPath())
}
dc, err = sdc.NewMixedDbClient(paths, prefix)
dc, err = sdc.NewMixedDbClient(paths, prefix, origin)
} else {
if s.config.EnableTranslibWrite == false {
common_utils.IncCounter(common_utils.GNMI_SET_FAIL)
return nil, grpc.Errorf(codes.Unimplemented, "Telemetry is in read-only mode")
return nil, grpc.Errorf(codes.Unimplemented, "Translib write is disabled")
}
/* Create Transl client. */
dc, err = sdc.NewTranslClient(prefix, nil, ctx, extensions)
Expand All @@ -416,7 +433,6 @@ func (s *Server) Set(ctx context.Context, req *gnmipb.SetRequest) (*gnmipb.SetRe

/* Add to Set response results. */
results = append(results, &res)

}

/* REPLACE */
Expand Down Expand Up @@ -465,7 +481,7 @@ func (s *Server) Capabilities(ctx context.Context, req *gnmipb.CapabilityRequest
var supportedModels []gnmipb.ModelData
dc, _ := sdc.NewTranslClient(nil, nil, ctx, extensions)
supportedModels = append(supportedModels, dc.Capabilities()...)
dc, _ = sdc.NewMixedDbClient(nil, nil)
dc, _ = sdc.NewMixedDbClient(nil, nil, "")
supportedModels = append(supportedModels, dc.Capabilities()...)

suppModels := make([]*gnmipb.ModelData, len(supportedModels))
Expand Down
35 changes: 27 additions & 8 deletions gnmi_server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import (
// Register supported client types.
spb "github.com/sonic-net/sonic-gnmi/proto"
sgpb "github.com/sonic-net/sonic-gnmi/proto/gnoi"
gnmipb "github.com/openconfig/gnmi/proto/gnmi"
sdc "github.com/sonic-net/sonic-gnmi/sonic_data_client"
sdcfg "github.com/sonic-net/sonic-gnmi/sonic_db_config"
"github.com/sonic-net/sonic-gnmi/common_utils"
Expand Down Expand Up @@ -982,13 +983,6 @@ func runGnmiTestGet(t *testing.T, namespace string) {
elem: <name: "MyCounters" >
`,
wantRetCode: codes.NotFound,
}, {
desc: "Test empty path target",
pathTarget: "",
textPbPath: `
elem: <name: "MyCounters" >
`,
wantRetCode: codes.Unimplemented,
}, {
desc: "Test passing asic in path for V2R Dataset Target",
pathTarget: "COUNTER_DB" + "/" + namespace,
Expand Down Expand Up @@ -2902,7 +2896,7 @@ print('%s')
}{
{
desc: "Set APPL_DB in batch",
pathTarget: "MIXED",
pathTarget: "",
textPbPath: `
origin: "sonic-db",
elem: <name: "APPL_DB" > elem:<name:"DASH_QOS" >
Expand Down Expand Up @@ -3003,6 +2997,31 @@ func TestInvalidServer(t *testing.T) {
}
}

func TestParseOrigin(t *testing.T) {
var test_paths []*gnmipb.Path
var err error

_, err = ParseOrigin("test", test_paths)
if err != nil {
t.Errorf("ParseOrigin failed for empty path: %v", err)
}

test_origin := "sonic-test"
path, err := xpath.ToGNMIPath(test_origin + ":CONFIG_DB/VLAN")
test_paths = append(test_paths, path)
origin, err := ParseOrigin("", test_paths)
if err != nil {
t.Errorf("ParseOrigin failed to get origin: %v", err)
}
if origin != test_origin {
t.Errorf("ParseOrigin return wrong origin: %v", origin)
}
origin, err = ParseOrigin("sonic-invalid", test_paths)
if err == nil {
t.Errorf("ParseOrigin should fail for conflict")
}
}

func init() {
// Enable logs at UT setup
flag.Lookup("v").Value.Set("10")
Expand Down
25 changes: 0 additions & 25 deletions sonic_data_client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,31 +298,6 @@ func TestJsonRemoveNegative(t *testing.T) {
}
}

func TestParseOrigin(t *testing.T) {
var test_paths []*gnmipb.Path
var err error

_, err = ParseOrigin("test", test_paths)
if err != nil {
t.Errorf("ParseOrigin failed for empty path: %v", err)
}

test_origin := "sonic-test"
path, err := xpath.ToGNMIPath(test_origin + ":CONFIG_DB/VLAN")
test_paths = append(test_paths, path)
origin, err := ParseOrigin("", test_paths)
if err != nil {
t.Errorf("ParseOrigin failed to get origin: %v", err)
}
if origin != test_origin {
t.Errorf("ParseOrigin return wrong origin: %v", origin)
}
origin, err = ParseOrigin("sonic-invalid", test_paths)
if err == nil {
t.Errorf("ParseOrigin should fail for conflict")
}
}

func TestParseTarget(t *testing.T) {
var test_paths []*gnmipb.Path
var err error
Expand Down
53 changes: 10 additions & 43 deletions sonic_data_client/mixed_db_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,41 +103,18 @@ func ParseTarget(target string, paths []*gnmipb.Path) (string, error) {
return target, nil
}

func ParseOrigin(origin string, paths []*gnmipb.Path) (string, error) {
if len(paths) == 0 {
return origin, nil
}
for i, path := range paths {
if origin == "" {
if i == 0 {
origin = path.Origin
}
} else if origin != path.Origin {
return "", status.Error(codes.Unimplemented, "Origin conflict in path")
}
}
if origin == "" {
return origin, status.Error(codes.Unimplemented, "No origin specified in path")
}
return origin, nil
}

func IsSupportedOrigin(origin string) bool {
for _, model := range supportedModels {
if model.Name == origin {
return true
}
}
return false
}

func (c *MixedDbClient) DbSetTable(table string, key string, values map[string]string) error {
pt, ok := c.tableMap[table]
if !ok {
pt = swsscommon.NewProducerStateTable(c.applDB, table)
c.tableMap[table] = pt
}
pt.Set(key, values, "SET", "")
vec := swsscommon.NewFieldValuePairs()
for k, v := range values {
pair := swsscommon.NewFieldValuePair(k, v)
vec.Add(pair)
}
pt.Set(key, vec, "SET", "")
return nil
}

Expand All @@ -151,7 +128,7 @@ func (c *MixedDbClient) DbDelTable(table string, key string) error {
return nil
}

func NewMixedDbClient(paths []*gnmipb.Path, prefix *gnmipb.Path) (Client, error) {
func NewMixedDbClient(paths []*gnmipb.Path, prefix *gnmipb.Path, origin string) (Client, error) {
var client MixedDbClient
var err error

Expand All @@ -162,13 +139,12 @@ func NewMixedDbClient(paths []*gnmipb.Path, prefix *gnmipb.Path) (Client, error)

client.prefix = prefix
client.target = ""
client.origin = ""
client.origin = origin
if prefix != nil {
elems := prefix.GetElem()
if elems != nil {
client.target = elems[0].GetName()
}
client.origin = prefix.Origin
}
if paths == nil {
return &client, nil
Expand All @@ -180,15 +156,6 @@ func NewMixedDbClient(paths []*gnmipb.Path, prefix *gnmipb.Path) (Client, error)
return nil, err
}
}
if client.origin == "" {
client.origin, err = ParseOrigin(client.origin, paths)
if err != nil {
return nil, err
}
}
if check := IsSupportedOrigin(client.origin); !check {
return nil, status.Errorf(codes.Unimplemented, "Invalid origin: %s", client.origin)
}
if client.origin == "sonic-yang" {
return nil, status.Errorf(codes.Unimplemented, "SONiC Yang Schema is not implemented yet")
}
Expand All @@ -198,7 +165,7 @@ func NewMixedDbClient(paths []*gnmipb.Path, prefix *gnmipb.Path) (Client, error)
}
client.paths = paths
client.workPath = common_utils.GNMI_WORK_PATH
client.applDB = swsscommon.NewDBConnector2(APPL_DB, REDIS_SOCK, SWSS_TIMEOUT)
client.applDB = swsscommon.NewDBConnector(APPL_DB, REDIS_SOCK, SWSS_TIMEOUT)
client.tableMap = map[string]swsscommon.ProducerStateTable{}

return &client, nil
Expand Down Expand Up @@ -1099,7 +1066,7 @@ func (c *MixedDbClient) Capabilities() []gnmipb.ModelData {

func (c *MixedDbClient) Close() error {
for _, pt := range c.tableMap {
pt.Delete()
pt.Del()
}
return nil
}
Expand Down
3 changes: 2 additions & 1 deletion swsscommon/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
SWIG ?= /usr/bin/swig
RM=rm -f

SWIG_FLAG = -c++ -go -intgosize 64
SWIG_FLAG = -go -cgo -c++ -intgosize 64
ifeq ($(CONFIGURED_ARCH),arm64)
SWIG_FLAG += -DSWIGWORDSIZE64
endif
Expand Down
Loading

0 comments on commit 81700b4

Please sign in to comment.