From patchwork Wed May 13 06:59:08 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrei Otcheretianski X-Patchwork-Id: 2237510 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=37lhX68p; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=lKxZmqZ0; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org; envelope-from=hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=patchwork.ozlabs.org) Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4gFks72vvDz1yLT for ; Wed, 13 May 2026 17:01:31 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-ID:Date:Subject:Cc :To:From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=U2hT2T0eN9ScHg9aQxLvvLL3BIYRBepRGUwQ81IT6JE=; b=37lhX68prhQsyd +jP77hCAVEJYNy+e/yn2T1mh9ozgnF0qg/U8C0mAn3ML2h1F342YmLDUPlrROZp5msqnyCsPjSXA6 5hDKqemDg8KIQM07AS4k+5aFzAl3eMxrSNDHzNhpZwY1WaabXowSpf7v7iohBmH2+BmjblrUofrwz y1hTMkjq8CSqIrcIAkhxxrY6+l3ogYWAQGj7hemcO4CBXaqnGc2s8XjK9WaLRRNzwUih8ZvTDeKYu /Z/NK8AVmA/Hg9cRx7dhoZ4Bi22DBoHGMBRsD8Y7420arTSyyE0KXr3G8IRGxUqSCr5FnTZJUYoD4 7qzeICq549722JWnvQ0A==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.99.1 #2 (Red Hat Linux)) id 1wN3ZF-00000001Ueo-0XrG; Wed, 13 May 2026 06:59:41 +0000 Received: from mgamail.intel.com ([198.175.65.10]) by bombadil.infradead.org with esmtps (Exim 4.99.1 #2 (Red Hat Linux)) id 1wN3ZD-00000001UdZ-1pFX for hostap@lists.infradead.org; Wed, 13 May 2026 06:59:40 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1778655580; x=1810191580; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=C9h4bCKmnAIggG91Q3v3GtNjCwSGfgh+oJfRbJLuthc=; b=lKxZmqZ0ub2zrdULrNpnVzAJZeKqHQiEu/W3VTh+iiOVnJkM38MF9Tcv l5BKoAgR2kW7nvLRKm3FrR2FZPencVeGUDWb1wARN5Wv0CnJWN2ZWWgeo qhEeONvw7rQPL3benydluRN8epD8PNWqMyPE1GydIs1WroSMP2JpVhJm1 yMmaevyGbkk3CB7gQ5ftaqh1xc3wWNbLZcnL+9Mkm/c8XSirh0MgN6zQt ze//Dtd9x/ZhwDFyrBDHJio/PaUmwBv4fwj77e2R2cXggs+lTNtiKfGDt 0sWwQacQOhQaauMChUog4hSQTbRT5Nw653UPG6shrkICL1SV/j3boUUU3 Q==; X-CSE-ConnectionGUID: d9kOh0JARg+nNsLcOoLZVQ== X-CSE-MsgGUID: XtrqhLuBShy7M2VXdHQGsA== X-IronPort-AV: E=McAfee;i="6800,10657,11784"; a="97001333" X-IronPort-AV: E=Sophos;i="6.23,232,1770624000"; d="scan'208";a="97001333" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 May 2026 23:59:39 -0700 X-CSE-ConnectionGUID: 2czMTAmnTn6tT1uyW553sg== X-CSE-MsgGUID: wCP3QkGQTwqSF/thBI8wGA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,232,1770624000"; d="scan'208";a="233721946" Received: from iapp347.iil.intel.com (HELO 87c02287900a.iil.intel.com) ([10.167.28.6]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 May 2026 23:59:37 -0700 From: Andrei Otcheretianski To: hostap@lists.infradead.org Cc: maheshkkv@google.com, vamsin@qti.qualcomm.com, Ilan Peer Subject: [PATCH 5/5] tests: Add NAN-STOPPED event tests on radio destruction Date: Wed, 13 May 2026 09:59:08 +0300 Message-ID: <20260513065909.12048-10-andrei.otcheretianski@intel.com> X-Mailer: git-send-email 2.53.0 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.9.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20260512_235939_521010_DEB149FC X-CRM114-Status: GOOD ( 10.53 ) X-Spam-Score: -4.8 (----) X-Spam-Report: Spam detection software, running on the system "bombadil.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From: Ilan Peer Add tests to verify that NAN-STOPPED is reported when the underlying radio is destroyed while NAN is active: - test_nan_stopped_on_iface_removal: Verifies NAN-STOPPED after radio destruction during se [...] Content analysis details: (-4.8 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/, medium trust [198.175.65.10 listed in list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.4 DKIMWL_WL_HIGH DKIMwl.org - High trust sender -0.0 DMARC_PASS DMARC pass policy X-BeenThere: hostap@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Hostap" Errors-To: hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Ilan Peer Add tests to verify that NAN-STOPPED is reported when the underlying radio is destroyed while NAN is active: - test_nan_stopped_on_iface_removal: Verifies NAN-STOPPED after radio destruction during service discovery, then recovers NAN on a new radio. - test_nan_stopped_on_iface_removal_with_ndp: Same scenario but with an active NDP (NAN Data Path) including connectivity verification. Signed-off-by: Ilan Peer --- tests/hwsim/test_nan.py | 144 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 143 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/test_nan.py b/tests/hwsim/test_nan.py index 691da50032..c2905c9933 100644 --- a/tests/hwsim/test_nan.py +++ b/tests/hwsim/test_nan.py @@ -10,9 +10,10 @@ logger = logging.getLogger() from utils import * import string import hwsim_utils -from hwsim import HWSimRadio +from hwsim import HWSimRadio, HWSimController from contextlib import contextmanager, ExitStack from test_p2p_channel import set_country +import time @contextmanager def hwsim_nan_radios(count=2, n_channels=3): @@ -2125,3 +2126,144 @@ def test_nan_override_potential_availability(dev, apdev, params): # expect any changes during the test execution. if potential != old_potential: raise Exception("Potential availability did not revert to original after clearing override") + +def test_nan_stopped_on_iface_removal(dev, apdev, params): + """NAN cluster and discovery followed by radio destruction reports NAN-STOPPED""" + controller = HWSimController() + radio1 = HWSimRadio(n_channels=3, use_nan=True) + radio1_id, ifname1 = radio1.__enter__() + radio1_destroyed = False + + try: + with HWSimRadio(n_channels=3, use_nan=True) as (radio2_id, ifname2): + wpas1 = WpaSupplicant(global_iface="/tmp/wpas-wlan5") + wpas1.interface_add(ifname1) + wpas2 = WpaSupplicant(global_iface="/tmp/wpas-wlan6") + wpas2.interface_add(ifname2) + + nan_ifname = "nan0" + + logger.info("Starting NAN on publisher") + pub = NanDevice(wpas1, nan_ifname) + pub.start() + + with NanDevice(wpas2, "nan1") as sub: + logger.info("Verifying service discovery") + nan_sync_discovery(pub, sub, "test_service", + pssi="aabbccdd", sssi="ddbbccaa") + + logger.info("Destroying publisher radio") + wpas1.dump_monitor() + controller.destroy_radio(radio1_id) + radio1_destroyed = True + + logger.info("Waiting for NAN-STOPPED event on publisher") + ev = wpas1.wait_global_event(["NAN-STOPPED"], timeout=5) + if ev is None: + raise Exception("NAN-STOPPED event not received after radio destruction") + if f"ifname={nan_ifname}" not in ev: + raise Exception(f"Unexpected NAN-STOPPED event content: {ev}") + + logger.info("Removing old interface and adding new radio") + sub.wpas.dump_monitor() + wpas1.interface_remove(ifname1) + + radio1 = HWSimRadio(n_channels=3, use_nan=True) + radio1_id, ifname1_new = radio1.__enter__() + radio1_destroyed = False + wpas1.interface_add(ifname1_new) + + logger.info("Starting NAN on re-added radio") + pub = NanDevice(wpas1, nan_ifname) + pub.start() + + logger.info("Verifying service discovery on re-added radio") + nan_sync_discovery(pub, sub, "test_service2", + pssi="11223344", sssi="44332211") + finally: + if not radio1_destroyed: + radio1.__exit__(None, None, None) + +def test_nan_stopped_on_iface_removal_with_ndp(dev, apdev, params): + """NAN cluster, NDP establishment, then radio destruction reports NAN-STOPPED""" + set_country("US") + controller = HWSimController() + radio1 = HWSimRadio(n_channels=3, use_nan=True) + radio1_id, ifname1 = radio1.__enter__() + radio1_destroyed = False + + try: + with HWSimRadio(n_channels=3, use_nan=True) as (radio2_id, ifname2): + wpas1 = WpaSupplicant(global_iface="/tmp/wpas-wlan5") + wpas1.interface_add(ifname1) + wpas2 = WpaSupplicant(global_iface="/tmp/wpas-wlan6") + wpas2.interface_add(ifname2) + + nan_ifname = "nan0" + ndi_name = "ndi0" + + logger.info("Starting NAN on publisher with NDI") + pub = NanDevice(wpas1, nan_ifname, ndi_name) + pub.start() + + with NanDevice(wpas2, "nan1", "ndi1") as sub: + logger.info("Establishing NDP between publisher and subscriber") + pid, sid, paddr, saddr = _nan_discover_service( + pub, sub, "test_service", "aabbccdd", "ddbbccaa", + data_path=True) + ndp_id, init_ndi = _nan_ndp_request_and_accept( + pub, sub, pid, sid, paddr, saddr, + req_ssi="aabbcc", resp_ssi="ddeeff") + + logger.info("Verifying connectivity over NDP") + _nan_test_connectivity(pub, sub) + + logger.info("Destroying publisher radio while NDP is active") + wpas1.dump_monitor() + sub.wpas.dump_monitor() + controller.destroy_radio(radio1_id) + radio1_destroyed = True + + logger.info("Waiting for NAN-STOPPED event on publisher") + ev = wpas1.wait_global_event(["NAN-STOPPED"], timeout=5) + if ev is None: + raise Exception("NAN-STOPPED event not received after radio destruction") + if f"ifname={nan_ifname}" not in ev: + raise Exception(f"Unexpected NAN-STOPPED event content: {ev}") + + logger.info("Terminating NDP on subscriber") + sub.ndp_terminate(paddr, init_ndi, ndp_id) + ev = sub.wpas.wait_event(["NAN-NDP-DISCONNECTED"], timeout=5) + if ev is None: + raise Exception("NAN-NDP-DISCONNECTED not received on subscriber") + + logger.info("Removing old interface and adding new radio") + sub.wpas.dump_monitor() + wpas1.interface_remove(ifname1) + + radio1 = HWSimRadio(n_channels=3, use_nan=True) + radio1_id, ifname1_new = radio1.__enter__() + radio1_destroyed = False + + wpas1.interface_add(ifname1_new) + + logger.info("Starting NAN on re-added radio with NDI") + pub = NanDevice(wpas1, nan_ifname, ndi_name) + pub.start() + + logger.info("Establishing NDP on re-added radio") + pid, sid, paddr, saddr = _nan_discover_service( + pub, sub, "test_service2", "11223344", "44332211", + data_path=True) + ndp_id, init_ndi = _nan_ndp_request_and_accept( + pub, sub, pid, sid, paddr, saddr, + req_ssi="aabbcc", resp_ssi="ddeeff") + + logger.info("Verifying connectivity on re-added radio") + _nan_test_connectivity(pub, sub) + + logger.info("NDP recovery after radio destruction verified successfully") + finally: + if not radio1_destroyed: + radio1.__exit__(None, None, None) + set_country("00")