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 <jouni@qca.qualcomm.com>
This commit is contained in:
parent
6752716663
commit
175171ac6c
3 changed files with 33 additions and 17 deletions
|
@ -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
|
* 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
|
* requested.
|
||||||
* in the meantime.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
|
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;
|
continue;
|
||||||
if (!dev->req_config_methods)
|
if (!dev->req_config_methods)
|
||||||
continue;
|
continue;
|
||||||
if (dev->flags & P2P_DEV_PD_FOR_JOIN)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send "
|
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send "
|
||||||
"pending Provision Discovery Request to "
|
"pending Provision Discovery Request to "
|
||||||
MACSTR " (config methods 0x%x)",
|
MACSTR " (config methods 0x%x)",
|
||||||
MAC2STR(dev->info.p2p_device_addr),
|
MAC2STR(dev->info.p2p_device_addr),
|
||||||
dev->req_config_methods);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3183,9 +3181,23 @@ static void p2p_timeout_prov_disc_req(struct p2p_data *p2p)
|
||||||
p2p->pd_retries--;
|
p2p->pd_retries--;
|
||||||
p2p_retry_pd(p2p);
|
p2p_retry_pd(p2p);
|
||||||
} else {
|
} 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)
|
if (p2p->cfg->prov_disc_fail)
|
||||||
p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx,
|
p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx,
|
||||||
p2p->pending_pd_devaddr,
|
p2p->pending_pd_devaddr,
|
||||||
|
for_join ?
|
||||||
|
P2P_PROV_DISC_TIMEOUT_JOIN :
|
||||||
P2P_PROV_DISC_TIMEOUT);
|
P2P_PROV_DISC_TIMEOUT);
|
||||||
p2p_reset_pending_pd(p2p);
|
p2p_reset_pending_pd(p2p);
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,6 +232,7 @@ enum p2p_prov_disc_status {
|
||||||
P2P_PROV_DISC_SUCCESS,
|
P2P_PROV_DISC_SUCCESS,
|
||||||
P2P_PROV_DISC_TIMEOUT,
|
P2P_PROV_DISC_TIMEOUT,
|
||||||
P2P_PROV_DISC_REJECTED,
|
P2P_PROV_DISC_REJECTED,
|
||||||
|
P2P_PROV_DISC_TIMEOUT_JOIN,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct p2p_channel {
|
struct p2p_channel {
|
||||||
|
|
|
@ -723,19 +723,13 @@ static void wpas_p2p_send_action_tx_status(struct wpa_supplicant *wpa_s,
|
||||||
if (result != OFFCHANNEL_SEND_ACTION_SUCCESS &&
|
if (result != OFFCHANNEL_SEND_ACTION_SUCCESS &&
|
||||||
wpa_s->pending_pd_before_join &&
|
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_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;
|
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 "
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: No ACK for PD Req "
|
"during p2p_connect-auto");
|
||||||
"during p2p_connect-auto");
|
wpas_p2p_fallback_to_go_neg(wpa_s, 0);
|
||||||
wpas_p2p_fallback_to_go_neg(wpa_s, 0);
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "P2P: Starting pending "
|
|
||||||
"join-existing-group operation (no ACK for PD "
|
|
||||||
"Req)");
|
|
||||||
wpas_p2p_join_start(wpa_s);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2290,6 +2284,15 @@ static void wpas_prov_disc_fail(void *ctx, const u8 *peer,
|
||||||
return;
|
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
|
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);
|
||||||
|
|
Loading…
Reference in a new issue