[PATCH 54/71] wpa_supplicant: Manage NDI operstate using per-interface NDP refcount

Andrei Otcheretianski andrei.otcheretianski at intel.com
Wed Apr 1 15:02:03 PDT 2026


From: Daniel Gabay <daniel.gabay at intel.com>

A single NDI can maintain NDPs with multiple peers concurrently.
Introduce a per-NDI reference count to track active NDPs across all
peers, ensuring correct operstate transitions:

- Set UP when the first NDP connects (refcount 0 -> 1)
- Set DORMANT when the last NDP disconnects (refcount 1 -> 0)
- Maintain operstate UP while any NDP remains active (refcount > 1)

Signed-off-by: Daniel Gabay <daniel.gabay at intel.com>
---
 wpa_supplicant/nan_supplicant.c   | 41 ++++++++++++++++++++++++++++---
 wpa_supplicant/wpa_supplicant_i.h |  1 +
 2 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/wpa_supplicant/nan_supplicant.c b/wpa_supplicant/nan_supplicant.c
index 3a5337bc7b..a00d92cb68 100644
--- a/wpa_supplicant/nan_supplicant.c
+++ b/wpa_supplicant/nan_supplicant.c
@@ -493,7 +493,7 @@ static int wpas_nan_add_ndi_sta(struct wpa_supplicant *wpa_s,
 		wpa_printf(MSG_DEBUG,
 			   "NAN: NDI station added without keys for peer "
 			   MACSTR, MAC2STR(peer_ndi));
-		return 0;
+		goto out_success;
 	}
 
 	if (nan_peer_get_tk(wpa_s->nan, peer_nmi, peer_ndi, local_ndi, tk,
@@ -512,8 +512,28 @@ static int wpas_nan_add_ndi_sta(struct wpa_supplicant *wpa_s,
 		return -1;
 	}
 
-	return wpa_drv_sta_set_flags(ndi_wpa_s, peer_ndi, WPA_STA_AUTHORIZED,
-				     WPA_STA_AUTHORIZED, ~0);
+	if (wpa_drv_sta_set_flags(ndi_wpa_s, peer_ndi, WPA_STA_AUTHORIZED,
+				  WPA_STA_AUTHORIZED, ~0)) {
+		wpa_printf(MSG_ERROR,
+			   "NAN: Failed to set authorize for NDI station");
+		wpas_nan_remove_ndi_keys(ndi_wpa_s, peer_ndi);
+		wpa_drv_sta_remove(ndi_wpa_s, peer_ndi);
+		return -1;
+	}
+
+out_success:
+	ndi_wpa_s->nan_ndi_ndp_refcount++;
+	wpa_printf(MSG_DEBUG,
+		   "NAN: NDP refcount incremented to %u (peer_ndi=" MACSTR
+		   " peer_nmi=" MACSTR ")",
+		   ndi_wpa_s->nan_ndi_ndp_refcount,
+		   MAC2STR(peer_ndi), MAC2STR(peer_nmi));
+
+	/* Set operstate UP only when first NDP is established on this NDI */
+	if (ndi_wpa_s->nan_ndi_ndp_refcount == 1)
+		wpa_drv_set_operstate(ndi_wpa_s, 1);
+
+	return 0;
 }
 
 
@@ -538,6 +558,21 @@ static void wpas_nan_remove_ndi_sta(struct wpa_supplicant *wpa_s,
 
 	wpas_nan_remove_ndi_keys(ndi_wpa_s, peer_ndi);
 	wpa_drv_sta_remove(ndi_wpa_s, peer_ndi);
+
+	if (!ndi_wpa_s->nan_ndi_ndp_refcount)
+		return;
+
+	ndi_wpa_s->nan_ndi_ndp_refcount--;
+	wpa_printf(MSG_DEBUG, "NAN: NDP refcount decremented to %u (peer_ndi="
+		   MACSTR ")", ndi_wpa_s->nan_ndi_ndp_refcount,
+		   MAC2STR(peer_ndi));
+
+	/* Set operstate DORMANT only when last NDP is removed from
+	 * this NDI
+	 */
+	if (!ndi_wpa_s->nan_ndi_ndp_refcount)
+		wpa_drv_set_operstate(ndi_wpa_s, 0);
+
 }
 
 
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 44a7f58c28..22e7c7b4fc 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -1737,6 +1737,7 @@ struct wpa_supplicant {
 	u16 nan_supported_csids;
 	struct wpa_freq_range_list nan_disallowed_freqs;
 	u16 nan_max_bw;
+	unsigned int nan_ndi_ndp_refcount; /* Active NDP count on this NDI */
 #endif /* CONFIG_NAN */
 #ifdef CONFIG_ENC_ASSOC
 	bool assoc_resp_encrypted; /* Whether (Re)Association Response frame
-- 
2.53.0




More information about the Hostap mailing list