From 4c88b7dc3cfbead81cc2874f7f9ad2ad8b6f8301 Mon Sep 17 00:00:00 2001 From: Pramod Maurya Date: Fri, 24 Jan 2025 09:31:28 +0530 Subject: [PATCH 01/10] rename QoSQueue to QoSClass same as in entity-naming library (#3713) --- .../dscp_transparency_test.go | 16 ++++++++-------- go.mod | 2 +- go.sum | 2 ++ 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/feature/qos/ecn/otg_tests/dscp_transparency_test/dscp_transparency_test.go b/feature/qos/ecn/otg_tests/dscp_transparency_test/dscp_transparency_test.go index 921451ad2bb..adabdd526dc 100644 --- a/feature/qos/ecn/otg_tests/dscp_transparency_test/dscp_transparency_test.go +++ b/feature/qos/ecn/otg_tests/dscp_transparency_test/dscp_transparency_test.go @@ -115,7 +115,7 @@ var ( "port3": atePort3, } - allQueueNames = []entname.QoSQueue{ + allQueueNames = []entname.QoSClass{ entname.QoSNC1, entname.QoSAF4, entname.QoSAF3, @@ -128,7 +128,7 @@ var ( testCases = []struct { name string createFlowsF func(otgConfig gosnappi.Config, protocol string, atePortSpeed int) - validateFlowsF func(t *testing.T, dut *ondatra.DUTDevice, ate *ondatra.ATEDevice, atePortSpeed int, startingCounters map[entname.QoSQueue]*queueCounters) + validateFlowsF func(t *testing.T, dut *ondatra.DUTDevice, ate *ondatra.ATEDevice, atePortSpeed int, startingCounters map[entname.QoSClass]*queueCounters) }{ { name: "TestNoCongestion", @@ -444,10 +444,10 @@ func createFlow(otgConfig gosnappi.Config, protocol string, targetTotalFlowRate return flow } -func getQueueCounters(t *testing.T, dut *ondatra.DUTDevice) map[entname.QoSQueue]*queueCounters { +func getQueueCounters(t *testing.T, dut *ondatra.DUTDevice) map[entname.QoSClass]*queueCounters { t.Helper() ep := dut.Port(t, dutEgressPort) - qc := map[entname.QoSQueue]*queueCounters{} + qc := map[entname.QoSClass]*queueCounters{} for _, egressQueueName := range allQueueNames { qc[egressQueueName] = &queueCounters{ @@ -460,7 +460,7 @@ func getQueueCounters(t *testing.T, dut *ondatra.DUTDevice) map[entname.QoSQueue return qc } -func logAndGetResolvedQueueCounters(t *testing.T, egressQueueName entname.QoSQueue, egressQueueStartingCounters, egressQueueEndingCounters *queueCounters) (uint64, uint64, uint64) { +func logAndGetResolvedQueueCounters(t *testing.T, egressQueueName entname.QoSClass, egressQueueStartingCounters, egressQueueEndingCounters *queueCounters) (uint64, uint64, uint64) { queueDroppedPackets := egressQueueEndingCounters.droppedPackets - egressQueueStartingCounters.droppedPackets queueTransmitPackets := egressQueueEndingCounters.transmitPackets - egressQueueStartingCounters.transmitPackets queueTransmitOctets := egressQueueEndingCounters.transmitOctets - egressQueueStartingCounters.transmitOctets @@ -517,7 +517,7 @@ func testNoCongestionCreateFlows(otgConfig gosnappi.Config, protocol string, dut } } -func testNoCongestionValidateFlows(t *testing.T, dut *ondatra.DUTDevice, ate *ondatra.ATEDevice, dutPortSpeed int, startingCounters map[entname.QoSQueue]*queueCounters) { +func testNoCongestionValidateFlows(t *testing.T, dut *ondatra.DUTDevice, ate *ondatra.ATEDevice, dutPortSpeed int, startingCounters map[entname.QoSClass]*queueCounters) { maxAllowedZeroPackets, _ := getZeroIshThresholds(dutPortSpeed) endingCounters := getQueueCounters(t, dut) @@ -607,7 +607,7 @@ func testCongestionCreateFlows(otgConfig gosnappi.Config, protocol string, dutPo } } -func testCongestionValidateFlows(t *testing.T, dut *ondatra.DUTDevice, ate *ondatra.ATEDevice, dutPortSpeed int, startingCounters map[entname.QoSQueue]*queueCounters) { +func testCongestionValidateFlows(t *testing.T, dut *ondatra.DUTDevice, ate *ondatra.ATEDevice, dutPortSpeed int, startingCounters map[entname.QoSClass]*queueCounters) { maxAllowedZeroPackets, _ := getZeroIshThresholds(dutPortSpeed) endingCounters := getQueueCounters(t, dut) @@ -741,7 +741,7 @@ func testNC1CongestionCreateFlows(otgConfig gosnappi.Config, protocol string, du } } -func testNC1CongestionValidateFlows(t *testing.T, dut *ondatra.DUTDevice, ate *ondatra.ATEDevice, dutPortSpeed int, startingCounters map[entname.QoSQueue]*queueCounters) { +func testNC1CongestionValidateFlows(t *testing.T, dut *ondatra.DUTDevice, ate *ondatra.ATEDevice, dutPortSpeed int, startingCounters map[entname.QoSClass]*queueCounters) { maxAllowedZeroPackets, maxAllowedZeroOctets := getZeroIshThresholds(dutPortSpeed) endingCounters := getQueueCounters(t, dut) diff --git a/go.mod b/go.mod index 269c599baa8..278de33bcf2 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/kr/pretty v0.3.1 github.com/open-traffic-generator/snappi/gosnappi v1.3.0 github.com/openconfig/containerz v0.0.0-20250119143156-ea1f112cd31c - github.com/openconfig/entity-naming v0.0.0-20230912181021-7ac806551a31 + github.com/openconfig/entity-naming v0.0.0-20250108173956-784f643e8b64 github.com/openconfig/gnmi v0.11.0 github.com/openconfig/gnoi v0.6.0 github.com/openconfig/gnoigo v0.0.0-20240320202954-ebd033e3542c diff --git a/go.sum b/go.sum index 09c4333466f..c34a20aa9ee 100644 --- a/go.sum +++ b/go.sum @@ -1658,6 +1658,8 @@ github.com/openconfig/containerz v0.0.0-20250119143156-ea1f112cd31c h1:4WtTr8Iv2 github.com/openconfig/containerz v0.0.0-20250119143156-ea1f112cd31c/go.mod h1:VcT2W5ddds98x7CS2r7q1tnUICgflBQ3Wv9rmRkb5TQ= github.com/openconfig/entity-naming v0.0.0-20230912181021-7ac806551a31 h1:K/9O+J20+liIof8WjquMydnebD0N1U9ItjhJYF6H4hg= github.com/openconfig/entity-naming v0.0.0-20230912181021-7ac806551a31/go.mod h1:ZRUrfwYYY+pLaOoWPad3p/8J4LLQcSqtXhBCkD2pXJc= +github.com/openconfig/entity-naming v0.0.0-20250108173956-784f643e8b64 h1:pS4NcCl49ker3FYRkvY+erNUw1CgL/lB8gnDQbax6Yk= +github.com/openconfig/entity-naming v0.0.0-20250108173956-784f643e8b64/go.mod h1:FDF5sbP9BbP2IM6EUopcAWfGJ5OPZ4VV2EYQ9vvqLjA= github.com/openconfig/gnmi v0.0.0-20200414194230-1597cc0f2600/go.mod h1:M/EcuapNQgvzxo1DDXHK4tx3QpYM/uG4l591v33jG2A= github.com/openconfig/gnmi v0.0.0-20200508230933-d19cebf5e7be/go.mod h1:M/EcuapNQgvzxo1DDXHK4tx3QpYM/uG4l591v33jG2A= github.com/openconfig/gnmi v0.10.0/go.mod h1:Y9os75GmSkhHw2wX8sMsxfI7qRGAEcDh8NTa5a8vj6E= From 52e90a36d9e12d81cdd25bc25d680f017c96a936 Mon Sep 17 00:00:00 2001 From: rszarecki <46606165+rszarecki@users.noreply.github.com> Date: Fri, 24 Jan 2025 07:51:58 -0800 Subject: [PATCH 02/10] Removing deviations no longer needed (#3708) --- .../otg_tests/route_summary_counters_test/metadata.textproto | 1 - .../otg_tests/scale_aft_summary/metadata.textproto | 1 - .../otg_tests/route_propagation_test/metadata.textproto | 1 - .../otg_tests/admin_distance_test/metadata.textproto | 3 --- .../bgp_long_lived_graceful_restart/metadata.textproto | 1 - .../bgp_isis_redistribution_test/metadata.textproto | 5 ----- .../ate_tests/bgp_graceful_restart_test/metadata.textproto | 1 - .../otg_tests/bgp_multipath_ecmp_test/metadata.textproto | 1 - .../metadata.textproto | 1 - feature/bgp/otg_tests/bgp_2byte_4byte_asn/metadata.textproto | 1 - .../bgp_2byte_4byte_asn_policy_test/metadata.textproto | 1 - .../bgp/otg_tests/bgp_afi_safi_defaults/metadata.textproto | 1 - .../bgp/otg_tests/bgp_always_compare_med/metadata.textproto | 1 - .../metadata.textproto | 1 - .../metadata.textproto | 1 - .../otg_tests/aspath_and_community_test/metadata.textproto | 2 -- .../bgp/policybase/otg_tests/aspath_test/metadata.textproto | 3 --- .../otg_tests/chained_policies_test/metadata.textproto | 1 - .../policybase/otg_tests/community_test/metadata.textproto | 3 --- .../otg_tests/default_policies_test/metadata.textproto | 1 - .../otg_tests/import_export_multi_test/metadata.textproto | 3 --- .../otg_tests/link_bandwidth_test/metadata.textproto | 3 --- .../policybase/otg_tests/nested_policies/metadata.textproto | 1 - .../policybase/otg_tests/prefix_set_test/metadata.textproto | 1 - .../otg_tests/route_installation_test/metadata.textproto | 1 - .../otg_tests/bgp_prefix_limit_test/metadata.textproto | 1 - .../static_route_bgp_redistribution_test/metadata.textproto | 4 ---- feature/bgp/tests/local_bgp_test/metadata.textproto | 1 - .../metadata.textproto | 1 - .../fib_failed_due_to_hw_res_exhaust_test/metadata.textproto | 1 - feature/gribi/otg_tests/gribi_route_test/metadata.textproto | 1 - .../aggregate_all_not_viable_test/metadata.textproto | 1 - .../otg_tests/graceful_restart_helper/metadata.textproto | 1 - .../otg_tests/graceful_restart_restarting/metadata.textproto | 1 - .../static_route_isis_redistribution/metadata.textproto | 5 ----- feature/isis/otg_tests/weighted_ecmp_test/metadata.textproto | 1 - .../otg_tests/utilization_test/metadata.textproto | 1 - .../basic_static_route_support_test/metadata.textproto | 5 ----- .../metadata.textproto | 1 - .../tests/full_configuration_replace_test/metadata.textproto | 1 - .../otg_tests/management_ha_test/metadata.textproto | 3 --- 41 files changed, 69 deletions(-) diff --git a/feature/aft/afts_summary/otg_tests/route_summary_counters_test/metadata.textproto b/feature/aft/afts_summary/otg_tests/route_summary_counters_test/metadata.textproto index 617ae227d00..bef6a660d74 100644 --- a/feature/aft/afts_summary/otg_tests/route_summary_counters_test/metadata.textproto +++ b/feature/aft/afts_summary/otg_tests/route_summary_counters_test/metadata.textproto @@ -49,7 +49,6 @@ platform_exceptions: { default_network_instance: "default" isis_instance_enabled_required: true isis_interface_afi_unsupported: true - route_policy_under_afi_unsupported: true } } diff --git a/feature/aft/afts_summary/otg_tests/scale_aft_summary/metadata.textproto b/feature/aft/afts_summary/otg_tests/scale_aft_summary/metadata.textproto index d61d4590b2b..8fb1fdbbe4e 100644 --- a/feature/aft/afts_summary/otg_tests/scale_aft_summary/metadata.textproto +++ b/feature/aft/afts_summary/otg_tests/scale_aft_summary/metadata.textproto @@ -49,6 +49,5 @@ platform_exceptions: { default_network_instance: "default" isis_instance_enabled_required: true isis_interface_afi_unsupported: true - route_policy_under_afi_unsupported: true } } diff --git a/feature/bgp/addpath/otg_tests/route_propagation_test/metadata.textproto b/feature/bgp/addpath/otg_tests/route_propagation_test/metadata.textproto index db7e7b16a42..86a84f7be76 100644 --- a/feature/bgp/addpath/otg_tests/route_propagation_test/metadata.textproto +++ b/feature/bgp/addpath/otg_tests/route_propagation_test/metadata.textproto @@ -28,7 +28,6 @@ platform_exceptions: { vendor: ARISTA } deviations: { - route_policy_under_afi_unsupported: true omit_l2_mtu: true interface_enabled: true default_network_instance: "default" diff --git a/feature/bgp/admin_distance/otg_tests/admin_distance_test/metadata.textproto b/feature/bgp/admin_distance/otg_tests/admin_distance_test/metadata.textproto index 42c8e91175e..c4c16ab351a 100644 --- a/feature/bgp/admin_distance/otg_tests/admin_distance_test/metadata.textproto +++ b/feature/bgp/admin_distance/otg_tests/admin_distance_test/metadata.textproto @@ -16,9 +16,6 @@ platform_exceptions: { interface_enabled: true default_network_instance: "default" isis_interface_afi_unsupported: true - skip_isis_set_level: true - skip_set_rp_match_set_options: true - skip_setting_disable_metric_propagation: true skip_setting_statement_for_policy: true } } diff --git a/feature/bgp/ate_tests/bgp_long_lived_graceful_restart/metadata.textproto b/feature/bgp/ate_tests/bgp_long_lived_graceful_restart/metadata.textproto index 004e3e5a3e6..ca088902401 100644 --- a/feature/bgp/ate_tests/bgp_long_lived_graceful_restart/metadata.textproto +++ b/feature/bgp/ate_tests/bgp_long_lived_graceful_restart/metadata.textproto @@ -36,7 +36,6 @@ platform_exceptions: { vendor: ARISTA } deviations: { - route_policy_under_afi_unsupported: true omit_l2_mtu: true interface_config_vrf_before_address: true deprecated_vlan_id: true diff --git a/feature/bgp/bgp_isis_redistribution/otg_tests/bgp_isis_redistribution_test/metadata.textproto b/feature/bgp/bgp_isis_redistribution/otg_tests/bgp_isis_redistribution_test/metadata.textproto index a3769f0ac2c..42840934722 100644 --- a/feature/bgp/bgp_isis_redistribution/otg_tests/bgp_isis_redistribution_test/metadata.textproto +++ b/feature/bgp/bgp_isis_redistribution/otg_tests/bgp_isis_redistribution_test/metadata.textproto @@ -11,16 +11,11 @@ platform_exceptions: { } deviations: { isis_instance_enabled_required: true - route_policy_under_afi_unsupported: true omit_l2_mtu: true missing_value_for_defaults: true interface_enabled: true default_network_instance: "default" isis_interface_afi_unsupported: true - skip_isis_set_level: true - skip_isis_set_metric_style_type: true - skip_set_rp_match_set_options: true - skip_setting_disable_metric_propagation: true } } platform_exceptions: { diff --git a/feature/bgp/gracefulrestart/ate_tests/bgp_graceful_restart_test/metadata.textproto b/feature/bgp/gracefulrestart/ate_tests/bgp_graceful_restart_test/metadata.textproto index 6bb6b0f824b..193098ce145 100644 --- a/feature/bgp/gracefulrestart/ate_tests/bgp_graceful_restart_test/metadata.textproto +++ b/feature/bgp/gracefulrestart/ate_tests/bgp_graceful_restart_test/metadata.textproto @@ -28,7 +28,6 @@ platform_exceptions: { vendor: ARISTA } deviations: { - route_policy_under_afi_unsupported: true omit_l2_mtu: true interface_enabled: true default_network_instance: "default" diff --git a/feature/bgp/multipath/otg_tests/bgp_multipath_ecmp_test/metadata.textproto b/feature/bgp/multipath/otg_tests/bgp_multipath_ecmp_test/metadata.textproto index b696e86ea0b..6a3d6250365 100644 --- a/feature/bgp/multipath/otg_tests/bgp_multipath_ecmp_test/metadata.textproto +++ b/feature/bgp/multipath/otg_tests/bgp_multipath_ecmp_test/metadata.textproto @@ -39,7 +39,6 @@ platform_exceptions: { vendor: ARISTA } deviations: { - route_policy_under_afi_unsupported: true omit_l2_mtu: true interface_enabled: true default_network_instance: "default" diff --git a/feature/bgp/multipath/otg_tests/bgp_multipath_wecmp_lbw_community_test/metadata.textproto b/feature/bgp/multipath/otg_tests/bgp_multipath_wecmp_lbw_community_test/metadata.textproto index 1f758c5b4f5..aa6885aa842 100644 --- a/feature/bgp/multipath/otg_tests/bgp_multipath_wecmp_lbw_community_test/metadata.textproto +++ b/feature/bgp/multipath/otg_tests/bgp_multipath_wecmp_lbw_community_test/metadata.textproto @@ -39,7 +39,6 @@ platform_exceptions: { vendor: ARISTA } deviations: { - route_policy_under_afi_unsupported: true omit_l2_mtu: true interface_enabled: true default_network_instance: "default" diff --git a/feature/bgp/otg_tests/bgp_2byte_4byte_asn/metadata.textproto b/feature/bgp/otg_tests/bgp_2byte_4byte_asn/metadata.textproto index 18a90886ebd..e9806a57b2a 100644 --- a/feature/bgp/otg_tests/bgp_2byte_4byte_asn/metadata.textproto +++ b/feature/bgp/otg_tests/bgp_2byte_4byte_asn/metadata.textproto @@ -10,7 +10,6 @@ platform_exceptions: { vendor: ARISTA } deviations: { - route_policy_under_afi_unsupported: true omit_l2_mtu: true network_instance_table_deletion_required: true interface_enabled: true diff --git a/feature/bgp/otg_tests/bgp_2byte_4byte_asn_policy_test/metadata.textproto b/feature/bgp/otg_tests/bgp_2byte_4byte_asn_policy_test/metadata.textproto index 58e2412e7cb..d2e9240bb24 100644 --- a/feature/bgp/otg_tests/bgp_2byte_4byte_asn_policy_test/metadata.textproto +++ b/feature/bgp/otg_tests/bgp_2byte_4byte_asn_policy_test/metadata.textproto @@ -30,7 +30,6 @@ platform_exceptions: { vendor: ARISTA } deviations: { - route_policy_under_afi_unsupported: true omit_l2_mtu: true interface_enabled: true default_network_instance: "default" diff --git a/feature/bgp/otg_tests/bgp_afi_safi_defaults/metadata.textproto b/feature/bgp/otg_tests/bgp_afi_safi_defaults/metadata.textproto index 070b871264d..8f222a52f9d 100644 --- a/feature/bgp/otg_tests/bgp_afi_safi_defaults/metadata.textproto +++ b/feature/bgp/otg_tests/bgp_afi_safi_defaults/metadata.textproto @@ -36,7 +36,6 @@ platform_exceptions: { vendor: ARISTA } deviations: { - route_policy_under_afi_unsupported: true omit_l2_mtu: true network_instance_table_deletion_required: true interface_enabled: true diff --git a/feature/bgp/otg_tests/bgp_always_compare_med/metadata.textproto b/feature/bgp/otg_tests/bgp_always_compare_med/metadata.textproto index ecf4c782d29..1aea5f11c14 100644 --- a/feature/bgp/otg_tests/bgp_always_compare_med/metadata.textproto +++ b/feature/bgp/otg_tests/bgp_always_compare_med/metadata.textproto @@ -19,7 +19,6 @@ platform_exceptions: { vendor: ARISTA } deviations: { - route_policy_under_afi_unsupported: true omit_l2_mtu: true interface_enabled: true default_network_instance: "default" diff --git a/feature/bgp/otg_tests/bgp_override_as_path_split_horizon_test/metadata.textproto b/feature/bgp/otg_tests/bgp_override_as_path_split_horizon_test/metadata.textproto index b4b418d51e2..f1f229cf639 100644 --- a/feature/bgp/otg_tests/bgp_override_as_path_split_horizon_test/metadata.textproto +++ b/feature/bgp/otg_tests/bgp_override_as_path_split_horizon_test/metadata.textproto @@ -19,7 +19,6 @@ platform_exceptions: { vendor: ARISTA } deviations: { - route_policy_under_afi_unsupported: true omit_l2_mtu: true interface_enabled: true default_network_instance: "default" diff --git a/feature/bgp/policybase/otg_tests/actions_med_localpref_prepend_flow_control/metadata.textproto b/feature/bgp/policybase/otg_tests/actions_med_localpref_prepend_flow_control/metadata.textproto index c11bd3995b2..d5e98b570c4 100644 --- a/feature/bgp/policybase/otg_tests/actions_med_localpref_prepend_flow_control/metadata.textproto +++ b/feature/bgp/policybase/otg_tests/actions_med_localpref_prepend_flow_control/metadata.textproto @@ -42,7 +42,6 @@ platform_exceptions: { vendor: ARISTA } deviations: { - route_policy_under_afi_unsupported: true omit_l2_mtu: true interface_enabled: true default_network_instance: "default" diff --git a/feature/bgp/policybase/otg_tests/aspath_and_community_test/metadata.textproto b/feature/bgp/policybase/otg_tests/aspath_and_community_test/metadata.textproto index 6075ea0b951..ea6cc928d37 100644 --- a/feature/bgp/policybase/otg_tests/aspath_and_community_test/metadata.textproto +++ b/feature/bgp/policybase/otg_tests/aspath_and_community_test/metadata.textproto @@ -17,8 +17,6 @@ platform_exceptions: { missing_value_for_defaults: true interface_enabled: true default_network_instance: "default" - skip_set_rp_match_set_options: true - skip_setting_disable_metric_propagation: true } } diff --git a/feature/bgp/policybase/otg_tests/aspath_test/metadata.textproto b/feature/bgp/policybase/otg_tests/aspath_test/metadata.textproto index c59c7f78251..a8d477d1315 100644 --- a/feature/bgp/policybase/otg_tests/aspath_test/metadata.textproto +++ b/feature/bgp/policybase/otg_tests/aspath_test/metadata.textproto @@ -11,13 +11,10 @@ platform_exceptions: { vendor: ARISTA } deviations: { - route_policy_under_afi_unsupported: true omit_l2_mtu: true missing_value_for_defaults: true interface_enabled: true default_network_instance: "default" - skip_set_rp_match_set_options: true - skip_setting_disable_metric_propagation: true } } platform_exceptions: { diff --git a/feature/bgp/policybase/otg_tests/chained_policies_test/metadata.textproto b/feature/bgp/policybase/otg_tests/chained_policies_test/metadata.textproto index 6dc207736c3..91a502a1acd 100644 --- a/feature/bgp/policybase/otg_tests/chained_policies_test/metadata.textproto +++ b/feature/bgp/policybase/otg_tests/chained_policies_test/metadata.textproto @@ -14,7 +14,6 @@ platform_exceptions: { interface_enabled: true default_network_instance: "default" missing_value_for_defaults: true - skip_set_rp_match_set_options: true default_import_export_policy_unsupported: false skip_setting_statement_for_policy: true } diff --git a/feature/bgp/policybase/otg_tests/community_test/metadata.textproto b/feature/bgp/policybase/otg_tests/community_test/metadata.textproto index 68da71ad8f8..c1ec937eca4 100644 --- a/feature/bgp/policybase/otg_tests/community_test/metadata.textproto +++ b/feature/bgp/policybase/otg_tests/community_test/metadata.textproto @@ -11,13 +11,10 @@ platform_exceptions: { vendor: ARISTA } deviations: { - route_policy_under_afi_unsupported: true omit_l2_mtu: true missing_value_for_defaults: true interface_enabled: true default_network_instance: "default" - skip_set_rp_match_set_options: true - skip_setting_disable_metric_propagation: true } } platform_exceptions: { diff --git a/feature/bgp/policybase/otg_tests/default_policies_test/metadata.textproto b/feature/bgp/policybase/otg_tests/default_policies_test/metadata.textproto index 21a048a2b80..c668c4dd4d3 100644 --- a/feature/bgp/policybase/otg_tests/default_policies_test/metadata.textproto +++ b/feature/bgp/policybase/otg_tests/default_policies_test/metadata.textproto @@ -24,7 +24,6 @@ platform_exceptions: { missing_isis_interface_afi_safi_enable: true isis_interface_afi_unsupported: true isis_instance_enabled_required: true - default_import_export_policy_unsupported: true bgp_default_policy_unsupported: true } } diff --git a/feature/bgp/policybase/otg_tests/import_export_multi_test/metadata.textproto b/feature/bgp/policybase/otg_tests/import_export_multi_test/metadata.textproto index 98502cb3188..959c157bc9e 100644 --- a/feature/bgp/policybase/otg_tests/import_export_multi_test/metadata.textproto +++ b/feature/bgp/policybase/otg_tests/import_export_multi_test/metadata.textproto @@ -16,10 +16,7 @@ platform_exceptions: { interface_enabled: true default_network_instance: "default" missing_value_for_defaults: true - skip_set_rp_match_set_options: true - bgp_community_set_refs_unsupported: true bgp_community_member_is_a_string: true - skip_bgp_send_community_type: true } } platform_exceptions: { diff --git a/feature/bgp/policybase/otg_tests/link_bandwidth_test/metadata.textproto b/feature/bgp/policybase/otg_tests/link_bandwidth_test/metadata.textproto index e5e9757204d..f0c47372b81 100644 --- a/feature/bgp/policybase/otg_tests/link_bandwidth_test/metadata.textproto +++ b/feature/bgp/policybase/otg_tests/link_bandwidth_test/metadata.textproto @@ -10,13 +10,10 @@ platform_exceptions: { vendor: ARISTA } deviations: { - route_policy_under_afi_unsupported: true omit_l2_mtu: true missing_value_for_defaults: true interface_enabled: true default_network_instance: "default" - skip_set_rp_match_set_options: true - skip_setting_disable_metric_propagation: true bgp_extended_community_index_unsupported: true } } diff --git a/feature/bgp/policybase/otg_tests/nested_policies/metadata.textproto b/feature/bgp/policybase/otg_tests/nested_policies/metadata.textproto index beed0cdd3fd..dce970ff455 100644 --- a/feature/bgp/policybase/otg_tests/nested_policies/metadata.textproto +++ b/feature/bgp/policybase/otg_tests/nested_policies/metadata.textproto @@ -14,7 +14,6 @@ platform_exceptions: { interface_enabled: true default_network_instance: "default" missing_value_for_defaults: true - skip_set_rp_match_set_options: true routing_policy_chaining_unsupported: true } } diff --git a/feature/bgp/policybase/otg_tests/prefix_set_test/metadata.textproto b/feature/bgp/policybase/otg_tests/prefix_set_test/metadata.textproto index 159d68be6a0..53a20acb188 100644 --- a/feature/bgp/policybase/otg_tests/prefix_set_test/metadata.textproto +++ b/feature/bgp/policybase/otg_tests/prefix_set_test/metadata.textproto @@ -27,7 +27,6 @@ platform_exceptions: { default_network_instance: "default" missing_value_for_defaults: true skip_set_rp_match_set_options: true - default_import_export_policy_unsupported: true } } platform_exceptions: { diff --git a/feature/bgp/policybase/otg_tests/route_installation_test/metadata.textproto b/feature/bgp/policybase/otg_tests/route_installation_test/metadata.textproto index eed0f9af8a2..389f5463bd3 100644 --- a/feature/bgp/policybase/otg_tests/route_installation_test/metadata.textproto +++ b/feature/bgp/policybase/otg_tests/route_installation_test/metadata.textproto @@ -29,7 +29,6 @@ platform_exceptions: { vendor: ARISTA } deviations: { - route_policy_under_afi_unsupported: true omit_l2_mtu: true interface_enabled: true default_network_instance: "default" diff --git a/feature/bgp/prefixlimit/otg_tests/bgp_prefix_limit_test/metadata.textproto b/feature/bgp/prefixlimit/otg_tests/bgp_prefix_limit_test/metadata.textproto index 3ffa1ab9deb..5dfec262b82 100644 --- a/feature/bgp/prefixlimit/otg_tests/bgp_prefix_limit_test/metadata.textproto +++ b/feature/bgp/prefixlimit/otg_tests/bgp_prefix_limit_test/metadata.textproto @@ -38,7 +38,6 @@ platform_exceptions: { vendor: ARISTA } deviations: { - route_policy_under_afi_unsupported: true omit_l2_mtu: true interface_enabled: true default_network_instance: "default" diff --git a/feature/bgp/static_route_bgp_redistribution/otg_tests/static_route_bgp_redistribution_test/metadata.textproto b/feature/bgp/static_route_bgp_redistribution/otg_tests/static_route_bgp_redistribution_test/metadata.textproto index 03580ac4f2c..4a1d861f80a 100644 --- a/feature/bgp/static_route_bgp_redistribution/otg_tests/static_route_bgp_redistribution_test/metadata.textproto +++ b/feature/bgp/static_route_bgp_redistribution/otg_tests/static_route_bgp_redistribution_test/metadata.textproto @@ -18,7 +18,6 @@ platform_exceptions: { skip_set_rp_match_set_options: true skip_prefix_set_mode: true table_connections_unsupported: true - use_vendor_native_tag_set_config: true skip_bgp_send_community_type: true } } @@ -31,10 +30,7 @@ platform_exceptions: { default_network_instance: "default" interface_enabled: true static_protocol_name: "STATIC" - skip_bgp_send_community_type: true - skip_setting_disable_metric_propagation: true same_policy_attached_to_all_afis: true - set_metric_as_preference: true } } platform_exceptions: { diff --git a/feature/bgp/tests/local_bgp_test/metadata.textproto b/feature/bgp/tests/local_bgp_test/metadata.textproto index b64b1439ba4..9c6cd72851e 100644 --- a/feature/bgp/tests/local_bgp_test/metadata.textproto +++ b/feature/bgp/tests/local_bgp_test/metadata.textproto @@ -32,7 +32,6 @@ platform_exceptions: { } deviations: { connect_retry: true - route_policy_under_afi_unsupported: true omit_l2_mtu: true network_instance_table_deletion_required: true missing_value_for_defaults: true diff --git a/feature/bgp/timers/otg_tests/bgp_keepalive_and_holdtimer_configuration_test/metadata.textproto b/feature/bgp/timers/otg_tests/bgp_keepalive_and_holdtimer_configuration_test/metadata.textproto index d9df992f174..279a2bc5dd5 100644 --- a/feature/bgp/timers/otg_tests/bgp_keepalive_and_holdtimer_configuration_test/metadata.textproto +++ b/feature/bgp/timers/otg_tests/bgp_keepalive_and_holdtimer_configuration_test/metadata.textproto @@ -29,7 +29,6 @@ platform_exceptions: { vendor: ARISTA } deviations: { - route_policy_under_afi_unsupported: true omit_l2_mtu: true interface_enabled: true default_network_instance: "default" diff --git a/feature/gribi/otg_tests/fib_failed_due_to_hw_res_exhaust_test/metadata.textproto b/feature/gribi/otg_tests/fib_failed_due_to_hw_res_exhaust_test/metadata.textproto index 179ddbcc314..d14c3475525 100644 --- a/feature/gribi/otg_tests/fib_failed_due_to_hw_res_exhaust_test/metadata.textproto +++ b/feature/gribi/otg_tests/fib_failed_due_to_hw_res_exhaust_test/metadata.textproto @@ -36,7 +36,6 @@ platform_exceptions: { vendor: ARISTA } deviations: { - route_policy_under_afi_unsupported: true omit_l2_mtu: true interface_enabled: true default_network_instance: "default" diff --git a/feature/gribi/otg_tests/gribi_route_test/metadata.textproto b/feature/gribi/otg_tests/gribi_route_test/metadata.textproto index 333a3e00ed4..23b4d0caa8f 100644 --- a/feature/gribi/otg_tests/gribi_route_test/metadata.textproto +++ b/feature/gribi/otg_tests/gribi_route_test/metadata.textproto @@ -45,7 +45,6 @@ platform_exceptions: { isis_interface_afi_unsupported: true missing_isis_interface_afi_safi_enable: true isis_require_same_l1_metric_with_l2_metric: true - route_policy_under_afi_unsupported: true static_protocol_name: "STATIC" aggregate_atomic_update: true missing_value_for_defaults: true diff --git a/feature/interface/aggregate/otg_tests/aggregate_all_not_viable_test/metadata.textproto b/feature/interface/aggregate/otg_tests/aggregate_all_not_viable_test/metadata.textproto index aedbceb764b..35428c812c4 100644 --- a/feature/interface/aggregate/otg_tests/aggregate_all_not_viable_test/metadata.textproto +++ b/feature/interface/aggregate/otg_tests/aggregate_all_not_viable_test/metadata.textproto @@ -45,7 +45,6 @@ platform_exceptions: { isis_interface_afi_unsupported: true missing_isis_interface_afi_safi_enable: true isis_require_same_l1_metric_with_l2_metric: true - route_policy_under_afi_unsupported: true static_protocol_name: "STATIC" aggregate_atomic_update: true missing_value_for_defaults: true diff --git a/feature/isis/otg_tests/graceful_restart_helper/metadata.textproto b/feature/isis/otg_tests/graceful_restart_helper/metadata.textproto index bd3ca85f0ae..0c495e60d7a 100644 --- a/feature/isis/otg_tests/graceful_restart_helper/metadata.textproto +++ b/feature/isis/otg_tests/graceful_restart_helper/metadata.textproto @@ -16,6 +16,5 @@ platform_exceptions: { isis_interface_afi_unsupported: true isis_instance_enabled_required: true missing_value_for_defaults: true - skip_isis_set_level: true } } \ No newline at end of file diff --git a/feature/isis/otg_tests/graceful_restart_restarting/metadata.textproto b/feature/isis/otg_tests/graceful_restart_restarting/metadata.textproto index 7adf6d82d19..330cb133b91 100644 --- a/feature/isis/otg_tests/graceful_restart_restarting/metadata.textproto +++ b/feature/isis/otg_tests/graceful_restart_restarting/metadata.textproto @@ -16,6 +16,5 @@ platform_exceptions: { isis_interface_afi_unsupported: true isis_instance_enabled_required: true missing_value_for_defaults: true - skip_isis_set_level: true } } \ No newline at end of file diff --git a/feature/isis/otg_tests/static_route_isis_redistribution/metadata.textproto b/feature/isis/otg_tests/static_route_isis_redistribution/metadata.textproto index 2e9a824e2c1..ce30ef694e5 100644 --- a/feature/isis/otg_tests/static_route_isis_redistribution/metadata.textproto +++ b/feature/isis/otg_tests/static_route_isis_redistribution/metadata.textproto @@ -26,12 +26,7 @@ platform_exceptions: { isis_interface_afi_unsupported: true isis_instance_enabled_required: true missing_value_for_defaults: true - skip_isis_set_level: true - skip_setting_disable_metric_propagation: true - ipv6_static_route_with_ipv4_next_hop_requires_static_arp: true - routing_policy_tag_set_embedded: true same_policy_attached_to_all_afis: true - match_tag_set_condition_unsupported: true } } platform_exceptions: { diff --git a/feature/isis/otg_tests/weighted_ecmp_test/metadata.textproto b/feature/isis/otg_tests/weighted_ecmp_test/metadata.textproto index 947afd21cf8..8c66bd70839 100644 --- a/feature/isis/otg_tests/weighted_ecmp_test/metadata.textproto +++ b/feature/isis/otg_tests/weighted_ecmp_test/metadata.textproto @@ -17,7 +17,6 @@ platform_exceptions: { isis_interface_afi_unsupported: true missing_isis_interface_afi_safi_enable: true isis_require_same_l1_metric_with_l2_metric: true - route_policy_under_afi_unsupported: true static_protocol_name: "STATIC" rib_wecmp: true explicit_port_speed: true diff --git a/feature/platform/integrated_circuit/otg_tests/utilization_test/metadata.textproto b/feature/platform/integrated_circuit/otg_tests/utilization_test/metadata.textproto index 45d28a4dcdf..176b048af2b 100644 --- a/feature/platform/integrated_circuit/otg_tests/utilization_test/metadata.textproto +++ b/feature/platform/integrated_circuit/otg_tests/utilization_test/metadata.textproto @@ -10,7 +10,6 @@ platform_exceptions: { vendor: ARISTA } deviations: { - route_policy_under_afi_unsupported: true interface_enabled: true default_network_instance: "default" mismatched_hardware_resource_name_in_component: true diff --git a/feature/staticroute/otg_tests/basic_static_route_support_test/metadata.textproto b/feature/staticroute/otg_tests/basic_static_route_support_test/metadata.textproto index af7f010bc52..ccac5af9ab0 100644 --- a/feature/staticroute/otg_tests/basic_static_route_support_test/metadata.textproto +++ b/feature/staticroute/otg_tests/basic_static_route_support_test/metadata.textproto @@ -18,11 +18,6 @@ platform_exceptions: { isis_interface_afi_unsupported: true missing_isis_interface_afi_safi_enable: true isis_require_same_l1_metric_with_l2_metric: true - ipv6_static_route_with_ipv4_next_hop_requires_static_arp: true - set_metric_as_preference: true - missing_static_route_next_hop_metric_telemetry: true - unsupported_static_route_next_hop_recurse: true - missing_static_route_drop_next_hop_telemetry: true } } platform_exceptions: { diff --git a/feature/system/gnmi/benchmarking/otg_tests/drained_configuration_convergence_time/metadata.textproto b/feature/system/gnmi/benchmarking/otg_tests/drained_configuration_convergence_time/metadata.textproto index e6104d7837a..36badab880d 100644 --- a/feature/system/gnmi/benchmarking/otg_tests/drained_configuration_convergence_time/metadata.textproto +++ b/feature/system/gnmi/benchmarking/otg_tests/drained_configuration_convergence_time/metadata.textproto @@ -31,7 +31,6 @@ platform_exceptions: { vendor: ARISTA } deviations: { - route_policy_under_afi_unsupported: true interface_enabled: true default_network_instance: "default" missing_isis_interface_afi_safi_enable: true diff --git a/feature/system/gnmi/benchmarking/tests/full_configuration_replace_test/metadata.textproto b/feature/system/gnmi/benchmarking/tests/full_configuration_replace_test/metadata.textproto index 64eed0547a0..7d9bb480d71 100644 --- a/feature/system/gnmi/benchmarking/tests/full_configuration_replace_test/metadata.textproto +++ b/feature/system/gnmi/benchmarking/tests/full_configuration_replace_test/metadata.textproto @@ -31,7 +31,6 @@ platform_exceptions: { vendor: ARISTA } deviations: { - route_policy_under_afi_unsupported: true interface_enabled: true missing_isis_interface_afi_safi_enable: true isis_interface_afi_unsupported: true diff --git a/feature/system/management/otg_tests/management_ha_test/metadata.textproto b/feature/system/management/otg_tests/management_ha_test/metadata.textproto index bbc70c53bc1..ed33d7b530c 100644 --- a/feature/system/management/otg_tests/management_ha_test/metadata.textproto +++ b/feature/system/management/otg_tests/management_ha_test/metadata.textproto @@ -10,13 +10,10 @@ platform_exceptions: { vendor: ARISTA } deviations: { - route_policy_under_afi_unsupported: true omit_l2_mtu: true static_protocol_name: "STATIC" interface_enabled: true default_network_instance: "default" - skip_set_rp_match_set_options: true - skip_setting_disable_metric_propagation: true set_no_peer_group: true explicit_enable_bgp_on_default_vrf: true } From 69964152e033fa9dac921a13708004fe7d057868 Mon Sep 17 00:00:00 2001 From: jianchen-g Date: Fri, 24 Jan 2025 16:34:23 -0800 Subject: [PATCH 03/10] Adding test files for 400G ZR++ chromatic dispersion test and uncorrectable fec test (#3700) * bug fixes: 1) in zr_laser_bias_current_test file, the time.Duration function returns value in nanosecond by default, needs to convert it to second; 2) in zr_low_power_mode_test file, to use the transceiver disable OC path, the input needs to be transceiver name instead of interface name. * Adding README files for the testing of a new type of optics 400G ZR++ * add README file for zrp_input_output_power_test * restructed the test folder for two optics PMDs of 400G ZR and ZR++. Each test item has its own folder, under which 400G ZR and ZR++ test scripts are separated. * make sure test paths follow feature/////_test.go * rename folder name to resovle the feature root errors * rename folder name to test_item_tests to resovle the feature root errors * adding tests folder to resolve folder root errors for cd tests * adding folder named tests to resolve folder root errors * rename folder chromatic_dispersion * rename folder performance_metrics * adding test files for 400G ZR++ chromatic dipersion test and uncorrectable fec test * adding a new line at the end of zrp_cd_test metadata.textproto file * change plan id for zrp_cd_test * change plan id for zrp_fec_uncorrectable_frames_test * 1) removed unnecessary portState constant; 2) make verifyAllCDValues as a table-driven test * keep one value between desc and streamType --------- Co-authored-by: anksaiki --- .../tests/zrp_cd_test/README.md | 2 +- .../tests/zrp_cd_test/metadata.textproto | 15 ++ .../tests/zrp_cd_test/zrp_cd_test.go | 172 ++++++++++++++++++ .../README.md | 2 +- .../metadata.textproto | 28 +++ .../zrp_fec_uncorrectable_frames_test.go | 116 ++++++++++++ 6 files changed, 333 insertions(+), 2 deletions(-) create mode 100644 feature/platform/transceiver/chromatic_dispersion/tests/zrp_cd_test/metadata.textproto create mode 100644 feature/platform/transceiver/chromatic_dispersion/tests/zrp_cd_test/zrp_cd_test.go create mode 100644 feature/platform/transceiver/fec_uncorrectable_frames/tests/zrp_fec_uncorrectable_frames_test/metadata.textproto create mode 100644 feature/platform/transceiver/fec_uncorrectable_frames/tests/zrp_fec_uncorrectable_frames_test/zrp_fec_uncorrectable_frames_test.go diff --git a/feature/platform/transceiver/chromatic_dispersion/tests/zrp_cd_test/README.md b/feature/platform/transceiver/chromatic_dispersion/tests/zrp_cd_test/README.md index 38d2a7baa9c..34a200dd80c 100644 --- a/feature/platform/transceiver/chromatic_dispersion/tests/zrp_cd_test/README.md +++ b/feature/platform/transceiver/chromatic_dispersion/tests/zrp_cd_test/README.md @@ -1,4 +1,4 @@ -# TRANSCEIVER-1: Telemetry: 400ZR_PLUS Chromatic Dispersion(CD) telemetry values streaming +# TRANSCEIVER-1 (400ZR_PLUS): Telemetry: 400ZR_PLUS Chromatic Dispersion(CD) telemetry values streaming ## Summary diff --git a/feature/platform/transceiver/chromatic_dispersion/tests/zrp_cd_test/metadata.textproto b/feature/platform/transceiver/chromatic_dispersion/tests/zrp_cd_test/metadata.textproto new file mode 100644 index 00000000000..cca50bb884c --- /dev/null +++ b/feature/platform/transceiver/chromatic_dispersion/tests/zrp_cd_test/metadata.textproto @@ -0,0 +1,15 @@ +# proto-file: github.com/openconfig/featureprofiles/proto/metadata.proto +# proto-message: Metadata +uuid: "6ee614f9-efa6-4d1c-bdea-b15332feedc7" +plan_id: "TRANSCEIVER-1 (400ZR_PLUS)" +description: "Telemetry: 400ZR_PLUS Chromatic Dispersion(CD) telemetry values streaming" +testbed: TESTBED_DUT_400ZR_PLUS +platform_exceptions: { + platform: { + vendor: ARISTA + } + deviations: { + default_network_instance: "default" + missing_port_to_optical_channel_component_mapping: true + } +} diff --git a/feature/platform/transceiver/chromatic_dispersion/tests/zrp_cd_test/zrp_cd_test.go b/feature/platform/transceiver/chromatic_dispersion/tests/zrp_cd_test/zrp_cd_test.go new file mode 100644 index 00000000000..e093b1675ab --- /dev/null +++ b/feature/platform/transceiver/chromatic_dispersion/tests/zrp_cd_test/zrp_cd_test.go @@ -0,0 +1,172 @@ +package zrp_cd_test + +import ( + "flag" + "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 + minCDValue = -200 + maxCDValue = 2400 + inActiveCDValue = 0.0 + timeout = 10 * time.Minute + flapInterval = 30 * time.Second +) + +var ( + frequencies = []uint64{191400000, 196100000} + targetOutputPowers = []float64{-7, 0} + operationalModeFlag = flag.Int("operational_mode", 5, "vendor-specific operational-mode for the channel") + operationalMode uint16 +) + +func TestMain(m *testing.M) { + fptest.RunTests(m) +} + +func verifyCDValue(t *testing.T, dut1 *ondatra.DUTDevice, pStream *samplestream.SampleStream[float64], sensorName string, operStatus oc.E_Interface_OperStatus) float64 { + cdSampleNexts := pStream.Nexts(2) + cdSample := cdSampleNexts[1] + t.Logf("CDSampleNexts %v", cdSampleNexts) + if cdSample == nil { + t.Fatalf("CD telemetry %s was not streamed in the most recent subscription interval", sensorName) + } + cdVal, ok := cdSample.Val() + if !ok { + t.Fatalf("CD %q telemetry is not present", cdSample) + } + if reflect.TypeOf(cdVal).Kind() != reflect.Float64 { + t.Fatalf("CD value is not type float64") + } + // Check CD return value of correct type + switch operStatus { + case oc.Interface_OperStatus_DOWN: + if cdVal != inActiveCDValue { + t.Fatalf("The inactive CD is %v, expected %v", cdVal, inActiveCDValue) + } + case oc.Interface_OperStatus_UP: + if cdVal < minCDValue || cdVal > maxCDValue { + t.Fatalf("The variable CD is %v, expected range (%v, %v)", cdVal, minCDValue, maxCDValue) + } + default: + t.Fatalf("Invalid status %v", operStatus) + } + // Get current time + now := time.Now() + // Format the time string + formattedTime := now.Format("2006-01-02 15:04:05") + t.Logf("%s Device %v CD %s value at status %v: %v", formattedTime, dut1.Name(), sensorName, operStatus, cdVal) + + return cdVal +} + +// TODO: Avg and Instant value checks are not available. Need to align their sample streaming windows. +func verifyAllCDValues(t *testing.T, dut1 *ondatra.DUTDevice, p1StreamInstant, p1StreamMax, p1StreamMin, p1StreamAvg *samplestream.SampleStream[float64], operStatus oc.E_Interface_OperStatus) { + tests := []struct { + desc string + stream *samplestream.SampleStream[float64] + streamType string + operStatus oc.E_Interface_OperStatus + }{ + { + desc: "Instant", + stream: p1StreamInstant, + operStatus: operStatus, + }, + { + desc: "Max", + stream: p1StreamMax, + operStatus: operStatus, + }, + { + desc: "Min", + stream: p1StreamMin, + operStatus: operStatus, + }, + { + desc: "Avg", + stream: p1StreamAvg, + operStatus: operStatus, + }, + } + + for _, tt := range tests { + t.Run(tt.desc, func(t *testing.T) { + verifyCDValue(t, dut1, tt.stream, tt.desc, tt.operStatus) + }) + } +} + +func TestCDValue(t *testing.T) { + dut := ondatra.DUT(t, "dut") + if operationalModeFlag != nil { + operationalMode = uint16(*operationalModeFlag) + } else { + t.Fatalf("Please specify the vendor-specific operational-mode flag") + } + fptest.ConfigureDefaultNetworkInstance(t, dut) + + dp1 := dut.Port(t, "port1") + dp2 := dut.Port(t, "port2") + + och1 := components.OpticalChannelComponentFromPort(t, dut, dp1) + och2 := components.OpticalChannelComponentFromPort(t, dut, dp2) + + component1 := gnmi.OC().Component(och1) + for _, frequency := range frequencies { + for _, targetOutputPower := range targetOutputPowers { + cfgplugins.ConfigOpticalChannel(t, dut, och1, frequency, targetOutputPower, operationalMode) + cfgplugins.ConfigOpticalChannel(t, dut, och2, frequency, targetOutputPower, operationalMode) + + // Wait for channels to be up. + gnmi.Await(t, dut, gnmi.OC().Interface(dp1.Name()).OperStatus().State(), timeout, oc.Interface_OperStatus_UP) + gnmi.Await(t, dut, gnmi.OC().Interface(dp2.Name()).OperStatus().State(), timeout, oc.Interface_OperStatus_UP) + + p1StreamInstant := samplestream.New(t, dut, component1.OpticalChannel().ChromaticDispersion().Instant().State(), samplingInterval) + p1StreamMin := samplestream.New(t, dut, component1.OpticalChannel().ChromaticDispersion().Min().State(), samplingInterval) + p1StreamMax := samplestream.New(t, dut, component1.OpticalChannel().ChromaticDispersion().Max().State(), samplingInterval) + p1StreamAvg := samplestream.New(t, dut, component1.OpticalChannel().ChromaticDispersion().Avg().State(), samplingInterval) + + defer p1StreamInstant.Close() + defer p1StreamMin.Close() + defer p1StreamMax.Close() + defer p1StreamAvg.Close() + + verifyAllCDValues(t, dut, p1StreamInstant, p1StreamMax, p1StreamMin, p1StreamAvg, oc.Interface_OperStatus_UP) + + // Disable interface. + for _, p := range dut.Ports() { + cfgplugins.ToggleInterface(t, dut, p.Name(), false) + } + // Wait for channels to be down. + gnmi.Await(t, dut, gnmi.OC().Interface(dp1.Name()).OperStatus().State(), timeout, oc.Interface_OperStatus_DOWN) + gnmi.Await(t, dut, gnmi.OC().Interface(dp2.Name()).OperStatus().State(), timeout, oc.Interface_OperStatus_DOWN) + t.Logf("Interfaces are down: %v, %v", dp1.Name(), dp2.Name()) + verifyAllCDValues(t, dut, p1StreamInstant, p1StreamMax, p1StreamMin, p1StreamAvg, oc.Interface_OperStatus_DOWN) + + time.Sleep(flapInterval) + + // Enable interface. + for _, p := range dut.Ports() { + cfgplugins.ToggleInterface(t, dut, p.Name(), true) + } + // Wait for channels to be up. + gnmi.Await(t, dut, gnmi.OC().Interface(dp1.Name()).OperStatus().State(), timeout, oc.Interface_OperStatus_UP) + gnmi.Await(t, dut, gnmi.OC().Interface(dp2.Name()).OperStatus().State(), timeout, oc.Interface_OperStatus_UP) + t.Logf("Interfaces are up: %v, %v", dp1.Name(), dp2.Name()) + verifyAllCDValues(t, dut, p1StreamInstant, p1StreamMax, p1StreamMin, p1StreamAvg, oc.Interface_OperStatus_UP) + + } + } +} diff --git a/feature/platform/transceiver/fec_uncorrectable_frames/tests/zrp_fec_uncorrectable_frames_test/README.md b/feature/platform/transceiver/fec_uncorrectable_frames/tests/zrp_fec_uncorrectable_frames_test/README.md index 9a36062a6b1..756bc623d6b 100644 --- a/feature/platform/transceiver/fec_uncorrectable_frames/tests/zrp_fec_uncorrectable_frames_test/README.md +++ b/feature/platform/transceiver/fec_uncorrectable_frames/tests/zrp_fec_uncorrectable_frames_test/README.md @@ -1,4 +1,4 @@ -# TRANSCEIVER-10: Telemetry: 400ZR_PLUS Optics FEC(Forward Error Correction) Uncorrectable Frames Streaming. +# TRANSCEIVER-10 (400ZR_PLUS): Telemetry: 400ZR_PLUS Optics FEC(Forward Error Correction) Uncorrectable Frames Streaming. ## Summary diff --git a/feature/platform/transceiver/fec_uncorrectable_frames/tests/zrp_fec_uncorrectable_frames_test/metadata.textproto b/feature/platform/transceiver/fec_uncorrectable_frames/tests/zrp_fec_uncorrectable_frames_test/metadata.textproto new file mode 100644 index 00000000000..4d15d622908 --- /dev/null +++ b/feature/platform/transceiver/fec_uncorrectable_frames/tests/zrp_fec_uncorrectable_frames_test/metadata.textproto @@ -0,0 +1,28 @@ +# proto-file: github.com/openconfig/featureprofiles/proto/metadata.proto +# proto-message: Metadata + +uuid: "387c1f76-7811-4a04-99e3-f690fba1e98e" +plan_id: "TRANSCEIVER-10 (400ZR_PLUS)" +description: "Telemetry: 400ZR_PLUS Optics FEC(Forward Error Correction) Uncorrectable Frames 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 + channel_assignment_rate_class_parameters_unsupported: true + } +} +platform_exceptions: { + platform: { + vendor: CISCO + } + deviations: { + otn_channel_trib_unsupported: true + eth_channel_ingress_parameters_unsupported: true + eth_channel_assignment_cisco_numbering: true + } +} diff --git a/feature/platform/transceiver/fec_uncorrectable_frames/tests/zrp_fec_uncorrectable_frames_test/zrp_fec_uncorrectable_frames_test.go b/feature/platform/transceiver/fec_uncorrectable_frames/tests/zrp_fec_uncorrectable_frames_test/zrp_fec_uncorrectable_frames_test.go new file mode 100644 index 00000000000..829376d5560 --- /dev/null +++ b/feature/platform/transceiver/fec_uncorrectable_frames/tests/zrp_fec_uncorrectable_frames_test/zrp_fec_uncorrectable_frames_test.go @@ -0,0 +1,116 @@ +// 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_fec_uncorrectable_frames_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 ( + sampleInterval = 10 * time.Second + intUpdateTime = 5 * time.Minute + otnIndexBase = uint32(4000) + ethIndexBase = uint32(40000) + 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 validateFecUncorrectableBlocks(t *testing.T, stream *samplestream.SampleStream[uint64]) { + fecStream := stream.Next() + if fecStream == nil { + t.Fatalf("Fec Uncorrectable Blocks was not streamed in the most recent subscription interval") + } + fec, ok := fecStream.Val() + if !ok { + t.Fatalf("Error capturing streaming Fec value") + } + if reflect.TypeOf(fec).Kind() != reflect.Uint64 { + t.Fatalf("fec value is not type uint64") + } + if fec != 0 { + t.Fatalf("Got FecUncorrectableBlocks got %d, want 0", fec) + } +} + +func TestZrUncorrectableFrames(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") + + var ( + // trs = make(map[string]string) + // ochs = make(map[string]string) + otnIndexes = make(map[string]uint32) + ethIndexes = make(map[string]uint32) + ) + + ports := []string{"port1", "port2"} + + for i, port := range ports { + p := dut.Port(t, port) + och := components.OpticalChannelComponentFromPort(t, dut, p) + otnIndexes[p.Name()] = otnIndexBase + uint32(i) + ethIndexes[p.Name()] = ethIndexBase + uint32(i) + cfgplugins.ConfigOpticalChannel(t, dut, och, frequency, targetOutputPower, operationalMode) + cfgplugins.ConfigOTNChannel(t, dut, och, otnIndexes[p.Name()], ethIndexes[p.Name()]) + cfgplugins.ConfigETHChannel(t, dut, p.Name(), och, otnIndexes[p.Name()], ethIndexes[p.Name()]) + } + + for _, port := range ports { + t.Run(fmt.Sprintf("Port:%s", port), func(t *testing.T) { + p := dut.Port(t, port) + gnmi.Await(t, dut, gnmi.OC().Interface(p.Name()).OperStatus().State(), intUpdateTime, oc.Interface_OperStatus_UP) + streamFecOtn := samplestream.New(t, dut, gnmi.OC().TerminalDevice().Channel(otnIndexes[p.Name()]).Otn().FecUncorrectableBlocks().State(), sampleInterval) + defer streamFecOtn.Close() + validateFecUncorrectableBlocks(t, streamFecOtn) + + // Disable interface + cfgplugins.ToggleInterface(t, dut, p.Name(), false) + // Wait for the cooling-off period + gnmi.Await(t, dut, gnmi.OC().Interface(p.Name()).OperStatus().State(), intUpdateTime, oc.Interface_OperStatus_DOWN) + + // Enable interface + cfgplugins.ToggleInterface(t, dut, p.Name(), true) + // Wait for the cooling-off period + gnmi.Await(t, dut, gnmi.OC().Interface(p.Name()).OperStatus().State(), intUpdateTime, oc.Interface_OperStatus_UP) + + validateFecUncorrectableBlocks(t, streamFecOtn) + }) + } +} From 5f6a91ea1aa4c9fba5d98fb726e7634aba5ebf1e Mon Sep 17 00:00:00 2001 From: Nisha Sadhasivam Date: Mon, 27 Jan 2025 10:25:32 +0530 Subject: [PATCH 04/10] gNMI-1.16 Fabric redundnacy test (#3690) * gNMI-1.16 Fabric redundnacy test * fix static analysis failure * fix static anlysis failure * fix README * fix README * fix readme * addressing review comments * Addressing review comments --- .../fabric_redundancy_test/README.md | 57 +- .../fabric_redundancy_test.go | 549 ++++++++++++++++++ .../fabric_redundancy_test/metadata.textproto | 21 +- 3 files changed, 609 insertions(+), 18 deletions(-) create mode 100644 feature/platform/fabric/otg_tests/fabric_redundancy_test/fabric_redundancy_test.go diff --git a/feature/platform/fabric/otg_tests/fabric_redundancy_test/README.md b/feature/platform/fabric/otg_tests/fabric_redundancy_test/README.md index fa4726e255b..7abcb725bab 100644 --- a/feature/platform/fabric/otg_tests/fabric_redundancy_test/README.md +++ b/feature/platform/fabric/otg_tests/fabric_redundancy_test/README.md @@ -1,4 +1,4 @@ -# gNMI-1.16 Fabric redundnacy test +# gNMI-1.16: Fabric redundnacy test ## Summary - collect inventory data for each fabric card @@ -41,26 +41,49 @@ * Wait * get last-reboot-time and compare with "PREVIOUS_REBOOT_TIME". The "PREVIOUS_REBOOT_TIME" must be smaller (earlier) then recently collected last-reboot-time +## OpenConfig Path and RPC Coverage -## Config Parameter coverage +```yaml +paths: + ## Config Parameter coverage -* /components/component/fabric/config/power-admin-state + /components/component/fabric/config/power-admin-state: + platform_type: [ "FABRIC" ] -## Telemetry Parameter coverage + ## Telemetry Parameter coverage -* /components/component/fabric/state/power-admin-state -* /components/component/state/description -* /components/component/state/hardware-version -* /components/component/state/id -* /components/component/state/mfg-name -* /components/component/state/name -* /components/component/state/oper-status -* /components/component/state/parent -* /components/component/state/part-no -* /components/component/state/serial-no -* /components/component/state/type -* /components/component/state/location -* /components/component/state/last-reboot-time + /components/component/fabric/state/power-admin-state: + platform_type: [ "FABRIC" ] + /components/component/state/description: + platform_type: [ "FABRIC" ] + /components/component/state/hardware-version: + platform_type: [ "FABRIC" ] + /components/component/state/id: + platform_type: [ "FABRIC" ] + /components/component/state/mfg-name: + platform_type: [ "FABRIC" ] + /components/component/state/name: + platform_type: [ "FABRIC" ] + /components/component/state/oper-status: + platform_type: [ "FABRIC" ] + /components/component/state/parent: + platform_type: [ "FABRIC" ] + /components/component/state/part-no: + platform_type: [ "FABRIC" ] + /components/component/state/serial-no: + platform_type: [ "FABRIC" ] + /components/component/state/type: + platform_type: [ "FABRIC" ] + /components/component/state/location: + platform_type: [ "FABRIC" ] + /components/component/state/last-reboot-time: + platform_type: [ "FABRIC" ] + +rpcs: + gnmi: + gNMI.Set: + gNMI.Subscribe: +``` ## Minimum DUT platform requirement * MFF diff --git a/feature/platform/fabric/otg_tests/fabric_redundancy_test/fabric_redundancy_test.go b/feature/platform/fabric/otg_tests/fabric_redundancy_test/fabric_redundancy_test.go new file mode 100644 index 00000000000..f4c3cbe8dd1 --- /dev/null +++ b/feature/platform/fabric/otg_tests/fabric_redundancy_test/fabric_redundancy_test.go @@ -0,0 +1,549 @@ +// 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 +// +// hfdp://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 fabric_redundancy_test + +import ( + "fmt" + "math/rand" + "reflect" + "strings" + "testing" + "time" + + "github.com/open-traffic-generator/snappi/gosnappi" + "github.com/openconfig/featureprofiles/internal/attrs" + "github.com/openconfig/featureprofiles/internal/components" + "github.com/openconfig/featureprofiles/internal/deviations" + "github.com/openconfig/featureprofiles/internal/fptest" + "github.com/openconfig/featureprofiles/internal/otgutils" + "github.com/openconfig/ondatra" + "github.com/openconfig/ondatra/gnmi" + "github.com/openconfig/ondatra/gnmi/oc" + "github.com/openconfig/ondatra/otg" + "github.com/openconfig/ygot/ygot" +) + +const ( + fabricType = oc.PlatformTypes_OPENCONFIG_HARDWARE_COMPONENT_FABRIC + ipv6 = "IPv6" + ipv4PrefixLen = 30 + ipv6PrefixLen = 126 + mtu = 4000 + trafficStopWaitDuration = 10 * time.Second + acceptablePacketSizeDelta = 0.5 + acceptableLossPercent = 0.001 + subInterfaceIndex = 0 + ppsRate = 100000 + packetsToSend = 16000000 +) + +var ( + fabricLeafOrValuePresent = make(map[string][]any) + fabricLeafOrValueNotPresent = make(map[string]string) + dutSrc = &attrs.Attributes{ + Name: "dutSrc", + MAC: "00:12:01:01:01:01", + IPv4: "192.0.2.1", + IPv6: "2001:db8::1", + IPv4Len: ipv4PrefixLen, + IPv6Len: ipv6PrefixLen, + MTU: mtu, + } + + dutDst = &attrs.Attributes{ + Name: "dutDst", + MAC: "00:12:02:01:01:01", + IPv4: "192.0.2.5", + IPv6: "2001:db8::5", + IPv4Len: ipv4PrefixLen, + IPv6Len: ipv6PrefixLen, + MTU: mtu, + } + + ateSrc = &attrs.Attributes{ + Name: "ateSrc", + MAC: "02:00:01:01:01:01", + IPv4: "192.0.2.2", + IPv6: "2001:db8::2", + IPv4Len: ipv4PrefixLen, + IPv6Len: ipv6PrefixLen, + MTU: mtu, + } + + ateDst = &attrs.Attributes{ + Name: "ateDst", + MAC: "02:00:02:01:01:01", + IPv4: "192.0.2.6", + IPv6: "2001:db8::6", + IPv4Len: ipv4PrefixLen, + IPv6Len: ipv6PrefixLen, + MTU: mtu, + } + dutPorts = map[string]*attrs.Attributes{ + "port1": dutSrc, + "port2": dutDst, + } + + atePorts = map[string]*attrs.Attributes{ + "port1": ateSrc, + "port2": ateDst, + } + + fd = flowDefinition{ + name: "flow_size_4000", + desc: "4000 byte flow", + flowSize: 4000, + } +) + +type flowDefinition struct { + name string + desc string + flowSize uint32 +} + +type otgData struct { + flowProto string + otg *otg.OTG + otgConfig gosnappi.Config +} + +func TestMain(m *testing.M) { + fptest.RunTests(m) +} + +func (d *otgData) waitInterface(t *testing.T) { + otgutils.WaitForARP(t, d.otg, d.otgConfig, d.flowProto) +} + +func createFlow(flowName string, flowSize uint32, ipv6 string) gosnappi.Flow { + flow := gosnappi.NewFlow().SetName(flowName) + flow.Metrics().SetEnable(true) + flow.Size().SetFixed(flowSize) + flow.Rate().SetPps(ppsRate) + flow.Duration().FixedPackets().SetPackets(packetsToSend) + flow.TxRx().Device(). + SetTxNames([]string{fmt.Sprintf("%s.%s", ateSrc.Name, ipv6)}). + SetRxNames([]string{fmt.Sprintf("%s.%s", ateDst.Name, ipv6)}) + ethHdr := flow.Packet().Add().Ethernet() + ethHdr.Src().SetValue(ateSrc.MAC) + flow.SetSize(gosnappi.NewFlowSize().SetFixed(flowSize)) + + v6 := flow.Packet().Add().Ipv6() + v6.Src().SetValue(ateSrc.IPv6) + v6.Dst().SetValue(ateDst.IPv6) + + flow.EgressPacket().Add().Ethernet() + + return flow +} + +func configureDUTPort( + t *testing.T, + dut *ondatra.DUTDevice, + port *ondatra.Port, + portAttrs *attrs.Attributes, +) { + gnmi.Replace( + t, + dut, + gnmi.OC().Interface(port.Name()).Config(), + portAttrs.NewOCInterface(port.Name(), dut), + ) + + if deviations.ExplicitPortSpeed(dut) { + fptest.SetPortSpeed(t, port) + } + + if deviations.ExplicitInterfaceInDefaultVRF(dut) { + fptest.AssignToNetworkInstance(t, dut, port.Name(), deviations.DefaultNetworkInstance(dut), subInterfaceIndex) + } +} + +func configureDUT(t *testing.T, dut *ondatra.DUTDevice) { + for portName, portAfdrs := range dutPorts { + port := dut.Port(t, portName) + configureDUTPort(t, dut, port, portAfdrs) + verifyDUTPort(t, dut, port.Name()) + } +} + +func verifyDUTPort(t *testing.T, dut *ondatra.DUTDevice, portName string) { + switch { + case deviations.OmitL2MTU(dut): + configuredIpv6SubInterfaceMtu := gnmi.Get(t, dut, gnmi.OC().Interface(portName).Subinterface(subInterfaceIndex).Ipv6().Mtu().State()) + expectedSubInterfaceMtu := mtu + + if int(configuredIpv6SubInterfaceMtu) != expectedSubInterfaceMtu { + t.Errorf( + "dut %s configured mtu is incorrect, got: %d, want: %d", + dut.Name(), configuredIpv6SubInterfaceMtu, expectedSubInterfaceMtu, + ) + } + default: + configuredInterfaceMtu := gnmi.Get(t, dut, gnmi.OC().Interface(portName).Mtu().State()) + expectedInterfaceMtu := mtu + 14 + + if int(configuredInterfaceMtu) != expectedInterfaceMtu { + t.Errorf( + "dut %s configured mtu is incorrect, got: %d, want: %d", + dut.Name(), configuredInterfaceMtu, expectedInterfaceMtu, + ) + } + } +} + +func configureATE(t *testing.T, ate *ondatra.ATEDevice) gosnappi.Config { + otgConfig := gosnappi.NewConfig() + + for portName, portAfdrs := range atePorts { + port := ate.Port(t, portName) + dutPort := dutPorts[portName] + portAfdrs.AddToOTG(otgConfig, port, dutPort) + } + + return otgConfig +} + +func testFabricInventory(t *testing.T, dut *ondatra.DUTDevice, fabrics []string, od otgData) { + for _, fabric := range fabrics { + t.Logf("\n\n VALIDATE %s: \n\n", fabric) + description := gnmi.OC().Component(fabric).Description() + hardwareVersion := gnmi.OC().Component(fabric).HardwareVersion() + id := gnmi.OC().Component(fabric).Id() + mfgName := gnmi.OC().Component(fabric).MfgName() + name := gnmi.OC().Component(fabric).Name() + operStatus := gnmi.OC().Component(fabric).OperStatus() + parent := gnmi.OC().Component(fabric).Parent() + partNo := gnmi.OC().Component(fabric).PartNo() + serialNo := gnmi.OC().Component(fabric).SerialNo() + typeVal := gnmi.OC().Component(fabric).Type() + location := gnmi.OC().Component(fabric).Location() + lastReboofdime := gnmi.OC().Component(fabric).LastRebootTime() + powerAdminState := gnmi.OC().Component(fabric).Fabric().PowerAdminState() + + descriptionKey := strings.Join([]string{fabric, "description"}, ":") + hardwareVersionKey := strings.Join([]string{fabric, "hardware-version"}, ":") + idKey := strings.Join([]string{fabric, "id"}, ":") + mfgNameKey := strings.Join([]string{fabric, "mfg-name"}, ":") + nameKey := strings.Join([]string{fabric, "name"}, ":") + operStatusKey := strings.Join([]string{fabric, "oper-status"}, ":") + parentKey := strings.Join([]string{fabric, "parent"}, ":") + partNoKey := strings.Join([]string{fabric, "part-no"}, ":") + serialNoKey := strings.Join([]string{fabric, "serial-no"}, ":") + typeValKey := strings.Join([]string{fabric, "type"}, ":") + locationKey := strings.Join([]string{fabric, "location"}, ":") + lastReboofdimeKey := strings.Join([]string{fabric, "last-reboot-time"}, ":") + powerAdminStateConfigKey := strings.Join([]string{fabric, "config/power-admin-state"}, ":") + powerAdminStateStateKey := strings.Join([]string{fabric, "state/power-admin-state"}, ":") + + /* fabricLeafOrValuePresent: Key: fabric:leaf, Value: []any{isLeafPresent, leafValue} */ + fabricLeafOrValuePresent[descriptionKey] = []any{gnmi.Lookup(t, dut, description.State()).IsPresent()} + fabricLeafOrValuePresent[hardwareVersionKey] = []any{gnmi.Lookup(t, dut, hardwareVersion.State()).IsPresent()} + fabricLeafOrValuePresent[idKey] = []any{gnmi.Lookup(t, dut, id.State()).IsPresent()} + fabricLeafOrValuePresent[mfgNameKey] = []any{gnmi.Lookup(t, dut, mfgName.State()).IsPresent()} + fabricLeafOrValuePresent[nameKey] = []any{gnmi.Lookup(t, dut, name.State()).IsPresent()} + fabricLeafOrValuePresent[operStatusKey] = []any{gnmi.Lookup(t, dut, operStatus.State()).IsPresent()} + fabricLeafOrValuePresent[parentKey] = []any{gnmi.Lookup(t, dut, parent.State()).IsPresent()} + fabricLeafOrValuePresent[partNoKey] = []any{gnmi.Lookup(t, dut, partNo.State()).IsPresent()} + fabricLeafOrValuePresent[serialNoKey] = []any{gnmi.Lookup(t, dut, serialNo.State()).IsPresent()} + fabricLeafOrValuePresent[typeValKey] = []any{gnmi.Lookup(t, dut, typeVal.State()).IsPresent()} + fabricLeafOrValuePresent[locationKey] = []any{gnmi.Lookup(t, dut, location.State()).IsPresent()} + fabricLeafOrValuePresent[lastReboofdimeKey] = []any{gnmi.Lookup(t, dut, lastReboofdime.State()).IsPresent()} + fabricLeafOrValuePresent[powerAdminStateConfigKey] = []any{gnmi.Lookup(t, dut, powerAdminState.Config()).IsPresent()} + fabricLeafOrValuePresent[powerAdminStateStateKey] = []any{gnmi.Lookup(t, dut, powerAdminState.State()).IsPresent()} + + for leaf, value := range fabricLeafOrValuePresent { + if value[0].(bool) && strings.Contains(leaf, fabric) { + switch leaf { + case descriptionKey: + fabricLeafOrValuePresent[leaf] = append(fabricLeafOrValuePresent[leaf], gnmi.Get(t, dut, description.State())) + case hardwareVersionKey: + fabricLeafOrValuePresent[leaf] = append(fabricLeafOrValuePresent[leaf], gnmi.Get(t, dut, hardwareVersion.State())) + case idKey: + fabricLeafOrValuePresent[leaf] = append(fabricLeafOrValuePresent[leaf], gnmi.Get(t, dut, id.State())) + case mfgNameKey: + fabricLeafOrValuePresent[leaf] = append(fabricLeafOrValuePresent[leaf], gnmi.Get(t, dut, mfgName.State())) + case nameKey: + fabricLeafOrValuePresent[leaf] = append(fabricLeafOrValuePresent[leaf], gnmi.Get(t, dut, name.State())) + case operStatusKey: + fabricLeafOrValuePresent[leaf] = append(fabricLeafOrValuePresent[leaf], gnmi.Get(t, dut, operStatus.State())) + case parentKey: + fabricLeafOrValuePresent[leaf] = append(fabricLeafOrValuePresent[leaf], gnmi.Get(t, dut, parent.State())) + case partNoKey: + fabricLeafOrValuePresent[leaf] = append(fabricLeafOrValuePresent[leaf], gnmi.Get(t, dut, partNo.State())) + case serialNoKey: + fabricLeafOrValuePresent[leaf] = append(fabricLeafOrValuePresent[leaf], gnmi.Get(t, dut, serialNo.State())) + case typeValKey: + fabricLeafOrValuePresent[leaf] = append(fabricLeafOrValuePresent[leaf], gnmi.Get(t, dut, typeVal.State())) + case locationKey: + fabricLeafOrValuePresent[leaf] = append(fabricLeafOrValuePresent[leaf], gnmi.Get(t, dut, location.State())) + case lastReboofdimeKey: + fabricLeafOrValuePresent[leaf] = append(fabricLeafOrValuePresent[leaf], gnmi.Get(t, dut, lastReboofdime.State())) + case powerAdminStateConfigKey: + fabricLeafOrValuePresent[leaf] = append(fabricLeafOrValuePresent[leaf], gnmi.Get(t, dut, powerAdminState.Config())) + case powerAdminStateStateKey: + fabricLeafOrValuePresent[leaf] = append(fabricLeafOrValuePresent[leaf], gnmi.Get(t, dut, powerAdminState.State())) + } + + // Check if the leaf value is present or not. nil, '', 0 or empty slice is considered as not present. + if fabricLeafOrValuePresent[leaf][1] == nil || reflect.ValueOf(fabricLeafOrValuePresent[leaf][1]).IsZero() || (reflect.ValueOf(fabricLeafOrValuePresent[leaf][1]).Kind() == reflect.Slice && reflect.ValueOf(fabricLeafOrValuePresent[leaf][1]).Len() == 0) { + fabricLeafOrValueNotPresent[leaf] = fmt.Sprintf("value: '%v' is not as expected", fabricLeafOrValuePresent[leaf][1]) + } else { + t.Logf("PASSED: leaf: '%v' value: '%v' is as expected", leaf, fabricLeafOrValuePresent[leaf][1]) + } + } else if !value[0].(bool) && strings.Contains(leaf, fabric) { + fabricLeafOrValueNotPresent[leaf] = "is not present" + } + } + } + + t.Logf("\n\n") + for leaf, value := range fabricLeafOrValueNotPresent { + t.Errorf("[FAILED]: leaf: '%v' %v", leaf, value) + } +} + +func testFabricLastRebootTime(t *testing.T, dut *ondatra.DUTDevice, fabrics []string, od otgData) { + // Create a new random source with a specific seed + source := rand.NewSource(time.Now().UnixNano()) + random := rand.New(source) + + // Generate a random index within the range of the slice + randomIndex := random.Intn(len(fabrics)) + + // Access the fabric at the random index + fabric := fabrics[randomIndex] + + t.Logf("\n\n VALIDATE %s: \n\n", fabric) + lastReboofdime := gnmi.OC().Component(fabric).LastRebootTime() + lastReboofdimeBefore := gnmi.Get(t, dut, lastReboofdime.State()) + + gnmi.Replace(t, dut, gnmi.OC().Component(fabric).Fabric().PowerAdminState().Config(), oc.Platform_ComponentPowerType_POWER_DISABLED) + gnmi.Await(t, dut, gnmi.OC().Component(fabric).Fabric().PowerAdminState().State(), time.Minute, oc.Platform_ComponentPowerType_POWER_DISABLED) + + t.Logf("Waiting for 90s after power disable...") + time.Sleep(90 * time.Second) + + gnmi.Replace(t, dut, gnmi.OC().Component(fabric).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(fabric).Fabric().PowerAdminState().State(), time.Minute, oc.Platform_ComponentPowerType_POWER_ENABLED).Val(); !ok { + t.Errorf("Component %s, power-admin-state got: %v, want: %v", fabric, power, oc.Platform_ComponentPowerType_POWER_ENABLED) + } + } + if oper, ok := gnmi.Await(t, dut, gnmi.OC().Component(fabric).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", fabric, oper, oc.PlatformTypes_COMPONENT_OPER_STATUS_ACTIVE) + } + + t.Logf("Waiting for 90s after power enable...") + time.Sleep(90 * time.Second) + + lastReboofdimeAfter := gnmi.Get(t, dut, lastReboofdime.State()) + + if lastReboofdimeBefore > lastReboofdimeAfter { + t.Errorf("Component %s, last-reboot-time before power disable is same as after power enable", fabric) + } +} + +func testFabricRedundancy(t *testing.T, dut *ondatra.DUTDevice, fabrics []string, od otgData) { + t.Logf("Name: %s, Description: %s", fd.name, fd.desc) + + flowParams := createFlow(fd.name, fd.flowSize, od.flowProto) + od.otgConfig.Flows().Clear() + od.otgConfig.Flows().Append(flowParams) + od.otg.PushConfig(t, od.otgConfig) + time.Sleep(time.Second * 30) + + disabledFabric := "" + // Create a new random source with a specific seed + source := rand.NewSource(time.Now().UnixNano()) + random := rand.New(source) + + // Generate a random index within the range of the slice + randomIndex := random.Intn(len(fabrics)) + + // Access the fabric at the random index + disabledFabric = fabrics[randomIndex] + + gnmi.Replace(t, dut, gnmi.OC().Component(disabledFabric).Fabric().PowerAdminState().Config(), oc.Platform_ComponentPowerType_POWER_DISABLED) + gnmi.Await(t, dut, gnmi.OC().Component(disabledFabric).Fabric().PowerAdminState().State(), time.Minute, oc.Platform_ComponentPowerType_POWER_DISABLED) + + t.Logf("Waiting for 90s after power disable...") + time.Sleep(90 * time.Second) + + od.otg.StartProtocols(t) + od.waitInterface(t) + + sleepTime := time.Duration(packetsToSend/uint32(ppsRate)) + 5 + od.otg.StartTraffic(t) + time.Sleep(sleepTime * time.Second) + + od.otg.StopTraffic(t) + time.Sleep(trafficStopWaitDuration) + + otgutils.LogFlowMetrics(t, od.otg, od.otgConfig) + + flow := gnmi.OTG().Flow(fd.name) + flowCounters := flow.Counters() + + outPkts := gnmi.Get(t, od.otg, flowCounters.OutPkts().State()) + inPkts := gnmi.Get(t, od.otg, flowCounters.InPkts().State()) + inOctets := gnmi.Get(t, od.otg, flowCounters.InOctets().State()) + + if outPkts == 0 || inPkts == 0 { + t.Error("flow did not send or receive any packets, this should not happen") + } + + lossPercent := (float32(outPkts-inPkts) / float32(outPkts)) * 100 + + if lossPercent > acceptableLossPercent { + t.Errorf( + "flow sent '%d' packets and received '%d' packets, resulting in a "+ + "loss percent of '%.2f'. max acceptable loss percent is '%.2f'", + outPkts, inPkts, lossPercent, acceptableLossPercent, + ) + } + + avgPacketSize := uint32(inOctets / inPkts) + packetSizeDelta := float32(avgPacketSize-fd.flowSize) / (float32(avgPacketSize+fd.flowSize) / 2) * 100 + + if packetSizeDelta > acceptablePacketSizeDelta { + t.Errorf( + "flow sent '%d' packets and received '%d' packets, resulting in "+ + "averagepacket size of '%d' and a packet size delta of '%.2f' percent. "+ + "packet size delta should not exceed '%.2f'", + outPkts, inPkts, avgPacketSize, packetSizeDelta, acceptablePacketSizeDelta, + ) + } + + gnmi.Replace(t, dut, gnmi.OC().Component(disabledFabric).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(disabledFabric).Fabric().PowerAdminState().State(), time.Minute, oc.Platform_ComponentPowerType_POWER_ENABLED).Val(); !ok { + t.Errorf("Component %s, power-admin-state got: %v, want: %v", disabledFabric, power, oc.Platform_ComponentPowerType_POWER_ENABLED) + } + } + if oper, ok := gnmi.Await(t, dut, gnmi.OC().Component(disabledFabric).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", disabledFabric, oper, oc.PlatformTypes_COMPONENT_OPER_STATUS_ACTIVE) + } + + t.Logf("Waiting for 90s after power enable...") + time.Sleep(90 * time.Second) + +} + +func TestFabricRedundancy(t *testing.T) { + dut := ondatra.DUT(t, "dut") + + // Get fabric list that are inserted in the DUT. + fabrics := components.FindComponentsByType(t, dut, fabricType) + t.Logf("Found fabric list: %v", fabrics) + index := 0 + for _, fabric := range fabrics { + empty, ok := gnmi.Lookup(t, dut, gnmi.OC().Component(fabric).Empty().State()).Val() + if !(ok && empty) { + fabrics[index] = fabric + index++ + } else { + t.Logf("Fabric Component %s is empty, hence skipping", fabric) + } + } + fabrics = fabrics[:index] + t.Logf("Found non-empty fabric list: %v", fabrics) + + // Validate that there are at least 2 non-empty fabrics in the DUT. + if len(fabrics) < 2 { + t.Fatalf("No of Fabrics on DUT (%q): got %v, want => 2", dut.Model(), len(fabrics)) + } + + /* configure the ATE device to send/receive 16 millions of packets + at 100kpps rate and using 4000B packets (with 10E-6 tolerance). */ + ate := ondatra.ATE(t, "ate") + otg := ate.OTG() + configureDUT(t, dut) + otgConfig := configureATE(t, ate) + od := otgData{ + flowProto: ipv6, + otg: otg, + otgConfig: otgConfig, + } + + // Cleanup the DUT config. + t.Cleanup(func() { + deleteBatch := &gnmi.SetBatch{} + if deviations.ExplicitInterfaceInDefaultVRF(dut) { + netInst := &oc.NetworkInstance{Name: ygot.String(deviations.DefaultNetworkInstance(dut))} + + for portName := range dutPorts { + gnmi.BatchDelete( + deleteBatch, + gnmi.OC(). + NetworkInstance(*netInst.Name). + Interface(fmt.Sprintf("%s.%d", dut.Port(t, portName).Name(), subInterfaceIndex)). + Config(), + ) + } + } + + for portName := range dutPorts { + gnmi.BatchDelete( + deleteBatch, + gnmi.OC(). + Interface(dut.Port(t, portName).Name()). + Subinterface(subInterfaceIndex). + Config(), + ) + gnmi.BatchDelete(deleteBatch, gnmi.OC().Interface(dut.Port(t, portName).Name()).Mtu().Config()) + } + deleteBatch.Set(t, dut) + }) + + // Test cases. + type testCase struct { + name string + fabrics []string + testFunc func(t *testing.T, dut *ondatra.DUTDevice, fabrics []string, od otgData) + } + + testCases := []testCase{ + { + name: "TEST 1: Fabric inventory", + fabrics: fabrics, + testFunc: testFabricInventory, + }, + { + name: "TEST 2: Fabric redundancy", + fabrics: fabrics, + testFunc: testFabricRedundancy, + }, + { + name: "TEST 3: Fabric last reboot time", + fabrics: fabrics, + testFunc: testFabricLastRebootTime, + }, + } + + // Run the test cases. + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + t.Logf("Description: %s", tc.name) + tc.testFunc(t, dut, tc.fabrics, od) + }) + } +} diff --git a/feature/platform/fabric/otg_tests/fabric_redundancy_test/metadata.textproto b/feature/platform/fabric/otg_tests/fabric_redundancy_test/metadata.textproto index 6bda502dc25..4281f41ad3d 100644 --- a/feature/platform/fabric/otg_tests/fabric_redundancy_test/metadata.textproto +++ b/feature/platform/fabric/otg_tests/fabric_redundancy_test/metadata.textproto @@ -3,5 +3,24 @@ uuid: "261d317f-9bcc-43f9-a412-295ae6c008cf" plan_id: "gNMI-1.16" -description: "fabric redundancy test" +description: "Fabric redundnacy test" testbed: TESTBED_DUT_ATE_2LINKS +platform_exceptions: { + platform: { + vendor: NOKIA + } + deviations: { + explicit_port_speed: true + explicit_interface_in_default_vrf: true + missing_value_for_defaults: true + } +} +platform_exceptions: { + platform: { + vendor: ARISTA + } + deviations: { + missing_value_for_defaults: true + default_network_instance: "default" + } +} From f7b680a687c71afcc4be91ac9afcfffbfbc7d834 Mon Sep 17 00:00:00 2001 From: Nisha Sadhasivam Date: Mon, 27 Jan 2025 12:36:46 +0530 Subject: [PATCH 05/10] Adding defer () function to flush all entries before exit (#3717) --- .../gribigo_compliance_test/gribigo_compliance_test.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/feature/gribi/otg_tests/gribigo_compliance_test/gribigo_compliance_test.go b/feature/gribi/otg_tests/gribigo_compliance_test/gribigo_compliance_test.go index 1792e620550..04300fb8eaf 100644 --- a/feature/gribi/otg_tests/gribigo_compliance_test/gribigo_compliance_test.go +++ b/feature/gribi/otg_tests/gribigo_compliance_test/gribigo_compliance_test.go @@ -224,6 +224,14 @@ func testAdditionalCompliance(tcArgs *testArgs, t *testing.T) { fn: addNHGReferencingToDownPort, }, } + + defer func() { + // Flush all entries after test. + if err := gribi.FlushAll(tcArgs.client); err != nil { + t.Error(err) + } + }() + for _, tt := range tests { t.Run(tt.desc, func(t *testing.T) { if err := gribi.FlushAll(tcArgs.client); err != nil { From 2da6b5cc9790afd39bcfc13979f034f07e95836c Mon Sep 17 00:00:00 2001 From: Nisha Sadhasivam Date: Mon, 27 Jan 2025 14:53:02 +0530 Subject: [PATCH 06/10] Update gnoi linkqual FNT test to use an aggregate interface (#3705) * Update gnoi linkqual FNT test to use an aggregate interface * addressing review comments * minor change * minor fix * gofmt * Addressing review comments * minor fix * gofmt * updated topology --- .../packet_link_qualification_test/README.md | 2 +- .../packet_link_qualification_test.go | 154 ++++++++++++++++-- 2 files changed, 139 insertions(+), 17 deletions(-) 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 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..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 @@ -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" ) @@ -36,7 +38,7 @@ func TestMain(m *testing.M) { } // Topology: -// dut1:port1 <--> port1:dut2 +// dut1:port1 <--> port1:dut2 (port1 as singleton and memberlink) // // Test notes: // @@ -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,26 +245,81 @@ 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 aggIdDut1 string + var aggIdDut2 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{} + aggID := netutil.NextAggregateInterface(t, dut) + + 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) + aggIdDut1 = aggID + } else { + a4 = s4.GetOrCreateAddress(agg1.dut2IPv4) + aggIdDut2 = 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) { + fptest.AssignToNetworkInstance(t, dut, aggID, deviations.DefaultNetworkInstance(dut), 0) } } + // Wait for LAG interfaces to be 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).OperStatus().State(), 60*time.Second, oc.Interface_OperStatus_UP) +} - plqID := dut1.Name() + ":" + dp1.Name() + "<->" + dut2.Name() + ":" + dp2.Name() +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)) @@ -452,3 +528,49 @@ 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 + 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", + plqID: dut1.Name() + ":" + dp1.Name() + "<->" + dut2.Name() + ":" + dp2.Name() + ":singleton", + testFunc: testLinkQualification, + aggregate: false, + }, { + desc: "Member Link LinkQualification", + plqID: dut1.Name() + ":" + dp1.Name() + "<->" + dut2.Name() + ":" + dp2.Name() + ":memberlink", + 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, tc.plqID) + }) + } +} From 2def93e02fe35fa75186698c7bd6a6c4f7dbadf3 Mon Sep 17 00:00:00 2001 From: ampattan Date: Mon, 27 Jan 2025 15:54:36 +0530 Subject: [PATCH 07/10] RT-1.23 BGP AFI SAFI OC DEFAULTS TEST changes incorporated. (#3146) * -RT-1.23 following changes incorporated. -Changes in metadata.textproto -explicit_interface_in_default_vrf -bgp_global_extended_next_hop_encoding_unsupported -skip_bgp_session_check_without_afisafi -Changes in bgp_afi_safi_defaults_test.go -Removed unused ports from verifyPortsUp func. -Enabled global AFI-SAFI configuration. -Unsetting IPV4 AFI-SAFI flag under nieghbour level -Added deviation ExplicitInterfaceInDefaultVRF, BGPGlobalExtendedNextHopEncodingUnsupported "This code is a Contribution to the OpenConfig Feature Profiles project ("Work") made under the Google Software Grant and Corporate Contributor License Agreement ("CLA") and governed by the Apache License 2.0. No other rights or licenses in or to any of Nokia's intellectual property are granted for any other purpose. This code is provided on an "as is" basis without any warranties of any kind." * RT-1.23 updated README "This code is a Contribution to the OpenConfig Feature Profiles project ("Work") made under the Google Software Grant and Corporate Contributor License Agreement ("CLA") and governed by the Apache License 2.0. No other rights or licenses in or to any of Nokia's intellectual property are granted for any other purpose. This code is provided on an "as is" basis without any warranties of any kind." * -comments incorporated "This code is a Contribution to the OpenConfig Feature Profiles project ("Work") made under the Google Software Grant and Corporate Contributor License Agreement ("CLA") and governed by the Apache License 2.0. No other rights or licenses in or to any of Nokia's intellectual property are granted for any other purpose. This code is provided on an "as is" basis without any warranties of any kind." * -The AFI-SAFI false flag has been removed and the review comments have been addressed. "This code is a Contribution to the OpenConfig Feature Profiles project ("Work") made under the Google Software Grant and Corporate Contributor License Agreement ("CLA") and governed by the Apache License 2.0. No other rights or licenses in or to any of Nokia's intellectual property are granted for any other purpose. This code is provided on an "as is" basis without any warranties of any kind." --- .../bgp_afi_safi_defaults_test.go | 20 +++++++++++++++---- .../bgp_afi_safi_defaults/metadata.textproto | 3 +++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/feature/bgp/otg_tests/bgp_afi_safi_defaults/bgp_afi_safi_defaults_test.go b/feature/bgp/otg_tests/bgp_afi_safi_defaults/bgp_afi_safi_defaults_test.go index 13ed1cf127b..77d1a362bc5 100644 --- a/feature/bgp/otg_tests/bgp_afi_safi_defaults/bgp_afi_safi_defaults_test.go +++ b/feature/bgp/otg_tests/bgp_afi_safi_defaults/bgp_afi_safi_defaults_test.go @@ -62,6 +62,7 @@ const ( var ( dutPort1 = attrs.Attributes{ Desc: "DUT to ATE Port1", + Name: "port1", IPv4: "192.0.2.1", IPv6: "2001:db8::192:0:2:1", IPv4Len: plenIPv4, @@ -77,6 +78,7 @@ var ( } dutPort2 = attrs.Attributes{ Desc: "DUT to ATE Port2", + Name: "port2", IPv4: "192.0.2.5", IPv6: "2001:db8::192:0:2:5", IPv4Len: plenIPv4, @@ -111,12 +113,17 @@ func configureDUT(t *testing.T, dut *ondatra.DUTDevice) { i2 := dutPort2.NewOCInterface(dut.Port(t, "port2").Name(), dut) gnmi.Replace(t, dut, dc.Interface(i2.GetName()).Config(), i2) + if deviations.ExplicitInterfaceInDefaultVRF(dut) { + fptest.AssignToNetworkInstance(t, dut, i1.GetName(), deviations.DefaultNetworkInstance(dut), 0) + fptest.AssignToNetworkInstance(t, dut, i2.GetName(), deviations.DefaultNetworkInstance(dut), 0) + } } // verifyPortsUp asserts that each port on the device is operating. -func verifyPortsUp(t *testing.T, dev *ondatra.Device) { +func verifyPortsUp(t *testing.T, dev *ondatra.Device, portList []string) { t.Helper() - for _, p := range dev.Ports() { + for _, port := range portList { + p := dev.Port(t, port) status := gnmi.Get(t, dev, gnmi.OC().Interface(p.Name()).OperStatus().State()) if want := oc.Interface_OperStatus_UP; status != want { t.Errorf("%s Status: got %v, want %v", p, status, want) @@ -144,7 +151,11 @@ func bgpCreateNbr(t *testing.T, localAs, peerAs uint32, dut *ondatra.DUTDevice, pg2 := bgp.GetOrCreatePeerGroup(peerGrpName2) // V6 peer group pg2.PeerAs = ygot.Uint32(dutAS) pg2.PeerGroupName = ygot.String(peerGrpName2) - + if isV4Only { + global.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).Enabled = ygot.Bool(true) + } else { + global.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).Enabled = ygot.Bool(true) + } for _, nbr := range nbrs { nv4 := bgp.GetOrCreateNeighbor(nbr.neighborip) nv4.PeerGroup = ygot.String(nbr.peerGrp) @@ -479,7 +490,8 @@ func TestAfiSafiOcDefaults(t *testing.T) { }) t.Run("Verify port status on DUT", func(t *testing.T) { - verifyPortsUp(t, dut.Device) + portList := []string{"port1", "port2"} + verifyPortsUp(t, dut.Device, portList) }) t.Run("Verify BGP telemetry", func(t *testing.T) { diff --git a/feature/bgp/otg_tests/bgp_afi_safi_defaults/metadata.textproto b/feature/bgp/otg_tests/bgp_afi_safi_defaults/metadata.textproto index 8f222a52f9d..f043a15764a 100644 --- a/feature/bgp/otg_tests/bgp_afi_safi_defaults/metadata.textproto +++ b/feature/bgp/otg_tests/bgp_afi_safi_defaults/metadata.textproto @@ -28,6 +28,9 @@ platform_exceptions: { vendor: NOKIA } deviations: { + skip_bgp_session_check_without_afisafi: true + explicit_interface_in_default_vrf: true + bgp_global_extended_next_hop_encoding_unsupported: true interface_enabled: true } } From 3b489c7b73398085e9c4f9fda4ee7c10d4b12461 Mon Sep 17 00:00:00 2001 From: Pramod Maurya Date: Mon, 27 Jan 2025 16:25:13 +0530 Subject: [PATCH 08/10] removed duplicate encapfrr util (#3718) --- internal/encap_frr/base.go | 578 ------------------------------------- 1 file changed, 578 deletions(-) delete mode 100644 internal/encap_frr/base.go diff --git a/internal/encap_frr/base.go b/internal/encap_frr/base.go deleted file mode 100644 index 30a0203e072..00000000000 --- a/internal/encap_frr/base.go +++ /dev/null @@ -1,578 +0,0 @@ -// 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 base contains utility functions for encap frr using repair VRF. -package base - -import ( - "context" - "strconv" - "testing" - "time" - - "github.com/openconfig/featureprofiles/internal/attrs" - "github.com/openconfig/featureprofiles/internal/deviations" - "github.com/openconfig/gribigo/chk" - "github.com/openconfig/gribigo/constants" - "github.com/openconfig/gribigo/fluent" - "github.com/openconfig/ondatra" - "github.com/openconfig/ondatra/gnmi" - "github.com/openconfig/ondatra/gnmi/oc" - "github.com/openconfig/ygot/ygot" -) - -const ( - plenIPv4 = 30 - magicIP = "192.168.1.1" - magicMAC = "02:00:00:00:00:01" - maskLen24 = "24" - maskLen32 = "32" - niEncapTeVrfA = "ENCAP_TE_VRF_A" - niTEVRF111 = "TE_VRF_111" - niTEVRF222 = "TE_VRF_222" - niRepairVrf = "REPAIR_VRF" - ipv4OuterSrc111Addr = "198.51.100.111" - ipv4OuterSrc222Addr = "198.51.100.222" - gribiIPv4EntryDefVRF1 = "192.0.2.101" - gribiIPv4EntryDefVRF2 = "192.0.2.102" - gribiIPv4EntryDefVRF3 = "192.0.2.103" - gribiIPv4EntryDefVRF4 = "192.0.2.104" - gribiIPv4EntryDefVRF5 = "192.0.2.105" - gribiIPv4EntryVRF1111 = "203.0.113.1" - gribiIPv4EntryVRF1112 = "203.0.113.2" - gribiIPv4EntryVRF2221 = "203.0.113.100" - gribiIPv4EntryVRF2222 = "203.0.113.101" - gribiIPv4EntryEncapVRF = "138.0.11.0" - noMatchEncapDest = "20.0.0.1" -) - -var ( - dutPort2DummyIP = attrs.Attributes{ - Desc: "dutPort2", - IPv4Sec: "192.0.2.33", - IPv4LenSec: plenIPv4, - } - - otgPort2DummyIP = attrs.Attributes{ - Desc: "otgPort2", - IPv4: "192.0.2.34", - IPv4Len: plenIPv4, - } - - dutPort3DummyIP = attrs.Attributes{ - Desc: "dutPort3", - IPv4Sec: "192.0.2.37", - IPv4LenSec: plenIPv4, - } - - otgPort3DummyIP = attrs.Attributes{ - Desc: "otgPort3", - IPv4: "192.0.2.38", - IPv4Len: plenIPv4, - } - - dutPort4DummyIP = attrs.Attributes{ - Desc: "dutPort4", - IPv4Sec: "192.0.2.41", - IPv4LenSec: plenIPv4, - } - - otgPort4DummyIP = attrs.Attributes{ - Desc: "otgPort4", - IPv4: "192.0.2.42", - IPv4Len: plenIPv4, - } - - dutPort5DummyIP = attrs.Attributes{ - Desc: "dutPort5", - IPv4Sec: "192.0.2.45", - IPv4LenSec: plenIPv4, - } - - otgPort5DummyIP = attrs.Attributes{ - Desc: "otgPort5", - IPv4: "192.0.2.46", - IPv4Len: plenIPv4, - } - dutPort6DummyIP = attrs.Attributes{ - Desc: "dutPort5", - IPv4Sec: "192.0.2.49", - IPv4LenSec: plenIPv4, - } - - otgPort6DummyIP = attrs.Attributes{ - Desc: "otgPort5", - IPv4: "192.0.2.50", - IPv4Len: plenIPv4, - } - dutPort7DummyIP = attrs.Attributes{ - Desc: "dutPort5", - IPv4Sec: "192.0.2.53", - IPv4LenSec: plenIPv4, - } - - otgPort7DummyIP = attrs.Attributes{ - Desc: "otgPort5", - IPv4: "192.0.2.54", - IPv4Len: plenIPv4, - } -) - -func programAftWithDummyIP(t *testing.T, dut *ondatra.DUTDevice, client *fluent.GRIBIClient) { - client.Modify().AddEntry(t, - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(11).WithMacAddress(magicMAC).WithInterfaceRef(dut.Port(t, "port2").Name()). - WithIPAddress(otgPort2DummyIP.IPv4), - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(12).WithMacAddress(magicMAC).WithInterfaceRef(dut.Port(t, "port3").Name()). - WithIPAddress(otgPort3DummyIP.IPv4), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(11).AddNextHop(11, 1).AddNextHop(12, 3), - fluent.IPv4Entry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithPrefix(gribiIPv4EntryDefVRF1+"/"+maskLen32).WithNextHopGroup(11), - - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(13).WithMacAddress(magicMAC).WithInterfaceRef(dut.Port(t, "port4").Name()). - WithIPAddress(otgPort4DummyIP.IPv4), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(12).AddNextHop(13, 2), - fluent.IPv4Entry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithPrefix(gribiIPv4EntryDefVRF2+"/"+maskLen32).WithNextHopGroup(12), - - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(14).WithMacAddress(magicMAC).WithInterfaceRef(dut.Port(t, "port5").Name()). - WithIPAddress(otgPort5DummyIP.IPv4), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(13).AddNextHop(14, 1), - fluent.IPv4Entry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithPrefix(gribiIPv4EntryDefVRF3+"/"+maskLen32).WithNextHopGroup(13), - - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(15).WithMacAddress(magicMAC).WithInterfaceRef(dut.Port(t, "port6").Name()). - WithIPAddress(otgPort6DummyIP.IPv4), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(14).AddNextHop(15, 1), - fluent.IPv4Entry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithPrefix(gribiIPv4EntryDefVRF4+"/"+maskLen32).WithNextHopGroup(14), - - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(16).WithMacAddress(magicMAC).WithInterfaceRef(dut.Port(t, "port7").Name()). - WithIPAddress(otgPort7DummyIP.IPv4), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(15).AddNextHop(16, 1), - fluent.IPv4Entry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithPrefix(gribiIPv4EntryDefVRF5+"/"+maskLen32).WithNextHopGroup(15), - ) -} - -// configStaticArp configures static arp entries -func configStaticArp(p string, ipv4addr string, macAddr string) *oc.Interface { - i := &oc.Interface{Name: ygot.String(p)} - i.Type = oc.IETFInterfaces_InterfaceType_ethernetCsmacd - s := i.GetOrCreateSubinterface(0) - s4 := s.GetOrCreateIpv4() - n4 := s4.GetOrCreateNeighbor(ipv4addr) - n4.LinkLayerAddress = ygot.String(macAddr) - return i -} - -// StaticARPWithSpecificIP configures secondary IPs and static ARP. -func StaticARPWithSpecificIP(t *testing.T, dut *ondatra.DUTDevice) { - t.Helper() - p2 := dut.Port(t, "port2") - p3 := dut.Port(t, "port3") - p4 := dut.Port(t, "port4") - p5 := dut.Port(t, "port5") - p6 := dut.Port(t, "port6") - p7 := dut.Port(t, "port7") - gnmi.Update(t, dut, gnmi.OC().Interface(p2.Name()).Config(), dutPort2DummyIP.NewOCInterface(p2.Name(), dut)) - gnmi.Update(t, dut, gnmi.OC().Interface(p3.Name()).Config(), dutPort3DummyIP.NewOCInterface(p3.Name(), dut)) - gnmi.Update(t, dut, gnmi.OC().Interface(p4.Name()).Config(), dutPort4DummyIP.NewOCInterface(p4.Name(), dut)) - gnmi.Update(t, dut, gnmi.OC().Interface(p5.Name()).Config(), dutPort5DummyIP.NewOCInterface(p5.Name(), dut)) - gnmi.Update(t, dut, gnmi.OC().Interface(p6.Name()).Config(), dutPort6DummyIP.NewOCInterface(p6.Name(), dut)) - gnmi.Update(t, dut, gnmi.OC().Interface(p7.Name()).Config(), dutPort7DummyIP.NewOCInterface(p7.Name(), dut)) - gnmi.Update(t, dut, gnmi.OC().Interface(p2.Name()).Config(), configStaticArp(p2.Name(), otgPort2DummyIP.IPv4, magicMAC)) - gnmi.Update(t, dut, gnmi.OC().Interface(p3.Name()).Config(), configStaticArp(p3.Name(), otgPort3DummyIP.IPv4, magicMAC)) - gnmi.Update(t, dut, gnmi.OC().Interface(p4.Name()).Config(), configStaticArp(p4.Name(), otgPort4DummyIP.IPv4, magicMAC)) - gnmi.Update(t, dut, gnmi.OC().Interface(p5.Name()).Config(), configStaticArp(p5.Name(), otgPort5DummyIP.IPv4, magicMAC)) - gnmi.Update(t, dut, gnmi.OC().Interface(p6.Name()).Config(), configStaticArp(p6.Name(), otgPort6DummyIP.IPv4, magicMAC)) - gnmi.Update(t, dut, gnmi.OC().Interface(p7.Name()).Config(), configStaticArp(p7.Name(), otgPort7DummyIP.IPv4, magicMAC)) -} - -// StaticARPWithMagicUniversalIP programs the static ARP with magic universal IP -func StaticARPWithMagicUniversalIP(t *testing.T, dut *ondatra.DUTDevice) { - t.Helper() - sb := &gnmi.SetBatch{} - p2 := dut.Port(t, "port2") - p3 := dut.Port(t, "port3") - p4 := dut.Port(t, "port4") - p5 := dut.Port(t, "port5") - p6 := dut.Port(t, "port6") - p7 := dut.Port(t, "port7") - portList := []*ondatra.Port{p2, p3, p4, p5, p6, p7} - for idx, p := range portList { - s := &oc.NetworkInstance_Protocol_Static{ - Prefix: ygot.String(magicIP + "/32"), - NextHop: map[string]*oc.NetworkInstance_Protocol_Static_NextHop{ - strconv.Itoa(idx): { - Index: ygot.String(strconv.Itoa(idx)), - InterfaceRef: &oc.NetworkInstance_Protocol_Static_NextHop_InterfaceRef{ - Interface: ygot.String(p.Name()), - }, - }, - }, - } - sp := gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(dut)).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_STATIC, deviations.StaticProtocolName(dut)) - gnmi.BatchUpdate(sb, sp.Static(magicIP+"/32").Config(), s) - gnmi.BatchUpdate(sb, gnmi.OC().Interface(p.Name()).Config(), configStaticArp(p.Name(), magicIP, magicMAC)) - } - sb.Set(t, dut) -} - -// ConfigureBaseGribiRoutes programs the base gribi routes for encap FRR using repair VRF -func ConfigureBaseGribiRoutes(ctx context.Context, t *testing.T, dut *ondatra.DUTDevice, client *fluent.GRIBIClient) { - t.Helper() - - // Programming AFT entries for prefixes in DEFAULT VRF - if deviations.GRIBIMACOverrideStaticARPStaticRoute(dut) { - client.Modify().AddEntry(t, - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(11).WithMacAddress(magicMAC).WithInterfaceRef(dut.Port(t, "port2").Name()).WithIPAddress(magicIP), - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(12).WithMacAddress(magicMAC).WithInterfaceRef(dut.Port(t, "port3").Name()).WithIPAddress(magicIP), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(11).AddNextHop(11, 1).AddNextHop(12, 3), - - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(13).WithMacAddress(magicMAC).WithInterfaceRef(dut.Port(t, "port4").Name()).WithIPAddress(magicIP), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(12).AddNextHop(13, 2), - - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(14).WithMacAddress(magicMAC).WithInterfaceRef(dut.Port(t, "port5").Name()).WithIPAddress(magicIP), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(13).AddNextHop(14, 1), - - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(15).WithMacAddress(magicMAC).WithInterfaceRef(dut.Port(t, "port6").Name()).WithIPAddress(magicIP), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(14).AddNextHop(15, 1), - - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(16).WithMacAddress(magicMAC).WithInterfaceRef(dut.Port(t, "port7").Name()).WithIPAddress(magicIP), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(15).AddNextHop(16, 1), - ) - } else if deviations.GRIBIMACOverrideWithStaticARP(dut) { - programAftWithDummyIP(t, dut, client) - } else { - client.Modify().AddEntry(t, - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(11).WithMacAddress(magicMAC).WithInterfaceRef(dut.Port(t, "port2").Name()), - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(12).WithMacAddress(magicMAC).WithInterfaceRef(dut.Port(t, "port3").Name()), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(11).AddNextHop(11, 1).AddNextHop(12, 3), - - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(13).WithMacAddress(magicMAC).WithInterfaceRef(dut.Port(t, "port4").Name()), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(12).AddNextHop(13, 2), - - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(14).WithMacAddress(magicMAC).WithInterfaceRef(dut.Port(t, "port5").Name()), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(13).AddNextHop(14, 1), - - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(15).WithMacAddress(magicMAC).WithInterfaceRef(dut.Port(t, "port6").Name()), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(14).AddNextHop(15, 1), - - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(16).WithMacAddress(magicMAC).WithInterfaceRef(dut.Port(t, "port7").Name()), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(15).AddNextHop(16, 1), - ) - } - if err := awaitTimeout(ctx, t, client, time.Minute); err != nil { - t.Logf("Could not program entries via client, got err, check error codes: %v", err) - } - - client.Modify().AddEntry(t, - fluent.IPv4Entry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithPrefix(gribiIPv4EntryDefVRF1+"/"+maskLen32).WithNextHopGroup(11), - fluent.IPv4Entry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithPrefix(gribiIPv4EntryDefVRF2+"/"+maskLen32).WithNextHopGroup(12), - fluent.IPv4Entry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithPrefix(gribiIPv4EntryDefVRF3+"/"+maskLen32).WithNextHopGroup(13), - fluent.IPv4Entry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithPrefix(gribiIPv4EntryDefVRF4+"/"+maskLen32).WithNextHopGroup(14), - fluent.IPv4Entry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithPrefix(gribiIPv4EntryDefVRF5+"/"+maskLen32).WithNextHopGroup(15), - ) - if err := awaitTimeout(ctx, t, client, time.Minute); err != nil { - t.Logf("Could not program entries via client, got err, check error codes: %v", err) - } - - defaultVRFIPList := []string{gribiIPv4EntryDefVRF1, gribiIPv4EntryDefVRF2, gribiIPv4EntryDefVRF3, gribiIPv4EntryDefVRF4, gribiIPv4EntryDefVRF5} - for ip := range defaultVRFIPList { - chk.HasResult(t, client.Results(t), - fluent.OperationResult(). - WithIPv4Operation(defaultVRFIPList[ip]+"/32"). - WithOperationType(constants.Add). - WithProgrammingResult(fluent.InstalledInFIB). - AsResult(), - chk.IgnoreOperationID(), - ) - } - - // Programming AFT entries for backup NHG - client.Modify().AddEntry(t, - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(2000).WithDecapsulateHeader(fluent.IPinIP).WithNextHopNetworkInstance(deviations.DefaultNetworkInstance(dut)), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(2000).AddNextHop(2000, 1), - ) - if err := awaitTimeout(ctx, t, client, time.Minute); err != nil { - t.Logf("Could not program entries via client, got err, check error codes: %v", err) - } - - // Programming AFT entries for prefixes in TE_VRF_222 - client.Modify().AddEntry(t, - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(3).WithIPAddress(gribiIPv4EntryDefVRF3), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(2).AddNextHop(3, 1).WithBackupNHG(2000), - fluent.IPv4Entry().WithNetworkInstance(niTEVRF222).WithNextHopGroupNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithPrefix(gribiIPv4EntryVRF2221+"/"+maskLen32).WithNextHopGroup(2), - - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(5).WithIPAddress(gribiIPv4EntryDefVRF5), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(4).AddNextHop(5, 1).WithBackupNHG(2000), - fluent.IPv4Entry().WithNetworkInstance(niTEVRF222).WithNextHopGroupNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithPrefix(gribiIPv4EntryVRF2222+"/"+maskLen32).WithNextHopGroup(4), - ) - if err := awaitTimeout(ctx, t, client, time.Minute); err != nil { - t.Logf("Could not program entries via client, got err, check error codes: %v", err) - } - - teVRF222IPList := []string{gribiIPv4EntryVRF2221, gribiIPv4EntryVRF2222} - for ip := range teVRF222IPList { - chk.HasResult(t, client.Results(t), - fluent.OperationResult(). - WithIPv4Operation(teVRF222IPList[ip]+"/32"). - WithOperationType(constants.Add). - WithProgrammingResult(fluent.InstalledInFIB). - AsResult(), - chk.IgnoreOperationID(), - ) - } - - // Programming AFT entries for backup NHG - client.Modify().AddEntry(t, - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(1000).WithDecapsulateHeader(fluent.IPinIP).WithEncapsulateHeader(fluent.IPinIP). - WithIPinIP(ipv4OuterSrc222Addr, gribiIPv4EntryVRF2221). - WithNextHopNetworkInstance(niTEVRF222), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(1000).AddNextHop(1000, 1).WithBackupNHG(2000), - - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(1001).WithDecapsulateHeader(fluent.IPinIP).WithEncapsulateHeader(fluent.IPinIP). - WithIPinIP(ipv4OuterSrc222Addr, gribiIPv4EntryVRF2222). - WithNextHopNetworkInstance(niTEVRF222), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(1001).AddNextHop(1001, 1).WithBackupNHG(2000), - - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(3000).WithNextHopNetworkInstance(niRepairVrf), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(3000).AddNextHop(3000, 1), - ) - if err := awaitTimeout(ctx, t, client, time.Minute); err != nil { - t.Logf("Could not program entries via client, got err, check error codes: %v", err) - } - - // Programming AFT entries for prefixes in TE_VRF_111 - client.Modify().AddEntry(t, - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(1).WithIPAddress(gribiIPv4EntryDefVRF1), - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(2).WithIPAddress(gribiIPv4EntryDefVRF2), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(1).AddNextHop(1, 1).AddNextHop(2, 3).WithBackupNHG(3000), - fluent.IPv4Entry().WithNetworkInstance(niTEVRF111).WithNextHopGroupNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithPrefix(gribiIPv4EntryVRF1111+"/"+maskLen32).WithNextHopGroup(1), - - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(4).WithIPAddress(gribiIPv4EntryDefVRF4), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(3).AddNextHop(4, 1).WithBackupNHG(3000), - fluent.IPv4Entry().WithNetworkInstance(niTEVRF111).WithNextHopGroupNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithPrefix(gribiIPv4EntryVRF1112+"/"+maskLen32).WithNextHopGroup(3), - - fluent.IPv4Entry().WithNetworkInstance(niRepairVrf).WithNextHopGroupNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithPrefix(gribiIPv4EntryVRF1111+"/"+maskLen32).WithNextHopGroup(1000), - fluent.IPv4Entry().WithNetworkInstance(niRepairVrf).WithNextHopGroupNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithPrefix(gribiIPv4EntryVRF1112+"/"+maskLen32).WithNextHopGroup(1001), - ) - if err := awaitTimeout(ctx, t, client, time.Minute); err != nil { - t.Logf("Could not program entries via client, got err, check error codes: %v", err) - } - - teVRF111IPList := []string{gribiIPv4EntryVRF1111, gribiIPv4EntryVRF1112} - for ip := range teVRF111IPList { - chk.HasResult(t, client.Results(t), - fluent.OperationResult(). - WithIPv4Operation(teVRF111IPList[ip]+"/32"). - WithOperationType(constants.Add). - WithProgrammingResult(fluent.InstalledInFIB). - AsResult(), - chk.IgnoreOperationID(), - ) - } - - // Programming AFT entries for backup NHG - client.Modify().AddEntry(t, - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(2001).WithNextHopNetworkInstance(deviations.DefaultNetworkInstance(dut)), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(2001).AddNextHop(2001, 1), - ) - if err := awaitTimeout(ctx, t, client, time.Minute); err != nil { - t.Logf("Could not program entries via client, got err, check error codes: %v", err) - } - - // Programming AFT entries for prefixes in ENCAP_TE_VRF_A - client.Modify().AddEntry(t, - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(101).WithEncapsulateHeader(fluent.IPinIP). - WithIPinIP(ipv4OuterSrc111Addr, gribiIPv4EntryVRF1111). - WithNextHopNetworkInstance(niTEVRF111), - fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithIndex(102).WithEncapsulateHeader(fluent.IPinIP). - WithIPinIP(ipv4OuterSrc111Addr, gribiIPv4EntryVRF1112). - WithNextHopNetworkInstance(niTEVRF111), - fluent.NextHopGroupEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithID(101).AddNextHop(101, 1).AddNextHop(102, 3).WithBackupNHG(2001), - fluent.IPv4Entry().WithNetworkInstance(niEncapTeVrfA).WithNextHopGroupNetworkInstance(deviations.DefaultNetworkInstance(dut)). - WithPrefix(gribiIPv4EntryEncapVRF+"/"+maskLen24).WithNextHopGroup(101), - ) - if err := awaitTimeout(ctx, t, client, time.Minute); err != nil { - t.Logf("Could not program entries via client, got err, check error codes: %v", err) - } - - chk.HasResult(t, client.Results(t), - fluent.OperationResult(). - WithIPv4Operation(gribiIPv4EntryEncapVRF+"/24"). - WithOperationType(constants.Add). - WithProgrammingResult(fluent.InstalledInFIB). - AsResult(), - chk.IgnoreOperationID(), - ) -} - -// TestCase is a struct to hold the parameters for FRR test cases. -type TestCase struct { - Desc string - DownPortList []string - CapturePortList []string - EncapHeaderOuterIPList []string - EncapHeaderInnerIPList []string - TrafficDestIP string - LoadBalancePercent []float64 - TestID string -} - -// TestCases returns a list of base test cases for FRR tests. -func TestCases(atePortNamelist []string, ipv4InnerDst string) []*TestCase { - cases := []*TestCase{ - { - Desc: "Test-1: primary encap unviable but backup encap viable for single tunnel", - DownPortList: []string{"port2", "port3", "port4"}, - CapturePortList: []string{atePortNamelist[4], atePortNamelist[5]}, - EncapHeaderOuterIPList: []string{gribiIPv4EntryVRF2221, gribiIPv4EntryVRF1112}, - EncapHeaderInnerIPList: []string{ipv4InnerDst, ipv4InnerDst}, - TrafficDestIP: ipv4InnerDst, - LoadBalancePercent: []float64{0, 0, 0, 0.25, 0.75, 0, 0}, - TestID: "primarySingle", - }, { - Desc: "Test-2: primary and backup encap unviable for single tunnel", - DownPortList: []string{"port2", "port3", "port4", "port5"}, - CapturePortList: []string{atePortNamelist[5], atePortNamelist[7]}, - EncapHeaderOuterIPList: []string{gribiIPv4EntryVRF1112}, - EncapHeaderInnerIPList: []string{ipv4InnerDst}, - TrafficDestIP: ipv4InnerDst, - LoadBalancePercent: []float64{0, 0, 0, 0, 0.75, 0, 0.25}, - TestID: "primaryBackupSingle", - }, { - Desc: "Test-3: primary encap unviable with backup to routing for single tunnel", - DownPortList: []string{"port2", "port3", "port4"}, - CapturePortList: []string{atePortNamelist[5], atePortNamelist[7]}, - EncapHeaderOuterIPList: []string{gribiIPv4EntryVRF1112}, - EncapHeaderInnerIPList: []string{ipv4InnerDst}, - TrafficDestIP: ipv4InnerDst, - LoadBalancePercent: []float64{0, 0, 0, 0, 0.75, 0, 0.25}, - TestID: "primaryBackupRoutingSingle", - }, { - Desc: "Test-4: primary encap unviable but backup encap viable for all tunnels", - DownPortList: []string{"port2", "port3", "port4", "port6"}, - CapturePortList: []string{atePortNamelist[4], atePortNamelist[6]}, - EncapHeaderOuterIPList: []string{gribiIPv4EntryVRF2221, gribiIPv4EntryVRF2222}, - EncapHeaderInnerIPList: []string{ipv4InnerDst, ipv4InnerDst}, - TrafficDestIP: ipv4InnerDst, - LoadBalancePercent: []float64{0, 0, 0, 0.25, 0, 0.75, 0}, - TestID: "primaryAll", - }, { - Desc: "Test-5: primary and backup encap unviable for all tunnels", - DownPortList: []string{"port2", "port3", "port4", "port5", "port6", "port7"}, - CapturePortList: []string{atePortNamelist[7]}, - EncapHeaderOuterIPList: []string{}, - EncapHeaderInnerIPList: []string{ipv4InnerDst}, - TrafficDestIP: ipv4InnerDst, - LoadBalancePercent: []float64{0, 0, 0, 0, 0, 0, 1}, - TestID: "primaryBackupAll", - }, { - Desc: "Test-6: primary encap unviable with backup to routing for all tunnels", - DownPortList: []string{"port2", "port3", "port4", "port6"}, - CapturePortList: []string{atePortNamelist[7]}, - EncapHeaderOuterIPList: []string{}, - EncapHeaderInnerIPList: []string{ipv4InnerDst}, - TrafficDestIP: ipv4InnerDst, - LoadBalancePercent: []float64{0, 0, 0, 0, 0, 0, 1}, - TestID: "primaryBackupRoutingAll", - }, { - Desc: "Test-7: no match in encap VRF", - DownPortList: []string{}, - CapturePortList: []string{atePortNamelist[7]}, - EncapHeaderOuterIPList: []string{}, - EncapHeaderInnerIPList: []string{noMatchEncapDest}, - TrafficDestIP: noMatchEncapDest, - LoadBalancePercent: []float64{0, 0, 0, 0, 0, 0, 1}, - TestID: "encapNoMatch", - }, - } - - return cases -} - -// awaitTimeout calls a fluent client Await, adding a timeout to the context. -func awaitTimeout(ctx context.Context, t testing.TB, c *fluent.GRIBIClient, timeout time.Duration) error { - t.Helper() - subctx, cancel := context.WithTimeout(ctx, timeout) - defer cancel() - return c.Await(subctx, t) -} From 0fce440dfc2b92fa4bc2671f7be4d4b999e0ee05 Mon Sep 17 00:00:00 2001 From: yini101 <86263319+yini101@users.noreply.github.com> Date: Mon, 27 Jan 2025 05:50:07 -0800 Subject: [PATCH 09/10] RT-1.54: Remove add path configuration (#3679) Disable add path on ixia since the test does not rely on add path. --- .../bgp_override_as_path_split_horizon_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/feature/bgp/otg_tests/bgp_override_as_path_split_horizon_test/bgp_override_as_path_split_horizon_test.go b/feature/bgp/otg_tests/bgp_override_as_path_split_horizon_test/bgp_override_as_path_split_horizon_test.go index 030f0d4fa88..7f574446d81 100644 --- a/feature/bgp/otg_tests/bgp_override_as_path_split_horizon_test/bgp_override_as_path_split_horizon_test.go +++ b/feature/bgp/otg_tests/bgp_override_as_path_split_horizon_test/bgp_override_as_path_split_horizon_test.go @@ -176,12 +176,10 @@ func configureOTG(t *testing.T, otg *otg.OTG) (gosnappi.BgpV4Peer, gosnappi.Devi iDut1Bgp4Peer := iDut1Bgp.Ipv4Interfaces().Add().SetIpv4Name(iDut1Ipv4.Name()).Peers().Add().SetName(otgPort1V4Peer) iDut1Bgp4Peer.SetPeerAddress(iDut1Ipv4.Gateway()).SetAsNumber(ateAS1).SetAsType(gosnappi.BgpV4PeerAsType.EBGP) - iDut1Bgp4Peer.Capability().SetIpv4UnicastAddPath(true).SetIpv6UnicastAddPath(true) iDut1Bgp4Peer.LearnedInformationFilter().SetUnicastIpv4Prefix(true).SetUnicastIpv6Prefix(true) iDut2Bgp4Peer := iDut2Bgp.Ipv4Interfaces().Add().SetIpv4Name(iDut2Ipv4.Name()).Peers().Add().SetName(otgPort2V4Peer) iDut2Bgp4Peer.SetPeerAddress(iDut2Ipv4.Gateway()).SetAsNumber(ateAS2).SetAsType(gosnappi.BgpV4PeerAsType.EBGP) - iDut2Bgp4Peer.Capability().SetIpv4UnicastAddPath(true).SetIpv6UnicastAddPath(true) iDut2Bgp4Peer.LearnedInformationFilter().SetUnicastIpv4Prefix(true).SetUnicastIpv6Prefix(true) t.Logf("Pushing config to OTG and starting protocols...") From 79aa0be0cf55b96572cad1ed2e845ebc6b02785a Mon Sep 17 00:00:00 2001 From: jianchen-g Date: Mon, 27 Jan 2025 09:18:29 -0800 Subject: [PATCH 10/10] Adding test files for 400G ZR++ logical channel test and tunable parameter test (#3712) * adding test files for 400G ZR++ logical channel test and tunable parameter test * modified the cisco deviation part --- .../tests/zrp_logical_channels_test/README.md | 2 +- .../metadata.textproto | 28 ++ .../zrp_logical_channels_test.go | 280 ++++++++++++++++ .../zrp_tunable_parameters_test/README.md | 2 +- .../metadata.textproto | 24 ++ .../zrp_tunable_parameters_test.go | 305 ++++++++++++++++++ 6 files changed, 639 insertions(+), 2 deletions(-) create mode 100644 feature/platform/transceiver/logical_channels/tests/zrp_logical_channels_test/metadata.textproto create mode 100644 feature/platform/transceiver/logical_channels/tests/zrp_logical_channels_test/zrp_logical_channels_test.go create mode 100644 feature/platform/transceiver/tunable_parameters/tests/zrp_tunable_parameters_test/metadata.textproto create mode 100644 feature/platform/transceiver/tunable_parameters/tests/zrp_tunable_parameters_test/zrp_tunable_parameters_test.go diff --git a/feature/platform/transceiver/logical_channels/tests/zrp_logical_channels_test/README.md b/feature/platform/transceiver/logical_channels/tests/zrp_logical_channels_test/README.md index d79558ddcb4..19b7daed9b7 100644 --- a/feature/platform/transceiver/logical_channels/tests/zrp_logical_channels_test/README.md +++ b/feature/platform/transceiver/logical_channels/tests/zrp_logical_channels_test/README.md @@ -1,4 +1,4 @@ -# TRANSCEIVER-11: Telemetry: 400ZR_PLUS Optics logical channels provisioning and related telemetry. +# TRANSCEIVER-11 (400ZR_PLUS): Telemetry: 400ZR_PLUS Optics logical channels provisioning and related telemetry. ## Summary diff --git a/feature/platform/transceiver/logical_channels/tests/zrp_logical_channels_test/metadata.textproto b/feature/platform/transceiver/logical_channels/tests/zrp_logical_channels_test/metadata.textproto new file mode 100644 index 00000000000..ce84a00ccfc --- /dev/null +++ b/feature/platform/transceiver/logical_channels/tests/zrp_logical_channels_test/metadata.textproto @@ -0,0 +1,28 @@ +# proto-file: github.com/openconfig/featureprofiles/proto/metadata.proto +# proto-message: Metadata +uuid: "e5b469c9-f765-4f95-b3dc-af4c926309f5" +plan_id: "TRANSCEIVER-11 (400ZR_PLUS)" +description: "Telemetry: 400ZR_PLUS Optics logical channels provisioning and related telemetry." +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 + channel_assignment_rate_class_parameters_unsupported: true + } +} +platform_exceptions: { + platform: { + vendor: CISCO + } + deviations: { + otn_channel_trib_unsupported: true + eth_channel_ingress_parameters_unsupported: true + eth_channel_assignment_cisco_numbering: true + otn_channel_assignment_cisco_numbering: true + } +} diff --git a/feature/platform/transceiver/logical_channels/tests/zrp_logical_channels_test/zrp_logical_channels_test.go b/feature/platform/transceiver/logical_channels/tests/zrp_logical_channels_test/zrp_logical_channels_test.go new file mode 100644 index 00000000000..d0253fa0c24 --- /dev/null +++ b/feature/platform/transceiver/logical_channels/tests/zrp_logical_channels_test/zrp_logical_channels_test.go @@ -0,0 +1,280 @@ +package zrp_logical_channels_test + +import ( + "flag" + "strings" + "testing" + "time" + + "github.com/google/go-cmp/cmp" + "github.com/openconfig/featureprofiles/internal/attrs" + "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 ( + targetOutputPower = -3 + frequency = 193100000 + samplingInterval = 10 * time.Second + timeout = 10 * time.Minute + otnIndex1 = uint32(4001) + otnIndex2 = uint32(4002) + ethernetIndex1 = uint32(40001) + ethernetIndex2 = uint32(40002) +) + +var ( + dutPort1 = attrs.Attributes{ + Desc: "dutPort1", + IPv4: "192.0.2.1", + IPv4Len: 30, + } + dutPort2 = attrs.Attributes{ + Desc: "dutPort2", + IPv4: "192.0.2.5", + IPv4Len: 30, + } + operationalModeFlag = flag.Int("operational_mode", 5, "vendor-specific operational-mode for the channel") + operationalMode uint16 +) + +type testcase struct { + desc string + got any + want any +} + +func TestMain(m *testing.M) { + fptest.RunTests(m) +} + +func Test400ZRLogicalChannels(t *testing.T) { + dut := ondatra.DUT(t, "dut") + if operationalModeFlag != nil { + operationalMode = uint16(*operationalModeFlag) + } else { + t.Fatalf("Please specify the vendor-specific operational-mode flag") + } + p1 := dut.Port(t, "port1") + p2 := dut.Port(t, "port2") + + fptest.ConfigureDefaultNetworkInstance(t, dut) + + gnmi.Replace(t, dut, gnmi.OC().Interface(p1.Name()).Config(), dutPort1.NewOCInterface(p1.Name(), dut)) + gnmi.Replace(t, dut, gnmi.OC().Interface(p2.Name()).Config(), dutPort2.NewOCInterface(p2.Name(), dut)) + + oc1 := components.OpticalChannelComponentFromPort(t, dut, p1) + oc2 := components.OpticalChannelComponentFromPort(t, dut, p2) + tr1 := gnmi.Get(t, dut, gnmi.OC().Interface(p1.Name()).Transceiver().State()) + tr2 := gnmi.Get(t, dut, gnmi.OC().Interface(p2.Name()).Transceiver().State()) + + cfgplugins.ConfigOpticalChannel(t, dut, oc1, frequency, targetOutputPower, operationalMode) + cfgplugins.ConfigOTNChannel(t, dut, oc1, otnIndex1, ethernetIndex1) + cfgplugins.ConfigETHChannel(t, dut, p1.Name(), tr1, otnIndex1, ethernetIndex1) + cfgplugins.ConfigOpticalChannel(t, dut, oc2, frequency, targetOutputPower, operationalMode) + cfgplugins.ConfigOTNChannel(t, dut, oc2, otnIndex2, ethernetIndex2) + cfgplugins.ConfigETHChannel(t, dut, p2.Name(), tr2, otnIndex2, ethernetIndex2) + + ethChan1 := samplestream.New(t, dut, gnmi.OC().TerminalDevice().Channel(ethernetIndex1).State(), samplingInterval) + defer ethChan1.Close() + ethChan2 := samplestream.New(t, dut, gnmi.OC().TerminalDevice().Channel(ethernetIndex2).State(), samplingInterval) + defer ethChan2.Close() + otnChan1 := samplestream.New(t, dut, gnmi.OC().TerminalDevice().Channel(otnIndex1).State(), samplingInterval) + defer otnChan1.Close() + otnChan2 := samplestream.New(t, dut, gnmi.OC().TerminalDevice().Channel(otnIndex2).State(), samplingInterval) + defer otnChan2.Close() + + gnmi.Await(t, dut, gnmi.OC().Interface(p1.Name()).OperStatus().State(), timeout, oc.Interface_OperStatus_UP) + gnmi.Await(t, dut, gnmi.OC().Interface(p2.Name()).OperStatus().State(), timeout, oc.Interface_OperStatus_UP) + + validateEthernetChannelTelemetry(t, dut, otnIndex1, ethernetIndex1, ethChan1) + validateEthernetChannelTelemetry(t, dut, otnIndex2, ethernetIndex2, ethChan2) + validateOTNChannelTelemetry(t, dut, otnIndex1, ethernetIndex1, oc1, otnChan1) + validateOTNChannelTelemetry(t, dut, otnIndex2, ethernetIndex2, oc2, otnChan2) +} + +func validateEthernetChannelTelemetry(t *testing.T, dut *ondatra.DUTDevice, otnChIdx, ethernetChIdx uint32, stream *samplestream.SampleStream[*oc.TerminalDevice_Channel]) { + val := stream.Next() // value received in the gnmi subscription within 10 seconds + if val == nil { + t.Fatalf("Ethernet Channel telemetry stream not received in last 10 seconds") + } + ec, ok := val.Val() + if !ok { + t.Fatalf("Ethernet Channel telemetry stream empty in last 10 seconds") + } + tcs := []testcase{ + { + desc: "Index", + got: ec.GetIndex(), + want: ethernetChIdx, + }, + { + desc: "Description", + got: ec.GetDescription(), + want: "ETH Logical Channel", + }, + { + desc: "Logical Channel Type", + got: ec.GetLogicalChannelType().String(), + want: oc.TransportTypes_LOGICAL_ELEMENT_PROTOCOL_TYPE_PROT_ETHERNET.String(), + }, + { + desc: "Trib Protocol", + got: ec.GetTribProtocol().String(), + want: oc.TransportTypes_TRIBUTARY_PROTOCOL_TYPE_PROT_400GE.String(), + }, + } + var assignmentIndexTestcases []testcase + + index := 0 + if deviations.EthChannelAssignmentCiscoNumbering(dut) { + index = 1 + } + + assignment := ec.GetAssignment(uint32(index)) + assignmentIndexTestcases = []testcase{ + { + desc: "Assignment: Index", + got: assignment.GetIndex(), + want: uint32(index), + }, + { + desc: "Assignment: Logical Channel", + got: assignment.GetLogicalChannel(), + want: otnChIdx, + }, + { + desc: "Assignment: Description", + got: assignment.GetDescription(), + want: "ETH to OTN", + }, + { + desc: "Assignment: Allocation", + got: assignment.GetAllocation(), + want: float64(400), + }, + { + desc: "Assignment: Type", + got: assignment.GetAssignmentType().String(), + want: oc.Assignment_AssignmentType_LOGICAL_CHANNEL.String(), + }, + } + tcs = append(tcs, assignmentIndexTestcases...) + for _, tc := range tcs { + t.Run(tc.desc, func(t *testing.T) { + if diff := cmp.Diff(tc.got, tc.want); diff != "" { + t.Errorf("Ethernet Logical Channel: %s, diff (-got +want):\n%s", tc.desc, diff) + } + }) + } +} + +func validateOTNChannelTelemetry(t *testing.T, dut *ondatra.DUTDevice, otnChIdx uint32, ethChIdx uint32, opticalChannel string, stream *samplestream.SampleStream[*oc.TerminalDevice_Channel]) { + val := stream.Next() // value received in the gnmi subscription within 10 seconds + if val == nil { + t.Fatalf("OTN Channel telemetry stream not received in last 10 seconds") + } + cc, ok := val.Val() + if !ok { + t.Fatalf("OTN Channel telemetry stream empty in last 10 seconds") + } + tcs := []testcase{ + { + desc: "Description", + got: cc.GetDescription(), + want: "OTN Logical Channel", + }, + { + desc: "Index", + got: cc.GetIndex(), + want: otnChIdx, + }, + { + desc: "Logical Channel Type", + got: cc.GetLogicalChannelType().String(), + want: oc.TransportTypes_LOGICAL_ELEMENT_PROTOCOL_TYPE_PROT_OTN.String(), + }, + } + var opticalChannelAssignmentIndexTestcases []testcase + + index := 0 + if deviations.OTNChannelAssignmentCiscoNumbering(dut) { + opticalChannel = strings.ReplaceAll(opticalChannel, "/", "_") // Ex: ciscoOpticalChannelFormat is OpticalChannel0_0_0_18 + index = 1 + } + + assignment := cc.GetAssignment(uint32(index)) + opticalChannelAssignmentIndexTestcases = []testcase{ + { + desc: "Assignment: Index", + got: assignment.GetIndex(), + want: uint32(index), + }, + { + desc: "Optical Channel Assignment: Optical Channel", + got: assignment.GetOpticalChannel(), + want: opticalChannel, + }, + { + desc: "Optical Channel Assignment: Description", + got: assignment.GetDescription(), + want: "OTN to Optical Channel", + }, + { + desc: "Optical Channel Assignment: Allocation", + got: assignment.GetAllocation(), + want: float64(400), + }, + { + desc: "Optical Channel Assignment: Type", + got: assignment.GetAssignmentType().String(), + want: oc.Assignment_AssignmentType_OPTICAL_CHANNEL.String(), + }, + } + tcs = append(tcs, opticalChannelAssignmentIndexTestcases...) + + if !deviations.OTNChannelTribUnsupported(dut) { + logicalChannelAssignmentTestcases := []testcase{ + { + desc: "Ethernet Assignment: Index", + got: cc.GetAssignment(1).GetIndex(), + want: uint32(1), + }, + { + desc: "Ethernet Assignment: Logical Channel", + got: cc.GetAssignment(1).GetLogicalChannel(), + want: ethChIdx, + }, + { + desc: "Ethernet Assignment: Description", + got: cc.GetAssignment(1).GetDescription(), + want: "OTN to ETH", + }, + { + desc: "Ethernet Assignment: Allocation", + got: cc.GetAssignment(1).GetAllocation(), + want: float64(400), + }, + { + desc: "Ethernet Assignment: Type", + got: cc.GetAssignment(1).GetAssignmentType().String(), + want: oc.Assignment_AssignmentType_LOGICAL_CHANNEL.String(), + }, + } + tcs = append(tcs, logicalChannelAssignmentTestcases...) + } + + for _, tc := range tcs { + t.Run(tc.desc, func(t *testing.T) { + if diff := cmp.Diff(tc.got, tc.want); diff != "" { + t.Errorf("OTN Logical Channel: %s, diff (-got +want):\n%s", tc.desc, diff) + } + }) + } +} diff --git a/feature/platform/transceiver/tunable_parameters/tests/zrp_tunable_parameters_test/README.md b/feature/platform/transceiver/tunable_parameters/tests/zrp_tunable_parameters_test/README.md index 567a834ff8d..3ea934270db 100644 --- a/feature/platform/transceiver/tunable_parameters/tests/zrp_tunable_parameters_test/README.md +++ b/feature/platform/transceiver/tunable_parameters/tests/zrp_tunable_parameters_test/README.md @@ -1,4 +1,4 @@ -# TRANSCEIVER-5: Configuration: 400ZR_PLUS channel frequency, output TX launch power and operational mode setting. +# TRANSCEIVER-5 (400ZR_PLUS): Configuration: 400ZR_PLUS channel frequency, output TX launch power and operational mode setting. ## Summary diff --git a/feature/platform/transceiver/tunable_parameters/tests/zrp_tunable_parameters_test/metadata.textproto b/feature/platform/transceiver/tunable_parameters/tests/zrp_tunable_parameters_test/metadata.textproto new file mode 100644 index 00000000000..547fb7e066a --- /dev/null +++ b/feature/platform/transceiver/tunable_parameters/tests/zrp_tunable_parameters_test/metadata.textproto @@ -0,0 +1,24 @@ +# proto-file: github.com/openconfig/featureprofiles/proto/metadata.proto +# proto-message: Metadata +uuid: "0ff18ddb-5333-4fc3-a2fb-5ac6d372a88f" +plan_id: "TRANSCEIVER-5 (400ZR_PLUS)" +description: "Configuration: 400ZR_PLUS channel frequency, output TX launch power and operational mode setting." +testbed: TESTBED_DUT_400ZR_PLUS +platform_exceptions: { + platform: { + vendor: ARISTA + } + deviations: { + interface_enabled: true + default_network_instance: "default" + missing_zr_optical_channel_tunable_parameters_telemetry: true + } +} +platform_exceptions: { + platform: { + vendor: JUNIPER + } + deviations: { + operational_mode_unsupported: true + } +} diff --git a/feature/platform/transceiver/tunable_parameters/tests/zrp_tunable_parameters_test/zrp_tunable_parameters_test.go b/feature/platform/transceiver/tunable_parameters/tests/zrp_tunable_parameters_test/zrp_tunable_parameters_test.go new file mode 100644 index 00000000000..6c2ca0872f6 --- /dev/null +++ b/feature/platform/transceiver/tunable_parameters/tests/zrp_tunable_parameters_test/zrp_tunable_parameters_test.go @@ -0,0 +1,305 @@ +package zrp_tunable_parameters_test + +import ( + "flag" + "fmt" + "math" + "reflect" + "testing" + "time" + + "github.com/openconfig/featureprofiles/internal/attrs" + "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 ( + samplingInterval = 10 * time.Second + frequencyTolerance = 1800 + timeout = 10 * time.Minute +) + +var ( + dutPort1 = attrs.Attributes{ + Desc: "dutPort1", + IPv4: "192.0.2.1", + IPv4Len: 30, + } + dutPort2 = attrs.Attributes{ + Desc: "dutPort2", + IPv4: "192.0.2.5", + IPv4Len: 30, + } + operationalModeFlag = flag.Int("operational_mode", 5, "vendor-specific operational-mode for the channel") + operationalMode uint16 +) + +func TestMain(m *testing.M) { + fptest.RunTests(m) +} + +func Test400ZRPlusTunableFrequency(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") + p1 := dut.Port(t, "port1") + p2 := dut.Port(t, "port2") + fptest.ConfigureDefaultNetworkInstance(t, dut) + gnmi.Replace(t, dut, gnmi.OC().Interface(p1.Name()).Config(), dutPort1.NewOCInterface(p1.Name(), dut)) + gnmi.Replace(t, dut, gnmi.OC().Interface(p2.Name()).Config(), dutPort2.NewOCInterface(p2.Name(), dut)) + oc1 := components.OpticalChannelComponentFromPort(t, dut, p1) + oc2 := components.OpticalChannelComponentFromPort(t, dut, p2) + streamOC1 := samplestream.New(t, dut, gnmi.OC().Component(oc1).State(), samplingInterval) + defer streamOC1.Close() + streamOC2 := samplestream.New(t, dut, gnmi.OC().Component(oc2).State(), samplingInterval) + defer streamOC2.Close() + tests := []struct { + description string + startFreq uint64 + endFreq uint64 + freqStep uint64 + targetOutputPower float64 + }{ + { + // Validate setting 400ZR++ optics module tunable laser center frequency + // across frequency range 196.100 - 191.375 THz for 75GHz grid. + description: "75GHz grid", + startFreq: 191375000, + endFreq: 196100000, + freqStep: 75000 * 6, + targetOutputPower: -3, + }, + } + for _, tc := range tests { + t.Run(tc.description, func(t *testing.T) { + for freq := tc.startFreq; freq <= tc.endFreq; freq += tc.freqStep { + t.Run(fmt.Sprintf("Freq: %v", freq), func(t *testing.T) { + if deviations.OperationalModeUnsupported(dut) { + operationalMode = 0 + } + cfgplugins.ConfigOpticalChannel(t, dut, oc1, freq, tc.targetOutputPower, operationalMode) + cfgplugins.ConfigOpticalChannel(t, dut, oc2, freq, tc.targetOutputPower, operationalMode) + gnmi.Await(t, dut, gnmi.OC().Interface(p1.Name()).OperStatus().State(), timeout, oc.Interface_OperStatus_UP) + gnmi.Await(t, dut, gnmi.OC().Interface(p2.Name()).OperStatus().State(), timeout, oc.Interface_OperStatus_UP) + validateOpticsTelemetry(t, []*samplestream.SampleStream[*oc.Component]{streamOC1, streamOC2}, freq, tc.targetOutputPower, oc.Interface_OperStatus_UP) + }) + } + }) + } + +} +func Test400ZRPlusTunableOutputPower(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") + p1 := dut.Port(t, "port1") + p2 := dut.Port(t, "port2") + fptest.ConfigureDefaultNetworkInstance(t, dut) + gnmi.Replace(t, dut, gnmi.OC().Interface(p1.Name()).Config(), dutPort1.NewOCInterface(p1.Name(), dut)) + gnmi.Replace(t, dut, gnmi.OC().Interface(p2.Name()).Config(), dutPort2.NewOCInterface(p2.Name(), dut)) + oc1 := components.OpticalChannelComponentFromPort(t, dut, p1) + oc2 := components.OpticalChannelComponentFromPort(t, dut, p2) + streamOC1 := samplestream.New(t, dut, gnmi.OC().Component(oc1).State(), samplingInterval) + defer streamOC1.Close() + streamOC2 := samplestream.New(t, dut, gnmi.OC().Component(oc2).State(), samplingInterval) + defer streamOC2.Close() + tests := []struct { + description string + frequency uint64 + startTargetOutputPower float64 + endTargetOutputPower float64 + targetOutputPowerStep float64 + }{ + { + // Validate adjustable range of transmit output power across -7 to 0 dBm + // range in steps of 1dB. So the module’s output power will be set to -7, + // -6,-5, -4, -3, -2, -1, 0 dBm in each step. + description: "adjustable range of transmit output power across -7 to 0 dBm range in steps of 1dB", + frequency: 193100000, + startTargetOutputPower: -7, + endTargetOutputPower: 0, + targetOutputPowerStep: 1, + }, + } + for _, tc := range tests { + for top := tc.startTargetOutputPower; top <= tc.endTargetOutputPower; top += tc.targetOutputPowerStep { + t.Run(fmt.Sprintf("Target Power: %v", top), func(t *testing.T) { + if deviations.OperationalModeUnsupported(dut) { + operationalMode = 0 + } + + cfgplugins.ConfigOpticalChannel(t, dut, oc1, tc.frequency, top, operationalMode) + cfgplugins.ConfigOpticalChannel(t, dut, oc2, tc.frequency, top, operationalMode) + gnmi.Await(t, dut, gnmi.OC().Interface(p1.Name()).OperStatus().State(), timeout, oc.Interface_OperStatus_UP) + gnmi.Await(t, dut, gnmi.OC().Interface(p2.Name()).OperStatus().State(), timeout, oc.Interface_OperStatus_UP) + validateOpticsTelemetry(t, []*samplestream.SampleStream[*oc.Component]{streamOC1, streamOC2}, tc.frequency, top, oc.Interface_OperStatus_UP) + }) + } + } +} + +func Test400ZRPlusInterfaceFlap(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") + p1 := dut.Port(t, "port1") + p2 := dut.Port(t, "port2") + fptest.ConfigureDefaultNetworkInstance(t, dut) + gnmi.Replace(t, dut, gnmi.OC().Interface(p1.Name()).Config(), dutPort1.NewOCInterface(p1.Name(), dut)) + gnmi.Replace(t, dut, gnmi.OC().Interface(p2.Name()).Config(), dutPort2.NewOCInterface(p2.Name(), dut)) + oc1 := components.OpticalChannelComponentFromPort(t, dut, p1) + oc2 := components.OpticalChannelComponentFromPort(t, dut, p2) + streamOC1 := samplestream.New(t, dut, gnmi.OC().Component(oc1).State(), samplingInterval) + defer streamOC1.Close() + streamOC2 := samplestream.New(t, dut, gnmi.OC().Component(oc2).State(), samplingInterval) + defer streamOC2.Close() + targetPower := float64(-3) + frequency := uint64(193100000) + + if deviations.OperationalModeUnsupported(dut) { + operationalMode = 0 + } + + cfgplugins.ConfigOpticalChannel(t, dut, oc1, frequency, targetPower, operationalMode) + cfgplugins.ConfigOpticalChannel(t, dut, oc2, frequency, targetPower, operationalMode) + gnmi.Await(t, dut, gnmi.OC().Interface(p1.Name()).OperStatus().State(), timeout, oc.Interface_OperStatus_UP) + gnmi.Await(t, dut, gnmi.OC().Interface(p2.Name()).OperStatus().State(), timeout, oc.Interface_OperStatus_UP) + t.Run("Telemetry before flap", func(t *testing.T) { + validateOpticsTelemetry(t, []*samplestream.SampleStream[*oc.Component]{streamOC1, streamOC2}, frequency, targetPower, oc.Interface_OperStatus_UP) + }) + // Disable or shut down the interface on the DUT. + cfgplugins.ToggleInterface(t, dut, p1.Name(), false) + cfgplugins.ToggleInterface(t, dut, p2.Name(), false) + gnmi.Await(t, dut, gnmi.OC().Interface(p1.Name()).OperStatus().State(), timeout, oc.Interface_OperStatus_DOWN) + gnmi.Await(t, dut, gnmi.OC().Interface(p2.Name()).OperStatus().State(), timeout, oc.Interface_OperStatus_DOWN) + + // Verify with interfaces in down state both optics are still streaming + // configured value for frequency. + // Verify for the TX output power with interface in down state a decimal64 + // value of -40 dB is streamed. + t.Run("Telemetry during interface disabled", func(t *testing.T) { + validateOpticsTelemetry(t, []*samplestream.SampleStream[*oc.Component]{streamOC1, streamOC2}, frequency, -40, oc.Interface_OperStatus_DOWN) + }) + // Re-enable the interfaces on the DUT. + cfgplugins.ToggleInterface(t, dut, p1.Name(), true) + cfgplugins.ToggleInterface(t, dut, p2.Name(), true) + gnmi.Await(t, dut, gnmi.OC().Interface(p1.Name()).OperStatus().State(), timeout, oc.Interface_OperStatus_UP) + gnmi.Await(t, dut, gnmi.OC().Interface(p2.Name()).OperStatus().State(), timeout, oc.Interface_OperStatus_UP) + // Verify the ZR optics tune back to the correct frequency and TX output + // power as per the configuration and related telemetry values are updated + // to the value in the normal range again. + t.Run("Telemetry after flap", func(t *testing.T) { + validateOpticsTelemetry(t, []*samplestream.SampleStream[*oc.Component]{streamOC1, streamOC2}, frequency, targetPower, oc.Interface_OperStatus_UP) + }) +} + +func validateOpticsTelemetry(t *testing.T, streams []*samplestream.SampleStream[*oc.Component], frequency uint64, outputPower float64, operStatus oc.E_Interface_OperStatus) { + dut := ondatra.DUT(t, "dut") + var ocs []*oc.Component_OpticalChannel + for _, s := range streams { + val := s.Next() + if val == nil { + t.Fatal("Optical channel streaming telemetry not received") + } + v, ok := val.Val() + if !ok { + t.Fatal("Optical channel streaming telemetry empty") + } + ocs = append(ocs, v.GetOpticalChannel()) + } + + for _, _oc := range ocs { + opm := _oc.GetOperationalMode() + inst := _oc.GetCarrierFrequencyOffset().GetInstant() + avg := _oc.GetCarrierFrequencyOffset().GetAvg() + min := _oc.GetCarrierFrequencyOffset().GetMin() + max := _oc.GetCarrierFrequencyOffset().GetMax() + if got, want := opm, uint16(operationalMode); got != want && !deviations.OperationalModeUnsupported(dut) { + t.Errorf("Optical-Channel: operational-mode: got %v, want %v", got, want) + } + // Laser frequency offset should not be more than +/- 1.8 GHz max from the + // configured centre frequency. + if inst < -1*frequencyTolerance || inst > frequencyTolerance { + t.Errorf("Optical-Channel: carrier-frequency-offset not in tolerable range, got: %v, want: (+/-)%v", inst, frequencyTolerance) + } + for _, ele := range []any{inst, min, max, avg} { + if reflect.TypeOf(ele).Kind() != reflect.Float64 { + t.Fatalf("Value %v is not type float64", ele) + } + } + if deviations.MissingZROpticalChannelTunableParametersTelemetry(dut) { + t.Log("Skipping Min/Max/Avg Tunable Parameters Telemetry validation. Deviation MissingZROpticalChannelTunableParametersTelemetry enabled.") + } else { + // For reported data check for validity: min <= avg/instant <= max + if min > math.Round(inst) { + t.Errorf("Optical-Channel: carrier-frequency-offset min: %v greater than carrier-frequency-offset instant: %v", min, inst) + } + if max < math.Round(inst) { + t.Errorf("Optical-Channel: carrier-frequency-offset max: %v less than carrier-frequency-offset instant: %v", max, inst) + } + if min > math.Round(avg) { + t.Errorf("Optical-Channel: carrier-frequency-offset min: %v greater than carrier-frequency-offset avg: %v", min, avg) + } + if max < math.Round(avg) { + t.Errorf("Optical-Channel: carrier-frequency-offset max: %v less than carrier-frequency-offset avg: %v", max, avg) + } + } + inst = _oc.GetOutputPower().GetInstant() + avg = _oc.GetOutputPower().GetAvg() + min = _oc.GetOutputPower().GetMin() + max = _oc.GetOutputPower().GetMax() + // When set to a specific target output power, transmit power control + // absolute accuracy should be within +/- 1 dBm of the target configured + // output power. + switch operStatus { + case oc.Interface_OperStatus_UP: + if inst < outputPower-1 || inst > outputPower+1 { + t.Errorf("Optical-Channel: output-power not in tolerable range, got: %v, want: %v", inst, outputPower) + } + case oc.Interface_OperStatus_DOWN: + if inst != -40 { + t.Errorf("Optical-Channel: output-power not in tolerable range, got: %v, want: %v", inst, -40) + } + } + for _, ele := range []any{inst, min, max, avg} { + if reflect.TypeOf(ele).Kind() != reflect.Float64 { + t.Fatalf("Value %v is not type float64", ele) + } + } + if deviations.MissingZROpticalChannelTunableParametersTelemetry(dut) { + t.Log("Skipping Min/Max/Avg Tunable Parameters Telemetry validation. Deviation MissingZROpticalChannelTunableParametersTelemetry enabled.") + } else { + // For reported data check for validity: min <= avg/instant <= max + if min > math.Round(inst) { + t.Errorf("Optical-Channel: output-power min: %v greater than output-power instant: %v", min, inst) + } + if max < math.Round(inst) { + t.Errorf("Optical-Channel: output-power max: %v less than output-power instant: %v", max, inst) + } + if min > math.Round(avg) { + t.Errorf("Optical-Channel: output-power min: %v greater than output-power avg: %v", min, avg) + } + if max < math.Round(avg) { + t.Errorf("Optical-Channel: output-power max: %v less than output-power avg: %v", max, avg) + } + } + if got, want := _oc.GetFrequency(), frequency; got != want { + t.Errorf("Optical-Channel: frequency: %v, want: %v", got, want) + } + } +}