Skip to content
Merged
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
10 changes: 8 additions & 2 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1062,7 +1062,10 @@ func TestGet(t *testing.T) {
t.Fatalf("cannot load TLS credentials, got err: %v", err)
}
srv := grpc.NewServer(grpc.Creds(creds))
s := server.NewFake(server.DisableRIBCheckFn())
s, err := server.NewFake(server.DisableRIBCheckFn())
if err != nil {
t.Fatalf("cannot create server, error: %v", err)
}

s.InjectRIB(nr)

Expand Down Expand Up @@ -1314,9 +1317,12 @@ func TestFlush(t *testing.T) {
t.Fatalf("cannot load TLS credentials, got err: %v", err)
}
srv := grpc.NewServer(grpc.Creds(creds))
s := server.NewFake(
s, err := server.NewFake(
server.DisableRIBCheckFn(),
)
if err != nil {
t.Fatalf("cannot create server, error: %v", err)
}

s.InjectRIB(rib.New(server.DefaultNetworkInstanceName))
if tt.inRIB != nil {
Expand Down
28 changes: 19 additions & 9 deletions compliance/compliance.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,30 @@ func SetElectionID(v uint64) {
electionID.Store(v)
}

// defaultNetworkInstance name is the string name of the default network instance
// on the server. It can be overridden by tests that have pushed a configuration
// to a server where they have specified a value for the default network instance.
var defaultNetworkInstanceName = server.DefaultNetworkInstanceName
var (
// defaultNetworkInstance name is the string name of the default network instance
// on the server. It can be overridden by tests that have pushed a configuration
// to a server where they have specified a value for the default network instance.
defaultNetworkInstanceName = server.DefaultNetworkInstanceName

// vrfName is a name of a non-default VRF that exists on the server. It can be
// overriden by tests that have pushed a configuration to the server where they
// have created a name that is not the specified string.
vrfName = "NON-DEFAULT-VRF"
)

// SetDefaultNetworkInstanceName allows an external caler to specify a network
// SetDefaultNetworkInstanceName allows an external caller to specify a network
// instance name to be used for the default network instance.
func SetDefaultNetworkInstanceName(n string) {
defaultNetworkInstanceName = n
}

// SetNonDefaultVRFName allows an external caller to specify a network-instance
// name to be used as a non-default Layer 3 VRF.
func SetNonDefaultVRFName(n string) {
vrfName = n
}

// Test describes a test within the compliance library.
type Test struct {
// Fn is the function to be run for a test. Tests must not error if additional
Expand Down Expand Up @@ -596,15 +609,12 @@ func AddIPv4Metadata(c *fluent.GRIBIClient, t testing.TB, _ ...TestOpt) {
// AddIPv4EntryDifferentNINHG adds an IPv4 entry that references a next-hop-group within a
// different network instance, and validates that the entry is successfully installed.
func AddIPv4EntryDifferentNINHG(c *fluent.GRIBIClient, wantACK fluent.ProgrammingResult, t testing.TB, _ ...TestOpt) {
// TODO(robjs): Server needs to be initialised with >1 VRF.
t.Skip()

defer flushServer(c, t)
ops := []func(){
func() {
c.Modify().AddEntry(t, fluent.IPv4Entry().
WithPrefix("1.1.1.1/32").
WithNetworkInstance("NON-DEFAULT").
WithNetworkInstance(vrfName).
WithNextHopGroup(1).
WithNextHopGroupNetworkInstance(defaultNetworkInstanceName))
c.Modify().AddEntry(t, fluent.NextHopGroupEntry().WithID(1).AddNextHop(1, 1))
Expand Down
13 changes: 12 additions & 1 deletion compliance/compliance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ import (
"github.com/openconfig/gribigo/device"
"github.com/openconfig/gribigo/fluent"
"github.com/openconfig/gribigo/negtest"
"github.com/openconfig/gribigo/ocrt"
"github.com/openconfig/gribigo/server"
"github.com/openconfig/gribigo/testcommon"
"github.com/openconfig/ygot/ygot"
)

func TestCompliance(t *testing.T) {
Expand All @@ -35,8 +38,16 @@ func TestCompliance(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())

defer cancel()
d, err := device.New(ctx, creds)

cfg := &ocrt.Device{}
cfg.GetOrCreateNetworkInstance(server.DefaultNetworkInstanceName).Type = ocrt.NetworkInstanceTypes_NETWORK_INSTANCE_TYPE_DEFAULT_INSTANCE
cfg.GetOrCreateNetworkInstance(vrfName).Type = ocrt.NetworkInstanceTypes_NETWORK_INSTANCE_TYPE_L3VRF
jsonConfig, err := ygot.Marshal7951(cfg)
if err != nil {
t.Fatalf("cannot create configuration for device, error: %v", err)
}

d, err := device.New(ctx, creds, device.DeviceConfig(jsonConfig))
if err != nil {
t.Fatalf("cannot start server, %v", err)
}
Expand Down
4 changes: 0 additions & 4 deletions compliance/flush.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,8 @@ func FlushFromNonMasterDefaultNI(c *fluent.GRIBIClient, wantACK fluent.Programmi
// L3VRF. It subsequently issues a Flush RPC and ensures that entries that are within the
// flushed network instance (the default) are removed, but the others are preserved.
func FlushOfSpecificNI(c *fluent.GRIBIClient, wantACK fluent.ProgrammingResult, t testing.TB, _ ...TestOpt) {
// TODO(robjs): we need to initialise the server with >1 network instance.
t.Skip()
defer flushServer(c, t)

vrfName := "TEST-VRF"

addFlushEntriesToNI(c, defaultNetworkInstanceName, wantACK, t)
addFlushEntriesToNI(c, vrfName, wantACK, t)

Expand Down
36 changes: 23 additions & 13 deletions device/device.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,23 +142,29 @@ func New(ctx context.Context, opts ...DevOpt) (*Device, error) {
d := &Device{}

jcfg := optDeviceCfg(opts)
dev := &ocrt.Device{}
switch jcfg {
case nil:
dev := &ocrt.Device{}
dev.GetOrCreateNetworkInstance("DEFAULT").Type = ocrt.NetworkInstanceTypes_NETWORK_INSTANCE_TYPE_DEFAULT_INSTANCE
sr, err := sysrib.NewSysRIB(dev)
if err != nil {
return nil, fmt.Errorf("cannot build system RIB, %v", err)
}
d.sysRIB = sr
dev.GetOrCreateNetworkInstance(server.DefaultNetworkInstanceName).Type = ocrt.NetworkInstanceTypes_NETWORK_INSTANCE_TYPE_DEFAULT_INSTANCE
default:
sr, err := sysrib.NewSysRIBFromJSON(jcfg)
if err != nil {
return nil, fmt.Errorf("cannot build system RIB, %v", err)
if err := ocrt.Unmarshal(jcfg, dev); err != nil {
return nil, fmt.Errorf("cannot unmarshal JSON configuration, %v", err)
}
d.sysRIB = sr
}

networkInstances := []string{}
for name, ni := range dev.NetworkInstance {
if ni.Type == ocrt.NetworkInstanceTypes_NETWORK_INSTANCE_TYPE_L3VRF {
networkInstances = append(networkInstances, name)
}
}

sr, err := sysrib.NewSysRIB(dev)
if err != nil {
return nil, fmt.Errorf("cannot build system RIB, %v", err)
}
d.sysRIB = sr

ribHookfn := func(o constants.OpType, ts int64, ni string, data ygot.GoStruct) {
_, _, _ = o, ni, data
// write gNMI notifications
Expand Down Expand Up @@ -215,6 +221,7 @@ func New(ctx context.Context, opts ...DevOpt) (*Device, error) {
gRIBIStop, err := d.startgRIBI(ctx, gr.host, gr.port, creds,
server.WithPostChangeRIBHook(ribHookfn),
server.WithRIBResolvedEntryHook(ribAddfn),
server.WithVRFs(networkInstances),
)
if err != nil {
return nil, fmt.Errorf("cannot start gRIBI server, %v", err)
Expand Down Expand Up @@ -282,11 +289,14 @@ func optTLSCreds(opts []DevOpt) *tlsCreds {
func (d *Device) startgRIBI(ctx context.Context, host string, port int, creds *tlsCreds, opt ...server.ServerOpt) (func(), error) {
l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", host, port))
if err != nil {
return nil, fmt.Errorf("cannot create gRIBI server, %v", err)
return nil, fmt.Errorf("cannot create gRPC server for gRIBI, %v", err)
}

s := grpc.NewServer(grpc.Creds(creds.c))
ts := server.New(opt...)
ts, err := server.New(opt...)
if err != nil {
return nil, fmt.Errorf("cannot create gRIBI server, %v", err)
}
spb.RegisterGRIBIServer(s, ts)
d.gribiAddr = l.Addr().String()
d.gribiSrv = ts
Expand Down
50 changes: 43 additions & 7 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,10 @@ func DisableRIBCheckFn() *disableCheckFn { return &disableCheckFn{} }
// disableCheckFn is the internal implementation of DisableRIBCheckFn.
type disableCheckFn struct{}

// isRIBOpt implements the RIBOpt interface
// isServerOpt implements the ServerOpt interface
func (*disableCheckFn) isServerOpt() {}

// hasDisableCheckFn checks whether the RIBOpt slice supplied contains the
// hasDisableCheckFn checks whether the ServerOpt slice supplied contains the
// disableCheckFn option.
func hasDisableCheckFn(opt []ServerOpt) bool {
for _, o := range opt {
Expand All @@ -212,8 +212,33 @@ func hasDisableCheckFn(opt []ServerOpt) bool {
return false
}

// WithVRFs specifies that the server should be initialised with the L3VRF
// network instances specified in the names list. Each is created in the
// server's RIB such that it can be referenced.
func WithVRFs(names []string) *withVRFs { return &withVRFs{names: names} }

// withVRFs is the internal implementation of WithVRFs that can be read by the
// server.
type withVRFs struct {
names []string
}

// isServerOpt implements the ServerOpt interface.
func (*withVRFs) isServerOpt() {}

// hasWithVRFs checks whether the ServerOpt slice supplied contains the withVRFs
// option and returns it if so.
func hasWithVRFs(opt []ServerOpt) []string {
for _, o := range opt {
if v, ok := o.(*withVRFs); ok {
return v.names
}
}
return nil
}

// New creates a new gRIBI server.
func New(opt ...ServerOpt) *Server {
func New(opt ...ServerOpt) (*Server, error) {
ribOpt := []rib.RIBOpt{}
if hasDisableCheckFn(opt) {
ribOpt = append(ribOpt, rib.DisableRIBCheckFn())
Expand All @@ -234,7 +259,15 @@ func New(opt ...ServerOpt) *Server {
s.masterRIB.SetResolvedEntryHook(v.fn)
}

return s
if vrfs := hasWithVRFs(opt); vrfs != nil {
for _, n := range vrfs {
if err := s.masterRIB.AddNetworkInstance(n); err != nil {
return nil, fmt.Errorf("cannot create network instance %s, %v", n, err)
}
}
}

return s, nil
}

// Modify implements the gRIBI Modify RPC.
Expand Down Expand Up @@ -1054,9 +1087,12 @@ type FakeServer struct {
// NewFake returns a new version of the fake server. This implementation wraps
// the Server implementation with functions to insert specific state into
// the server without a need to use the public APIs.
func NewFake(opt ...ServerOpt) *FakeServer {
s := New(opt...)
return &FakeServer{Server: s}
func NewFake(opt ...ServerOpt) (*FakeServer, error) {
s, err := New(opt...)
if err != nil {
return nil, err
}
return &FakeServer{Server: s}, nil
}

// InjectRIB allows a client to inject a RIB into the server as though it was
Expand Down
Loading