diff mbox

[1/1] P2P: Handle Freq conflict in single channel concurrency case

Message ID 20131126131016.GA31478@jithu@broadcom.com
State Accepted
Headers show

Commit Message

Jithu Jance Nov. 26, 2013, 1:10 p.m. UTC
Based on priority, remove the least priority connection whenever
a frequency conflict is detected
Signed-hostap: Jithu Jance <jithu@broadcom.com>
---
 src/common/wpa_ctrl.h           |    2 ++
 wpa_supplicant/p2p_supplicant.c |   59 ++++++++++++++++++++++++++++++++++++++-
 wpa_supplicant/p2p_supplicant.h |    2 ++
 wpa_supplicant/wpa_supplicant.c |   13 +++++++++
 4 files changed, 75 insertions(+), 1 deletion(-)

--
1.7.9.5

Comments

Jouni Malinen Dec. 8, 2013, 5:11 a.m. UTC | #1
On Tue, Nov 26, 2013 at 06:40:16PM +0530, Jithu Jance wrote:
> Based on priority, remove the least priority connection whenever
> a frequency conflict is detected

Thanks, applied.
diff mbox

Patch

diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index b435310..29befab 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -66,6 +66,8 @@  extern "C" {
 /** RSN IBSS 4-way handshakes completed with specified peer */
 #define IBSS_RSN_COMPLETED "IBSS-RSN-COMPLETED "

+/** 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 "
 /** Available WPS AP with active PBC found in scan results */
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index eb2648a..63952fb 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -92,7 +92,8 @@  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,
+	P2P_GROUP_REMOVAL_FREQ_CONFLICT
 };


@@ -112,6 +113,7 @@  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);
+static void wpas_p2p_group_freq_conflict(void *eloop_ctx, void *timeout_ctx);
 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);
@@ -426,6 +428,9 @@  static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s,
 	case P2P_GROUP_REMOVAL_PSK_FAILURE:
 		reason = " reason=PSK_FAILURE";
 		break;
+	case P2P_GROUP_REMOVAL_FREQ_CONFLICT:
+		reason = " reason=FREQ_CONFLICT";
+		break;
 	default:
 		reason = "";
 		break;
@@ -436,6 +441,8 @@  static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s,
 			       wpa_s->ifname, gtype, reason);
 	}

+	if (eloop_cancel_timeout(wpas_p2p_group_freq_conflict, wpa_s, NULL) > 0)
+		wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group freq_conflict timeout");
 	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,
@@ -6535,6 +6542,56 @@  static void wpas_p2p_psk_failure_removal(void *eloop_ctx, void *timeout_ctx)
 	wpas_p2p_group_delete(wpa_s, P2P_GROUP_REMOVAL_PSK_FAILURE);
 }

+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;
+
+	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))) {
+
+			/* Remove the connection with least 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
+					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 p2p connection is in progress, continue connecting...*/
+				if (wpa_s == iface)
+					return 0;
+				else
+					return -1;
+			}
+		}
+	}
+	return 0;
+}

 int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s)
 {
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index 785062d..9630eb5 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -29,6 +29,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, struct wpa_ssid *ssid);
 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, int vht);
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index f43ef14..bd5f852 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1294,6 +1294,7 @@  void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
 	struct ieee80211_ht_capabilities htcaps;
 	struct ieee80211_ht_capabilities htcaps_mask;
 #endif /* CONFIG_HT_OVERRIDES */
+	int freq;

 #ifdef CONFIG_IBSS_RSN
 	ibss_rsn_deinit(wpa_s->ibss_rsn);
@@ -1647,6 +1648,18 @@  void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
 	wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
 #endif /* CONFIG_HT_OVERRIDES */

+	/* If multi-channel concurrency is not supported, check for any
+	 * frequency conflict. In case of any frequency conflict remove the
+	 * least prioritized connection
+	 */
+	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;
+	}
+
 	ret = wpa_drv_associate(wpa_s, &params);
 	if (ret < 0) {
 		wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "