From patchwork Sun Apr 8 18:38:11 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [RFC,4/4] P2P: Handling single channel concurrency Date: Sun, 08 Apr 2012 08:38:11 -0000 From: Jouni Malinen X-Patchwork-Id: 151370 Message-Id: <20120408183811.GD12438@w1.fi> To: hostap@lists.shmoo.com On Tue, Mar 06, 2012 at 10:34:38AM +0530, Jithu Jance wrote: > This patch handles cases where a STA connection is attempted after a P2P > connection and the new sta connection detects a freq > conflict with the existing P2P connection. Now based on the priority of the > connection (either sta or p2p), either one of the connection > will be terminated. I applied the driver_nl80211.c part and below is a cleaned up version of the rest. Though, I did not go through all the details yet. [PATCH 3/3] P2P: Handle single channel concurrency This patch handles cases where a STA connection is attempted after a P2P connection and the new sta connection detects a freq conflict with the existing P2P connection. Now based on the priority of the connection (either sta or p2p), either one of the connection will be terminated. Signed-hostap: Jithu Jance --- src/common/wpa_ctrl.h | 2 + wpa_supplicant/p2p_supplicant.c | 50 +++++++++++++++++++++++++++++++++++++ wpa_supplicant/p2p_supplicant.h | 2 + wpa_supplicant/wpa_supplicant.c | 27 ++++++++++++++++++++ wpa_supplicant/wpa_supplicant_i.h | 3 +- 5 files changed, 83 insertions(+), 1 deletions(-) diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index 35012e8..2e35e9c 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -56,6 +56,8 @@ extern "C" { #define WPA_EVENT_BSS_ADDED "CTRL-EVENT-BSS-ADDED " /** A BSS entry was removed (followed by BSS entry id and BSSID) */ #define WPA_EVENT_BSS_REMOVED "CTRL-EVENT-BSS-REMOVED " +/** Notify the Userspace about the freq conflict */ +#define WPA_EVENT_FREQ_CONFLICT "CTRL-EVENT-FREQ-CONFLICT " /** WPS overlap detected in PBC mode */ #define WPS_EVENT_OVERLAP "WPS-OVERLAP-DETECTED " diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 9d31fdb..3abcee7 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -4609,3 +4609,53 @@ void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s, return; wpas_p2p_add_persistent_group_client(wpa_s, addr); } + + +int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s, int freq) +{ + struct wpa_supplicant *iface; + + for (iface = wpa_s->global->ifaces; iface; iface = iface->next) { + if (!iface->p2p_group_interface || !iface->current_ssid || + iface->current_ssid->frequency == freq) + continue; + + 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 (wpa_drv_switch_channel(iface, freq) == 0) { + wpa_printf(MSG_INFO, "P2P: GO Moved to freq " + "%d MHz", freq); + iface->current_ssid->frequency = freq; + continue; + } + } + + /* + * If GO cannot be moved or if the conflicting interface is a + * P2P Client, remove the interface depending up on the + * connection priority. + */ + if (!wpas_is_p2p_prioritized(iface)) { + /* + * STA connection has priority over existing P2P + * connection, so remove the interface. + */ + wpas_p2p_disconnect(iface); + iface->removal_reason = + P2P_GROUP_REMOVAL_FREQ_CONFLICT; + wpas_p2p_group_delete(iface); + } else { + /* + * Existing connection has the priority. Disable the + * newly selected network and let the application know + * about it. + */ + return -1; + } + } + + return 0; +} diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h index 8f8e635..fb0522b 100644 --- a/wpa_supplicant/p2p_supplicant.h +++ b/wpa_supplicant/p2p_supplicant.h @@ -25,6 +25,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); +int 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 1c88949..7b4e178 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1091,6 +1091,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; #ifdef CONFIG_HT_OVERRIDES struct ieee80211_ht_capabilities htcaps; struct ieee80211_ht_capabilities htcaps_mask; @@ -1404,6 +1405,32 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, wpa_supplicant_apply_ht_overrides(wpa_s, ssid, ¶ms); #endif /* CONFIG_HT_OVERRIDES */ + /* + * If multichannel concurrency is not supported, check for any + * frequency conflict and take appropriate action. + */ + if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT) && + ((freq = wpa_drv_shared_freq(wpa_s)) > 0) && freq != params.freq) { + wpa_printf(MSG_DEBUG, "Shared interface with conflicting " + "frequency found (%d != %d)", freq, params.freq); +#ifdef CONFIG_P2P + if (wpas_p2p_handle_frequency_conflicts(wpa_s, params.freq) < + 0) { + /* + * Handling conflicts failed. Disable the current + * connect req and notify the userspace to take + * appropriate action. + */ + wpa_printf(MSG_DEBUG, "prioritize is not set. " + "Notifying user space to handle the case."); + wpa_supplicant_disable_network(wpa_s, ssid); + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_FREQ_CONFLICT + " id=%d", ssid->id); + os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); + } +#endif /* CONFIG_P2P */ + } + ret = wpa_drv_associate(wpa_s, ¶ms); if (ret < 0) { wpa_msg(wpa_s, MSG_INFO, "Association request to the driver " diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 3f1f589..3c86857 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -509,7 +509,8 @@ struct wpa_supplicant { P2P_GROUP_REMOVAL_REQUESTED, P2P_GROUP_REMOVAL_IDLE_TIMEOUT, P2P_GROUP_REMOVAL_UNAVAILABLE, - P2P_GROUP_REMOVAL_GO_ENDING_SESSION + P2P_GROUP_REMOVAL_GO_ENDING_SESSION, + P2P_GROUP_REMOVAL_FREQ_CONFLICT } removal_reason; unsigned int p2p_cb_on_scan_complete:1;