From f976bca215e4e699f3abf0865aa37c35d1081fe2 Mon Sep 17 00:00:00 2001 From: Nisha Sadhasivam Date: Tue, 21 Jan 2025 12:26:40 +0000 Subject: [PATCH 1/9] Update gnoi linkqual FNT test to use an aggregate interface --- .../packet_link_qualification_test.go | 156 ++++++++++++++++-- 1 file changed, 142 insertions(+), 14 deletions(-) diff --git a/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go b/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go index 3da68cc1db0..48ac0f4d02f 100644 --- a/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go +++ b/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go @@ -16,6 +16,7 @@ package packet_link_qualification_test import ( "context" + "fmt" "math" "testing" "time" @@ -27,6 +28,7 @@ import ( "github.com/openconfig/ondatra" "github.com/openconfig/ondatra/gnmi" "github.com/openconfig/ondatra/gnmi/oc" + "github.com/openconfig/ondatra/netutil" "github.com/openconfig/ygot/ygot" "google.golang.org/protobuf/types/known/durationpb" ) @@ -44,9 +46,28 @@ func TestMain(m *testing.M) { // https://github.com/fullstorydev/grpcurl // +type aggPortData struct { + dut1IPv4 string + dut2IPv4 string + ateAggName string + aggPortIDDUT1 uint32 + aggPortIDDUT2 uint32 +} + +const ( + ipv4PLen = 30 +) + var ( minRequiredGeneratorMTU = uint64(8184) minRequiredGeneratorPPS = uint64(1e8) + agg1 = &aggPortData{ + dut1IPv4: "192.0.2.1", + dut2IPv4: "192.0.2.2", + ateAggName: "lag3", + aggPortIDDUT1: 10, + aggPortIDDUT2: 11, + } ) func TestCapabilitiesResponse(t *testing.T) { @@ -224,25 +245,89 @@ func configInterfaceMTU(i *oc.Interface, dut *ondatra.DUTDevice) *oc.Interface { return i } -func TestLinkQualification(t *testing.T) { - dut1 := ondatra.DUT(t, "dut1") - dut2 := ondatra.DUT(t, "dut2") - - dp1 := dut1.Port(t, "port1") - dp2 := dut2.Port(t, "port1") - t.Logf("dut1: %v, dut2: %v", dut1.Name(), dut2.Name()) - t.Logf("dut1 dp1 name: %v, dut2 dp2 name : %v", dp1.Name(), dp2.Name()) +// configures DUT1 lagID <-----> lagID DUT2 with 1 member link. +func configureDUTAggregate(t *testing.T, dut1 *ondatra.DUTDevice, dut2 *ondatra.DUTDevice) { + t.Helper() + fptest.ConfigureDefaultNetworkInstance(t, dut1) + fptest.ConfigureDefaultNetworkInstance(t, dut2) + var aggIDsDUT1 []string + var aggIDsDUT2 []string for _, dut := range []*ondatra.DUTDevice{dut1, dut2} { - d := gnmi.OC() - p := dut.Port(t, "port1") - i := &oc.Interface{Name: ygot.String(p.Name())} - gnmi.Replace(t, dut, d.Interface(p.Name()).Config(), configInterfaceMTU(i, dut)) - if deviations.ExplicitPortSpeed(dut) { - fptest.SetPortSpeed(t, p) + b := &gnmi.SetBatch{} + d := &oc.Root{} + var aggIDs []string + aggID := netutil.NextAggregateInterface(t, dut) + aggIDs = append(aggIDs, aggID) + + agg := d.GetOrCreateInterface(aggID) + agg.GetOrCreateAggregation().LagType = oc.IfAggregate_AggregationType_STATIC + agg.Type = oc.IETFInterfaces_InterfaceType_ieee8023adLag + agg.Description = ygot.String(agg1.ateAggName) + if !deviations.OmitL2MTU(dut) { + agg.Mtu = ygot.Uint16(9000) + } + if deviations.InterfaceEnabled(dut) { + agg.Enabled = ygot.Bool(true) + } + + s := agg.GetOrCreateSubinterface(0) + s4 := s.GetOrCreateIpv4() + if deviations.InterfaceEnabled(dut) { + s4.Enabled = ygot.Bool(true) + } + var a4 *oc.Interface_Subinterface_Ipv4_Address + if dut == dut1 { + a4 = s4.GetOrCreateAddress(agg1.dut1IPv4) + aggIDsDUT1 = append(aggIDsDUT1, aggID) + } else { + a4 = s4.GetOrCreateAddress(agg1.dut2IPv4) + aggIDsDUT2 = append(aggIDsDUT2, aggID) + } + a4.PrefixLength = ygot.Uint8(ipv4PLen) + + gnmi.BatchDelete(b, gnmi.OC().Interface(aggID).Aggregation().MinLinks().Config()) + gnmi.BatchReplace(b, gnmi.OC().Interface(aggID).Config(), agg) + + p1 := dut.Port(t, "port1") + for _, port := range []*ondatra.Port{p1} { + gnmi.BatchDelete(b, gnmi.OC().Interface(port.Name()).Ethernet().AggregateId().Config()) + i := d.GetOrCreateInterface(port.Name()) + if dut == dut1 { + i.Id = ygot.Uint32(agg1.aggPortIDDUT1) + } else { + i.Id = ygot.Uint32(agg1.aggPortIDDUT2) + } + i.Description = ygot.String(fmt.Sprintf("LAG - Member -%s", port.Name())) + e := i.GetOrCreateEthernet() + e.AggregateId = ygot.String(aggID) + i.Type = oc.IETFInterfaces_InterfaceType_ethernetCsmacd + + if deviations.InterfaceEnabled(dut) { + i.Enabled = ygot.Bool(true) + } + gnmi.BatchReplace(b, gnmi.OC().Interface(port.Name()).Config(), i) + } + + b.Set(t, dut) + + if deviations.ExplicitInterfaceInDefaultVRF(dut) { + for _, aggID := range aggIDs { + fptest.AssignToNetworkInstance(t, dut, aggID, deviations.DefaultNetworkInstance(dut), 0) + } } } + // Wait for LAG interfaces to be UP + for _, aggID := range aggIDsDUT1 { + gnmi.Await(t, dut1, gnmi.OC().Interface(aggID).AdminStatus().State(), 60*time.Second, oc.Interface_AdminStatus_UP) + } + for _, aggID := range aggIDsDUT2 { + gnmi.Await(t, dut2, gnmi.OC().Interface(aggID).AdminStatus().State(), 60*time.Second, oc.Interface_AdminStatus_UP) + } +} + +func testLinkQualification(t *testing.T, dut1 *ondatra.DUTDevice, dut2 *ondatra.DUTDevice, dp1 *ondatra.Port, dp2 *ondatra.Port) { plqID := dut1.Name() + ":" + dp1.Name() + "<->" + dut2.Name() + ":" + dp2.Name() if deviations.PLQGeneratorCapabilitiesMaxMTU(dut1) != 0 { @@ -452,3 +537,46 @@ func TestLinkQualification(t *testing.T) { } } } + +func TestLinkQualification(t *testing.T) { + dut1 := ondatra.DUT(t, "dut1") + dut2 := ondatra.DUT(t, "dut2") + + dp1 := dut1.Port(t, "port1") + dp2 := dut2.Port(t, "port1") + t.Logf("dut1: %v, dut2: %v", dut1.Name(), dut2.Name()) + t.Logf("dut1 dp1 name: %v, dut2 dp2 name : %v", dp1.Name(), dp2.Name()) + + for _, dut := range []*ondatra.DUTDevice{dut1, dut2} { + d := gnmi.OC() + p := dut.Port(t, "port1") + i := &oc.Interface{Name: ygot.String(p.Name())} + gnmi.Replace(t, dut, d.Interface(p.Name()).Config(), configInterfaceMTU(i, dut)) + if deviations.ExplicitPortSpeed(dut) { + fptest.SetPortSpeed(t, p) + } + } + + cases := []struct { + desc string + testFunc func(t *testing.T, dut1 *ondatra.DUTDevice, dut2 *ondatra.DUTDevice, dp1 *ondatra.Port, dp2 *ondatra.Port) + aggregate bool + }{{ + desc: "Singleton Interface LinkQualification", + testFunc: testLinkQualification, + aggregate: false, + }, { + desc: "Member Link LinkQualification", + testFunc: testLinkQualification, + aggregate: true, + }} + + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + if tc.aggregate { + configureDUTAggregate(t, dut1, dut2) + } + tc.testFunc(t, dut1, dut2, dp1, dp2) + }) + } +} From 59961b371db20be84a8a1a4ee79faf6a00d695cc Mon Sep 17 00:00:00 2001 From: Nisha Sadhasivam Date: Thu, 23 Jan 2025 08:54:11 +0000 Subject: [PATCH 2/9] addressing review comments --- .../packet_link_qualification_test.go | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go b/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go index 48ac0f4d02f..7676bb291da 100644 --- a/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go +++ b/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go @@ -38,7 +38,7 @@ func TestMain(m *testing.M) { } // Topology: -// dut1:port1 <--> port1:dut2 +// dut1:port1 <--> port1:dut2 (port1 as singleton and memberlink) // // Test notes: // @@ -250,15 +250,13 @@ func configureDUTAggregate(t *testing.T, dut1 *ondatra.DUTDevice, dut2 *ondatra. t.Helper() fptest.ConfigureDefaultNetworkInstance(t, dut1) fptest.ConfigureDefaultNetworkInstance(t, dut2) - var aggIDsDUT1 []string - var aggIDsDUT2 []string + var aggIdDut1 string + var aggIdDut2 string for _, dut := range []*ondatra.DUTDevice{dut1, dut2} { b := &gnmi.SetBatch{} d := &oc.Root{} - var aggIDs []string aggID := netutil.NextAggregateInterface(t, dut) - aggIDs = append(aggIDs, aggID) agg := d.GetOrCreateInterface(aggID) agg.GetOrCreateAggregation().LagType = oc.IfAggregate_AggregationType_STATIC @@ -279,10 +277,10 @@ func configureDUTAggregate(t *testing.T, dut1 *ondatra.DUTDevice, dut2 *ondatra. var a4 *oc.Interface_Subinterface_Ipv4_Address if dut == dut1 { a4 = s4.GetOrCreateAddress(agg1.dut1IPv4) - aggIDsDUT1 = append(aggIDsDUT1, aggID) + aggIdDut1 = aggID } else { a4 = s4.GetOrCreateAddress(agg1.dut2IPv4) - aggIDsDUT2 = append(aggIDsDUT2, aggID) + aggIdDut2 = aggID } a4.PrefixLength = ygot.Uint8(ipv4PLen) @@ -312,23 +310,16 @@ func configureDUTAggregate(t *testing.T, dut1 *ondatra.DUTDevice, dut2 *ondatra. b.Set(t, dut) if deviations.ExplicitInterfaceInDefaultVRF(dut) { - for _, aggID := range aggIDs { - fptest.AssignToNetworkInstance(t, dut, aggID, deviations.DefaultNetworkInstance(dut), 0) - } + fptest.AssignToNetworkInstance(t, dut, aggID, deviations.DefaultNetworkInstance(dut), 0) } } // Wait for LAG interfaces to be UP - for _, aggID := range aggIDsDUT1 { - gnmi.Await(t, dut1, gnmi.OC().Interface(aggID).AdminStatus().State(), 60*time.Second, oc.Interface_AdminStatus_UP) - } + gnmi.Await(t, dut1, gnmi.OC().Interface(aggIdDut1).AdminStatus().State(), 60*time.Second, oc.Interface_AdminStatus_UP) - for _, aggID := range aggIDsDUT2 { - gnmi.Await(t, dut2, gnmi.OC().Interface(aggID).AdminStatus().State(), 60*time.Second, oc.Interface_AdminStatus_UP) - } + gnmi.Await(t, dut2, gnmi.OC().Interface(aggIdDut2).AdminStatus().State(), 60*time.Second, oc.Interface_AdminStatus_UP) } func testLinkQualification(t *testing.T, dut1 *ondatra.DUTDevice, dut2 *ondatra.DUTDevice, dp1 *ondatra.Port, dp2 *ondatra.Port) { - plqID := dut1.Name() + ":" + dp1.Name() + "<->" + dut2.Name() + ":" + dp2.Name() if deviations.PLQGeneratorCapabilitiesMaxMTU(dut1) != 0 { minRequiredGeneratorMTU = uint64(deviations.PLQGeneratorCapabilitiesMaxMTU(dut1)) @@ -559,15 +550,18 @@ func TestLinkQualification(t *testing.T) { cases := []struct { desc string - testFunc func(t *testing.T, dut1 *ondatra.DUTDevice, dut2 *ondatra.DUTDevice, dp1 *ondatra.Port, dp2 *ondatra.Port) + testFunc func(t *testing.T, dut1 *ondatra.DUTDevice, dut2 *ondatra.DUTDevice, dp1 *ondatra.Port, dp2 *ondatra.Port, plqID string) + plqID string aggregate bool }{{ desc: "Singleton Interface LinkQualification", testFunc: testLinkQualification, + plqID: dut1.Name() + ":" + dp1.Name() + "<->" + dut2.Name() + ":" + dp2.Name() + ":singleton", aggregate: false, }, { desc: "Member Link LinkQualification", testFunc: testLinkQualification, + plqID: dut1.Name() + ":" + dp1.Name() + "<->" + dut2.Name() + ":" + dp2.Name() + ":memberlink", aggregate: true, }} @@ -576,7 +570,7 @@ func TestLinkQualification(t *testing.T) { if tc.aggregate { configureDUTAggregate(t, dut1, dut2) } - tc.testFunc(t, dut1, dut2, dp1, dp2) + tc.testFunc(t, dut1, dut2, dp1, dp2, tc.plqID) }) } } From 61adf720586d1f108616ef6025d7d9db0b58fdb8 Mon Sep 17 00:00:00 2001 From: Nisha Sadhasivam Date: Thu, 23 Jan 2025 16:58:42 +0000 Subject: [PATCH 3/9] minor change --- .../packet_link_qualification_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go b/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go index 7676bb291da..81e3d33558d 100644 --- a/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go +++ b/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go @@ -319,7 +319,7 @@ func configureDUTAggregate(t *testing.T, dut1 *ondatra.DUTDevice, dut2 *ondatra. gnmi.Await(t, dut2, gnmi.OC().Interface(aggIdDut2).AdminStatus().State(), 60*time.Second, oc.Interface_AdminStatus_UP) } -func testLinkQualification(t *testing.T, dut1 *ondatra.DUTDevice, dut2 *ondatra.DUTDevice, dp1 *ondatra.Port, dp2 *ondatra.Port) { +func testLinkQualification(t *testing.T, dut1 *ondatra.DUTDevice, dut2 *ondatra.DUTDevice, dp1 *ondatra.Port, dp2 *ondatra.Port, plqID string) { if deviations.PLQGeneratorCapabilitiesMaxMTU(dut1) != 0 { minRequiredGeneratorMTU = uint64(deviations.PLQGeneratorCapabilitiesMaxMTU(dut1)) From f741654203d112522155981ad5af7482f5978d3e Mon Sep 17 00:00:00 2001 From: Nisha Sadhasivam Date: Thu, 23 Jan 2025 22:39:00 +0530 Subject: [PATCH 4/9] minor fix From 7dbe9a8e0d25573e27ef64240b3f8c485c17225d Mon Sep 17 00:00:00 2001 From: Nisha Sadhasivam Date: Thu, 23 Jan 2025 22:58:40 +0530 Subject: [PATCH 5/9] gofmt --- .../packet_link_qualification_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go b/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go index 81e3d33558d..e181d9f3074 100644 --- a/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go +++ b/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go @@ -551,7 +551,7 @@ func TestLinkQualification(t *testing.T) { cases := []struct { desc string testFunc func(t *testing.T, dut1 *ondatra.DUTDevice, dut2 *ondatra.DUTDevice, dp1 *ondatra.Port, dp2 *ondatra.Port, plqID string) - plqID string + plqID string aggregate bool }{{ desc: "Singleton Interface LinkQualification", From b4f6db71add800a66c39f78e4d3a3648fa3fe98f Mon Sep 17 00:00:00 2001 From: Nisha Sadhasivam Date: Fri, 24 Jan 2025 08:22:39 +0530 Subject: [PATCH 6/9] Addressing review comments --- .../packet_link_qualification_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go b/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go index e181d9f3074..1176523034e 100644 --- a/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go +++ b/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go @@ -314,9 +314,9 @@ func configureDUTAggregate(t *testing.T, dut1 *ondatra.DUTDevice, dut2 *ondatra. } } // Wait for LAG interfaces to be UP - gnmi.Await(t, dut1, gnmi.OC().Interface(aggIdDut1).AdminStatus().State(), 60*time.Second, oc.Interface_AdminStatus_UP) + gnmi.Await(t, dut1, gnmi.OC().Interface(aggIdDut1).AdminStatus().State(), 60*time.Second, oc.Interface_OperStatus_UP) - gnmi.Await(t, dut2, gnmi.OC().Interface(aggIdDut2).AdminStatus().State(), 60*time.Second, oc.Interface_AdminStatus_UP) + gnmi.Await(t, dut2, gnmi.OC().Interface(aggIdDut2).AdminStatus().State(), 60*time.Second, oc.Interface_OperStatus_UP) } func testLinkQualification(t *testing.T, dut1 *ondatra.DUTDevice, dut2 *ondatra.DUTDevice, dp1 *ondatra.Port, dp2 *ondatra.Port, plqID string) { @@ -550,18 +550,18 @@ func TestLinkQualification(t *testing.T) { cases := []struct { desc string - testFunc func(t *testing.T, dut1 *ondatra.DUTDevice, dut2 *ondatra.DUTDevice, dp1 *ondatra.Port, dp2 *ondatra.Port, plqID string) plqID string + testFunc func(t *testing.T, dut1 *ondatra.DUTDevice, dut2 *ondatra.DUTDevice, dp1 *ondatra.Port, dp2 *ondatra.Port, plqID string) aggregate bool }{{ desc: "Singleton Interface LinkQualification", - testFunc: testLinkQualification, plqID: dut1.Name() + ":" + dp1.Name() + "<->" + dut2.Name() + ":" + dp2.Name() + ":singleton", + testFunc: testLinkQualification, aggregate: false, }, { desc: "Member Link LinkQualification", - testFunc: testLinkQualification, plqID: dut1.Name() + ":" + dp1.Name() + "<->" + dut2.Name() + ":" + dp2.Name() + ":memberlink", + testFunc: testLinkQualification, aggregate: true, }} From 0a8f91acd0fe89d55a5f958f4ebbc9d91597172f Mon Sep 17 00:00:00 2001 From: Nisha Sadhasivam Date: Fri, 24 Jan 2025 08:53:53 +0530 Subject: [PATCH 7/9] minor fix --- .../packet_link_qualification_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go b/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go index 1176523034e..2211c5bbf56 100644 --- a/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go +++ b/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go @@ -314,9 +314,9 @@ func configureDUTAggregate(t *testing.T, dut1 *ondatra.DUTDevice, dut2 *ondatra. } } // Wait for LAG interfaces to be UP - gnmi.Await(t, dut1, gnmi.OC().Interface(aggIdDut1).AdminStatus().State(), 60*time.Second, oc.Interface_OperStatus_UP) + gnmi.Await(t, dut1, gnmi.OC().Interface(aggIdDut1).OperStatus().State(), 60*time.Second, oc.Interface_OperStatus_UP) - gnmi.Await(t, dut2, gnmi.OC().Interface(aggIdDut2).AdminStatus().State(), 60*time.Second, oc.Interface_OperStatus_UP) + gnmi.Await(t, dut2, gnmi.OC().Interface(aggIdDut2).OperStatus().State(), 60*time.Second, oc.Interface_OperStatus_UP) } func testLinkQualification(t *testing.T, dut1 *ondatra.DUTDevice, dut2 *ondatra.DUTDevice, dp1 *ondatra.Port, dp2 *ondatra.Port, plqID string) { From 8cb1359f33fcefb7ab9e905289cd2b23179a64d7 Mon Sep 17 00:00:00 2001 From: Nisha Sadhasivam Date: Fri, 24 Jan 2025 03:57:28 +0000 Subject: [PATCH 8/9] gofmt --- .../packet_link_qualification_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go b/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go index 2211c5bbf56..e18eb3daade 100644 --- a/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go +++ b/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/packet_link_qualification_test.go @@ -561,7 +561,7 @@ func TestLinkQualification(t *testing.T) { }, { desc: "Member Link LinkQualification", plqID: dut1.Name() + ":" + dp1.Name() + "<->" + dut2.Name() + ":" + dp2.Name() + ":memberlink", - testFunc: testLinkQualification, + testFunc: testLinkQualification, aggregate: true, }} From 2eea1338bf0adad4984a5bcde3c53501665f6741 Mon Sep 17 00:00:00 2001 From: Nisha Sadhasivam Date: Fri, 24 Jan 2025 14:59:00 +0000 Subject: [PATCH 9/9] updated topology --- .../tests/packet_link_qualification_test/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/README.md b/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/README.md index 01e4aca9b19..fa4005ee36c 100644 --- a/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/README.md +++ b/feature/gnoi/packet_link_qualification/tests/packet_link_qualification_test/README.md @@ -7,7 +7,7 @@ between 2 DUTs. ## Topology -* dut1:port1 <--> port1:dut2 +* dut1:port1 <--> port1:dut2 (port1 as singleton and memberlink) ## Procedure