Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[testplan] Macsec static key ciphers #13189

Open
wants to merge 57 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
e8fb9e1
Merge pull request #1 from sonic-net/master
Azarack Oct 11, 2022
7d37d5a
Merge pull request #3 from sonic-net/master
Azarack Oct 17, 2022
1597709
Merge branch 'sonic-net:master' into master
Azarack Oct 26, 2022
70bea76
Merge branch 'sonic-net:master' into master
Azarack Oct 27, 2022
d7182bc
Merge branch 'sonic-net:master' into master
Azarack Nov 9, 2022
cd5f77d
Merge branch 'sonic-net:master' into master
Azarack Nov 10, 2022
025d4f2
Merge branch 'sonic-net:master' into master
Azarack Mar 15, 2023
44449fb
Merge branch 'sonic-net:master' into master
Azarack Mar 16, 2023
e15ea86
Merge branch 'sonic-net:master' into master
Azarack Mar 21, 2023
8d81027
Merge branch 'sonic-net:master' into master
Azarack Mar 21, 2023
e5d2305
Merge branch 'sonic-net:master' into master
Azarack Mar 28, 2023
6149cb3
Merge branch 'sonic-net:master' into master
Azarack Apr 4, 2023
52dcf3f
Merge branch 'sonic-net:master' into master
Azarack Apr 7, 2023
954e1f4
Merge branch 'sonic-net:master' into master
Azarack Apr 21, 2023
fbbf6c9
Merge branch 'sonic-net:master' into master
Azarack May 10, 2023
5bf1157
Merge branch 'sonic-net:master' into master
Azarack May 16, 2023
a34389c
Merge branch 'sonic-net:master' into master
Azarack Jun 5, 2023
925b27b
Merge branch 'sonic-net:master' into master
Azarack Jun 26, 2023
5ded63d
Merge branch 'sonic-net:master' into master
Azarack Jul 10, 2023
ebdbd3f
Merge branch 'sonic-net:master' into master
Azarack Aug 9, 2023
982bf2d
Merge branch 'sonic-net:master' into master
Azarack Aug 10, 2023
52abbaf
Merge branch 'sonic-net:master' into master
Azarack Aug 15, 2023
3316a92
Merge branch 'sonic-net:master' into master
Azarack Aug 16, 2023
fb86539
Merge branch 'sonic-net:master' into master
Azarack Aug 25, 2023
76b08cc
Merge branch 'sonic-net:master' into master
Azarack Aug 28, 2023
5b68634
Merge branch 'sonic-net:master' into master
Azarack Sep 5, 2023
ef6774b
Merge branch 'sonic-net:master' into master
Azarack Oct 4, 2023
9bfb561
Merge branch 'sonic-net:master' into master
Azarack Oct 5, 2023
112da65
Merge branch 'sonic-net:master' into master
Azarack Oct 10, 2023
4341f17
Merge branch 'sonic-net:master' into master
Azarack Oct 11, 2023
794a3b8
Merge branch 'sonic-net:master' into master
Azarack Oct 16, 2023
6124c0d
Merge branch 'sonic-net:master' into master
parmarkj Oct 17, 2023
0b981fb
Merge branch 'sonic-net:master' into master
Azarack Oct 24, 2023
99aca6a
Merge branch 'sonic-net:master' into master
Azarack Oct 27, 2023
904401d
Merge branch 'sonic-net:master' into master
Azarack Nov 1, 2023
c18d841
Merge branch 'sonic-net:master' into master
Azarack Nov 2, 2023
4383cb4
Merge branch 'sonic-net:master' into master
Azarack Nov 6, 2023
0edbf2b
Merge branch 'sonic-net:master' into master
Azarack Nov 13, 2023
ed4515a
Merge branch 'sonic-net:master' into master
Azarack Dec 11, 2023
f3cbac8
Merge branch 'sonic-net:master' into master
Azarack Jan 31, 2024
fb4e934
Merge branch 'sonic-net:master' into master
Azarack Mar 11, 2024
d5f7a5e
Merge branch 'sonic-net:master' into master
Azarack Mar 15, 2024
60a7672
Merge branch 'sonic-net:master' into master
Azarack Mar 19, 2024
00abb73
Merge branch 'sonic-net:master' into master
Azarack Apr 25, 2024
8b6779e
Merge branch 'sonic-net:master' into master
mrkcmo May 10, 2024
d4d5995
Merge branch 'sonic-net:master' into master
Azarack May 16, 2024
7eff15b
Merge branch 'sonic-net:master' into master
Azarack May 28, 2024
acc55cc
submit for pr
Azarack Jun 7, 2024
3ea25ca
adjusting timers
Azarack Jun 7, 2024
eebaefb
trigger rebuild
Azarack Jun 10, 2024
65d051a
pipeline
Azarack Jun 10, 2024
1e41f10
trigger pipeline
Azarack Jun 11, 2024
d6a4733
trigger pipeline
Azarack Jun 11, 2024
d3b1a05
update comment
Azarack Jul 11, 2024
5a07d16
trigger pipeline
Azarack Jul 22, 2024
4b80dab
changing duthost fixtures
Azarack Nov 13, 2024
d68a9a1
using random single dut fixture
Azarack Nov 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/testplan/MACsec-test-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
8 changes: 4 additions & 4 deletions tests/macsec/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion tests/macsec/macsec_config_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to multiply the waiting time by 6?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We were seeing a lot of failures in cleanup where it was taking longer for the session to be re-established. Adjusting this timer helped alleviate those issues.



def setup_macsec_configuration(duthost, ctrl_links, profile_name, default_priority,
Expand Down
134 changes: 134 additions & 0 deletions tests/macsec/test_static_key_ciphers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
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 is up
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 specific 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 and established
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 is established
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(duthosts, nbrhosts, request, profile_name, tbinfo, ctrl_links, rekey_period,
enum_rand_one_per_hwsku_frontend_hostname):
if request.config.getoption("neighbor_type") != "sonic":
pytest.skip("Neighbor type must be sonic")
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}")
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(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
for k, v in list(macsec_profiles.items()):
if duthost.facts["asic_type"] == "vs" and v['send_sci'] == "false":
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this topic relevant here? Given that both duthost and neighbor host are SONiC, there is no EOS machine involved, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check was taken from here in the macsec init file:

def startup_macsec(self, request, macsec_duthost, ctrl_links, macsec_profile, tbinfo):
        topo_name = tbinfo['topo']['name']
        def __startup_macsec():
            profile = macsec_profile
            if request.config.getoption("neighbor_type") == "eos":
                if macsec_duthost.facts["asic_type"] == "vs" and profile['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.
                    pytest.skip(
                        "macsec on dut vsonic, neighbor eos, send_sci false")
                ```

When those two conditions are met the test fails.

# 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'],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how can it work if we only change the MACsec profile of the duthost without updating the neighbor's profile? At least, the CAK key will be different. Isn't that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The setup_macsec_configuration function in use here configured both DUT and the neighbor.

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)
Loading