From 4da3a947458a0452d93e2dc086022054c883a27b Mon Sep 17 00:00:00 2001 From: Pramod Maurya Date: Wed, 6 Dec 2023 23:34:00 +0530 Subject: [PATCH] validate sample and on-change mode for various backplane capacity counters (#2441) --- .../README.md | 8 +- .../metadata.textproto | 47 ++++ ...ampled_backplane_capacity_counters_test.go | 237 ++++++++++++++++++ 3 files changed, 288 insertions(+), 4 deletions(-) create mode 100644 feature/platform/fabric/otg_tests/sampled_backplane_capacity_counters_test/metadata.textproto create mode 100644 feature/platform/fabric/otg_tests/sampled_backplane_capacity_counters_test/sampled_backplane_capacity_counters_test.go diff --git a/feature/platform/fabric/otg_tests/sampled_backplane_capacity_counters_test/README.md b/feature/platform/fabric/otg_tests/sampled_backplane_capacity_counters_test/README.md index 65dfe9ab455..0e5e7dd101d 100644 --- a/feature/platform/fabric/otg_tests/sampled_backplane_capacity_counters_test/README.md +++ b/feature/platform/fabric/otg_tests/sampled_backplane_capacity_counters_test/README.md @@ -17,7 +17,7 @@ the available backplane capacity counters correctly while forwarding traffic ## Procedure -### gNMI-1.18.1 [TODO: https://github.com/openconfig/featureprofiles/issues/2322] +### gNMI-1.18.1 * Connect DUT port-1 and 2 to ATE port-1 and 2 respectively @@ -35,7 +35,7 @@ the available backplane capacity counters correctly while forwarding traffic * Initiate traffic: * Initiate traffic as per below threshold: - + Port number | Interface1(line rate %) -------------- | ----------------------- Port1 | 20% @@ -52,7 +52,7 @@ the available backplane capacity counters correctly while forwarding traffic * Validate we are now receiving increased consumed capacity metrics at the selected SAMPLE interval -### gNMI-1.18.2 [TODO: https://github.com/openconfig/featureprofiles/issues/2323] +### gNMI-1.18.2 * Connect DUT port-1 and 2 to ATE port-1 and 2 respectively @@ -74,7 +74,7 @@ the available backplane capacity counters correctly while forwarding traffic * Enable the FABRIC component that was disabled in the previous step - * Set /components/component/{fabric|linecard|controller-card}/config/power-admin-state to POWER_ENABLED + * Set /components/component/{fabric}/config/power-admin-state to POWER_ENABLED * Validate that we recieve changed metrics of a higher value for each of the telemetry paths diff --git a/feature/platform/fabric/otg_tests/sampled_backplane_capacity_counters_test/metadata.textproto b/feature/platform/fabric/otg_tests/sampled_backplane_capacity_counters_test/metadata.textproto new file mode 100644 index 00000000000..52f4163134e --- /dev/null +++ b/feature/platform/fabric/otg_tests/sampled_backplane_capacity_counters_test/metadata.textproto @@ -0,0 +1,47 @@ +# proto-file: third_party/openconfig/featureprofiles/proto/metadata.proto +# proto-message: Metadata + +uuid: "ef804c64-84dd-432d-ab38-630e9c82b42d" +plan_id: "gNMI-1.18" +description: "gNMI subscribe with sample mode for backplane capacity counters" +testbed: TESTBED_DUT +platform_exceptions: { + platform: { + vendor: CISCO + } + deviations: { + ipv4_missing_enabled: true + } +} +platform_exceptions: { + platform: { + vendor: JUNIPER + } + deviations: { + explicit_interface_ref_definition: true + backplane_facing_capacity_unsupported: true + } +} +platform_exceptions: { + platform: { + vendor: NOKIA + } + deviations: { + interface_enabled: true + explicit_port_speed: true + explicit_interface_in_default_vrf: true + qos_queue_requires_id: true + missing_value_for_defaults: true + backplane_facing_capacity_unsupported: true + } +} +platform_exceptions: { + platform: { + vendor: ARISTA + } + deviations: { + interface_enabled: true + missing_value_for_defaults: true + } +} + diff --git a/feature/platform/fabric/otg_tests/sampled_backplane_capacity_counters_test/sampled_backplane_capacity_counters_test.go b/feature/platform/fabric/otg_tests/sampled_backplane_capacity_counters_test/sampled_backplane_capacity_counters_test.go new file mode 100644 index 00000000000..4c1c707c0c6 --- /dev/null +++ b/feature/platform/fabric/otg_tests/sampled_backplane_capacity_counters_test/sampled_backplane_capacity_counters_test.go @@ -0,0 +1,237 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sampled_backplane_capacity_counters_test + +import ( + "fmt" + "regexp" + "testing" + "time" + + "github.com/openconfig/featureprofiles/internal/components" + "github.com/openconfig/featureprofiles/internal/deviations" + "github.com/openconfig/featureprofiles/internal/fptest" + gpb "github.com/openconfig/gnmi/proto/gnmi" + "github.com/openconfig/ondatra" + "github.com/openconfig/ondatra/gnmi" + "github.com/openconfig/ondatra/gnmi/oc" + "github.com/openconfig/ygnmi/ygnmi" +) + +// Topology: +// ATE port 1 +// | +// DUT--------ATE port 3 +// | +// ATE port 2 + +var ( + icPattern = map[ondatra.Vendor]string{ + ondatra.ARISTA: "^SwitchChip", + ondatra.CISCO: "^[0-9]/[0-9]/CPU[0-9]-NPU[0-9]", + ondatra.JUNIPER: "NPU[0-9]$", + ondatra.NOKIA: "^SwitchChip", + } +) + +func TestMain(m *testing.M) { + fptest.RunTests(m) +} + +func TestSampledBackplaneCapacityCounters(t *testing.T) { + dut := ondatra.DUT(t, "dut") + + ics := components.FindComponentsByType(t, dut, oc.PlatformTypes_OPENCONFIG_HARDWARE_COMPONENT_INTEGRATED_CIRCUIT) + if len(ics) == 0 { + t.Fatalf("Get IntegratedCircuit card list for %q: got 0, want > 0", dut.Model()) + } + t.Logf("IntegratedCircuit components count: %d", len(ics)) + + subscribeTimeout := 30 * time.Second + + for _, ic := range ics { + if !isCompNameExpected(t, ic, dut.Vendor()) { + continue + } + + t.Run(fmt.Sprintf("Backplane:%s", ic), func(t *testing.T) { + if deviations.BackplaneFacingCapacityUnsupported(dut) { + t.Skipf("Skipping check for BackplanceFacingCapacity due to deviation BackplaneFacingCapacityUnsupported") + } + + for _, sampleInterval := range []time.Duration{10 * time.Second, 15 * time.Second} { + minWant := int(subscribeTimeout/sampleInterval) - 1 + consumedCapacities := gnmi.Collect(t, gnmiOptsForSample(t, dut, sampleInterval), gnmi.OC().Component(ic).IntegratedCircuit().BackplaneFacingCapacity().ConsumedCapacity().State(), subscribeTimeout).Await(t) + if len(consumedCapacities) < minWant { + t.Errorf("ConsumedCapacities: got %d, want >= %d", len(consumedCapacities), minWant) + } + } + }) + } +} + +func isCompNameExpected(t *testing.T, name string, vendor ondatra.Vendor) bool { + t.Helper() + + regexpPattern, ok := icPattern[vendor] + if !ok { + return false + } + r, err := regexp.Compile(regexpPattern) + if err != nil { + t.Fatalf("Cannot compile regular expression: %v", err) + } + return r.MatchString(name) +} + +func gnmiOptsForSample(t *testing.T, dut *ondatra.DUTDevice, interval time.Duration) *gnmi.Opts { + return dut.GNMIOpts().WithYGNMIOpts( + ygnmi.WithSubscriptionMode(gpb.SubscriptionMode_SAMPLE), + ygnmi.WithSampleInterval(interval), + ) +} + +func gnmiOptsForOnChange(t *testing.T, dut *ondatra.DUTDevice) *gnmi.Opts { + return dut.GNMIOpts().WithYGNMIOpts(ygnmi.WithSubscriptionMode(gpb.SubscriptionMode_ON_CHANGE)) +} + +func TestOnChangeBackplaneCapacityCounters(t *testing.T) { + dut := ondatra.DUT(t, "dut") + + ics := components.FindComponentsByType(t, dut, oc.PlatformTypes_OPENCONFIG_HARDWARE_COMPONENT_INTEGRATED_CIRCUIT) + if len(ics) == 0 { + t.Fatalf("Get IntegratedCircuit card list for %q: got 0, want > 0", dut.Model()) + } + t.Logf("IntegratedCircuit components count: %d", len(ics)) + + fabrics := components.FindComponentsByType(t, dut, oc.PlatformTypes_OPENCONFIG_HARDWARE_COMPONENT_FABRIC) + if len(fabrics) == 0 { + t.Skipf("Get Fabric card list for %q: got 0, want > 0", dut.Model()) + } + t.Logf("Fabric components count: %d", len(fabrics)) + + ts1, tocs1, apct1 := getBackplaneCapacityCounters(t, dut, ics) + + fc := (len(fabrics) / 2) + 1 + for _, f := range fabrics[:fc] { + gnmi.Replace(t, dut, gnmi.OC().Component(f).Fabric().PowerAdminState().Config(), oc.Platform_ComponentPowerType_POWER_DISABLED) + gnmi.Await(t, dut, gnmi.OC().Component(f).Fabric().PowerAdminState().State(), time.Minute, oc.Platform_ComponentPowerType_POWER_DISABLED) + } + + ts2, tocs2, apct2 := getBackplaneCapacityCounters(t, dut, ics) + + for _, f := range fabrics[:fc] { + gnmi.Replace(t, dut, gnmi.OC().Component(f).Fabric().PowerAdminState().Config(), oc.Platform_ComponentPowerType_POWER_ENABLED) + if deviations.MissingValueForDefaults(dut) { + time.Sleep(time.Minute) + } else { + if power, ok := gnmi.Await(t, dut, gnmi.OC().Component(f).Fabric().PowerAdminState().State(), time.Minute, oc.Platform_ComponentPowerType_POWER_ENABLED).Val(); !ok { + t.Errorf("Component %s, power-admin-state got: %v, want: %v", f, power, oc.Platform_ComponentPowerType_POWER_ENABLED) + } + } + if oper, ok := gnmi.Await(t, dut, gnmi.OC().Component(f).OperStatus().State(), 2*time.Minute, oc.PlatformTypes_COMPONENT_OPER_STATUS_ACTIVE).Val(); !ok { + t.Errorf("Component %s oper-status after POWER_ENABLED, got: %v, want: %v", f, oper, oc.PlatformTypes_COMPONENT_OPER_STATUS_ACTIVE) + } + } + + ts3, tocs3, apct3 := getBackplaneCapacityCounters(t, dut, ics) + + for _, ic := range ics { + if !isCompNameExpected(t, ic, dut.Vendor()) { + continue + } + + t.Run(fmt.Sprintf("Backplane:CountersCheck:%s", ic), func(t *testing.T) { + if deviations.BackplaneFacingCapacityUnsupported(dut) { + t.Skipf("Skipping check for BackplanceFacingCapacity due to deviation BackplaneFacingCapacityUnsupported") + } + + v1, ok1 := ts1[ic] + v2, ok2 := ts2[ic] + v3, ok3 := ts3[ic] + switch { + case !ok1 || !ok2 || !ok3: + t.Errorf("BackplaneFacingCapacity Total not present: ok1 %t, ok2 %t, ok3 %t", ok1, ok2, ok3) + case v1 <= v2 || v1 != v3: + t.Errorf("BackplaneFacingCapacity Total are not valid: v1 %d, v2 %d, v3 %d", v1, v2, v3) + } + + v1, ok1 = tocs1[ic] + v2, ok2 = tocs2[ic] + v3, ok3 = tocs3[ic] + switch { + case !ok1 || !ok2 || !ok3: + t.Errorf("BackplaneFacingCapacity TotalOperationalCapacity not present: ok1 %t, ok2 %t, ok3 %t", ok1, ok2, ok3) + case v1 <= v2 || v1 != v3: + t.Errorf("BackplaneFacingCapacity TotalOperationalCapacity are not valid: v1 %d, v2 %d, v3 %d", v1, v2, v3) + } + + v1, ok1 = apct1[ic] + v2, ok2 = apct2[ic] + v3, ok3 = apct3[ic] + switch { + case !ok1 || !ok2 || !ok3: + t.Errorf("BackplaneFacingCapacity AvailablePct not present: ok1 %t, ok2 %t, ok3 %t", ok1, ok2, ok3) + case v1 <= v2 || v1 != v3: + t.Errorf("BackplaneFacingCapacity AvailablePct are not valid: v1 %d, v2 %d, v3 %d", v1, v2, v3) + } + }) + } +} + +func getBackplaneCapacityCounters(t *testing.T, dut *ondatra.DUTDevice, ics []string) (map[string]uint64, map[string]uint64, map[string]uint64) { + subscribeTimeout := 30 * time.Second + + totals := make(map[string]uint64) + totalOperationalCapacities := make(map[string]uint64) + availablePcts := make(map[string]uint64) + for _, ic := range ics { + if !isCompNameExpected(t, ic, dut.Vendor()) { + continue + } + + t.Run(fmt.Sprintf("Backplane:%s", ic), func(t *testing.T) { + if deviations.BackplaneFacingCapacityUnsupported(dut) { + t.Skipf("Skipping check for BackplanceFacingCapacity due to deviation BackplaneFacingCapacityUnsupported") + } + + ts, ok := gnmi.Watch(t, gnmiOptsForOnChange(t, dut), gnmi.OC().Component(ic).IntegratedCircuit().BackplaneFacingCapacity().Total().State(), subscribeTimeout, func(v *ygnmi.Value[uint64]) bool { + return v.IsPresent() + }).Await(t) + if ok { + v, _ := ts.Val() + totals[ic] = v + } + + tocs, ok := gnmi.Watch(t, gnmiOptsForOnChange(t, dut), gnmi.OC().Component(ic).IntegratedCircuit().BackplaneFacingCapacity().TotalOperationalCapacity().State(), subscribeTimeout, func(v *ygnmi.Value[uint64]) bool { + return v.IsPresent() + }).Await(t) + if ok { + v, _ := tocs.Val() + totalOperationalCapacities[ic] = v + } + + apcts, ok := gnmi.Watch(t, gnmiOptsForOnChange(t, dut), gnmi.OC().Component(ic).IntegratedCircuit().BackplaneFacingCapacity().AvailablePct().State(), subscribeTimeout, func(v *ygnmi.Value[uint16]) bool { + return v.IsPresent() + }).Await(t) + if ok { + v, _ := apcts.Val() + availablePcts[ic] = uint64(v) + } + }) + } + + return totals, totalOperationalCapacities, availablePcts +}