[17/25] OCV: Perform a SA Query after a channel switch

Message ID 20180806194643.1328-18-Mathy.Vanhoef@cs.kuleuven.be
State New
Headers show
Series
  • Add support for Operating Channel Validation (OCV)
Related show

Commit Message

Mathy Vanhoef Aug. 6, 2018, 7:46 p.m.
After the network changed to a new channel, perform a SA Query with the
AP after a random delay. This is used to confirm that we are still
operating on the real operating channel of the network.

Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@cs.kuleuven.be>
---
 src/ap/drv_callbacks.c  |  2 ++
 wpa_supplicant/events.c |  1 +
 wpa_supplicant/sme.c    | 22 ++++++++++++++++++++++
 wpa_supplicant/sme.h    |  1 +
 4 files changed, 26 insertions(+)

Patch

diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 1b15d3a69..a175c807b 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -735,6 +735,8 @@  void hostapd_event_sta_opmode_changed(struct hostapd_data *hapd, const u8 *addr,
 void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
 			     int offset, int width, int cf1, int cf2)
 {
+	/* TODO: If OCV is enabled deauth STAs that don't perform a SA Query */
+
 #ifdef NEED_AP_MLME
 	int channel, chwidth, is_dfs;
 	u8 seg0_idx = 0, seg1_idx = 0;
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index fb77f1dbd..428cb7368 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -4295,6 +4295,7 @@  void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
 		}
 #endif /* CONFIG_AP */
 
+		sme_event_ch_switch(wpa_s);
 		wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_CS);
 		break;
 #ifdef CONFIG_AP
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index a9202e28a..e699eb5b2 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -2051,6 +2051,7 @@  void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable)
 
 static const unsigned int sa_query_max_timeout = 1000;
 static const unsigned int sa_query_retry_timeout = 201;
+static const unsigned int sa_query_ch_switch_max_delay = 5000; /* in usec */
 
 static int sme_check_sa_query_timeout(struct wpa_supplicant *wpa_s)
 {
@@ -2197,6 +2198,27 @@  void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa,
 }
 
 
+void sme_event_ch_switch(struct wpa_supplicant *wpa_s)
+{
+	unsigned int usec;
+	u32 _rand;
+
+	if (wpa_s->wpa_state != WPA_COMPLETED)
+		return;
+	if (!wpa_sm_ocv_enabled(wpa_s->wpa))
+		return;
+
+	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Channel switch completed - "
+		"trigger new SA Query to verify new operating channel");
+	sme_stop_sa_query(wpa_s);
+
+	if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
+		_rand = os_random();
+	usec = _rand % (sa_query_ch_switch_max_delay + 1);
+	eloop_register_timeout(0, usec, sme_sa_query_timer, wpa_s, NULL);
+}
+
+
 static void sme_process_sa_query_request(struct wpa_supplicant *wpa_s,
 				const u8 *sa, const u8 *data, size_t len)
 {
diff --git a/wpa_supplicant/sme.h b/wpa_supplicant/sme.h
index f3c822025..ea20da78f 100644
--- a/wpa_supplicant/sme.h
+++ b/wpa_supplicant/sme.h
@@ -28,6 +28,7 @@  void sme_event_disassoc(struct wpa_supplicant *wpa_s,
 			struct disassoc_info *info);
 void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa,
 				 const u8 *da, u16 reason_code);
+void sme_event_ch_switch(struct wpa_supplicant *wpa_s);
 void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa,
 		     const u8 *data, size_t len);
 void sme_state_changed(struct wpa_supplicant *wpa_s);