From: Jouni Malinen Date: Fri, 1 Nov 2013 09:21:28 +0000 (+0200) Subject: AOSP: P2P frequency conflict X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=46e8091ca0806344909ac9c0db4c2b04f12c74a0;p=thirdparty%2Fhostap.git AOSP: P2P frequency conflict --- diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index 81c4c2709..fd7f686cb 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -62,6 +62,10 @@ 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 " +#ifdef ANDROID_P2P +/** Notify the Userspace about the freq conflict */ +#define WPA_EVENT_FREQ_CONFLICT "CTRL-EVENT-FREQ-CONFLICT " +#endif /** RSN IBSS 4-way handshakes completed with specified peer */ #define IBSS_RSN_COMPLETED "IBSS-RSN-COMPLETED " diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 9338ad5b0..9479cfc23 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -83,7 +83,10 @@ enum p2p_group_removal_reason { P2P_GROUP_REMOVAL_IDLE_TIMEOUT, P2P_GROUP_REMOVAL_UNAVAILABLE, P2P_GROUP_REMOVAL_GO_ENDING_SESSION, - P2P_GROUP_REMOVAL_PSK_FAILURE + P2P_GROUP_REMOVAL_PSK_FAILURE, +#ifdef ANDROID_P2P + P2P_GROUP_REMOVAL_FREQ_CONFLICT +#endif }; @@ -103,6 +106,9 @@ 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 void wpas_p2p_group_formation_timeout(void *eloop_ctx, void *timeout_ctx); +#ifdef ANDROID_P2P +static void wpas_p2p_group_freq_conflict(void *eloop_ctx, void *timeout_ctx); +#endif static void wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s, int group_added); static int wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s); @@ -395,6 +401,11 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s, case P2P_GROUP_REMOVAL_PSK_FAILURE: reason = " reason=PSK_FAILURE"; break; +#ifdef ANDROID_P2P + case P2P_GROUP_REMOVAL_FREQ_CONFLICT: + reason = " reason=FREQ_CONFLICT"; + break; +#endif default: reason = ""; break; @@ -405,6 +416,9 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s, wpa_s->ifname, gtype, reason); } +#ifdef ANDROID_P2P + eloop_cancel_timeout(wpas_p2p_group_freq_conflict, wpa_s, NULL); +#endif if (eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL) > 0) wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group idle timeout"); if (eloop_cancel_timeout(wpas_p2p_group_formation_timeout, @@ -3361,6 +3375,9 @@ void wpas_p2p_deinit(struct wpa_supplicant *wpa_s) os_free(wpa_s->go_params); wpa_s->go_params = NULL; +#ifdef ANDROID_P2P + eloop_cancel_timeout(wpas_p2p_group_freq_conflict, wpa_s, NULL); +#endif eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s, NULL); eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL); wpa_s->p2p_long_listen = 0; @@ -3768,7 +3785,17 @@ static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq) struct wpabuf *wps_ie, *ies; size_t ielen; int freqs[2] = { 0, 0 }; +#ifdef ANDROID_P2P + int oper_freq; + /* If freq is not provided, check the operating freq of the GO and do a + * a directed scan to save time + */ + if(!freq) { + freq = (oper_freq = p2p_get_oper_freq(wpa_s->global->p2p, + wpa_s->pending_join_iface_addr) == -1) ? 0 : oper_freq; + } +#endif os_memset(¶ms, 0, sizeof(params)); /* P2P Wildcard SSID */ @@ -6320,3 +6347,73 @@ int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s) wpa_s->p2p_last_4way_hs_fail = ssid; return 0; } + +#ifdef ANDROID_P2P +static void wpas_p2p_group_freq_conflict(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + + wpa_printf(MSG_DEBUG, "P2P: Frequency conflict - terminate group"); + wpas_p2p_group_delete(wpa_s, P2P_GROUP_REMOVAL_FREQ_CONFLICT); +} + +int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s, int freq, + struct wpa_ssid *ssid) +{ + struct wpa_supplicant *iface = NULL; + struct p2p_data *p2p = wpa_s->global->p2p; + + for (iface = wpa_s->global->ifaces; iface; iface = iface->next) { + if ((iface->current_ssid) && + (iface->current_ssid->frequency != freq) && + ((iface->p2p_group_interface) || + (iface->current_ssid->p2p_group))) { + + if ((iface->p2p_group_interface == P2P_GROUP_INTERFACE_GO) || + (iface->current_ssid->mode == WPAS_MODE_P2P_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_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 depending up on the connection + * priority */ + if(!wpas_is_p2p_prioritized(iface)) { + /* STA connection has priority over existing + * P2P connection. So remove the interface */ + wpa_printf(MSG_DEBUG, "P2P: Removing P2P connection due to Single channel" + "concurrent mode frequency conflict"); + eloop_register_timeout(0, 0, wpas_p2p_group_freq_conflict, + iface, NULL); + /* If connection in progress is p2p connection, do not proceed for the connection */ + if (wpa_s == iface) + return -1; + else + /* If connection in progress is STA connection, proceed for the connection */ + return 0; + } else { + /* P2p connection has priority, disable the STA network*/ + wpa_supplicant_disable_network(wpa_s->global->ifaces, ssid); + wpa_msg(wpa_s->global->ifaces, MSG_INFO, WPA_EVENT_FREQ_CONFLICT + " id=%d", ssid->id); + os_memset(wpa_s->global->ifaces->pending_bssid, 0, ETH_ALEN); + if (wpa_s == iface) { + /* p2p connection is in progress, continue connecting...*/ + return 0; + } + else { + /* STA connection is in progress, do not allow to continue */ + return -1; + } + } + } + } + return 0; +} +#endif diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h index 26f5def4e..65ccbf987 100644 --- a/wpa_supplicant/p2p_supplicant.h +++ b/wpa_supplicant/p2p_supplicant.h @@ -29,6 +29,10 @@ 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); +#ifdef ANDROID_P2P +int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s, + int freq, struct wpa_ssid *ssid); +#endif 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, int ht40); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 334ccc93c..8a1574efa 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1284,6 +1284,9 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, ibss_rsn_deinit(wpa_s->ibss_rsn); wpa_s->ibss_rsn = NULL; #endif /* CONFIG_IBSS_RSN */ +#ifdef ANDROID_P2P + int freq = 0; +#endif if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO || ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) { @@ -1620,6 +1623,18 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, wpa_supplicant_apply_ht_overrides(wpa_s, ssid, ¶ms); #endif /* CONFIG_HT_OVERRIDES */ +#ifdef ANDROID_P2P + /* If multichannel concurrency is not supported, check for any frequency + * conflict and take appropriate action. + */ + if ((wpa_s->num_multichan_concurrent < 2) && + ((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); + if (wpas_p2p_handle_frequency_conflicts(wpa_s, params.freq, ssid) < 0) + return; + } +#endif ret = wpa_drv_associate(wpa_s, ¶ms); if (ret < 0) { wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "