]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
P2P: Retry PD Request in join-a-running-group case
authorJouni Malinen <jouni@qca.qualcomm.com>
Thu, 22 Nov 2012 22:53:42 +0000 (00:53 +0200)
committerJouni Malinen <j@w1.fi>
Thu, 22 Nov 2012 22:53:42 +0000 (00:53 +0200)
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>

src/p2p/p2p.c
src/p2p/p2p.h
wpa_supplicant/p2p_supplicant.c

index af2d24afdb4b0a50bce97d16b49c82fd239d99b9..22760d91ed8a008a4e392533a395574d4dfb47ff 100644 (file)
@@ -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);
        }
index 5eeb653858d8965eccbe0d434f07ecc5d6dca342..8b2aab2d17d127032491ccdf56a557289e991b5e 100644 (file)
@@ -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 {
index d3e63b73fd714819cd1c1ff1e12adcec7d6bec61..9b6a88e7f919769fc6cccce7d57c0c19198f7ce6 100644 (file)
@@ -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);