P2P: Handle frequency conflict in single channel concurrency case
Based on priority, remove the connection with least priority whenever a frequency conflict is detected. Signed-hostap: Jithu Jance <jithu@broadcom.com>
This commit is contained in:
parent
b125c48fce
commit
8567866d75
4 changed files with 93 additions and 1 deletions
|
@ -66,6 +66,12 @@ extern "C" {
|
|||
/** RSN IBSS 4-way handshakes completed with specified peer */
|
||||
#define IBSS_RSN_COMPLETED "IBSS-RSN-COMPLETED "
|
||||
|
||||
/** Notification of frequency conflict due to a concurrent operation.
|
||||
*
|
||||
* The indicated network is disabled and needs to be re-enabled before it can
|
||||
* be used again.
|
||||
*/
|
||||
#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 */
|
||||
|
|
|
@ -93,7 +93,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
|
||||
};
|
||||
|
||||
|
||||
|
@ -113,6 +114,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);
|
||||
|
@ -427,6 +429,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;
|
||||
|
@ -437,6 +442,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,
|
||||
|
@ -3574,6 +3581,7 @@ void wpas_p2p_deinit(struct wpa_supplicant *wpa_s)
|
|||
eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL);
|
||||
eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL);
|
||||
wpas_p2p_remove_pending_group_interface(wpa_s);
|
||||
eloop_cancel_timeout(wpas_p2p_group_freq_conflict, wpa_s, NULL);
|
||||
|
||||
/* TODO: remove group interface from the driver if this wpa_s instance
|
||||
* is on top of a P2P group interface */
|
||||
|
@ -6547,6 +6555,63 @@ static void wpas_p2p_psk_failure_removal(void *eloop_ctx, void *timeout_ctx)
|
|||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
for (iface = wpa_s->global->ifaces; iface; iface = iface->next) {
|
||||
if (!iface->current_ssid ||
|
||||
iface->current_ssid->frequency == freq ||
|
||||
(iface->p2p_group_interface == NOT_P2P_GROUP_INTERFACE &&
|
||||
!iface->current_ssid->p2p_group))
|
||||
continue;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
struct wpa_ssid *ssid = wpa_s->current_ssid;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1647,6 +1647,25 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
|
|||
wpa_supplicant_apply_ht_overrides(wpa_s, ssid, ¶ms);
|
||||
#endif /* CONFIG_HT_OVERRIDES */
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
/*
|
||||
* 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) {
|
||||
int freq = wpa_drv_shared_freq(wpa_s);
|
||||
if (freq > 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 /* CONFIG_P2P */
|
||||
|
||||
ret = wpa_drv_associate(wpa_s, ¶ms);
|
||||
if (ret < 0) {
|
||||
wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
|
||||
|
|
Loading…
Reference in a new issue