From 175171ac6c3f2bb501897237d559de0fedfd992e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 23 Nov 2012 00:53:42 +0200 Subject: [PATCH] P2P: Retry PD Request in join-a-running-group case The GO may be in sleep when we send a PD Request frame to indicate that we are about to join a running group. Previously, this frame was not retried more than normal low level retries. This can result in the GO not getting the frame especially in cases where concurrent multi-channel operations or aggressive sleep schedule is used since most drivers do not yet synchronize with the GO's NoA before association. Increase the likelihood of the GO receiving the PD Request frame by retransmitting it similarly to the PD-for-GO-Negotiation case. Start the actual join operation only after these retries have failed to get an acknowledgment from the GO to give the connection attempt a chance to succeed if the driver implements better NoA synchronization for it. Signed-hostap: Jouni Malinen --- src/p2p/p2p.c | 22 +++++++++++++++++----- src/p2p/p2p.h | 1 + wpa_supplicant/p2p_supplicant.c | 27 +++++++++++++++------------ 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index af2d24afd..22760d91e 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -2650,8 +2650,7 @@ static void p2p_retry_pd(struct p2p_data *p2p) /* * Retry the prov disc req attempt only for the peer that the user had - * requested for and provided a join has not been initiated on it - * in the meantime. + * requested. */ dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) { @@ -2660,15 +2659,14 @@ static void p2p_retry_pd(struct p2p_data *p2p) continue; if (!dev->req_config_methods) continue; - if (dev->flags & P2P_DEV_PD_FOR_JOIN) - continue; wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send " "pending Provision Discovery Request to " MACSTR " (config methods 0x%x)", MAC2STR(dev->info.p2p_device_addr), dev->req_config_methods); - p2p_send_prov_disc_req(p2p, dev, 0, 0); + p2p_send_prov_disc_req(p2p, dev, + dev->flags & P2P_DEV_PD_FOR_JOIN, 0); return; } } @@ -3183,9 +3181,23 @@ static void p2p_timeout_prov_disc_req(struct p2p_data *p2p) p2p->pd_retries--; p2p_retry_pd(p2p); } else { + struct p2p_device *dev; + int for_join = 0; + + dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) { + if (os_memcmp(p2p->pending_pd_devaddr, + dev->info.p2p_device_addr, ETH_ALEN) != 0) + continue; + if (dev->req_config_methods && + (dev->flags & P2P_DEV_PD_FOR_JOIN)) + for_join = 1; + } + if (p2p->cfg->prov_disc_fail) p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx, p2p->pending_pd_devaddr, + for_join ? + P2P_PROV_DISC_TIMEOUT_JOIN : P2P_PROV_DISC_TIMEOUT); p2p_reset_pending_pd(p2p); } diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index 5eeb65385..8b2aab2d1 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -232,6 +232,7 @@ enum p2p_prov_disc_status { P2P_PROV_DISC_SUCCESS, P2P_PROV_DISC_TIMEOUT, P2P_PROV_DISC_REJECTED, + P2P_PROV_DISC_TIMEOUT_JOIN, }; struct p2p_channel { diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index d3e63b73f..9b6a88e7f 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -723,19 +723,13 @@ static void wpas_p2p_send_action_tx_status(struct wpa_supplicant *wpa_s, if (result != OFFCHANNEL_SEND_ACTION_SUCCESS && wpa_s->pending_pd_before_join && (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->p2p_fallback_to_go_neg) { 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 " - "join-existing-group operation (no ACK for PD " - "Req)"); - wpas_p2p_join_start(wpa_s); + 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; } } @@ -2290,6 +2284,15 @@ static void wpas_prov_disc_fail(void *ctx, const u8 *peer, return; } + if (status == P2P_PROV_DISC_TIMEOUT_JOIN) { + wpa_s->pending_pd_before_join = 0; + wpa_printf(MSG_DEBUG, "P2P: Starting pending " + "join-existing-group operation (no ACK for PD " + "Req attempts)"); + wpas_p2p_join_start(wpa_s); + return; + } + wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_FAILURE " p2p_dev_addr=" MACSTR " status=%d", MAC2STR(peer), status);