[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, ¶ms);
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