Patchwork [3/3] wpa_supplicant: Add support to handle OBSS scan request

login
register
mail settings
Submitter Rajkumar Manoharan
Date April 24, 2012, 1:08 p.m.
Message ID <1335272917-7503-3-git-send-email-rmanohar@qca.qualcomm.com>
Download mbox | patch
Permalink /patch/154675/
State Accepted
Headers show

Comments

Rajkumar Manoharan - April 24, 2012, 1:08 p.m.
Parse the OBSS scan parameter from beacon IE and schedule periodic
scan to generate 2040 coexistence channel report. This patch decodes
Scan Interval alone from the OBSS Scan parameter IE and triggers
scan on timeout.

Signed-off-by: Rajkumar Manoharan <rmanohar@qca.qualcomm.com>
---
 wpa_supplicant/bss.h            |    3 +++
 wpa_supplicant/events.c         |    9 ++++-----
 wpa_supplicant/sme.c            |   40 +++++++++++++++++++++++++++++++++++++++
 wpa_supplicant/sme.h            |    4 ++++
 wpa_supplicant/wpa_supplicant.c |    2 ++
 5 files changed, 53 insertions(+), 5 deletions(-)

Patch

diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h
index 37ca72c..d1c8e8f 100644
--- a/wpa_supplicant/bss.h
+++ b/wpa_supplicant/bss.h
@@ -36,6 +36,7 @@  struct wpa_scan_res;
  * @level: signal level
  * @tsf: Timestamp of last Beacon/Probe Response frame
  * @last_update: Time of the last update (i.e., Beacon or Probe Response RX)
+ * @obss_scan_int: OBSS scan interval in seconds (host byte order)
  * @ie_len: length of the following IE field in octets (from Probe Response)
  * @beacon_ie_len: length of the following Beacon IE field in octets
  *
@@ -69,6 +70,8 @@  struct wpa_bss {
 	struct wpabuf *anqp_3gpp;
 	struct wpabuf *anqp_domain_name;
 #endif /* CONFIG_INTERWORKING */
+	u8 sched_obss_scan;
+	u16 obss_scan_int;
 	size_t ie_len;
 	size_t beacon_ie_len;
 	/* followed by ie_len octets of IEs */
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index a0bd903..4960bba 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -1096,11 +1096,10 @@  static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
 
 	selected = wpa_supplicant_pick_network(wpa_s, scan_res, &ssid);
 
-	/*
-	 * TODO: This should be done at the completion of OBSS scan operations
-	 * which may or may not be identical to other scans..
-	 */
-	sme_proc_40mhz_intolerant(wpa_s);
+	if (wpa_s->current_bss && wpa_s->current_bss->sched_obss_scan) {
+		wpa_s->current_bss->sched_obss_scan = 0;
+		sme_proc_40mhz_intolerant(wpa_s);
+	}
 
 	if (selected) {
 		int skip;
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 07f5d3e..5e06390 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -760,6 +760,46 @@  void sme_proc_40mhz_intolerant(struct wpa_supplicant *wpa_s)
 				       num_channels, num_intol);
 }
 
+static void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+	struct wpa_supplicant *wpa_s = eloop_ctx;
+	struct wpa_driver_scan_params params;
+
+	if (!wpa_s->current_bss) {
+		wpa_printf(MSG_DEBUG, "SME OBSS: Ignore Scan Request\n");
+		return;
+	}
+
+	os_memset(&params, 0, sizeof(params));
+	wpa_printf(MSG_DEBUG, "SME OBSS: Request a OBSS scan");
+
+	if (wpa_supplicant_trigger_scan(wpa_s, &params))
+		wpa_printf(MSG_DEBUG, "SME OBSS: Failed to trigger scan");
+	else
+		wpa_s->current_bss->sched_obss_scan = 1;
+
+	eloop_register_timeout(wpa_s->current_bss->obss_scan_int, 0,
+			       sme_obss_scan_timeout, wpa_s, NULL);
+}
+
+void sme_sched_obss_scan(struct wpa_supplicant *wpa_s)
+{
+	const u8 *ie;
+
+	if (wpa_s->wpa_state != WPA_COMPLETED)
+		return;
+
+	ie = wpa_bss_get_ie(wpa_s->current_bss,
+			    WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS);
+	if (!ie || (ie[1] != 14))
+		return;
+
+	wpa_s->current_bss->obss_scan_int = WPA_GET_LE16(ie + 6);
+	wpa_printf(MSG_DEBUG, "SME: OBSS Scan Interval %d\n",
+		   wpa_s->current_bss->obss_scan_int);
+	eloop_register_timeout(wpa_s->current_bss->obss_scan_int, 0,
+			       sme_obss_scan_timeout, wpa_s, NULL);
+}
 #ifdef CONFIG_IEEE80211W
 
 static const unsigned int sa_query_max_timeout = 1000;
diff --git a/wpa_supplicant/sme.h b/wpa_supplicant/sme.h
index f735832..ef6c091 100644
--- a/wpa_supplicant/sme.h
+++ b/wpa_supplicant/sme.h
@@ -37,6 +37,7 @@  void sme_deinit(struct wpa_supplicant *wpa_s);
 
 void sme_proc_40mhz_intolerant(struct wpa_supplicant *wpa_s);
 
+void sme_sched_obss_scan(struct wpa_supplicant *wpa_s);
 #else /* CONFIG_SME */
 
 static inline void sme_authenticate(struct wpa_supplicant *wpa_s,
@@ -101,6 +102,9 @@  static inline void sme_proc_40mhz_intolerant(struct wpa_supplicant *wpa_s)
 {
 }
 
+static inline void sme_sched_obss_scan(struct wpa_supplicant *wpa_s)
+{
+}
 #endif /* CONFIG_SME */
 
 #endif /* SME_H */
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index c5a7115..a9d9b85 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -624,6 +624,8 @@  void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
 		wpa_supplicant_stop_bgscan(wpa_s);
 #endif /* CONFIG_BGSCAN */
 
+	sme_sched_obss_scan(wpa_s);
+
 	if (wpa_s->wpa_state != old_state) {
 		wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);