From ea05e2fd0cd2a8359e0f31094d15a1c9a6ea1461 Mon Sep 17 00:00:00 2001 From: Jonathan Hui Date: Sun, 22 Mar 2026 23:34:11 -0500 Subject: [PATCH] [nexus] fix flaky BBR-TC-03 by filtering transient mDNS responses (#12736) Nexus test 1_2_BBR_TC_3 occasionally fails during Step 6 after a device reboot. The failure occurs because the Backbone Router (BBR) is reported as active in the mDNS state bitmap ('sb' record), but the mandatory 'omr' record is not yet present in the response. This transient state happens because the BBR function is enabled immediately upon attachment, whereas the Routing Manager requires a brief period to establish and favor an OMR prefix. This commit updates the Python verification script to filter for mDNS responses that include the 'omr' record in Steps 6 and 13. This allows the test to wait for the complete state to be published naturally, rather than failing on the first transient packet received. Validated with 50 successful sequential executions of the test. --- tests/nexus/verify_1_2_BBR_TC_3.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/tests/nexus/verify_1_2_BBR_TC_3.py b/tests/nexus/verify_1_2_BBR_TC_3.py index f657c058e..cad0b9f4c 100644 --- a/tests/nexus/verify_1_2_BBR_TC_3.py +++ b/tests/nexus/verify_1_2_BBR_TC_3.py @@ -108,6 +108,22 @@ def verify(pv): entries[bytes(txt).decode()] = None return entries + def get_bbr_txt_entries_if_complete(p): + """Returns mDNS TXT entries if 'omr' and 'sb' records are present and have values, otherwise None.""" + txt = get_txt_entries(p) + if txt and txt.get('omr') and txt.get('sb') is not None: + return txt + return None + + def has_sb_bit(p, bit_pos): + """Checks for a bit in the 'sb' record of a complete ('omr' and 'sb' present) mDNS response.""" + txt = get_bbr_txt_entries_if_complete(p) + if not txt: + return False + # 'sb' is a 4-byte value. + sb_val = struct.unpack('>I', txt['sb'])[0] + return (sb_val >> bit_pos) & 1 == 1 + def verify_mdns_response(p, expected_sb_bits, expected_omr_var): # Verify Service Instance Name names = [] @@ -263,6 +279,7 @@ def verify(pv): filter_eth_src(BR_1_ETH).\ filter(is_mdns_response).\ filter(lambda p: p.number > q_number).\ + filter(get_bbr_txt_entries_if_complete).\ must_next() verify_mdns_response(p1, { 'ifstate': [1, 2], @@ -320,7 +337,7 @@ def verify(pv): filter_eth_src(BR_2_ETH).\ filter(is_mdns_response).\ filter(lambda p: p.number > q_number).\ - filter(lambda p: (struct.unpack('>I', get_txt_entries(p)['sb'])[0] >> 8) & 1 == 1).\ + filter(lambda p: has_sb_bit(p, 8)).\ must_next() verify_mdns_response(p2, {'ifstate': 2, 'active': 1, 'primary': 1}, expected_omr_var='OMR_PREFIX_STEP_10') @@ -342,7 +359,7 @@ def verify(pv): filter_eth_src(BR_1_ETH).\ filter(is_mdns_response).\ filter(lambda p: p.number > q_number).\ - filter(lambda p: (struct.unpack('>I', get_txt_entries(p)['sb'])[0] >> 7) & 1 == 1).\ + filter(lambda p: has_sb_bit(p, 7)).\ must_next() verify_mdns_response(p1, {'ifstate': 2, 'active': 1, 'primary': 0}, expected_omr_var='OMR_PREFIX_STEP_11') @@ -351,7 +368,7 @@ def verify(pv): filter_eth_src(BR_2_ETH).\ filter(is_mdns_response).\ filter(lambda p: p.number > q_number).\ - filter(lambda p: (struct.unpack('>I', get_txt_entries(p)['sb'])[0] >> 8) & 1 == 1).\ + filter(lambda p: has_sb_bit(p, 8)).\ must_next() verify_mdns_response(p2, {'ifstate': 2, 'active': 1, 'primary': 1}, expected_omr_var='OMR_PREFIX_STEP_10')