Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
bc51840
Fixes found during nightly run with macsec enabled topology
judyjoseph Feb 21, 2025
a66f663
Ffix for copp pfc voq ptftests
judyjoseph Feb 22, 2025
f8ea997
Fix the port_number to port_id things again
judyjoseph Feb 22, 2025
1cbadca
Fixes for acl tests, changes in config reload to pass override option…
judyjoseph Feb 27, 2025
74c4369
Fixes to get generate_golden_config work when this run for a non macs…
judyjoseph Feb 27, 2025
6bea951
Flake errors and unwanted imports removed
judyjoseph Feb 28, 2025
4fbc9b3
minor fixes
judyjoseph Feb 28, 2025
c0d028a
Add macsec support in acstests and saitests
judyjoseph Feb 28, 2025
af19d86
Loop for count of packets to be sent as we need to increment PN
judyjoseph Mar 1, 2025
708b1d4
We need to import macsec to override send_packet and dp_poll
judyjoseph Mar 2, 2025
3c1253f
Fixes for ip,copp,qos probably
judyjoseph Mar 3, 2025
7f922d5
Update the macsec errors to support multi-asic
judyjoseph Mar 14, 2025
a793381
Changes moved to a different PR : #17530
judyjoseph Mar 14, 2025
cd32d62
flake fixes
judyjoseph Mar 27, 2025
90ac7f4
Remove redundant macsec.py files - make it all point to ansible/roles…
judyjoseph Mar 27, 2025
6bb0f29
Fix already made via PR : https://github.com/sonic-net/sonic-mgmt/pul…
judyjoseph Apr 1, 2025
20441a1
swap port_id and port_number for macsec_send call
judyjoseph Apr 1, 2025
5d0194b
Take care of T0 macsec tests as well, so that t0-sonic is fine
judyjoseph Apr 3, 2025
3206c7b
Additional fix to support multiple profile names given as input
judyjoseph Apr 4, 2025
9a1c996
Use the right command KEYS instead of HGET
judyjoseph Apr 4, 2025
cf47a73
Update comment, use macsec_card to set MacSecEnabled in DeviceMetadata
judyjoseph Apr 14, 2025
c4c13e6
Merge branch 'master' into macsec_nightly_run_fixes
judyjoseph Apr 17, 2025
2f586c2
Remove extra line in auto merge
judyjoseph Apr 17, 2025
77da26c
Skip ACL egress tests when run on macsec enabled toplogy with braodco…
judyjoseph Apr 22, 2025
9464f9c
Fix flake error
judyjoseph Apr 22, 2025
b4bb30e
Merge branch 'master' into macsec_nightly_run_fixes
judyjoseph May 13, 2025
fb37dd1
Merge branch 'master' into macsec_nightly_run_fixes
judyjoseph May 15, 2025
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
1 change: 1 addition & 0 deletions ansible/roles/test/files/acstests/py3/lag_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,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

Expand Down
1 change: 1 addition & 0 deletions ansible/roles/test/files/acstests/py3/macsec.py
25 changes: 15 additions & 10 deletions ansible/roles/test/files/ptftests/macsec.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,18 @@ def macsec_send(test, port_id, pkt, count=1):
encrypt, send_sci, xpn_en, sci, an, sak, ssci, salt, peer_sci, peer_an, peer_ssci, pn = \
MACSEC_INFOS[port_number]

# 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_id, macsec_pkt, count)
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_id, macsec_pkt, 1)
else:
# send the packet
__origin_send_packet(test, port_id, pkt, count)
Expand Down Expand Up @@ -95,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
Expand All @@ -108,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
Expand Down
2 changes: 2 additions & 0 deletions ansible/roles/test/files/ptftests/py3/IP_decap_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@
from ptf.mask import Mask
from ptf.base_tests import BaseTest

import macsec # noqa F401


class DecapPacketTest(BaseTest):
""" IP in IP decapsulation test """
Expand Down
1 change: 1 addition & 0 deletions ansible/roles/test/files/ptftests/py3/arptest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions ansible/roles/test/files/ptftests/py3/copp_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import signal
import threading
import time
import macsec # noqa F401

import ptf.packet as scapy
import ptf.testutils as testutils
Expand Down
1 change: 1 addition & 0 deletions ansible/roles/test/files/ptftests/py3/hash_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

import fib
import lpm
import macsec # noqa F401


class HashTest(BaseTest):
Expand Down
1 change: 1 addition & 0 deletions ansible/roles/test/files/ptftests/py3/mtu_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +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):
Expand Down
1 change: 1 addition & 0 deletions ansible/roles/test/files/ptftests/py3/pfc_pause_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +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):
Expand Down
1 change: 1 addition & 0 deletions ansible/roles/test/files/ptftests/py3/pfc_wd.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 # noqa F401


class PfcWdTest(BaseTest):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +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):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import ptf.packet as scapy
from ptf.mask import Mask
import ptf
import macsec # noqa F401


class BG_pkt_sender(BaseTest):
Expand Down
1 change: 1 addition & 0 deletions ansible/roles/test/files/ptftests/py3/voq.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
14 changes: 12 additions & 2 deletions tests/acl/test_acl.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ 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):
tbinfo, ptfadapter, topo_scenario, vlan_name, is_macsec_enabled_for_test):
"""Gather all required test information from DUT and tbinfo.

Args:
Expand Down Expand Up @@ -464,6 +464,10 @@ def setup(duthosts, ptfhost, rand_selected_dut, rand_selected_front_end_dut, ran
for duthost in duthosts:
duthost.command("mkdir -p {}".format(DUT_TMP_DIR))

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

yield setup_information

logger.info("Removing temporary directory \"{}\"".format(DUT_TMP_DIR))
Expand Down Expand Up @@ -542,13 +546,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.
Expand All @@ -561,6 +566,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


Expand Down
8 changes: 7 additions & 1 deletion tests/common/config_reload.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,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',
Expand All @@ -161,7 +167,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)
Expand Down
18 changes: 16 additions & 2 deletions tests/common/macsec/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
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

# flake8: noqa: F401
from tests.common.plugins.sanity_check import sanity_check

Expand Down Expand Up @@ -107,7 +111,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
Expand All @@ -116,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, macsec_profile, 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())}
Expand Down Expand Up @@ -251,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):
Expand Down
28 changes: 28 additions & 0 deletions tests/common/macsec/macsec_config_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,34 @@ 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, mac_profile, ctrl_links):
is_profile_present = False
is_port_profile_present = False
profile_name = mac_profile['name']

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

# 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(
Expand Down
35 changes: 25 additions & 10 deletions tests/common/macsec/macsec_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -484,13 +489,18 @@ def macsec_send(test, port_id, pkt, count=1):
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]

# 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
for n in range(count):
if isinstance(pkt, bytes):
# If in bytes, convert it to an Ether packet
pkt = scapy.Ether(pkt)

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)
# 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_id, macsec_pkt, 1)
else:
# send the packet
__origin_send_packet(test, port_id, pkt, count)
Expand Down Expand Up @@ -519,20 +529,25 @@ 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]:
# 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]
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
Expand Down
10 changes: 10 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,16 @@ 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

Expand Down
1 change: 1 addition & 0 deletions tests/saitests/py3/macsec.py
1 change: 1 addition & 0 deletions tests/saitests/py3/sai_qos_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading