[PATCH v3 34/46] nl80211: Add dedicated PR ranging socket and stop op

Kavita Kavita kavita.kavita at oss.qualcomm.com
Wed May 13 02:59:58 PDT 2026


From: Veerendranath Jakkam <vjakkam at qti.qualcomm.com>

Create a dedicated netlink socket (nl_pr) in nl80211_global for PR
peer measurements. The socket is created when start_peer_measurement()
is called, used to send NL80211_CMD_PEER_MEASUREMENT_START, and
registered with eloop to receive RESULT and COMPLETE events.

Add stop_peer_measurement() driver op implemented by
nl80211_stop_peer_measurement() which destroys the nl_pr socket and
unregisters it from eloop. Also add cleanup in nl80211_global_deinit()
for the case where stop was never called.

Signed-off-by: Veerendranath Jakkam <vjakkam at qti.qualcomm.com>
---
 src/drivers/driver.h         |  9 +++++++
 src/drivers/driver_nl80211.c | 46 +++++++++++++++++++++++++++++++++++-
 src/drivers/driver_nl80211.h |  4 ++++
 3 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index ee710fad8..4689bc5b0 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -5863,6 +5863,15 @@ struct wpa_driver_ops {
 	int (*start_peer_measurement)(void *priv, const u8 *peer_addr,
 				      int freq, u8 channel, int bw,
 				      struct pr_pasn_ranging_params *params);
+
+	/**
+	 * stop_peer_measurement - Stop peer measurement and destroy ranging socket
+	 * @priv: Private driver interface data
+	 *
+	 * Unregisters the ranging socket from eloop and frees all associated
+	 * resources. Safe to call when no ranging session is active (no-op).
+	 */
+	void (*stop_peer_measurement)(void *priv);
 #endif /* CONFIG_PR */
 
 #ifdef CONFIG_NAN
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 8af3efe98..4435b915d 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -9330,6 +9330,20 @@ static int nl80211_start_peer_measurement(void *priv, const u8 *peer_addr,
 		return -1;
 	}
 
+	/* Create dedicated ranging socket if not already created */
+	if (drv->global->nl_pr) {
+		wpa_printf(MSG_ERROR,
+			   "nl80211: PR ranging socket already in use");
+		return -1;
+	}
+
+	drv->global->nl_pr = nl_create_handle(drv->global->nl_cb, "pr");
+	if (!drv->global->nl_pr) {
+		wpa_printf(MSG_ERROR,
+			   "nl80211: Failed to create PR ranging socket");
+		return -1;
+	}
+
 	/* Route via PD wdev if src_addr matches */
 	if (drv->pd_bss && !is_zero_ether_addr(params->src_addr) &&
 	    ether_addr_equal(params->src_addr, drv->pd_bss->addr)) {
@@ -9553,19 +9567,29 @@ static int nl80211_start_peer_measurement(void *priv, const u8 *peer_addr,
 	cookie = 0;
 	os_memset(&ack_arg, 0, sizeof(struct nl80211_ack_ext_arg));
 	ack_arg.ext_data = &cookie;
-	ret = send_and_recv(drv, drv->global->nl, msg, NULL, NULL,
+	ret = send_and_recv(drv, drv->global->nl_pr, msg, NULL, NULL,
 			    ack_handler_cookie, &ack_arg, NULL);
 
 	if (ret < 0) {
 		wpa_printf(MSG_ERROR,
 			   "nl80211: Peer measurement start failed: ret=%d (%s)",
 			   ret, strerror(-ret));
+		nl_destroy_handles(&drv->global->nl_pr);
 	} else {
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: Peer measurement started successfully addr=" MACSTR
 			   " cookie=%llu", MAC2STR(peer_addr),
 			   (unsigned long long) cookie);
 		params->cookie = cookie;
+		/*
+		 * Register the PR socket with eloop so that
+		 * NL80211_CMD_PEER_MEASUREMENT_RESULT and
+		 * NL80211_CMD_PEER_MEASUREMENT_COMPLETE events are delivered
+		 * to the existing nl80211 event handler.
+		 */
+		nl80211_register_eloop_read(&drv->global->nl_pr,
+					    wpa_driver_nl80211_event_receive,
+					    drv->global->nl_cb, 1);
 	}
 
 	return ret;
@@ -9573,9 +9597,23 @@ static int nl80211_start_peer_measurement(void *priv, const u8 *peer_addr,
 fail:
 	wpa_printf(MSG_ERROR, "nl80211: Failed to build peer measurement message");
 	nlmsg_free(msg);
+	nl_destroy_handles(&drv->global->nl_pr);
 	return -1;
 }
 
+
+static void nl80211_stop_peer_measurement(void *priv)
+{
+	struct i802_bss *bss = priv;
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+
+	if (!drv->global->nl_pr)
+		return;
+
+	wpa_printf(MSG_DEBUG, "nl80211: Stopping PR ranging socket");
+	nl80211_destroy_eloop_handle(&drv->global->nl_pr, 1);
+}
+
 #endif /* CONFIG_PR */
 
 static void dump_ifidx(struct wpa_driver_nl80211_data *drv)
@@ -11354,6 +11392,11 @@ static void nl80211_global_deinit(void *priv)
 
 	nl_cb_put(global->nl_cb);
 
+#ifdef CONFIG_PR
+	if (global->nl_pr)
+		nl80211_destroy_eloop_handle(&global->nl_pr, 1);
+#endif /* CONFIG_PR */
+
 	if (global->ioctl_sock >= 0)
 		close(global->ioctl_sock);
 
@@ -16722,5 +16765,6 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
 	.pd_start = nl80211_pd_start,
 	.pd_stop = nl80211_pd_stop,
 	.start_peer_measurement = nl80211_start_peer_measurement,
+	.stop_peer_measurement = nl80211_stop_peer_measurement,
 #endif /* CONFIG_PR */
 };
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index d1133a1fe..9c871ce18 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -52,6 +52,10 @@ struct nl80211_global {
 	/* Dedicated socket for NAN interface creation and events */
 	struct nl_sock *nl_nan;
 #endif /* CONFIG_NAN */
+#ifdef CONFIG_PR
+	/* Dedicated socket for PR peer measurement commands and events */
+	struct nl_sock *nl_pr;
+#endif /* CONFIG_PR */
 };
 
 struct nl80211_wiphy_data {
-- 
2.34.1




More information about the Hostap mailing list