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 */
|
/** RSN IBSS 4-way handshakes completed with specified peer */
|
||||||
#define IBSS_RSN_COMPLETED "IBSS-RSN-COMPLETED "
|
#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 */
|
/** WPS overlap detected in PBC mode */
|
||||||
#define WPS_EVENT_OVERLAP "WPS-OVERLAP-DETECTED "
|
#define WPS_EVENT_OVERLAP "WPS-OVERLAP-DETECTED "
|
||||||
/** Available WPS AP with active PBC found in scan results */
|
/** 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_IDLE_TIMEOUT,
|
||||||
P2P_GROUP_REMOVAL_UNAVAILABLE,
|
P2P_GROUP_REMOVAL_UNAVAILABLE,
|
||||||
P2P_GROUP_REMOVAL_GO_ENDING_SESSION,
|
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_set_group_idle_timeout(struct wpa_supplicant *wpa_s);
|
||||||
static void wpas_p2p_group_formation_timeout(void *eloop_ctx,
|
static void wpas_p2p_group_formation_timeout(void *eloop_ctx,
|
||||||
void *timeout_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,
|
static void wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
|
||||||
int group_added);
|
int group_added);
|
||||||
static int wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s);
|
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:
|
case P2P_GROUP_REMOVAL_PSK_FAILURE:
|
||||||
reason = " reason=PSK_FAILURE";
|
reason = " reason=PSK_FAILURE";
|
||||||
break;
|
break;
|
||||||
|
case P2P_GROUP_REMOVAL_FREQ_CONFLICT:
|
||||||
|
reason = " reason=FREQ_CONFLICT";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
reason = "";
|
reason = "";
|
||||||
break;
|
break;
|
||||||
|
@ -437,6 +442,8 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s,
|
||||||
wpa_s->ifname, gtype, reason);
|
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)
|
if (eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL) > 0)
|
||||||
wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group idle timeout");
|
wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group idle timeout");
|
||||||
if (eloop_cancel_timeout(wpas_p2p_group_formation_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_long_listen_timeout, wpa_s, NULL);
|
||||||
eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL);
|
eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL);
|
||||||
wpas_p2p_remove_pending_group_interface(wpa_s);
|
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
|
/* TODO: remove group interface from the driver if this wpa_s instance
|
||||||
* is on top of a P2P group interface */
|
* 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)
|
int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s)
|
||||||
{
|
{
|
||||||
struct wpa_ssid *ssid = wpa_s->current_ssid;
|
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);
|
unsigned int freq, unsigned int duration);
|
||||||
void wpas_p2p_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
|
void wpas_p2p_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
|
||||||
unsigned int freq);
|
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_remove(struct wpa_supplicant *wpa_s, const char *ifname);
|
||||||
int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
|
int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
|
||||||
int freq, int ht40, int vht);
|
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);
|
wpa_supplicant_apply_ht_overrides(wpa_s, ssid, ¶ms);
|
||||||
#endif /* CONFIG_HT_OVERRIDES */
|
#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);
|
ret = wpa_drv_associate(wpa_s, ¶ms);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
|
wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
|
||||||
|
|
Loading…
Reference in a new issue