Skip to content

Commit

Permalink
Add example saipb test that uses the local bind (#349)
Browse files Browse the repository at this point in the history
* sai test

* more fixes

* fix
  • Loading branch information
DanG100 authored Jan 25, 2024
1 parent 10f2aa1 commit 728dc7e
Show file tree
Hide file tree
Showing 4 changed files with 226 additions and 5 deletions.
7 changes: 7 additions & 0 deletions integration_tests/dataplane/basictraffic/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@ go_test(
srcs = ["basic_traffic_test.go"],
data = [":testbed.pb.txt"],
deps = [
"//dataplane/proto/sai",
"//internal/attrs",
"//internal/binding",
"@com_github_open_traffic_generator_snappi_gosnappi//:gosnappi",
"@com_github_openconfig_ondatra//:ondatra",
"@com_github_openconfig_ondatra//binding",
"@com_github_openconfig_ondatra//gnmi",
"@org_golang_google_grpc//:go_default_library",
"@org_golang_google_protobuf//proto",
],
)
200 changes: 198 additions & 2 deletions integration_tests/dataplane/basictraffic/basic_traffic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,214 @@
package basictraffic

import (
"context"
"strconv"
"testing"
"time"

"github.com/open-traffic-generator/snappi/gosnappi"
"github.com/openconfig/ondatra"
"github.com/openconfig/ondatra/gnmi"
"google.golang.org/grpc"
"google.golang.org/protobuf/proto"

"github.com/openconfig/lemming/internal/attrs"
"github.com/openconfig/lemming/internal/binding"

obind "github.com/openconfig/ondatra/binding"

saipb "github.com/openconfig/lemming/dataplane/proto/sai"
)

const (
ipv4PrefixLen = 30
ateDstNetCIDR = "198.51.100.0/24"
ateIndirectNH = "203.0.113.1"
ateIndirectNHCIDR = ateIndirectNH + "/32"
nhIndex = 1
nhgIndex = 42
nhIndex2 = 2
nhgIndex2 = 52
nhIndex3 = 3
nhgIndex3 = 62
defaultNetworkInstance = "DEFAULT"
)

var (
dutPort1 = attrs.Attributes{
Desc: "dutPort1",
IPv4: "192.0.2.1",
IPv4Len: ipv4PrefixLen,
}

atePort1 = attrs.Attributes{
Name: "port1",
MAC: "02:00:01:01:01:01",
IPv4: "192.0.2.2",
IPv4Len: ipv4PrefixLen,
}

dutPort2 = attrs.Attributes{
Desc: "dutPort2",
IPv4: "192.0.2.5",
IPv4Len: ipv4PrefixLen,
}

atePort2 = attrs.Attributes{
Name: "port2",
MAC: "02:00:02:01:01:01",
IPv4: "192.0.2.6",
IPv4Len: ipv4PrefixLen,
}
)

func TestMain(m *testing.M) {
ondatra.RunTests(m, binding.Local("."))
}

func dataplaneConn(t testing.TB, dut *ondatra.DUTDevice) *grpc.ClientConn {
t.Helper()
var lemming interface {
DataplaneConn(ctx context.Context, opts ...grpc.DialOption) (*grpc.ClientConn, error)
}
if err := obind.DUTAs(dut.RawAPIs().BindingDUT(), &lemming); err != nil {
t.Fatalf("failed to get lemming dut: %v", err)
}
conn, err := lemming.DataplaneConn(context.Background())
if err != nil {
t.Fatal(err)
}
return conn
}

func configureDUT(t testing.TB, dut *ondatra.DUTDevice) {
t.Helper()
conn := dataplaneConn(t, dut)
ric := saipb.NewRouterInterfaceClient(conn)
port1ID, err := strconv.ParseUint(dut.Port(t, "port1").Name(), 10, 64)
if err != nil {
t.Fatal(err)
}
port2ID, err := strconv.ParseUint(dut.Port(t, "port2").Name(), 10, 64)
if err != nil {
t.Fatal(err)
}

_, err = ric.CreateRouterInterface(context.Background(), &saipb.CreateRouterInterfaceRequest{
Switch: 1,
PortId: proto.Uint64(port1ID),
Type: saipb.RouterInterfaceType_ROUTER_INTERFACE_TYPE_PORT.Enum(),
SrcMacAddress: []byte{10, 10, 10, 10, 10, 10},
})
if err != nil {
t.Fatal(err)
}
rif2Resp, err := ric.CreateRouterInterface(context.Background(), &saipb.CreateRouterInterfaceRequest{
Switch: 1,
PortId: proto.Uint64(port2ID),
Type: saipb.RouterInterfaceType_ROUTER_INTERFACE_TYPE_PORT.Enum(),
SrcMacAddress: []byte{10, 10, 10, 10, 10, 11},
})
if err != nil {
t.Fatal(err)
}

rc := saipb.NewRouteClient(conn)
_, err = rc.CreateRouteEntry(context.Background(), &saipb.CreateRouteEntryRequest{
Entry: &saipb.RouteEntry{
SwitchId: 1,
VrId: 0,
Destination: &saipb.IpPrefix{
Addr: []byte{192, 0, 2, 6},
Mask: []byte{255, 255, 255, 255},
},
},
PacketAction: saipb.PacketAction_PACKET_ACTION_FORWARD.Enum(),
NextHopId: &rif2Resp.Oid,
})
if err != nil {
t.Fatal(err)
}

nc := saipb.NewNeighborClient(conn)
_, err = nc.CreateNeighborEntry(context.Background(), &saipb.CreateNeighborEntryRequest{
Entry: &saipb.NeighborEntry{
SwitchId: 1,
RifId: rif2Resp.Oid,
IpAddress: []byte{192, 0, 2, 6},
},
DstMacAddress: []byte{0o2, 0o0, 0o2, 0o1, 0o1, 0o1},
})
if err != nil {
t.Fatal(err)
}
}

func TestTraffic(t *testing.T) {
ondatra.DUT(t, "dut")
ondatra.DUT(t, "dut2")
ate := ondatra.ATE(t, "ate")
ateTop := configureATE(t, ate)
ate.OTG().PushConfig(t, ateTop)
ate.OTG().StartProtocols(t)

dut := ondatra.DUT(t, "dut")
configureDUT(t, dut)

loss := testTraffic(t, ate, ateTop, atePort1, atePort2, 10*time.Second)
if loss > 1 {
t.Errorf("loss %f, greater than 1", loss)
}
}

// configureATE configures port1 and port2 on the ATE.
func configureATE(t *testing.T, ate *ondatra.ATEDevice) gosnappi.Config {
top := gosnappi.NewConfig()

p1 := ate.Port(t, "port1")
p2 := ate.Port(t, "port2")

atePort1.AddToOTG(top, p1, &dutPort1)
atePort2.AddToOTG(top, p2, &dutPort2)
return top
}

// testTraffic generates traffic flow from source network to
// destination network via srcEndPoint to dstEndPoint and checks for
// packet loss and returns loss percentage as float.
func testTraffic(t *testing.T, ate *ondatra.ATEDevice, top gosnappi.Config, srcEndPoint, dstEndPoint attrs.Attributes, dur time.Duration) float32 {
otg := ate.OTG()
top.Flows().Clear().Items()

ipFLow := top.Flows().Add().SetName("Flow")
ipFLow.Metrics().SetEnable(true)
ipFLow.TxRx().Port().SetTxName(srcEndPoint.Name).SetRxNames([]string{dstEndPoint.Name})

ipFLow.Rate().SetPps(10)

// OTG specifies that the order of the <flow>.Packet().Add() calls determines
// the stack of headers that are to be used, starting at the outer-most and
// ending with the inner-most.

// Set up ethernet layer.
eth := ipFLow.Packet().Add().Ethernet()
eth.Src().SetValue(srcEndPoint.MAC)
eth.Dst().SetValue(dstEndPoint.MAC)

ip4 := ipFLow.Packet().Add().Ipv4()
ip4.Src().SetValue(srcEndPoint.IPv4)
ip4.Dst().SetValue(dstEndPoint.IPv4)
ip4.Version().SetValue(4)

otg.PushConfig(t, top)

otg.StartTraffic(t)
time.Sleep(dur)
t.Logf("Stop traffic")
otg.StopTraffic(t)

time.Sleep(5 * time.Second)

txPkts := gnmi.Get(t, otg, gnmi.OTG().Flow("Flow").Counters().OutPkts().State())
rxPkts := gnmi.Get(t, otg, gnmi.OTG().Flow("Flow").Counters().InPkts().State())
lossPct := (txPkts - rxPkts) * 100 / txPkts
return float32(lossPct)
}
17 changes: 14 additions & 3 deletions integration_tests/dataplane/basictraffic/testbed.pb.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,27 @@ duts {
ports {
id: "port1"
}
ports {
id: "port2"
}
}

duts {
id: "dut2"
ates {
id: "ate"
ports {
id: "port1"
}
ports {
id: "port2"
}
}

links {
a: "dut:port1"
b: "dut2:port1"
b: "ate:port1"
}

links {
a: "dut:port2"
b: "ate:port2"
}
7 changes: 7 additions & 0 deletions internal/binding/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,12 @@ func (l *localLemming) DialGRIBI(ctx context.Context, opts ...grpc.DialOption) (
return grpb.NewGRIBIClient(conn), nil
}

// DataplaneConn returns a gRPC conn for the dataplane
func (l *localLemming) DataplaneConn(ctx context.Context, opts ...grpc.DialOption) (*grpc.ClientConn, error) {
opts = append(opts, grpc.WithTransportCredentials(local.NewCredentials()))
return grpc.DialContext(ctx, net.JoinHostPort(l.addr, fmt.Sprint(dataplanePort)), opts...)
}

type localMagna struct {
binding.AbstractATE
addr string
Expand Down Expand Up @@ -278,6 +284,7 @@ func (lb *LocalBind) createDUT(ctx context.Context, dut *opb.Device, portMgr *du
}
boundLemming := &localLemming{
l: l,
addr: addr,
dutID: dutID,
AbstractDUT: binding.AbstractDUT{
Dims: &binding.Dims{
Expand Down

0 comments on commit 728dc7e

Please sign in to comment.