P2P: Wait for PD-before-join response

Even though the Provision Discovery Response frame from PD-before-join
does not really provide any additional information, it can be better to
wait for it before starting the join operation. This adds a minimal
extra latency in the most common case and cleans up the sequence of
driver operations and debug log by avoiding potential processing of the
Provision Discovery Response while already running a scan for the actual
connection.

If transmission of Provision Discovery Request fails, join operation is
started without the additional wait. In addition, a new timeout is used
to start the join if Provision Discovery Response is lost for any
reason.

Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2012-02-05 20:52:24 +02:00
parent c19316354e
commit f63b854215

View file

@ -62,6 +62,8 @@ static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s);
static void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx); static void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx);
static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr, static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr,
const u8 *dev_addr, enum p2p_wps_method wps_method); const u8 *dev_addr, enum p2p_wps_method wps_method);
static void wpas_p2p_pd_before_join_timeout(void *eloop_ctx,
void *timeout_ctx);
static int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s); 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);
@ -638,12 +640,14 @@ static void wpas_p2p_send_action_tx_status(struct wpa_supplicant *wpa_s,
p2p_send_action_cb(wpa_s->global->p2p, freq, dst, src, bssid, res); p2p_send_action_cb(wpa_s->global->p2p, freq, dst, src, bssid, res);
if (wpa_s->pending_pd_before_join && 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_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;
wpa_printf(MSG_DEBUG, "P2P: Starting pending " wpa_printf(MSG_DEBUG, "P2P: Starting pending "
"join-existing-group operation"); "join-existing-group operation (no ACK for PD "
"Req)");
wpas_p2p_join_start(wpa_s); wpas_p2p_join_start(wpa_s);
} }
} }
@ -2408,6 +2412,7 @@ void wpas_p2p_deinit(struct wpa_supplicant *wpa_s)
wpa_s->go_params = NULL; wpa_s->go_params = NULL;
eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s, NULL); eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s, NULL);
eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL); eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
eloop_cancel_timeout(wpas_p2p_pd_before_join_timeout, wpa_s, NULL);
wpa_s->p2p_long_listen = 0; wpa_s->p2p_long_listen = 0;
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);
@ -2542,6 +2547,21 @@ static void wpas_p2p_check_join_scan_limit(struct wpa_supplicant *wpa_s)
} }
static void wpas_p2p_pd_before_join_timeout(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_supplicant *wpa_s = eloop_ctx;
if (!wpa_s->pending_pd_before_join)
return;
/*
* Provision Discovery Response may have been lost - try to connect
* anyway since we do not need any information from this PD.
*/
wpa_printf(MSG_DEBUG, "P2P: PD timeout for join-existing-group - "
"try to connect anyway");
wpas_p2p_join_start(wpa_s);
}
static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s, static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res) struct wpa_scan_results *scan_res)
{ {
@ -2640,8 +2660,15 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
/* /*
* Actual join operation will be started from the Action frame * Actual join operation will be started from the Action frame
* TX status callback. * TX status callback (if no ACK is received) or when the
* Provision Discovery Response is received. Use a short
* timeout as a backup mechanism should the Provision Discovery
* Response be lost for any reason.
*/ */
eloop_cancel_timeout(wpas_p2p_pd_before_join_timeout, wpa_s,
NULL);
eloop_register_timeout(2, 0, wpas_p2p_pd_before_join_timeout,
wpa_s, NULL);
return; return;
} }
@ -2740,6 +2767,7 @@ static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s)
struct wpa_supplicant *group; struct wpa_supplicant *group;
struct p2p_go_neg_results res; struct p2p_go_neg_results res;
eloop_cancel_timeout(wpas_p2p_pd_before_join_timeout, wpa_s, NULL);
group = wpas_p2p_get_group_iface(wpa_s, 0, 0); group = wpas_p2p_get_group_iface(wpa_s, 0, 0);
if (group == NULL) if (group == NULL)
return -1; return -1;