Skip to content

Commit

Permalink
[gNMI-1.11, RT-5.1/3] - add InterfaceCountersUpdateDelayed deviation …
Browse files Browse the repository at this point in the history
…for CISCO (#2805)

* wait for counters update

* revert some changes

* bug fix

* go fmt

* fix readme check

* readme check change

* restore gnmi-1.10

* restore gnmi-1.10

* remove /tmp

* remove tmp path

* fix readme

* fix indentation

* fix readme

---------

Co-authored-by: arvbaska <[email protected]>
Co-authored-by: arvbaska1 <[email protected]>
  • Loading branch information
3 people authored Oct 3, 2024
1 parent e0b5ce2 commit 43e3890
Show file tree
Hide file tree
Showing 11 changed files with 230 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ platform_exceptions: {
ipv4_missing_enabled: true
interface_counters_from_container: true
subinterface_packet_counters_missing: true
interface_counters_update_delayed: true
}
}
platform_exceptions: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,31 @@ func fetchInAndOutPkts(t *testing.T, dut *ondatra.DUTDevice, i1, i2 *interfaces.
return inPkts, outPkts
}

func waitForCountersUpdate(t *testing.T, dut *ondatra.DUTDevice, i1, i2 *interfaces.InterfacePath,
inTarget, outTarget uint64) (map[string]uint64, map[string]uint64) {
inWatcher := gnmi.Watch(t, dut, i1.Counters().InUnicastPkts().State(), time.Second*60, func(v *ygnmi.Value[uint64]) bool {
got, present := v.Val()
return present && got >= inTarget
})
outWatcher := gnmi.Watch(t, dut, i2.Counters().OutUnicastPkts().State(),
time.Second*60, func(v *ygnmi.Value[uint64]) bool {
got, present := v.Val()
return present && got >= outTarget
})

inPktsV, ok := inWatcher.Await(t)
if !ok {
t.Fatalf("InPkts counter did not update in time")
}
outPktsV, ok := outWatcher.Await(t)
if !ok {
t.Fatalf("OutPkts counter did not update in time")
}
inPkts, _ := inPktsV.Val()
outPkts, _ := outPktsV.Val()
return map[string]uint64{"parent": inPkts}, map[string]uint64{"parent": outPkts}
}

func TestIntfCounterUpdate(t *testing.T) {
dut := ondatra.DUT(t, "dut")
dp1 := dut.Port(t, "port1")
Expand Down Expand Up @@ -378,7 +403,14 @@ func TestIntfCounterUpdate(t *testing.T) {
}
}

dutInPktsAfterTraffic, dutOutPktsAfterTraffic := fetchInAndOutPkts(t, dut, i1, i2)
var dutInPktsAfterTraffic, dutOutPktsAfterTraffic map[string]uint64
if deviations.InterfaceCountersUpdateDelayed(dut) {
dutInPktsAfterTraffic, dutOutPktsAfterTraffic = waitForCountersUpdate(t, dut, i1, i2,
dutInPktsBeforeTraffic["parent"]+ateInPkts["parent"],
dutOutPktsBeforeTraffic["parent"]+ateOutPkts["parent"])
} else {
dutInPktsAfterTraffic, dutOutPktsAfterTraffic = fetchInAndOutPkts(t, dut, i1, i2)
}

t.Logf("inPkts: %v and outPkts: %v after traffic: ", dutInPktsAfterTraffic, dutOutPktsAfterTraffic)
for k := range dutInPktsAfterTraffic {
Expand Down
23 changes: 23 additions & 0 deletions feature/interface/aggregate/otg_tests/balancing_test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,26 @@ None
## Minimum DUT platform requirement

vRX

## OpenConfig Path and RPC Coverage

The below yaml defines the OC paths and RPC intended to be covered by this test.

```yaml
paths:
/interfaces/interface/ethernet/config/aggregate-id:
/interfaces/interface/aggregation/config/lag-type:
/lacp/config/system-priority:
/lacp/interfaces/interface/config/name:
/lacp/interfaces/interface/config/interval:
/lacp/interfaces/interface/config/lacp-mode:
/lacp/interfaces/interface/config/system-id-mac:
/lacp/interfaces/interface/config/system-priority:

rpcs:
gnmi:
gNMI.Set:
union_replace: false
gNMI.Subscribe:
on_change: false
```
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,30 @@ func (tc *testCase) testFlow(t *testing.T, l3header string) {
if pkts == 0 {
t.Errorf("Flow sent packets: got %v, want non zero", pkts)
}

if deviations.InterfaceCountersUpdateDelayed(tc.dut) {
batch := gnmi.OCBatch()
for _, port := range tc.dutPorts[1:] {
batch.AddPaths(gnmi.OC().Interface(port.Name()).Counters())
}

_, ok := gnmi.Watch(t, tc.dut, batch.State(), time.Second*60, func(v *ygnmi.Value[*oc.Root]) bool {
got, present := v.Val()
if !present {
return false
}
totalPks := uint64(0)
for _, port := range tc.dutPorts[1:] {
totalPks += got.GetInterface(port.Name()).GetCounters().GetOutPkts() - beforeTrafficCounters[port.Name()].GetOutPkts()
}
return totalPks >= pkts
}).Await(t)

if !ok {
t.Fatalf("Counters did not update in time")
}
}

afterTrafficCounters := tc.getCounters(t, "after")
tc.verifyCounterDiff(t, beforeTrafficCounters, afterTrafficCounters)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ platform_exceptions: {
}
deviations: {
ipv4_missing_enabled: true
interface_counters_update_delayed: true
}
}
platform_exceptions: {
Expand Down
53 changes: 53 additions & 0 deletions feature/interface/singleton/otg_tests/singleton_test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,56 @@ a new testbed configuration with the desired port types.
## Minimum DUT Platform Requirement

vRX

## OpenConfig Path and RPC Coverage

The below yaml defines the OC paths and RPC intended to be covered by this test.

```yaml
paths:
/interfaces/interface/ethernet/state/counters/in-mac-pause-frames:
/interfaces/interface/ethernet/state/counters/out-mac-pause-frames:
/interfaces/interface/ethernet/state/mac-address:
/interfaces/interface/state/counters/in-broadcast-pkts:
/interfaces/interface/state/counters/in-discards:
/interfaces/interface/state/counters/in-errors:
/interfaces/interface/state/counters/in-multicast-pkts:
/interfaces/interface/state/counters/in-octets:
/interfaces/interface/state/counters/in-unicast-pkts:
/interfaces/interface/state/counters/in-unknown-protos:
/interfaces/interface/state/counters/out-broadcast-pkts:
/interfaces/interface/state/counters/out-discards:
/interfaces/interface/state/counters/out-errors:
/interfaces/interface/state/counters/out-multicast-pkts:
/interfaces/interface/state/counters/out-octets:
/interfaces/interface/state/counters/out-pkts:
/interfaces/interface/state/counters/out-unicast-pkts:
/interfaces/interface/subinterfaces/subinterface/ipv4/state/mtu:
/interfaces/interface/subinterfaces/subinterface/ipv6/state/mtu:
/interfaces/interface/state/oper-status:
/interfaces/interface/subinterfaces/subinterface/ipv4/addresses/address/ip:
/interfaces/interface/subinterfaces/subinterface/ipv4/state/counters/in-pkts:
/interfaces/interface/subinterfaces/subinterface/ipv4/state/counters/out-pkts:
/interfaces/interface/subinterfaces/subinterface/ipv6/addresses/address/ip:
/interfaces/interface/subinterfaces/subinterface/ipv6/state/counters/in-discarded-pkts:
/interfaces/interface/subinterfaces/subinterface/ipv6/state/counters/in-pkts:
/interfaces/interface/subinterfaces/subinterface/ipv6/state/counters/out-discarded-pkts:
/interfaces/interface/subinterfaces/subinterface/ipv6/state/counters/out-pkts:
/interfaces/interface/ethernet/state/aggregate-id:
/interfaces/interface/ethernet/state/port-speed:
/interfaces/interface/state/admin-status:
/interfaces/interface/state/description:
/interfaces/interface/state/type:
/interfaces/interface/subinterfaces/subinterface/ipv6/state/counters/out-forwarded-pkts:
/interfaces/interface/state/hardware-port:
/interfaces/interface/state/id:
/interfaces/interface/state/counters/in-fcs-errors:
/interfaces/interface/state/counters/carrier-transitions:

rpcs:
gnmi:
gNMI.Set:
union_replace: false
gNMI.Subscribe:
on_change: false
```
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ platform_exceptions: {
deviations: {
ip_neighbor_missing: true
ipv4_missing_enabled: true
interface_counters_update_delayed: true
}
}
platform_exceptions: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/openconfig/ondatra"
"github.com/openconfig/ondatra/gnmi"
"github.com/openconfig/ondatra/gnmi/oc"
"github.com/openconfig/ygnmi/ygnmi"
"github.com/openconfig/ygot/ygot"

otgtelemetry "github.com/openconfig/ondatra/gnmi/otg"
Expand Down Expand Up @@ -430,6 +431,36 @@ func (tc *testCase) testFlow(t *testing.T, packetSize uint16, configIPHeader otg
t.Logf("ap1 out-octets %d -> ap2 in-octets %d", aicp1.GetCounters().GetOutOctets(), aicp2.GetCounters().GetInOctets())
}

// Flow counters
otgutils.LogFlowMetrics(t, tc.ate.OTG(), tc.top)
fp := gnmi.Get(t, tc.ate.OTG(), gnmi.OTG().Flow(flow.Name()).State())
fpc := fp.GetCounters()

// Pragmatic check on the average in and out packet sizes. IPv4 may
// fragment the packet unless DF bit is set. IPv6 never fragments.
// Under no circumstances should DUT send packets greater than MTU.

octets := fpc.GetOutOctets()
ateOutPkts := fpc.GetOutPkts()
ateInPkts := fpc.GetInPkts()

if deviations.InterfaceCountersUpdateDelayed(tc.dut) {
batch := gnmi.OCBatch()
batch.AddPaths(
gnmi.OC().Interface(p1.Name()).Counters(),
gnmi.OC().Interface(p2.Name()).Counters(),
)
gnmi.Watch(t, tc.dut, batch.State(), time.Second*60, func(v *ygnmi.Value[*oc.Root]) bool {
got, present := v.Val()
if !present {
return false
}
diffP1 := diffCounters(p1InBefore, inCounters(got.GetInterface(p1.Name()).GetCounters()))
diffP2 := diffCounters(p2OutBefore, outCounters(got.GetInterface(p2.Name()).GetCounters()))
return (diffP1.unicast+diffP1.drop >= ateOutPkts) && (diffP2.unicast >= ateInPkts-diffP2.drop)
}).Await(t)
}

// After Traffic Unicast, Multicast, Broadcast Counter
p1InAfter := inCounters(gnmi.Get(t, tc.dut, p1Counter.State()))
p2OutAfter := outCounters(gnmi.Get(t, tc.dut, p2Counter.State()))
Expand All @@ -449,18 +480,6 @@ func (tc *testCase) testFlow(t *testing.T, packetSize uint16, configIPHeader otg
t.Errorf("Large number of outbound Broadcast packets %d, want <= 100)", p2OutDiff.broadcast)
}

// Flow counters
otgutils.LogFlowMetrics(t, tc.ate.OTG(), tc.top)
fp := gnmi.Get(t, tc.ate.OTG(), gnmi.OTG().Flow(flow.Name()).State())
fpc := fp.GetCounters()

// Pragmatic check on the average in and out packet sizes. IPv4 may
// fragment the packet unless DF bit is set. IPv6 never fragments.
// Under no circumstances should DUT send packets greater than MTU.

octets := fpc.GetOutOctets()
ateOutPkts := fpc.GetOutPkts()
ateInPkts := fpc.GetInPkts()
if ateOutPkts == 0 {
t.Error("Flow did not send any packet")
} else if avg := octets / ateOutPkts; avg > uint64(tc.mtu) {
Expand Down
6 changes: 6 additions & 0 deletions internal/deviations/deviations.go
Original file line number Diff line number Diff line change
Expand Up @@ -1151,6 +1151,12 @@ func ComponentMfgDateUnsupported(dut *ondatra.DUTDevice) bool {
return lookupDUTDeviations(dut).GetComponentMfgDateUnsupported()
}

// InterfaceCountersUpdateDelayed returns true if telemetry for interface counters
// does not return the latest counter values.
func InterfaceCountersUpdateDelayed(dut *ondatra.DUTDevice) bool {
return lookupDUTDeviations(dut).GetInterfaceCountersUpdateDelayed()
}

// OTNChannelTribUnsupported returns true if TRIB parameter is unsupported under OTN channel configuration
func OTNChannelTribUnsupported(dut *ondatra.DUTDevice) bool {
return lookupDUTDeviations(dut).GetOtnChannelTribUnsupported()
Expand Down
2 changes: 2 additions & 0 deletions proto/metadata.proto
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,8 @@ message Metadata {
bool eth_channel_ingress_parameters_unsupported = 222;
// Cisco numbering for eth channel assignment starts from 1 instead of 0
bool eth_channel_assignment_cisco_numbering = 223;
// Devices needs time to update interface counters.
bool interface_counters_update_delayed = 224;
// Reserved field numbers and identifiers.
reserved 84, 9, 28, 20, 90, 97, 55, 89, 19, 36, 35, 40, 173;
}
Expand Down
Loading

0 comments on commit 43e3890

Please sign in to comment.