[PATCH 04/18] tests: hwsim: Verify NDP setup against the peer schedule channels

Andrei Otcheretianski andrei.otcheretianski at intel.com
Mon Oct 12 08:46:38 PDT 2026


Add two additional NDP tests for the following schedule combinations:

- Peers that advertise the same time bitmaps but map them to opposite
  channels, so no NDP can be set up.
- Peers that use the same control channel with a different bandwidth,
  and thus a different operating class. This is expected to succeed.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski at intel.com>
---
 tests/hwsim/test_nan.py | 124 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 124 insertions(+)

diff --git a/tests/hwsim/test_nan.py b/tests/hwsim/test_nan.py
index 71d95ea03e..7944dfaece 100644
--- a/tests/hwsim/test_nan.py
+++ b/tests/hwsim/test_nan.py
@@ -1989,6 +1989,130 @@ def test_nan_dp_open_counter_conditional(dev, apdev, params):
     """NAN DP open with counter proposal using conditional availability"""
     run_nan_dp(counter=True, force_conditional=True)
 
+def _nan_dp_expect_counter(pub, sub, pid, sid, paddr, saddr):
+    """Request an NDP and verify that the publisher counters the proposal.
+
+    Returns the (ndp_id, init_ndi) carried in the counter request.
+    """
+    if "OK" not in sub.ndp_request(sub.ndi_name, sid, paddr, pid, "aabbcc"):
+        raise Exception("NDP request failed")
+
+    ev = pub.wpas.wait_event(["NAN-NDP-REQUEST"], timeout=5)
+    if ev is None:
+        raise Exception("NAN-NDP-REQUEST event not seen")
+
+    data = split_nan_event(ev)
+    if "OK" not in pub.ndp_response("accept", saddr, ndi=pub.ndi_name,
+                                    ndp_id=data['ndp_id'],
+                                    init_ndi=data['init_ndi'],
+                                    handle=pid, ssi="ddeeff"):
+        raise Exception("NDP response (accept) failed")
+
+    ev = sub.wpas.wait_event(["NAN-NDP-COUNTER-REQUEST", "NAN-NDP-CONNECTED",
+                              "NAN-NDP-DISCONNECTED"], timeout=5)
+    if ev is None:
+        raise Exception("No NDP result event on subscriber")
+
+    if "NAN-NDP-COUNTER-REQUEST" not in ev:
+        raise Exception(f"Publisher did not counter the proposal: {ev}")
+
+    data = split_nan_event(ev)
+    return data['ndp_id'], data['init_ndi']
+
+def _run_nan_dp_swapped_channels():
+    sub_chans = [(2437, "0e000000"), (5180, "f0ffffff")]
+    pub_chans = [(2437, "f0ffffff"), (5180, "0e000000")]
+
+    with hwsim_nan_radios() as (wpas1, wpas2), \
+        NanDevice(wpas1, "nan0", "ndi0") as pub, \
+        NanDevice(wpas2, "nan1", "ndi1") as sub:
+
+        pid, sid, paddr, saddr = _nan_discover_service(pub, sub,
+                                                       "test_service",
+                                                       "aabbccdd", "ddbbccaa",
+                                                       data_path=True)
+
+        _nan_schedule_config(sub, *sub_chans)
+        _nan_schedule_config(pub, *pub_chans)
+
+        ndp_id, init_ndi = _nan_dp_expect_counter(pub, sub, pid, sid, paddr,
+                                                  saddr)
+
+        logger.info("Publisher countered the proposed schedule")
+
+        # Accepting the counter while still using the local schedule leaves
+        # the two schedules just as incompatible
+        if "OK" not in sub.ndp_response("accept", paddr, ndi=sub.ndi_name,
+                                        ndp_id=ndp_id, init_ndi=init_ndi,
+                                        handle=sid, ssi="11223344"):
+            raise Exception("NDP response (confirm) failed")
+
+        for dev, name in ((sub, "subscriber"), (pub, "publisher")):
+            ev = dev.wpas.wait_event(["NAN-NDP-DISCONNECTED"], timeout=5)
+            if ev is None or "failure=1" not in ev:
+                raise Exception(f"NDP not rejected on {name}: {ev}")
+
+        logger.info("Confirming the counter without moving channels failed")
+
+        # Adopt the countered channels and retry
+        pub.wpas.dump_monitor()
+        sub.wpas.dump_monitor()
+        _nan_schedule_config(sub, *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)
+
+        _nan_test_connectivity(pub, sub)
+        _nan_ndp_terminate(pub, sub, paddr, init_ndi, ndp_id)
+
+def test_nan_dp_swapped_channels(dev, apdev, params):
+    """NAN DP - peers use the same slots on swapped channels"""
+    set_country("US")
+    try:
+        # The two devices advertise the same time bitmaps, but each one maps
+        # them to the other one's channel, so there is no slot on which both
+        # are on the same channel.
+        _run_nan_dp_swapped_channels()
+    finally:
+        set_country("00")
+
+def test_nan_dp_different_bandwidth(dev, apdev, params):
+    """NAN DP - peers use the same control channel with different bandwidths"""
+    set_country("US")
+    try:
+        with hwsim_nan_radios() as (wpas1, wpas2), \
+            NanDevice(wpas1, "nan0", "ndi0") as pub, \
+            NanDevice(wpas2, "nan1", "ndi1") as sub:
+
+            # The publisher is limited to 20 MHz while the subscriber uses the
+            # widest channel it can, so the two advertise the same channel with
+            # a different operating class. They still share the control
+            # channel, so the NDP has to be established.
+            pub.set("max_bw", 20)
+
+            pid, sid, paddr, saddr = _nan_discover_service(pub, sub,
+                                                           "test_service",
+                                                           "aabbccdd",
+                                                           "ddbbccaa",
+                                                           data_path=True)
+
+            _nan_schedule_config(sub, (5180, "f0ffffff"))
+            _nan_schedule_config(pub, (5180, "f0ffffff"))
+
+            ndp_id, init_ndi = _nan_ndp_request_and_accept(pub, sub, pid, sid,
+                                                           paddr, saddr,
+                                                           req_ssi="aabbcc",
+                                                           resp_ssi="ddeeff",
+                                                           configure_schedule=False)
+
+            _nan_test_connectivity(pub, sub)
+            _nan_ndp_terminate(pub, sub, paddr, init_ndi, ndp_id)
+    finally:
+        set_country("00")
+
 def test_nan_dp_sk_ccmp128(dev, apdev, params):
     """NAN DP - 2way NDL + SK CCMP security"""
     run_nan_dp(csid=1)
-- 
2.53.0




More information about the Hostap mailing list