From f63b8542156496ba88ef9f161e5931122d7319b9 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 5 Feb 2012 20:52:24 +0200 Subject: [PATCH] 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 --- wpa_supplicant/p2p_supplicant.c | 34 ++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index ffda3bb6f..5cfa9720d 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -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 int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr, 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 void wpas_p2p_cross_connect_setup(struct wpa_supplicant *wpa_s); 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); - 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_iface_addr, ETH_ALEN) == 0)) { wpa_s->pending_pd_before_join = 0; 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); } } @@ -2408,6 +2412,7 @@ void wpas_p2p_deinit(struct wpa_supplicant *wpa_s) wpa_s->go_params = 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_pd_before_join_timeout, wpa_s, NULL); wpa_s->p2p_long_listen = 0; eloop_cancel_timeout(wpas_p2p_long_listen_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, 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 - * 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; } @@ -2740,6 +2767,7 @@ static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s) struct wpa_supplicant *group; 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); if (group == NULL) return -1;