Skip to content

Commit

Permalink
Wecmp (openconfig#2882)
Browse files Browse the repository at this point in the history
* Update weighted_ecmp_test.go

* Update README.md

Removed total traffic from the Readme as traffic values are fixed after fine tuning.

* Update deviations.go

Adding deviation to enable cli knob

* Update metadata.proto

Add deviation for Arista CLI knob

* Update metadata.textproto

* Update deviations.go

* Generated metadata.pb.go

* Fixed typo

* Added new line

* Added new line

* Formatted the file

* Formatted the file

* Formatted the file

---------

Co-authored-by: Pramod Maurya <[email protected]>
  • Loading branch information
AmrNJ and self-maurya authored Apr 19, 2024
1 parent 56dc030 commit 95e7a39
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 85 deletions.
2 changes: 0 additions & 2 deletions feature/isis/otg_tests/weighted_ecmp_test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ In the topology above,
* Start 1024 flows from IPv6 addresses in 2001:db8:64:65::/64 to
2001:db8:64:64::/64

* Ensure that the total traffic of all flows combined is ~20Gbps

### Verification

Expand Down Expand Up @@ -125,7 +124,6 @@ In the topology above,
* Restart 1024 flows from IPv6 addresses in 2001:db8:64:65::/64 to
2001:db8:64:64::/64

* Ensure that the total traffic of all flows combined is ~20Gbps

### Verification

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ platform_exceptions: {
isis_require_same_l1_metric_with_l2_metric: true
route_policy_under_afi_unsupported: true
static_protocol_name: "STATIC"
rib_wecmp: true
}
}
71 changes: 49 additions & 22 deletions feature/isis/otg_tests/weighted_ecmp_test/weighted_ecmp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"testing"
"time"

"math/rand"

"github.com/open-traffic-generator/snappi/gosnappi"
"github.com/openconfig/featureprofiles/internal/attrs"
"github.com/openconfig/featureprofiles/internal/cfgplugins"
Expand All @@ -27,13 +29,14 @@ const (
dutSysID = "1920.0000.2001"
asn = 64501
acceptRoutePolicy = "PERMIT-ALL"
trafficPPS = 5000000
trafficPPS = 50000 // Should be 5000000
trafficv6PPS = 50000 // Should be 5000000
srcTrafficV4 = "100.0.2.1"
srcTrafficV6 = "2001:db8:64:65::1"
dstTrafficV4 = "100.0.1.1"
dstTrafficV6 = "2001:db8:64:64::1"
v4Count = 254
v6Count = 100000000
v6Count = 1000 // Should be 10000000
)

type aggPortData struct {
Expand Down Expand Up @@ -85,8 +88,8 @@ var (
agg3 = &aggPortData{
dutIPv4: "192.0.2.9",
ateIPv4: "192.0.2.10",
dutIPv6: "2001:db8::9",
ateIPv6: "2001:db8::10",
dutIPv6: "2001:db8::11",
ateIPv6: "2001:db8::12",
ateAggName: "lag3",
ateAggMAC: "02:00:01:01:01:07",
atePort1MAC: "02:00:01:01:01:08",
Expand All @@ -98,8 +101,8 @@ var (
agg4 = &aggPortData{
dutIPv4: "192.0.2.13",
ateIPv4: "192.0.2.14",
dutIPv6: "2001:db8::13",
ateIPv6: "2001:db8::14",
dutIPv6: "2001:db8::14",
ateIPv6: "2001:db8::15",
ateAggName: "lag4",
ateAggMAC: "02:00:01:01:01:10",
atePort1MAC: "02:00:01:01:01:11",
Expand Down Expand Up @@ -132,25 +135,28 @@ func TestMain(m *testing.M) {
}

func TestWeightedECMPForISIS(t *testing.T) {
// ondatra.Debug().Breakpoint(t)
dut := ondatra.DUT(t, "dut")
ate := ondatra.ATE(t, "ate")

aggIDs := configureDUT(t, dut)

// Enable weighted ECMP and set LoadBalancing to Auto
b := &gnmi.SetBatch{}
isisPath := gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(dut)).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_ISIS, isisInstance).Isis()
gnmi.BatchReplace(b, isisPath.Global().WeightedEcmp().Config(), true)
for _, aggID := range aggIDs {
gnmi.BatchReplace(b, isisPath.Interface(aggID).WeightedEcmp().Config(), &oc.NetworkInstance_Protocol_Isis_Interface_WeightedEcmp{
LoadBalancingWeight: oc.NetworkInstance_Protocol_Isis_Interface_WeightedEcmp_LoadBalancingWeight_Union(oc.WeightedEcmp_LoadBalancingWeight_auto),
})
if !deviations.RibWecmp(dut) {
b := &gnmi.SetBatch{}
// isisPath := gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(dut)).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_ISIS, isisInstance)
isisPath := gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(dut)).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_ISIS, isisInstance).Isis()
gnmi.BatchReplace(b, isisPath.Global().WeightedEcmp().Config(), true)
for _, aggID := range aggIDs {
gnmi.BatchReplace(b, isisPath.Interface(aggID).WeightedEcmp().Config(), &oc.NetworkInstance_Protocol_Isis_Interface_WeightedEcmp{
LoadBalancingWeight: oc.NetworkInstance_Protocol_Isis_Interface_WeightedEcmp_LoadBalancingWeight_Union(oc.WeightedEcmp_LoadBalancingWeight_auto),
})
}
b.Set(t, dut)
}
b.Set(t, dut)

top := configureATE(t, ate)
flows := configureFlows(t, top, ate1AdvV4, ate1AdvV6, ate2AdvV4, ate2AdvV6)

ate.OTG().PushConfig(t, top)
ate.OTG().StartProtocols(t)
for _, agg := range []*aggPortData{agg1, agg2} {
Expand All @@ -160,10 +166,9 @@ func TestWeightedECMPForISIS(t *testing.T) {
}

startTraffic(t, ate, top)

t.Run("Equal_Distribution_Of_Traffic", func(t *testing.T) {
for _, flow := range flows {
loss := otgutils.GetFlowLossPct(t, ate.OTG(), flow.Name(), 5*time.Second)
loss := otgutils.GetFlowLossPct(t, ate.OTG(), flow.Name(), 20*time.Second)
if got, want := loss, 0.0; got != want {
t.Errorf("Flow %s loss: got %f, want %f", flow.Name(), got, want)
}
Expand All @@ -180,26 +185,28 @@ func TestWeightedECMPForISIS(t *testing.T) {
if deviations.ATEPortLinkStateOperationsUnsupported(ate) {
p3 := dut.Port(t, "port3")
gnmi.Replace(t, dut, gnmi.OC().Interface(p3.Name()).Enabled().Config(), false)
t.Logf("Disable ATE2:Port1: %s, %s", p3.Name(), gnmi.OC().Interface(p3.Name()).OperStatus().State())
} else {
p3 := ate.Port(t, "port3") // ATE:port3 is ATE2:port1
psa := gosnappi.NewControlState()
psa.Port().Link().SetPortNames([]string{p3.ID()}).SetState(gosnappi.StatePortLinkState.DOWN)
ate.OTG().SetControlState(t, psa)

time.Sleep(10 * time.Second)
defer func() {
psa := gosnappi.NewControlState()
psa.Port().Link().SetPortNames([]string{p3.ID()}).SetState(gosnappi.StatePortLinkState.UP)
ate.OTG().SetControlState(t, psa)
}()
}
p3 := dut.Port(t, "port3")
gnmi.Await(t, dut, gnmi.OC().Interface(p3.Name()).OperStatus().State(), time.Minute, oc.Interface_OperStatus_LOWER_LAYER_DOWN)
gnmi.Await(t, dut, gnmi.OC().Interface(p3.Name()).OperStatus().State(), time.Minute*2, oc.Interface_OperStatus_DOWN)
top.Flows().Clear()

startTraffic(t, ate, top)

t.Run("Unequal_Distribution_Of_Traffic", func(t *testing.T) {
for _, flow := range flows {
loss := otgutils.GetFlowLossPct(t, ate.OTG(), flow.Name(), 5*time.Second)
loss := otgutils.GetFlowLossPct(t, ate.OTG(), flow.Name(), 20*time.Second)
if got, want := loss, 0.0; got != want {
t.Errorf("Flow %s loss: got %f, want %f", flow.Name(), got, want)
}
Expand Down Expand Up @@ -239,8 +246,23 @@ func startTraffic(t *testing.T, ate *ondatra.ATEDevice, top gosnappi.Config) {
otgutils.LogLAGMetrics(t, ate.OTG(), top)
}

func randRange(t *testing.T, start, end uint32, count int) []uint32 {
if count > int(end-start) {
t.Fatal("randRange: count greater than end-start.")
}
rand.New(rand.NewSource(time.Now().UnixNano()))
var result []uint32
for len(result) < count {
diff := end - start
randomValue := rand.Int31n(int32(diff)) + int32(start)
result = append(result, uint32(randomValue))
}
return result
}

func configureFlows(t *testing.T, top gosnappi.Config, srcV4, srcV6, dstV4, dstV6 *ipAddr) []gosnappi.Flow {
t.Helper()
top.Flows().Clear()
fV4 := top.Flows().Add().SetName("flowV4")
fV4.Metrics().SetEnable(true)
fV4.TxRx().Device().
Expand All @@ -253,21 +275,26 @@ func configureFlows(t *testing.T, top gosnappi.Config, srcV4, srcV6, dstV4, dstV
v4 := fV4.Packet().Add().Ipv4()
v4.Src().Increment().SetStart(srcTrafficV4).SetCount(v4Count)
v4.Dst().Increment().SetStart(dstTrafficV4).SetCount(v4Count)
udp := fV4.Packet().Add().Udp()
udp.SrcPort().SetValues(randRange(t, 34525, 65535, 500))
udp.DstPort().SetValues(randRange(t, 49152, 65535, 500))

fV6 := top.Flows().Add().SetName("flowV6")
fV6.Metrics().SetEnable(true)
fV6.TxRx().Device().
SetTxNames([]string{agg1.ateAggName + ".IPv6"}).
SetRxNames([]string{agg2.ateAggName + ".IPv6", agg3.ateAggName + ".IPv6", agg4.ateAggName + ".IPv6"})
fV6.Size().SetFixed(1500)
fV6.Rate().SetPps(trafficPPS)
fV6.Rate().SetPps(trafficv6PPS)
eV6 := fV6.Packet().Add().Ethernet()
eV6.Src().SetValue(agg1.ateAggMAC)

v6 := fV6.Packet().Add().Ipv6()
v6.Src().Increment().SetStart(srcTrafficV6).SetCount(v6Count)
v6.Dst().Increment().SetStart(dstTrafficV6).SetCount(v6Count)

udpv6 := fV6.Packet().Add().Udp()
udpv6.SrcPort().SetValues(randRange(t, 35521, 65535, 500))
udpv6.DstPort().SetValues(randRange(t, 49152, 65535, 500))
return []gosnappi.Flow{fV4, fV6}
}

Expand Down
5 changes: 5 additions & 0 deletions internal/deviations/deviations.go
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,11 @@ func ExplicitInterfaceInDefaultVRF(dut *ondatra.DUTDevice) bool {
return lookupDUTDeviations(dut).GetExplicitInterfaceInDefaultVrf()
}

// RibWecmp returns if device requires CLI knob to enable wecmp feature.
func RibWecmp(dut *ondatra.DUTDevice) bool {
return lookupDUTDeviations(dut).GetRibWecmp()
}

// InterfaceConfigVRFBeforeAddress returns if vrf should be configured before IP address when configuring interface.
func InterfaceConfigVRFBeforeAddress(dut *ondatra.DUTDevice) bool {
return lookupDUTDeviations(dut).GetInterfaceConfigVrfBeforeAddress()
Expand Down
8 changes: 5 additions & 3 deletions proto/metadata.proto
Original file line number Diff line number Diff line change
Expand Up @@ -475,12 +475,14 @@ message Metadata {
bool bgp_extended_community_index_unsupported = 167;
// Support for bgp community set refs
bool bgp_community_set_refs_unsupported = 168;
// Arista device needs CLI knob to enable WECMP feature
bool rib_wecmp = 169;
// Device not supporting table-connection need to set this true
bool table_connections_unsupported = 169;
bool table_connections_unsupported = 170;
// Configure tag-set using vendor native model
bool use_vendor_native_tag_set_config = 170;
bool use_vendor_native_tag_set_config = 171;
// Skip setting send-community-type in bgp global config
bool skip_bgp_send_community_type = 171;
bool skip_bgp_send_community_type = 172;
// Reserved field numbers and identifiers.
reserved 84, 9, 28, 20, 90, 97, 55, 89, 19;
}
Expand Down
Loading

0 comments on commit 95e7a39

Please sign in to comment.