From 3d442efc3a76f962c5b83100bac3e699120b32e0 Mon Sep 17 00:00:00 2001 From: vsuryaprasad-hcl Date: Wed, 22 May 2024 10:39:29 -0400 Subject: [PATCH 1/4] [sdn_tests]: Adding Installation test to pins_ondatra. --- .../pins_ondatra/tests/installation_test.go | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 sdn_tests/pins_ondatra/tests/installation_test.go diff --git a/sdn_tests/pins_ondatra/tests/installation_test.go b/sdn_tests/pins_ondatra/tests/installation_test.go new file mode 100644 index 00000000000..f9349642451 --- /dev/null +++ b/sdn_tests/pins_ondatra/tests/installation_test.go @@ -0,0 +1,33 @@ +package installation_test + +import ( + "testing" + "time" + + syspb "github.com/openconfig/gnoi/system" + "github.com/openconfig/ondatra" + "github.com/sonic-net/sonic-mgmt/sdn_tests/pins_ondatra/infrastructure/binding/pinsbind" + "github.com/sonic-net/sonic-mgmt/sdn_tests/pins_ondatra/infrastructure/testhelper/testhelper" +) + +func TestMain(m *testing.M) { + ondatra.RunTests(m, pinsbind.New) +} + +func TestConfigInstallationSuccess(t *testing.T) { + ttID := "0dedda87-1b76-40a2-8712-24c1572587ee" + defer testhelper.NewTearDownOptions(t).WithID(ttID).Teardown(t) + dut := ondatra.DUT(t, "DUT") + err :=testhelper.ConfigPush(t, dut, nil) + if err != nil { + t.Fatalf("switch config push failed due to err : %v", err) + } + waitTime, err := testhelper.RebootTimeForDevice(t, dut) + if err != nil { + t.Fatalf("Unable to get reboot wait time: %v", err) + } + params := testhelper.NewRebootParams().WithWaitTime(waitTime).WithCheckInterval(30*time.Second).WithRequest(syspb.RebootMethod_COLD).WithLatencyMeasurement(ttID, "gNOI Reboot With Type: "+syspb.RebootMethod_COLD.String()) + if err := testhelper.Reboot(t, dut, params); err != nil { + t.Fatalf("Failed to reboot DUT: %v", err) + } +} From 5eaf255250e4da789c6c5789409823de426ca0e5 Mon Sep 17 00:00:00 2001 From: vsuryaprasad-hcl Date: Wed, 22 May 2024 13:05:07 -0400 Subject: [PATCH 2/4] [sdn_tests]: Adding inband sw interface dual switch test to pins_ondatra. --- .../inband_sw_interface_dual_switch_test.go | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 sdn_tests/pins_ondatra/tests/inband_sw_interface_dual_switch_test.go diff --git a/sdn_tests/pins_ondatra/tests/inband_sw_interface_dual_switch_test.go b/sdn_tests/pins_ondatra/tests/inband_sw_interface_dual_switch_test.go new file mode 100644 index 00000000000..c6e2075a7b2 --- /dev/null +++ b/sdn_tests/pins_ondatra/tests/inband_sw_interface_dual_switch_test.go @@ -0,0 +1,107 @@ +package inband_sw_interface_dual_switch_test + +import ( + "net" + "testing" + "time" + + "github.com/google/gopacket" + "github.com/google/gopacket/layers" + "github.com/openconfig/ondatra" + "github.com/openconfig/ondatra/gnmi" + "github.com/openconfig/ondatra/gnmi/oc" + "github.com/sonic-net/sonic-mgmt/sdn_tests/pins_ondatra/infrastructure/binding/pinsbind" + "github.com/sonic-net/sonic-mgmt/sdn_tests/pins_ondatra/infrastructure/testhelper/testhelper" +) + +// These are the counters we track in these tests. +type counters struct { + inPkts uint64 + outPkts uint64 + inOctets uint64 + outOctets uint64 +} + +var ( + inbandSwIntfName = "Loopback0" + interfaceIndex = uint32(0) + configuredIPv4Path = "6.7.8.9" + configuredIPv4PrefixLength = uint8(32) + configuredIPv6Path = "3000::2" + configuredIPv6PrefixLength = uint8(128) + calledMockConfigPush = false +) + +// readCounters reads all the counters via GNMI and returns a counters struct. +func readCounters(t *testing.T, dut *ondatra.DUTDevice, intf string) *counters { + t.Helper() + cntStruct := gnmi.Get(t, dut, gnmi.OC().Interface(intf).Counters().State()) + return &counters{ + inPkts: cntStruct.GetInPkts(), + outPkts: cntStruct.GetOutPkts(), + inOctets: cntStruct.GetInOctets(), + outOctets: cntStruct.GetOutOctets(), + } +} + +// showCountersDelta shows debug info after an unexpected change in counters. +func showCountersDelta(t *testing.T, before *counters, after *counters, expect *counters) { + t.Helper() + + for _, s := range []struct { + desc string + before, after, expect uint64 + }{ + {"in-pkts", before.inPkts, after.inPkts, expect.inPkts}, + {"out-pkts", before.outPkts, after.outPkts, expect.outPkts}, + {"in-octets", before.inOctets, after.inOctets, expect.inOctets}, + {"out-octets", before.outOctets, after.outOctets, expect.outOctets}, + } { + if s.before != s.after || s.expect != s.before { + t.Logf("%v %d -> %d expected %d (%+d)", s.desc, s.before, s.after, s.expect, s.after-s.before) + } + } +} + +func mockConfigPush(t *testing.T) { + // Performs a mock config push by setting up the loopback0 interface database + // entries and the IPv4 and IPv6 addresses expected to be configured. + // TODO: Remove calls to this function once the helper function + // to perform a default config during setup is available. See b/188927677. + + if calledMockConfigPush { + return + } + + // Create the loopback0 interface. + t.Logf("Config push for %v", inbandSwIntfName) + dut := ondatra.DUT(t, "DUT") + d := &oc.Root{} + + newIface := d.GetOrCreateInterface(inbandSwIntfName) + newIface.Name = &inbandSwIntfName + newIface.Type = oc.IETFInterfaces_InterfaceType_softwareLoopback + gnmi.Replace(t, dut, gnmi.OC().Interface(inbandSwIntfName).Config(), newIface) + + iface := d.GetOrCreateInterface(inbandSwIntfName).GetOrCreateSubinterface(interfaceIndex) + + // Seed an IPv4 address for the loopback0 interface. + t.Logf("Config push for %v/%v", configuredIPv4Path, configuredIPv4PrefixLength) + newV4 := iface.GetOrCreateIpv4().GetOrCreateAddress(configuredIPv4Path) + newV4.Ip = &configuredIPv4Path + newV4.PrefixLength = &configuredIPv4PrefixLength + gnmi.Replace(t, dut, gnmi.OC().Interface(inbandSwIntfName).Subinterface(interfaceIndex).Ipv4().Address(configuredIPv4Path).Config(), newV4) + + gnmi.Await(t, dut, gnmi.OC().Interface(inbandSwIntfName).Subinterface(interfaceIndex).Ipv4().Address(configuredIPv4Path).Ip().State(), 5*time.Second, configuredIPv4Path) + + // Seed an IPv6 address for the loopback0 interface. + t.Logf("Config push for %v/%v", configuredIPv6Path, configuredIPv6PrefixLength) + newV6 := iface.GetOrCreateIpv6().GetOrCreateAddress(configuredIPv6Path) + newV6.Ip = &configuredIPv6Path + newV6.PrefixLength = &configuredIPv6PrefixLength + gnmi.Replace(t, dut, gnmi.OC().Interface(inbandSwIntfName).Subinterface(interfaceIndex).Ipv6().Address(configuredIPv6Path).Config(), newV6) + + gnmi.Await(t, dut, gnmi.OC().Interface(inbandSwIntfName).Subinterface(interfaceIndex).Ipv6().Address(configuredIPv6Path).Ip().State(), 5*time.Second, configuredIPv6Path) + + calledMockConfigPush = true +} From 8537293e05ec796be5b32220ff0002483dcc3808 Mon Sep 17 00:00:00 2001 From: vsuryaprasad-hcl Date: Wed, 22 May 2024 16:02:06 -0400 Subject: [PATCH 3/4] [sdn_tests]: Adding GNMI inband sw interface dual switch LoopbackInCnts test. --- .../inband_sw_interface_dual_switch_test.go | 127 ++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/sdn_tests/pins_ondatra/tests/inband_sw_interface_dual_switch_test.go b/sdn_tests/pins_ondatra/tests/inband_sw_interface_dual_switch_test.go index c6e2075a7b2..d5900128f49 100644 --- a/sdn_tests/pins_ondatra/tests/inband_sw_interface_dual_switch_test.go +++ b/sdn_tests/pins_ondatra/tests/inband_sw_interface_dual_switch_test.go @@ -105,3 +105,130 @@ func mockConfigPush(t *testing.T) { calledMockConfigPush = true } + +// Tests start here. +func TestMain(m *testing.M) { + ondatra.RunTests(m, pinsbind.New) +} + +// TestGNMIInbandSwLoopbackInCnts - Check Loopback0 in-traffic counters +func TestGNMIInbandSwLoopbackInCnts(t *testing.T) { + const ( + pktsPerTry uint64 = 50 + counterUpdateDelay = 1500 * time.Millisecond + packetPayloadSize = 1000 + ) + + // Report results to TestTracker at the end. + defer testhelper.NewTearDownOptions(t).WithID("8e6b32f4-cf39-419f-ba36-db9c778ad317").Teardown(t) + + dut := ondatra.DUT(t, "DUT") + control := ondatra.DUT(t, "CONTROL") + mockConfigPush(t) + + // Select a random front panel interface EthernetX. + params := testhelper.RandomInterfaceParams{ + PortList: []string{ + dut.Port(t, "port1").Name(), + dut.Port(t, "port2").Name(), + dut.Port(t, "port3").Name(), + dut.Port(t, "port4").Name(), + }} + intf, err := testhelper.RandomInterface(t, dut, ¶ms) + if err != nil { + t.Fatalf("Failed to fetch random interface: %v", err) + } + + bad := false + i := 0 + + // Iterate up to 5 times to get a successful test. + for i = 1; i <= 5; i++ { + t.Logf("\n----- TestGNMIInbandSwLoopbackInCnts: Iteration %v -----\n", i) + bad = false + + // Read all the relevant counters initial values. + before := readCounters(t, dut, inbandSwIntfName) + + // Construct packet. + eth := &layers.Ethernet{ + SrcMAC: net.HardwareAddr{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}, + DstMAC: net.HardwareAddr{0x00, 0x1a, 0x11, 0x17, 0x5f, 0x80}, + EthernetType: layers.EthernetTypeIPv4, + } + ip := &layers.IPv4{ + Version: 4, + TTL: 64, + Protocol: layers.IPProtocolTCP, + SrcIP: net.ParseIP("2.2.2.2").To4(), + DstIP: net.ParseIP(configuredIPv4Path).To4(), + } + tcp := &layers.TCP{ + SrcPort: 10000, + DstPort: 22, + Seq: 11050, + } + // Required for checksum computation. + tcp.SetNetworkLayerForChecksum(ip) + + data := make([]byte, packetPayloadSize) + for i := range data { + data[i] = 0xfe + } + payload := gopacket.Payload(data) + + buf := gopacket.NewSerializeBuffer() + + // Enable reconstruction of length and checksum fields based on packet headers. + opts := gopacket.SerializeOptions{ + FixLengths: true, + ComputeChecksums: true, + } + if err := gopacket.SerializeLayers(buf, opts, eth, ip, tcp, payload); err != nil { + t.Fatalf("Failed to serialize packet (%v)", err) + } + + // Compute the expected counters after the test. + expect := before + // Currently, counter increasing is not supported on loopback (b/197764888) + // Uncomment below 2 lines when it becomes supported. + // expect.inPkts += pktsPerTry + // expect.inOctets += pktsPerTry * uint64(len(buf.Bytes())) + + packetOut := &testhelper.PacketOut{ + EgressPort: intf, // or "Ethernet8" for testing + Count: uint(pktsPerTry), + Interval: 1 * time.Millisecond, + Packet: buf.Bytes(), + } + + p4rtClient, err := testhelper.FetchP4RTClient(t, control, control.RawAPIs().P4RT(t), nil) + if err != nil { + t.Fatalf("Failed to create P4RT client: %v", err) + } + if err := p4rtClient.SendPacketOut(t, packetOut); err != nil { + t.Fatalf("SendPacketOut operation failed for %+v (%v)", packetOut, err) + } + + // Sleep for enough time that the counters are polled after the + // transmit completes sending bytes. At 500ms we frequently + // read the counters before they're updated. + time.Sleep(counterUpdateDelay) + + // Read all the relevant counters again. + if after := readCounters(t, dut, inbandSwIntfName); *after != *expect { + showCountersDelta(t, before, after, expect) + bad = true + } + + if !bad { + break + } + } + + if bad { + t.Fatalf("\n\n----- TestGNMIInbandSwLoopbackInCnts: FAILED after %v Iterations -----\n\n", i-1) + } + + t.Logf("\n\n----- TestGNMIInbandSwLoopbackInCnts: SUCCESS after %v Iteration(s) -----\n\n", i) +} From cada2cc139db3dc77c80bd0bdf74cd300fe31cf5 Mon Sep 17 00:00:00 2001 From: vsuryaprasad-hcl Date: Wed, 22 May 2024 16:55:59 -0400 Subject: [PATCH 4/4] [sdn_tests]: Adding GNMI inband sw interface dual switch LoopbackOutCnts test. --- sdn_tests/pins_ondatra/tests/BUILD.bazel | 32 +++++ .../inband_sw_interface_dual_switch_test.go | 121 ++++++++++++++++++ 2 files changed, 153 insertions(+) diff --git a/sdn_tests/pins_ondatra/tests/BUILD.bazel b/sdn_tests/pins_ondatra/tests/BUILD.bazel index 180622d8b5d..f0d1bcd4738 100644 --- a/sdn_tests/pins_ondatra/tests/BUILD.bazel +++ b/sdn_tests/pins_ondatra/tests/BUILD.bazel @@ -105,3 +105,35 @@ ondatra_test_suite( "@com_github_openconfig_ondatra//gnmi/oc", ], ) + +# Installation Test +ondatra_test( + name = "installation_test", + srcs = ["installation_test.go"], + deps = [ + "//infrastructure/binding:pinsbind", + "//infrastructure/testhelper", + "@com_github_openconfig_gnmi//proto/gnmi:gnmi_go_proto", + "@com_github_openconfig_gnoi//system:system_go_proto", + "@com_github_openconfig_ondatra//:go_default_library", + "@com_github_openconfig_ondatra//gnmi", + "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//codes", + "@org_golang_google_grpc//status", + ], +) + +# Inband SW Interface Counter Tests (two switches) +ondatra_test( + name = "inband_sw_interface_dual_switch_test", + srcs = ["inband_sw_interface_dual_switch_test.go"], + deps = [ + "//infrastructure/binding:pinsbind", + "//infrastructure/testhelper", + "@com_github_google_gopacket//:gopacket", + "@com_github_google_gopacket//layers", + "@com_github_openconfig_ondatra//:go_default_library", + "@com_github_openconfig_ondatra//gnmi", + "@com_github_openconfig_ondatra//gnmi/oc", + ], +) diff --git a/sdn_tests/pins_ondatra/tests/inband_sw_interface_dual_switch_test.go b/sdn_tests/pins_ondatra/tests/inband_sw_interface_dual_switch_test.go index d5900128f49..29c720b8fa2 100644 --- a/sdn_tests/pins_ondatra/tests/inband_sw_interface_dual_switch_test.go +++ b/sdn_tests/pins_ondatra/tests/inband_sw_interface_dual_switch_test.go @@ -232,3 +232,124 @@ func TestGNMIInbandSwLoopbackInCnts(t *testing.T) { t.Logf("\n\n----- TestGNMIInbandSwLoopbackInCnts: SUCCESS after %v Iteration(s) -----\n\n", i) } + +// TestGNMIInbandSwLoopbackOutCnts - Check Loopback0 out-traffic counters +func TestGNMIInbandSwLoopbackOutCnts(t *testing.T) { + const ( + pktsPerTry uint64 = 50 + counterUpdateDelay = 1500 * time.Millisecond + packetPayloadSize = 1000 + ) + + // Report results to TestTracker at the end. + defer testhelper.NewTearDownOptions(t).WithID("57fbd43d-eeb3-478d-9740-69d9bb23fca6").Teardown(t) + + dut := ondatra.DUT(t, "DUT") + mockConfigPush(t) + + // Select a random front panel interface EthernetX. + params := testhelper.RandomInterfaceParams{ + PortList: []string{ + dut.Port(t, "port1").Name(), + dut.Port(t, "port2").Name(), + dut.Port(t, "port3").Name(), + dut.Port(t, "port4").Name(), + }} + intf, err := testhelper.RandomInterface(t, dut, ¶ms) + if err != nil { + t.Fatalf("Failed to fetch random interface: %v", err) + } + + bad := false + i := 0 + + // Iterate up to 5 times to get a successful test. + for i = 1; i <= 5; i++ { + t.Logf("\n----- TestGNMIInbandSwLoopbackOutCnts: Iteration %v -----\n", i) + bad = false + + // Read all the relevant counters initial values. + before := readCounters(t, dut, inbandSwIntfName) + + // Construct packet. + eth := &layers.Ethernet{ + SrcMAC: net.HardwareAddr{0x00, 0x11, 0x22, 0x66, 0x77, 0x88}, + DstMAC: net.HardwareAddr{0x00, 0x1a, 0x11, 0x17, 0x5f, 0x80}, + EthernetType: layers.EthernetTypeIPv4, + } + ip := &layers.IPv4{ + Version: 4, + TTL: 64, + Protocol: layers.IPProtocolTCP, + SrcIP: net.ParseIP(configuredIPv4Path).To4(), + DstIP: net.ParseIP("2.2.2.2").To4(), + } + tcp := &layers.TCP{ + SrcPort: 10000, + DstPort: 22, + Seq: 11050, + } + // Required for checksum computation. + tcp.SetNetworkLayerForChecksum(ip) + + data := make([]byte, packetPayloadSize) + for i := range data { + data[i] = 0xfe + } + payload := gopacket.Payload(data) + + buf := gopacket.NewSerializeBuffer() + + // Enable reconstruction of length and checksum fields based on packet headers. + opts := gopacket.SerializeOptions{ + FixLengths: true, + ComputeChecksums: true, + } + if err := gopacket.SerializeLayers(buf, opts, eth, ip, tcp, payload); err != nil { + t.Fatalf("Failed to serialize packet (%v)", err) + } + + // Compute the expected counters after the test. + expect := before + // Currently, counter increasing is not supported on loopback (b/197764888) + // Uncomment below 2 lines when it becomes supported. + // expect.inPkts += pktsPerTry + // expect.inOctets += pktsPerTry * uint64(len(buf.Bytes())) + + packetOut := &testhelper.PacketOut{ + EgressPort: intf, // or "Ethernet8" for testing + Count: uint(pktsPerTry), + Interval: 1 * time.Millisecond, + Packet: buf.Bytes(), + } + + p4rtClient, err := testhelper.FetchP4RTClient(t, dut, dut.RawAPIs().P4RT(t), nil) + if err != nil { + t.Fatalf("Failed to create P4RT client: %v", err) + } + if err := p4rtClient.SendPacketOut(t, packetOut); err != nil { + t.Fatalf("SendPacketOut operation failed for %+v (%v)", packetOut, err) + } + + // Sleep for enough time that the counters are polled after the + // transmit completes sending bytes. At 500ms we frequently + // read the counters before they're updated. + time.Sleep(counterUpdateDelay) + + // Read all the relevant counters again. + if after := readCounters(t, dut, inbandSwIntfName); *after != *expect { + showCountersDelta(t, before, after, expect) + bad = true + } + + if !bad { + break + } + } + + if bad { + t.Fatalf("\n\n----- TestGNMIInbandSwLoopbackOutCnts: FAILED after %v Iterations -----\n\n", i-1) + } + + t.Logf("\n\n----- TestGNMIInbandSwLoopbackOutCnts: SUCCESS after %v Iteration(s) -----\n\n", i) +}