[RFC 1/2] nl80211: Implement support for scheduled scan timeout

Jussi Laakkonen jussi.laakkonen at jolla.com
Fri Dec 13 09:56:29 PST 2024


Some drivers do start scheduled scan but never finish with the results.
This timeout is equal to the scan timeout and behaves similarly, except
the scan stopped event is sent when timeout is reached.

Timeout will be started when the scheduled scan is initiated and
canceled when the scan is stopped. Timeout itself is calculated
similarly to the scan event timeout, ranging from 10s to 30s and for
this a separate wpa_driver_nl80211_get_scan_timeout() is created to
avoid code duplication.

Signed-off-by: Jussi Laakkonen <jussi.laakkonen at jolla.com>
---
 src/drivers/driver_nl80211.h       |  3 ++
 src/drivers/driver_nl80211_event.c | 11 +++++-
 src/drivers/driver_nl80211_scan.c  | 59 ++++++++++++++++++++++++------
 3 files changed, 61 insertions(+), 12 deletions(-)

diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index 7fd234c8a..e27547415 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -400,6 +400,9 @@ int wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon,
 /* driver_nl80211_scan.c */
 
 void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx);
+void wpa_driver_nl80211_scheduled_scan_timeout(void *eloop_ctx,
+			    void *timeout_ctx);
+int wpa_driver_nl80211_get_scan_timeout(struct wpa_driver_nl80211_data *drv);
 int wpa_driver_nl80211_scan(struct i802_bss *bss,
 			    struct wpa_driver_scan_params *params);
 int wpa_driver_nl80211_sched_scan(void *priv,
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index f04ac64a1..fdadf1c74 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -3971,6 +3971,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
 {
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	int external_scan_event = 0;
+	int timeout = 0;
 	struct nlattr *frame = tb[NL80211_ATTR_FRAME];
 
 	wpa_printf(MSG_DEBUG, "nl80211: Drv Event %d (%s) received for %s",
@@ -4024,11 +4025,19 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
 	case NL80211_CMD_START_SCHED_SCAN:
 		wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: Sched scan started");
 		drv->scan_state = SCHED_SCAN_STARTED;
+		eloop_cancel_timeout(wpa_driver_nl80211_scheduled_scan_timeout,
+				drv, drv->ctx);
+		timeout = wpa_driver_nl80211_get_scan_timeout(drv);
+		eloop_register_timeout(timeout, 0,
+				wpa_driver_nl80211_scheduled_scan_timeout, drv,
+				drv->ctx);
 		break;
 	case NL80211_CMD_SCHED_SCAN_STOPPED:
 		wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: Sched scan stopped");
 		drv->scan_state = SCHED_SCAN_STOPPED;
-		wpa_supplicant_event(bss->ctx, EVENT_SCHED_SCAN_STOPPED, NULL);
+		eloop_cancel_timeout(wpa_driver_nl80211_scheduled_scan_timeout,
+				drv, drv->ctx);
+		wpa_supplicant_event(drv->ctx, EVENT_SCHED_SCAN_STOPPED, NULL);
 		break;
 	case NL80211_CMD_NEW_SCAN_RESULTS:
 		wpa_dbg(bss->ctx, MSG_DEBUG,
diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c
index 8e98fcdf8..a234ad55a 100644
--- a/src/drivers/driver_nl80211_scan.c
+++ b/src/drivers/driver_nl80211_scan.c
@@ -187,6 +187,35 @@ void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
 	wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
 }
 
+void wpa_driver_nl80211_scheduled_scan_timeout(void *eloop_ctx,
+							void *timeout_ctx)
+{
+	struct wpa_driver_nl80211_data *drv = eloop_ctx;
+
+	wpa_printf(MSG_DEBUG, "nl80211: Sched scan timeout - try to abort it");
+
+#ifdef CONFIG_DRIVER_NL80211_QCA
+	if (drv->vendor_scan_cookie &&
+	    nl80211_abort_vendor_scan(drv, drv->vendor_scan_cookie) == 0)
+		return;
+#endif /* CONFIG_DRIVER_NL80211_QCA */
+	if (!drv->vendor_scan_cookie && nl80211_abort_scan(drv->first_bss) == 0)
+		return;
+
+	wpa_printf(MSG_DEBUG, "nl80211: Failed to abort sched scan");
+
+	if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED)
+		nl80211_restore_ap_mode(drv->first_bss);
+
+	wpa_printf(MSG_DEBUG, "nl80211: Try to get sched scan results");
+	/* TODO use EVENT_SCAN_RESULTS for now, there isn't one for scheduled
+	 * scan results.*/
+	wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
+
+	drv->scan_state = SCHED_SCAN_STOPPED;
+	wpa_printf(MSG_DEBUG, "nl80211: Send stop scheduled scan event");
+	wpa_supplicant_event(timeout_ctx, EVENT_SCHED_SCAN_STOPPED, NULL);
+}
 
 static struct nl_msg *
 nl80211_scan_common(struct i802_bss *bss, u8 cmd,
@@ -347,6 +376,24 @@ fail:
 	return NULL;
 }
 
+int wpa_driver_nl80211_get_scan_timeout(struct wpa_driver_nl80211_data *drv)
+{
+	int timeout = 0;
+
+	timeout = drv->uses_6ghz ? 20 : 10;
+	if (drv->uses_s1g)
+		timeout += 5;
+	if (drv->scan_complete_events) {
+		/*
+		 * The driver seems to deliver events to notify when scan is
+		 * complete, so use longer timeout to avoid race conditions
+		 * with scanning and following association request.
+		 */
+		timeout = 30;
+	}
+
+	return timeout;
+}
 
 /**
  * wpa_driver_nl80211_scan - Request the driver to initiate scan
@@ -470,17 +517,7 @@ int wpa_driver_nl80211_scan(struct i802_bss *bss,
 	drv->scan_state = SCAN_REQUESTED;
 	/* Not all drivers generate "scan completed" wireless event, so try to
 	 * read results after a timeout. */
-	timeout = drv->uses_6ghz ? 20 : 10;
-	if (drv->uses_s1g)
-		timeout += 5;
-	if (drv->scan_complete_events) {
-		/*
-		 * The driver seems to deliver events to notify when scan is
-		 * complete, so use longer timeout to avoid race conditions
-		 * with scanning and following association request.
-		 */
-		timeout = 30;
-	}
+	timeout = wpa_driver_nl80211_get_scan_timeout(drv);
 	wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d "
 		   "seconds", ret, timeout);
 	eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, bss->ctx);
-- 
2.39.2




More information about the Hostap mailing list