[macsec] Add fault-handling tests for MKA timeout on LAG member - #26062
[macsec] Add fault-handling tests for MKA timeout on LAG member#26062karthik-nexthop wants to merge 3 commits into
Conversation
Adds MACsec fault-handling tests for LAG members: - test_eapol_block_brings_lag_member_down: blocks inbound EAPOL on the DUT ingress while the link stays physically up. Verifies the MKA session expires within ~MKA_TIMEOUT and that the LAG member is brought down quickly instead of blackholing traffic until the 90s LACP timeout. - test_macsec_rekey_keeps_lag_member_up: verifies a periodic MACsec rekey does not spuriously disable or flap the LAG member while the session stays up. Signed-off-by: karthik-nexthop <karthik@nexthop.ai>
|
|
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
/azp run |
|
Azure Pipelines will not run the associated pipelines, because the pull request was updated after the run command was issued. Review the pull request again and issue a new run command. |
|
Hi, the Pre_test Static Analysis pre-checker is failing on this PR due to a flake8 lint error in your change:
|
Resolve leftover conflict markers so flake8 can parse the file, keeping the new LAG MKA tests and port_profiles on the mismatch test. Signed-off-by: Karthik Siruvalam <karthik@nexthop.ai>
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
|
Hi, there are workflow run(s) waiting for approval, you may be first-time contributor. I will notify maintainers to help approve once PR is approved. Thanks! ---Powered by SONiC BuildBot
|
|
|
||
| @pytest.mark.disable_loganalyzer | ||
| @pytest.mark.parametrize("lag_kind", ["single_member", "multi_member"]) | ||
| def test_macsec_down_disables_lag_member(self, duthost, ctrl_links, |
There was a problem hiding this comment.
The test case name is correct here, please update your PR Description with this name.
| cfg = [{"LAG_MEMBER_TABLE:{}:{}".format(pc_name, port_name): {"status": status}, "OP": "SET"}] | ||
| tmp = duthost.shell("mktemp")["stdout"].strip() | ||
| duthost.copy(content=json.dumps(cfg), dest=tmp, verbose=False) | ||
| duthost.docker_exec_swssconfig("/dev/stdin < {}".format(tmp), "swss", asic_idx) |
There was a problem hiding this comment.
can you check for result of docker_exec_swssconfig?
| 90s LACP timeout -- and must keep it down (a teamsyncd APP_LAG_MEMBER_TABLE refresh | ||
| must not silently re-enable it while MACsec is down). For a single-member LAG the | ||
| whole PortChannel goes down, which withdraws the BGP session over it; for a | ||
| multi-member LAG the PortChannel stays up on the other members, so BGP must NOT be |
There was a problem hiding this comment.
Portchannel/BGP not going down on multi-member LAG depends on min_links settings in PortChannel right?
| # Block inbound EAPOL on the DUT so the DUT cannot receive peer MKA hellos and | ||
| # its session times out. del-before-add is idempotent. | ||
| ns_prefix = get_ipnetns_prefix(duthost, port_name) | ||
| duthost.shell("sudo tc qdisc del dev {} clsact".format(dut_eth_port), |
There was a problem hiding this comment.
few tc commands are executed in the asic namespace, and these are in the host namespace. Don't you need to use asic name space for all?
| def teamd_member_selected(duthost, pc_name, port_name): | ||
| """teamd's view: is `port_name` currently a selected member of `pc_name`?""" | ||
| try: | ||
| state = duthost.get_port_channel_status(pc_name) |
There was a problem hiding this comment.
get_port_channel_status has "self.command("docker exec -i teamd teamdctl {} state dump".format(port_channel_name))" which won't work for multi-asic platform since there is teamd docker per asic
| return (egress == "true", ingress == "true") | ||
|
|
||
|
|
||
| def push_lag_member_status(duthost, pc_name, port_name, status): |
There was a problem hiding this comment.
push_lag_member_status discards the docker_exec_swssconfig result. If the injection silently fails, the member simply stays disabled and check (5) (assert not member_reenabled_in_asic) passes without ever driving the re-enable race — which is the exact behavior this test exists to verify. Please confirm the injection actually took effect before asserting the ASIC stayed disabled (e.g. read back LAG_MEMBER_TABLE shows status=enabled), not just check the shell return.
| return duthost.shell(cmd)["stdout"].strip() == "Established" | ||
|
|
||
|
|
||
| def macsec_lag_disable_log_count(duthost, port_name): |
There was a problem hiding this comment.
macsec_lag_disable_log_count greps exact orchagent strings ('MACsec disabled LAG member ...', 'Flapping host interface ... MACsec down'). If the log wording differs on the image/branch under test, the count is always 0 and disable_logs_after == disable_logs_before (0==0) passes even if a spurious flap happened. Consider anchoring the primary assertion on ASIC_DB disable state and treating the log grep as secondary.
Harden multi-ASIC tc/teamd paths, verify swssconfig injection via APPL_DB readback, honor PortChannel min_links for multi-member BGP expectations, and treat rekey disable-log greps as secondary to ASIC_DB checks. Signed-off-by: Karthik Siruvalam <karthik@nexthop.ai>
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
|
Fix is in review stage. Hence the test script is failing . Will trigger tests again post fix merge. |
Description of PR
Adds MACsec fault-handling tests for LAG members:
test_macsec_down_disables_lag_member: blocks inbound EAPOL (ethertype 0x888e, whichcarries MKA PDUs) on the DUT ingress while the link stays physically up. Verifies the MKA
session expires within ~MKA_TIMEOUT (6s) and that the LAG member is brought down quickly
(single-member PortChannel goes
Dw, multi-member LAG deselects the member) instead ofblackholing traffic until the 90s LACP timeout. Also checks that a teamsyncd
LAG_MEMBER_TABLErefresh does not re-enable the member while MACsec is down, and thatMACsec/LAG/BGP recover after the block is removed. Multi-member PortChannel/BGP staying
up is gated on remaining members still satisfying CONFIG_DB
min_links.test_macsec_rekey_keeps_lag_member_up: verifies a periodic MACsec rekey does notspuriously disable or flap the LAG member while the session stays up (primary gate is
ASIC_DB disable state).
Summary:
Adds regression coverage in
tests/macsec/test_fault_handling.pyfor MACsec session losson LAG members: prompt LAG-member teardown on MKA timeout, no spurious member flap during
rekey, and recovery after the fault is cleared.
Depends on orchagent fix: sonic-net/sonic-swss#4744 (covers sonic-buildimage#19254).
Fixes # (issue)
Type of change
Back port request
Tracking issue/work item for backport/cherry-pick request:
Failure type:
Approach
What is the motivation for this PR?
When a MACsec session on a LAG member dies (MKA PDUs stop arriving), the member should be
brought down promptly rather than staying selected in the LAG until the LACP timeout, which
would blackhole traffic over a link with no working MACsec. A healthy MACsec rekey should
not spuriously disable or flap the LAG member while the session remains up.
How did you do it?
Extended
TestFaultHandlingintests/macsec/test_fault_handling.pywith helper functionsto observe LAG-member state via teamd, ASIC_DB, and APPL_DB, then added:
test_macsec_down_disables_lag_member— installs a DUT-sidetcclsact ingressfilter dropping protocol 0x888e (in the port's ASIC netns on multi-ASIC), then asserts:
teamd/teamdN)LAG_MEMBER_TABLErefresh withstatus=enableddoes not re-enable themember while MACsec is down (
swssconfigrc checked and APPL_DB status read backbefore the ASIC race assertion)
min_links): PortChannel and BGP withdraw; multi-member LAG with remaining membersstill meeting
min_links: BGP stays upParameterized over
single_memberandmulti_memberLAGs.test_macsec_rekey_keeps_lag_member_up— observes across ~2xrekey_period, samplingASIC_DB LAG-member disable state as the primary gate, and asserts no spurious member
disable while SAs rotate and the session stays up. Orchagent disable-log greps are
secondary only (wording can differ by image).
Reuses existing
ctrl_links,upstream_links,rekey_period, andwait_mka_establishfixtures. Existing
test_mismatch_macsec_configurationis preserved with upstreamport_profilescompatibility.How did you verify/test it?
--enable_macsecand SONiC neighbors(
--neighbor_type sonic).single-member LAGs.
PortChannel, and that BGP stays Established when one member goes down when remaining
members still satisfy
min_links.Any platform specific information?
The
tc-based EAPOL block runs on the DUT (ASIC netns on multi-ASIC) and is neighbor-OSindependent. ASIC_DB LAG-member disable checks require platforms where orchagent programs
SAI_LAG_MEMBER_ATTR_EGRESS_DISABLE/INGRESS_DISABLE. The multi-member LAG variantskips automatically when the testbed has no suitable multi-member MACsec control link.
Supported testbed topology if it's a new test case?
t0, t2, lrh, urh, t0-sonic (module
pytestmark). Requires--enable_macsecand SONiCneighbors (
--neighbor_type sonic).Documentation
N/A — test-only change; no documentation update required.
Signed-off-by: Karthik Siruvalam karthik@nexthop.ai