[PATCH 15/18] tests: hwsim: Verify that the NDC channel is not evacuated
Andrei Otcheretianski
andrei.otcheretianski at intel.com
Mon Oct 12 08:46:49 PDT 2026
Add a hwsim test that checks that NDC channel is not evacuated.
Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski at intel.com>
---
tests/hwsim/test_nan.py | 88 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 88 insertions(+)
diff --git a/tests/hwsim/test_nan.py b/tests/hwsim/test_nan.py
index 920d5144a4..b9ef2b3516 100644
--- a/tests/hwsim/test_nan.py
+++ b/tests/hwsim/test_nan.py
@@ -10,6 +10,7 @@ logger = logging.getLogger()
from utils import *
import string
import hwsim_utils
+import hostapd
from hwsim import HWSimRadio, HWSimController
from contextlib import contextmanager, ExitStack
from test_p2p_channel import set_country
@@ -3205,6 +3206,9 @@ def _nan_get_ndc_freq(dev):
m = re.search(r'^nan_ndc_freq=(\d+)$', status, re.MULTILINE)
return int(m.group(1)) if m else None
+def _nan_bitmap_slots(bitmap):
+ return bin(int(bitmap, 16)).count("1")
+
def _nan_get_advertised_ndc(dev, addr):
"""Query the NDC ID and time bitmap advertised in a peer's SDFs, if any
(NAN_PEER_INFO schedule)."""
@@ -3393,3 +3397,87 @@ def test_nan_dp_ndc_not_reusable(dev, apdev, params):
_nan_ndp_terminate(dev_a, dev_b, addr_a, init_ndi1, ndp_id1)
finally:
set_country("00")
+
+# TODO: Drop @disable_ipv6 once mac80211_hwsim is fixed - IPv6 MLD reports on the
+# NDI hit a "TX w/o channel" warning while the evacuation is in progress
+ at disable_ipv6
+def test_nan_dp_ndc_chan_not_evacuated(dev, apdev, params):
+ """NAN DP - channel evacuation skips the NDC channel"""
+ set_country("US")
+ try:
+ # The radio supports only two channels, so bringing up a BSS on a
+ # third one forces the driver to evacuate one of the NAN channels.
+ with hwsim_nan_radios(count=2, n_channels=2) as [wpas1, wpas2], \
+ NanDevice(wpas1, "nan0", "ndi0") as pub, \
+ NanDevice(wpas2, "nan1", "ndi1") as sub:
+
+ pssi = "aabbccdd001122334455667788"
+ sssi = "ddbbccaa001122334455667788"
+
+ # The NDC is expected on 2437 MHz, which has the fewest slots,
+ # i.e. it is the channel the driver would evacuate first if it
+ # were not protected.
+ chans = ((2437, "0e000000"), (5180, "f0000000"))
+ slots = {freq: _nan_bitmap_slots(bitmap) for freq, bitmap in chans}
+
+ pid, sid, paddr, saddr = _nan_discover_service(
+ pub, sub, "test_svc", pssi, sssi, data_path=True)
+
+ _nan_schedule_config(sub, *chans)
+ _nan_schedule_config(pub, *chans)
+
+ ndp_id, init_ndi = _nan_ndp_request_and_accept(
+ pub, sub, pid, sid, paddr, saddr,
+ req_ssi="aabbcc", resp_ssi="ddeeff",
+ configure_schedule=False)
+
+ if _nan_get_ndc_id(pub) is None:
+ raise Exception("NDC not established after NDP")
+
+ ndc_freq = _nan_get_ndc_freq(pub)
+ if ndc_freq not in slots:
+ raise Exception(f"NDC on unexpected freq {ndc_freq}")
+ # mac80211 evacuates the least used channel first; the test only
+ # proves anything while that assumption holds
+ if slots[ndc_freq] != min(slots.values()):
+ raise Exception(
+ f"NDC freq {ndc_freq} is not the cheapest evacuation "
+ "candidate, the test would not prove anything")
+
+ logger.info(f"NDC established on {ndc_freq} MHz")
+
+ # Bring up a BSS on a channel that NAN is not using, leaving the
+ # driver no choice but to evacuate one of the NAN channels.
+ params_ap = {"ssid": "test-nan-bss", "channel": "1",
+ "country_code": "US", "ieee80211n": "1"}
+ hostapd.add_ap(apdev[0], params_ap)
+
+ # mac80211_hwsim keeps the radio on the NDC channel, so the STA
+ # misses the authentication response and the association never
+ # completes. Only the evacuation decision is verified here.
+ # TODO: Wait for the connection and verify that the NDP survived
+ # it once mac80211_hwsim is fixed.
+ pub.wpas.dump_monitor()
+ wpas1.connect("test-nan-bss", key_mgmt="NONE", scan_freq="2412",
+ wait_connect=False)
+
+ ev = pub.wpas.wait_event(["NAN-CHAN-EVACUATION"], timeout=10)
+ if ev is None:
+ raise Exception("No NAN channel was evacuated for the BSS")
+
+ evac_freq = int(split_nan_event(ev)['freq'])
+ logger.info(f"Evacuated {evac_freq} MHz")
+
+ other_freq = next(freq for freq in slots if freq != ndc_freq)
+ if evac_freq != other_freq:
+ raise Exception(f"Expected {other_freq} MHz to be evacuated, "
+ f"got {evac_freq} MHz")
+
+ # The NDC survived, so the NDP is still usable.
+ if _nan_get_ndc_freq(pub) != ndc_freq:
+ raise Exception("NDC moved after the evacuation")
+
+ _nan_test_connectivity(pub, sub)
+ _nan_ndp_terminate(pub, sub, paddr, init_ndi, ndp_id)
+ finally:
+ set_country("00")
--
2.53.0
More information about the Hostap
mailing list