P2P: Allow older scan results to improve p2p_connect-auto robustness
Previusly the peer was assumed to not be operating a GO if the BSS entry for it was not updated in the single scan run started by p2p_connect-auto. This is not very robust since a scan may miss the peer if either a Probe Request or Probe Response frame is lost. Improve robustness by assuming the peer is still operating the GO and starting the join operation. If the GO is not found during PD-for-join or the single-channel scans during the join, fall back to GO Negotiation. Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
701fe506c8
commit
aa9bb7644b
4 changed files with 81 additions and 14 deletions
|
@ -1131,6 +1131,9 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
|
||||||
int timeout_sec = wpa_s->scan_interval;
|
int timeout_sec = wpa_s->scan_interval;
|
||||||
int timeout_usec = 0;
|
int timeout_usec = 0;
|
||||||
#ifdef CONFIG_P2P
|
#ifdef CONFIG_P2P
|
||||||
|
if (wpas_p2p_scan_no_go_seen(wpa_s) == 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (wpa_s->p2p_in_provisioning) {
|
if (wpa_s->p2p_in_provisioning) {
|
||||||
/*
|
/*
|
||||||
* Use shorter wait during P2P Provisioning
|
* Use shorter wait during P2P Provisioning
|
||||||
|
|
|
@ -71,6 +71,8 @@ static int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s);
|
||||||
static void wpas_p2p_cross_connect_setup(struct wpa_supplicant *wpa_s);
|
static void wpas_p2p_cross_connect_setup(struct wpa_supplicant *wpa_s);
|
||||||
static void wpas_p2p_group_idle_timeout(void *eloop_ctx, void *timeout_ctx);
|
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_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
|
||||||
|
int group_added);
|
||||||
|
|
||||||
|
|
||||||
static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s,
|
static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s,
|
||||||
|
@ -216,7 +218,7 @@ static struct wpa_supplicant * wpas_get_p2p_group(struct wpa_supplicant *wpa_s,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void wpas_p2p_group_delete(struct wpa_supplicant *wpa_s)
|
static void wpas_p2p_group_delete(struct wpa_supplicant *wpa_s, int silent)
|
||||||
{
|
{
|
||||||
struct wpa_ssid *ssid;
|
struct wpa_ssid *ssid;
|
||||||
char *gtype;
|
char *gtype;
|
||||||
|
@ -271,13 +273,16 @@ static void wpas_p2p_group_delete(struct wpa_supplicant *wpa_s)
|
||||||
reason = "";
|
reason = "";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
wpa_msg(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_REMOVED "%s %s%s",
|
if (!silent) {
|
||||||
|
wpa_msg(wpa_s->parent, MSG_INFO,
|
||||||
|
P2P_EVENT_GROUP_REMOVED "%s %s%s",
|
||||||
wpa_s->ifname, gtype, reason);
|
wpa_s->ifname, gtype, reason);
|
||||||
|
}
|
||||||
|
|
||||||
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 (ssid)
|
if (!silent && ssid)
|
||||||
wpas_notify_p2p_group_removed(wpa_s, ssid, gtype);
|
wpas_notify_p2p_group_removed(wpa_s, ssid, gtype);
|
||||||
|
|
||||||
if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE) {
|
if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE) {
|
||||||
|
@ -547,7 +552,7 @@ static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s,
|
||||||
if (!success) {
|
if (!success) {
|
||||||
wpa_msg(wpa_s->parent, MSG_INFO,
|
wpa_msg(wpa_s->parent, MSG_INFO,
|
||||||
P2P_EVENT_GROUP_FORMATION_FAILURE);
|
P2P_EVENT_GROUP_FORMATION_FAILURE);
|
||||||
wpas_p2p_group_delete(wpa_s);
|
wpas_p2p_group_delete(wpa_s, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -655,6 +660,13 @@ static void wpas_p2p_send_action_tx_status(struct wpa_supplicant *wpa_s,
|
||||||
(os_memcmp(dst, wpa_s->pending_join_dev_addr, ETH_ALEN) == 0 ||
|
(os_memcmp(dst, wpa_s->pending_join_dev_addr, ETH_ALEN) == 0 ||
|
||||||
os_memcmp(dst, wpa_s->pending_join_iface_addr, ETH_ALEN) == 0)) {
|
os_memcmp(dst, wpa_s->pending_join_iface_addr, ETH_ALEN) == 0)) {
|
||||||
wpa_s->pending_pd_before_join = 0;
|
wpa_s->pending_pd_before_join = 0;
|
||||||
|
if (wpa_s->p2p_fallback_to_go_neg) {
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: No ACK for PD Req "
|
||||||
|
"during p2p_connect-auto");
|
||||||
|
wpas_p2p_fallback_to_go_neg(wpa_s, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "P2P: Starting pending "
|
wpa_printf(MSG_DEBUG, "P2P: Starting pending "
|
||||||
"join-existing-group operation (no ACK for PD "
|
"join-existing-group operation (no ACK for PD "
|
||||||
"Req)");
|
"Req)");
|
||||||
|
@ -1877,6 +1889,13 @@ static void wpas_prov_disc_fail(void *ctx, const u8 *peer,
|
||||||
{
|
{
|
||||||
struct wpa_supplicant *wpa_s = ctx;
|
struct wpa_supplicant *wpa_s = ctx;
|
||||||
|
|
||||||
|
if (wpa_s->p2p_fallback_to_go_neg) {
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: PD for p2p_connect-auto "
|
||||||
|
"failed - fall back to GO Negotiation");
|
||||||
|
wpas_p2p_fallback_to_go_neg(wpa_s, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_FAILURE
|
wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_FAILURE
|
||||||
" p2p_dev_addr=" MACSTR " status=%d",
|
" p2p_dev_addr=" MACSTR " status=%d",
|
||||||
MAC2STR(peer), status);
|
MAC2STR(peer), status);
|
||||||
|
@ -2702,7 +2721,7 @@ static int wpas_p2p_peer_go(struct wpa_supplicant *wpa_s,
|
||||||
|
|
||||||
bss = wpa_bss_get_p2p_dev_addr(wpa_s, peer_dev_addr);
|
bss = wpa_bss_get_p2p_dev_addr(wpa_s, peer_dev_addr);
|
||||||
if (bss == NULL)
|
if (bss == NULL)
|
||||||
return 0;
|
return -1;
|
||||||
if (bss->last_update_idx < wpa_s->bss_update_idx) {
|
if (bss->last_update_idx < wpa_s->bss_update_idx) {
|
||||||
wpa_printf(MSG_DEBUG, "P2P: Peer BSS entry not updated in the "
|
wpa_printf(MSG_DEBUG, "P2P: Peer BSS entry not updated in the "
|
||||||
"last scan");
|
"last scan");
|
||||||
|
@ -2741,6 +2760,8 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
|
||||||
if (wpa_s->p2p_auto_pd) {
|
if (wpa_s->p2p_auto_pd) {
|
||||||
int join = wpas_p2p_peer_go(wpa_s,
|
int join = wpas_p2p_peer_go(wpa_s,
|
||||||
wpa_s->pending_join_dev_addr);
|
wpa_s->pending_join_dev_addr);
|
||||||
|
if (join < 0)
|
||||||
|
join = 0;
|
||||||
wpa_s->p2p_auto_pd = 0;
|
wpa_s->p2p_auto_pd = 0;
|
||||||
wpa_s->pending_pd_use = join ? AUTO_PD_JOIN : AUTO_PD_GO_NEG;
|
wpa_s->pending_pd_use = join ? AUTO_PD_JOIN : AUTO_PD_GO_NEG;
|
||||||
wpa_printf(MSG_DEBUG, "P2P: Auto PD with " MACSTR " join=%d",
|
wpa_printf(MSG_DEBUG, "P2P: Auto PD with " MACSTR " join=%d",
|
||||||
|
@ -2758,7 +2779,9 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wpa_s->p2p_auto_join) {
|
if (wpa_s->p2p_auto_join) {
|
||||||
if (!wpas_p2p_peer_go(wpa_s, wpa_s->pending_join_dev_addr)) {
|
int join = wpas_p2p_peer_go(wpa_s,
|
||||||
|
wpa_s->pending_join_dev_addr);
|
||||||
|
if (join < 0) {
|
||||||
wpa_printf(MSG_DEBUG, "P2P: Peer was not found to be "
|
wpa_printf(MSG_DEBUG, "P2P: Peer was not found to be "
|
||||||
"running a GO -> use GO Negotiation");
|
"running a GO -> use GO Negotiation");
|
||||||
wpas_p2p_connect(wpa_s, wpa_s->pending_join_dev_addr,
|
wpas_p2p_connect(wpa_s, wpa_s->pending_join_dev_addr,
|
||||||
|
@ -2770,8 +2793,11 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "P2P: Peer was found running GO -> try "
|
wpa_printf(MSG_DEBUG, "P2P: Peer was found running GO%s -> "
|
||||||
"to join the group");
|
"try to join the group", join ? "" :
|
||||||
|
" in older scan");
|
||||||
|
if (!join)
|
||||||
|
wpa_s->p2p_fallback_to_go_neg = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
freq = p2p_get_oper_freq(wpa_s->global->p2p,
|
freq = p2p_get_oper_freq(wpa_s->global->p2p,
|
||||||
|
@ -2986,6 +3012,7 @@ static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s)
|
||||||
}
|
}
|
||||||
|
|
||||||
group->p2p_in_provisioning = 1;
|
group->p2p_in_provisioning = 1;
|
||||||
|
group->p2p_fallback_to_go_neg = wpa_s->p2p_fallback_to_go_neg;
|
||||||
|
|
||||||
os_memset(&res, 0, sizeof(res));
|
os_memset(&res, 0, sizeof(res));
|
||||||
os_memcpy(res.peer_interface_addr, wpa_s->pending_join_iface_addr,
|
os_memcpy(res.peer_interface_addr, wpa_s->pending_join_iface_addr,
|
||||||
|
@ -3072,6 +3099,7 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
|
||||||
wpa_s->p2p_persistent_id = persistent_id;
|
wpa_s->p2p_persistent_id = persistent_id;
|
||||||
wpa_s->p2p_go_intent = go_intent;
|
wpa_s->p2p_go_intent = go_intent;
|
||||||
wpa_s->p2p_connect_freq = freq;
|
wpa_s->p2p_connect_freq = freq;
|
||||||
|
wpa_s->p2p_fallback_to_go_neg = 0;
|
||||||
|
|
||||||
if (pin)
|
if (pin)
|
||||||
os_strlcpy(wpa_s->p2p_pin, pin, sizeof(wpa_s->p2p_pin));
|
os_strlcpy(wpa_s->p2p_pin, pin, sizeof(wpa_s->p2p_pin));
|
||||||
|
@ -3564,6 +3592,8 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
|
||||||
/* Make sure we are not running find during connection establishment */
|
/* Make sure we are not running find during connection establishment */
|
||||||
wpas_p2p_stop_find(wpa_s);
|
wpas_p2p_stop_find(wpa_s);
|
||||||
|
|
||||||
|
wpa_s->p2p_fallback_to_go_neg = 0;
|
||||||
|
|
||||||
if (ssid->mode == WPAS_MODE_INFRA)
|
if (ssid->mode == WPAS_MODE_INFRA)
|
||||||
return wpas_start_p2p_client(wpa_s, ssid, addr_allocated);
|
return wpas_start_p2p_client(wpa_s, ssid, addr_allocated);
|
||||||
|
|
||||||
|
@ -3740,6 +3770,7 @@ int wpas_p2p_prov_disc(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
|
||||||
{
|
{
|
||||||
u16 config_methods;
|
u16 config_methods;
|
||||||
|
|
||||||
|
wpa_s->p2p_fallback_to_go_neg = 0;
|
||||||
wpa_s->pending_pd_use = NORMAL_PD;
|
wpa_s->pending_pd_use = NORMAL_PD;
|
||||||
if (os_strncmp(config_method, "display", 7) == 0)
|
if (os_strncmp(config_method, "display", 7) == 0)
|
||||||
config_methods = WPS_CONFIG_DISPLAY;
|
config_methods = WPS_CONFIG_DISPLAY;
|
||||||
|
@ -4205,7 +4236,7 @@ static void wpas_p2p_group_idle_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||||
wpa_printf(MSG_DEBUG, "P2P: Group idle timeout reached - terminate "
|
wpa_printf(MSG_DEBUG, "P2P: Group idle timeout reached - terminate "
|
||||||
"group");
|
"group");
|
||||||
wpa_s->removal_reason = P2P_GROUP_REMOVAL_IDLE_TIMEOUT;
|
wpa_s->removal_reason = P2P_GROUP_REMOVAL_IDLE_TIMEOUT;
|
||||||
wpas_p2p_group_delete(wpa_s);
|
wpas_p2p_group_delete(wpa_s, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4285,7 +4316,7 @@ void wpas_p2p_deauth_notif(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||||
wpa_printf(MSG_DEBUG, "P2P: GO indicated that the P2P Group "
|
wpa_printf(MSG_DEBUG, "P2P: GO indicated that the P2P Group "
|
||||||
"session is ending");
|
"session is ending");
|
||||||
wpa_s->removal_reason = P2P_GROUP_REMOVAL_GO_ENDING_SESSION;
|
wpa_s->removal_reason = P2P_GROUP_REMOVAL_GO_ENDING_SESSION;
|
||||||
wpas_p2p_group_delete(wpa_s);
|
wpas_p2p_group_delete(wpa_s, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4653,7 +4684,7 @@ int wpas_p2p_cancel(struct wpa_supplicant *wpa_s)
|
||||||
found = 1;
|
found = 1;
|
||||||
eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
|
eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
|
||||||
wpa_s->parent, NULL);
|
wpa_s->parent, NULL);
|
||||||
wpas_p2p_group_delete(wpa_s);
|
wpas_p2p_group_delete(wpa_s, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4675,7 +4706,7 @@ void wpas_p2p_interface_unavailable(struct wpa_supplicant *wpa_s)
|
||||||
wpa_printf(MSG_DEBUG, "P2P: Remove group due to driver resource not "
|
wpa_printf(MSG_DEBUG, "P2P: Remove group due to driver resource not "
|
||||||
"being available anymore");
|
"being available anymore");
|
||||||
wpa_s->removal_reason = P2P_GROUP_REMOVAL_UNAVAILABLE;
|
wpa_s->removal_reason = P2P_GROUP_REMOVAL_UNAVAILABLE;
|
||||||
wpas_p2p_group_delete(wpa_s);
|
wpas_p2p_group_delete(wpa_s, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4722,7 +4753,7 @@ int wpas_p2p_disconnect(struct wpa_supplicant *wpa_s)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
wpa_s->removal_reason = P2P_GROUP_REMOVAL_REQUESTED;
|
wpa_s->removal_reason = P2P_GROUP_REMOVAL_REQUESTED;
|
||||||
wpas_p2p_group_delete(wpa_s);
|
wpas_p2p_group_delete(wpa_s, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -4796,3 +4827,34 @@ void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s,
|
||||||
return;
|
return;
|
||||||
wpas_p2p_add_persistent_group_client(wpa_s, addr);
|
wpas_p2p_add_persistent_group_client(wpa_s, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
|
||||||
|
int group_added)
|
||||||
|
{
|
||||||
|
struct wpa_supplicant *group = wpa_s;
|
||||||
|
if (wpa_s->global->p2p_group_formation)
|
||||||
|
group = wpa_s->global->p2p_group_formation;
|
||||||
|
wpa_s = wpa_s->parent;
|
||||||
|
if (group_added)
|
||||||
|
wpas_p2p_group_delete(group, 1);
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Fall back to GO Negotiation");
|
||||||
|
wpas_p2p_connect(wpa_s, wpa_s->pending_join_dev_addr, wpa_s->p2p_pin,
|
||||||
|
wpa_s->p2p_wps_method, wpa_s->p2p_persistent_group, 0,
|
||||||
|
0, 0, wpa_s->p2p_go_intent, wpa_s->p2p_connect_freq,
|
||||||
|
wpa_s->p2p_persistent_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wpas_p2p_scan_no_go_seen(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
if (!wpa_s->p2p_fallback_to_go_neg ||
|
||||||
|
wpa_s->p2p_in_provisioning <= 5)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: GO not found for p2p_connect-auto - "
|
||||||
|
"fallback to GO Negotiation");
|
||||||
|
wpas_p2p_fallback_to_go_neg(wpa_s, 1);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
|
@ -140,5 +140,6 @@ struct wpa_ssid * wpas_p2p_get_persistent(struct wpa_supplicant *wpa_s,
|
||||||
size_t ssid_len);
|
size_t ssid_len);
|
||||||
void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s,
|
void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s,
|
||||||
const u8 *addr);
|
const u8 *addr);
|
||||||
|
int wpas_p2p_scan_no_go_seen(struct wpa_supplicant *wpa_s);
|
||||||
|
|
||||||
#endif /* P2P_SUPPLICANT_H */
|
#endif /* P2P_SUPPLICANT_H */
|
||||||
|
|
|
@ -517,6 +517,7 @@ struct wpa_supplicant {
|
||||||
unsigned int p2p_auto_join:1;
|
unsigned int p2p_auto_join:1;
|
||||||
unsigned int p2p_auto_pd:1;
|
unsigned int p2p_auto_pd:1;
|
||||||
unsigned int p2p_persistent_group:1;
|
unsigned int p2p_persistent_group:1;
|
||||||
|
unsigned int p2p_fallback_to_go_neg:1;
|
||||||
int p2p_persistent_id;
|
int p2p_persistent_id;
|
||||||
int p2p_go_intent;
|
int p2p_go_intent;
|
||||||
int p2p_connect_freq;
|
int p2p_connect_freq;
|
||||||
|
|
Loading…
Reference in a new issue