From 18582fbb396dcec7522eff041897e0b4b81e242e Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Thu, 23 Jan 2025 22:39:11 +0000 Subject: [PATCH 1/3] adding test files for 400G ZR++ supply voltage and temperature test --- .../tests/zrp_supply_voltage_test/README.md | 2 +- .../metadata.textproto | 0 .../zrp_supply_voltage_test.go | 111 +++++++++ .../tests/zrp_temperature_test/README.md | 2 +- .../zrp_temperature_test/metadata.textproto | 26 +++ .../zrp_temperature_test.go | 216 ++++++++++++++++++ 6 files changed, 355 insertions(+), 2 deletions(-) create mode 100644 feature/platform/transceiver/supply_voltage/tests/zrp_supply_voltage_test/metadata.textproto create mode 100644 feature/platform/transceiver/supply_voltage/tests/zrp_supply_voltage_test/zrp_supply_voltage_test.go create mode 100644 feature/platform/transceiver/temperature/tests/zrp_temperature_test/metadata.textproto create mode 100644 feature/platform/transceiver/temperature/tests/zrp_temperature_test/zrp_temperature_test.go diff --git a/feature/platform/transceiver/supply_voltage/tests/zrp_supply_voltage_test/README.md b/feature/platform/transceiver/supply_voltage/tests/zrp_supply_voltage_test/README.md index a2c9241920f..966d1db0d2e 100644 --- a/feature/platform/transceiver/supply_voltage/tests/zrp_supply_voltage_test/README.md +++ b/feature/platform/transceiver/supply_voltage/tests/zrp_supply_voltage_test/README.md @@ -1,4 +1,4 @@ -# TRANSCEIVER-12: Telemetry: 400ZR_PLUS Transceiver Supply Voltage streaming. +# TRANSCEIVER-12 (400ZR_PLUS): Telemetry: 400ZR_PLUS Transceiver Supply Voltage streaming. ## Summary diff --git a/feature/platform/transceiver/supply_voltage/tests/zrp_supply_voltage_test/metadata.textproto b/feature/platform/transceiver/supply_voltage/tests/zrp_supply_voltage_test/metadata.textproto new file mode 100644 index 00000000000..e69de29bb2d diff --git a/feature/platform/transceiver/supply_voltage/tests/zrp_supply_voltage_test/zrp_supply_voltage_test.go b/feature/platform/transceiver/supply_voltage/tests/zrp_supply_voltage_test/zrp_supply_voltage_test.go new file mode 100644 index 00000000000..de540c6c485 --- /dev/null +++ b/feature/platform/transceiver/supply_voltage/tests/zrp_supply_voltage_test/zrp_supply_voltage_test.go @@ -0,0 +1,111 @@ +// Copyright 2024 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 zrp_supply_voltage_test + +import ( + "flag" + "fmt" + "reflect" + "testing" + "time" + + "github.com/openconfig/featureprofiles/internal/cfgplugins" + "github.com/openconfig/featureprofiles/internal/components" + "github.com/openconfig/featureprofiles/internal/fptest" + "github.com/openconfig/featureprofiles/internal/samplestream" + "github.com/openconfig/ondatra" + "github.com/openconfig/ondatra/gnmi" + "github.com/openconfig/ondatra/gnmi/oc" +) + +const ( + samplingInterval = 10 * time.Second + intUpdateTime = 5 * time.Minute + targetOutputPower = -3 + frequency = 193100000 +) + +var ( + operationalModeFlag = flag.Int("operational_mode", 5, "vendor-specific operational-mode for the channel") + operationalMode uint16 +) + +func TestMain(m *testing.M) { + fptest.RunTests(m) +} + +func verifyVoltageValue(t *testing.T, pStream *samplestream.SampleStream[float64], path string) float64 { + voltageSample := pStream.Next() + if voltageSample == nil { + t.Fatalf("Voltage telemetry %s was not streamed in the most recent subscription interval", path) + } + voltageVal, ok := voltageSample.Val() + if !ok { + t.Fatalf("Voltage %q telemetry is not present", voltageSample) + } + // Check voltage return value of correct type + if reflect.TypeOf(voltageVal).Kind() != reflect.Float64 { + t.Fatalf("Return value is not type float64") + } + t.Logf("Voltage sample value %s: %v", path, voltageVal) + return voltageVal +} + +func TestZrSupplyVoltage(t *testing.T) { + if operationalModeFlag != nil { + operationalMode = uint16(*operationalModeFlag) + } else { + t.Fatalf("Please specify the vendor-specific operational-mode flag") + } + dut := ondatra.DUT(t, "dut") + dp1 := dut.Port(t, "port1") + dp2 := dut.Port(t, "port2") + och1 := components.OpticalChannelComponentFromPort(t, dut, dp1) + och2 := components.OpticalChannelComponentFromPort(t, dut, dp2) + cfgplugins.ConfigOpticalChannel(t, dut, och1, frequency, targetOutputPower, operationalMode) + cfgplugins.ConfigOpticalChannel(t, dut, och2, frequency, targetOutputPower, operationalMode) + + for _, port := range []string{"port1", "port2"} { + t.Run(fmt.Sprintf("Port:%s", port), func(t *testing.T) { + dp := dut.Port(t, port) + t.Logf("Port %s", dp.Name()) + + gnmi.Await(t, dut, gnmi.OC().Interface(dp.Name()).OperStatus().State(), intUpdateTime, oc.Interface_OperStatus_UP) + + // Derive transceiver names from ports. + tr := gnmi.Get(t, dut, gnmi.OC().Interface(dp.Name()).Transceiver().State()) + component := gnmi.OC().Component(tr) + + streamInst := samplestream.New(t, dut, component.Transceiver().SupplyVoltage().Instant().State(), samplingInterval) + defer streamInst.Close() + + volInst := verifyVoltageValue(t, streamInst, "Instant") + t.Logf("Port %s instant voltage: %v", dp.Name(), volInst) + + // Disable interface + cfgplugins.ToggleInterface(t, dut, dp.Name(), false) + // Wait for the cooling-off period + gnmi.Await(t, dut, gnmi.OC().Interface(dp.Name()).OperStatus().State(), intUpdateTime, oc.Interface_OperStatus_DOWN) + + volInstNew := verifyVoltageValue(t, streamInst, "Instant") + t.Logf("Port %s instant voltage after port down: %v", dp.Name(), volInstNew) + + // Enable interface again. + cfgplugins.ToggleInterface(t, dut, dp.Name(), true) + // Wait for the cooling-off period + gnmi.Await(t, dut, gnmi.OC().Interface(dp.Name()).OperStatus().State(), intUpdateTime, oc.Interface_OperStatus_UP) + }) + } +} diff --git a/feature/platform/transceiver/temperature/tests/zrp_temperature_test/README.md b/feature/platform/transceiver/temperature/tests/zrp_temperature_test/README.md index fb3c44445cf..028121870f9 100644 --- a/feature/platform/transceiver/temperature/tests/zrp_temperature_test/README.md +++ b/feature/platform/transceiver/temperature/tests/zrp_temperature_test/README.md @@ -1,4 +1,4 @@ -# TRANSCEIVER-8: Telemetry: 400ZR_PLUS Optics module temperature streaming. +# TRANSCEIVER-8 (400ZR_PLUS): Telemetry: 400ZR_PLUS Optics module temperature streaming. ## Summary diff --git a/feature/platform/transceiver/temperature/tests/zrp_temperature_test/metadata.textproto b/feature/platform/transceiver/temperature/tests/zrp_temperature_test/metadata.textproto new file mode 100644 index 00000000000..eb1da57414e --- /dev/null +++ b/feature/platform/transceiver/temperature/tests/zrp_temperature_test/metadata.textproto @@ -0,0 +1,26 @@ +# proto-file: third_party/openconfig/featureprofiles/proto/metadata.proto +# proto-message: Metadata + +uuid: "e75c20d2-2f9a-407f-adf8-8d506f74f571" +plan_id: "TRANSCEIVER-8 (400ZR_PLUS)" +description: "Telemetry: 400ZR_PLUS Optics module temperature streaming." +testbed: TESTBED_DUT_400ZR_PLUS +platform_exceptions: { + platform: { + vendor: ARISTA + } + deviations: { + interface_enabled: true + default_network_instance: "default" + missing_port_to_optical_channel_component_mapping: true + missing_zr_optical_channel_tunable_parameters_telemetry: true + } +} +platform_exceptions: { + platform: { + vendor: CISCO + } + deviations: { + use_parent_component_for_temperature_telemetry: true + } +} diff --git a/feature/platform/transceiver/temperature/tests/zrp_temperature_test/zrp_temperature_test.go b/feature/platform/transceiver/temperature/tests/zrp_temperature_test/zrp_temperature_test.go new file mode 100644 index 00000000000..5ecffc8109f --- /dev/null +++ b/feature/platform/transceiver/temperature/tests/zrp_temperature_test/zrp_temperature_test.go @@ -0,0 +1,216 @@ +// Copyright 2022 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 zrp_temperature_test + +import ( + "flag" + "reflect" + "testing" + "time" + + "github.com/openconfig/featureprofiles/internal/cfgplugins" + "github.com/openconfig/featureprofiles/internal/components" + "github.com/openconfig/featureprofiles/internal/deviations" + "github.com/openconfig/featureprofiles/internal/fptest" + "github.com/openconfig/featureprofiles/internal/samplestream" + "github.com/openconfig/ondatra" + "github.com/openconfig/ondatra/gnmi" + "github.com/openconfig/ondatra/gnmi/oc" +) + +const ( + sensorType = oc.PlatformTypes_OPENCONFIG_HARDWARE_COMPONENT_SENSOR + targetOutputPower = -3 + frequency = 193100000 + intUpdateTime = 5 * time.Minute +) + +var ( + operationalModeFlag = flag.Int("operational_mode", 5, "vendor-specific operational-mode for the channel") + operationalMode uint16 +) + +func TestMain(m *testing.M) { + fptest.RunTests(m) +} + +// Topology: +// +// dut:port1 <--> port2:dut + +func verifyTemperatureSensorValue(t *testing.T, pStream *samplestream.SampleStream[float64], sensorName string) float64 { + temperatureSample := pStream.Next() + if temperatureSample == nil { + t.Fatalf("Temperature telemetry %s was not streamed in the most recent subscription interval", sensorName) + } + temperatureVal, ok := temperatureSample.Val() + if !ok { + t.Fatalf("Temperature %q telemetry is not present", temperatureSample) + } + // Check temperature return value of correct type + if reflect.TypeOf(temperatureVal).Kind() != reflect.Float64 { + t.Fatalf("Return value is not type float64") + } else if temperatureVal <= 0 && temperatureVal >= 300 { + t.Fatalf("The variable temperature instent is not between 0 and 300") + } + t.Logf("Temperature sample value %s: %v", sensorName, temperatureVal) + return temperatureVal +} + +func TestZRTemperatureState(t *testing.T) { + if operationalModeFlag != nil { + operationalMode = uint16(*operationalModeFlag) + } else { + t.Fatalf("Please specify the vendor-specific operational-mode flag") + } + dut1 := ondatra.DUT(t, "dut") + dp1 := dut1.Port(t, "port1") + dp2 := dut1.Port(t, "port2") + t.Logf("dut1: %v", dut1) + t.Logf("dut1 dp1 name: %v", dp1.Name()) + och1 := components.OpticalChannelComponentFromPort(t, dut1, dp1) + och2 := components.OpticalChannelComponentFromPort(t, dut1, dp2) + cfgplugins.ConfigOpticalChannel(t, dut1, och1, frequency, targetOutputPower, operationalMode) + cfgplugins.ConfigOpticalChannel(t, dut1, och2, frequency, targetOutputPower, operationalMode) + gnmi.Await(t, dut1, gnmi.OC().Interface(dp1.Name()).OperStatus().State(), intUpdateTime, oc.Interface_OperStatus_UP) + transceiverName := gnmi.Get(t, dut1, gnmi.OC().Interface(dp1.Name()).Transceiver().State()) + // Check if TRANSCEIVER is of type 400ZR_PLUS. + // Uncomment once the Ondatra OC release version is fixed + // if dp1.PMD() != ondatra.PMD400GBASEZRP { + // t.Fatalf("%s Transceiver is not 400ZR_PLUS its of type: %v", transceiverName, dp1.PMD()) + // } + compWithTemperature := gnmi.OC().Component(transceiverName) + if !deviations.UseParentComponentForTemperatureTelemetry(dut1) { + subcomponents := gnmi.LookupAll[*oc.Component_Subcomponent](t, dut1, compWithTemperature.SubcomponentAny().State()) + for _, s := range subcomponents { + subc, ok := s.Val() + if ok { + sensorComponent := gnmi.Get[*oc.Component](t, dut1, gnmi.OC().Component(subc.GetName()).State()) + if sensorComponent.GetType() == sensorType { + scomponent := gnmi.OC().Component(sensorComponent.GetName()) + if scomponent != nil { + compWithTemperature = scomponent + } + } + } + } + } + p1StreamInstant := samplestream.New(t, dut1, compWithTemperature.Temperature().Instant().State(), 10*time.Second) + temperatureInstant := verifyTemperatureSensorValue(t, p1StreamInstant, "Instant") + t.Logf("Port1 dut1 %s Instant Temperature: %v", dp1.Name(), temperatureInstant) + if deviations.MissingZROpticalChannelTunableParametersTelemetry(dut1) { + t.Log("Skipping Min/Max/Avg Tunable Parameters Telemetry validation. Deviation MissingZROpticalChannelTunableParametersTelemetry enabled.") + } else { + p1StreamAvg := samplestream.New(t, dut1, compWithTemperature.Temperature().Avg().State(), 10*time.Second) + p1StreamMin := samplestream.New(t, dut1, compWithTemperature.Temperature().Min().State(), 10*time.Second) + p1StreamMax := samplestream.New(t, dut1, compWithTemperature.Temperature().Max().State(), 10*time.Second) + + temperatureMax := verifyTemperatureSensorValue(t, p1StreamMax, "Max") + t.Logf("Port1 dut1 %s Max Temperature: %v", dp1.Name(), temperatureMax) + temperatureMin := verifyTemperatureSensorValue(t, p1StreamMin, "Min") + t.Logf("Port1 dut1 %s Min Temperature: %v", dp1.Name(), temperatureMin) + temperatureAvg := verifyTemperatureSensorValue(t, p1StreamAvg, "Avg") + t.Logf("Port1 dut1 %s Avg Temperature: %v", dp1.Name(), temperatureAvg) + if temperatureAvg >= temperatureMin && temperatureAvg <= temperatureMax { + t.Logf("The average is between the maximum and minimum values") + } else { + t.Fatalf("The average is not between the maximum and minimum values, Avg:%v Max:%v Min:%v", temperatureAvg, temperatureMax, temperatureMin) + } + p1StreamMin.Close() + p1StreamMax.Close() + p1StreamAvg.Close() + } + p1StreamInstant.Close() +} + +func TestZRTemperatureStateInterfaceFlap(t *testing.T) { + if operationalModeFlag != nil { + operationalMode = uint16(*operationalModeFlag) + } else { + t.Fatalf("Please specify the vendor-specific operational-mode flag") + } + dut1 := ondatra.DUT(t, "dut") + dp1 := dut1.Port(t, "port1") + dp2 := dut1.Port(t, "port2") + t.Logf("dut1: %v", dut1) + t.Logf("dut1 dp1 name: %v", dp1.Name()) + och1 := components.OpticalChannelComponentFromPort(t, dut1, dp1) + och2 := components.OpticalChannelComponentFromPort(t, dut1, dp2) + cfgplugins.ConfigOpticalChannel(t, dut1, och1, frequency, targetOutputPower, operationalMode) + cfgplugins.ConfigOpticalChannel(t, dut1, och2, frequency, targetOutputPower, operationalMode) + gnmi.Await(t, dut1, gnmi.OC().Interface(dp1.Name()).OperStatus().State(), intUpdateTime, oc.Interface_OperStatus_UP) + transceiverName := gnmi.Get(t, dut1, gnmi.OC().Interface(dp1.Name()).Transceiver().State()) + // Check if TRANSCEIVER is of type 400ZR_PLUS + // Uncomment once the Ondatra OC release version is fixed + // if dp1.PMD() != ondatra.PMD400GBASEZRP { + // t.Fatalf("%s Transceiver is not 400ZR_PLUS its of type: %v", transceiverName, dp1.PMD()) + // } + // Disable interface + cfgplugins.ToggleInterface(t, dut1, dp1.Name(), false) + compWithTemperature := gnmi.OC().Component(transceiverName) + if !deviations.UseParentComponentForTemperatureTelemetry(dut1) { + subcomponents := gnmi.LookupAll[*oc.Component_Subcomponent](t, dut1, compWithTemperature.SubcomponentAny().State()) + for _, s := range subcomponents { + subc, ok := s.Val() + if ok { + sensorComponent := gnmi.Get[*oc.Component](t, dut1, gnmi.OC().Component(subc.GetName()).State()) + if sensorComponent.GetType() == sensorType { + scomponent := gnmi.OC().Component(sensorComponent.GetName()) + if scomponent != nil { + compWithTemperature = scomponent + } + } + } + } + } + p1StreamInstant := samplestream.New(t, dut1, compWithTemperature.Temperature().Instant().State(), 10*time.Second) + p1StreamAvg := samplestream.New(t, dut1, compWithTemperature.Temperature().Avg().State(), 10*time.Second) + p1StreamMin := samplestream.New(t, dut1, compWithTemperature.Temperature().Min().State(), 10*time.Second) + p1StreamMax := samplestream.New(t, dut1, compWithTemperature.Temperature().Max().State(), 10*time.Second) + // Wait 120 sec cooling-off period + gnmi.Await(t, dut1, gnmi.OC().Interface(dp1.Name()).OperStatus().State(), intUpdateTime, oc.Interface_OperStatus_DOWN) + temperatureInstant := verifyTemperatureSensorValue(t, p1StreamInstant, "Instant") + t.Logf("Port1 dut1 %s Instant Temperature after interface down: %v", dp1.Name(), temperatureInstant) + if deviations.MissingZROpticalChannelTunableParametersTelemetry(dut1) { + t.Log("Skipping Min/Max/Avg Tunable Parameters Telemetry validation. Deviation MissingZROpticalChannelTunableParametersTelemetry enabled.") + } else { + temperatureMax := verifyTemperatureSensorValue(t, p1StreamMax, "Max") + t.Logf("Port1 dut1 %s Max Temperature: %v", dp1.Name(), temperatureMax) + temperatureMin := verifyTemperatureSensorValue(t, p1StreamMin, "Min") + t.Logf("Port1 dut1 %s Min Temperature: %v", dp1.Name(), temperatureMin) + temperatureAvg := verifyTemperatureSensorValue(t, p1StreamAvg, "Avg") + t.Logf("Port1 dut1 %s Avg Temperature: %v", dp1.Name(), temperatureAvg) + } + // Enable interface + cfgplugins.ToggleInterface(t, dut1, dp1.Name(), true) + gnmi.Await(t, dut1, gnmi.OC().Interface(dp1.Name()).OperStatus().State(), intUpdateTime, oc.Interface_OperStatus_UP) + temperatureInstant = verifyTemperatureSensorValue(t, p1StreamInstant, "Instant") + t.Logf("Port1 dut1 %s Instant Temperature after interface up: %v", dp1.Name(), temperatureInstant) + if deviations.MissingZROpticalChannelTunableParametersTelemetry(dut1) { + t.Log("Skipping Min/Max/Avg Tunable Parameters Telemetry validation. Deviation MissingZROpticalChannelTunableParametersTelemetry enabled.") + } else { + temperatureMax := verifyTemperatureSensorValue(t, p1StreamMax, "Max") + t.Logf("Port1 dut1 %s Max Temperature: %v", dp1.Name(), temperatureMax) + temperatureMin := verifyTemperatureSensorValue(t, p1StreamMin, "Min") + t.Logf("Port1 dut1 %s Min Temperature: %v", dp1.Name(), temperatureMin) + temperatureAvg := verifyTemperatureSensorValue(t, p1StreamAvg, "Avg") + t.Logf("Port1 dut1 %s Avg Temperature: %v", dp1.Name(), temperatureAvg) + if temperatureAvg >= temperatureMin && temperatureAvg <= temperatureMax { + t.Logf("The average is between the maximum and minimum values") + } else { + t.Fatalf("The average is not between the maximum and minimum values") + } + } +} From fbe14769866cf4ffb5ac5d8536a7d054a103757c Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Thu, 23 Jan 2025 22:45:36 +0000 Subject: [PATCH 2/3] adding missing metadata.textproto file for supply voltage test --- .../zrp_supply_voltage_test/metadata.textproto | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/feature/platform/transceiver/supply_voltage/tests/zrp_supply_voltage_test/metadata.textproto b/feature/platform/transceiver/supply_voltage/tests/zrp_supply_voltage_test/metadata.textproto index e69de29bb2d..69505fb49b0 100644 --- a/feature/platform/transceiver/supply_voltage/tests/zrp_supply_voltage_test/metadata.textproto +++ b/feature/platform/transceiver/supply_voltage/tests/zrp_supply_voltage_test/metadata.textproto @@ -0,0 +1,17 @@ +# proto-file: github.com/openconfig/featureprofiles/proto/metadata.proto +# proto-message: Metadata + +uuid: "b8aa3809-068a-4da1-9c29-7ce34c67c965" +plan_id: "TRANSCEIVER-12 (400ZR_PLUS)" +description: "Telemetry: 400ZR_PLUS Transceiver Supply Voltage streaming." +testbed: TESTBED_DUT_400ZR_PLUS +platform_exceptions: { + platform: { + vendor: ARISTA + } + deviations: { + interface_enabled: true + default_network_instance: "default" + missing_port_to_optical_channel_component_mapping: true + } +} From 17394774a208bc5122107765d70ba30d3a66001c Mon Sep 17 00:00:00 2001 From: Jian Chen Date: Thu, 23 Jan 2025 22:48:30 +0000 Subject: [PATCH 3/3] changed path in proto-file of temperature test --- .../temperature/tests/zrp_temperature_test/metadata.textproto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/platform/transceiver/temperature/tests/zrp_temperature_test/metadata.textproto b/feature/platform/transceiver/temperature/tests/zrp_temperature_test/metadata.textproto index eb1da57414e..9e66602bece 100644 --- a/feature/platform/transceiver/temperature/tests/zrp_temperature_test/metadata.textproto +++ b/feature/platform/transceiver/temperature/tests/zrp_temperature_test/metadata.textproto @@ -1,4 +1,4 @@ -# proto-file: third_party/openconfig/featureprofiles/proto/metadata.proto +# proto-file: github.com/openconfig/featureprofiles/proto/metadata.proto # proto-message: Metadata uuid: "e75c20d2-2f9a-407f-adf8-8d506f74f571"