From dd152cbca457094add4c4c5853909e39d2d6d3e9 Mon Sep 17 00:00:00 2001 From: Guy Shemesh Date: Wed, 28 May 2025 16:27:15 +0300 Subject: [PATCH 01/55] example for PR example --- docs/code-review-guidlines.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/code-review-guidlines.md b/docs/code-review-guidlines.md index 55baf65c6d3..5317a39b4dc 100644 --- a/docs/code-review-guidlines.md +++ b/docs/code-review-guidlines.md @@ -1,4 +1,4 @@ -# SONiC-MGMT code review guidelines +# SONiC-MGMT code review guidelines- guy shemesh ## Style guide - Avoid usage of hardcoded values, define constants instead. From 8df4b25bd4cb992b05765f58742a73fa137f7943 Mon Sep 17 00:00:00 2001 From: Guy Shemesh Date: Wed, 11 Jun 2025 14:58:41 +0300 Subject: [PATCH 02/55] Adding WA to for Port Error Test 1. adding reeboot before running the test to clean up the db for reset the faults counters 2. adding command that bringup all the ports od the device 3. addding condition for the picked ports, that they are up and connected to optical module. --- tests/layer1/test_port_error.py | 57 +++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index 2801127146b..6d0baa923a6 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -5,6 +5,7 @@ from tests.common.helpers.assertions import pytest_assert from tests.common.utilities import skip_release +from tests.common.platform.transceiver_utils import parse_sfp_eeprom_infos pytestmark = [ pytest.mark.disable_loganalyzer, # disable automatic loganalyzer @@ -44,23 +45,46 @@ def get_mac_fault_count(dut, interface, fault_type): def get_interface_status(dut, interface): return dut.show_and_parse("show interfaces status {}".format(interface))[0].get("oper", "unknown") - @pytest.fixture + @staticmethod + def verify_ports_startup(dut): + dut.shell('show interface status | awk \'NR>2 {print $1}\' | xargs -I{} sudo config interface startup {}') + time.sleep(30) + + #TODO: Reboot the switch before test as a WA of #4384527, remove this after the issue is fixed + @pytest.fixture(scope="class", autouse=True) + def reboot_dut(self, duthosts, localhost, enum_rand_one_per_hwsku_frontend_hostname): + from infra.tools.redmine.redmine_api import is_redmine_issue_active + from tests.common.reboot import reboot + if is_redmine_issue_active([4384527])[0]: + reboot(duthosts[enum_rand_one_per_hwsku_frontend_hostname], + localhost, safe_reboot=True, check_intf_up_ports=False) + + @pytest.fixture(scope="class") def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_hostname): dut = duthosts[enum_rand_one_per_hwsku_frontend_hostname] - interfaces = list(dut.show_and_parse("show interfaces status")) + + self.verify_ports_startup(dut) sfp_presence = dut.command(cmd_sfp_presence) parsed_presence = {line.split()[0]: line.split()[1] for line in sfp_presence["stdout_lines"][2:]} - available_interfaces = [ - intf["interface"] for intf in interfaces - if parsed_presence.get(intf["interface"]) == "Present" - ] + eeprom_infos = dut.command("sudo sfputil show eeprom -d")['stdout'] + eeprom_infos = parse_sfp_eeprom_infos(eeprom_infos) - pytest_assert(available_interfaces, "No interfaces with SFP detected. Cannot proceed with tests.") + available_optical_interfaces = [] + for port_name, eeprom_info in eeprom_infos.items(): + if parsed_presence.get(port_name) == "Present" and \ + "SFP EEPROM detected" in eeprom_info[port_name] \ + and "COPPER" not in eeprom_info.get("Media Interface Technology", "COPPER").upper() \ + and self.get_interface_status(dut, interface) == "up": + available_optical_interfaces.append(port_name) + + pytest_assert(available_optical_interfaces, "No interfaces with SFP detected. Cannot proceed with tests.") + logging.info("Available Optical interfaces for tests: {}".format(available_optical_interfaces)) # Select 5 random interfaces (or fewer if not enough available) - selected_interfaces = random.sample(available_interfaces, min(5, len(available_interfaces))) + selected_interfaces = random.sample(available_optical_interfaces, min(5, len(available_optical_interfaces))) + logging.info("Selected interfaces for tests: {}".format(selected_interfaces)) return dut, selected_interfaces @@ -77,19 +101,21 @@ def test_mac_local_fault_increment(self, select_random_interfaces): dut.shell("sudo sfputil debug rx-output {} disable".format(interface)) time.sleep(5) pytest_assert(self.get_interface_status(dut, interface) == "down", - "Interface {} did not go down after disabling rx-output using sfputil".format(interface)) + "Interface {iface} did not go down after 'sudo sfputil debug rx-output {iface} disable'" + .format(iface=interface)) dut.shell("sudo sfputil debug rx-output {} enable".format(interface)) time.sleep(20) pytest_assert(self.get_interface_status(dut, interface) == "up", - "Interface {} did not come up after enabling rx-output using sfputil".format(interface)) + "Interface {iface} did not come up after 'sudo sfputil debug rx-output {iface} enable'" + .format(iface=interface)) local_fault_after = self.get_mac_fault_count(dut, interface, "mac local fault") logging.info("MAC local fault count after disabling/enabling rx-output using sfputil {}: {}".format( interface, local_fault_after)) pytest_assert(local_fault_after > local_fault_before, - "MAC local fault count did not increment after disabling/enabling tx-output on the device") + "MAC local fault count did not increment after disabling/enabling rx-output on the device") def test_mac_remote_fault_increment(self, select_random_interfaces): dut, interfaces = select_random_interfaces @@ -104,17 +130,20 @@ def test_mac_remote_fault_increment(self, select_random_interfaces): dut.shell("sudo sfputil debug tx-output {} disable".format(interface)) time.sleep(5) pytest_assert(self.get_interface_status(dut, interface) == "down", - "Interface {} did not go down after disabling rx-output using sfputil".format(interface)) + "Interface {iface} did not go down after 'sudo sfputil debug tx-output {iface} disable'" + .format(iface=interface)) dut.shell("sudo sfputil debug tx-output {} enable".format(interface)) time.sleep(20) pytest_assert(self.get_interface_status(dut, interface) == "up", - "Interface {} did not come up after disabling tx-output using sfputil".format(interface)) + "Interface {iface} did not come up after 'sudo sfputil debug tx-output {iface} enable'" + .format(iface=interface)) remote_fault_after = self.get_mac_fault_count(dut, interface, "mac remote fault") - logging.info("MAC remote fault count after disabling/enabling rx-output using sfputil {}: {}".format( + logging.info("MAC remote fault count after disabling/enabling tx-output using sfputil {}: {}".format( interface, remote_fault_after)) pytest_assert(remote_fault_after > remote_fault_before, "MAC remote fault count did not increment after disabling/enabling tx-output on the device") + From 72572a2997310623591ae57ecc2ad2aa534fef44 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Wed, 11 Jun 2025 15:17:09 +0300 Subject: [PATCH 03/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index 6d0baa923a6..68cfacea00b 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -50,14 +50,13 @@ def verify_ports_startup(dut): dut.shell('show interface status | awk \'NR>2 {print $1}\' | xargs -I{} sudo config interface startup {}') time.sleep(30) - #TODO: Reboot the switch before test as a WA of #4384527, remove this after the issue is fixed + #TODO: Reboot the switch before test as a WA to handle that config reload doesn't reset errors/faults counters on unsplit ports, remove this after the issue is fixed @pytest.fixture(scope="class", autouse=True) def reboot_dut(self, duthosts, localhost, enum_rand_one_per_hwsku_frontend_hostname): from infra.tools.redmine.redmine_api import is_redmine_issue_active from tests.common.reboot import reboot - if is_redmine_issue_active([4384527])[0]: - reboot(duthosts[enum_rand_one_per_hwsku_frontend_hostname], - localhost, safe_reboot=True, check_intf_up_ports=False) + reboot(duthosts[enum_rand_one_per_hwsku_frontend_hostname], + localhost, safe_reboot=True, check_intf_up_ports=False) @pytest.fixture(scope="class") def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_hostname): From dd2246005441719e338a44cac399294dffdb0627 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Mon, 16 Jun 2025 09:32:38 +0300 Subject: [PATCH 04/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index 68cfacea00b..16afb852b35 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -45,25 +45,21 @@ def get_mac_fault_count(dut, interface, fault_type): def get_interface_status(dut, interface): return dut.show_and_parse("show interfaces status {}".format(interface))[0].get("oper", "unknown") - @staticmethod - def verify_ports_startup(dut): - dut.shell('show interface status | awk \'NR>2 {print $1}\' | xargs -I{} sudo config interface startup {}') - time.sleep(30) - #TODO: Reboot the switch before test as a WA to handle that config reload doesn't reset errors/faults counters on unsplit ports, remove this after the issue is fixed @pytest.fixture(scope="class", autouse=True) - def reboot_dut(self, duthosts, localhost, enum_rand_one_per_hwsku_frontend_hostname): - from infra.tools.redmine.redmine_api import is_redmine_issue_active + def reboot_dut(self, duthosts, localhost, enum_rand_one_per_hwsku_frontend_hostname, request): + from tests.common.plugins.loganalyzer_dynamic_errors_ignore.la_dynamic_errors_ignore import GitHubDynamicErrorsIgnore from tests.common.reboot import reboot - reboot(duthosts[enum_rand_one_per_hwsku_frontend_hostname], - localhost, safe_reboot=True, check_intf_up_ports=False) + github_checker = GitHubDynamicErrorsIgnore(conditions_dict={}, pytest_item_obj=request) + if github_checker.is_github_issue_active("https://github.com/sonic-net/sonic-buildimage/issues/22205"): + reboot(duthosts[enum_rand_one_per_hwsku_frontend_hostname], + localhost, safe_reboot=True, check_intf_up_ports=True) + @pytest.fixture(scope="class") def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_hostname): dut = duthosts[enum_rand_one_per_hwsku_frontend_hostname] - self.verify_ports_startup(dut) - sfp_presence = dut.command(cmd_sfp_presence) parsed_presence = {line.split()[0]: line.split()[1] for line in sfp_presence["stdout_lines"][2:]} @@ -74,8 +70,7 @@ def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_ho for port_name, eeprom_info in eeprom_infos.items(): if parsed_presence.get(port_name) == "Present" and \ "SFP EEPROM detected" in eeprom_info[port_name] \ - and "COPPER" not in eeprom_info.get("Media Interface Technology", "COPPER").upper() \ - and self.get_interface_status(dut, interface) == "up": + and "COPPER" not in eeprom_info.get("Media Interface Technology", "COPPER").upper(): available_optical_interfaces.append(port_name) pytest_assert(available_optical_interfaces, "No interfaces with SFP detected. Cannot proceed with tests.") @@ -145,4 +140,3 @@ def test_mac_remote_fault_increment(self, select_random_interfaces): pytest_assert(remote_fault_after > remote_fault_before, "MAC remote fault count did not increment after disabling/enabling tx-output on the device") - From e58fe899d332184c45e3fed9205309f3ef5c535a Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Mon, 16 Jun 2025 09:52:19 +0300 Subject: [PATCH 05/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index 16afb852b35..bda3cb47b2a 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -45,7 +45,6 @@ def get_mac_fault_count(dut, interface, fault_type): def get_interface_status(dut, interface): return dut.show_and_parse("show interfaces status {}".format(interface))[0].get("oper", "unknown") - @pytest.fixture(scope="class", autouse=True) def reboot_dut(self, duthosts, localhost, enum_rand_one_per_hwsku_frontend_hostname, request): from tests.common.plugins.loganalyzer_dynamic_errors_ignore.la_dynamic_errors_ignore import GitHubDynamicErrorsIgnore @@ -55,7 +54,6 @@ def reboot_dut(self, duthosts, localhost, enum_rand_one_per_hwsku_frontend_hostn reboot(duthosts[enum_rand_one_per_hwsku_frontend_hostname], localhost, safe_reboot=True, check_intf_up_ports=True) - @pytest.fixture(scope="class") def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_hostname): dut = duthosts[enum_rand_one_per_hwsku_frontend_hostname] From c263165bc263ab2b0c75be4ff4cb13fac8c78453 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Mon, 16 Jun 2025 10:00:21 +0300 Subject: [PATCH 06/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index bda3cb47b2a..39fe02b49b5 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -47,12 +47,14 @@ def get_interface_status(dut, interface): @pytest.fixture(scope="class", autouse=True) def reboot_dut(self, duthosts, localhost, enum_rand_one_per_hwsku_frontend_hostname, request): - from tests.common.plugins.loganalyzer_dynamic_errors_ignore.la_dynamic_errors_ignore import GitHubDynamicErrorsIgnore + from tests.common.plugins.loganalyzer_dynamic_errors_ignore.la_dynamic_errors_ignore import ( + GitHubDynamicErrorsIgnore + ) from tests.common.reboot import reboot github_checker = GitHubDynamicErrorsIgnore(conditions_dict={}, pytest_item_obj=request) if github_checker.is_github_issue_active("https://github.com/sonic-net/sonic-buildimage/issues/22205"): reboot(duthosts[enum_rand_one_per_hwsku_frontend_hostname], - localhost, safe_reboot=True, check_intf_up_ports=True) + localhost, safe_reboot=True, check_intf_up_ports=True) @pytest.fixture(scope="class") def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_hostname): From 50fa7e4175bbdf8ec740a5431ea3db9eb7aac643 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Mon, 16 Jun 2025 10:01:27 +0300 Subject: [PATCH 07/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index 39fe02b49b5..a58823d8b29 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -47,9 +47,9 @@ def get_interface_status(dut, interface): @pytest.fixture(scope="class", autouse=True) def reboot_dut(self, duthosts, localhost, enum_rand_one_per_hwsku_frontend_hostname, request): - from tests.common.plugins.loganalyzer_dynamic_errors_ignore.la_dynamic_errors_ignore import ( - GitHubDynamicErrorsIgnore - ) + from tests.common.plugins.loganalyzer_dynamic_errors_ignore.la_dynamic_errors_ignore import ( + GitHubDynamicErrorsIgnore + ) from tests.common.reboot import reboot github_checker = GitHubDynamicErrorsIgnore(conditions_dict={}, pytest_item_obj=request) if github_checker.is_github_issue_active("https://github.com/sonic-net/sonic-buildimage/issues/22205"): From e6e28ecd27436898b0f227661cd854351ea43637 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Tue, 17 Jun 2025 16:03:57 +0300 Subject: [PATCH 08/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index a58823d8b29..459e2861dff 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -45,16 +45,12 @@ def get_mac_fault_count(dut, interface, fault_type): def get_interface_status(dut, interface): return dut.show_and_parse("show interfaces status {}".format(interface))[0].get("oper", "unknown") + #TODO: Reboot the switch before test as a WA of #22205, remove this after the issue is fixed @pytest.fixture(scope="class", autouse=True) def reboot_dut(self, duthosts, localhost, enum_rand_one_per_hwsku_frontend_hostname, request): - from tests.common.plugins.loganalyzer_dynamic_errors_ignore.la_dynamic_errors_ignore import ( - GitHubDynamicErrorsIgnore - ) from tests.common.reboot import reboot - github_checker = GitHubDynamicErrorsIgnore(conditions_dict={}, pytest_item_obj=request) - if github_checker.is_github_issue_active("https://github.com/sonic-net/sonic-buildimage/issues/22205"): - reboot(duthosts[enum_rand_one_per_hwsku_frontend_hostname], - localhost, safe_reboot=True, check_intf_up_ports=True) + reboot(duthosts[enum_rand_one_per_hwsku_frontend_hostname], + localhost, safe_reboot=True, check_intf_up_ports=True) @pytest.fixture(scope="class") def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_hostname): From b40aa2c5a530c62c95fea1df6a1695268025d222 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Tue, 17 Jun 2025 16:09:01 +0300 Subject: [PATCH 09/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index 459e2861dff..811f6aec1da 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -45,13 +45,13 @@ def get_mac_fault_count(dut, interface, fault_type): def get_interface_status(dut, interface): return dut.show_and_parse("show interfaces status {}".format(interface))[0].get("oper", "unknown") - #TODO: Reboot the switch before test as a WA of #22205, remove this after the issue is fixed + # TODO: Reboot the switch before test as a WA of #22205, remove this after the issue is fixed @pytest.fixture(scope="class", autouse=True) def reboot_dut(self, duthosts, localhost, enum_rand_one_per_hwsku_frontend_hostname, request): from tests.common.reboot import reboot reboot(duthosts[enum_rand_one_per_hwsku_frontend_hostname], - localhost, safe_reboot=True, check_intf_up_ports=True) - + localhost, safe_reboot=True, check_intf_up_ports=True) + @pytest.fixture(scope="class") def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_hostname): dut = duthosts[enum_rand_one_per_hwsku_frontend_hostname] From 51b1052498a2175fe9dee2e1cd2fdadefc3bed1c Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Wed, 18 Jun 2025 09:47:42 +0300 Subject: [PATCH 10/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index 811f6aec1da..cd23690858b 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -51,7 +51,7 @@ def reboot_dut(self, duthosts, localhost, enum_rand_one_per_hwsku_frontend_hostn from tests.common.reboot import reboot reboot(duthosts[enum_rand_one_per_hwsku_frontend_hostname], localhost, safe_reboot=True, check_intf_up_ports=True) - + @pytest.fixture(scope="class") def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_hostname): dut = duthosts[enum_rand_one_per_hwsku_frontend_hostname] From 81d7e2aa1466d89d08440d818695064a908bfc9f Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Wed, 2 Jul 2025 14:50:22 +0300 Subject: [PATCH 11/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index cd23690858b..348f15e097b 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -27,6 +27,23 @@ def is_supported_platform(self, duthost, tbinfo): else: pytest.skip("DUT has platform {}, test is not supported".format(duthost.facts['platform'])) + if "nvidia" in duthost.facts["platform"].lower() and not self.is_independent_module_enabled(duthost): + pytest.skip("Skipping test: Independent module feature is not enabled on the DUT") + + def is_independent_module_enabled(self, duthost): + """ + Fixture to check if the independent module feature is enabled on the DUT. + Returns True if SAI_INDEPENDENT_MODULE_MODE=1 is set in sai.profile, else False. + """ + # You may need to adjust these paths based on your platform + platform = duthost.facts["platform"] + hwsku = duthost.facts["hwsku"] + sai_profile_path = f"/usr/share/sonic/device/{platform}/{hwsku}/sai.profile" + + cmd = f"grep '^SAI_INDEPENDENT_MODULE_MODE=1' {sai_profile_path}" + result = duthost.shell(cmd, module_ignore_errors=True) + return result["rc"] == 0 + @staticmethod def get_mac_fault_count(dut, interface, fault_type): output = dut.show_and_parse("show int errors {}".format(interface)) @@ -45,13 +62,15 @@ def get_mac_fault_count(dut, interface, fault_type): def get_interface_status(dut, interface): return dut.show_and_parse("show interfaces status {}".format(interface))[0].get("oper", "unknown") - # TODO: Reboot the switch before test as a WA of #22205, remove this after the issue is fixed + + #TODO: Reboot the switch before test as a WA of #22205, remove this after the issue is fixed @pytest.fixture(scope="class", autouse=True) - def reboot_dut(self, duthosts, localhost, enum_rand_one_per_hwsku_frontend_hostname, request): + def reboot_dut(self, duthosts, localhost, enum_rand_one_per_hwsku_frontend_hostname): from tests.common.reboot import reboot reboot(duthosts[enum_rand_one_per_hwsku_frontend_hostname], localhost, safe_reboot=True, check_intf_up_ports=True) + @pytest.fixture(scope="class") def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_hostname): dut = duthosts[enum_rand_one_per_hwsku_frontend_hostname] @@ -64,9 +83,14 @@ def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_ho available_optical_interfaces = [] for port_name, eeprom_info in eeprom_infos.items(): + try: + is_cmis_supported = float(eeprom_info.get("CMIS Rev", "0")) >= 5.0 + except ValueError: + is_cmis_supported = False if parsed_presence.get(port_name) == "Present" and \ "SFP EEPROM detected" in eeprom_info[port_name] \ - and "COPPER" not in eeprom_info.get("Media Interface Technology", "COPPER").upper(): + and "COPPER" not in eeprom_info.get("Media Interface Technology", "COPPER").upper() \ + and is_cmis_supported: available_optical_interfaces.append(port_name) pytest_assert(available_optical_interfaces, "No interfaces with SFP detected. Cannot proceed with tests.") From a5fa257d21088c687d15b2a5c815430f5a41c873 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Wed, 2 Jul 2025 14:50:42 +0300 Subject: [PATCH 12/55] Update code-review-guidlines.md --- docs/code-review-guidlines.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/code-review-guidlines.md b/docs/code-review-guidlines.md index 5317a39b4dc..55baf65c6d3 100644 --- a/docs/code-review-guidlines.md +++ b/docs/code-review-guidlines.md @@ -1,4 +1,4 @@ -# SONiC-MGMT code review guidelines- guy shemesh +# SONiC-MGMT code review guidelines ## Style guide - Avoid usage of hardcoded values, define constants instead. From 7bf6710ae188d27cca4c0e677936f04bcd31cc35 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Wed, 2 Jul 2025 14:56:37 +0300 Subject: [PATCH 13/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index 348f15e097b..eceb1da3c0b 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -62,7 +62,6 @@ def get_mac_fault_count(dut, interface, fault_type): def get_interface_status(dut, interface): return dut.show_and_parse("show interfaces status {}".format(interface))[0].get("oper", "unknown") - #TODO: Reboot the switch before test as a WA of #22205, remove this after the issue is fixed @pytest.fixture(scope="class", autouse=True) def reboot_dut(self, duthosts, localhost, enum_rand_one_per_hwsku_frontend_hostname): @@ -70,7 +69,6 @@ def reboot_dut(self, duthosts, localhost, enum_rand_one_per_hwsku_frontend_hostn reboot(duthosts[enum_rand_one_per_hwsku_frontend_hostname], localhost, safe_reboot=True, check_intf_up_ports=True) - @pytest.fixture(scope="class") def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_hostname): dut = duthosts[enum_rand_one_per_hwsku_frontend_hostname] From 5d4a01f106b7fe26d3e43d63f76c0956987a523b Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Wed, 2 Jul 2025 15:08:05 +0300 Subject: [PATCH 14/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index eceb1da3c0b..f8cb3424a55 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -62,7 +62,7 @@ def get_mac_fault_count(dut, interface, fault_type): def get_interface_status(dut, interface): return dut.show_and_parse("show interfaces status {}".format(interface))[0].get("oper", "unknown") - #TODO: Reboot the switch before test as a WA of #22205, remove this after the issue is fixed + # TODO: Reboot the switch before test as a WA of #22205, remove this after the issue is fixed @pytest.fixture(scope="class", autouse=True) def reboot_dut(self, duthosts, localhost, enum_rand_one_per_hwsku_frontend_hostname): from tests.common.reboot import reboot From 8cfa578fe7a6eca4a13ee34e9ff88095612f9a1f Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Wed, 2 Jul 2025 15:09:31 +0300 Subject: [PATCH 15/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index f8cb3424a55..927787731a3 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -82,7 +82,7 @@ def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_ho available_optical_interfaces = [] for port_name, eeprom_info in eeprom_infos.items(): try: - is_cmis_supported = float(eeprom_info.get("CMIS Rev", "0")) >= 5.0 + is_cmis_supported = float(eeprom_info.get("CMIS Revision", "0")) >= 5.0 except ValueError: is_cmis_supported = False if parsed_presence.get(port_name) == "Present" and \ From 1a672185428c9c870031156314d40d3acf7fddac Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Wed, 2 Jul 2025 15:27:10 +0300 Subject: [PATCH 16/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index 927787731a3..ca9ecec9fa7 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -32,10 +32,9 @@ def is_supported_platform(self, duthost, tbinfo): def is_independent_module_enabled(self, duthost): """ - Fixture to check if the independent module feature is enabled on the DUT. + Fixture to check if the independent module feature is enabled on the Nvidia DUT. Returns True if SAI_INDEPENDENT_MODULE_MODE=1 is set in sai.profile, else False. """ - # You may need to adjust these paths based on your platform platform = duthost.facts["platform"] hwsku = duthost.facts["hwsku"] sai_profile_path = f"/usr/share/sonic/device/{platform}/{hwsku}/sai.profile" From 4e115ca91b75e28edcd9535c15f87a5c5af9ab5e Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Wed, 2 Jul 2025 15:35:04 +0300 Subject: [PATCH 17/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index ca9ecec9fa7..0c482ab47d8 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -32,7 +32,7 @@ def is_supported_platform(self, duthost, tbinfo): def is_independent_module_enabled(self, duthost): """ - Fixture to check if the independent module feature is enabled on the Nvidia DUT. + Check if the independent module feature is enabled on the Nvidia DUT. Returns True if SAI_INDEPENDENT_MODULE_MODE=1 is set in sai.profile, else False. """ platform = duthost.facts["platform"] From 32663a46311e0792fc6813c6ab45848125462cb7 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Wed, 2 Jul 2025 15:48:16 +0300 Subject: [PATCH 18/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index 0c482ab47d8..2d1f2d7a7d6 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -84,6 +84,11 @@ def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_ho is_cmis_supported = float(eeprom_info.get("CMIS Revision", "0")) >= 5.0 except ValueError: is_cmis_supported = False + + if not is_cmis_supported: + logger.info(f"Port {port} skipped: CMIS not supported on this port.") + continue + if parsed_presence.get(port_name) == "Present" and \ "SFP EEPROM detected" in eeprom_info[port_name] \ and "COPPER" not in eeprom_info.get("Media Interface Technology", "COPPER").upper() \ From 5710fca755d030af62df5f0b58968966f0392507 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Wed, 2 Jul 2025 15:58:05 +0300 Subject: [PATCH 19/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index 2d1f2d7a7d6..8880ac85239 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -86,7 +86,7 @@ def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_ho is_cmis_supported = False if not is_cmis_supported: - logger.info(f"Port {port} skipped: CMIS not supported on this port.") + logging.info(f"Port {port_name} skipped: CMIS not supported on this port.") continue if parsed_presence.get(port_name) == "Present" and \ From 4916a6851b429befe78ed1862b4c443c22672cfb Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Wed, 2 Jul 2025 17:09:04 +0300 Subject: [PATCH 20/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index 8880ac85239..db42d6077b1 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -75,7 +75,7 @@ def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_ho sfp_presence = dut.command(cmd_sfp_presence) parsed_presence = {line.split()[0]: line.split()[1] for line in sfp_presence["stdout_lines"][2:]} - eeprom_infos = dut.command("sudo sfputil show eeprom -d")['stdout'] + eeprom_infos = dut.shell("sudo sfputil show eeprom -d")['stdout'] eeprom_infos = parse_sfp_eeprom_infos(eeprom_infos) available_optical_interfaces = [] From 9c21be4a1512dec4e5727bc8b4fe1411e47e5141 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Wed, 2 Jul 2025 17:38:49 +0300 Subject: [PATCH 21/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index db42d6077b1..cebf2fac162 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -6,6 +6,7 @@ from tests.common.helpers.assertions import pytest_assert from tests.common.utilities import skip_release from tests.common.platform.transceiver_utils import parse_sfp_eeprom_infos +from tests.platform_tests.sfp.software_control.conftest import check_platform_support pytestmark = [ pytest.mark.disable_loganalyzer, # disable automatic loganalyzer @@ -18,7 +19,7 @@ class TestMACFault(object): @pytest.fixture(autouse=True) - def is_supported_platform(self, duthost, tbinfo): + def is_supported_platform(self, duthost, tbinfo, check_platform_support): if 'ptp' not in tbinfo['topo']['name']: pytest.skip("Skipping test: Not applicable for non-PTP topology") @@ -27,22 +28,6 @@ def is_supported_platform(self, duthost, tbinfo): else: pytest.skip("DUT has platform {}, test is not supported".format(duthost.facts['platform'])) - if "nvidia" in duthost.facts["platform"].lower() and not self.is_independent_module_enabled(duthost): - pytest.skip("Skipping test: Independent module feature is not enabled on the DUT") - - def is_independent_module_enabled(self, duthost): - """ - Check if the independent module feature is enabled on the Nvidia DUT. - Returns True if SAI_INDEPENDENT_MODULE_MODE=1 is set in sai.profile, else False. - """ - platform = duthost.facts["platform"] - hwsku = duthost.facts["hwsku"] - sai_profile_path = f"/usr/share/sonic/device/{platform}/{hwsku}/sai.profile" - - cmd = f"grep '^SAI_INDEPENDENT_MODULE_MODE=1' {sai_profile_path}" - result = duthost.shell(cmd, module_ignore_errors=True) - return result["rc"] == 0 - @staticmethod def get_mac_fault_count(dut, interface, fault_type): output = dut.show_and_parse("show int errors {}".format(interface)) From 8a7f377f49558c9186f108746b53d75545fdd0cf Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Wed, 2 Jul 2025 18:04:58 +0300 Subject: [PATCH 22/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index cebf2fac162..3a7a6a77f78 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -6,7 +6,7 @@ from tests.common.helpers.assertions import pytest_assert from tests.common.utilities import skip_release from tests.common.platform.transceiver_utils import parse_sfp_eeprom_infos -from tests.platform_tests.sfp.software_control.conftest import check_platform_support +from tests.platform_tests.sfp.software_control.helpers import check_sc_sai_attribute_value pytestmark = [ pytest.mark.disable_loganalyzer, # disable automatic loganalyzer @@ -19,7 +19,7 @@ class TestMACFault(object): @pytest.fixture(autouse=True) - def is_supported_platform(self, duthost, tbinfo, check_platform_support): + def is_supported_platform(self, duthost, tbinfo): if 'ptp' not in tbinfo['topo']['name']: pytest.skip("Skipping test: Not applicable for non-PTP topology") @@ -28,6 +28,9 @@ def is_supported_platform(self, duthost, tbinfo, check_platform_support): else: pytest.skip("DUT has platform {}, test is not supported".format(duthost.facts['platform'])) + if not check_sc_sai_attribute_value(duthost): + pytest.skip("SW control feature is not enabled") + @staticmethod def get_mac_fault_count(dut, interface, fault_type): output = dut.show_and_parse("show int errors {}".format(interface)) From 2a9fd16a72636f16a596b012a1653cd69fe53a34 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Thu, 3 Jul 2025 21:15:05 +0300 Subject: [PATCH 23/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index 3a7a6a77f78..3e1583afda8 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -68,19 +68,17 @@ def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_ho available_optical_interfaces = [] for port_name, eeprom_info in eeprom_infos.items(): - try: - is_cmis_supported = float(eeprom_info.get("CMIS Revision", "0")) >= 5.0 - except ValueError: - is_cmis_supported = False - - if not is_cmis_supported: - logging.info(f"Port {port_name} skipped: CMIS not supported on this port.") - continue - if parsed_presence.get(port_name) == "Present" and \ "SFP EEPROM detected" in eeprom_info[port_name] \ - and "COPPER" not in eeprom_info.get("Media Interface Technology", "COPPER").upper() \ - and is_cmis_supported: + and "COPPER" not in eeprom_info.get("Media Interface Technology", "COPPER").upper(): + try: + is_cmis_supported = float(eeprom_info.get("CMIS Revision", "0")) >= 5.0 + except ValueError: + is_cmis_supported = False + + if not is_cmis_supported: + logging.info(f"Port {port_name} skipped: CMIS not supported on this port.") + continue available_optical_interfaces.append(port_name) pytest_assert(available_optical_interfaces, "No interfaces with SFP detected. Cannot proceed with tests.") From 9cf53ff0889dd055692e900cec51f7afb212f3bb Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Thu, 17 Jul 2025 15:24:54 +0300 Subject: [PATCH 24/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index 3e1583afda8..c0f7b7af758 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -7,6 +7,7 @@ from tests.common.utilities import skip_release from tests.common.platform.transceiver_utils import parse_sfp_eeprom_infos from tests.platform_tests.sfp.software_control.helpers import check_sc_sai_attribute_value +from tests.common.utilities import wait_until pytestmark = [ pytest.mark.disable_loganalyzer, # disable automatic loganalyzer @@ -90,10 +91,21 @@ def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_ho return dut, selected_interfaces + def shutdown_and_startup_interfaces(self, dut, interface): + dut.command("sudo config interface shutdown {}".format(interface)) + pytest_assert(wait_until(30, 2, 0, lambda: self.get_interface_status(dut, interface) == "down"), + "Interface {} did not go down after shutdown".format(interface)) + + dut.command("sudo config interface startup {}".format(interface)) + pytest_assert(wait_until(30, 2, 0, lambda: self.get_interface_status(dut, interface) == "up"), + "Interface {} did not come up after startup".format(interface)) + def test_mac_local_fault_increment(self, select_random_interfaces): dut, interfaces = select_random_interfaces for interface in interfaces: + self.shutdown_and_startup_interfaces(dut, interface) + pytest_assert(self.get_interface_status(dut, interface) == "up", "Interface {} was not up before disabling/enabling rx-output using sfputil".format(interface)) @@ -123,6 +135,8 @@ def test_mac_remote_fault_increment(self, select_random_interfaces): dut, interfaces = select_random_interfaces for interface in interfaces: + self.shutdown_and_startup_interfaces(dut, interface) + pytest_assert(self.get_interface_status(dut, interface) == "up", "Interface {} was not up before disabling/enabling tx-output using sfputil".format(interface)) From 75d5d4a79dedbf74c044a4651c8313a9c6ef892e Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Thu, 24 Jul 2025 10:51:03 +0300 Subject: [PATCH 25/55] Update test_port_error.py remove Nvidia platform checks --- tests/layer1/test_port_error.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index c0f7b7af758..a7fdf84d224 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -6,7 +6,6 @@ from tests.common.helpers.assertions import pytest_assert from tests.common.utilities import skip_release from tests.common.platform.transceiver_utils import parse_sfp_eeprom_infos -from tests.platform_tests.sfp.software_control.helpers import check_sc_sai_attribute_value from tests.common.utilities import wait_until pytestmark = [ @@ -29,8 +28,6 @@ def is_supported_platform(self, duthost, tbinfo): else: pytest.skip("DUT has platform {}, test is not supported".format(duthost.facts['platform'])) - if not check_sc_sai_attribute_value(duthost): - pytest.skip("SW control feature is not enabled") @staticmethod def get_mac_fault_count(dut, interface, fault_type): @@ -50,7 +47,6 @@ def get_mac_fault_count(dut, interface, fault_type): def get_interface_status(dut, interface): return dut.show_and_parse("show interfaces status {}".format(interface))[0].get("oper", "unknown") - # TODO: Reboot the switch before test as a WA of #22205, remove this after the issue is fixed @pytest.fixture(scope="class", autouse=True) def reboot_dut(self, duthosts, localhost, enum_rand_one_per_hwsku_frontend_hostname): from tests.common.reboot import reboot From 45087e2e736014985a5057875a4477cae3b1094d Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Sun, 27 Jul 2025 10:31:35 +0300 Subject: [PATCH 26/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index a7fdf84d224..9d37be6b1a4 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -6,6 +6,7 @@ from tests.common.helpers.assertions import pytest_assert from tests.common.utilities import skip_release from tests.common.platform.transceiver_utils import parse_sfp_eeprom_infos +from tests.platform_tests.sfp.software_control.helpers import check_sc_sai_attribute_value from tests.common.utilities import wait_until pytestmark = [ @@ -28,6 +29,9 @@ def is_supported_platform(self, duthost, tbinfo): else: pytest.skip("DUT has platform {}, test is not supported".format(duthost.facts['platform'])) + if 'nvidia' in duthost.facts['platform'].lower() and not check_sc_sai_attribute_value(duthost): + pytest.skip("SW control feature is not enabled on platform") + @staticmethod def get_mac_fault_count(dut, interface, fault_type): From 29079a75fbff804f8a8592e20267bc2469cd6a6d Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Sun, 3 Aug 2025 11:09:23 +0300 Subject: [PATCH 27/55] Update transceiver_utils.py --- tests/common/platform/transceiver_utils.py | 41 ++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tests/common/platform/transceiver_utils.py b/tests/common/platform/transceiver_utils.py index 3a1cd4f1e26..6ec7b4cff28 100644 --- a/tests/common/platform/transceiver_utils.py +++ b/tests/common/platform/transceiver_utils.py @@ -478,3 +478,44 @@ def is_sw_control_enabled(duthost, port_index): sw_control_enabled = True logging.info(f'The sw control enable of port index {port_index} is {sw_control_enabled}') return sw_control_enabled + + +def is_cmis_version_supported(cmis_version, min_required_version=5.0): + """ + Check if a CMIS version supports a specific feature by comparing it to a minimum required version + @param: cmis_version: CMIS version string (e.g., "5.0", "4.0", etc.) + @param: min_required_version: Minimum required CMIS version (default: 5.0) + @return: bool: True if CMIS version is supported, False otherwise + """ + try: + cmis_version_float = float(cmis_version) + return cmis_version_float >= min_required_version + except (ValueError, TypeError): + return False + + +def get_available_optical_interfaces(eeprom_infos, parsed_presence, min_cmis_version=5.0): + """ + Filter available optical interfaces based on presence, EEPROM detection, media type, and CMIS version support + @param: eeprom_infos: Dictionary containing EEPROM information for each port + @param: parsed_presence: Dictionary containing presence status for each port + @param: min_cmis_version: Minimum required CMIS version (default: 5.0) + @return: list: List of available optical interface names that meet all criteria + """ + available_optical_interfaces = [] + + for port_name, eeprom_info in eeprom_infos.items(): + if parsed_presence.get(port_name) != "Present": + continue + if "SFP EEPROM detected" not in eeprom_info[port_name]: + continue + media_technology = eeprom_info.get("Media Interface Technology", "COPPER").upper() + if "COPPER" in media_technology: + continue + cmis_version = eeprom_info.get("CMIS Revision", "0") + if not is_cmis_version_supported(cmis_version, min_cmis_version): + logging.info(f"Port {port_name} skipped: CMIS not supported on this port.") + continue + available_optical_interfaces.append(port_name) + + return available_optical_interfaces From be36623d042e275b6bcd3424608a7453788e4e80 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Sun, 3 Aug 2025 11:14:59 +0300 Subject: [PATCH 28/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index 9d37be6b1a4..adcce7b95a7 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -5,7 +5,7 @@ from tests.common.helpers.assertions import pytest_assert from tests.common.utilities import skip_release -from tests.common.platform.transceiver_utils import parse_sfp_eeprom_infos +from tests.common.platform.transceiver_utils import parse_sfp_eeprom_infos, get_available_optical_interfaces from tests.platform_tests.sfp.software_control.helpers import check_sc_sai_attribute_value from tests.common.utilities import wait_until @@ -58,7 +58,7 @@ def reboot_dut(self, duthosts, localhost, enum_rand_one_per_hwsku_frontend_hostn localhost, safe_reboot=True, check_intf_up_ports=True) @pytest.fixture(scope="class") - def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_hostname): + def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_hostname, collected_ports_num): dut = duthosts[enum_rand_one_per_hwsku_frontend_hostname] sfp_presence = dut.command(cmd_sfp_presence) @@ -67,26 +67,13 @@ def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_ho eeprom_infos = dut.shell("sudo sfputil show eeprom -d")['stdout'] eeprom_infos = parse_sfp_eeprom_infos(eeprom_infos) - available_optical_interfaces = [] - for port_name, eeprom_info in eeprom_infos.items(): - if parsed_presence.get(port_name) == "Present" and \ - "SFP EEPROM detected" in eeprom_info[port_name] \ - and "COPPER" not in eeprom_info.get("Media Interface Technology", "COPPER").upper(): - try: - is_cmis_supported = float(eeprom_info.get("CMIS Revision", "0")) >= 5.0 - except ValueError: - is_cmis_supported = False - - if not is_cmis_supported: - logging.info(f"Port {port_name} skipped: CMIS not supported on this port.") - continue - available_optical_interfaces.append(port_name) + available_optical_interfaces = get_available_optical_interfaces(eeprom_infos, parsed_presence) pytest_assert(available_optical_interfaces, "No interfaces with SFP detected. Cannot proceed with tests.") logging.info("Available Optical interfaces for tests: {}".format(available_optical_interfaces)) # Select 5 random interfaces (or fewer if not enough available) - selected_interfaces = random.sample(available_optical_interfaces, min(5, len(available_optical_interfaces))) + selected_interfaces = random.sample(available_optical_interfaces, min(collected_ports_num, len(available_optical_interfaces))) logging.info("Selected interfaces for tests: {}".format(selected_interfaces)) return dut, selected_interfaces @@ -100,8 +87,8 @@ def shutdown_and_startup_interfaces(self, dut, interface): pytest_assert(wait_until(30, 2, 0, lambda: self.get_interface_status(dut, interface) == "up"), "Interface {} did not come up after startup".format(interface)) - def test_mac_local_fault_increment(self, select_random_interfaces): - dut, interfaces = select_random_interfaces + def test_mac_local_fault_increment(self, select_random_interfaces, collected_ports_num=5): + dut, interfaces = select_random_interfaces(collected_ports_num=collected_ports_num) for interface in interfaces: self.shutdown_and_startup_interfaces(dut, interface) @@ -131,8 +118,8 @@ def test_mac_local_fault_increment(self, select_random_interfaces): pytest_assert(local_fault_after > local_fault_before, "MAC local fault count did not increment after disabling/enabling rx-output on the device") - def test_mac_remote_fault_increment(self, select_random_interfaces): - dut, interfaces = select_random_interfaces + def test_mac_remote_fault_increment(self, select_random_interfaces, collected_ports_num=5): + dut, interfaces = select_random_interfaces(collected_ports_num=collected_ports_num) for interface in interfaces: self.shutdown_and_startup_interfaces(dut, interface) From bfc1e7e43040eb6cf21f821e99f911a5103bfecb Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Sun, 3 Aug 2025 11:20:24 +0300 Subject: [PATCH 29/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index adcce7b95a7..c4744851793 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -16,7 +16,26 @@ SUPPORTED_PLATFORMS = ["arista_7060x6", "nvidia_sn5640", "nvidia_sn5600"] cmd_sfp_presence = "sudo sfpshow presence" - +DEFAULT_COLLECTED_PORTS_NUM = 5 + +def pytest_addoption(parser): + """ + Add command line options for pytest + """ + parser.addoption( + "--collected-ports-num", + action="store", + default=DEFAULT_COLLECTED_PORTS_NUM, + type=int, + help="Number of ports to collect for testing (default: {})".format(DEFAULT_COLLECTED_PORTS_NUM) + ) + +@pytest.fixture(scope="session") +def collected_ports_num(request): + """ + Fixture to get the number of ports to collect from command line argument + """ + return request.config.getoption("--collected-ports-num") class TestMACFault(object): @pytest.fixture(autouse=True) @@ -87,8 +106,8 @@ def shutdown_and_startup_interfaces(self, dut, interface): pytest_assert(wait_until(30, 2, 0, lambda: self.get_interface_status(dut, interface) == "up"), "Interface {} did not come up after startup".format(interface)) - def test_mac_local_fault_increment(self, select_random_interfaces, collected_ports_num=5): - dut, interfaces = select_random_interfaces(collected_ports_num=collected_ports_num) + def test_mac_local_fault_increment(self, select_random_interfaces): + dut, interfaces = select_random_interfaces for interface in interfaces: self.shutdown_and_startup_interfaces(dut, interface) @@ -118,8 +137,8 @@ def test_mac_local_fault_increment(self, select_random_interfaces, collected_por pytest_assert(local_fault_after > local_fault_before, "MAC local fault count did not increment after disabling/enabling rx-output on the device") - def test_mac_remote_fault_increment(self, select_random_interfaces, collected_ports_num=5): - dut, interfaces = select_random_interfaces(collected_ports_num=collected_ports_num) + def test_mac_remote_fault_increment(self, select_random_interfaces): + dut, interfaces = select_random_interfaces for interface in interfaces: self.shutdown_and_startup_interfaces(dut, interface) From 282f51ab4e8f2ca7e52654cdac5d89a1b5940f24 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Sun, 3 Aug 2025 14:53:55 +0300 Subject: [PATCH 30/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index c4744851793..7ec0abbdd07 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -35,7 +35,7 @@ def collected_ports_num(request): """ Fixture to get the number of ports to collect from command line argument """ - return request.config.getoption("--collected-ports-num") + return request.config.getoption("collected_ports_num", default=DEFAULT_COLLECTED_PORTS_NUM) class TestMACFault(object): @pytest.fixture(autouse=True) From f4d44f2854e9ecdc5838ffd92ecb2669741c656d Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Sun, 3 Aug 2025 15:16:40 +0300 Subject: [PATCH 31/55] Update transceiver_utils.py --- tests/common/platform/transceiver_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/common/platform/transceiver_utils.py b/tests/common/platform/transceiver_utils.py index 6ec7b4cff28..a96b5c22c3f 100644 --- a/tests/common/platform/transceiver_utils.py +++ b/tests/common/platform/transceiver_utils.py @@ -494,7 +494,7 @@ def is_cmis_version_supported(cmis_version, min_required_version=5.0): return False -def get_available_optical_interfaces(eeprom_infos, parsed_presence, min_cmis_version=5.0): +def get_supported_available_optical_interfaces(eeprom_infos, parsed_presence, min_cmis_version=5.0): """ Filter available optical interfaces based on presence, EEPROM detection, media type, and CMIS version support @param: eeprom_infos: Dictionary containing EEPROM information for each port From 3e9ec46e091c34b176a38e96462e2e2951324ef3 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Sun, 3 Aug 2025 15:17:01 +0300 Subject: [PATCH 32/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index 7ec0abbdd07..a78447de1a3 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -86,7 +86,7 @@ def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_ho eeprom_infos = dut.shell("sudo sfputil show eeprom -d")['stdout'] eeprom_infos = parse_sfp_eeprom_infos(eeprom_infos) - available_optical_interfaces = get_available_optical_interfaces(eeprom_infos, parsed_presence) + available_optical_interfaces = get_supported_available_optical_interfaces(eeprom_infos, parsed_presence) pytest_assert(available_optical_interfaces, "No interfaces with SFP detected. Cannot proceed with tests.") logging.info("Available Optical interfaces for tests: {}".format(available_optical_interfaces)) From f108723afc872d712e87e767f9e5c37fa4f1c6e2 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Mon, 4 Aug 2025 13:45:55 +0300 Subject: [PATCH 33/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index a78447de1a3..12018c27b7a 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -5,7 +5,7 @@ from tests.common.helpers.assertions import pytest_assert from tests.common.utilities import skip_release -from tests.common.platform.transceiver_utils import parse_sfp_eeprom_infos, get_available_optical_interfaces +from tests.common.platform.transceiver_utils import parse_sfp_eeprom_infos, get_supported_available_optical_interfaces from tests.platform_tests.sfp.software_control.helpers import check_sc_sai_attribute_value from tests.common.utilities import wait_until @@ -18,6 +18,7 @@ cmd_sfp_presence = "sudo sfpshow presence" DEFAULT_COLLECTED_PORTS_NUM = 5 + def pytest_addoption(parser): """ Add command line options for pytest @@ -30,6 +31,7 @@ def pytest_addoption(parser): help="Number of ports to collect for testing (default: {})".format(DEFAULT_COLLECTED_PORTS_NUM) ) + @pytest.fixture(scope="session") def collected_ports_num(request): """ @@ -37,6 +39,7 @@ def collected_ports_num(request): """ return request.config.getoption("collected_ports_num", default=DEFAULT_COLLECTED_PORTS_NUM) + class TestMACFault(object): @pytest.fixture(autouse=True) def is_supported_platform(self, duthost, tbinfo): @@ -51,7 +54,6 @@ def is_supported_platform(self, duthost, tbinfo): if 'nvidia' in duthost.facts['platform'].lower() and not check_sc_sai_attribute_value(duthost): pytest.skip("SW control feature is not enabled on platform") - @staticmethod def get_mac_fault_count(dut, interface, fault_type): output = dut.show_and_parse("show int errors {}".format(interface)) @@ -92,7 +94,8 @@ def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_ho logging.info("Available Optical interfaces for tests: {}".format(available_optical_interfaces)) # Select 5 random interfaces (or fewer if not enough available) - selected_interfaces = random.sample(available_optical_interfaces, min(collected_ports_num, len(available_optical_interfaces))) + selected_interfaces = random.sample(available_optical_interfaces, + min(collected_ports_num, len(available_optical_interfaces))) logging.info("Selected interfaces for tests: {}".format(selected_interfaces)) return dut, selected_interfaces From 3969754b32f8c59e98b1f8ebfe886d69725054c3 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Mon, 4 Aug 2025 18:09:35 +0300 Subject: [PATCH 34/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index 12018c27b7a..8627c180d07 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -103,11 +103,11 @@ def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_ho def shutdown_and_startup_interfaces(self, dut, interface): dut.command("sudo config interface shutdown {}".format(interface)) pytest_assert(wait_until(30, 2, 0, lambda: self.get_interface_status(dut, interface) == "down"), - "Interface {} did not go down after shutdown".format(interface)) - + "Interface {} did not go down after shutdown".format(interface)) + dut.command("sudo config interface startup {}".format(interface)) pytest_assert(wait_until(30, 2, 0, lambda: self.get_interface_status(dut, interface) == "up"), - "Interface {} did not come up after startup".format(interface)) + "Interface {} did not come up after startup".format(interface)) def test_mac_local_fault_increment(self, select_random_interfaces): dut, interfaces = select_random_interfaces From 4bd09691b41faf306dd27dfdb74f76a083441182 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Mon, 25 Aug 2025 11:41:52 +0300 Subject: [PATCH 35/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 51 ++++++++++++--------------------- 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index 8627c180d07..f20940cbfbc 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -16,20 +16,6 @@ SUPPORTED_PLATFORMS = ["arista_7060x6", "nvidia_sn5640", "nvidia_sn5600"] cmd_sfp_presence = "sudo sfpshow presence" -DEFAULT_COLLECTED_PORTS_NUM = 5 - - -def pytest_addoption(parser): - """ - Add command line options for pytest - """ - parser.addoption( - "--collected-ports-num", - action="store", - default=DEFAULT_COLLECTED_PORTS_NUM, - type=int, - help="Number of ports to collect for testing (default: {})".format(DEFAULT_COLLECTED_PORTS_NUM) - ) @pytest.fixture(scope="session") @@ -37,7 +23,7 @@ def collected_ports_num(request): """ Fixture to get the number of ports to collect from command line argument """ - return request.config.getoption("collected_ports_num", default=DEFAULT_COLLECTED_PORTS_NUM) + return request.config.getoption("--collected-ports-num") class TestMACFault(object): @@ -79,7 +65,7 @@ def reboot_dut(self, duthosts, localhost, enum_rand_one_per_hwsku_frontend_hostn localhost, safe_reboot=True, check_intf_up_ports=True) @pytest.fixture(scope="class") - def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_hostname, collected_ports_num): + def get_dut_and_supported_available_optical_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_hostname): dut = duthosts[enum_rand_one_per_hwsku_frontend_hostname] sfp_presence = dut.command(cmd_sfp_presence) @@ -88,31 +74,29 @@ def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_ho eeprom_infos = dut.shell("sudo sfputil show eeprom -d")['stdout'] eeprom_infos = parse_sfp_eeprom_infos(eeprom_infos) - available_optical_interfaces = get_supported_available_optical_interfaces(eeprom_infos, parsed_presence) - - pytest_assert(available_optical_interfaces, "No interfaces with SFP detected. Cannot proceed with tests.") - logging.info("Available Optical interfaces for tests: {}".format(available_optical_interfaces)) + supported_available_optical_interfaces = get_supported_available_optical_interfaces(eeprom_infos, parsed_presence) - # Select 5 random interfaces (or fewer if not enough available) - selected_interfaces = random.sample(available_optical_interfaces, - min(collected_ports_num, len(available_optical_interfaces))) - logging.info("Selected interfaces for tests: {}".format(selected_interfaces)) + pytest_assert(supported_available_optical_interfaces, "No interfaces with SFP detected. Cannot proceed with tests.") + logging.info("Available Optical interfaces for tests: {}".format(supported_available_optical_interfaces)) - return dut, selected_interfaces + return dut, supported_available_optical_interfaces def shutdown_and_startup_interfaces(self, dut, interface): dut.command("sudo config interface shutdown {}".format(interface)) pytest_assert(wait_until(30, 2, 0, lambda: self.get_interface_status(dut, interface) == "down"), "Interface {} did not go down after shutdown".format(interface)) - + dut.command("sudo config interface startup {}".format(interface)) pytest_assert(wait_until(30, 2, 0, lambda: self.get_interface_status(dut, interface) == "up"), "Interface {} did not come up after startup".format(interface)) - def test_mac_local_fault_increment(self, select_random_interfaces): - dut, interfaces = select_random_interfaces + def test_mac_local_fault_increment(self, get_dut_and_supported_available_optical_interfaces, collected_ports_num): + dut, supported_available_optical_interfaces = get_dut_and_supported_available_optical_interfaces + + selected_interfaces = random.sample(supported_available_optical_interfaces, min(collected_ports_num, len(supported_available_optical_interfaces))) + logging.info("Selected interfaces for tests: {}".format(selected_interfaces)) - for interface in interfaces: + for interface in selected_interfaces: self.shutdown_and_startup_interfaces(dut, interface) pytest_assert(self.get_interface_status(dut, interface) == "up", @@ -140,10 +124,13 @@ def test_mac_local_fault_increment(self, select_random_interfaces): pytest_assert(local_fault_after > local_fault_before, "MAC local fault count did not increment after disabling/enabling rx-output on the device") - def test_mac_remote_fault_increment(self, select_random_interfaces): - dut, interfaces = select_random_interfaces + def test_mac_remote_fault_increment(self, get_dut_and_supported_available_optical_interfaces, collected_ports_num): + dut, supported_available_optical_interfaces = get_dut_and_supported_available_optical_interfaces + + selected_interfaces = random.sample(supported_available_optical_interfaces, min(collected_ports_num, len(supported_available_optical_interfaces))) + logging.info("Selected interfaces for tests: {}".format(selected_interfaces)) - for interface in interfaces: + for interface in selected_interfaces: self.shutdown_and_startup_interfaces(dut, interface) pytest_assert(self.get_interface_status(dut, interface) == "up", From 682423cd3da6fa9a5702ef25b7a1b861fae3f61c Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Mon, 25 Aug 2025 11:43:00 +0300 Subject: [PATCH 36/55] Update conftest.py --- tests/conftest.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/conftest.py b/tests/conftest.py index b4949938bef..717d2db2aff 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -297,6 +297,12 @@ def pytest_addoption(parser): help="This flag indicates that the test is being run by the container test.") + ################################# + # Port error test options # + ################################# + parser.addoption("--collected-ports-num", action="store", default=5, type=int, + help="Number of ports to collect for testing (default: 5)") + def pytest_configure(config): if config.getoption("enable_macsec"): topo = config.getoption("topology") From c83316e5cef2f0b63fe9d540619ae959287b3cc6 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Mon, 25 Aug 2025 11:45:02 +0300 Subject: [PATCH 37/55] Update test_port_error.py From 2a62fb0133d0d597bfb57064e4e32e24433e8fa3 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Wed, 10 Sep 2025 17:08:03 +0300 Subject: [PATCH 38/55] Update test_crm.py --- tests/crm/test_crm.py | 71 +++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 37 deletions(-) diff --git a/tests/crm/test_crm.py b/tests/crm/test_crm.py index dc218c99646..ab98783e9b7 100755 --- a/tests/crm/test_crm.py +++ b/tests/crm/test_crm.py @@ -14,9 +14,9 @@ from tests.common.helpers.assertions import pytest_assert from tests.common.helpers.crm import get_used_percent, CRM_UPDATE_TIME, CRM_POLLING_INTERVAL, EXPECT_EXCEEDED, \ EXPECT_CLEAR, THR_VERIFY_CMDS -from tests.common.fixtures.duthost_utils import disable_route_checker # noqa: F401 -from tests.common.fixtures.duthost_utils import disable_fdb_aging # noqa: F401 -from tests.common.utilities import wait_until, get_data_acl +from tests.common.fixtures.duthost_utils import disable_route_checker # noqa F401 +from tests.common.fixtures.duthost_utils import disable_fdb_aging # noqa F401 +from tests.common.utilities import wait_until, get_data_acl, is_ipv6_only_topology from tests.common.mellanox_data import is_mellanox_device from tests.common.helpers.dut_utils import get_sai_sdk_dump_file @@ -419,29 +419,22 @@ def configure_neighbors(amount, interface, ip_ver, asichost, test_name): del_neighbors_template = Template(del_template) add_neighbors_template = Template(add_template) - # Increase default Linux configuration for ARP cache - increase_arp_cache(asichost, amount, ip_ver, test_name) - - # https://github.com/sonic-net/sonic-mgmt/issues/18624 - # May need to batch the commands to avoid hitting "Argument list too long" error - # IPv4 will consume at most 14 characters: " 2.XXX.XXX.XXX" - # IPv6 will consume at most 11 characters: " 2001::XXXX" - # Assuming our argument character limit is 128KB (1310072) - # Our Max number of neighbors would be: 1310072 / 14 = 9362 (Using 9000 to leave room for other characters) ip_addr_list = generate_neighbors(amount, ip_ver) - for ip_addr_batch in [ip_addr_list[i:i + 9000] for i in range(0, len(ip_addr_list), 9000)]: - ip_addr_str = " ".join([str(item) for item in ip_addr_batch]) + ip_addr_list = " ".join([str(item) for item in ip_addr_list]) - # Store CLI command to delete all created neighbors - RESTORE_CMDS[test_name].append(del_neighbors_template.render( - neigh_ip_list=ip_addr_str, - iface=interface, - namespace=asichost.namespace)) - - asichost.shell(add_neighbors_template.render( - neigh_ip_list=ip_addr_str, + # Store CLI command to delete all created neighbors + RESTORE_CMDS[test_name].append(del_neighbors_template.render( + neigh_ip_list=ip_addr_list, iface=interface, namespace=asichost.namespace)) + + # Increase default Linux configuration for ARP cache + increase_arp_cache(asichost, amount, ip_ver, test_name) + + asichost.shell(add_neighbors_template.render( + neigh_ip_list=ip_addr_list, + iface=interface, + namespace=asichost.namespace)) # Make sure CRM counters updated time.sleep(CRM_UPDATE_TIME) @@ -501,14 +494,6 @@ def test_crm_route(duthosts, enum_rand_one_per_hwsku_frontend_hostname, enum_fro asic_type = duthost.facts['asic_type'] skip_stats_check = True if asic_type == "vs" else False RESTORE_CMDS["crm_threshold_name"] = "ipv{ip_ver}_route".format(ip_ver=ip_ver) - - # will be changed to use is_ipv6_only_topology from tests.common.utilities - # once PR #19639 is merged - is_ipv6_only_topology = ( - "-v6-" in tbinfo["topo"]["name"] - if tbinfo and "topo" in tbinfo and "name" in tbinfo["topo"] - else False - ) if is_ipv6_only_topology and ip_ver == "4": pytest.skip("Skipping IPv4 test on IPv6-only topology") @@ -665,13 +650,17 @@ def get_expected_crm_stats_route_available(crm_stats_route_available, crm_stats_ @pytest.mark.parametrize("ip_ver,nexthop", [("4", "2.2.2.2"), ("6", "2001::1")]) def test_crm_nexthop(duthosts, enum_rand_one_per_hwsku_frontend_hostname, - enum_frontend_asic_index, crm_interface, ip_ver, nexthop, ptfhost, cleanup_ptf_interface): + enum_frontend_asic_index, crm_interface, ip_ver, nexthop, ptfhost, cleanup_ptf_interface, tbinfo): + + if ip_ver == "4" and is_ipv6_only_topology(tbinfo): + pytest.skip("Skipping IPv4 test on IPv6-only topology") + duthost = duthosts[enum_rand_one_per_hwsku_frontend_hostname] asichost = duthost.asic_instance(enum_frontend_asic_index) asic_type = duthost.facts['asic_type'] skip_stats_check = True if asic_type == "vs" else False RESTORE_CMDS["crm_threshold_name"] = "ipv{ip_ver}_nexthop".format(ip_ver=ip_ver) - if duthost.facts["asic_type"] in ["marvell-prestera", "marvell"]: + if duthost.facts["asic_type"] == "marvell": if ip_ver == "4": ptfhost.add_ip_to_dev('eth1', nexthop+'/24') ptfhost.set_dev_up_or_down('eth1', 'is_up') @@ -722,7 +711,7 @@ def test_crm_nexthop(duthosts, enum_rand_one_per_hwsku_frontend_hostname, "\"crm_stats_ipv{}_nexthop_available\" counter was not decremented".format(ip_ver, ip_ver)) # Remove nexthop asichost.shell(nexthop_del_cmd) - if duthost.facts["asic_type"] in ["marvell-prestera", "marvell"]: + if duthost.facts["asic_type"] == "marvell": asichost.shell(ip_remove_cmd) asichost.sonichost.add_member_to_vlan(1000, 'Ethernet1', is_tagged=False) ptfhost.remove_ip_addresses() @@ -755,7 +744,11 @@ def test_crm_nexthop(duthosts, enum_rand_one_per_hwsku_frontend_hostname, @pytest.mark.parametrize("ip_ver,neighbor,host", [("4", "2.2.2.2", "2.2.2.1/8"), ("6", "2001::1", "2001::2/64")]) def test_crm_neighbor(duthosts, enum_rand_one_per_hwsku_frontend_hostname, - enum_frontend_asic_index, crm_interface, ip_ver, neighbor, host): + enum_frontend_asic_index, crm_interface, ip_ver, neighbor, host, tbinfo): + + if ip_ver == "4" and is_ipv6_only_topology(tbinfo): + pytest.skip("Skipping IPv4 test on IPv6-only topology") + duthost = duthosts[enum_rand_one_per_hwsku_frontend_hostname] asichost = duthost.asic_instance(enum_frontend_asic_index) get_nexthop_stats = "{db_cli} COUNTERS_DB HMGET CRM:STATS \ @@ -835,7 +828,11 @@ def test_crm_neighbor(duthosts, enum_rand_one_per_hwsku_frontend_hostname, @pytest.mark.usefixtures('disable_route_checker') @pytest.mark.parametrize("group_member,network", [(False, "2.2.2.0/24"), (True, "2.2.2.0/24")]) def test_crm_nexthop_group(duthosts, enum_rand_one_per_hwsku_frontend_hostname, - enum_frontend_asic_index, crm_interface, group_member, network): + enum_frontend_asic_index, crm_interface, group_member, tbinfo, network): + + if is_ipv6_only_topology(tbinfo): + pytest.skip("Skipping IPv4 test on IPv6-only topology") + duthost = duthosts[enum_rand_one_per_hwsku_frontend_hostname] asichost = duthost.asic_instance(enum_frontend_asic_index) asic_type = duthost.facts['asic_type'] @@ -964,7 +961,7 @@ def test_acl_entry(duthosts, enum_rand_one_per_hwsku_frontend_hostname, enum_fro asichost = duthost.asic_instance(enum_frontend_asic_index) asic_collector = collector[asichost.asic_index] try: - if duthost.facts["asic_type"] in ["marvell-prestera", "marvell"]: + if duthost.facts["asic_type"] == "marvell": # Remove DATA ACL Table and add it again with ports in same port group mg_facts = duthost.get_extended_minigraph_facts(tbinfo) tmp_ports = sorted(mg_facts["minigraph_ports"], key=lambda x: int(x[8:])) @@ -1066,7 +1063,7 @@ def verify_acl_crm_stats(duthost, asichost, enum_rand_one_per_hwsku_frontend_hos .format(db_cli=asichost.sonic_db_cli, acl_tbl_key=acl_tbl_key) global crm_stats_checker - if duthost.facts["asic_type"] in ["marvell-prestera", "marvell"]: + if duthost.facts["asic_type"] == "marvell": crm_stats_checker = wait_until( 30, 5, From fd7797fcecc7e8e322475cee1539595c39b280ad Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Wed, 10 Sep 2025 17:08:22 +0300 Subject: [PATCH 39/55] Update conftest.py --- tests/crm/conftest.py | 69 ++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/tests/crm/conftest.py b/tests/crm/conftest.py index e84cd0758b8..5368adfc89c 100755 --- a/tests/crm/conftest.py +++ b/tests/crm/conftest.py @@ -8,7 +8,7 @@ from test_crm import RESTORE_CMDS, get_nh_ip from tests.common.helpers.crm import CRM_POLLING_INTERVAL from tests.common.errors import RunAnsibleModuleFail -from tests.common.utilities import wait_until, recover_acl_rule +from tests.common.utilities import wait_until, recover_acl_rule, is_ipv6_only_topology from tests.common.platform.interface_utils import parse_intf_status from tests.common.mellanox_data import is_mellanox_device from tests.common.helpers.dut_utils import get_sai_sdk_dump_file @@ -30,7 +30,7 @@ def pytest_runtest_teardown(item, nextitem): && sonic-db-cli CONFIG_DB hset 'CRM|Config' {threshold_name}_high_threshold {high} \ && sonic-db-cli CONFIG_DB hset 'CRM|Config' {threshold_name}_low_threshold {low}\"" if item.rep_setup.passed and not item.rep_call.skipped: - # Restore CRM thresholds + # Restore CRM threshods if crm_threshold_name: crm_thresholds = item.funcargs["crm_thresholds"] cmd = restore_cmd.format(threshold_name=crm_threshold_name, high=crm_thresholds[crm_threshold_name]["high"], @@ -194,7 +194,7 @@ def check_interface_status(duthost, intf_list, expected_oper='up'): return True -def configure_a_route_with_same_prefix_as_vlan_for_mlnx(duthost, asichost, tbinfo, crm_interface): +def configure_a_route_with_same_prefix_as_vlan_for_mlnx(duthost, asichost, tbinfo, crm_interface, ip_ver): """ For mellanox device, the crm available counter is related to LPM tree. When shutdown all interfaces in vlan (e.g. vlan 1000), @@ -205,55 +205,64 @@ def configure_a_route_with_same_prefix_as_vlan_for_mlnx(duthost, asichost, tbinf but we cannot estimate how long the change is ready. Therefore, it will lead the first case of test_crm_route fail occasionally because the expected available counter is not decreased. - So, we add another route with the same prefix(21) as the vlan's so that the LPM tree is not changed. + So, we add another route with the same prefix as the vlan's so that the LPM tree is not changed. """ # Get NH IP - nh_ip = get_nh_ip(duthost, asichost, crm_interface, '4') - - dump_ip_for_construct_test_route_with_same_prefix_as_vlan_interface = '21.21.21.21' - network_with_same_prefix_as_vlan_interface = str( - ipaddress.IPv4Interface( - f"{dump_ip_for_construct_test_route_with_same_prefix_as_vlan_interface}/" - f"{get_vlan_ipv4_prefix_len(asichost, tbinfo)}").network) - add_route_command = f"sudo ip route add {network_with_same_prefix_as_vlan_interface} via {nh_ip}" - duthost.shell(add_route_command) - assert wait_until(30, 5, 0, check_route_exist, duthost, network_with_same_prefix_as_vlan_interface, nh_ip), \ - f"Failed to add route {network_with_same_prefix_as_vlan_interface} via {nh_ip} " - - # Get sai sdk dump file in case test fail, we can get the LPM tree information - get_sai_sdk_dump_file(duthost, "sai_sdk_dump_before_shutdown_vlan_ports") + nh_ip = get_nh_ip(duthost, asichost, crm_interface, ip_ver) + prefix_len = get_vlan_prefix_len_per_ip_ver(asichost, tbinfo, ip_ver) + + if ip_ver == "4": + dump_ip_for_construct_test_route_with_same_prefix_as_vlan_interface = '21.21.21.21' + network_with_same_prefix_as_vlan_interface = str( + ipaddress.IPv4Interface( + f"{dump_ip_for_construct_test_route_with_same_prefix_as_vlan_interface}/{prefix_len}").network) + else: + dump_ip_for_construct_test_route_with_same_prefix_as_vlan_interface = '2021:21:21:21::21' + network_with_same_prefix_as_vlan_interface = str( + ipaddress.IPv6Interface( + f"{dump_ip_for_construct_test_route_with_same_prefix_as_vlan_interface}/{prefix_len}").network) + + add_route_command = f"sudo ip {'-6' if ip_ver == '6' else ''} route add {network_with_same_prefix_as_vlan_interface} via {nh_ip}" + route_check_command = f"show {'ipv6' if ip_ver == '6' else 'ip'} route {network_with_same_prefix_as_vlan_interface}" + del_dump_route_with_same_prefix_as_vlan_interface_cmd = f"sudo ip {'-6' if ip_ver == '6' else ''} route del {network_with_same_prefix_as_vlan_interface} via {nh_ip}" - del_dump_route_with_same_prefix_as_vlan_interface_cmd = \ - f" sudo ip route del {network_with_same_prefix_as_vlan_interface} via {nh_ip}" + duthost.shell(add_route_command, module_ignore_errors=True) + assert wait_until(30, 5, 0, check_route_exist, duthost, network_with_same_prefix_as_vlan_interface, nh_ip, route_check_command), \ + f"Failed to add route {network_with_same_prefix_as_vlan_interface} via {nh_ip}" + + get_sai_sdk_dump_file(duthost, "sai_sdk_dump_before_shutdown_vlan_ports") return del_dump_route_with_same_prefix_as_vlan_interface_cmd -def check_route_exist(duthost, network_with_same_prefix_as_vlan_interface, nh_ip): - route_output = duthost.shell(f"show ip route {network_with_same_prefix_as_vlan_interface}")["stdout"] +def check_route_exist(duthost, network_with_same_prefix_as_vlan_interface, nh_ip, route_check_command): + route_output = duthost.shell(route_check_command)["stdout"] return f"Routing entry for {network_with_same_prefix_as_vlan_interface}" in route_output and nh_ip in route_output -def get_vlan_ipv4_prefix_len(asichost, tbinfo): +def get_vlan_prefix_len_per_ip_ver(asichost, tbinfo, ip_ver): mg_facts = asichost.get_extended_minigraph_facts(tbinfo) for vlan_port_data in mg_facts["minigraph_vlan_interfaces"]: - if ipaddress.ip_interface(vlan_port_data['addr']).version == 4: - logger.info(f"vlan interface v4 prefix is :{vlan_port_data['prefixlen']}") + if ipaddress.ip_interface(vlan_port_data['addr']).version == int(ip_ver): + logger.info(f"vlan interface {ip_ver} prefix is :{vlan_port_data['prefixlen']}") return vlan_port_data['prefixlen'] - assert False, "Not find v4 prefix for vlan interface config" + assert False, f"Not find {ip_ver} prefix for vlan interface config" @pytest.fixture(scope="module", autouse=True) def shutdown_unnecessary_intf( - duthosts, tbinfo, enum_frontend_asic_index, enum_rand_one_per_hwsku_frontend_hostname, crm_interface): + duthosts, tbinfo, enum_frontend_asic_index, enum_rand_one_per_hwsku_frontend_hostname, crm_interface, request): """ Shutdown unused interfaces to avoid fdb entry influenced by mac learning """ duthost = duthosts[enum_rand_one_per_hwsku_frontend_hostname] asichost = duthost.asic_instance(enum_frontend_asic_index) intfs_connect_with_ptf = get_intf_list(duthost, tbinfo, enum_frontend_asic_index) + ip_ver = "4" if not is_ipv6_only_topology(tbinfo) else "6" + + del_dump_route_with_same_prefix_as_vlan_interface_cmd = None if intfs_connect_with_ptf: if is_mellanox_device(duthost): del_dump_route_with_same_prefix_as_vlan_interface_cmd = configure_a_route_with_same_prefix_as_vlan_for_mlnx( - duthost, asichost, tbinfo, crm_interface) + duthost, asichost, tbinfo, crm_interface, ip_ver) logger.info("Shutdown interfaces: {}".format(intfs_connect_with_ptf)) duthost.shutdown_multiple(intfs_connect_with_ptf) assert wait_until(300, 20, 0, check_interface_status, duthost, intfs_connect_with_ptf, 'down'), \ @@ -270,7 +279,7 @@ def shutdown_unnecessary_intf( duthost.no_shutdown_multiple(intfs_connect_with_ptf) assert wait_until(300, 20, 0, check_interface_status, duthost, intfs_connect_with_ptf), \ "All interfaces should be up!" - if is_mellanox_device(duthost): + if is_mellanox_device(duthost) and del_dump_route_with_same_prefix_as_vlan_interface_cmd: duthost.shell(del_dump_route_with_same_prefix_as_vlan_interface_cmd) @@ -299,7 +308,7 @@ def cleanup_ptf_interface(duthosts, ip_ver, enum_rand_one_per_hwsku_frontend_hos yield - if duthost.facts["asic_type"] in ["marvell-prestera", "marvell"]: + if duthost.facts["asic_type"] == "marvell": asichost.shell(ip_remove_cmd) # Check if member not removed output = asichost.shell(check_vlan_cmd, module_ignore_errors=True) From 7a48b852c8f93a5ab94a256e103e4b9a477c338f Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Wed, 10 Sep 2025 17:17:07 +0300 Subject: [PATCH 40/55] Update transceiver_utils.py --- tests/common/platform/transceiver_utils.py | 41 ---------------------- 1 file changed, 41 deletions(-) diff --git a/tests/common/platform/transceiver_utils.py b/tests/common/platform/transceiver_utils.py index a96b5c22c3f..3a1cd4f1e26 100644 --- a/tests/common/platform/transceiver_utils.py +++ b/tests/common/platform/transceiver_utils.py @@ -478,44 +478,3 @@ def is_sw_control_enabled(duthost, port_index): sw_control_enabled = True logging.info(f'The sw control enable of port index {port_index} is {sw_control_enabled}') return sw_control_enabled - - -def is_cmis_version_supported(cmis_version, min_required_version=5.0): - """ - Check if a CMIS version supports a specific feature by comparing it to a minimum required version - @param: cmis_version: CMIS version string (e.g., "5.0", "4.0", etc.) - @param: min_required_version: Minimum required CMIS version (default: 5.0) - @return: bool: True if CMIS version is supported, False otherwise - """ - try: - cmis_version_float = float(cmis_version) - return cmis_version_float >= min_required_version - except (ValueError, TypeError): - return False - - -def get_supported_available_optical_interfaces(eeprom_infos, parsed_presence, min_cmis_version=5.0): - """ - Filter available optical interfaces based on presence, EEPROM detection, media type, and CMIS version support - @param: eeprom_infos: Dictionary containing EEPROM information for each port - @param: parsed_presence: Dictionary containing presence status for each port - @param: min_cmis_version: Minimum required CMIS version (default: 5.0) - @return: list: List of available optical interface names that meet all criteria - """ - available_optical_interfaces = [] - - for port_name, eeprom_info in eeprom_infos.items(): - if parsed_presence.get(port_name) != "Present": - continue - if "SFP EEPROM detected" not in eeprom_info[port_name]: - continue - media_technology = eeprom_info.get("Media Interface Technology", "COPPER").upper() - if "COPPER" in media_technology: - continue - cmis_version = eeprom_info.get("CMIS Revision", "0") - if not is_cmis_version_supported(cmis_version, min_cmis_version): - logging.info(f"Port {port_name} skipped: CMIS not supported on this port.") - continue - available_optical_interfaces.append(port_name) - - return available_optical_interfaces From 5b371435478e7e41964f1543af945a2093e85017 Mon Sep 17 00:00:00 2001 From: Guy Shemesh Date: Wed, 10 Sep 2025 21:47:33 +0300 Subject: [PATCH 41/55] Adjust test_dynamic_acl.py so it can handle only ipv6 topologies. On generate packets method is will create ipv4 packets only if its not ipv6 topology test_gcu_acl_forward_rule_removal ,added skip in conditional mark file. on test_gcu_acl_arp_rule_creation , only if the variable is_ipv4_test is false/raise exception while generate the value (can happen on only ipv6 topologies) and its running on ipv6 only topology it will be skipped --- .../tests_mark_conditions.yaml | 6 + .../test_dynamic_acl.py | 188 ++++++------------ 2 files changed, 67 insertions(+), 127 deletions(-) diff --git a/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml b/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml index 71e1a16d85b..bc0adec19ac 100644 --- a/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml +++ b/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml @@ -2043,6 +2043,12 @@ generic_config_updater/test_dynamic_acl.py: - "topo_name in ['m0-2vlan']" - "platform in ['x86_64-8101_32fh_o-r0', 'x86_64-8102_64h_o-r0', 'x86_64-8101_32fh_o_c01-r0']" +tests/generic_config_updater/test_dynamic_acl.py::test_gcu_acl_forward_rule_removal: + skip: + reason: "skip for IPv6-only topologies" + conditions: + - "'-v6-' in topo_name" + generic_config_updater/test_dynamic_acl.py::test_gcu_acl_dhcp_rule_creation: skip: reason: "DHCP is not enabled in isolated topo" diff --git a/tests/generic_config_updater/test_dynamic_acl.py b/tests/generic_config_updater/test_dynamic_acl.py index 11e5133a238..0affe18fb4c 100644 --- a/tests/generic_config_updater/test_dynamic_acl.py +++ b/tests/generic_config_updater/test_dynamic_acl.py @@ -25,17 +25,17 @@ from ipaddress import ip_network, IPv6Network, IPv4Network -from tests.common.fixtures.ptfhost_utils import remove_ip_addresses # noqa: F401 +from tests.common.fixtures.ptfhost_utils import remove_ip_addresses # noqa F401 from tests.common.gu_utils import expect_op_success, expect_op_failure from tests.common.gu_utils import create_checkpoint, delete_checkpoint, rollback_or_reload from tests.common.gu_utils import apply_formed_json_patch from tests.common.gu_utils import expect_acl_rule_match, expect_acl_rule_removed from tests.common.gu_utils import expect_acl_table_match_multiple_bindings from tests.generic_config_updater.gu_utils import format_and_apply_template, load_and_apply_json_patch -from tests.common.dualtor.mux_simulator_control import toggle_all_simulator_ports_to_rand_selected_tor # noqa: F401 -from tests.common.dualtor.dual_tor_utils import setup_standby_ports_on_rand_unselected_tor # noqa: F401 +from tests.common.dualtor.mux_simulator_control import toggle_all_simulator_ports_to_rand_selected_tor # noqa F401 +from tests.common.dualtor.dual_tor_utils import setup_standby_ports_on_rand_unselected_tor # noqa F401 from tests.common.utilities import get_all_upstream_neigh_type, get_downstream_neigh_type, \ - increment_ipv4_addr, increment_ipv6_addr + increment_ipv4_addr, increment_ipv6_addr, is_ipv6_only_topology pytestmark = [ pytest.mark.topology('t0', 'm0'), @@ -46,7 +46,6 @@ CREATE_CUSTOM_TABLE_TYPE_FILE = "create_custom_table_type.json" CREATE_CUSTOM_TABLE_TEMPLATE = "create_custom_table.j2" CREATE_FORWARD_RULES_TEMPLATE = "create_forward_rules.j2" -CREATE_FORWARD_RULES_SAME_PRIORITY_TEMPLATE = "create_forward_rules_same_priority.j2" CREATE_SECONDARY_FORWARD_RULES_TEMPLATE = "create_secondary_forward_rules.j2" CREATE_INITIAL_DROP_RULE_TEMPLATE = "create_initial_drop_rule.j2" CREATE_SECONDARY_DROP_RULE_TEMPLATE = "create_secondary_drop_rule.j2" @@ -76,8 +75,8 @@ DST_IP_BLOCKED = "103.23.3.1" DST_IPV6_BLOCKED = "103:23:3:1::1" -MAX_IP_RULE_PRIORITY = 800 -MAX_DROP_RULE_PRIORITY = 200 +MAX_IP_RULE_PRIORITY = 9900 +MAX_DROP_RULE_PRIORITY = 9000 # DHCP Constants @@ -161,6 +160,7 @@ def setup(rand_selected_dut, rand_unselected_dut, tbinfo, vlan_name, topo_scenar 't0-isolated-d96u32s2', 't0-isolated-d32u32s2', 't0-isolated-d16u16s2', + 't0-isolated-v6-d32u32s2', 't1-isolated-d224u8', 't1-isolated-d128', 't1-isolated-d56u2', @@ -185,13 +185,13 @@ def setup(rand_selected_dut, rand_unselected_dut, tbinfo, vlan_name, topo_scenar upstream_port_ids.append(port_id) else: downstream_ports = list(mg_facts["minigraph_vlans"][vlan_name]["members"]) - # Put all portchannel members into dst_ports + # Put all upstream ports into dst_ports upstream_port_ids = [] upstream_ports = [] - for _, v in mg_facts['minigraph_portchannels'].items(): - for member in v['members']: - upstream_port_ids.append(mg_facts['minigraph_ptf_indices'][member]) - upstream_ports.append(member) + for port in mg_facts['minigraph_ports']: + if port not in downstream_ports and port in mg_facts['minigraph_ptf_indices']: + upstream_port_ids.append(mg_facts['minigraph_ptf_indices'][port]) + upstream_ports.append(port) for port in downstream_ports: if port in mg_facts['minigraph_port_name_to_alias_map']: @@ -336,7 +336,6 @@ def intfs_for_test(duthosts, enum_rand_one_per_hwsku_frontend_hostname, enum_fro ports = list(sorted(external_ports, key=lambda item: int(item.replace('Ethernet', '')))) is_storage_backend = 'backend' in tbinfo['topo']['name'] - is_isolated_topo = 'isolated' in tbinfo['topo']['name'] if tbinfo['topo']['type'] == 't0': if is_storage_backend: @@ -344,12 +343,6 @@ def intfs_for_test(duthosts, enum_rand_one_per_hwsku_frontend_hostname, enum_fro intfs_to_t1 = [_['attachto'].split(constants.VLAN_SUB_INTERFACE_SEPARATOR)[0] for _ in vlan_sub_intfs] ports_for_test = [_ for _ in ports if _ not in intfs_to_t1] - intf1 = ports_for_test[0] - elif is_isolated_topo: - upstream_intfs = mg_facts['minigraph_interfaces'] - intfs_to_t1 = [_intf['attachto'] for _intf in upstream_intfs] - ports_for_test = [_ for _ in ports if _ not in intfs_to_t1] - intf1 = ports_for_test[0] else: if 'PORTCHANNEL_MEMBER' in config_facts: @@ -646,13 +639,13 @@ def verify_expected_packet_behavior(exp_pkt, ptfadapter, setup, expect_drop): testutils.verify_packet_any_port(ptfadapter, exp_pkt, ports=setup["dst_port_indices"], timeout=20) -def generate_packets(setup, dst_ip=DST_IP_FORWARDED_ORIGINAL, dst_ipv6=DST_IPV6_FORWARDED_ORIGINAL): +def generate_packets(setup, tbinfo, dst_ip=DST_IP_FORWARDED_ORIGINAL, dst_ipv6=DST_IPV6_FORWARDED_ORIGINAL): """Generate packets that match the destination IP of given ips. If no IP is given, default to our original forwarding ips""" packets = {} - - packets["IPV4"] = testutils.simple_tcp_packet(eth_dst=setup["router_mac"], + if not is_ipv6_only_topology(tbinfo): + packets["IPV4"] = testutils.simple_tcpv6_packet(eth_dst=setup["router_mac"], ip_src=IP_SOURCE, ip_dst=dst_ip, ip_ttl=64) @@ -741,8 +734,8 @@ def dynamic_acl_create_forward_rules(duthost, setup): outputs = format_and_apply_template(duthost, CREATE_FORWARD_RULES_TEMPLATE, extra_vars, setup) - expected_rule_1_content = ["DYNAMIC_ACL_TABLE", "RULE_1", "900", "FORWARD", "DST_IP: " + IPV4_SUBNET, "Active"] - expected_rule_2_content = ["DYNAMIC_ACL_TABLE", "RULE_2", "899", "FORWARD", "DST_IPV6: " + IPV6_SUBNET, "Active"] + expected_rule_1_content = ["DYNAMIC_ACL_TABLE", "RULE_1", "9999", "FORWARD", "DST_IP: " + IPV4_SUBNET, "Active"] + expected_rule_2_content = ["DYNAMIC_ACL_TABLE", "RULE_2", "9998", "FORWARD", "DST_IPV6: " + IPV6_SUBNET, "Active"] for output in outputs: expect_op_success(duthost, output) @@ -751,46 +744,6 @@ def dynamic_acl_create_forward_rules(duthost, setup): expect_acl_rule_match(duthost, "RULE_2", expected_rule_2_content, setup) -def dynamic_acl_create_forward_rules_same_priority(duthost, setup): - """Create forward ACL rules with same priority""" - - IPV4_SUBNET = DST_IP_FORWARDED_ORIGINAL + "/32" - IPV4_SUBNET_2 = increment_ipv4_addr(DST_IP_FORWARDED_ORIGINAL, 1) + "/32" - IPV4_SUBNET_3 = increment_ipv4_addr(DST_IP_FORWARDED_ORIGINAL, 2) + "/32" - - IPV6_SUBNET = DST_IPV6_FORWARDED_ORIGINAL + "/128" - IPV6_SUBNET_2 = increment_ipv6_addr(DST_IPV6_FORWARDED_ORIGINAL, 1) + "/128" - IPV6_SUBNET_3 = increment_ipv6_addr(DST_IPV6_FORWARDED_ORIGINAL, 2) + "/128" - - extra_vars = { - 'ipv4_subnet': IPV4_SUBNET, - 'ipv4_subnet_2': IPV4_SUBNET_2, - 'ipv4_subnet_3': IPV4_SUBNET_3, - 'ipv6_subnet': IPV6_SUBNET, - 'ipv6_subnet_2': IPV6_SUBNET_2, - 'ipv6_subnet_3': IPV6_SUBNET_3 - } - - outputs = format_and_apply_template(duthost, CREATE_FORWARD_RULES_SAME_PRIORITY_TEMPLATE, extra_vars, setup) - - expected_rule_1_content = ["DYNAMIC_ACL_TABLE", "RULE_1", "900", "FORWARD", "DST_IP: " + IPV4_SUBNET, "Active"] - expected_rule_2_content = ["DYNAMIC_ACL_TABLE", "RULE_2", "900", "FORWARD", "DST_IPV6: " + IPV6_SUBNET, "Active"] - expected_rule_4_content = ["DYNAMIC_ACL_TABLE", "RULE_4", "900", "FORWARD", "DST_IP: " + IPV4_SUBNET_2, "Active"] - expected_rule_5_content = ["DYNAMIC_ACL_TABLE", "RULE_5", "900", "FORWARD", "DST_IPV6: " + IPV6_SUBNET_2, "Active"] - expected_rule_6_content = ["DYNAMIC_ACL_TABLE", "RULE_6", "900", "FORWARD", "DST_IP: " + IPV4_SUBNET_3, "Active"] - expected_rule_7_content = ["DYNAMIC_ACL_TABLE", "RULE_7", "900", "FORWARD", "DST_IPV6: " + IPV6_SUBNET_3, "Active"] - - for output in outputs: - expect_op_success(duthost, output) - - expect_acl_rule_match(duthost, "RULE_1", expected_rule_1_content, setup) - expect_acl_rule_match(duthost, "RULE_2", expected_rule_2_content, setup) - expect_acl_rule_match(duthost, "RULE_4", expected_rule_4_content, setup) - expect_acl_rule_match(duthost, "RULE_5", expected_rule_5_content, setup) - expect_acl_rule_match(duthost, "RULE_6", expected_rule_6_content, setup) - expect_acl_rule_match(duthost, "RULE_7", expected_rule_7_content, setup) - - def dynamic_acl_create_secondary_drop_rule(duthost, setup, blocked_port_name=None): """Create a drop rule in the format required when an ACL table has rules in it already""" @@ -804,7 +757,7 @@ def dynamic_acl_create_secondary_drop_rule(duthost, setup, blocked_port_name=Non expected_rule_content = ["DYNAMIC_ACL_TABLE", "RULE_3", - "896", + "9995", "DROP", "IN_PORTS: " + blocked_name, "Active"] @@ -826,7 +779,7 @@ def dynamic_acl_create_drop_rule_initial(duthost, setup): expected_rule_content = ["DYNAMIC_ACL_TABLE", "RULE_3", - "898", + "9997", "DROP", "IN_PORTS: " + setup["blocked_src_port_name"], "Active"] @@ -854,19 +807,19 @@ def dynamic_acl_create_three_drop_rules(duthost, setup): expected_rule_3_content = ["DYNAMIC_ACL_TABLE", "RULE_3", - "898", + "9997", "DROP", "IN_PORTS: " + extra_vars['blocked_port_1'], "Active"] expected_rule_4_content = ["DYNAMIC_ACL_TABLE", "RULE_4", - "897", + "9996", "DROP", "IN_PORTS: " + extra_vars['blocked_port_2'], "Active"] expected_rule_5_content = ["DYNAMIC_ACL_TABLE", "RULE_5", - "896", + "9995", "DROP", "IN_PORTS: " + extra_vars['blocked_port_3'], "Active"] @@ -887,7 +840,7 @@ def dynamic_acl_create_arp_forward_rule(duthost, setup): for output in outputs: expect_op_success(duthost, output) - expected_rule_content = ["DYNAMIC_ACL_TABLE", "ARP_RULE", "898", "FORWARD", "ETHER_TYPE: 0x0806", "Active"] + expected_rule_content = ["DYNAMIC_ACL_TABLE", "ARP_RULE", "9997", "FORWARD", "ETHER_TYPE: 0x0806", "Active"] expect_acl_rule_match(duthost, "ARP_RULE", expected_rule_content, setup) @@ -900,7 +853,7 @@ def dynamic_acl_create_ndp_forward_rule(duthost, setup): for output in outputs: expect_op_success(duthost, output) - expected_rule_content = ["DYNAMIC_ACL_TABLE", "NDP_RULE", "897", "FORWARD", "IP_PROTOCOL: 58", "Active"] + expected_rule_content = ["DYNAMIC_ACL_TABLE", "NDP_RULE", "9996", "FORWARD", "IP_PROTOCOL: 58", "Active"] expect_acl_rule_match(duthost, "NDP_RULE", expected_rule_content, setup) @@ -914,7 +867,7 @@ def dynamic_acl_create_dhcp_forward_rule(duthost, setup): expect_op_success(duthost, output) expected_v6_rule_content = ["DYNAMIC_ACL_TABLE", - "DHCPV6_RULE", "899", + "DHCPV6_RULE", "9998", "FORWARD", "IP_PROTOCOL: 17", "L4_DST_PORT_RANGE: 547-548", @@ -922,7 +875,7 @@ def dynamic_acl_create_dhcp_forward_rule(duthost, setup): "Active"] expected_rule_content = ["DYNAMIC_ACL_TABLE", - "DHCP_RULE", "900", + "DHCP_RULE", "9999", "FORWARD", "IP_PROTOCOL: 17", "L4_DST_PORT: 67", @@ -995,13 +948,13 @@ def dynamic_acl_replace_rules(duthost, setup): expected_rule_1_content = ["DYNAMIC_ACL_TABLE", "RULE_1", - "900", + "9999", "FORWARD", "DST_IP: " + REPLACEMENT_IPV4_SUBNET, "Active"] expected_rule_2_content = ["DYNAMIC_ACL_TABLE", "RULE_2", - "899", + "9998", "FORWARD", "DST_IPV6: " + REPLACEMENT_IPV6_SUBNET, "Active"] @@ -1153,13 +1106,22 @@ def test_gcu_acl_arp_rule_creation(rand_selected_dut, setup, dynamic_acl_create_table, prepare_ptf_intf_and_ip, - toggle_all_simulator_ports_to_rand_selected_tor): # noqa: F811 + toggle_all_simulator_ports_to_rand_selected_tor, tbinfo): # noqa F811 """Test that we can create a blanket ARP/NDP packet forwarding rule with GCU, and that ARP/NDP packets are correctly forwarded while all others are dropped.""" ip_address_for_test, _, ptf_intf_index, port_name = prepare_ptf_intf_and_ip - is_ipv4_test = type(ip_network(ip_address_for_test, strict=False)) is IPv4Network + is_ipv4_test = False + try: + is_ipv4_test = type(ip_network(ip_address_for_test, strict=False)) is IPv4Network + except ValueError as err: + if is_ipv6_only_topology(tbinfo): + pytest.skip("IPv6 only topology, skipping test") + else: + raise err + if is_ipv4_test and is_ipv6_only_topology(tbinfo): + pytest.skip("IPv4 test in IPv6 only topology, skipping test") if is_ipv4_test: show_cmd = "show arp" @@ -1186,7 +1148,7 @@ def test_gcu_acl_arp_rule_creation(rand_selected_dut, dynamic_acl_verify_packets(setup, ptfadapter, - packets=generate_packets(setup, DST_IP_BLOCKED, DST_IPV6_BLOCKED), + packets=generate_packets(setup, tbinfo, DST_IP_BLOCKED, DST_IPV6_BLOCKED), packets_dropped=True, src_port=ptf_intf_index) @@ -1196,8 +1158,8 @@ def test_gcu_acl_dhcp_rule_creation(rand_selected_dut, ptfadapter, setup, dynamic_acl_create_table, - toggle_all_simulator_ports_to_rand_selected_tor, # noqa: F811 - setup_standby_ports_on_rand_unselected_tor): # noqa: F811 + toggle_all_simulator_ports_to_rand_selected_tor, # noqa F811 + setup_standby_ports_on_rand_unselected_tor, tbinfo): # noqa F811 """Verify that DHCP and DHCPv6 forwarding rules can be created, and that dhcp packets are properly forwarded whereas others are dropped""" @@ -1211,7 +1173,7 @@ def test_gcu_acl_dhcp_rule_creation(rand_selected_dut, dynamic_acl_verify_packets(setup, ptfadapter, - packets=generate_packets(setup, DST_IP_BLOCKED, DST_IPV6_BLOCKED), + packets=generate_packets(setup, tbinfo, DST_IP_BLOCKED, DST_IPV6_BLOCKED), packets_dropped=True) @@ -1220,7 +1182,7 @@ def test_gcu_acl_drop_rule_creation(rand_selected_dut, ptfadapter, setup, dynamic_acl_create_table, - toggle_all_simulator_ports_to_rand_selected_tor): # noqa: F811 + toggle_all_simulator_ports_to_rand_selected_tor, tbinfo): # noqa F811 """Test that we can create a drop rule via GCU, and that once this drop rule is in place packets that match the drop rule are dropped and packets that do not match the drop rule are forwarded""" @@ -1228,11 +1190,11 @@ def test_gcu_acl_drop_rule_creation(rand_selected_dut, dynamic_acl_verify_packets(setup, ptfadapter, - packets=generate_packets(setup, DST_IP_BLOCKED, DST_IPV6_BLOCKED), + packets=generate_packets(setup, tbinfo, DST_IP_BLOCKED, DST_IPV6_BLOCKED), packets_dropped=True) dynamic_acl_verify_packets(setup, ptfadapter, - packets=generate_packets(setup, DST_IP_BLOCKED, DST_IPV6_BLOCKED), + packets=generate_packets(setup, tbinfo, DST_IP_BLOCKED, DST_IPV6_BLOCKED), packets_dropped=False, src_port=setup["unblocked_src_port_indice"]) @@ -1242,7 +1204,7 @@ def test_gcu_acl_drop_rule_removal(rand_selected_dut, ptfadapter, setup, dynamic_acl_create_table, - toggle_all_simulator_ports_to_rand_selected_tor): # noqa: F811 + toggle_all_simulator_ports_to_rand_selected_tor, tbinfo): # noqa F811 """Test that once a drop rule is removed, packets that were previously being dropped are now forwarded""" dynamic_acl_create_three_drop_rules(rand_selected_dut, setup) @@ -1250,7 +1212,7 @@ def test_gcu_acl_drop_rule_removal(rand_selected_dut, dynamic_acl_verify_packets(setup, ptfadapter, - packets=generate_packets(setup, DST_IP_BLOCKED, DST_IPV6_BLOCKED), + packets=generate_packets(setup, tbinfo, DST_IP_BLOCKED, DST_IPV6_BLOCKED), packets_dropped=False, src_port=setup["scale_port_indices"][2]) @@ -1260,7 +1222,7 @@ def test_gcu_acl_forward_rule_priority_respected(rand_selected_dut, ptfadapter, setup, dynamic_acl_create_table, - toggle_all_simulator_ports_to_rand_selected_tor): # noqa: F811 + toggle_all_simulator_ports_to_rand_selected_tor, tbinfo): # noqa F811 """Test that forward rules and drop rules can be created at the same time, with the forward rules having higher priority than drop. Then, perform a traffic test to confirm that packets that match both the forward and drop rules are correctly forwarded, as the forwarding rules have higher priority""" @@ -1268,38 +1230,10 @@ def test_gcu_acl_forward_rule_priority_respected(rand_selected_dut, dynamic_acl_create_forward_rules(rand_selected_dut, setup) dynamic_acl_create_secondary_drop_rule(rand_selected_dut, setup) - dynamic_acl_verify_packets(setup, ptfadapter, packets=generate_packets(setup), - packets_dropped=False) - dynamic_acl_verify_packets(setup, ptfadapter, - packets=generate_packets(setup, DST_IP_BLOCKED, DST_IPV6_BLOCKED), - packets_dropped=True) - - -def test_gcu_acl_forward_rule_same_priority(rand_selected_dut, - rand_unselected_dut, - ptfadapter, - setup, - dynamic_acl_create_table, - toggle_all_simulator_ports_to_rand_selected_tor): # noqa: F811 - """Test that forward rules can have the exact same priority and still all be applied correctly - Then, perform a traffic test to confirm that packets that match both the forward - and drop rules are correctly forwarded, as the forwarding rules have higher priority""" - - dynamic_acl_create_forward_rules_same_priority(rand_selected_dut, setup) - dynamic_acl_create_secondary_drop_rule(rand_selected_dut, setup) - - dynamic_acl_verify_packets(setup, ptfadapter, packets=generate_packets(setup), - packets_dropped=False) - dynamic_acl_verify_packets(setup, ptfadapter, packets=generate_packets(setup, - increment_ipv4_addr(DST_IP_FORWARDED_ORIGINAL, 1), - increment_ipv6_addr(DST_IPV6_FORWARDED_ORIGINAL, 1)), - packets_dropped=False) - dynamic_acl_verify_packets(setup, ptfadapter, packets=generate_packets(setup, - increment_ipv4_addr(DST_IP_FORWARDED_ORIGINAL, 2), - increment_ipv6_addr(DST_IPV6_FORWARDED_ORIGINAL, 2)), + dynamic_acl_verify_packets(setup, ptfadapter, packets=generate_packets(setup, tbinfo), packets_dropped=False) dynamic_acl_verify_packets(setup, ptfadapter, - packets=generate_packets(setup, DST_IP_BLOCKED, DST_IPV6_BLOCKED), + packets=generate_packets(setup, tbinfo, DST_IP_BLOCKED, DST_IPV6_BLOCKED), packets_dropped=True) @@ -1308,7 +1242,7 @@ def test_gcu_acl_forward_rule_replacement(rand_selected_dut, ptfadapter, setup, dynamic_acl_create_table, - toggle_all_simulator_ports_to_rand_selected_tor): # noqa: F811 + toggle_all_simulator_ports_to_rand_selected_tor, tbinfo): # noqa F811 """Test that forward rules can be created, and then afterwards can have their match pattern updated to a new value. Confirm that packets sent that match this new value are correctly forwarded, and that packets that are sent that match the old, replaced value are correctly dropped.""" @@ -1319,11 +1253,11 @@ def test_gcu_acl_forward_rule_replacement(rand_selected_dut, dynamic_acl_verify_packets(setup, ptfadapter, - packets=generate_packets(setup, + packets=generate_packets(setup, tbinfo, DST_IP_FORWARDED_REPLACEMENT, DST_IPV6_FORWARDED_REPLACEMENT), packets_dropped=False) - dynamic_acl_verify_packets(setup, ptfadapter, packets=generate_packets(setup), packets_dropped=True) + dynamic_acl_verify_packets(setup, ptfadapter, packets=generate_packets(setup, tbinfo), packets_dropped=True) @pytest.mark.parametrize("ip_type", ["IPV4", "IPV6"]) @@ -1333,7 +1267,7 @@ def test_gcu_acl_forward_rule_removal(rand_selected_dut, setup, ip_type, dynamic_acl_create_table, - toggle_all_simulator_ports_to_rand_selected_tor): # noqa: F811 + toggle_all_simulator_ports_to_rand_selected_tor, tbinfo): # noqa F811 """Test that if a forward rule is created, and then removed, that packets associated with that rule are properly no longer forwarded, and packets associated with the remaining rule are forwarded""" @@ -1341,7 +1275,7 @@ def test_gcu_acl_forward_rule_removal(rand_selected_dut, dynamic_acl_create_secondary_drop_rule(rand_selected_dut, setup) dynamic_acl_remove_ip_forward_rule(rand_selected_dut, ip_type, setup) - forward_packets = generate_packets(setup) + forward_packets = generate_packets(setup, tbinfo) drop_packets = forward_packets.copy() if ip_type == "IPV4": other_type = "IPV6" @@ -1355,7 +1289,7 @@ def test_gcu_acl_forward_rule_removal(rand_selected_dut, def test_gcu_acl_scale_rules(rand_selected_dut, rand_unselected_dut, ptfadapter, setup, dynamic_acl_create_table, - toggle_all_simulator_ports_to_rand_selected_tor): # noqa:F811 + toggle_all_simulator_ports_to_rand_selected_tor, tbinfo): # noqa F811 """Perform a scale test, creating 150 forward rules with top priority, and then creating a drop rule for every single VLAN port on our device. Select any one of our blocked ports, as well as the ips for two of our forward rules, @@ -1373,25 +1307,25 @@ def test_gcu_acl_scale_rules(rand_selected_dut, rand_unselected_dut, ptfadapter, dynamic_acl_verify_packets(setup, ptfadapter, - generate_packets(setup, v4_dest, v6_dest), + generate_packets(setup, tbinfo, v4_dest, v6_dest), packets_dropped=False, src_port=blocked_scale_port) dynamic_acl_verify_packets(setup, ptfadapter, - generate_packets(setup, DST_IP_BLOCKED, DST_IPV6_BLOCKED), + generate_packets(setup, tbinfo, DST_IP_BLOCKED, DST_IPV6_BLOCKED), packets_dropped=True, src_port=blocked_scale_port) def test_gcu_acl_nonexistent_rule_replacement(rand_selected_dut, - toggle_all_simulator_ports_to_rand_selected_tor, # noqa:F811 + toggle_all_simulator_ports_to_rand_selected_tor, # noqa F811 setup): """Confirm that replacing a nonexistent rule results in operation failure""" dynamic_acl_replace_nonexistent_rule(rand_selected_dut, setup) def test_gcu_acl_nonexistent_table_removal(rand_selected_dut, - toggle_all_simulator_ports_to_rand_selected_tor, # noqa:F811 + toggle_all_simulator_ports_to_rand_selected_tor, # noqa F811 setup): """Confirm that removing a nonexistent table results in operation failure""" dynamic_acl_remove_nonexistent_table(rand_selected_dut, setup) From b00168a8fa7f59ef99f50795e818013e19853b6e Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Sun, 14 Sep 2025 18:45:19 +0300 Subject: [PATCH 42/55] Update conftest.py --- tests/crm/conftest.py | 69 +++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 39 deletions(-) diff --git a/tests/crm/conftest.py b/tests/crm/conftest.py index 5368adfc89c..e84cd0758b8 100755 --- a/tests/crm/conftest.py +++ b/tests/crm/conftest.py @@ -8,7 +8,7 @@ from test_crm import RESTORE_CMDS, get_nh_ip from tests.common.helpers.crm import CRM_POLLING_INTERVAL from tests.common.errors import RunAnsibleModuleFail -from tests.common.utilities import wait_until, recover_acl_rule, is_ipv6_only_topology +from tests.common.utilities import wait_until, recover_acl_rule from tests.common.platform.interface_utils import parse_intf_status from tests.common.mellanox_data import is_mellanox_device from tests.common.helpers.dut_utils import get_sai_sdk_dump_file @@ -30,7 +30,7 @@ def pytest_runtest_teardown(item, nextitem): && sonic-db-cli CONFIG_DB hset 'CRM|Config' {threshold_name}_high_threshold {high} \ && sonic-db-cli CONFIG_DB hset 'CRM|Config' {threshold_name}_low_threshold {low}\"" if item.rep_setup.passed and not item.rep_call.skipped: - # Restore CRM threshods + # Restore CRM thresholds if crm_threshold_name: crm_thresholds = item.funcargs["crm_thresholds"] cmd = restore_cmd.format(threshold_name=crm_threshold_name, high=crm_thresholds[crm_threshold_name]["high"], @@ -194,7 +194,7 @@ def check_interface_status(duthost, intf_list, expected_oper='up'): return True -def configure_a_route_with_same_prefix_as_vlan_for_mlnx(duthost, asichost, tbinfo, crm_interface, ip_ver): +def configure_a_route_with_same_prefix_as_vlan_for_mlnx(duthost, asichost, tbinfo, crm_interface): """ For mellanox device, the crm available counter is related to LPM tree. When shutdown all interfaces in vlan (e.g. vlan 1000), @@ -205,64 +205,55 @@ def configure_a_route_with_same_prefix_as_vlan_for_mlnx(duthost, asichost, tbinf but we cannot estimate how long the change is ready. Therefore, it will lead the first case of test_crm_route fail occasionally because the expected available counter is not decreased. - So, we add another route with the same prefix as the vlan's so that the LPM tree is not changed. + So, we add another route with the same prefix(21) as the vlan's so that the LPM tree is not changed. """ # Get NH IP - nh_ip = get_nh_ip(duthost, asichost, crm_interface, ip_ver) - prefix_len = get_vlan_prefix_len_per_ip_ver(asichost, tbinfo, ip_ver) - - if ip_ver == "4": - dump_ip_for_construct_test_route_with_same_prefix_as_vlan_interface = '21.21.21.21' - network_with_same_prefix_as_vlan_interface = str( - ipaddress.IPv4Interface( - f"{dump_ip_for_construct_test_route_with_same_prefix_as_vlan_interface}/{prefix_len}").network) - else: - dump_ip_for_construct_test_route_with_same_prefix_as_vlan_interface = '2021:21:21:21::21' - network_with_same_prefix_as_vlan_interface = str( - ipaddress.IPv6Interface( - f"{dump_ip_for_construct_test_route_with_same_prefix_as_vlan_interface}/{prefix_len}").network) - - add_route_command = f"sudo ip {'-6' if ip_ver == '6' else ''} route add {network_with_same_prefix_as_vlan_interface} via {nh_ip}" - route_check_command = f"show {'ipv6' if ip_ver == '6' else 'ip'} route {network_with_same_prefix_as_vlan_interface}" - del_dump_route_with_same_prefix_as_vlan_interface_cmd = f"sudo ip {'-6' if ip_ver == '6' else ''} route del {network_with_same_prefix_as_vlan_interface} via {nh_ip}" - - duthost.shell(add_route_command, module_ignore_errors=True) - assert wait_until(30, 5, 0, check_route_exist, duthost, network_with_same_prefix_as_vlan_interface, nh_ip, route_check_command), \ - f"Failed to add route {network_with_same_prefix_as_vlan_interface} via {nh_ip}" - + nh_ip = get_nh_ip(duthost, asichost, crm_interface, '4') + + dump_ip_for_construct_test_route_with_same_prefix_as_vlan_interface = '21.21.21.21' + network_with_same_prefix_as_vlan_interface = str( + ipaddress.IPv4Interface( + f"{dump_ip_for_construct_test_route_with_same_prefix_as_vlan_interface}/" + f"{get_vlan_ipv4_prefix_len(asichost, tbinfo)}").network) + add_route_command = f"sudo ip route add {network_with_same_prefix_as_vlan_interface} via {nh_ip}" + duthost.shell(add_route_command) + assert wait_until(30, 5, 0, check_route_exist, duthost, network_with_same_prefix_as_vlan_interface, nh_ip), \ + f"Failed to add route {network_with_same_prefix_as_vlan_interface} via {nh_ip} " + + # Get sai sdk dump file in case test fail, we can get the LPM tree information get_sai_sdk_dump_file(duthost, "sai_sdk_dump_before_shutdown_vlan_ports") + del_dump_route_with_same_prefix_as_vlan_interface_cmd = \ + f" sudo ip route del {network_with_same_prefix_as_vlan_interface} via {nh_ip}" + return del_dump_route_with_same_prefix_as_vlan_interface_cmd -def check_route_exist(duthost, network_with_same_prefix_as_vlan_interface, nh_ip, route_check_command): - route_output = duthost.shell(route_check_command)["stdout"] +def check_route_exist(duthost, network_with_same_prefix_as_vlan_interface, nh_ip): + route_output = duthost.shell(f"show ip route {network_with_same_prefix_as_vlan_interface}")["stdout"] return f"Routing entry for {network_with_same_prefix_as_vlan_interface}" in route_output and nh_ip in route_output -def get_vlan_prefix_len_per_ip_ver(asichost, tbinfo, ip_ver): +def get_vlan_ipv4_prefix_len(asichost, tbinfo): mg_facts = asichost.get_extended_minigraph_facts(tbinfo) for vlan_port_data in mg_facts["minigraph_vlan_interfaces"]: - if ipaddress.ip_interface(vlan_port_data['addr']).version == int(ip_ver): - logger.info(f"vlan interface {ip_ver} prefix is :{vlan_port_data['prefixlen']}") + if ipaddress.ip_interface(vlan_port_data['addr']).version == 4: + logger.info(f"vlan interface v4 prefix is :{vlan_port_data['prefixlen']}") return vlan_port_data['prefixlen'] - assert False, f"Not find {ip_ver} prefix for vlan interface config" + assert False, "Not find v4 prefix for vlan interface config" @pytest.fixture(scope="module", autouse=True) def shutdown_unnecessary_intf( - duthosts, tbinfo, enum_frontend_asic_index, enum_rand_one_per_hwsku_frontend_hostname, crm_interface, request): + duthosts, tbinfo, enum_frontend_asic_index, enum_rand_one_per_hwsku_frontend_hostname, crm_interface): """ Shutdown unused interfaces to avoid fdb entry influenced by mac learning """ duthost = duthosts[enum_rand_one_per_hwsku_frontend_hostname] asichost = duthost.asic_instance(enum_frontend_asic_index) intfs_connect_with_ptf = get_intf_list(duthost, tbinfo, enum_frontend_asic_index) - ip_ver = "4" if not is_ipv6_only_topology(tbinfo) else "6" - - del_dump_route_with_same_prefix_as_vlan_interface_cmd = None if intfs_connect_with_ptf: if is_mellanox_device(duthost): del_dump_route_with_same_prefix_as_vlan_interface_cmd = configure_a_route_with_same_prefix_as_vlan_for_mlnx( - duthost, asichost, tbinfo, crm_interface, ip_ver) + duthost, asichost, tbinfo, crm_interface) logger.info("Shutdown interfaces: {}".format(intfs_connect_with_ptf)) duthost.shutdown_multiple(intfs_connect_with_ptf) assert wait_until(300, 20, 0, check_interface_status, duthost, intfs_connect_with_ptf, 'down'), \ @@ -279,7 +270,7 @@ def shutdown_unnecessary_intf( duthost.no_shutdown_multiple(intfs_connect_with_ptf) assert wait_until(300, 20, 0, check_interface_status, duthost, intfs_connect_with_ptf), \ "All interfaces should be up!" - if is_mellanox_device(duthost) and del_dump_route_with_same_prefix_as_vlan_interface_cmd: + if is_mellanox_device(duthost): duthost.shell(del_dump_route_with_same_prefix_as_vlan_interface_cmd) @@ -308,7 +299,7 @@ def cleanup_ptf_interface(duthosts, ip_ver, enum_rand_one_per_hwsku_frontend_hos yield - if duthost.facts["asic_type"] == "marvell": + if duthost.facts["asic_type"] in ["marvell-prestera", "marvell"]: asichost.shell(ip_remove_cmd) # Check if member not removed output = asichost.shell(check_vlan_cmd, module_ignore_errors=True) From 708da22db9fa7aaa10c4978a8c49a1cb47a706cd Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Sun, 14 Sep 2025 18:46:26 +0300 Subject: [PATCH 43/55] Update test_crm.py --- tests/crm/test_crm.py | 71 ++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 34 deletions(-) diff --git a/tests/crm/test_crm.py b/tests/crm/test_crm.py index ab98783e9b7..dc218c99646 100755 --- a/tests/crm/test_crm.py +++ b/tests/crm/test_crm.py @@ -14,9 +14,9 @@ from tests.common.helpers.assertions import pytest_assert from tests.common.helpers.crm import get_used_percent, CRM_UPDATE_TIME, CRM_POLLING_INTERVAL, EXPECT_EXCEEDED, \ EXPECT_CLEAR, THR_VERIFY_CMDS -from tests.common.fixtures.duthost_utils import disable_route_checker # noqa F401 -from tests.common.fixtures.duthost_utils import disable_fdb_aging # noqa F401 -from tests.common.utilities import wait_until, get_data_acl, is_ipv6_only_topology +from tests.common.fixtures.duthost_utils import disable_route_checker # noqa: F401 +from tests.common.fixtures.duthost_utils import disable_fdb_aging # noqa: F401 +from tests.common.utilities import wait_until, get_data_acl from tests.common.mellanox_data import is_mellanox_device from tests.common.helpers.dut_utils import get_sai_sdk_dump_file @@ -419,22 +419,29 @@ def configure_neighbors(amount, interface, ip_ver, asichost, test_name): del_neighbors_template = Template(del_template) add_neighbors_template = Template(add_template) + # Increase default Linux configuration for ARP cache + increase_arp_cache(asichost, amount, ip_ver, test_name) + + # https://github.com/sonic-net/sonic-mgmt/issues/18624 + # May need to batch the commands to avoid hitting "Argument list too long" error + # IPv4 will consume at most 14 characters: " 2.XXX.XXX.XXX" + # IPv6 will consume at most 11 characters: " 2001::XXXX" + # Assuming our argument character limit is 128KB (1310072) + # Our Max number of neighbors would be: 1310072 / 14 = 9362 (Using 9000 to leave room for other characters) ip_addr_list = generate_neighbors(amount, ip_ver) - ip_addr_list = " ".join([str(item) for item in ip_addr_list]) + for ip_addr_batch in [ip_addr_list[i:i + 9000] for i in range(0, len(ip_addr_list), 9000)]: + ip_addr_str = " ".join([str(item) for item in ip_addr_batch]) - # Store CLI command to delete all created neighbors - RESTORE_CMDS[test_name].append(del_neighbors_template.render( - neigh_ip_list=ip_addr_list, + # Store CLI command to delete all created neighbors + RESTORE_CMDS[test_name].append(del_neighbors_template.render( + neigh_ip_list=ip_addr_str, + iface=interface, + namespace=asichost.namespace)) + + asichost.shell(add_neighbors_template.render( + neigh_ip_list=ip_addr_str, iface=interface, namespace=asichost.namespace)) - - # Increase default Linux configuration for ARP cache - increase_arp_cache(asichost, amount, ip_ver, test_name) - - asichost.shell(add_neighbors_template.render( - neigh_ip_list=ip_addr_list, - iface=interface, - namespace=asichost.namespace)) # Make sure CRM counters updated time.sleep(CRM_UPDATE_TIME) @@ -494,6 +501,14 @@ def test_crm_route(duthosts, enum_rand_one_per_hwsku_frontend_hostname, enum_fro asic_type = duthost.facts['asic_type'] skip_stats_check = True if asic_type == "vs" else False RESTORE_CMDS["crm_threshold_name"] = "ipv{ip_ver}_route".format(ip_ver=ip_ver) + + # will be changed to use is_ipv6_only_topology from tests.common.utilities + # once PR #19639 is merged + is_ipv6_only_topology = ( + "-v6-" in tbinfo["topo"]["name"] + if tbinfo and "topo" in tbinfo and "name" in tbinfo["topo"] + else False + ) if is_ipv6_only_topology and ip_ver == "4": pytest.skip("Skipping IPv4 test on IPv6-only topology") @@ -650,17 +665,13 @@ def get_expected_crm_stats_route_available(crm_stats_route_available, crm_stats_ @pytest.mark.parametrize("ip_ver,nexthop", [("4", "2.2.2.2"), ("6", "2001::1")]) def test_crm_nexthop(duthosts, enum_rand_one_per_hwsku_frontend_hostname, - enum_frontend_asic_index, crm_interface, ip_ver, nexthop, ptfhost, cleanup_ptf_interface, tbinfo): - - if ip_ver == "4" and is_ipv6_only_topology(tbinfo): - pytest.skip("Skipping IPv4 test on IPv6-only topology") - + enum_frontend_asic_index, crm_interface, ip_ver, nexthop, ptfhost, cleanup_ptf_interface): duthost = duthosts[enum_rand_one_per_hwsku_frontend_hostname] asichost = duthost.asic_instance(enum_frontend_asic_index) asic_type = duthost.facts['asic_type'] skip_stats_check = True if asic_type == "vs" else False RESTORE_CMDS["crm_threshold_name"] = "ipv{ip_ver}_nexthop".format(ip_ver=ip_ver) - if duthost.facts["asic_type"] == "marvell": + if duthost.facts["asic_type"] in ["marvell-prestera", "marvell"]: if ip_ver == "4": ptfhost.add_ip_to_dev('eth1', nexthop+'/24') ptfhost.set_dev_up_or_down('eth1', 'is_up') @@ -711,7 +722,7 @@ def test_crm_nexthop(duthosts, enum_rand_one_per_hwsku_frontend_hostname, "\"crm_stats_ipv{}_nexthop_available\" counter was not decremented".format(ip_ver, ip_ver)) # Remove nexthop asichost.shell(nexthop_del_cmd) - if duthost.facts["asic_type"] == "marvell": + if duthost.facts["asic_type"] in ["marvell-prestera", "marvell"]: asichost.shell(ip_remove_cmd) asichost.sonichost.add_member_to_vlan(1000, 'Ethernet1', is_tagged=False) ptfhost.remove_ip_addresses() @@ -744,11 +755,7 @@ def test_crm_nexthop(duthosts, enum_rand_one_per_hwsku_frontend_hostname, @pytest.mark.parametrize("ip_ver,neighbor,host", [("4", "2.2.2.2", "2.2.2.1/8"), ("6", "2001::1", "2001::2/64")]) def test_crm_neighbor(duthosts, enum_rand_one_per_hwsku_frontend_hostname, - enum_frontend_asic_index, crm_interface, ip_ver, neighbor, host, tbinfo): - - if ip_ver == "4" and is_ipv6_only_topology(tbinfo): - pytest.skip("Skipping IPv4 test on IPv6-only topology") - + enum_frontend_asic_index, crm_interface, ip_ver, neighbor, host): duthost = duthosts[enum_rand_one_per_hwsku_frontend_hostname] asichost = duthost.asic_instance(enum_frontend_asic_index) get_nexthop_stats = "{db_cli} COUNTERS_DB HMGET CRM:STATS \ @@ -828,11 +835,7 @@ def test_crm_neighbor(duthosts, enum_rand_one_per_hwsku_frontend_hostname, @pytest.mark.usefixtures('disable_route_checker') @pytest.mark.parametrize("group_member,network", [(False, "2.2.2.0/24"), (True, "2.2.2.0/24")]) def test_crm_nexthop_group(duthosts, enum_rand_one_per_hwsku_frontend_hostname, - enum_frontend_asic_index, crm_interface, group_member, tbinfo, network): - - if is_ipv6_only_topology(tbinfo): - pytest.skip("Skipping IPv4 test on IPv6-only topology") - + enum_frontend_asic_index, crm_interface, group_member, network): duthost = duthosts[enum_rand_one_per_hwsku_frontend_hostname] asichost = duthost.asic_instance(enum_frontend_asic_index) asic_type = duthost.facts['asic_type'] @@ -961,7 +964,7 @@ def test_acl_entry(duthosts, enum_rand_one_per_hwsku_frontend_hostname, enum_fro asichost = duthost.asic_instance(enum_frontend_asic_index) asic_collector = collector[asichost.asic_index] try: - if duthost.facts["asic_type"] == "marvell": + if duthost.facts["asic_type"] in ["marvell-prestera", "marvell"]: # Remove DATA ACL Table and add it again with ports in same port group mg_facts = duthost.get_extended_minigraph_facts(tbinfo) tmp_ports = sorted(mg_facts["minigraph_ports"], key=lambda x: int(x[8:])) @@ -1063,7 +1066,7 @@ def verify_acl_crm_stats(duthost, asichost, enum_rand_one_per_hwsku_frontend_hos .format(db_cli=asichost.sonic_db_cli, acl_tbl_key=acl_tbl_key) global crm_stats_checker - if duthost.facts["asic_type"] == "marvell": + if duthost.facts["asic_type"] in ["marvell-prestera", "marvell"]: crm_stats_checker = wait_until( 30, 5, From c2d44fbbd82e2aec76a3a6cc5abdfaf79aab467b Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Sun, 14 Sep 2025 18:47:02 +0300 Subject: [PATCH 44/55] Update test_port_error.py --- tests/layer1/test_port_error.py | 86 +++++++++------------------------ 1 file changed, 23 insertions(+), 63 deletions(-) diff --git a/tests/layer1/test_port_error.py b/tests/layer1/test_port_error.py index f20940cbfbc..2801127146b 100644 --- a/tests/layer1/test_port_error.py +++ b/tests/layer1/test_port_error.py @@ -5,9 +5,6 @@ from tests.common.helpers.assertions import pytest_assert from tests.common.utilities import skip_release -from tests.common.platform.transceiver_utils import parse_sfp_eeprom_infos, get_supported_available_optical_interfaces -from tests.platform_tests.sfp.software_control.helpers import check_sc_sai_attribute_value -from tests.common.utilities import wait_until pytestmark = [ pytest.mark.disable_loganalyzer, # disable automatic loganalyzer @@ -18,14 +15,6 @@ cmd_sfp_presence = "sudo sfpshow presence" -@pytest.fixture(scope="session") -def collected_ports_num(request): - """ - Fixture to get the number of ports to collect from command line argument - """ - return request.config.getoption("--collected-ports-num") - - class TestMACFault(object): @pytest.fixture(autouse=True) def is_supported_platform(self, duthost, tbinfo): @@ -37,9 +26,6 @@ def is_supported_platform(self, duthost, tbinfo): else: pytest.skip("DUT has platform {}, test is not supported".format(duthost.facts['platform'])) - if 'nvidia' in duthost.facts['platform'].lower() and not check_sc_sai_attribute_value(duthost): - pytest.skip("SW control feature is not enabled on platform") - @staticmethod def get_mac_fault_count(dut, interface, fault_type): output = dut.show_and_parse("show int errors {}".format(interface)) @@ -58,47 +44,30 @@ def get_mac_fault_count(dut, interface, fault_type): def get_interface_status(dut, interface): return dut.show_and_parse("show interfaces status {}".format(interface))[0].get("oper", "unknown") - @pytest.fixture(scope="class", autouse=True) - def reboot_dut(self, duthosts, localhost, enum_rand_one_per_hwsku_frontend_hostname): - from tests.common.reboot import reboot - reboot(duthosts[enum_rand_one_per_hwsku_frontend_hostname], - localhost, safe_reboot=True, check_intf_up_ports=True) - - @pytest.fixture(scope="class") - def get_dut_and_supported_available_optical_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_hostname): + @pytest.fixture + def select_random_interfaces(self, duthosts, enum_rand_one_per_hwsku_frontend_hostname): dut = duthosts[enum_rand_one_per_hwsku_frontend_hostname] + interfaces = list(dut.show_and_parse("show interfaces status")) sfp_presence = dut.command(cmd_sfp_presence) parsed_presence = {line.split()[0]: line.split()[1] for line in sfp_presence["stdout_lines"][2:]} - eeprom_infos = dut.shell("sudo sfputil show eeprom -d")['stdout'] - eeprom_infos = parse_sfp_eeprom_infos(eeprom_infos) - - supported_available_optical_interfaces = get_supported_available_optical_interfaces(eeprom_infos, parsed_presence) + available_interfaces = [ + intf["interface"] for intf in interfaces + if parsed_presence.get(intf["interface"]) == "Present" + ] - pytest_assert(supported_available_optical_interfaces, "No interfaces with SFP detected. Cannot proceed with tests.") - logging.info("Available Optical interfaces for tests: {}".format(supported_available_optical_interfaces)) + pytest_assert(available_interfaces, "No interfaces with SFP detected. Cannot proceed with tests.") - return dut, supported_available_optical_interfaces + # Select 5 random interfaces (or fewer if not enough available) + selected_interfaces = random.sample(available_interfaces, min(5, len(available_interfaces))) - def shutdown_and_startup_interfaces(self, dut, interface): - dut.command("sudo config interface shutdown {}".format(interface)) - pytest_assert(wait_until(30, 2, 0, lambda: self.get_interface_status(dut, interface) == "down"), - "Interface {} did not go down after shutdown".format(interface)) + return dut, selected_interfaces - dut.command("sudo config interface startup {}".format(interface)) - pytest_assert(wait_until(30, 2, 0, lambda: self.get_interface_status(dut, interface) == "up"), - "Interface {} did not come up after startup".format(interface)) - - def test_mac_local_fault_increment(self, get_dut_and_supported_available_optical_interfaces, collected_ports_num): - dut, supported_available_optical_interfaces = get_dut_and_supported_available_optical_interfaces - - selected_interfaces = random.sample(supported_available_optical_interfaces, min(collected_ports_num, len(supported_available_optical_interfaces))) - logging.info("Selected interfaces for tests: {}".format(selected_interfaces)) - - for interface in selected_interfaces: - self.shutdown_and_startup_interfaces(dut, interface) + def test_mac_local_fault_increment(self, select_random_interfaces): + dut, interfaces = select_random_interfaces + for interface in interfaces: pytest_assert(self.get_interface_status(dut, interface) == "up", "Interface {} was not up before disabling/enabling rx-output using sfputil".format(interface)) @@ -108,31 +77,24 @@ def test_mac_local_fault_increment(self, get_dut_and_supported_available_optical dut.shell("sudo sfputil debug rx-output {} disable".format(interface)) time.sleep(5) pytest_assert(self.get_interface_status(dut, interface) == "down", - "Interface {iface} did not go down after 'sudo sfputil debug rx-output {iface} disable'" - .format(iface=interface)) + "Interface {} did not go down after disabling rx-output using sfputil".format(interface)) dut.shell("sudo sfputil debug rx-output {} enable".format(interface)) time.sleep(20) pytest_assert(self.get_interface_status(dut, interface) == "up", - "Interface {iface} did not come up after 'sudo sfputil debug rx-output {iface} enable'" - .format(iface=interface)) + "Interface {} did not come up after enabling rx-output using sfputil".format(interface)) local_fault_after = self.get_mac_fault_count(dut, interface, "mac local fault") logging.info("MAC local fault count after disabling/enabling rx-output using sfputil {}: {}".format( interface, local_fault_after)) pytest_assert(local_fault_after > local_fault_before, - "MAC local fault count did not increment after disabling/enabling rx-output on the device") - - def test_mac_remote_fault_increment(self, get_dut_and_supported_available_optical_interfaces, collected_ports_num): - dut, supported_available_optical_interfaces = get_dut_and_supported_available_optical_interfaces - - selected_interfaces = random.sample(supported_available_optical_interfaces, min(collected_ports_num, len(supported_available_optical_interfaces))) - logging.info("Selected interfaces for tests: {}".format(selected_interfaces)) + "MAC local fault count did not increment after disabling/enabling tx-output on the device") - for interface in selected_interfaces: - self.shutdown_and_startup_interfaces(dut, interface) + def test_mac_remote_fault_increment(self, select_random_interfaces): + dut, interfaces = select_random_interfaces + for interface in interfaces: pytest_assert(self.get_interface_status(dut, interface) == "up", "Interface {} was not up before disabling/enabling tx-output using sfputil".format(interface)) @@ -142,18 +104,16 @@ def test_mac_remote_fault_increment(self, get_dut_and_supported_available_optica dut.shell("sudo sfputil debug tx-output {} disable".format(interface)) time.sleep(5) pytest_assert(self.get_interface_status(dut, interface) == "down", - "Interface {iface} did not go down after 'sudo sfputil debug tx-output {iface} disable'" - .format(iface=interface)) + "Interface {} did not go down after disabling rx-output using sfputil".format(interface)) dut.shell("sudo sfputil debug tx-output {} enable".format(interface)) time.sleep(20) pytest_assert(self.get_interface_status(dut, interface) == "up", - "Interface {iface} did not come up after 'sudo sfputil debug tx-output {iface} enable'" - .format(iface=interface)) + "Interface {} did not come up after disabling tx-output using sfputil".format(interface)) remote_fault_after = self.get_mac_fault_count(dut, interface, "mac remote fault") - logging.info("MAC remote fault count after disabling/enabling tx-output using sfputil {}: {}".format( + logging.info("MAC remote fault count after disabling/enabling rx-output using sfputil {}: {}".format( interface, remote_fault_after)) pytest_assert(remote_fault_after > remote_fault_before, From 02ebf47f5de3dec019f4586e0443a9c004a019b5 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Sun, 14 Sep 2025 18:47:39 +0300 Subject: [PATCH 45/55] Update conftest.py --- tests/conftest.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index de9be166b76..93605b18feb 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -297,12 +297,6 @@ def pytest_addoption(parser): help="This flag indicates that the test is being run by the container test.") - ################################# - # Port error test options # - ################################# - parser.addoption("--collected-ports-num", action="store", default=5, type=int, - help="Number of ports to collect for testing (default: 5)") - def pytest_configure(config): if config.getoption("enable_macsec"): topo = config.getoption("topology") From 1841ee96d8b002a8dac01303eeba46a031962e8b Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Mon, 15 Sep 2025 10:01:13 +0300 Subject: [PATCH 46/55] Update test_dynamic_acl.py --- tests/generic_config_updater/test_dynamic_acl.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/generic_config_updater/test_dynamic_acl.py b/tests/generic_config_updater/test_dynamic_acl.py index 0affe18fb4c..62d9d0167ec 100644 --- a/tests/generic_config_updater/test_dynamic_acl.py +++ b/tests/generic_config_updater/test_dynamic_acl.py @@ -646,9 +646,9 @@ def generate_packets(setup, tbinfo, dst_ip=DST_IP_FORWARDED_ORIGINAL, dst_ipv6=D packets = {} if not is_ipv6_only_topology(tbinfo): packets["IPV4"] = testutils.simple_tcpv6_packet(eth_dst=setup["router_mac"], - ip_src=IP_SOURCE, - ip_dst=dst_ip, - ip_ttl=64) + ip_src=IP_SOURCE, + ip_dst=dst_ip, + ip_ttl=64) packets["IPV6"] = testutils.simple_tcpv6_packet(eth_dst=setup["router_mac"], ipv6_src=IPV6_SOURCE, From 7b372ab62e3e2b72da208fff2c641e3cdaa01a08 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Mon, 15 Sep 2025 10:08:28 +0300 Subject: [PATCH 47/55] Update tests_mark_conditions.yaml --- .../common/plugins/conditional_mark/tests_mark_conditions.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml b/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml index bc0adec19ac..8633f63bfa7 100644 --- a/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml +++ b/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml @@ -2043,7 +2043,7 @@ generic_config_updater/test_dynamic_acl.py: - "topo_name in ['m0-2vlan']" - "platform in ['x86_64-8101_32fh_o-r0', 'x86_64-8102_64h_o-r0', 'x86_64-8101_32fh_o_c01-r0']" -tests/generic_config_updater/test_dynamic_acl.py::test_gcu_acl_forward_rule_removal: +generic_config_updater/test_dynamic_acl.py::test_gcu_acl_forward_rule_removal: skip: reason: "skip for IPv6-only topologies" conditions: From f27e3346eb8c51714b737396f9513298379511f4 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Mon, 15 Sep 2025 10:14:42 +0300 Subject: [PATCH 48/55] Update tests_mark_conditions.yaml --- .../conditional_mark/tests_mark_conditions.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml b/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml index 8633f63bfa7..a27c01af52b 100644 --- a/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml +++ b/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml @@ -2043,18 +2043,18 @@ generic_config_updater/test_dynamic_acl.py: - "topo_name in ['m0-2vlan']" - "platform in ['x86_64-8101_32fh_o-r0', 'x86_64-8102_64h_o-r0', 'x86_64-8101_32fh_o_c01-r0']" -generic_config_updater/test_dynamic_acl.py::test_gcu_acl_forward_rule_removal: - skip: - reason: "skip for IPv6-only topologies" - conditions: - - "'-v6-' in topo_name" - generic_config_updater/test_dynamic_acl.py::test_gcu_acl_dhcp_rule_creation: skip: reason: "DHCP is not enabled in isolated topo" conditions: - "'t0-isolated' in topo_name" +generic_config_updater/test_dynamic_acl.py::test_gcu_acl_forward_rule_removal: + skip: + reason: "skip for IPv6-only topologies" + conditions: + - "'-v6-' in topo_name" + generic_config_updater/test_ecn_config_update.py::test_ecn_config_updates: skip: reason: "This test is not run on this asic type, topology, or version currently" From 488decb6dfea4aa9565ee1ecabd34d7d12a87b49 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Mon, 15 Sep 2025 16:39:01 +0300 Subject: [PATCH 49/55] Update test_dynamic_acl.py --- .../test_dynamic_acl.py | 151 +++++++++++++----- 1 file changed, 113 insertions(+), 38 deletions(-) diff --git a/tests/generic_config_updater/test_dynamic_acl.py b/tests/generic_config_updater/test_dynamic_acl.py index 62d9d0167ec..71b52ec65ab 100644 --- a/tests/generic_config_updater/test_dynamic_acl.py +++ b/tests/generic_config_updater/test_dynamic_acl.py @@ -25,15 +25,15 @@ from ipaddress import ip_network, IPv6Network, IPv4Network -from tests.common.fixtures.ptfhost_utils import remove_ip_addresses # noqa F401 +from tests.common.fixtures.ptfhost_utils import remove_ip_addresses # noqa: F401 from tests.common.gu_utils import expect_op_success, expect_op_failure from tests.common.gu_utils import create_checkpoint, delete_checkpoint, rollback_or_reload from tests.common.gu_utils import apply_formed_json_patch from tests.common.gu_utils import expect_acl_rule_match, expect_acl_rule_removed from tests.common.gu_utils import expect_acl_table_match_multiple_bindings from tests.generic_config_updater.gu_utils import format_and_apply_template, load_and_apply_json_patch -from tests.common.dualtor.mux_simulator_control import toggle_all_simulator_ports_to_rand_selected_tor # noqa F401 -from tests.common.dualtor.dual_tor_utils import setup_standby_ports_on_rand_unselected_tor # noqa F401 +from tests.common.dualtor.mux_simulator_control import toggle_all_simulator_ports_to_rand_selected_tor # noqa: F401 +from tests.common.dualtor.dual_tor_utils import setup_standby_ports_on_rand_unselected_tor # noqa: F401 from tests.common.utilities import get_all_upstream_neigh_type, get_downstream_neigh_type, \ increment_ipv4_addr, increment_ipv6_addr, is_ipv6_only_topology @@ -46,6 +46,7 @@ CREATE_CUSTOM_TABLE_TYPE_FILE = "create_custom_table_type.json" CREATE_CUSTOM_TABLE_TEMPLATE = "create_custom_table.j2" CREATE_FORWARD_RULES_TEMPLATE = "create_forward_rules.j2" +CREATE_FORWARD_RULES_SAME_PRIORITY_TEMPLATE = "create_forward_rules_same_priority.j2" CREATE_SECONDARY_FORWARD_RULES_TEMPLATE = "create_secondary_forward_rules.j2" CREATE_INITIAL_DROP_RULE_TEMPLATE = "create_initial_drop_rule.j2" CREATE_SECONDARY_DROP_RULE_TEMPLATE = "create_secondary_drop_rule.j2" @@ -75,8 +76,8 @@ DST_IP_BLOCKED = "103.23.3.1" DST_IPV6_BLOCKED = "103:23:3:1::1" -MAX_IP_RULE_PRIORITY = 9900 -MAX_DROP_RULE_PRIORITY = 9000 +MAX_IP_RULE_PRIORITY = 800 +MAX_DROP_RULE_PRIORITY = 200 # DHCP Constants @@ -160,7 +161,6 @@ def setup(rand_selected_dut, rand_unselected_dut, tbinfo, vlan_name, topo_scenar 't0-isolated-d96u32s2', 't0-isolated-d32u32s2', 't0-isolated-d16u16s2', - 't0-isolated-v6-d32u32s2', 't1-isolated-d224u8', 't1-isolated-d128', 't1-isolated-d56u2', @@ -185,13 +185,13 @@ def setup(rand_selected_dut, rand_unselected_dut, tbinfo, vlan_name, topo_scenar upstream_port_ids.append(port_id) else: downstream_ports = list(mg_facts["minigraph_vlans"][vlan_name]["members"]) - # Put all upstream ports into dst_ports + # Put all portchannel members into dst_ports upstream_port_ids = [] upstream_ports = [] - for port in mg_facts['minigraph_ports']: - if port not in downstream_ports and port in mg_facts['minigraph_ptf_indices']: - upstream_port_ids.append(mg_facts['minigraph_ptf_indices'][port]) - upstream_ports.append(port) + for _, v in mg_facts['minigraph_portchannels'].items(): + for member in v['members']: + upstream_port_ids.append(mg_facts['minigraph_ptf_indices'][member]) + upstream_ports.append(member) for port in downstream_ports: if port in mg_facts['minigraph_port_name_to_alias_map']: @@ -336,6 +336,7 @@ def intfs_for_test(duthosts, enum_rand_one_per_hwsku_frontend_hostname, enum_fro ports = list(sorted(external_ports, key=lambda item: int(item.replace('Ethernet', '')))) is_storage_backend = 'backend' in tbinfo['topo']['name'] + is_isolated_topo = 'isolated' in tbinfo['topo']['name'] if tbinfo['topo']['type'] == 't0': if is_storage_backend: @@ -343,6 +344,12 @@ def intfs_for_test(duthosts, enum_rand_one_per_hwsku_frontend_hostname, enum_fro intfs_to_t1 = [_['attachto'].split(constants.VLAN_SUB_INTERFACE_SEPARATOR)[0] for _ in vlan_sub_intfs] ports_for_test = [_ for _ in ports if _ not in intfs_to_t1] + intf1 = ports_for_test[0] + elif is_isolated_topo: + upstream_intfs = mg_facts['minigraph_interfaces'] + intfs_to_t1 = [_intf['attachto'] for _intf in upstream_intfs] + ports_for_test = [_ for _ in ports if _ not in intfs_to_t1] + intf1 = ports_for_test[0] else: if 'PORTCHANNEL_MEMBER' in config_facts: @@ -646,9 +653,9 @@ def generate_packets(setup, tbinfo, dst_ip=DST_IP_FORWARDED_ORIGINAL, dst_ipv6=D packets = {} if not is_ipv6_only_topology(tbinfo): packets["IPV4"] = testutils.simple_tcpv6_packet(eth_dst=setup["router_mac"], - ip_src=IP_SOURCE, - ip_dst=dst_ip, - ip_ttl=64) + ip_src=IP_SOURCE, + ip_dst=dst_ip, + ip_ttl=64) packets["IPV6"] = testutils.simple_tcpv6_packet(eth_dst=setup["router_mac"], ipv6_src=IPV6_SOURCE, @@ -734,8 +741,8 @@ def dynamic_acl_create_forward_rules(duthost, setup): outputs = format_and_apply_template(duthost, CREATE_FORWARD_RULES_TEMPLATE, extra_vars, setup) - expected_rule_1_content = ["DYNAMIC_ACL_TABLE", "RULE_1", "9999", "FORWARD", "DST_IP: " + IPV4_SUBNET, "Active"] - expected_rule_2_content = ["DYNAMIC_ACL_TABLE", "RULE_2", "9998", "FORWARD", "DST_IPV6: " + IPV6_SUBNET, "Active"] + expected_rule_1_content = ["DYNAMIC_ACL_TABLE", "RULE_1", "900", "FORWARD", "DST_IP: " + IPV4_SUBNET, "Active"] + expected_rule_2_content = ["DYNAMIC_ACL_TABLE", "RULE_2", "899", "FORWARD", "DST_IPV6: " + IPV6_SUBNET, "Active"] for output in outputs: expect_op_success(duthost, output) @@ -744,6 +751,46 @@ def dynamic_acl_create_forward_rules(duthost, setup): expect_acl_rule_match(duthost, "RULE_2", expected_rule_2_content, setup) +def dynamic_acl_create_forward_rules_same_priority(duthost, setup): + """Create forward ACL rules with same priority""" + + IPV4_SUBNET = DST_IP_FORWARDED_ORIGINAL + "/32" + IPV4_SUBNET_2 = increment_ipv4_addr(DST_IP_FORWARDED_ORIGINAL, 1) + "/32" + IPV4_SUBNET_3 = increment_ipv4_addr(DST_IP_FORWARDED_ORIGINAL, 2) + "/32" + + IPV6_SUBNET = DST_IPV6_FORWARDED_ORIGINAL + "/128" + IPV6_SUBNET_2 = increment_ipv6_addr(DST_IPV6_FORWARDED_ORIGINAL, 1) + "/128" + IPV6_SUBNET_3 = increment_ipv6_addr(DST_IPV6_FORWARDED_ORIGINAL, 2) + "/128" + + extra_vars = { + 'ipv4_subnet': IPV4_SUBNET, + 'ipv4_subnet_2': IPV4_SUBNET_2, + 'ipv4_subnet_3': IPV4_SUBNET_3, + 'ipv6_subnet': IPV6_SUBNET, + 'ipv6_subnet_2': IPV6_SUBNET_2, + 'ipv6_subnet_3': IPV6_SUBNET_3 + } + + outputs = format_and_apply_template(duthost, CREATE_FORWARD_RULES_SAME_PRIORITY_TEMPLATE, extra_vars, setup) + + expected_rule_1_content = ["DYNAMIC_ACL_TABLE", "RULE_1", "900", "FORWARD", "DST_IP: " + IPV4_SUBNET, "Active"] + expected_rule_2_content = ["DYNAMIC_ACL_TABLE", "RULE_2", "900", "FORWARD", "DST_IPV6: " + IPV6_SUBNET, "Active"] + expected_rule_4_content = ["DYNAMIC_ACL_TABLE", "RULE_4", "900", "FORWARD", "DST_IP: " + IPV4_SUBNET_2, "Active"] + expected_rule_5_content = ["DYNAMIC_ACL_TABLE", "RULE_5", "900", "FORWARD", "DST_IPV6: " + IPV6_SUBNET_2, "Active"] + expected_rule_6_content = ["DYNAMIC_ACL_TABLE", "RULE_6", "900", "FORWARD", "DST_IP: " + IPV4_SUBNET_3, "Active"] + expected_rule_7_content = ["DYNAMIC_ACL_TABLE", "RULE_7", "900", "FORWARD", "DST_IPV6: " + IPV6_SUBNET_3, "Active"] + + for output in outputs: + expect_op_success(duthost, output) + + expect_acl_rule_match(duthost, "RULE_1", expected_rule_1_content, setup) + expect_acl_rule_match(duthost, "RULE_2", expected_rule_2_content, setup) + expect_acl_rule_match(duthost, "RULE_4", expected_rule_4_content, setup) + expect_acl_rule_match(duthost, "RULE_5", expected_rule_5_content, setup) + expect_acl_rule_match(duthost, "RULE_6", expected_rule_6_content, setup) + expect_acl_rule_match(duthost, "RULE_7", expected_rule_7_content, setup) + + def dynamic_acl_create_secondary_drop_rule(duthost, setup, blocked_port_name=None): """Create a drop rule in the format required when an ACL table has rules in it already""" @@ -757,7 +804,7 @@ def dynamic_acl_create_secondary_drop_rule(duthost, setup, blocked_port_name=Non expected_rule_content = ["DYNAMIC_ACL_TABLE", "RULE_3", - "9995", + "896", "DROP", "IN_PORTS: " + blocked_name, "Active"] @@ -779,7 +826,7 @@ def dynamic_acl_create_drop_rule_initial(duthost, setup): expected_rule_content = ["DYNAMIC_ACL_TABLE", "RULE_3", - "9997", + "898", "DROP", "IN_PORTS: " + setup["blocked_src_port_name"], "Active"] @@ -807,19 +854,19 @@ def dynamic_acl_create_three_drop_rules(duthost, setup): expected_rule_3_content = ["DYNAMIC_ACL_TABLE", "RULE_3", - "9997", + "898", "DROP", "IN_PORTS: " + extra_vars['blocked_port_1'], "Active"] expected_rule_4_content = ["DYNAMIC_ACL_TABLE", "RULE_4", - "9996", + "897", "DROP", "IN_PORTS: " + extra_vars['blocked_port_2'], "Active"] expected_rule_5_content = ["DYNAMIC_ACL_TABLE", "RULE_5", - "9995", + "896", "DROP", "IN_PORTS: " + extra_vars['blocked_port_3'], "Active"] @@ -840,7 +887,7 @@ def dynamic_acl_create_arp_forward_rule(duthost, setup): for output in outputs: expect_op_success(duthost, output) - expected_rule_content = ["DYNAMIC_ACL_TABLE", "ARP_RULE", "9997", "FORWARD", "ETHER_TYPE: 0x0806", "Active"] + expected_rule_content = ["DYNAMIC_ACL_TABLE", "ARP_RULE", "898", "FORWARD", "ETHER_TYPE: 0x0806", "Active"] expect_acl_rule_match(duthost, "ARP_RULE", expected_rule_content, setup) @@ -853,7 +900,7 @@ def dynamic_acl_create_ndp_forward_rule(duthost, setup): for output in outputs: expect_op_success(duthost, output) - expected_rule_content = ["DYNAMIC_ACL_TABLE", "NDP_RULE", "9996", "FORWARD", "IP_PROTOCOL: 58", "Active"] + expected_rule_content = ["DYNAMIC_ACL_TABLE", "NDP_RULE", "897", "FORWARD", "IP_PROTOCOL: 58", "Active"] expect_acl_rule_match(duthost, "NDP_RULE", expected_rule_content, setup) @@ -867,7 +914,7 @@ def dynamic_acl_create_dhcp_forward_rule(duthost, setup): expect_op_success(duthost, output) expected_v6_rule_content = ["DYNAMIC_ACL_TABLE", - "DHCPV6_RULE", "9998", + "DHCPV6_RULE", "899", "FORWARD", "IP_PROTOCOL: 17", "L4_DST_PORT_RANGE: 547-548", @@ -875,7 +922,7 @@ def dynamic_acl_create_dhcp_forward_rule(duthost, setup): "Active"] expected_rule_content = ["DYNAMIC_ACL_TABLE", - "DHCP_RULE", "9999", + "DHCP_RULE", "900", "FORWARD", "IP_PROTOCOL: 17", "L4_DST_PORT: 67", @@ -948,13 +995,13 @@ def dynamic_acl_replace_rules(duthost, setup): expected_rule_1_content = ["DYNAMIC_ACL_TABLE", "RULE_1", - "9999", + "900", "FORWARD", "DST_IP: " + REPLACEMENT_IPV4_SUBNET, "Active"] expected_rule_2_content = ["DYNAMIC_ACL_TABLE", "RULE_2", - "9998", + "899", "FORWARD", "DST_IPV6: " + REPLACEMENT_IPV6_SUBNET, "Active"] @@ -1106,7 +1153,7 @@ def test_gcu_acl_arp_rule_creation(rand_selected_dut, setup, dynamic_acl_create_table, prepare_ptf_intf_and_ip, - toggle_all_simulator_ports_to_rand_selected_tor, tbinfo): # noqa F811 + toggle_all_simulator_ports_to_rand_selected_tor, tbinfo): # noqa: F811 """Test that we can create a blanket ARP/NDP packet forwarding rule with GCU, and that ARP/NDP packets are correctly forwarded while all others are dropped.""" @@ -1158,8 +1205,8 @@ def test_gcu_acl_dhcp_rule_creation(rand_selected_dut, ptfadapter, setup, dynamic_acl_create_table, - toggle_all_simulator_ports_to_rand_selected_tor, # noqa F811 - setup_standby_ports_on_rand_unselected_tor, tbinfo): # noqa F811 + toggle_all_simulator_ports_to_rand_selected_tor, # noqa: F811 + setup_standby_ports_on_rand_unselected_tor, tbinfo): # noqa: F811 """Verify that DHCP and DHCPv6 forwarding rules can be created, and that dhcp packets are properly forwarded whereas others are dropped""" @@ -1182,7 +1229,7 @@ def test_gcu_acl_drop_rule_creation(rand_selected_dut, ptfadapter, setup, dynamic_acl_create_table, - toggle_all_simulator_ports_to_rand_selected_tor, tbinfo): # noqa F811 + toggle_all_simulator_ports_to_rand_selected_tor, tbinfo): # noqa: F811 """Test that we can create a drop rule via GCU, and that once this drop rule is in place packets that match the drop rule are dropped and packets that do not match the drop rule are forwarded""" @@ -1204,7 +1251,7 @@ def test_gcu_acl_drop_rule_removal(rand_selected_dut, ptfadapter, setup, dynamic_acl_create_table, - toggle_all_simulator_ports_to_rand_selected_tor, tbinfo): # noqa F811 + toggle_all_simulator_ports_to_rand_selected_tor, tbinfo): # noqa: F811 """Test that once a drop rule is removed, packets that were previously being dropped are now forwarded""" dynamic_acl_create_three_drop_rules(rand_selected_dut, setup) @@ -1222,7 +1269,7 @@ def test_gcu_acl_forward_rule_priority_respected(rand_selected_dut, ptfadapter, setup, dynamic_acl_create_table, - toggle_all_simulator_ports_to_rand_selected_tor, tbinfo): # noqa F811 + toggle_all_simulator_ports_to_rand_selected_tor, tbinfo): # noqa: F811 """Test that forward rules and drop rules can be created at the same time, with the forward rules having higher priority than drop. Then, perform a traffic test to confirm that packets that match both the forward and drop rules are correctly forwarded, as the forwarding rules have higher priority""" @@ -1237,12 +1284,40 @@ def test_gcu_acl_forward_rule_priority_respected(rand_selected_dut, packets_dropped=True) +def test_gcu_acl_forward_rule_same_priority(rand_selected_dut, + rand_unselected_dut, + ptfadapter, + setup, + dynamic_acl_create_table, + toggle_all_simulator_ports_to_rand_selected_tor, tbinfo): # noqa: F811 + """Test that forward rules can have the exact same priority and still all be applied correctly + Then, perform a traffic test to confirm that packets that match both the forward + and drop rules are correctly forwarded, as the forwarding rules have higher priority""" + + dynamic_acl_create_forward_rules_same_priority(rand_selected_dut, setup) + dynamic_acl_create_secondary_drop_rule(rand_selected_dut, setup) + + dynamic_acl_verify_packets(setup, ptfadapter, packets=generate_packets(setup, tbinfo), + packets_dropped=False) + dynamic_acl_verify_packets(setup, ptfadapter, packets=generate_packets(setup, tbinfo, + increment_ipv4_addr(DST_IP_FORWARDED_ORIGINAL, 1), + increment_ipv6_addr(DST_IPV6_FORWARDED_ORIGINAL, 1)), + packets_dropped=False) + dynamic_acl_verify_packets(setup, ptfadapter, packets=generate_packets(setup, tbinfo, + increment_ipv4_addr(DST_IP_FORWARDED_ORIGINAL, 2), + increment_ipv6_addr(DST_IPV6_FORWARDED_ORIGINAL, 2)), + packets_dropped=False) + dynamic_acl_verify_packets(setup, ptfadapter, + packets=generate_packets(setup, tbinfo,DST_IP_BLOCKED, DST_IPV6_BLOCKED), + packets_dropped=True) + + def test_gcu_acl_forward_rule_replacement(rand_selected_dut, rand_unselected_dut, ptfadapter, setup, dynamic_acl_create_table, - toggle_all_simulator_ports_to_rand_selected_tor, tbinfo): # noqa F811 + toggle_all_simulator_ports_to_rand_selected_tor, tbinfo): # noqa: F811 """Test that forward rules can be created, and then afterwards can have their match pattern updated to a new value. Confirm that packets sent that match this new value are correctly forwarded, and that packets that are sent that match the old, replaced value are correctly dropped.""" @@ -1267,7 +1342,7 @@ def test_gcu_acl_forward_rule_removal(rand_selected_dut, setup, ip_type, dynamic_acl_create_table, - toggle_all_simulator_ports_to_rand_selected_tor, tbinfo): # noqa F811 + toggle_all_simulator_ports_to_rand_selected_tor, tbinfo): # noqa: F811 """Test that if a forward rule is created, and then removed, that packets associated with that rule are properly no longer forwarded, and packets associated with the remaining rule are forwarded""" @@ -1289,7 +1364,7 @@ def test_gcu_acl_forward_rule_removal(rand_selected_dut, def test_gcu_acl_scale_rules(rand_selected_dut, rand_unselected_dut, ptfadapter, setup, dynamic_acl_create_table, - toggle_all_simulator_ports_to_rand_selected_tor, tbinfo): # noqa F811 + toggle_all_simulator_ports_to_rand_selected_tor, tbinfo): # noqa:F811 """Perform a scale test, creating 150 forward rules with top priority, and then creating a drop rule for every single VLAN port on our device. Select any one of our blocked ports, as well as the ips for two of our forward rules, @@ -1318,14 +1393,14 @@ def test_gcu_acl_scale_rules(rand_selected_dut, rand_unselected_dut, ptfadapter, def test_gcu_acl_nonexistent_rule_replacement(rand_selected_dut, - toggle_all_simulator_ports_to_rand_selected_tor, # noqa F811 + toggle_all_simulator_ports_to_rand_selected_tor, # noqa:F811 setup): """Confirm that replacing a nonexistent rule results in operation failure""" dynamic_acl_replace_nonexistent_rule(rand_selected_dut, setup) def test_gcu_acl_nonexistent_table_removal(rand_selected_dut, - toggle_all_simulator_ports_to_rand_selected_tor, # noqa F811 + toggle_all_simulator_ports_to_rand_selected_tor, # noqa:F811 setup): """Confirm that removing a nonexistent table results in operation failure""" dynamic_acl_remove_nonexistent_table(rand_selected_dut, setup) From 51f6c838b80881b0c3f7248ced133d2b4fbb2369 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Mon, 15 Sep 2025 16:44:44 +0300 Subject: [PATCH 50/55] Update test_dynamic_acl.py --- tests/generic_config_updater/test_dynamic_acl.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/generic_config_updater/test_dynamic_acl.py b/tests/generic_config_updater/test_dynamic_acl.py index 71b52ec65ab..ee3a789e7ce 100644 --- a/tests/generic_config_updater/test_dynamic_acl.py +++ b/tests/generic_config_updater/test_dynamic_acl.py @@ -653,9 +653,9 @@ def generate_packets(setup, tbinfo, dst_ip=DST_IP_FORWARDED_ORIGINAL, dst_ipv6=D packets = {} if not is_ipv6_only_topology(tbinfo): packets["IPV4"] = testutils.simple_tcpv6_packet(eth_dst=setup["router_mac"], - ip_src=IP_SOURCE, - ip_dst=dst_ip, - ip_ttl=64) + ip_src=IP_SOURCE, + ip_dst=dst_ip, + ip_ttl=64) packets["IPV6"] = testutils.simple_tcpv6_packet(eth_dst=setup["router_mac"], ipv6_src=IPV6_SOURCE, @@ -1308,7 +1308,7 @@ def test_gcu_acl_forward_rule_same_priority(rand_selected_dut, increment_ipv6_addr(DST_IPV6_FORWARDED_ORIGINAL, 2)), packets_dropped=False) dynamic_acl_verify_packets(setup, ptfadapter, - packets=generate_packets(setup, tbinfo,DST_IP_BLOCKED, DST_IPV6_BLOCKED), + packets=generate_packets(setup, tbinfo, DST_IP_BLOCKED, DST_IPV6_BLOCKED), packets_dropped=True) From c34e143d74377c213e572467301c2e4c970f47eb Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Tue, 16 Sep 2025 09:51:30 +0300 Subject: [PATCH 51/55] Update test_dynamic_acl.py --- tests/generic_config_updater/test_dynamic_acl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/generic_config_updater/test_dynamic_acl.py b/tests/generic_config_updater/test_dynamic_acl.py index ee3a789e7ce..1eba83e03f0 100644 --- a/tests/generic_config_updater/test_dynamic_acl.py +++ b/tests/generic_config_updater/test_dynamic_acl.py @@ -652,7 +652,7 @@ def generate_packets(setup, tbinfo, dst_ip=DST_IP_FORWARDED_ORIGINAL, dst_ipv6=D packets = {} if not is_ipv6_only_topology(tbinfo): - packets["IPV4"] = testutils.simple_tcpv6_packet(eth_dst=setup["router_mac"], + packets["IPV4"] = testutils.simple_tcp_packet(eth_dst=setup["router_mac"], ip_src=IP_SOURCE, ip_dst=dst_ip, ip_ttl=64) From 582c9a8383b3b6776ee29988d163ab2e08fda224 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Tue, 16 Sep 2025 10:09:31 +0300 Subject: [PATCH 52/55] Update test_dynamic_acl.py --- tests/generic_config_updater/test_dynamic_acl.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/generic_config_updater/test_dynamic_acl.py b/tests/generic_config_updater/test_dynamic_acl.py index 1eba83e03f0..6283c80b1c9 100644 --- a/tests/generic_config_updater/test_dynamic_acl.py +++ b/tests/generic_config_updater/test_dynamic_acl.py @@ -653,9 +653,9 @@ def generate_packets(setup, tbinfo, dst_ip=DST_IP_FORWARDED_ORIGINAL, dst_ipv6=D packets = {} if not is_ipv6_only_topology(tbinfo): packets["IPV4"] = testutils.simple_tcp_packet(eth_dst=setup["router_mac"], - ip_src=IP_SOURCE, - ip_dst=dst_ip, - ip_ttl=64) + ip_src=IP_SOURCE, + ip_dst=dst_ip, + ip_ttl=64) packets["IPV6"] = testutils.simple_tcpv6_packet(eth_dst=setup["router_mac"], ipv6_src=IPV6_SOURCE, From 32fe781866ac457f0569efccb21e6892723a6266 Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Sun, 28 Sep 2025 10:09:43 +0300 Subject: [PATCH 53/55] Update tests_mark_conditions.yaml --- .../common/plugins/conditional_mark/tests_mark_conditions.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml b/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml index d6781082009..fea5d2d9529 100644 --- a/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml +++ b/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml @@ -2089,7 +2089,7 @@ generic_config_updater/test_dynamic_acl.py::test_gcu_acl_dhcp_rule_creation: - "'t0-isolated' in topo_name" generic_config_updater/test_dynamic_acl.py::test_gcu_acl_forward_rule_removal: - skip: + xfail: reason: "skip for IPv6-only topologies" conditions: - "'-v6-' in topo_name" From 384de973d76ffaa462c49b71be9d1ac072cef41c Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Sun, 28 Sep 2025 13:23:20 +0300 Subject: [PATCH 54/55] Update tests_mark_conditions.yaml From f05a8e42ddf2da72ab44d551d4b898f37630014b Mon Sep 17 00:00:00 2001 From: gshemesh2 Date: Thu, 9 Oct 2025 08:59:09 +0300 Subject: [PATCH 55/55] Update test_dynamic_acl.py --- tests/generic_config_updater/test_dynamic_acl.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/tests/generic_config_updater/test_dynamic_acl.py b/tests/generic_config_updater/test_dynamic_acl.py index 6283c80b1c9..a864b4afa84 100644 --- a/tests/generic_config_updater/test_dynamic_acl.py +++ b/tests/generic_config_updater/test_dynamic_acl.py @@ -1159,16 +1159,7 @@ def test_gcu_acl_arp_rule_creation(rand_selected_dut, ip_address_for_test, _, ptf_intf_index, port_name = prepare_ptf_intf_and_ip - is_ipv4_test = False - try: - is_ipv4_test = type(ip_network(ip_address_for_test, strict=False)) is IPv4Network - except ValueError as err: - if is_ipv6_only_topology(tbinfo): - pytest.skip("IPv6 only topology, skipping test") - else: - raise err - if is_ipv4_test and is_ipv6_only_topology(tbinfo): - pytest.skip("IPv4 test in IPv6 only topology, skipping test") + is_ipv4_test = type(ip_network(ip_address_for_test, strict=False)) is IPv4Network if is_ipv4_test: show_cmd = "show arp"