[RFC] P2P: Handling single channel concurrency

Jithu Jance jithu
Tue Dec 27 03:15:49 PST 2011


Hi Jouni,

This patch attempts to handle the single channel concurrency scenario where we initially have a P2P connection and then a STA connection is attempted.

As a first step, i tried implementing following things.
1. When STA connection is attempted, try to find whether there is any frequency conflict between any other interface. 
2. If the conflicting interface is a P2P GO, announce channel switch in beacons and move the GO. /* Just a hook is provided. Functionality is not yet implemented */
3. If GO is not able to move the channel or the driver doesn't support the functionality, remove the P2P GO interface.
4. If the conflicting interface is a P2P Client, disconnect & remove the client interface.


Request your opinion on the below patch.


Signed-hostap: Jithu Jance <jithu at broadcom.com>

---
 src/drivers/driver.h            |   11 +++++++++++
 src/drivers/driver_nl80211.c    |    7 +++++--
 wpa_supplicant/driver_i.h       |    7 +++++++
 wpa_supplicant/p2p_supplicant.c |   33 +++++++++++++++++++++++++++++++++
 wpa_supplicant/p2p_supplicant.h |    2 ++
 wpa_supplicant/wpa_supplicant.c |   11 +++++++++++
 6 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 53d1c25..104059e 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -2483,6 +2483,17 @@ struct wpa_driver_ops {
 	 */
 	void (*poll_client)(void *priv, const u8 *own_addr,
 			    const u8 *addr, int qos);
+	/**
+	 * go_switch_channel - Announce channel switch and migrate the GO to a
+	 * given frequency.
+	 * @priv: Private driver interface data
+	 * @freq: frequency in MHz
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This function is used to move the GO to the legacy STA channel to avoid
+	 * frequency conflict in single channel concurrency.
+	 */
+	int (*go_switch_channel)(void *priv, unsigned int freq);
 };
 
 
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 2299cc8..7e758c4 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -8285,14 +8285,17 @@ static int wpa_driver_nl80211_shared_freq(void *priv)
 			 struct wpa_driver_nl80211_data, list) {
 		if (drv == driver ||
 		    os_strcmp(drv->phyname, driver->phyname) != 0 ||
-		    !driver->associated)
+		    (!driver->associated && !is_ap_interface(driver->nlmode)))
 			continue;
 
 		wpa_printf(MSG_DEBUG, "nl80211: Found a match for PHY %s - %s "
 			   MACSTR,
 			   driver->phyname, driver->first_bss.ifname,
 			   MAC2STR(driver->first_bss.addr));
-		freq = nl80211_get_assoc_freq(driver);
+		if(is_ap_interface(driver->nlmode))
+			freq = driver->first_bss.freq;
+		else
+			freq = nl80211_get_assoc_freq(driver);
 		wpa_printf(MSG_DEBUG, "nl80211: Shared freq for PHY %s: %d",
 			   drv->phyname, freq);
 	}
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index d61b3fd..92f291b 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -663,4 +663,11 @@ static inline void wpa_drv_set_rekey_info(struct wpa_supplicant *wpa_s,
 	wpa_s->driver->set_rekey_info(wpa_s->drv_priv, kek, kck, replay_ctr);
 }
 
+static inline int wpa_drv_go_switch_channel(struct wpa_supplicant *wpa_s,
+					  int freq)
+{
+	if (!wpa_s->driver->go_switch_channel)
+		return -1;
+	return wpa_s->driver->go_switch_channel(wpa_s->drv_priv, freq);
+}
 #endif /* DRIVER_I_H */
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 5ff94ef..cd693ab 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -66,7 +66,40 @@ static int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s);
 static void wpas_p2p_cross_connect_setup(struct wpa_supplicant *wpa_s);
 static void wpas_p2p_group_idle_timeout(void *eloop_ctx, void *timeout_ctx);
 static void wpas_p2p_set_group_idle_timeout(struct wpa_supplicant *wpa_s);
+static int wpas_p2p_go_switch_channel(struct wpa_supplicant *wpa_s, int freq)
+{
+	int ret = -1;
+	/* Need to add support for channel switch for softmac drivers */
+
+		return ret;
+}
+
+void wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s, int freq)
+{
+	struct wpa_supplicant *iface = NULL;
 
+	for (iface = wpa_s->global->ifaces; iface; iface = iface->next) {
+		if((iface->p2p_group_interface) && (iface->current_ssid) &&
+			(iface->current_ssid->frequency != freq)) {
+
+			if (iface->p2p_group_interface == P2P_GROUP_INTERFACE_GO) {
+					/* Try to see whether we can move the GO. If it
+					 * is not possible, remove the GO interface
+					 */
+					if((wpas_p2p_go_switch_channel(iface, freq) == 0)
+						|| (wpa_drv_go_switch_channel(iface, freq) == 0)) {
+							wpa_printf(MSG_ERROR, "P2P: GO Moved to freq(%d)", freq);
+							iface->current_ssid->frequency = freq;
+							continue;
+					}
+			}
+
+			/* If GO cannot be moved or if the conflicting interface is a
+			 * P2P Client, remove the interface */
+			wpas_p2p_disconnect(iface);
+		}
+	}
+}
 
 static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s,
 				      struct wpa_scan_results *scan_res)
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index 3150f04..4fa155b 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -31,6 +31,8 @@ void wpas_p2p_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
 				   unsigned int freq, unsigned int duration);
 void wpas_p2p_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
 					  unsigned int freq);
+void wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s,
+                                          int freq);
 int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname);
 int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
 		       int freq);
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 675b592..5b4eac9 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1121,6 +1121,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
 	struct wpa_driver_capa capa;
 	int assoc_failed = 0;
 	struct wpa_ssid *old_ssid;
+	int freq = 0;
 
 #ifdef CONFIG_IBSS_RSN
 	ibss_rsn_deinit(wpa_s->ibss_rsn);
@@ -1415,6 +1416,16 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
 	else
 		params.uapsd = -1;
 
+	/* If multichannel concurrency is not supported, check for any frequency
+	 * conflict and take appropriate action.
+	 */
+	if (((freq = wpa_drv_shared_freq(wpa_s)) > 0) && (freq != params.freq) &&
+		!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT)) {
+		wpa_printf(MSG_ERROR, "Shared interface with conflicting frequency found (%d != %d)"
+																, freq, params.freq);
+		wpas_p2p_handle_frequency_conflicts(wpa_s, params.freq);
+	}
+
 	ret = wpa_drv_associate(wpa_s, &params);
 	if (ret < 0) {
 		wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
-- 
1.7.4.1


- Jithu Jance



More information about the Hostap mailing list