From acc55cc39f1336ab0c2749041f2199957b8f171e Mon Sep 17 00:00:00 2001 From: Azarack Date: Fri, 7 Jun 2024 20:42:42 +0000 Subject: [PATCH 01/10] submit for pr --- docs/testplan/MACsec-test-plan.md | 6 ++ tests/macsec/__init__.py | 8 +- tests/macsec/macsec_config_helper.py | 2 +- tests/macsec/test_static_key_ciphers.py | 131 ++++++++++++++++++++++++ 4 files changed, 142 insertions(+), 5 deletions(-) create mode 100644 tests/macsec/test_static_key_ciphers.py diff --git a/docs/testplan/MACsec-test-plan.md b/docs/testplan/MACsec-test-plan.md index 721f5007633..3578f434ff8 100644 --- a/docs/testplan/MACsec-test-plan.md +++ b/docs/testplan/MACsec-test-plan.md @@ -505,3 +505,9 @@ The switch should only react encrypted PFC frames, send encrypted PFC frames. #### Macsec enabled on all interfaces and the DUT is rebooted - Check the macsec docker comes up and macsec sessions are established. + +### Testcase : Static Key Ciphers + +- Cycle through each macsec profile listed in the profiles.json file + - Disable previous profile and configure new one + - Verify macsec connection between peers comes online diff --git a/tests/macsec/__init__.py b/tests/macsec/__init__.py index 5d07d12056a..86c56266c2f 100644 --- a/tests/macsec/__init__.py +++ b/tests/macsec/__init__.py @@ -127,7 +127,7 @@ def ctrl_links(self, macsec_duthost, tbinfo, nbrhosts): topo_name = tbinfo['topo']['name'] pytest.skip("None of neighbors on topology {}".format(topo_name)) - ctrl_nbr_names = self.get_ctrl_nbr_names(macsec_duthost, nbrhosts) + ctrl_nbr_names = self.get_ctrl_nbr_names(macsec_duthost, nbrhosts, tbinfo) logger.info("Controlled links {}".format(ctrl_nbr_names)) nbrhosts = {name: nbrhosts[name] for name in ctrl_nbr_names} return self.find_links_from_nbr(macsec_duthost, tbinfo, nbrhosts) @@ -250,12 +250,12 @@ class MacsecPluginT2(MacsecPlugin): def __init__(self): super(MacsecPluginT2, self).__init__() - def get_ctrl_nbr_names(self, macsec_duthost, nbrhosts): - mg_facts = macsec_duthost.get_extended_minigraph_facts() + def get_ctrl_nbr_names(self, macsec_duthost, nbrhosts, tbinfo): + mg_facts = macsec_duthost.get_extended_minigraph_facts(tbinfo) ctrl_nbr_names = mg_facts['macsec_neighbors'] return ctrl_nbr_names - def downstream_neighbor(self,tbinfo, neighbor): + def downstream_neighbor(self, tbinfo, neighbor): if ("t2" in tbinfo["topo"]["type"] and "T1" in neighbor["name"]): return True return False diff --git a/tests/macsec/macsec_config_helper.py b/tests/macsec/macsec_config_helper.py index 374ce371429..12806e6de79 100644 --- a/tests/macsec/macsec_config_helper.py +++ b/tests/macsec/macsec_config_helper.py @@ -189,7 +189,7 @@ def cleanup_macsec_configuration(duthost, ctrl_links, profile_name): for d in devices: if isinstance(d, EosHost): continue - assert wait_until(30, 1, 0, lambda d=d: not get_mka_session(d)) + assert wait_until(180, 1, 0, lambda d=d: not get_mka_session(d)) def setup_macsec_configuration(duthost, ctrl_links, profile_name, default_priority, diff --git a/tests/macsec/test_static_key_ciphers.py b/tests/macsec/test_static_key_ciphers.py new file mode 100644 index 00000000000..6f19d7d46e7 --- /dev/null +++ b/tests/macsec/test_static_key_ciphers.py @@ -0,0 +1,131 @@ +import pytest +import logging +import random +import time +import json +import os + +from .macsec_config_helper import setup_macsec_configuration, cleanup_macsec_configuration + +logger = logging.getLogger(__name__) + +pytestmark = [ + pytest.mark.macsec_required, + pytest.mark.topology("t2"), +] + + +def macsec_check(host, cli_options, int, neighv4, neighv6, macsec=True, cipher=None): + if macsec: + # Verify Macsec Status Between Neighbors + output = host.shell('sonic-cfggen{} -d -v PORT.{}'.format(cli_options, int), + module_ignore_errors=True)['stdout'] + logger.debug(output) + logger.debug("'macsec': '{}'".format(cipher)) + assert "'macsec': '{}'".format(cipher) in output + # Verify WPA Supplicant process is running on port + output = host.shell('ps aux | grep "USER\\|wpa_supplicant"', module_ignore_errors=True)['stdout'] + logger.debug(output) + assert int in output + # Verify macsec is enabled on port and session is up + output = host.shell("show macsec{} {}".format(cli_options, int), module_ignore_errors=True) + output = output['stdout'].split("\n") + logger.debug(output) + assert "enable true" in output[3] + + # Verify BGP Between Neighbors + output = host.shell("show ip bgp neighbor {}".format(neighv4))['stdout'] + logger.debug("BGP v4: {}".format(output)) + assert "BGP state = Established" in output + output = host.shell("show ipv6 bgp neighbor {}".format(neighv6))['stdout'] + logger.debug("BGP v6: {}".format(output)) + assert "BGP state = Established" in output + + +def test_static_key_ciphers(duthost, nbrhosts, request, profile_name, tbinfo, ctrl_links, rekey_period): + if request.config.getoption("neighbor_type") != "sonic": + pytest.skip("Neighbor type must be sonic") + dut_asn = tbinfo['topo']['properties']['configuration_properties']['common']['dut_asn'] + asic_index = random.choice(duthost.get_frontend_asic_ids()) + logger.debug(f"ASIC index: {asic_index}") + skip_hosts = duthost.get_asic_namespace_list() + if duthost.is_multi_asic: + cli_options = " -n " + duthost.get_namespace_from_asic_id(asic_index) + else: + cli_options = '' + dut_lldp_table = duthost.shell("show lldp table")['stdout'].split("\n")[3].split() + dut_to_neigh_int = dut_lldp_table[0] + neigh_to_dut_int = dut_lldp_table[4] + neigh_name = dut_lldp_table[1] + neighhost = nbrhosts[dut_lldp_table[1]]["host"] + if neighhost.is_multi_asic: + neigh_cli_options = " -n " + neighhost.get_namespace_from_asic_id(neighhost.get_frontend_asic_ids()) + else: + neigh_cli_options = '' + logger.debug("dut cli: {} neigh cli: {}".format(cli_options, neigh_cli_options)) + + int_list = { + dut_to_neigh_int: { + 'host': neighhost, + 'port': neigh_to_dut_int + } + } + time.sleep(45) + + # gather IP address information + dut_ip_v4 = tbinfo['topo']['properties']['configuration'][neigh_name]['bgp']['peers'][dut_asn][0] + dut_ip_v6 = tbinfo['topo']['properties']['configuration'][neigh_name]['bgp']['peers'][dut_asn][1].lower() + bgp_facts = duthost.bgp_facts(instance_id=asic_index)['ansible_facts'] + for k, v in bgp_facts['bgp_neighbors'].items(): + if v['description'].lower() not in skip_hosts: + if v['description'] == neigh_name: + if v['ip_version'] == 4: + neigh_ip_v4 = k + elif v['ip_version'] == 6: + neigh_ip_v6 = k + logger.debug(v['state']) + assert v['state'] == 'established' + + with open(os.path.dirname(__file__) + '/profile.json') as f: + macsec_profiles = json.load(f) + + cleanup_macsec_configuration(duthost, ctrl_links, profile_name) + # wait to ensure link has come up with no macsec + time.sleep(30) + macsec_check(duthost, cli_options, dut_to_neigh_int, neigh_ip_v4, neigh_ip_v6, macsec=False) + + # use each macsec profile and verify operation + for k, v in list(macsec_profiles.items()): + if duthost.facts["asic_type"] == "vs" and v['send_sci'] == "false": + # On EOS, portchannel mac is not same as the member port mac (being as SCI), + # then src mac is not equal to SCI in its sending packet. The receiver of vSONIC + # will drop it for macsec kernel module does not correctly handle it. + continue + else: + logger.debug("k: {} v: {}".format(k, v)) + setup_macsec_configuration(duthost, int_list, k, v['priority'], + v['cipher_suite'], v['primary_cak'], v['primary_ckn'], v['policy'], + v['send_sci'], + rekey_period) + + logger.debug("dut macsec profiles:") + logger.debug(duthost.shell("sonic-cfggen -d --var-json MACSEC_PROFILE")['stdout']) + logger.debug("neighbor macsec profiles:") + logger.debug(neighhost.shell("sonic-cfggen -d --var-json MACSEC_PROFILE")['stdout']) + + # wait for BGP to come up + time.sleep(30) + macsec_check(duthost, cli_options, dut_to_neigh_int, neigh_ip_v4, neigh_ip_v6, cipher=k) + macsec_check(neighhost, neigh_cli_options, neigh_to_dut_int, dut_ip_v4, dut_ip_v6, cipher=k) + cleanup_macsec_configuration(duthost, int_list, k) + time.sleep(30) + macsec_check(duthost, cli_options, dut_to_neigh_int, neigh_ip_v4, neigh_ip_v6, macsec=False) + + # reenable original profile + setup_macsec_configuration(duthost, int_list, profile_name, macsec_profiles[profile_name]['priority'], + macsec_profiles[profile_name]['cipher_suite'], + macsec_profiles[profile_name]['primary_cak'], + macsec_profiles[profile_name]['primary_ckn'], macsec_profiles[profile_name]['policy'], + macsec_profiles[profile_name]['send_sci'], rekey_period) + logger.debug(duthost.shell("docker ps")['stdout']) + macsec_check(duthost, cli_options, dut_to_neigh_int, neigh_ip_v4, neigh_ip_v6, cipher=profile_name) From 3ea25ca10aaf7cf98c3b45661d1a90c77129d065 Mon Sep 17 00:00:00 2001 From: Azarack Date: Fri, 7 Jun 2024 20:50:02 +0000 Subject: [PATCH 02/10] adjusting timers --- tests/macsec/test_static_key_ciphers.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/macsec/test_static_key_ciphers.py b/tests/macsec/test_static_key_ciphers.py index 6f19d7d46e7..2755d0641e0 100644 --- a/tests/macsec/test_static_key_ciphers.py +++ b/tests/macsec/test_static_key_ciphers.py @@ -90,8 +90,9 @@ def test_static_key_ciphers(duthost, nbrhosts, request, profile_name, tbinfo, ct macsec_profiles = json.load(f) cleanup_macsec_configuration(duthost, ctrl_links, profile_name) + # wait to ensure link has come up with no macsec - time.sleep(30) + time.sleep(45) macsec_check(duthost, cli_options, dut_to_neigh_int, neigh_ip_v4, neigh_ip_v6, macsec=False) # use each macsec profile and verify operation From eebaefbb0895146b5747e2d6e6e759b6c80783f6 Mon Sep 17 00:00:00 2001 From: Azarack Date: Mon, 10 Jun 2024 13:49:50 +0000 Subject: [PATCH 03/10] trigger rebuild --- tests/macsec/test_static_key_ciphers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/macsec/test_static_key_ciphers.py b/tests/macsec/test_static_key_ciphers.py index 2755d0641e0..e20be0b3cb1 100644 --- a/tests/macsec/test_static_key_ciphers.py +++ b/tests/macsec/test_static_key_ciphers.py @@ -109,7 +109,7 @@ def test_static_key_ciphers(duthost, nbrhosts, request, profile_name, tbinfo, ct v['send_sci'], rekey_period) - logger.debug("dut macsec profiles:") + logger.debug("dut macsec profiles: ") logger.debug(duthost.shell("sonic-cfggen -d --var-json MACSEC_PROFILE")['stdout']) logger.debug("neighbor macsec profiles:") logger.debug(neighhost.shell("sonic-cfggen -d --var-json MACSEC_PROFILE")['stdout']) From 65d051a13c9b87af4e4e3cf668d855291784ee78 Mon Sep 17 00:00:00 2001 From: Azarack Date: Mon, 10 Jun 2024 15:59:43 +0000 Subject: [PATCH 04/10] pipeline --- tests/macsec/test_static_key_ciphers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/macsec/test_static_key_ciphers.py b/tests/macsec/test_static_key_ciphers.py index e20be0b3cb1..2755d0641e0 100644 --- a/tests/macsec/test_static_key_ciphers.py +++ b/tests/macsec/test_static_key_ciphers.py @@ -109,7 +109,7 @@ def test_static_key_ciphers(duthost, nbrhosts, request, profile_name, tbinfo, ct v['send_sci'], rekey_period) - logger.debug("dut macsec profiles: ") + logger.debug("dut macsec profiles:") logger.debug(duthost.shell("sonic-cfggen -d --var-json MACSEC_PROFILE")['stdout']) logger.debug("neighbor macsec profiles:") logger.debug(neighhost.shell("sonic-cfggen -d --var-json MACSEC_PROFILE")['stdout']) From 1e41f10a1dc1647dceb06592c2e69dbdd6a18a85 Mon Sep 17 00:00:00 2001 From: Azarack Date: Tue, 11 Jun 2024 15:21:57 +0000 Subject: [PATCH 05/10] trigger pipeline --- tests/macsec/test_static_key_ciphers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/macsec/test_static_key_ciphers.py b/tests/macsec/test_static_key_ciphers.py index 2755d0641e0..94b585218ec 100644 --- a/tests/macsec/test_static_key_ciphers.py +++ b/tests/macsec/test_static_key_ciphers.py @@ -17,7 +17,7 @@ def macsec_check(host, cli_options, int, neighv4, neighv6, macsec=True, cipher=None): if macsec: - # Verify Macsec Status Between Neighbors + # Verify Macsec Status Between Neighbors is up output = host.shell('sonic-cfggen{} -d -v PORT.{}'.format(cli_options, int), module_ignore_errors=True)['stdout'] logger.debug(output) From d6a4733ab7d0986df70271e0c5c80e0f6e565a13 Mon Sep 17 00:00:00 2001 From: Azarack Date: Tue, 11 Jun 2024 17:03:33 +0000 Subject: [PATCH 06/10] trigger pipeline --- tests/macsec/test_static_key_ciphers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/macsec/test_static_key_ciphers.py b/tests/macsec/test_static_key_ciphers.py index 94b585218ec..a4a7eac5832 100644 --- a/tests/macsec/test_static_key_ciphers.py +++ b/tests/macsec/test_static_key_ciphers.py @@ -23,7 +23,7 @@ def macsec_check(host, cli_options, int, neighv4, neighv6, macsec=True, cipher=N logger.debug(output) logger.debug("'macsec': '{}'".format(cipher)) assert "'macsec': '{}'".format(cipher) in output - # Verify WPA Supplicant process is running on port + # Verify WPA Supplicant process is running on specific port output = host.shell('ps aux | grep "USER\\|wpa_supplicant"', module_ignore_errors=True)['stdout'] logger.debug(output) assert int in output From d3b1a051946b7312d744645cfb4ef3bc490fe874 Mon Sep 17 00:00:00 2001 From: Azarack Date: Thu, 11 Jul 2024 17:07:51 +0000 Subject: [PATCH 07/10] update comment --- tests/macsec/test_static_key_ciphers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/macsec/test_static_key_ciphers.py b/tests/macsec/test_static_key_ciphers.py index a4a7eac5832..79c469ff626 100644 --- a/tests/macsec/test_static_key_ciphers.py +++ b/tests/macsec/test_static_key_ciphers.py @@ -27,7 +27,7 @@ def macsec_check(host, cli_options, int, neighv4, neighv6, macsec=True, cipher=N output = host.shell('ps aux | grep "USER\\|wpa_supplicant"', module_ignore_errors=True)['stdout'] logger.debug(output) assert int in output - # Verify macsec is enabled on port and session is up + # Verify macsec is enabled on port and session is up and established output = host.shell("show macsec{} {}".format(cli_options, int), module_ignore_errors=True) output = output['stdout'].split("\n") logger.debug(output) From 5a07d16fa1604d5ab8472c2ece1f42fe090aae6a Mon Sep 17 00:00:00 2001 From: Azarack Date: Mon, 22 Jul 2024 14:43:17 +0000 Subject: [PATCH 08/10] trigger pipeline --- tests/macsec/test_static_key_ciphers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/macsec/test_static_key_ciphers.py b/tests/macsec/test_static_key_ciphers.py index 79c469ff626..b284ab49470 100644 --- a/tests/macsec/test_static_key_ciphers.py +++ b/tests/macsec/test_static_key_ciphers.py @@ -33,7 +33,7 @@ def macsec_check(host, cli_options, int, neighv4, neighv6, macsec=True, cipher=N logger.debug(output) assert "enable true" in output[3] - # Verify BGP Between Neighbors + # Verify BGP Between Neighbors is established output = host.shell("show ip bgp neighbor {}".format(neighv4))['stdout'] logger.debug("BGP v4: {}".format(output)) assert "BGP state = Established" in output From 4b80dab18918ce4694e65a117e04d87691b0f04b Mon Sep 17 00:00:00 2001 From: Azarack Date: Wed, 13 Nov 2024 20:48:15 +0000 Subject: [PATCH 09/10] changing duthost fixtures --- tests/macsec/test_static_key_ciphers.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/macsec/test_static_key_ciphers.py b/tests/macsec/test_static_key_ciphers.py index b284ab49470..33feaa45920 100644 --- a/tests/macsec/test_static_key_ciphers.py +++ b/tests/macsec/test_static_key_ciphers.py @@ -42,9 +42,11 @@ def macsec_check(host, cli_options, int, neighv4, neighv6, macsec=True, cipher=N assert "BGP state = Established" in output -def test_static_key_ciphers(duthost, nbrhosts, request, profile_name, tbinfo, ctrl_links, rekey_period): +def test_static_key_ciphers(duthosts, nbrhosts, request, profile_name, tbinfo, ctrl_links, rekey_period, + enum_frontend_dut_hostname): if request.config.getoption("neighbor_type") != "sonic": pytest.skip("Neighbor type must be sonic") + duthost = duthosts[enum_frontend_dut_hostname] dut_asn = tbinfo['topo']['properties']['configuration_properties']['common']['dut_asn'] asic_index = random.choice(duthost.get_frontend_asic_ids()) logger.debug(f"ASIC index: {asic_index}") From d68a9a1fa33a1716cd792645f00e0895304c9fce Mon Sep 17 00:00:00 2001 From: Azarack Date: Wed, 13 Nov 2024 20:49:18 +0000 Subject: [PATCH 10/10] using random single dut fixture --- tests/macsec/test_static_key_ciphers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/macsec/test_static_key_ciphers.py b/tests/macsec/test_static_key_ciphers.py index 33feaa45920..8e03a85d25b 100644 --- a/tests/macsec/test_static_key_ciphers.py +++ b/tests/macsec/test_static_key_ciphers.py @@ -43,10 +43,10 @@ def macsec_check(host, cli_options, int, neighv4, neighv6, macsec=True, cipher=N def test_static_key_ciphers(duthosts, nbrhosts, request, profile_name, tbinfo, ctrl_links, rekey_period, - enum_frontend_dut_hostname): + enum_rand_one_per_hwsku_frontend_hostname): if request.config.getoption("neighbor_type") != "sonic": pytest.skip("Neighbor type must be sonic") - duthost = duthosts[enum_frontend_dut_hostname] + duthost = duthosts[enum_rand_one_per_hwsku_frontend_hostname] dut_asn = tbinfo['topo']['properties']['configuration_properties']['common']['dut_asn'] asic_index = random.choice(duthost.get_frontend_asic_ids()) logger.debug(f"ASIC index: {asic_index}")