From 7c88bc716db95d823180076a04f70bdc666cf1e5 Mon Sep 17 00:00:00 2001 From: Jonathan Hui Date: Thu, 26 Feb 2026 15:56:40 -0600 Subject: [PATCH] [nexus] improve robustness of MLE and WPAN packet verification (#12571) This commit addresses several issues in the Nexus verification scripts to improve test reliability and prevent runtime errors. - Fixed a TypeError caused by NullField in MLE command checks. When p.mle.cmd returns a NullField, it is unhashable and fails when checked against a set or list (e.g., 'p.mle.cmd in { ... }'). A truthiness check for p.mle.cmd was added to verify_5_6_4.py, verify_5_6_5.py, verify_6_2_2.py, and verify_7_1_5.py. - Improved verify_6_2_2.py robustness: - Wrapped must_not_next() checks within 'with pkts.save_index()' to ensure the packet iterator remains at the correct position after verifying the absence of specific messages. - Refactored MLE command filtering into a helper function for better readability and consistency. - Updated connectivity checks to allow filtering by ROUTER_1_RLOC16 and specifically look for WPAN Data Requests. - Cleaned up verify_5_6_4.py by replacing the explicit 'nullField' comparison with a more idiomatic truthiness check. --- tests/nexus/verify_5_6_4.py | 3 +-- tests/nexus/verify_5_6_5.py | 2 +- tests/nexus/verify_6_2_2.py | 25 +++++++++++++++---------- tests/nexus/verify_7_1_5.py | 2 +- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/tests/nexus/verify_5_6_4.py b/tests/nexus/verify_5_6_4.py index d91e586f9..2e056b6ec 100644 --- a/tests/nexus/verify_5_6_4.py +++ b/tests/nexus/verify_5_6_4.py @@ -170,8 +170,7 @@ def verify(pv): # - The Prefix 2 TLV MUST NOT be included # - Active Timestamp TLV print("Step 9: Leader (DUT)") - pkts.filter(lambda p: p.mle.cmd is not nullField).\ - filter(lambda p: p.mle.cmd in {consts.MLE_CHILD_UPDATE_REQUEST, consts.MLE_DATA_RESPONSE}).\ + pkts.filter(lambda p: p.mle.cmd and p.mle.cmd in {consts.MLE_CHILD_UPDATE_REQUEST, consts.MLE_DATA_RESPONSE}).\ filter(lambda p: p.wpan.src64 == DUT).\ filter(lambda p: p.wpan.dst64 == SED_1).\ filter(lambda p: { diff --git a/tests/nexus/verify_5_6_5.py b/tests/nexus/verify_5_6_5.py index f296f9f86..59ea190a2 100644 --- a/tests/nexus/verify_5_6_5.py +++ b/tests/nexus/verify_5_6_5.py @@ -171,7 +171,7 @@ def verify(pv): pkts.copy().\ filter_wpan_src64(LEADER).\ filter_wpan_dst64(SED_1).\ - filter(lambda p: p.mle.cmd in { + filter(lambda p: p.mle.cmd and p.mle.cmd in { consts.MLE_CHILD_UPDATE_REQUEST, consts.MLE_DATA_RESPONSE }).\ diff --git a/tests/nexus/verify_6_2_2.py b/tests/nexus/verify_6_2_2.py index 86e324027..9f4b1ea3a 100644 --- a/tests/nexus/verify_6_2_2.py +++ b/tests/nexus/verify_6_2_2.py @@ -66,6 +66,10 @@ def verify(pv): ROUTER_1 = pv.vars['ROUTER_1'] ROUTER_2 = pv.vars['ROUTER_2'] + def is_mle_announce_or_child_id_request(p): + """Checks if a packet is an MLE Announce or Child ID Request.""" + return p.mle.cmd and p.mle.cmd in {consts.MLE_ANNOUNCE, consts.MLE_CHILD_ID_REQUEST} + if 'ED_1' in pv.vars: DUT = pv.vars['ED_1'] IS_TOPOLOGY_A = True @@ -143,10 +147,10 @@ def verify(pv): must_next() # Verify no MLE Announce or additional Child ID Request from DUT - pkts.filter_wpan_src64(DUT).\ - filter(lambda p: hasattr(p, 'mle') and\ - p.mle.cmd in [consts.MLE_ANNOUNCE, consts.MLE_CHILD_ID_REQUEST]).\ - must_not_next() + with pkts.save_index(): + pkts.filter_wpan_src64(DUT).\ + filter(is_mle_announce_or_child_id_request).\ + must_not_next() else: # Step 8: SED_1 (DUT) [Topology B only] @@ -157,16 +161,17 @@ def verify(pv): # - The DUT MUST NOT transmit a MLE Announce message or an additional MLE Child ID Request. If it does, the # test has failed. print("Step 8: SED_1 (DUT) [Topology B only]") - # We look for any packet from DUT to its parent ROUTER_1 as a sign of connectivity and keep-alive. + # We look for a Data Request from DUT to its parent ROUTER_1 as a sign of connectivity and keep-alive. pkts.filter_wpan_src64(DUT).\ - filter_wpan_dst64(ROUTER_1).\ + filter(lambda p: p.wpan.dst64 == ROUTER_1 or p.wpan.dst16 == pv.vars['ROUTER_1_RLOC16']).\ + filter_wpan_cmd(consts.WPAN_DATA_REQUEST).\ must_next() # Verify no MLE Announce or additional Child ID Request from DUT - pkts.filter_wpan_src64(DUT).\ - filter(lambda p: hasattr(p, 'mle') and\ - p.mle.cmd in [consts.MLE_ANNOUNCE, consts.MLE_CHILD_ID_REQUEST]).\ - must_not_next() + with pkts.save_index(): + pkts.filter_wpan_src64(DUT).\ + filter(is_mle_announce_or_child_id_request).\ + must_not_next() # Step 9: Router_1 # - Description: To verify connectivity, Harness instructs Router_1 to send an ICMPv6 Echo Request to the DUT link diff --git a/tests/nexus/verify_7_1_5.py b/tests/nexus/verify_7_1_5.py index bef6dcc56..b992e4311 100644 --- a/tests/nexus/verify_7_1_5.py +++ b/tests/nexus/verify_7_1_5.py @@ -188,7 +188,7 @@ def verify(pv): # Unicast packets should be decrypted correctly. We allow some leeway for SED poll timing. pkts.filter_wpan_src64(ROUTER_1).\ filter_wpan_dst64(SED_1).\ - filter(lambda p: p.mle.cmd in { + filter(lambda p: p.mle.cmd and p.mle.cmd in { consts.MLE_CHILD_UPDATE_REQUEST, consts.MLE_DATA_RESPONSE }).\