From bc5184015efcae84ea64afcfada9a3688d2bb303 Mon Sep 17 00:00:00 2001 From: Judy Joseph Date: Fri, 21 Feb 2025 02:55:34 +0000 Subject: [PATCH 01/24] Fixes found during nightly run with macsec enabled topology --- ansible/library/get_macsec_profile.py | 32 ++++++++++++++++--- ansible/roles/eos/tasks/ceos_config.yml | 1 + ansible/roles/test/files/ptftests/fib_test.py | 2 +- ansible/roles/test/files/ptftests/macsec.py | 10 +++--- .../test/files/ptftests/py3/IP_decap_test.py | 2 +- .../test/files/ptftests/py3/hash_test.py | 1 + tests/common/macsec/__init__.py | 10 +++++- tests/common/macsec/macsec_helper.py | 10 +++--- 8 files changed, 51 insertions(+), 17 deletions(-) diff --git a/ansible/library/get_macsec_profile.py b/ansible/library/get_macsec_profile.py index 65b0cdb5a92..143461bd137 100644 --- a/ansible/library/get_macsec_profile.py +++ b/ansible/library/get_macsec_profile.py @@ -4,8 +4,24 @@ import json from ansible.module_utils.basic import AnsibleModule +def convert_to_eos(cipher_name): + # Set the cipher suite as 256 xpn by default + eos_cipher_name = 'aes256-gcm-xpn' -def get_macsec_profile(module, macsec_profile): + if cipher_name == 'GCM-AES-XPN-256': + eos_cipher_name = 'aes256-gcm-xpn' + elif cipher_name == 'GCM-AES-128': + eos_cipher_name = 'aes128-gcm' + elif cipher_name == 'GCM-AES-256': + eos_cipher_name = 'aes256-gcm' + elif cipher_name == 'GCM-AES-XPN-128': + eos_cipher_name = 'aes128-gcm-xpn' + + return eos_cipher_name + + +# This API support EoS based templates now +def get_macsec_profile(module, macsec_profile, vm_type): with open('/tmp/profile.json') as f: macsec_profiles = json.load(f) @@ -13,15 +29,23 @@ def get_macsec_profile(module, macsec_profile): if profile: profile['macsec_profile'] = macsec_profile + # Currently handling ceos, add more cases for vsonic etc + if vm_type == 'ceos': + # Get the cipher suite in eos terminology + eos_cipher_suite_name = convert_to_eos(profile['cipher_suite']) + profile['cipher_suite'] = eos_cipher_suite_name + return profile def main(): - module = AnsibleModule(argument_spec=dict(macsec_profile=dict(required=True, type='str'))) + module = AnsibleModule(argument_spec=dict( + macsec_profile=dict(required=True, type='str'), + vm_type=dict(required=True, type='str'))) macsec_profile = module.params['macsec_profile'] - module.exit_json(profile=get_macsec_profile(module, macsec_profile), changed=False) - + vm_type = module.params['vm_type'] + module.exit_json(profile=get_macsec_profile(module, macsec_profile, vm_type), changed=False) if __name__ == "__main__": main() diff --git a/ansible/roles/eos/tasks/ceos_config.yml b/ansible/roles/eos/tasks/ceos_config.yml index 2c55894ffb6..faf748ebeca 100644 --- a/ansible/roles/eos/tasks/ceos_config.yml +++ b/ansible/roles/eos/tasks/ceos_config.yml @@ -42,6 +42,7 @@ - name: Get the macsec profile data from profile_name get_macsec_profile: macsec_profile: "{{ macsec_profile }}" + vm_type: "{{ vm_type }}" register: profile_raw become: true when: "'t2' == base_topo and enable_macsec is defined" diff --git a/ansible/roles/test/files/ptftests/fib_test.py b/ansible/roles/test/files/ptftests/fib_test.py index 94fc40beec7..c18af9a787d 100644 --- a/ansible/roles/test/files/ptftests/fib_test.py +++ b/ansible/roles/test/files/ptftests/fib_test.py @@ -25,7 +25,7 @@ import json import itertools import fib - +import macsec import ptf import ptf.packet as scapy diff --git a/ansible/roles/test/files/ptftests/macsec.py b/ansible/roles/test/files/ptftests/macsec.py index f81f7dd2f06..89b1798d640 100644 --- a/ansible/roles/test/files/ptftests/macsec.py +++ b/ansible/roles/test/files/ptftests/macsec.py @@ -18,15 +18,15 @@ MACSEC_INFOS = {} -def macsec_send(test, port_id, pkt, count=1): +def macsec_send(test, port_number, pkt, count=1): # Check if the port is macsec enabled, if so send the macsec encap/encrypted frame global MACSEC_GLOBAL_PN_OFFSET global MACSEC_GLOBAL_PN_INCR - device, port_number = ptf.testutils.port_to_tuple(port_id) + device, port_id = ptf.testutils.port_to_tuple(port_number) if port_number in MACSEC_INFOS and MACSEC_INFOS[port_number]: encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = \ - MACSEC_INFOS[port_number] + MACSEC_INFOS[port_id] # Increment the PN by an offset so that the macsec frames are not late on DUT pn += MACSEC_GLOBAL_PN_OFFSET @@ -34,10 +34,10 @@ def macsec_send(test, port_id, pkt, count=1): macsec_pkt = encap_macsec_pkt(pkt, peer_sci, peer_an, sak, encrypt, send_sci, pn, xpn_en, peer_ssci, salt) # send the packet - __origin_send_packet(test, port_id, macsec_pkt, count) + __origin_send_packet(test, port_number, macsec_pkt, count) else: # send the packet - __origin_send_packet(test, port_id, pkt, count) + __origin_send_packet(test, port_number, pkt, count) def encap_macsec_pkt(macsec_pkt, sci, an, sak, encrypt, send_sci, pn, xpn_en=False, ssci=None, salt=None): diff --git a/ansible/roles/test/files/ptftests/py3/IP_decap_test.py b/ansible/roles/test/files/ptftests/py3/IP_decap_test.py index 19532d4dd55..8824670005d 100644 --- a/ansible/roles/test/files/ptftests/py3/IP_decap_test.py +++ b/ansible/roles/test/files/ptftests/py3/IP_decap_test.py @@ -50,7 +50,7 @@ import itertools import fib import time - +import macsec import ptf import ptf.packet as scapy import ptf.testutils as testutils diff --git a/ansible/roles/test/files/ptftests/py3/hash_test.py b/ansible/roles/test/files/ptftests/py3/hash_test.py index fe463c6e24e..16ab98f17e7 100644 --- a/ansible/roles/test/files/ptftests/py3/hash_test.py +++ b/ansible/roles/test/files/ptftests/py3/hash_test.py @@ -32,6 +32,7 @@ import fib import lpm +import macsec class HashTest(BaseTest): diff --git a/tests/common/macsec/__init__.py b/tests/common/macsec/__init__.py index 5e414a43ab3..8d336273ec5 100644 --- a/tests/common/macsec/__init__.py +++ b/tests/common/macsec/__init__.py @@ -16,6 +16,9 @@ from .macsec_config_helper import disable_macsec_feature from .macsec_config_helper import setup_macsec_configuration from .macsec_config_helper import cleanup_macsec_configuration +from .macsec_config_helper import get_macsec_enable_status, get_macsec_profile +from .macsec_helper import load_all_macsec_info + # flake8: noqa: F401 from tests.common.plugins.sanity_check import sanity_check @@ -78,6 +81,11 @@ def macsec_feature(self, start_macsec_service, stop_macsec_service): yield stop_macsec_service() + @pytest.fixture(scope="module", autouse=True) + def load_macsec_info(self, request, macsec_duthost, ctrl_links, tbinfo): + if get_macsec_enable_status(macsec_duthost) and get_macsec_profile(macsec_duthost): + load_all_macsec_info(macsec_duthost, ctrl_links, tbinfo) + @pytest.fixture(scope="module") def startup_macsec(self, request, macsec_duthost, ctrl_links, macsec_profile, tbinfo): topo_name = tbinfo['topo']['name'] @@ -107,7 +115,7 @@ def __shutdown_macsec(): cleanup_macsec_configuration(macsec_duthost, ctrl_links, profile['name']) return __shutdown_macsec - @pytest.fixture(scope="module", autouse=True) + @pytest.fixture(scope="module") def macsec_setup(self, startup_macsec, shutdown_macsec, macsec_feature): ''' setup macsec links diff --git a/tests/common/macsec/macsec_helper.py b/tests/common/macsec/macsec_helper.py index c7caf89fb2d..22e1edb0cbf 100644 --- a/tests/common/macsec/macsec_helper.py +++ b/tests/common/macsec/macsec_helper.py @@ -475,14 +475,14 @@ def load_all_macsec_info(duthost, ctrl_links, tbinfo): MACSEC_INFO[ptf_id] = get_macsec_attr(duthost, port) -def macsec_send(test, port_id, pkt, count=1): +def macsec_send(test, port_number, pkt, count=1): global MACSEC_GLOBAL_PN_OFFSET global MACSEC_GLOBAL_PN_INCR # Check if the port is macsec enabled, if so send the macsec encap/encrypted frame - device, port_number = testutils.port_to_tuple(port_id) + device, port_id = testutils.port_to_tuple(port_number) if port_number in MACSEC_INFO and MACSEC_INFO[port_number]: - encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = MACSEC_INFO[port_number] + encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = MACSEC_INFO[port_id] # Increment the PN in packet so that the packet s not marked as late in DUT pn += MACSEC_GLOBAL_PN_OFFSET @@ -490,10 +490,10 @@ def macsec_send(test, port_id, pkt, count=1): macsec_pkt = encap_macsec_pkt(pkt, peer_sci, peer_an, sak, encrypt, send_sci, pn, xpn_en, peer_ssci, salt) # send the packet - __origin_send_packet(test, port_id, macsec_pkt, count) + __origin_send_packet(test, port_number, macsec_pkt, count) else: # send the packet - __origin_send_packet(test, port_id, pkt, count) + __origin_send_packet(test, port_number, pkt, count) def macsec_dp_poll(test, device_number=0, port_number=None, timeout=None, exp_pkt=None): From a66f663b399e25b2639250e6f65d4c8e1b065d6d Mon Sep 17 00:00:00 2001 From: Judy Joseph Date: Sat, 22 Feb 2025 20:55:12 +0000 Subject: [PATCH 02/24] Ffix for copp pfc voq ptftests --- ansible/roles/test/files/ptftests/py3/copp_tests.py | 2 +- ansible/roles/test/files/ptftests/py3/pfc_wd.py | 1 + ansible/roles/test/files/ptftests/py3/voq.py | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ansible/roles/test/files/ptftests/py3/copp_tests.py b/ansible/roles/test/files/ptftests/py3/copp_tests.py index 92211065432..0ca5c4ca298 100644 --- a/ansible/roles/test/files/ptftests/py3/copp_tests.py +++ b/ansible/roles/test/files/ptftests/py3/copp_tests.py @@ -41,7 +41,7 @@ from ptf.base_tests import BaseTest from ptf import config - +import macsec class ControlPlaneBaseTest(BaseTest): MAX_PORTS = 128 diff --git a/ansible/roles/test/files/ptftests/py3/pfc_wd.py b/ansible/roles/test/files/ptftests/py3/pfc_wd.py index 575993b41d1..10eb25c1256 100644 --- a/ansible/roles/test/files/ptftests/py3/pfc_wd.py +++ b/ansible/roles/test/files/ptftests/py3/pfc_wd.py @@ -10,6 +10,7 @@ from ptf.base_tests import BaseTest from ptf.mask import Mask from ptf.testutils import test_params_get, simple_tcp_packet, send_packet, verify_no_packet_any, verify_packet_any_port +import macsec class PfcWdTest(BaseTest): diff --git a/ansible/roles/test/files/ptftests/py3/voq.py b/ansible/roles/test/files/ptftests/py3/voq.py index 3f10842ff5d..98ad62c7c95 100644 --- a/ansible/roles/test/files/ptftests/py3/voq.py +++ b/ansible/roles/test/files/ptftests/py3/voq.py @@ -11,6 +11,7 @@ from scapy.all import Ether from scapy.layers.l2 import Dot1Q from scapy.layers.inet6 import IPv6, ICMPv6ND_NA, ICMPv6NDOptDstLLAddr +import macsec import logging From f8ea997a68d079ae1811afcdfaabd1accf4b3ab1 Mon Sep 17 00:00:00 2001 From: Judy Joseph Date: Sat, 22 Feb 2025 22:10:35 +0000 Subject: [PATCH 03/24] Fix the port_number to port_id things again --- ansible/roles/test/files/ptftests/macsec.py | 2 +- tests/common/macsec/macsec_helper.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ansible/roles/test/files/ptftests/macsec.py b/ansible/roles/test/files/ptftests/macsec.py index 89b1798d640..e52d05137c4 100644 --- a/ansible/roles/test/files/ptftests/macsec.py +++ b/ansible/roles/test/files/ptftests/macsec.py @@ -24,7 +24,7 @@ def macsec_send(test, port_number, pkt, count=1): global MACSEC_GLOBAL_PN_INCR device, port_id = ptf.testutils.port_to_tuple(port_number) - if port_number in MACSEC_INFOS and MACSEC_INFOS[port_number]: + if port_id in MACSEC_INFOS and MACSEC_INFOS[port_id]: encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = \ MACSEC_INFOS[port_id] diff --git a/tests/common/macsec/macsec_helper.py b/tests/common/macsec/macsec_helper.py index 22e1edb0cbf..e8850c243bc 100644 --- a/tests/common/macsec/macsec_helper.py +++ b/tests/common/macsec/macsec_helper.py @@ -481,7 +481,7 @@ def macsec_send(test, port_number, pkt, count=1): # Check if the port is macsec enabled, if so send the macsec encap/encrypted frame device, port_id = testutils.port_to_tuple(port_number) - if port_number in MACSEC_INFO and MACSEC_INFO[port_number]: + if port_id in MACSEC_INFO and MACSEC_INFO[port_id]: encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = MACSEC_INFO[port_id] # Increment the PN in packet so that the packet s not marked as late in DUT From 1cbadca924297eaab3d7e76ce9257d5e31ab9347 Mon Sep 17 00:00:00 2001 From: Judy Joseph Date: Thu, 27 Feb 2025 03:03:34 +0000 Subject: [PATCH 04/24] Fixes for acl tests, changes in config reload to pass override option if macsec is anebled, introduce the force_reload option if we need to reload macsec config for a port --- tests/acl/test_acl.py | 8 +++++++- tests/common/config_reload.py | 8 +++++++- tests/common/macsec/macsec_helper.py | 9 +++++++++ tests/conftest.py | 9 +++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/tests/acl/test_acl.py b/tests/acl/test_acl.py index 4b5e05688af..375ea454d8b 100644 --- a/tests/acl/test_acl.py +++ b/tests/acl/test_acl.py @@ -261,7 +261,8 @@ def get_t2_info(duthosts, tbinfo): @pytest.fixture(scope="module") -def setup(duthosts, ptfhost, rand_selected_dut, rand_unselected_dut, tbinfo, ptfadapter, topo_scenario, vlan_name): +def setup(duthosts, ptfhost, rand_selected_dut, rand_unselected_dut, tbinfo, ptfadapter, topo_scenario, + vlan_name, is_macsec_enabled_for_test): """Gather all required test information from DUT and tbinfo. Args: @@ -441,6 +442,11 @@ def setup(duthosts, ptfhost, rand_selected_dut, rand_unselected_dut, tbinfo, ptf for duthost in duthosts: duthost.command("mkdir -p {}".format(DUT_TMP_DIR)) + # Reload macsec config if enable_macsec is set for this test run + # If macsec is enabled, use the override option to get macsec profile from golden config + if is_macsec_enabled_for_test == True: + setattr(ptfadapter, "force_reload_macsec", True) + yield setup_information logger.info("Removing temporary directory \"{}\"".format(DUT_TMP_DIR)) diff --git a/tests/common/config_reload.py b/tests/common/config_reload.py index a674c979d4e..d70744c2ae1 100644 --- a/tests/common/config_reload.py +++ b/tests/common/config_reload.py @@ -148,6 +148,12 @@ def _config_reload_cmd_wrapper(cmd, executable): # Extend ignore fabric port msgs for T2 chassis with DNX chipset on Linecards ignore_t2_syslog_msgs(sonic_host) + # Retrieve the enable_macsec passed by user for this test run + # If macsec is enabled, use the override option to get macsec profile from golden config + request = sonic_host.duthosts.request + if request: + macsec_en = request.config.getoption("--enable_macsec", default=False) + if config_source == 'minigraph': if start_dynamic_buffer and sonic_host.facts['asic_type'] == 'mellanox': output = sonic_host.shell('redis-cli -n 4 hget "DEVICE_METADATA|localhost" buffer_model', @@ -158,7 +164,7 @@ def _config_reload_cmd_wrapper(cmd, executable): cmd = 'config load_minigraph -y &>/dev/null' if traffic_shift_away: cmd += ' -t' - if override_config: + if override_config or macsec_en: cmd += ' -o' if golden_config_path: cmd += ' -p {} '.format(golden_config_path) diff --git a/tests/common/macsec/macsec_helper.py b/tests/common/macsec/macsec_helper.py index e8850c243bc..78de42eb2e7 100644 --- a/tests/common/macsec/macsec_helper.py +++ b/tests/common/macsec/macsec_helper.py @@ -467,6 +467,11 @@ def load_macsec_info(duthost, port, force_reload=None): return __macsec_infos[port] +def load_macsec_info_for_ptf_id(duthost, ptf_id, port, force_reload=None): + if force_reload: + MACSEC_INFO[ptf_id] = get_macsec_attr(duthost, port) + + # This API load the macsec session details from all ctrl links def load_all_macsec_info(duthost, ctrl_links, tbinfo): mg_facts = duthost.get_extended_minigraph_facts(tbinfo) @@ -528,6 +533,10 @@ def macsec_dp_poll(test, device_number=0, port_number=None, timeout=None, exp_pk return ret else: if ret.port in MACSEC_INFO and MACSEC_INFO[ret.port]: + # Reload the macsec session if the session was restarted + if force_reload[ret.port]: + load_macsec_info_for_ptf_id(test.duthost, ret.port, + find_portname_from_ptf_id(test.mg_facts, ret.port), force_reload[ret.port]) encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = \ MACSEC_INFO[ret.port] force_reload[ret.port] = False diff --git a/tests/conftest.py b/tests/conftest.py index db3cef55eb6..7c77119ea56 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -537,6 +537,15 @@ def macsec_duthost(duthosts, tbinfo): return macsec_dut +@pytest.fixture(scope="session") +def is_macsec_enabled_for_test(duthosts): + # If macsec is enabled, use the override option to get macsec profile from golden config + macsec_en = False + request = duthosts.request + if request: + macsec_en = request.config.getoption("--enable_macsec", default=False) + return macsec_en + # Make sure in same test module, always use same random DUT rand_one_dut_hostname_var = None From 74c43692e19bf322f8a8841f32ca4657ff0af4c9 Mon Sep 17 00:00:00 2001 From: Judy Joseph Date: Thu, 27 Feb 2025 03:15:32 +0000 Subject: [PATCH 05/24] Fixes to get generate_golden_config work when this run for a non macsec case in t2 topo --- ansible/config_sonic_basedon_testbed.yml | 1 - ansible/library/generate_golden_config_db.py | 2 +- ansible/templates/minigraph_link_meta.j2 | 5 +++-- ansible/templates/minigraph_meta.j2 | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ansible/config_sonic_basedon_testbed.yml b/ansible/config_sonic_basedon_testbed.yml index bcfb2ba242f..52334ce86f7 100644 --- a/ansible/config_sonic_basedon_testbed.yml +++ b/ansible/config_sonic_basedon_testbed.yml @@ -590,7 +590,6 @@ topo_name: "{{ topo }}" port_index_map: "{{ port_index_map | default({}) }}" become: true - when: "'t2' not in topo" - name: Copy macsec profile json to dut copy: src=../tests/common/macsec/profile.json diff --git a/ansible/library/generate_golden_config_db.py b/ansible/library/generate_golden_config_db.py index ecec75f157a..4b619fc832b 100644 --- a/ansible/library/generate_golden_config_db.py +++ b/ansible/library/generate_golden_config_db.py @@ -386,7 +386,7 @@ def generate(self): elif self.topo_name == "t1-28-lag" or self.topo_name == "smartswitch-t1": config = self.generate_smartswitch_golden_config_db() self.module.run_command("sudo rm -f {}".format(TEMP_SMARTSWITCH_CONFIG_PATH)) - elif "t2" in self.topo_name: + elif "t2" in self.topo_name and self.macsec_profile: config = self.generate_t2_golden_config_db() self.module.run_command("sudo rm -f {}".format(MACSEC_PROFILE_PATH)) self.module.run_command("sudo rm -f {}".format(GOLDEN_CONFIG_TEMPLATE_PATH)) diff --git a/ansible/templates/minigraph_link_meta.j2 b/ansible/templates/minigraph_link_meta.j2 index 51dd83c2e75..03d16937c90 100644 --- a/ansible/templates/minigraph_link_meta.j2 +++ b/ansible/templates/minigraph_link_meta.j2 @@ -1,6 +1,7 @@ {%- set ns = namespace(link_metadata_defined=False) -%} -{%- if 'dualtor' in topo or (macsec_card is defined and macsec_card == True and 't2' in topo) -%} +{% if 'dualtor' in topo or + (macsec_card is defined and enable_macsec is defined and macsec_card == True and 't2' in topo) %} {% set ns.link_metadata_defined = True %} {%- endif -%} @@ -38,7 +39,7 @@ {% endfor %} {% endif %} -{% if macsec_card is defined and macsec_card == True and 't2' in topo %} +{% if macsec_card is defined and enable_macsec is defined and macsec_card == True and 't2' in topo %} {% for index in range(vms_number) %} {% set vm_intfs=vm_topo_config['vm'][vms[index]]['intfs'][dut_index|int]|sort %} {% set dut_intfs=vm_topo_config['vm'][vms[index]]['interface_indexes'][dut_index|int]|sort %} diff --git a/ansible/templates/minigraph_meta.j2 b/ansible/templates/minigraph_meta.j2 index 4e8b1e4e1da..1fcbacc7cf5 100644 --- a/ansible/templates/minigraph_meta.j2 +++ b/ansible/templates/minigraph_meta.j2 @@ -226,7 +226,7 @@ {{ switch_type }} {% endif %} -{% if macsec_card is defined and macsec_card == True and 't2' in topo %} +{% if macsec_card is defined and enable_macsec is defined and macsec_card == True and 't2' in topo %} MacSecProfile PrimaryKey="MACSEC_PROFILE" FallbackKey="macsec-profile2" MacsecPolicy="" From 6bea951385ee6a5640c7d004cae5c74ecc37124b Mon Sep 17 00:00:00 2001 From: Judy Joseph Date: Fri, 28 Feb 2025 01:52:54 +0000 Subject: [PATCH 06/24] Flake errors and unwanted imports removed --- ansible/library/get_macsec_profile.py | 2 ++ ansible/roles/test/files/ptftests/py3/IP_decap_test.py | 1 - ansible/roles/test/files/ptftests/py3/copp_tests.py | 2 +- ansible/roles/test/files/ptftests/py3/hash_test.py | 1 - ansible/roles/test/files/ptftests/py3/pfc_wd.py | 1 - ansible/roles/test/files/ptftests/py3/voq.py | 1 - tests/acl/test_acl.py | 4 ++-- tests/common/macsec/macsec_helper.py | 4 ++-- tests/conftest.py | 1 + 9 files changed, 8 insertions(+), 9 deletions(-) diff --git a/ansible/library/get_macsec_profile.py b/ansible/library/get_macsec_profile.py index 143461bd137..3c8d2d0257a 100644 --- a/ansible/library/get_macsec_profile.py +++ b/ansible/library/get_macsec_profile.py @@ -4,6 +4,7 @@ import json from ansible.module_utils.basic import AnsibleModule + def convert_to_eos(cipher_name): # Set the cipher suite as 256 xpn by default eos_cipher_name = 'aes256-gcm-xpn' @@ -47,5 +48,6 @@ def main(): vm_type = module.params['vm_type'] module.exit_json(profile=get_macsec_profile(module, macsec_profile, vm_type), changed=False) + if __name__ == "__main__": main() diff --git a/ansible/roles/test/files/ptftests/py3/IP_decap_test.py b/ansible/roles/test/files/ptftests/py3/IP_decap_test.py index 8824670005d..7f821779759 100644 --- a/ansible/roles/test/files/ptftests/py3/IP_decap_test.py +++ b/ansible/roles/test/files/ptftests/py3/IP_decap_test.py @@ -50,7 +50,6 @@ import itertools import fib import time -import macsec import ptf import ptf.packet as scapy import ptf.testutils as testutils diff --git a/ansible/roles/test/files/ptftests/py3/copp_tests.py b/ansible/roles/test/files/ptftests/py3/copp_tests.py index 0ca5c4ca298..92211065432 100644 --- a/ansible/roles/test/files/ptftests/py3/copp_tests.py +++ b/ansible/roles/test/files/ptftests/py3/copp_tests.py @@ -41,7 +41,7 @@ from ptf.base_tests import BaseTest from ptf import config -import macsec + class ControlPlaneBaseTest(BaseTest): MAX_PORTS = 128 diff --git a/ansible/roles/test/files/ptftests/py3/hash_test.py b/ansible/roles/test/files/ptftests/py3/hash_test.py index 16ab98f17e7..fe463c6e24e 100644 --- a/ansible/roles/test/files/ptftests/py3/hash_test.py +++ b/ansible/roles/test/files/ptftests/py3/hash_test.py @@ -32,7 +32,6 @@ import fib import lpm -import macsec class HashTest(BaseTest): diff --git a/ansible/roles/test/files/ptftests/py3/pfc_wd.py b/ansible/roles/test/files/ptftests/py3/pfc_wd.py index 10eb25c1256..575993b41d1 100644 --- a/ansible/roles/test/files/ptftests/py3/pfc_wd.py +++ b/ansible/roles/test/files/ptftests/py3/pfc_wd.py @@ -10,7 +10,6 @@ from ptf.base_tests import BaseTest from ptf.mask import Mask from ptf.testutils import test_params_get, simple_tcp_packet, send_packet, verify_no_packet_any, verify_packet_any_port -import macsec class PfcWdTest(BaseTest): diff --git a/ansible/roles/test/files/ptftests/py3/voq.py b/ansible/roles/test/files/ptftests/py3/voq.py index 98ad62c7c95..3f10842ff5d 100644 --- a/ansible/roles/test/files/ptftests/py3/voq.py +++ b/ansible/roles/test/files/ptftests/py3/voq.py @@ -11,7 +11,6 @@ from scapy.all import Ether from scapy.layers.l2 import Dot1Q from scapy.layers.inet6 import IPv6, ICMPv6ND_NA, ICMPv6NDOptDstLLAddr -import macsec import logging diff --git a/tests/acl/test_acl.py b/tests/acl/test_acl.py index 375ea454d8b..6c075e2f072 100644 --- a/tests/acl/test_acl.py +++ b/tests/acl/test_acl.py @@ -262,7 +262,7 @@ def get_t2_info(duthosts, tbinfo): @pytest.fixture(scope="module") def setup(duthosts, ptfhost, rand_selected_dut, rand_unselected_dut, tbinfo, ptfadapter, topo_scenario, - vlan_name, is_macsec_enabled_for_test): + vlan_name, is_macsec_enabled_for_test): """Gather all required test information from DUT and tbinfo. Args: @@ -444,7 +444,7 @@ def setup(duthosts, ptfhost, rand_selected_dut, rand_unselected_dut, tbinfo, ptf # Reload macsec config if enable_macsec is set for this test run # If macsec is enabled, use the override option to get macsec profile from golden config - if is_macsec_enabled_for_test == True: + if is_macsec_enabled_for_test: setattr(ptfadapter, "force_reload_macsec", True) yield setup_information diff --git a/tests/common/macsec/macsec_helper.py b/tests/common/macsec/macsec_helper.py index 78de42eb2e7..b619cc2daac 100644 --- a/tests/common/macsec/macsec_helper.py +++ b/tests/common/macsec/macsec_helper.py @@ -536,9 +536,9 @@ def macsec_dp_poll(test, device_number=0, port_number=None, timeout=None, exp_pk # Reload the macsec session if the session was restarted if force_reload[ret.port]: load_macsec_info_for_ptf_id(test.duthost, ret.port, - find_portname_from_ptf_id(test.mg_facts, ret.port), force_reload[ret.port]) + find_portname_from_ptf_id(test.mg_facts, ret.port), force_reload[ret.port]) encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = \ - MACSEC_INFO[ret.port] + MACSEC_INFO[ret.port] force_reload[ret.port] = False pkt, decap_success = decap_macsec_pkt(pkt, sci, an, sak, encrypt, send_sci, 0, xpn_en, ssci, salt) if decap_success and ptf.dataplane.match_exp_pkt(exp_pkt, pkt): diff --git a/tests/conftest.py b/tests/conftest.py index 7c77119ea56..c686459f236 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -546,6 +546,7 @@ def is_macsec_enabled_for_test(duthosts): macsec_en = request.config.getoption("--enable_macsec", default=False) return macsec_en + # Make sure in same test module, always use same random DUT rand_one_dut_hostname_var = None From 4fbc9b333be10f0907b4a7d8d9a38d75d3181fb5 Mon Sep 17 00:00:00 2001 From: Judy Joseph Date: Fri, 28 Feb 2025 01:56:18 +0000 Subject: [PATCH 07/24] minor fixes --- ansible/roles/test/files/ptftests/fib_test.py | 2 +- ansible/roles/test/files/ptftests/py3/IP_decap_test.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ansible/roles/test/files/ptftests/fib_test.py b/ansible/roles/test/files/ptftests/fib_test.py index c18af9a787d..94fc40beec7 100644 --- a/ansible/roles/test/files/ptftests/fib_test.py +++ b/ansible/roles/test/files/ptftests/fib_test.py @@ -25,7 +25,7 @@ import json import itertools import fib -import macsec + import ptf import ptf.packet as scapy diff --git a/ansible/roles/test/files/ptftests/py3/IP_decap_test.py b/ansible/roles/test/files/ptftests/py3/IP_decap_test.py index 7f821779759..19532d4dd55 100644 --- a/ansible/roles/test/files/ptftests/py3/IP_decap_test.py +++ b/ansible/roles/test/files/ptftests/py3/IP_decap_test.py @@ -50,6 +50,7 @@ import itertools import fib import time + import ptf import ptf.packet as scapy import ptf.testutils as testutils From c0d028a91682f7f1244b52eef3de15eafb80e372 Mon Sep 17 00:00:00 2001 From: Judy Joseph Date: Fri, 28 Feb 2025 01:40:35 +0000 Subject: [PATCH 08/24] Add macsec support in acstests and saitests --- ansible/roles/test/files/acstests/macsec.py | 127 ++++++++++++++++++ .../roles/test/files/acstests/py3/macsec.py | 1 + tests/saitests/macsec.py | 127 ++++++++++++++++++ tests/saitests/py3/macsec.py | 1 + 4 files changed, 256 insertions(+) create mode 100644 ansible/roles/test/files/acstests/macsec.py create mode 120000 ansible/roles/test/files/acstests/py3/macsec.py create mode 100644 tests/saitests/macsec.py create mode 120000 tests/saitests/py3/macsec.py diff --git a/ansible/roles/test/files/acstests/macsec.py b/ansible/roles/test/files/acstests/macsec.py new file mode 100644 index 00000000000..e52d05137c4 --- /dev/null +++ b/ansible/roles/test/files/acstests/macsec.py @@ -0,0 +1,127 @@ +import os +import pickle +import cryptography.exceptions +import time + +import ptf +import scapy.all as scapy +MACSEC_SUPPORTED = False +if hasattr(scapy, "VERSION") and tuple(map(int, scapy.VERSION.split('.'))) >= (2, 4, 5): + MACSEC_SUPPORTED = True +if MACSEC_SUPPORTED: + import scapy.contrib.macsec as scapy_macsec + +MACSEC_INFO_FILE = "macsec_info.pickle" +MACSEC_GLOBAL_PN_OFFSET = 1000 +MACSEC_GLOBAL_PN_INCR = 100 + +MACSEC_INFOS = {} + + +def macsec_send(test, port_number, pkt, count=1): + # Check if the port is macsec enabled, if so send the macsec encap/encrypted frame + global MACSEC_GLOBAL_PN_OFFSET + global MACSEC_GLOBAL_PN_INCR + + device, port_id = ptf.testutils.port_to_tuple(port_number) + if port_id in MACSEC_INFOS and MACSEC_INFOS[port_id]: + encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = \ + MACSEC_INFOS[port_id] + + # Increment the PN by an offset so that the macsec frames are not late on DUT + pn += MACSEC_GLOBAL_PN_OFFSET + MACSEC_GLOBAL_PN_OFFSET += MACSEC_GLOBAL_PN_INCR + + macsec_pkt = encap_macsec_pkt(pkt, peer_sci, peer_an, sak, encrypt, send_sci, pn, xpn_en, peer_ssci, salt) + # send the packet + __origin_send_packet(test, port_number, macsec_pkt, count) + else: + # send the packet + __origin_send_packet(test, port_number, pkt, count) + + +def encap_macsec_pkt(macsec_pkt, sci, an, sak, encrypt, send_sci, pn, xpn_en=False, ssci=None, salt=None): + sa = scapy_macsec.MACsecSA(sci=sci, + an=an, + pn=pn, + key=sak, + icvlen=16, + encrypt=encrypt, + send_sci=send_sci, + xpn_en=xpn_en, + ssci=ssci, + salt=salt) + macsec_pkt = sa.encap(macsec_pkt) + pkt = sa.encrypt(macsec_pkt) + return pkt + + +def __decap_macsec_pkt(macsec_pkt, sci, an, sak, encrypt, send_sci, pn, xpn_en=False, ssci=None, salt=None): + sa = scapy_macsec.MACsecSA(sci=sci, + an=an, + pn=pn, + key=sak, + icvlen=16, + encrypt=encrypt, + send_sci=send_sci, + xpn_en=xpn_en, + ssci=ssci, + salt=salt) + try: + pkt = sa.decrypt(macsec_pkt) + except cryptography.exceptions.InvalidTag: + # Invalid MACsec packets + return macsec_pkt, False + pkt = sa.decap(pkt) + return pkt, True + + +def __macsec_dp_poll(test, device_number=0, port_number=None, timeout=None, exp_pkt=None): + recent_packets = [] + packet_count = 0 + if timeout is None: + timeout = ptf.ptfutils.default_timeout + while True: + start_time = time.time() + ret = __origin_dp_poll( + test, device_number=device_number, port_number=port_number, timeout=timeout, exp_pkt=None) + timeout -= time.time() - start_time + # Since we call __origin_dp_poll with exp_pkt=None, it should only ever fail if no packets are received at all. + # In this case, continue normally until we exceed the timeout value provided to macsec_dp_poll. + if isinstance(ret, test.dataplane.PollFailure): + if timeout <= 0: + break + else: + continue + # The device number of PTF host is 0, if the target port isn't a injected port(belong to ptf host), + # Don't need to do MACsec further. + if ret.device != 0 or exp_pkt is None: + return ret + pkt = scapy.Ether(ret.packet) + if pkt[scapy.Ether].type != 0x88e5: + if ptf.dataplane.match_exp_pkt(exp_pkt, pkt): + return ret + else: + continue + if ret.port in MACSEC_INFOS and MACSEC_INFOS[ret.port]: + encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = \ + MACSEC_INFOS[ret.port] + pkt, decap_success = __decap_macsec_pkt( + pkt, sci, an, sak, encrypt, send_sci, 0, xpn_en, ssci, salt) + if decap_success and ptf.dataplane.match_exp_pkt(exp_pkt, pkt): + return ret + recent_packets.append(pkt) + packet_count += 1 + if timeout <= 0: + break + return test.dataplane.PollFailure(exp_pkt, recent_packets, packet_count) + + +if MACSEC_SUPPORTED and os.path.exists(MACSEC_INFO_FILE): + with open(MACSEC_INFO_FILE, "rb") as f: + MACSEC_INFOS = pickle.load(f, encoding="bytes") + if MACSEC_INFOS: + __origin_dp_poll = ptf.testutils.dp_poll + ptf.testutils.dp_poll = __macsec_dp_poll + __origin_send_packet = ptf.testutils.send_packet + ptf.testutils.send_packet = macsec_send diff --git a/ansible/roles/test/files/acstests/py3/macsec.py b/ansible/roles/test/files/acstests/py3/macsec.py new file mode 120000 index 00000000000..f8db57172ed --- /dev/null +++ b/ansible/roles/test/files/acstests/py3/macsec.py @@ -0,0 +1 @@ +../macsec.py \ No newline at end of file diff --git a/tests/saitests/macsec.py b/tests/saitests/macsec.py new file mode 100644 index 00000000000..e52d05137c4 --- /dev/null +++ b/tests/saitests/macsec.py @@ -0,0 +1,127 @@ +import os +import pickle +import cryptography.exceptions +import time + +import ptf +import scapy.all as scapy +MACSEC_SUPPORTED = False +if hasattr(scapy, "VERSION") and tuple(map(int, scapy.VERSION.split('.'))) >= (2, 4, 5): + MACSEC_SUPPORTED = True +if MACSEC_SUPPORTED: + import scapy.contrib.macsec as scapy_macsec + +MACSEC_INFO_FILE = "macsec_info.pickle" +MACSEC_GLOBAL_PN_OFFSET = 1000 +MACSEC_GLOBAL_PN_INCR = 100 + +MACSEC_INFOS = {} + + +def macsec_send(test, port_number, pkt, count=1): + # Check if the port is macsec enabled, if so send the macsec encap/encrypted frame + global MACSEC_GLOBAL_PN_OFFSET + global MACSEC_GLOBAL_PN_INCR + + device, port_id = ptf.testutils.port_to_tuple(port_number) + if port_id in MACSEC_INFOS and MACSEC_INFOS[port_id]: + encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = \ + MACSEC_INFOS[port_id] + + # Increment the PN by an offset so that the macsec frames are not late on DUT + pn += MACSEC_GLOBAL_PN_OFFSET + MACSEC_GLOBAL_PN_OFFSET += MACSEC_GLOBAL_PN_INCR + + macsec_pkt = encap_macsec_pkt(pkt, peer_sci, peer_an, sak, encrypt, send_sci, pn, xpn_en, peer_ssci, salt) + # send the packet + __origin_send_packet(test, port_number, macsec_pkt, count) + else: + # send the packet + __origin_send_packet(test, port_number, pkt, count) + + +def encap_macsec_pkt(macsec_pkt, sci, an, sak, encrypt, send_sci, pn, xpn_en=False, ssci=None, salt=None): + sa = scapy_macsec.MACsecSA(sci=sci, + an=an, + pn=pn, + key=sak, + icvlen=16, + encrypt=encrypt, + send_sci=send_sci, + xpn_en=xpn_en, + ssci=ssci, + salt=salt) + macsec_pkt = sa.encap(macsec_pkt) + pkt = sa.encrypt(macsec_pkt) + return pkt + + +def __decap_macsec_pkt(macsec_pkt, sci, an, sak, encrypt, send_sci, pn, xpn_en=False, ssci=None, salt=None): + sa = scapy_macsec.MACsecSA(sci=sci, + an=an, + pn=pn, + key=sak, + icvlen=16, + encrypt=encrypt, + send_sci=send_sci, + xpn_en=xpn_en, + ssci=ssci, + salt=salt) + try: + pkt = sa.decrypt(macsec_pkt) + except cryptography.exceptions.InvalidTag: + # Invalid MACsec packets + return macsec_pkt, False + pkt = sa.decap(pkt) + return pkt, True + + +def __macsec_dp_poll(test, device_number=0, port_number=None, timeout=None, exp_pkt=None): + recent_packets = [] + packet_count = 0 + if timeout is None: + timeout = ptf.ptfutils.default_timeout + while True: + start_time = time.time() + ret = __origin_dp_poll( + test, device_number=device_number, port_number=port_number, timeout=timeout, exp_pkt=None) + timeout -= time.time() - start_time + # Since we call __origin_dp_poll with exp_pkt=None, it should only ever fail if no packets are received at all. + # In this case, continue normally until we exceed the timeout value provided to macsec_dp_poll. + if isinstance(ret, test.dataplane.PollFailure): + if timeout <= 0: + break + else: + continue + # The device number of PTF host is 0, if the target port isn't a injected port(belong to ptf host), + # Don't need to do MACsec further. + if ret.device != 0 or exp_pkt is None: + return ret + pkt = scapy.Ether(ret.packet) + if pkt[scapy.Ether].type != 0x88e5: + if ptf.dataplane.match_exp_pkt(exp_pkt, pkt): + return ret + else: + continue + if ret.port in MACSEC_INFOS and MACSEC_INFOS[ret.port]: + encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = \ + MACSEC_INFOS[ret.port] + pkt, decap_success = __decap_macsec_pkt( + pkt, sci, an, sak, encrypt, send_sci, 0, xpn_en, ssci, salt) + if decap_success and ptf.dataplane.match_exp_pkt(exp_pkt, pkt): + return ret + recent_packets.append(pkt) + packet_count += 1 + if timeout <= 0: + break + return test.dataplane.PollFailure(exp_pkt, recent_packets, packet_count) + + +if MACSEC_SUPPORTED and os.path.exists(MACSEC_INFO_FILE): + with open(MACSEC_INFO_FILE, "rb") as f: + MACSEC_INFOS = pickle.load(f, encoding="bytes") + if MACSEC_INFOS: + __origin_dp_poll = ptf.testutils.dp_poll + ptf.testutils.dp_poll = __macsec_dp_poll + __origin_send_packet = ptf.testutils.send_packet + ptf.testutils.send_packet = macsec_send diff --git a/tests/saitests/py3/macsec.py b/tests/saitests/py3/macsec.py new file mode 120000 index 00000000000..f8db57172ed --- /dev/null +++ b/tests/saitests/py3/macsec.py @@ -0,0 +1 @@ +../macsec.py \ No newline at end of file From af19d86a160d3e6a1c78ba7de2287f93b3dcac7a Mon Sep 17 00:00:00 2001 From: Judy Joseph Date: Sat, 1 Mar 2025 07:14:53 +0000 Subject: [PATCH 09/24] Loop for count of packets to be sent as we need to increment PN --- ansible/roles/test/files/acstests/macsec.py | 15 ++++++++------- ansible/roles/test/files/ptftests/macsec.py | 15 ++++++++------- tests/common/macsec/macsec_helper.py | 15 ++++++++------- tests/saitests/macsec.py | 16 ++++++++-------- 4 files changed, 32 insertions(+), 29 deletions(-) diff --git a/ansible/roles/test/files/acstests/macsec.py b/ansible/roles/test/files/acstests/macsec.py index e52d05137c4..aef01732b16 100644 --- a/ansible/roles/test/files/acstests/macsec.py +++ b/ansible/roles/test/files/acstests/macsec.py @@ -28,13 +28,14 @@ def macsec_send(test, port_number, pkt, count=1): encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = \ MACSEC_INFOS[port_id] - # Increment the PN by an offset so that the macsec frames are not late on DUT - pn += MACSEC_GLOBAL_PN_OFFSET - MACSEC_GLOBAL_PN_OFFSET += MACSEC_GLOBAL_PN_INCR - - macsec_pkt = encap_macsec_pkt(pkt, peer_sci, peer_an, sak, encrypt, send_sci, pn, xpn_en, peer_ssci, salt) - # send the packet - __origin_send_packet(test, port_number, macsec_pkt, count) + for n in range(count): + # Increment the PN by an offset so that the macsec frames are not late on DUT + MACSEC_GLOBAL_PN_OFFSET += MACSEC_GLOBAL_PN_INCR + pn += MACSEC_GLOBAL_PN_OFFSET + + macsec_pkt = encap_macsec_pkt(pkt, peer_sci, peer_an, sak, encrypt, send_sci, pn, xpn_en, peer_ssci, salt) + # send the packet + __origin_send_packet(test, port_number, macsec_pkt, 1) else: # send the packet __origin_send_packet(test, port_number, pkt, count) diff --git a/ansible/roles/test/files/ptftests/macsec.py b/ansible/roles/test/files/ptftests/macsec.py index e52d05137c4..aef01732b16 100644 --- a/ansible/roles/test/files/ptftests/macsec.py +++ b/ansible/roles/test/files/ptftests/macsec.py @@ -28,13 +28,14 @@ def macsec_send(test, port_number, pkt, count=1): encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = \ MACSEC_INFOS[port_id] - # Increment the PN by an offset so that the macsec frames are not late on DUT - pn += MACSEC_GLOBAL_PN_OFFSET - MACSEC_GLOBAL_PN_OFFSET += MACSEC_GLOBAL_PN_INCR - - macsec_pkt = encap_macsec_pkt(pkt, peer_sci, peer_an, sak, encrypt, send_sci, pn, xpn_en, peer_ssci, salt) - # send the packet - __origin_send_packet(test, port_number, macsec_pkt, count) + for n in range(count): + # Increment the PN by an offset so that the macsec frames are not late on DUT + MACSEC_GLOBAL_PN_OFFSET += MACSEC_GLOBAL_PN_INCR + pn += MACSEC_GLOBAL_PN_OFFSET + + macsec_pkt = encap_macsec_pkt(pkt, peer_sci, peer_an, sak, encrypt, send_sci, pn, xpn_en, peer_ssci, salt) + # send the packet + __origin_send_packet(test, port_number, macsec_pkt, 1) else: # send the packet __origin_send_packet(test, port_number, pkt, count) diff --git a/tests/common/macsec/macsec_helper.py b/tests/common/macsec/macsec_helper.py index b619cc2daac..a0f20c7ffa0 100644 --- a/tests/common/macsec/macsec_helper.py +++ b/tests/common/macsec/macsec_helper.py @@ -489,13 +489,14 @@ def macsec_send(test, port_number, pkt, count=1): if port_id in MACSEC_INFO and MACSEC_INFO[port_id]: encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = MACSEC_INFO[port_id] - # Increment the PN in packet so that the packet s not marked as late in DUT - pn += MACSEC_GLOBAL_PN_OFFSET - MACSEC_GLOBAL_PN_OFFSET += MACSEC_GLOBAL_PN_INCR - - macsec_pkt = encap_macsec_pkt(pkt, peer_sci, peer_an, sak, encrypt, send_sci, pn, xpn_en, peer_ssci, salt) - # send the packet - __origin_send_packet(test, port_number, macsec_pkt, count) + for n in range(count): + # Increment the PN in packet so that the packet s not marked as late in DUT + MACSEC_GLOBAL_PN_OFFSET += MACSEC_GLOBAL_PN_INCR + pn += MACSEC_GLOBAL_PN_OFFSET + + macsec_pkt = encap_macsec_pkt(pkt, peer_sci, peer_an, sak, encrypt, send_sci, pn, xpn_en, peer_ssci, salt) + # send the packet + __origin_send_packet(test, port_number, macsec_pkt, 1) else: # send the packet __origin_send_packet(test, port_number, pkt, count) diff --git a/tests/saitests/macsec.py b/tests/saitests/macsec.py index e52d05137c4..b80e973188a 100644 --- a/tests/saitests/macsec.py +++ b/tests/saitests/macsec.py @@ -27,14 +27,14 @@ def macsec_send(test, port_number, pkt, count=1): if port_id in MACSEC_INFOS and MACSEC_INFOS[port_id]: encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = \ MACSEC_INFOS[port_id] - - # Increment the PN by an offset so that the macsec frames are not late on DUT - pn += MACSEC_GLOBAL_PN_OFFSET - MACSEC_GLOBAL_PN_OFFSET += MACSEC_GLOBAL_PN_INCR - - macsec_pkt = encap_macsec_pkt(pkt, peer_sci, peer_an, sak, encrypt, send_sci, pn, xpn_en, peer_ssci, salt) - # send the packet - __origin_send_packet(test, port_number, macsec_pkt, count) + for n in range(count): + # Increment the PN by an offset so that the macsec frames are not late on DUT + MACSEC_GLOBAL_PN_OFFSET += MACSEC_GLOBAL_PN_INCR + pn += MACSEC_GLOBAL_PN_OFFSET + + macsec_pkt = encap_macsec_pkt(pkt, peer_sci, peer_an, sak, encrypt, send_sci, pn, xpn_en, peer_ssci, salt) + # send the packet + __origin_send_packet(test, port_number, macsec_pkt, 1) else: # send the packet __origin_send_packet(test, port_number, pkt, count) From 708b1d4b1c719e67c76f9898c17866958eaf5ba4 Mon Sep 17 00:00:00 2001 From: Judy Joseph Date: Sun, 2 Mar 2025 05:48:59 +0000 Subject: [PATCH 10/24] We need to import macsec to override send_packet and dp_poll --- ansible/roles/test/files/acstests/py3/lag_test.py | 1 + ansible/roles/test/files/ptftests/py3/IP_decap_test.py | 1 + ansible/roles/test/files/ptftests/py3/arptest.py | 1 + ansible/roles/test/files/ptftests/py3/copp_tests.py | 1 + ansible/roles/test/files/ptftests/py3/hash_test.py | 2 +- ansible/roles/test/files/ptftests/py3/mtu_test.py | 2 +- ansible/roles/test/files/ptftests/py3/pfc_pause_test.py | 2 +- ansible/roles/test/files/ptftests/py3/pfc_wd.py | 2 +- .../roles/test/files/ptftests/py3/pfc_wd_background_traffic.py | 2 +- .../roles/test/files/ptftests/py3/pfcwd_background_traffic.py | 2 +- ansible/roles/test/files/ptftests/py3/voq.py | 1 + tests/saitests/py3/sai_qos_tests.py | 1 + 12 files changed, 12 insertions(+), 6 deletions(-) diff --git a/ansible/roles/test/files/acstests/py3/lag_test.py b/ansible/roles/test/files/acstests/py3/lag_test.py index 3786bf30e7d..4feb05f9d92 100644 --- a/ansible/roles/test/files/acstests/py3/lag_test.py +++ b/ansible/roles/test/files/acstests/py3/lag_test.py @@ -15,6 +15,7 @@ from ptf.testutils import send from ptf.testutils import verify_packet_any_port from ptf.mask import Mask +import macsec # noqa F401 from router_utils import RouterUtility diff --git a/ansible/roles/test/files/ptftests/py3/IP_decap_test.py b/ansible/roles/test/files/ptftests/py3/IP_decap_test.py index 19532d4dd55..a8c30b70995 100644 --- a/ansible/roles/test/files/ptftests/py3/IP_decap_test.py +++ b/ansible/roles/test/files/ptftests/py3/IP_decap_test.py @@ -59,6 +59,7 @@ from ptf.mask import Mask from ptf.base_tests import BaseTest +import macsec # noqa F401 class DecapPacketTest(BaseTest): """ IP in IP decapsulation test """ diff --git a/ansible/roles/test/files/ptftests/py3/arptest.py b/ansible/roles/test/files/ptftests/py3/arptest.py index 7146062a5ed..4f1a9a2e7f3 100644 --- a/ansible/roles/test/files/ptftests/py3/arptest.py +++ b/ansible/roles/test/files/ptftests/py3/arptest.py @@ -3,6 +3,7 @@ ''' import os import ptf +import macsec # noqa F401 from ptf.testutils import test_params_get, add_filter, not_ipv6_filter, reset_filters, ptf_ports,\ simple_arp_packet, send_packet, verify_packet, verify_no_packet_any, verify_no_packet from ptf import config diff --git a/ansible/roles/test/files/ptftests/py3/copp_tests.py b/ansible/roles/test/files/ptftests/py3/copp_tests.py index 92211065432..682a0775aad 100644 --- a/ansible/roles/test/files/ptftests/py3/copp_tests.py +++ b/ansible/roles/test/files/ptftests/py3/copp_tests.py @@ -35,6 +35,7 @@ import signal import threading import time +import macsec # noqa F401 import ptf.packet as scapy import ptf.testutils as testutils diff --git a/ansible/roles/test/files/ptftests/py3/hash_test.py b/ansible/roles/test/files/ptftests/py3/hash_test.py index fe463c6e24e..c90e25ba6aa 100644 --- a/ansible/roles/test/files/ptftests/py3/hash_test.py +++ b/ansible/roles/test/files/ptftests/py3/hash_test.py @@ -32,7 +32,7 @@ import fib import lpm - +import macsec # noqa F401 class HashTest(BaseTest): diff --git a/ansible/roles/test/files/ptftests/py3/mtu_test.py b/ansible/roles/test/files/ptftests/py3/mtu_test.py index b33ffc638db..1aae902879d 100644 --- a/ansible/roles/test/files/ptftests/py3/mtu_test.py +++ b/ansible/roles/test/files/ptftests/py3/mtu_test.py @@ -27,7 +27,7 @@ from ptf.mask import Mask from ptf.testutils import test_params_get, simple_icmp_packet, simple_icmpv6_packet, send_packet,\ simple_ip_packet, simple_tcpv6_packet, verify_packet_any_port - +import macsec # noqa F401 class MtuTest(BaseTest): ''' diff --git a/ansible/roles/test/files/ptftests/py3/pfc_pause_test.py b/ansible/roles/test/files/ptftests/py3/pfc_pause_test.py index 90739b1e5e7..8f62b6d5fd5 100755 --- a/ansible/roles/test/files/ptftests/py3/pfc_pause_test.py +++ b/ansible/roles/test/files/ptftests/py3/pfc_pause_test.py @@ -12,7 +12,7 @@ from ptf.base_tests import BaseTest from ptf.mask import Mask from ptf.testutils import add_filter, reset_filters, dp_poll, simple_udp_packet, send_packet, test_params_get - +import macsec # noqa F401 def udp_filter(pkt_str): try: diff --git a/ansible/roles/test/files/ptftests/py3/pfc_wd.py b/ansible/roles/test/files/ptftests/py3/pfc_wd.py index 575993b41d1..3328a97d5e7 100644 --- a/ansible/roles/test/files/ptftests/py3/pfc_wd.py +++ b/ansible/roles/test/files/ptftests/py3/pfc_wd.py @@ -10,7 +10,7 @@ from ptf.base_tests import BaseTest from ptf.mask import Mask from ptf.testutils import test_params_get, simple_tcp_packet, send_packet, verify_no_packet_any, verify_packet_any_port - +import macsec # noqa F401 class PfcWdTest(BaseTest): def __init__(self): diff --git a/ansible/roles/test/files/ptftests/py3/pfc_wd_background_traffic.py b/ansible/roles/test/files/ptftests/py3/pfc_wd_background_traffic.py index 7f5e3afd474..2411fc8a9da 100644 --- a/ansible/roles/test/files/ptftests/py3/pfc_wd_background_traffic.py +++ b/ansible/roles/test/files/ptftests/py3/pfc_wd_background_traffic.py @@ -4,7 +4,7 @@ from ptf.base_tests import BaseTest import time from ptf.testutils import test_params_get, simple_udp_packet, send_packet - +import macsec # noqa F401 class PfcWdBackgroundTrafficTest(BaseTest): def __init__(self): diff --git a/ansible/roles/test/files/ptftests/py3/pfcwd_background_traffic.py b/ansible/roles/test/files/ptftests/py3/pfcwd_background_traffic.py index 442aa0c6775..5e73cb5e885 100644 --- a/ansible/roles/test/files/ptftests/py3/pfcwd_background_traffic.py +++ b/ansible/roles/test/files/ptftests/py3/pfcwd_background_traffic.py @@ -29,7 +29,7 @@ import ptf.packet as scapy from ptf.mask import Mask import ptf - +import macsec # noqa F401 class BG_pkt_sender(BaseTest): def __init__(self): diff --git a/ansible/roles/test/files/ptftests/py3/voq.py b/ansible/roles/test/files/ptftests/py3/voq.py index 3f10842ff5d..5a633df7c5e 100644 --- a/ansible/roles/test/files/ptftests/py3/voq.py +++ b/ansible/roles/test/files/ptftests/py3/voq.py @@ -11,6 +11,7 @@ from scapy.all import Ether from scapy.layers.l2 import Dot1Q from scapy.layers.inet6 import IPv6, ICMPv6ND_NA, ICMPv6NDOptDstLLAddr +import macsec # noqa F401 import logging diff --git a/tests/saitests/py3/sai_qos_tests.py b/tests/saitests/py3/sai_qos_tests.py index 5a48ee24f50..d3543d1904f 100755 --- a/tests/saitests/py3/sai_qos_tests.py +++ b/tests/saitests/py3/sai_qos_tests.py @@ -12,6 +12,7 @@ import texttable import math import os +import macsec # noqa F401 import concurrent.futures from ptf.testutils import (ptf_ports, dp_poll, From 3c1253f9b5096964136454bcf7fd5339cfdf5947 Mon Sep 17 00:00:00 2001 From: Judy Joseph Date: Mon, 3 Mar 2025 07:52:03 +0000 Subject: [PATCH 11/24] Fixes for ip,copp,qos probably --- ansible/roles/test/files/acstests/macsec.py | 10 +++++++--- ansible/roles/test/files/ptftests/macsec.py | 10 +++++++--- tests/common/macsec/macsec_helper.py | 10 +++++++--- tests/saitests/macsec.py | 10 +++++++--- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/ansible/roles/test/files/acstests/macsec.py b/ansible/roles/test/files/acstests/macsec.py index aef01732b16..00b0e11eaac 100644 --- a/ansible/roles/test/files/acstests/macsec.py +++ b/ansible/roles/test/files/acstests/macsec.py @@ -29,6 +29,10 @@ def macsec_send(test, port_number, pkt, count=1): MACSEC_INFOS[port_id] for n in range(count): + if isinstance(pkt, bytes): + # If in bytes, convert it to an Ether packet + pkt = scapy.Ether(pkt) + # Increment the PN by an offset so that the macsec frames are not late on DUT MACSEC_GLOBAL_PN_OFFSET += MACSEC_GLOBAL_PN_INCR pn += MACSEC_GLOBAL_PN_OFFSET @@ -96,11 +100,11 @@ def __macsec_dp_poll(test, device_number=0, port_number=None, timeout=None, exp_ continue # The device number of PTF host is 0, if the target port isn't a injected port(belong to ptf host), # Don't need to do MACsec further. - if ret.device != 0 or exp_pkt is None: + if ret.device != 0: return ret pkt = scapy.Ether(ret.packet) if pkt[scapy.Ether].type != 0x88e5: - if ptf.dataplane.match_exp_pkt(exp_pkt, pkt): + if exp_pkt is None or ptf.dataplane.match_exp_pkt(exp_pkt, pkt): return ret else: continue @@ -109,7 +113,7 @@ def __macsec_dp_poll(test, device_number=0, port_number=None, timeout=None, exp_ MACSEC_INFOS[ret.port] pkt, decap_success = __decap_macsec_pkt( pkt, sci, an, sak, encrypt, send_sci, 0, xpn_en, ssci, salt) - if decap_success and ptf.dataplane.match_exp_pkt(exp_pkt, pkt): + if exp_pkt is None or decap_success and ptf.dataplane.match_exp_pkt(exp_pkt, pkt): return ret recent_packets.append(pkt) packet_count += 1 diff --git a/ansible/roles/test/files/ptftests/macsec.py b/ansible/roles/test/files/ptftests/macsec.py index aef01732b16..00b0e11eaac 100644 --- a/ansible/roles/test/files/ptftests/macsec.py +++ b/ansible/roles/test/files/ptftests/macsec.py @@ -29,6 +29,10 @@ def macsec_send(test, port_number, pkt, count=1): MACSEC_INFOS[port_id] for n in range(count): + if isinstance(pkt, bytes): + # If in bytes, convert it to an Ether packet + pkt = scapy.Ether(pkt) + # Increment the PN by an offset so that the macsec frames are not late on DUT MACSEC_GLOBAL_PN_OFFSET += MACSEC_GLOBAL_PN_INCR pn += MACSEC_GLOBAL_PN_OFFSET @@ -96,11 +100,11 @@ def __macsec_dp_poll(test, device_number=0, port_number=None, timeout=None, exp_ continue # The device number of PTF host is 0, if the target port isn't a injected port(belong to ptf host), # Don't need to do MACsec further. - if ret.device != 0 or exp_pkt is None: + if ret.device != 0: return ret pkt = scapy.Ether(ret.packet) if pkt[scapy.Ether].type != 0x88e5: - if ptf.dataplane.match_exp_pkt(exp_pkt, pkt): + if exp_pkt is None or ptf.dataplane.match_exp_pkt(exp_pkt, pkt): return ret else: continue @@ -109,7 +113,7 @@ def __macsec_dp_poll(test, device_number=0, port_number=None, timeout=None, exp_ MACSEC_INFOS[ret.port] pkt, decap_success = __decap_macsec_pkt( pkt, sci, an, sak, encrypt, send_sci, 0, xpn_en, ssci, salt) - if decap_success and ptf.dataplane.match_exp_pkt(exp_pkt, pkt): + if exp_pkt is None or decap_success and ptf.dataplane.match_exp_pkt(exp_pkt, pkt): return ret recent_packets.append(pkt) packet_count += 1 diff --git a/tests/common/macsec/macsec_helper.py b/tests/common/macsec/macsec_helper.py index a0f20c7ffa0..5ff65de4b66 100644 --- a/tests/common/macsec/macsec_helper.py +++ b/tests/common/macsec/macsec_helper.py @@ -490,6 +490,10 @@ def macsec_send(test, port_number, pkt, count=1): encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = MACSEC_INFO[port_id] for n in range(count): + if isinstance(pkt, bytes): + # If in bytes, convert it to an Ether packet + pkt = scapy.Ether(pkt) + # Increment the PN in packet so that the packet s not marked as late in DUT MACSEC_GLOBAL_PN_OFFSET += MACSEC_GLOBAL_PN_INCR pn += MACSEC_GLOBAL_PN_OFFSET @@ -525,12 +529,12 @@ def macsec_dp_poll(test, device_number=0, port_number=None, timeout=None, exp_pk continue # The device number of PTF host is 0, if the target port isn't a injected port(belong to ptf host), # Don't need to do MACsec further. - if ret.device != 0 or exp_pkt is None: + if ret.device != 0: return ret pkt = scapy.Ether(ret.packet) if pkt.haslayer(scapy.Ether): if pkt[scapy.Ether].type != 0x88e5: - if ptf.dataplane.match_exp_pkt(exp_pkt, pkt): + if exp_pkt is None or ptf.dataplane.match_exp_pkt(exp_pkt, pkt): return ret else: if ret.port in MACSEC_INFO and MACSEC_INFO[ret.port]: @@ -542,7 +546,7 @@ def macsec_dp_poll(test, device_number=0, port_number=None, timeout=None, exp_pk MACSEC_INFO[ret.port] force_reload[ret.port] = False pkt, decap_success = decap_macsec_pkt(pkt, sci, an, sak, encrypt, send_sci, 0, xpn_en, ssci, salt) - if decap_success and ptf.dataplane.match_exp_pkt(exp_pkt, pkt): + if exp_pkt is None or decap_success and ptf.dataplane.match_exp_pkt(exp_pkt, pkt): # Here we explicitly create the PollSuccess struct and send the pkt which us decoded # and the caller test can validate the pkt fields. Without this fix in case of macsec # the encrypted packet is being send back to caller which it will not be able to dissect diff --git a/tests/saitests/macsec.py b/tests/saitests/macsec.py index b80e973188a..75a3b42cb3d 100644 --- a/tests/saitests/macsec.py +++ b/tests/saitests/macsec.py @@ -28,6 +28,10 @@ def macsec_send(test, port_number, pkt, count=1): encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = \ MACSEC_INFOS[port_id] for n in range(count): + if isinstance(pkt, bytes): + # If in bytes, convert it to an Ether packet + pkt = scapy.Ether(pkt) + # Increment the PN by an offset so that the macsec frames are not late on DUT MACSEC_GLOBAL_PN_OFFSET += MACSEC_GLOBAL_PN_INCR pn += MACSEC_GLOBAL_PN_OFFSET @@ -95,11 +99,11 @@ def __macsec_dp_poll(test, device_number=0, port_number=None, timeout=None, exp_ continue # The device number of PTF host is 0, if the target port isn't a injected port(belong to ptf host), # Don't need to do MACsec further. - if ret.device != 0 or exp_pkt is None: + if ret.device != 0: return ret pkt = scapy.Ether(ret.packet) if pkt[scapy.Ether].type != 0x88e5: - if ptf.dataplane.match_exp_pkt(exp_pkt, pkt): + if exp_pkt is None or ptf.dataplane.match_exp_pkt(exp_pkt, pkt): return ret else: continue @@ -108,7 +112,7 @@ def __macsec_dp_poll(test, device_number=0, port_number=None, timeout=None, exp_ MACSEC_INFOS[ret.port] pkt, decap_success = __decap_macsec_pkt( pkt, sci, an, sak, encrypt, send_sci, 0, xpn_en, ssci, salt) - if decap_success and ptf.dataplane.match_exp_pkt(exp_pkt, pkt): + if exp_pkt is None or decap_success and ptf.dataplane.match_exp_pkt(exp_pkt, pkt): return ret recent_packets.append(pkt) packet_count += 1 From 7f922d58438109eb3833a8713294fff91673d833 Mon Sep 17 00:00:00 2001 From: Judy Joseph Date: Fri, 14 Mar 2025 17:47:35 +0000 Subject: [PATCH 12/24] Update the macsec errors to support multi-asic --- .../files/tools/loganalyzer/loganalyzer_common_ignore.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ansible/roles/test/files/tools/loganalyzer/loganalyzer_common_ignore.txt b/ansible/roles/test/files/tools/loganalyzer/loganalyzer_common_ignore.txt index 0a15a9daca2..27c2f0aed8d 100644 --- a/ansible/roles/test/files/tools/loganalyzer/loganalyzer_common_ignore.txt +++ b/ansible/roles/test/files/tools/loganalyzer/loganalyzer_common_ignore.txt @@ -43,9 +43,9 @@ r, ".* ERR swss#orchagent: :- querySwitchLagHashAlgorithmEnumCapabilities: Faile r, ".* ERR syncd\d*#syncd.*SAI_API_PORT:_brcm_sai_read_fec_stat_err_counters.* failed with error Feature unavailable.*" # White list below messages found on KVM for now. Need to address them later. -r, ".* ERR macsec#wpa_supplicant.*l2_packet_send.*Network is down.*" -r, ".* ERR macsec#wpa_supplicant.*could not process SIGINT or SIGTERM in two seconds.*" -r, ".* ERR macsec#wpa_supplicant.*KaY: Life time has not elapsed since prior SAK distributed.*" +r, ".* ERR macsec\d*#wpa_supplicant.*l2_packet_send.*Network is down.*" +r, ".* ERR macsec\d*#wpa_supplicant.*could not process SIGINT or SIGTERM in two seconds.*" +r, ".* ERR macsec\d*#wpa_supplicant.*KaY: Life time has not elapsed since prior SAK distributed.*" r, ".* ERR systemd.*Failed to start dhcp_relay container.*" r, ".* ERR monit.* 'rsyslog' failed to get service data.*" r, ".* ERR monit.* 'rsyslog' process is not running.*" From a793381cf396fe6949b8458b7723f81e54405c1d Mon Sep 17 00:00:00 2001 From: Judy Joseph Date: Fri, 14 Mar 2025 18:54:03 +0000 Subject: [PATCH 13/24] Changes moved to a different PR : #17530 --- ansible/config_sonic_basedon_testbed.yml | 1 + ansible/library/generate_golden_config_db.py | 2 +- ansible/library/get_macsec_profile.py | 32 ++------------------ ansible/roles/eos/tasks/ceos_config.yml | 1 - ansible/templates/minigraph_link_meta.j2 | 5 ++- ansible/templates/minigraph_meta.j2 | 2 +- 6 files changed, 8 insertions(+), 35 deletions(-) diff --git a/ansible/config_sonic_basedon_testbed.yml b/ansible/config_sonic_basedon_testbed.yml index 52334ce86f7..bcfb2ba242f 100644 --- a/ansible/config_sonic_basedon_testbed.yml +++ b/ansible/config_sonic_basedon_testbed.yml @@ -590,6 +590,7 @@ topo_name: "{{ topo }}" port_index_map: "{{ port_index_map | default({}) }}" become: true + when: "'t2' not in topo" - name: Copy macsec profile json to dut copy: src=../tests/common/macsec/profile.json diff --git a/ansible/library/generate_golden_config_db.py b/ansible/library/generate_golden_config_db.py index 4b619fc832b..ecec75f157a 100644 --- a/ansible/library/generate_golden_config_db.py +++ b/ansible/library/generate_golden_config_db.py @@ -386,7 +386,7 @@ def generate(self): elif self.topo_name == "t1-28-lag" or self.topo_name == "smartswitch-t1": config = self.generate_smartswitch_golden_config_db() self.module.run_command("sudo rm -f {}".format(TEMP_SMARTSWITCH_CONFIG_PATH)) - elif "t2" in self.topo_name and self.macsec_profile: + elif "t2" in self.topo_name: config = self.generate_t2_golden_config_db() self.module.run_command("sudo rm -f {}".format(MACSEC_PROFILE_PATH)) self.module.run_command("sudo rm -f {}".format(GOLDEN_CONFIG_TEMPLATE_PATH)) diff --git a/ansible/library/get_macsec_profile.py b/ansible/library/get_macsec_profile.py index 3c8d2d0257a..65b0cdb5a92 100644 --- a/ansible/library/get_macsec_profile.py +++ b/ansible/library/get_macsec_profile.py @@ -5,24 +5,7 @@ from ansible.module_utils.basic import AnsibleModule -def convert_to_eos(cipher_name): - # Set the cipher suite as 256 xpn by default - eos_cipher_name = 'aes256-gcm-xpn' - - if cipher_name == 'GCM-AES-XPN-256': - eos_cipher_name = 'aes256-gcm-xpn' - elif cipher_name == 'GCM-AES-128': - eos_cipher_name = 'aes128-gcm' - elif cipher_name == 'GCM-AES-256': - eos_cipher_name = 'aes256-gcm' - elif cipher_name == 'GCM-AES-XPN-128': - eos_cipher_name = 'aes128-gcm-xpn' - - return eos_cipher_name - - -# This API support EoS based templates now -def get_macsec_profile(module, macsec_profile, vm_type): +def get_macsec_profile(module, macsec_profile): with open('/tmp/profile.json') as f: macsec_profiles = json.load(f) @@ -30,23 +13,14 @@ def get_macsec_profile(module, macsec_profile, vm_type): if profile: profile['macsec_profile'] = macsec_profile - # Currently handling ceos, add more cases for vsonic etc - if vm_type == 'ceos': - # Get the cipher suite in eos terminology - eos_cipher_suite_name = convert_to_eos(profile['cipher_suite']) - profile['cipher_suite'] = eos_cipher_suite_name - return profile def main(): - module = AnsibleModule(argument_spec=dict( - macsec_profile=dict(required=True, type='str'), - vm_type=dict(required=True, type='str'))) + module = AnsibleModule(argument_spec=dict(macsec_profile=dict(required=True, type='str'))) macsec_profile = module.params['macsec_profile'] - vm_type = module.params['vm_type'] - module.exit_json(profile=get_macsec_profile(module, macsec_profile, vm_type), changed=False) + module.exit_json(profile=get_macsec_profile(module, macsec_profile), changed=False) if __name__ == "__main__": diff --git a/ansible/roles/eos/tasks/ceos_config.yml b/ansible/roles/eos/tasks/ceos_config.yml index faf748ebeca..2c55894ffb6 100644 --- a/ansible/roles/eos/tasks/ceos_config.yml +++ b/ansible/roles/eos/tasks/ceos_config.yml @@ -42,7 +42,6 @@ - name: Get the macsec profile data from profile_name get_macsec_profile: macsec_profile: "{{ macsec_profile }}" - vm_type: "{{ vm_type }}" register: profile_raw become: true when: "'t2' == base_topo and enable_macsec is defined" diff --git a/ansible/templates/minigraph_link_meta.j2 b/ansible/templates/minigraph_link_meta.j2 index 03d16937c90..51dd83c2e75 100644 --- a/ansible/templates/minigraph_link_meta.j2 +++ b/ansible/templates/minigraph_link_meta.j2 @@ -1,7 +1,6 @@ {%- set ns = namespace(link_metadata_defined=False) -%} -{% if 'dualtor' in topo or - (macsec_card is defined and enable_macsec is defined and macsec_card == True and 't2' in topo) %} +{%- if 'dualtor' in topo or (macsec_card is defined and macsec_card == True and 't2' in topo) -%} {% set ns.link_metadata_defined = True %} {%- endif -%} @@ -39,7 +38,7 @@ {% endfor %} {% endif %} -{% if macsec_card is defined and enable_macsec is defined and macsec_card == True and 't2' in topo %} +{% if macsec_card is defined and macsec_card == True and 't2' in topo %} {% for index in range(vms_number) %} {% set vm_intfs=vm_topo_config['vm'][vms[index]]['intfs'][dut_index|int]|sort %} {% set dut_intfs=vm_topo_config['vm'][vms[index]]['interface_indexes'][dut_index|int]|sort %} diff --git a/ansible/templates/minigraph_meta.j2 b/ansible/templates/minigraph_meta.j2 index 1fcbacc7cf5..4e8b1e4e1da 100644 --- a/ansible/templates/minigraph_meta.j2 +++ b/ansible/templates/minigraph_meta.j2 @@ -226,7 +226,7 @@ {{ switch_type }} {% endif %} -{% if macsec_card is defined and enable_macsec is defined and macsec_card == True and 't2' in topo %} +{% if macsec_card is defined and macsec_card == True and 't2' in topo %} MacSecProfile PrimaryKey="MACSEC_PROFILE" FallbackKey="macsec-profile2" MacsecPolicy="" From cd32d62c121c4b129a2558e02d2943b1ecc399ed Mon Sep 17 00:00:00 2001 From: Judy Joseph Date: Thu, 27 Mar 2025 04:04:30 +0000 Subject: [PATCH 14/24] flake fixes --- ansible/roles/test/files/ptftests/py3/IP_decap_test.py | 1 + ansible/roles/test/files/ptftests/py3/hash_test.py | 1 + ansible/roles/test/files/ptftests/py3/mtu_test.py | 1 + ansible/roles/test/files/ptftests/py3/pfc_pause_test.py | 1 + ansible/roles/test/files/ptftests/py3/pfc_wd.py | 1 + .../test/files/ptftests/py3/pfc_wd_background_traffic.py | 1 + .../test/files/ptftests/py3/pfcwd_background_traffic.py | 1 + tests/common/macsec/macsec_helper.py | 5 +++-- 8 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ansible/roles/test/files/ptftests/py3/IP_decap_test.py b/ansible/roles/test/files/ptftests/py3/IP_decap_test.py index a8c30b70995..1c72406ef3e 100644 --- a/ansible/roles/test/files/ptftests/py3/IP_decap_test.py +++ b/ansible/roles/test/files/ptftests/py3/IP_decap_test.py @@ -61,6 +61,7 @@ import macsec # noqa F401 + class DecapPacketTest(BaseTest): """ IP in IP decapsulation test """ diff --git a/ansible/roles/test/files/ptftests/py3/hash_test.py b/ansible/roles/test/files/ptftests/py3/hash_test.py index c90e25ba6aa..89a64095ad7 100644 --- a/ansible/roles/test/files/ptftests/py3/hash_test.py +++ b/ansible/roles/test/files/ptftests/py3/hash_test.py @@ -34,6 +34,7 @@ import lpm import macsec # noqa F401 + class HashTest(BaseTest): # --------------------------------------------------------------------- diff --git a/ansible/roles/test/files/ptftests/py3/mtu_test.py b/ansible/roles/test/files/ptftests/py3/mtu_test.py index 1aae902879d..a992ce75b78 100644 --- a/ansible/roles/test/files/ptftests/py3/mtu_test.py +++ b/ansible/roles/test/files/ptftests/py3/mtu_test.py @@ -29,6 +29,7 @@ simple_ip_packet, simple_tcpv6_packet, verify_packet_any_port import macsec # noqa F401 + class MtuTest(BaseTest): ''' @summary: Overview of functionality diff --git a/ansible/roles/test/files/ptftests/py3/pfc_pause_test.py b/ansible/roles/test/files/ptftests/py3/pfc_pause_test.py index 8f62b6d5fd5..49fd6ec1eff 100755 --- a/ansible/roles/test/files/ptftests/py3/pfc_pause_test.py +++ b/ansible/roles/test/files/ptftests/py3/pfc_pause_test.py @@ -14,6 +14,7 @@ from ptf.testutils import add_filter, reset_filters, dp_poll, simple_udp_packet, send_packet, test_params_get import macsec # noqa F401 + def udp_filter(pkt_str): try: pkt = scapy.Ether(pkt_str) diff --git a/ansible/roles/test/files/ptftests/py3/pfc_wd.py b/ansible/roles/test/files/ptftests/py3/pfc_wd.py index 3328a97d5e7..3df0e7c2fae 100644 --- a/ansible/roles/test/files/ptftests/py3/pfc_wd.py +++ b/ansible/roles/test/files/ptftests/py3/pfc_wd.py @@ -12,6 +12,7 @@ from ptf.testutils import test_params_get, simple_tcp_packet, send_packet, verify_no_packet_any, verify_packet_any_port import macsec # noqa F401 + class PfcWdTest(BaseTest): def __init__(self): BaseTest.__init__(self) diff --git a/ansible/roles/test/files/ptftests/py3/pfc_wd_background_traffic.py b/ansible/roles/test/files/ptftests/py3/pfc_wd_background_traffic.py index 2411fc8a9da..1d5c749af76 100644 --- a/ansible/roles/test/files/ptftests/py3/pfc_wd_background_traffic.py +++ b/ansible/roles/test/files/ptftests/py3/pfc_wd_background_traffic.py @@ -6,6 +6,7 @@ from ptf.testutils import test_params_get, simple_udp_packet, send_packet import macsec # noqa F401 + class PfcWdBackgroundTrafficTest(BaseTest): def __init__(self): BaseTest.__init__(self) diff --git a/ansible/roles/test/files/ptftests/py3/pfcwd_background_traffic.py b/ansible/roles/test/files/ptftests/py3/pfcwd_background_traffic.py index 5e73cb5e885..68a569e78e0 100644 --- a/ansible/roles/test/files/ptftests/py3/pfcwd_background_traffic.py +++ b/ansible/roles/test/files/ptftests/py3/pfcwd_background_traffic.py @@ -31,6 +31,7 @@ import ptf import macsec # noqa F401 + class BG_pkt_sender(BaseTest): def __init__(self): BaseTest.__init__(self) diff --git a/tests/common/macsec/macsec_helper.py b/tests/common/macsec/macsec_helper.py index 5ff65de4b66..1745136fb13 100644 --- a/tests/common/macsec/macsec_helper.py +++ b/tests/common/macsec/macsec_helper.py @@ -540,8 +540,9 @@ def macsec_dp_poll(test, device_number=0, port_number=None, timeout=None, exp_pk if ret.port in MACSEC_INFO and MACSEC_INFO[ret.port]: # Reload the macsec session if the session was restarted if force_reload[ret.port]: - load_macsec_info_for_ptf_id(test.duthost, ret.port, - find_portname_from_ptf_id(test.mg_facts, ret.port), force_reload[ret.port]) + load_macsec_info_for_ptf_id( + test.duthost, ret.port, find_portname_from_ptf_id(test.mg_facts, ret.port), + force_reload[ret.port]) encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = \ MACSEC_INFO[ret.port] force_reload[ret.port] = False From 90ac7f4f1fa6dc3ffcf6e8f4b417fdc517a991cb Mon Sep 17 00:00:00 2001 From: Judy Joseph Date: Thu, 27 Mar 2025 06:40:26 +0000 Subject: [PATCH 15/24] Remove redundant macsec.py files - make it all point to ansible/roles/test/files/ptftests/macsec.py --- ansible/roles/test/files/acstests/macsec.py | 132 ------------------ .../roles/test/files/acstests/py3/macsec.py | 2 +- tests/saitests/macsec.py | 131 ----------------- tests/saitests/py3/macsec.py | 2 +- 4 files changed, 2 insertions(+), 265 deletions(-) delete mode 100644 ansible/roles/test/files/acstests/macsec.py delete mode 100644 tests/saitests/macsec.py diff --git a/ansible/roles/test/files/acstests/macsec.py b/ansible/roles/test/files/acstests/macsec.py deleted file mode 100644 index 00b0e11eaac..00000000000 --- a/ansible/roles/test/files/acstests/macsec.py +++ /dev/null @@ -1,132 +0,0 @@ -import os -import pickle -import cryptography.exceptions -import time - -import ptf -import scapy.all as scapy -MACSEC_SUPPORTED = False -if hasattr(scapy, "VERSION") and tuple(map(int, scapy.VERSION.split('.'))) >= (2, 4, 5): - MACSEC_SUPPORTED = True -if MACSEC_SUPPORTED: - import scapy.contrib.macsec as scapy_macsec - -MACSEC_INFO_FILE = "macsec_info.pickle" -MACSEC_GLOBAL_PN_OFFSET = 1000 -MACSEC_GLOBAL_PN_INCR = 100 - -MACSEC_INFOS = {} - - -def macsec_send(test, port_number, pkt, count=1): - # Check if the port is macsec enabled, if so send the macsec encap/encrypted frame - global MACSEC_GLOBAL_PN_OFFSET - global MACSEC_GLOBAL_PN_INCR - - device, port_id = ptf.testutils.port_to_tuple(port_number) - if port_id in MACSEC_INFOS and MACSEC_INFOS[port_id]: - encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = \ - MACSEC_INFOS[port_id] - - for n in range(count): - if isinstance(pkt, bytes): - # If in bytes, convert it to an Ether packet - pkt = scapy.Ether(pkt) - - # Increment the PN by an offset so that the macsec frames are not late on DUT - MACSEC_GLOBAL_PN_OFFSET += MACSEC_GLOBAL_PN_INCR - pn += MACSEC_GLOBAL_PN_OFFSET - - macsec_pkt = encap_macsec_pkt(pkt, peer_sci, peer_an, sak, encrypt, send_sci, pn, xpn_en, peer_ssci, salt) - # send the packet - __origin_send_packet(test, port_number, macsec_pkt, 1) - else: - # send the packet - __origin_send_packet(test, port_number, pkt, count) - - -def encap_macsec_pkt(macsec_pkt, sci, an, sak, encrypt, send_sci, pn, xpn_en=False, ssci=None, salt=None): - sa = scapy_macsec.MACsecSA(sci=sci, - an=an, - pn=pn, - key=sak, - icvlen=16, - encrypt=encrypt, - send_sci=send_sci, - xpn_en=xpn_en, - ssci=ssci, - salt=salt) - macsec_pkt = sa.encap(macsec_pkt) - pkt = sa.encrypt(macsec_pkt) - return pkt - - -def __decap_macsec_pkt(macsec_pkt, sci, an, sak, encrypt, send_sci, pn, xpn_en=False, ssci=None, salt=None): - sa = scapy_macsec.MACsecSA(sci=sci, - an=an, - pn=pn, - key=sak, - icvlen=16, - encrypt=encrypt, - send_sci=send_sci, - xpn_en=xpn_en, - ssci=ssci, - salt=salt) - try: - pkt = sa.decrypt(macsec_pkt) - except cryptography.exceptions.InvalidTag: - # Invalid MACsec packets - return macsec_pkt, False - pkt = sa.decap(pkt) - return pkt, True - - -def __macsec_dp_poll(test, device_number=0, port_number=None, timeout=None, exp_pkt=None): - recent_packets = [] - packet_count = 0 - if timeout is None: - timeout = ptf.ptfutils.default_timeout - while True: - start_time = time.time() - ret = __origin_dp_poll( - test, device_number=device_number, port_number=port_number, timeout=timeout, exp_pkt=None) - timeout -= time.time() - start_time - # Since we call __origin_dp_poll with exp_pkt=None, it should only ever fail if no packets are received at all. - # In this case, continue normally until we exceed the timeout value provided to macsec_dp_poll. - if isinstance(ret, test.dataplane.PollFailure): - if timeout <= 0: - break - else: - continue - # The device number of PTF host is 0, if the target port isn't a injected port(belong to ptf host), - # Don't need to do MACsec further. - if ret.device != 0: - return ret - pkt = scapy.Ether(ret.packet) - if pkt[scapy.Ether].type != 0x88e5: - if exp_pkt is None or ptf.dataplane.match_exp_pkt(exp_pkt, pkt): - return ret - else: - continue - if ret.port in MACSEC_INFOS and MACSEC_INFOS[ret.port]: - encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = \ - MACSEC_INFOS[ret.port] - pkt, decap_success = __decap_macsec_pkt( - pkt, sci, an, sak, encrypt, send_sci, 0, xpn_en, ssci, salt) - if exp_pkt is None or decap_success and ptf.dataplane.match_exp_pkt(exp_pkt, pkt): - return ret - recent_packets.append(pkt) - packet_count += 1 - if timeout <= 0: - break - return test.dataplane.PollFailure(exp_pkt, recent_packets, packet_count) - - -if MACSEC_SUPPORTED and os.path.exists(MACSEC_INFO_FILE): - with open(MACSEC_INFO_FILE, "rb") as f: - MACSEC_INFOS = pickle.load(f, encoding="bytes") - if MACSEC_INFOS: - __origin_dp_poll = ptf.testutils.dp_poll - ptf.testutils.dp_poll = __macsec_dp_poll - __origin_send_packet = ptf.testutils.send_packet - ptf.testutils.send_packet = macsec_send diff --git a/ansible/roles/test/files/acstests/py3/macsec.py b/ansible/roles/test/files/acstests/py3/macsec.py index f8db57172ed..f046b126bc3 120000 --- a/ansible/roles/test/files/acstests/py3/macsec.py +++ b/ansible/roles/test/files/acstests/py3/macsec.py @@ -1 +1 @@ -../macsec.py \ No newline at end of file +../../ptftests/macsec.py \ No newline at end of file diff --git a/tests/saitests/macsec.py b/tests/saitests/macsec.py deleted file mode 100644 index 75a3b42cb3d..00000000000 --- a/tests/saitests/macsec.py +++ /dev/null @@ -1,131 +0,0 @@ -import os -import pickle -import cryptography.exceptions -import time - -import ptf -import scapy.all as scapy -MACSEC_SUPPORTED = False -if hasattr(scapy, "VERSION") and tuple(map(int, scapy.VERSION.split('.'))) >= (2, 4, 5): - MACSEC_SUPPORTED = True -if MACSEC_SUPPORTED: - import scapy.contrib.macsec as scapy_macsec - -MACSEC_INFO_FILE = "macsec_info.pickle" -MACSEC_GLOBAL_PN_OFFSET = 1000 -MACSEC_GLOBAL_PN_INCR = 100 - -MACSEC_INFOS = {} - - -def macsec_send(test, port_number, pkt, count=1): - # Check if the port is macsec enabled, if so send the macsec encap/encrypted frame - global MACSEC_GLOBAL_PN_OFFSET - global MACSEC_GLOBAL_PN_INCR - - device, port_id = ptf.testutils.port_to_tuple(port_number) - if port_id in MACSEC_INFOS and MACSEC_INFOS[port_id]: - encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = \ - MACSEC_INFOS[port_id] - for n in range(count): - if isinstance(pkt, bytes): - # If in bytes, convert it to an Ether packet - pkt = scapy.Ether(pkt) - - # Increment the PN by an offset so that the macsec frames are not late on DUT - MACSEC_GLOBAL_PN_OFFSET += MACSEC_GLOBAL_PN_INCR - pn += MACSEC_GLOBAL_PN_OFFSET - - macsec_pkt = encap_macsec_pkt(pkt, peer_sci, peer_an, sak, encrypt, send_sci, pn, xpn_en, peer_ssci, salt) - # send the packet - __origin_send_packet(test, port_number, macsec_pkt, 1) - else: - # send the packet - __origin_send_packet(test, port_number, pkt, count) - - -def encap_macsec_pkt(macsec_pkt, sci, an, sak, encrypt, send_sci, pn, xpn_en=False, ssci=None, salt=None): - sa = scapy_macsec.MACsecSA(sci=sci, - an=an, - pn=pn, - key=sak, - icvlen=16, - encrypt=encrypt, - send_sci=send_sci, - xpn_en=xpn_en, - ssci=ssci, - salt=salt) - macsec_pkt = sa.encap(macsec_pkt) - pkt = sa.encrypt(macsec_pkt) - return pkt - - -def __decap_macsec_pkt(macsec_pkt, sci, an, sak, encrypt, send_sci, pn, xpn_en=False, ssci=None, salt=None): - sa = scapy_macsec.MACsecSA(sci=sci, - an=an, - pn=pn, - key=sak, - icvlen=16, - encrypt=encrypt, - send_sci=send_sci, - xpn_en=xpn_en, - ssci=ssci, - salt=salt) - try: - pkt = sa.decrypt(macsec_pkt) - except cryptography.exceptions.InvalidTag: - # Invalid MACsec packets - return macsec_pkt, False - pkt = sa.decap(pkt) - return pkt, True - - -def __macsec_dp_poll(test, device_number=0, port_number=None, timeout=None, exp_pkt=None): - recent_packets = [] - packet_count = 0 - if timeout is None: - timeout = ptf.ptfutils.default_timeout - while True: - start_time = time.time() - ret = __origin_dp_poll( - test, device_number=device_number, port_number=port_number, timeout=timeout, exp_pkt=None) - timeout -= time.time() - start_time - # Since we call __origin_dp_poll with exp_pkt=None, it should only ever fail if no packets are received at all. - # In this case, continue normally until we exceed the timeout value provided to macsec_dp_poll. - if isinstance(ret, test.dataplane.PollFailure): - if timeout <= 0: - break - else: - continue - # The device number of PTF host is 0, if the target port isn't a injected port(belong to ptf host), - # Don't need to do MACsec further. - if ret.device != 0: - return ret - pkt = scapy.Ether(ret.packet) - if pkt[scapy.Ether].type != 0x88e5: - if exp_pkt is None or ptf.dataplane.match_exp_pkt(exp_pkt, pkt): - return ret - else: - continue - if ret.port in MACSEC_INFOS and MACSEC_INFOS[ret.port]: - encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = \ - MACSEC_INFOS[ret.port] - pkt, decap_success = __decap_macsec_pkt( - pkt, sci, an, sak, encrypt, send_sci, 0, xpn_en, ssci, salt) - if exp_pkt is None or decap_success and ptf.dataplane.match_exp_pkt(exp_pkt, pkt): - return ret - recent_packets.append(pkt) - packet_count += 1 - if timeout <= 0: - break - return test.dataplane.PollFailure(exp_pkt, recent_packets, packet_count) - - -if MACSEC_SUPPORTED and os.path.exists(MACSEC_INFO_FILE): - with open(MACSEC_INFO_FILE, "rb") as f: - MACSEC_INFOS = pickle.load(f, encoding="bytes") - if MACSEC_INFOS: - __origin_dp_poll = ptf.testutils.dp_poll - ptf.testutils.dp_poll = __macsec_dp_poll - __origin_send_packet = ptf.testutils.send_packet - ptf.testutils.send_packet = macsec_send diff --git a/tests/saitests/py3/macsec.py b/tests/saitests/py3/macsec.py index f8db57172ed..c79e8fdec53 120000 --- a/tests/saitests/py3/macsec.py +++ b/tests/saitests/py3/macsec.py @@ -1 +1 @@ -../macsec.py \ No newline at end of file +../../../ansible/roles/test/files/ptftests/macsec.py \ No newline at end of file From 6bb0f29728dd0e4ac5798ea78e1e96136eef2917 Mon Sep 17 00:00:00 2001 From: Judy Joseph Date: Tue, 1 Apr 2025 15:45:09 +0000 Subject: [PATCH 16/24] Fix already made via PR : https://github.com/sonic-net/sonic-mgmt/pull/17637 --- .../files/tools/loganalyzer/loganalyzer_common_ignore.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ansible/roles/test/files/tools/loganalyzer/loganalyzer_common_ignore.txt b/ansible/roles/test/files/tools/loganalyzer/loganalyzer_common_ignore.txt index 27c2f0aed8d..0a15a9daca2 100644 --- a/ansible/roles/test/files/tools/loganalyzer/loganalyzer_common_ignore.txt +++ b/ansible/roles/test/files/tools/loganalyzer/loganalyzer_common_ignore.txt @@ -43,9 +43,9 @@ r, ".* ERR swss#orchagent: :- querySwitchLagHashAlgorithmEnumCapabilities: Faile r, ".* ERR syncd\d*#syncd.*SAI_API_PORT:_brcm_sai_read_fec_stat_err_counters.* failed with error Feature unavailable.*" # White list below messages found on KVM for now. Need to address them later. -r, ".* ERR macsec\d*#wpa_supplicant.*l2_packet_send.*Network is down.*" -r, ".* ERR macsec\d*#wpa_supplicant.*could not process SIGINT or SIGTERM in two seconds.*" -r, ".* ERR macsec\d*#wpa_supplicant.*KaY: Life time has not elapsed since prior SAK distributed.*" +r, ".* ERR macsec#wpa_supplicant.*l2_packet_send.*Network is down.*" +r, ".* ERR macsec#wpa_supplicant.*could not process SIGINT or SIGTERM in two seconds.*" +r, ".* ERR macsec#wpa_supplicant.*KaY: Life time has not elapsed since prior SAK distributed.*" r, ".* ERR systemd.*Failed to start dhcp_relay container.*" r, ".* ERR monit.* 'rsyslog' failed to get service data.*" r, ".* ERR monit.* 'rsyslog' process is not running.*" From 20441a14fbaf28a2519d21809f8840a69a154d57 Mon Sep 17 00:00:00 2001 From: Judy Joseph Date: Tue, 1 Apr 2025 21:11:40 +0000 Subject: [PATCH 17/24] swap port_id and port_number for macsec_send call --- ansible/roles/test/files/ptftests/macsec.py | 12 ++++++------ tests/common/macsec/macsec_helper.py | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ansible/roles/test/files/ptftests/macsec.py b/ansible/roles/test/files/ptftests/macsec.py index 00b0e11eaac..8622f1b5835 100644 --- a/ansible/roles/test/files/ptftests/macsec.py +++ b/ansible/roles/test/files/ptftests/macsec.py @@ -18,15 +18,15 @@ MACSEC_INFOS = {} -def macsec_send(test, port_number, pkt, count=1): +def macsec_send(test, port_id, pkt, count=1): # Check if the port is macsec enabled, if so send the macsec encap/encrypted frame global MACSEC_GLOBAL_PN_OFFSET global MACSEC_GLOBAL_PN_INCR - device, port_id = ptf.testutils.port_to_tuple(port_number) - if port_id in MACSEC_INFOS and MACSEC_INFOS[port_id]: + device, port_number = ptf.testutils.port_to_tuple(port_id) + if port_number in MACSEC_INFOS and MACSEC_INFOS[port_number]: encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = \ - MACSEC_INFOS[port_id] + MACSEC_INFOS[port_number] for n in range(count): if isinstance(pkt, bytes): @@ -39,10 +39,10 @@ def macsec_send(test, port_number, pkt, count=1): macsec_pkt = encap_macsec_pkt(pkt, peer_sci, peer_an, sak, encrypt, send_sci, pn, xpn_en, peer_ssci, salt) # send the packet - __origin_send_packet(test, port_number, macsec_pkt, 1) + __origin_send_packet(test, port_id, macsec_pkt, 1) else: # send the packet - __origin_send_packet(test, port_number, pkt, count) + __origin_send_packet(test, port_id, pkt, count) def encap_macsec_pkt(macsec_pkt, sci, an, sak, encrypt, send_sci, pn, xpn_en=False, ssci=None, salt=None): diff --git a/tests/common/macsec/macsec_helper.py b/tests/common/macsec/macsec_helper.py index 1745136fb13..fcf5bdae572 100644 --- a/tests/common/macsec/macsec_helper.py +++ b/tests/common/macsec/macsec_helper.py @@ -480,14 +480,14 @@ def load_all_macsec_info(duthost, ctrl_links, tbinfo): MACSEC_INFO[ptf_id] = get_macsec_attr(duthost, port) -def macsec_send(test, port_number, pkt, count=1): +def macsec_send(test, port_id, pkt, count=1): global MACSEC_GLOBAL_PN_OFFSET global MACSEC_GLOBAL_PN_INCR # Check if the port is macsec enabled, if so send the macsec encap/encrypted frame - device, port_id = testutils.port_to_tuple(port_number) - if port_id in MACSEC_INFO and MACSEC_INFO[port_id]: - encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = MACSEC_INFO[port_id] + device, port_number = testutils.port_to_tuple(port_id) + if port_number in MACSEC_INFO and MACSEC_INFO[port_number]: + encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = MACSEC_INFO[port_number] for n in range(count): if isinstance(pkt, bytes): @@ -500,10 +500,10 @@ def macsec_send(test, port_number, pkt, count=1): macsec_pkt = encap_macsec_pkt(pkt, peer_sci, peer_an, sak, encrypt, send_sci, pn, xpn_en, peer_ssci, salt) # send the packet - __origin_send_packet(test, port_number, macsec_pkt, 1) + __origin_send_packet(test, port_id, macsec_pkt, 1) else: # send the packet - __origin_send_packet(test, port_number, pkt, count) + __origin_send_packet(test, port_id, pkt, count) def macsec_dp_poll(test, device_number=0, port_number=None, timeout=None, exp_pkt=None): From 5d0194b6f58cd2a15d0678bb5d2a8ec4f23e1890 Mon Sep 17 00:00:00 2001 From: Judy Joseph Date: Thu, 3 Apr 2025 18:55:48 +0000 Subject: [PATCH 18/24] Take care of T0 macsec tests as well, so that t0-sonic is fine --- tests/common/macsec/__init__.py | 18 ++++++++---- tests/common/macsec/macsec_config_helper.py | 31 +++++++++++++++++++++ 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/tests/common/macsec/__init__.py b/tests/common/macsec/__init__.py index 8d336273ec5..a3faa69e303 100644 --- a/tests/common/macsec/__init__.py +++ b/tests/common/macsec/__init__.py @@ -16,6 +16,7 @@ from .macsec_config_helper import disable_macsec_feature from .macsec_config_helper import setup_macsec_configuration from .macsec_config_helper import cleanup_macsec_configuration +from .macsec_config_helper import is_macsec_configured from .macsec_config_helper import get_macsec_enable_status, get_macsec_profile from .macsec_helper import load_all_macsec_info @@ -81,11 +82,6 @@ def macsec_feature(self, start_macsec_service, stop_macsec_service): yield stop_macsec_service() - @pytest.fixture(scope="module", autouse=True) - def load_macsec_info(self, request, macsec_duthost, ctrl_links, tbinfo): - if get_macsec_enable_status(macsec_duthost) and get_macsec_profile(macsec_duthost): - load_all_macsec_info(macsec_duthost, ctrl_links, tbinfo) - @pytest.fixture(scope="module") def startup_macsec(self, request, macsec_duthost, ctrl_links, macsec_profile, tbinfo): topo_name = tbinfo['topo']['name'] @@ -124,6 +120,14 @@ def macsec_setup(self, startup_macsec, shutdown_macsec, macsec_feature): yield shutdown_macsec() + @pytest.fixture(scope="module", autouse=True) + def load_macsec_info(self, request, macsec_duthost, ctrl_links, macsec_profile, tbinfo): + if get_macsec_enable_status(macsec_duthost) and get_macsec_profile(macsec_duthost): + if is_macsec_configured(macsec_duthost, ctrl_links): + load_all_macsec_info(macsec_duthost, ctrl_links, tbinfo) + else: + request.getfixturevalue('macsec_setup') + @pytest.fixture(scope="module") def macsec_nbrhosts(self, ctrl_links): return {nbr["name"]: nbr for nbr in list(ctrl_links.values())} @@ -259,8 +263,10 @@ def __init__(self): super(MacsecPluginT2, self).__init__() def get_ctrl_nbr_names(self, macsec_duthost, nbrhosts, tbinfo): + ctrl_nbr_names = [] mg_facts = macsec_duthost.get_extended_minigraph_facts(tbinfo) - ctrl_nbr_names = mg_facts['macsec_neighbors'] + if 'macsec_neighbors' in mg_facts: + ctrl_nbr_names = mg_facts['macsec_neighbors'] return ctrl_nbr_names def downstream_neighbor(self,tbinfo, neighbor): diff --git a/tests/common/macsec/macsec_config_helper.py b/tests/common/macsec/macsec_config_helper.py index 03741c5c860..491ea9b4d1e 100644 --- a/tests/common/macsec/macsec_config_helper.py +++ b/tests/common/macsec/macsec_config_helper.py @@ -81,6 +81,37 @@ def set_macsec_profile(host, port, profile_name, priority, cipher_suite, host.command("lldpcli configure system bond-slave-src-mac-type real") +def is_macsec_configured(host, ctrl_links): + is_profile_present = False + is_port_profile_present = False + + profile_name = get_macsec_profile(host) + if profile_name is None: + return False + + # Check macsec profile is configured in all namespaces + if host.is_multi_asic: + for ns in host.get_asic_namespace_list(): + CMD_PREFIX = "-n {}".format(ns) if ns is not None else " " + cmd = "sonic-db-cli {} CONFIG_DB KEYS 'MACSEC_PROFILE|{}'".format(CMD_PREFIX, profile_name) + output = host.command(cmd)['stdout'].strip() + profile = output.split('|')[1] if output else None + is_profile_present = (profile == profile_name) + else: + cmd = "sonic-db-cli CONFIG_DB HGET 'MACSEC_PROFILE|{}'".format(profile_name) + output = host.command(cmd)['stdout'].strip() + profile = output.split('|')[1] if output else None + is_profile_present = (profile == profile_name) + + # Check if macsec profile is configured on interfaces + for port, nbr in ctrl_links.items(): + cmd = "sonic-db-cli {} CONFIG_DB HGET 'PORT|{}' 'macsec' ".format(getns_prefix(host, port), port) + output = host.command(cmd)['stdout'].strip() + is_port_profile_present = (output == profile_name) + + return is_profile_present and is_port_profile_present + + def delete_macsec_profile(host, port, profile_name): if isinstance(host, EosHost): host.eos_config( From 3206c7b5b933e6116936464fdff4b8b242c148b6 Mon Sep 17 00:00:00 2001 From: Judy Joseph Date: Fri, 4 Apr 2025 02:45:24 +0000 Subject: [PATCH 19/24] Additional fix to support multiple profile names given as input --- tests/common/macsec/__init__.py | 2 +- tests/common/macsec/macsec_config_helper.py | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/common/macsec/__init__.py b/tests/common/macsec/__init__.py index a3faa69e303..1cad935eab3 100644 --- a/tests/common/macsec/__init__.py +++ b/tests/common/macsec/__init__.py @@ -123,7 +123,7 @@ def macsec_setup(self, startup_macsec, shutdown_macsec, macsec_feature): @pytest.fixture(scope="module", autouse=True) def load_macsec_info(self, request, macsec_duthost, ctrl_links, macsec_profile, tbinfo): if get_macsec_enable_status(macsec_duthost) and get_macsec_profile(macsec_duthost): - if is_macsec_configured(macsec_duthost, ctrl_links): + if is_macsec_configured(macsec_duthost, macsec_profile, ctrl_links): load_all_macsec_info(macsec_duthost, ctrl_links, tbinfo) else: request.getfixturevalue('macsec_setup') diff --git a/tests/common/macsec/macsec_config_helper.py b/tests/common/macsec/macsec_config_helper.py index 491ea9b4d1e..7417d4f60fb 100644 --- a/tests/common/macsec/macsec_config_helper.py +++ b/tests/common/macsec/macsec_config_helper.py @@ -81,13 +81,10 @@ def set_macsec_profile(host, port, profile_name, priority, cipher_suite, host.command("lldpcli configure system bond-slave-src-mac-type real") -def is_macsec_configured(host, ctrl_links): +def is_macsec_configured(host, mac_profile, ctrl_links): is_profile_present = False is_port_profile_present = False - - profile_name = get_macsec_profile(host) - if profile_name is None: - return False + profile_name = mac_profile['name'] # Check macsec profile is configured in all namespaces if host.is_multi_asic: From 9a1c9960bd377bd3f473487b374f2d3835244f72 Mon Sep 17 00:00:00 2001 From: Judy Joseph Date: Fri, 4 Apr 2025 16:48:55 +0000 Subject: [PATCH 20/24] Use the right command KEYS instead of HGET --- tests/common/macsec/macsec_config_helper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/common/macsec/macsec_config_helper.py b/tests/common/macsec/macsec_config_helper.py index 7417d4f60fb..412b724b89a 100644 --- a/tests/common/macsec/macsec_config_helper.py +++ b/tests/common/macsec/macsec_config_helper.py @@ -95,7 +95,7 @@ def is_macsec_configured(host, mac_profile, ctrl_links): profile = output.split('|')[1] if output else None is_profile_present = (profile == profile_name) else: - cmd = "sonic-db-cli CONFIG_DB HGET 'MACSEC_PROFILE|{}'".format(profile_name) + cmd = "sonic-db-cli CONFIG_DB KEYS 'MACSEC_PROFILE|{}'".format(profile_name) output = host.command(cmd)['stdout'].strip() profile = output.split('|')[1] if output else None is_profile_present = (profile == profile_name) From cf47a733b56689ea45ea64a1bf185af8632700ea Mon Sep 17 00:00:00 2001 From: Judy Joseph Date: Mon, 14 Apr 2025 06:25:12 +0000 Subject: [PATCH 21/24] Update comment, use macsec_card to set MacSecEnabled in DeviceMetadata --- ansible/templates/minigraph_meta.j2 | 2 +- tests/acl/test_acl.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ansible/templates/minigraph_meta.j2 b/ansible/templates/minigraph_meta.j2 index 4e8b1e4e1da..040d68ba33c 100644 --- a/ansible/templates/minigraph_meta.j2 +++ b/ansible/templates/minigraph_meta.j2 @@ -31,7 +31,7 @@ MacSecEnabled -{% if dut_index|int == 0 %} +{% if macsec_card is defined and enable_macsec is defined and macsec_card == True and 't2' in topo %} True {% else %} False diff --git a/tests/acl/test_acl.py b/tests/acl/test_acl.py index 6c075e2f072..fd07e810806 100644 --- a/tests/acl/test_acl.py +++ b/tests/acl/test_acl.py @@ -442,8 +442,7 @@ def setup(duthosts, ptfhost, rand_selected_dut, rand_unselected_dut, tbinfo, ptf for duthost in duthosts: duthost.command("mkdir -p {}".format(DUT_TMP_DIR)) - # Reload macsec config if enable_macsec is set for this test run - # If macsec is enabled, use the override option to get macsec profile from golden config + # Set the flag force_reload_macsec to True, if enable_macsec is set for this test run if is_macsec_enabled_for_test: setattr(ptfadapter, "force_reload_macsec", True) From 2f586c249b160287d219e1e85466d06e359091e0 Mon Sep 17 00:00:00 2001 From: Judy Joseph Date: Thu, 17 Apr 2025 23:40:13 +0000 Subject: [PATCH 22/24] Remove extra line in auto merge --- tests/acl/test_acl.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/acl/test_acl.py b/tests/acl/test_acl.py index 76edf9636b3..6cf9132ae10 100644 --- a/tests/acl/test_acl.py +++ b/tests/acl/test_acl.py @@ -263,7 +263,6 @@ def get_t2_info(duthosts, tbinfo): @pytest.fixture(scope="module") - def setup(duthosts, ptfhost, rand_selected_dut, rand_selected_front_end_dut, rand_unselected_dut, tbinfo, ptfadapter, topo_scenario, vlan_name, is_macsec_enabled_for_test): """Gather all required test information from DUT and tbinfo. From 77da26c31bcb0bca206c65a55cd743463dbbb484 Mon Sep 17 00:00:00 2001 From: Judy Joseph Date: Tue, 22 Apr 2025 21:06:23 +0000 Subject: [PATCH 23/24] Skip ACL egress tests when run on macsec enabled toplogy with braodcom DNX --- tests/acl/test_acl.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/acl/test_acl.py b/tests/acl/test_acl.py index 6cf9132ae10..ef195b07ceb 100644 --- a/tests/acl/test_acl.py +++ b/tests/acl/test_acl.py @@ -530,13 +530,14 @@ def populate_arp_table(): @pytest.fixture(scope="module", params=["ingress", "egress"]) -def stage(request, duthosts, rand_one_dut_hostname, tbinfo): +def stage(request, duthosts, rand_one_dut_hostname, tbinfo, is_macsec_enabled_for_test): """Parametrize tests for Ingress/Egress stage testing. Args: request: A fixture to interact with Pytest data. duthosts: All DUTs belong to the testbed. rand_one_dut_hostname: hostname of a random chosen dut to run test. + is_macsec_enabled_for_test: flag for macsec topology selected for run. Returns: str: The ACL stage to be tested. @@ -549,6 +550,11 @@ def stage(request, duthosts, rand_one_dut_hostname, tbinfo): "Egress ACLs are not currently supported on \"{}\" ASICs".format(duthost.facts["asic_type"]) ) + # Skip ACL egress tests when run on macsec enabled toplogy with braodcom DNX + if request.param == "egress" and is_macsec_enabled_for_test and \ + duthost.facts.get("platform_asic") == "broadcom-dnx": + pytest.skip("Egress ACLs not supported with MACSEC on \"{}\" ASICs".format(duthost.facts["asic_type"])) + return request.param From 9464f9cdf95e6ad6776d81981fe7b7ffd14fa3cd Mon Sep 17 00:00:00 2001 From: Judy Joseph Date: Tue, 22 Apr 2025 21:18:13 +0000 Subject: [PATCH 24/24] Fix flake error --- tests/acl/test_acl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/acl/test_acl.py b/tests/acl/test_acl.py index ef195b07ceb..bd019db6a92 100644 --- a/tests/acl/test_acl.py +++ b/tests/acl/test_acl.py @@ -552,7 +552,7 @@ def stage(request, duthosts, rand_one_dut_hostname, tbinfo, is_macsec_enabled_fo # Skip ACL egress tests when run on macsec enabled toplogy with braodcom DNX if request.param == "egress" and is_macsec_enabled_for_test and \ - duthost.facts.get("platform_asic") == "broadcom-dnx": + duthost.facts.get("platform_asic") == "broadcom-dnx": pytest.skip("Egress ACLs not supported with MACSEC on \"{}\" ASICs".format(duthost.facts["asic_type"])) return request.param