]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
P2P: Optimize scan for GO during persistent group invocation
authorRashmi Ramanna <c_ramanr.qualcomm.com>
Fri, 21 Mar 2014 12:56:02 +0000 (18:26 +0530)
committerJouni Malinen <j@w1.fi>
Tue, 25 Mar 2014 13:38:33 +0000 (15:38 +0200)
Scan for GO on the negotiated operating channel for few iterations
before searching on all the supported channels during persistent group
reinvocation. In addition, use the already known SSID of the group in
the scans. These optimizations reduce group formation time.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
src/p2p/p2p.c
src/p2p/p2p.h
src/p2p/p2p_invitation.c
wpa_supplicant/events.c
wpa_supplicant/p2p_supplicant.c
wpa_supplicant/scan.c
wpa_supplicant/wpa_supplicant_i.h

index a1325d36debe672791288300666de858d8c19f56..ea1676172301da7165fdc18c0f16f5f7b8ebe67e 100644 (file)
@@ -3310,7 +3310,7 @@ static void p2p_timeout_invite_listen(struct p2p_data *p2p)
                                p2p->cfg->invitation_result(
                                        p2p->cfg->cb_ctx, -1, NULL, NULL,
                                        p2p->invite_peer->info.p2p_device_addr,
-                                       0);
+                                       0, 0);
                }
                p2p_set_state(p2p, P2P_IDLE);
        }
index 08e7176c1d436113a0de1a16f622d67f6c136c5f..abbb1114b3a47050df0e7d8ac658650181f7170c 100644 (file)
@@ -764,6 +764,8 @@ struct p2p_config {
         * @channels: Available operating channels for the group
         * @addr: Peer address
         * @freq: Frequency (in MHz) indicated during invitation or 0
+        * @peer_oper_freq: Operating frequency (in MHz) advertized by the peer
+        * during invitation or 0
         *
         * This callback is used to indicate result of an Invitation procedure
         * started with a call to p2p_invite(). The indicated status code is
@@ -773,7 +775,7 @@ struct p2p_config {
         */
        void (*invitation_result)(void *ctx, int status, const u8 *bssid,
                                  const struct p2p_channels *channels,
-                                 const u8 *addr, int freq);
+                                 const u8 *addr, int freq, int peer_oper_freq);
 
        /**
         * go_connected - Check whether we are connected to a GO
index a45fe198d819475d530b996fdbe8ff9c1c3b9353..cb77aee3b7b62064aa8735e75edc300518788fb4 100644 (file)
@@ -288,7 +288,9 @@ void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
                        }
                }
 
-               if (!p2p_channels_includes(&intersection, p2p->op_reg_class,
+               /* Reselect the channel only for the case of the GO */
+               if (go &&
+                   !p2p_channels_includes(&intersection, p2p->op_reg_class,
                                           p2p->op_channel)) {
                        p2p_dbg(p2p, "Initially selected channel (op_class %d channel %d) not in channel intersection - try to reselect",
                                p2p->op_reg_class, p2p->op_channel);
@@ -303,7 +305,7 @@ void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
                                status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
                                goto fail;
                        }
-               } else if (!(dev->flags & P2P_DEV_FORCE_FREQ) &&
+               } else if (go && !(dev->flags & P2P_DEV_FORCE_FREQ) &&
                           !p2p->cfg->cfg_op_channel) {
                        p2p_dbg(p2p, "Try to reselect channel selection with peer information received; previously selected op_class %u channel %u",
                                p2p->op_reg_class, p2p->op_channel);
@@ -444,13 +446,23 @@ void p2p_process_invitation_resp(struct p2p_data *p2p, const u8 *sa,
        }
 
        if (p2p->cfg->invitation_result) {
+               int peer_oper_freq = 0;
                int freq = p2p_channel_to_freq(p2p->op_reg_class,
                                               p2p->op_channel);
                if (freq < 0)
                        freq = 0;
+
+               if (msg.operating_channel) {
+                       peer_oper_freq = p2p_channel_to_freq(
+                               msg.operating_channel[3],
+                               msg.operating_channel[4]);
+                       if (peer_oper_freq < 0)
+                               peer_oper_freq = 0;
+               }
+
                p2p->cfg->invitation_result(p2p->cfg->cb_ctx, *msg.status,
                                            msg.group_bssid, channels, sa,
-                                           freq);
+                                           freq, peer_oper_freq);
        }
 
        p2p_parse_free(&msg);
index 343baa61b3d78ad3da059c33a9b9a6f86cc8fb6a..56f22f0e65f58fff80ab24675b7c9d66d3ba4951 100644 (file)
@@ -1430,7 +1430,8 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
                                return 0;
 
                        if (wpa_s->p2p_in_provisioning ||
-                           wpa_s->show_group_started) {
+                           wpa_s->show_group_started ||
+                           wpa_s->p2p_in_invitation) {
                                /*
                                 * Use shorter wait during P2P Provisioning
                                 * state and during P2P join-a-group operation
index 6f9f2176b9547de2156afd7bee59b2fb603cfad2..77088df714bd96ebe72da71bb799949b3cecf47c 100644 (file)
@@ -501,6 +501,8 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s,
                wpa_s->p2p_in_provisioning = 0;
        }
 
+       wpa_s->p2p_in_invitation = 0;
+
        /*
         * Make sure wait for the first client does not remain active after the
         * group has been removed.
@@ -3070,7 +3072,7 @@ static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid,
                if (s) {
                        int go = s->mode == WPAS_MODE_P2P_GO;
                        wpas_p2p_group_add_persistent(
-                               wpa_s, s, go, 0, go ? op_freq : 0, 0, 0, NULL,
+                               wpa_s, s, go, 0, op_freq, 0, 0, NULL,
                                go ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0);
                } else if (bssid) {
                        wpa_s->user_initiated_pd = 0;
@@ -3177,10 +3179,12 @@ static void wpas_remove_persistent_client(struct wpa_supplicant *wpa_s,
 
 static void wpas_invitation_result(void *ctx, int status, const u8 *bssid,
                                   const struct p2p_channels *channels,
-                                  const u8 *peer, int neg_freq)
+                                  const u8 *peer, int neg_freq,
+                                  int peer_oper_freq)
 {
        struct wpa_supplicant *wpa_s = ctx;
        struct wpa_ssid *ssid;
+       int freq;
 
        if (bssid) {
                wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RESULT
@@ -3236,10 +3240,21 @@ static void wpas_invitation_result(void *ctx, int status, const u8 *bssid,
                "starting persistent group");
        os_sleep(0, 50000);
 
+       if (neg_freq > 0 && ssid->mode == WPAS_MODE_P2P_GO &&
+           freq_included(channels, neg_freq))
+               freq = neg_freq;
+       else if (peer_oper_freq > 0 && ssid->mode != WPAS_MODE_P2P_GO &&
+                freq_included(channels, peer_oper_freq))
+               freq = peer_oper_freq;
+       else
+               freq = 0;
+
+       wpa_printf(MSG_DEBUG, "P2P: Persistent group invitation success - op_freq=%d MHz SSID=%s",
+                  freq, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
        wpas_p2p_group_add_persistent(wpa_s, ssid,
                                      ssid->mode == WPAS_MODE_P2P_GO,
                                      wpa_s->p2p_persistent_go_freq,
-                                     neg_freq,
+                                     freq,
                                      wpa_s->p2p_go_ht40, wpa_s->p2p_go_vht,
                                      channels,
                                      ssid->mode == WPAS_MODE_P2P_GO ?
@@ -5150,7 +5165,8 @@ int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
 
 
 static int wpas_start_p2p_client(struct wpa_supplicant *wpa_s,
-                                struct wpa_ssid *params, int addr_allocated)
+                                struct wpa_ssid *params, int addr_allocated,
+                                int freq)
 {
        struct wpa_ssid *ssid;
 
@@ -5187,6 +5203,8 @@ static int wpas_start_p2p_client(struct wpa_supplicant *wpa_s,
                ssid->passphrase = os_strdup(params->passphrase);
 
        wpa_s->show_group_started = 1;
+       wpa_s->p2p_in_invitation = 1;
+       wpa_s->p2p_invite_go_freq = freq;
 
        wpa_supplicant_select_network(wpa_s, ssid);
 
@@ -5221,12 +5239,6 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
 
        wpa_s->p2p_fallback_to_go_neg = 0;
 
-       if (ssid->mode == WPAS_MODE_INFRA)
-               return wpas_start_p2p_client(wpa_s, ssid, addr_allocated);
-
-       if (ssid->mode != WPAS_MODE_P2P_GO)
-               return -1;
-
        if (force_freq > 0) {
                freq = wpas_p2p_select_go_freq(wpa_s, force_freq);
                if (freq < 0)
@@ -5237,6 +5249,12 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
                        freq = 0;
        }
 
+       if (ssid->mode == WPAS_MODE_INFRA)
+               return wpas_start_p2p_client(wpa_s, ssid, addr_allocated, freq);
+
+       if (ssid->mode != WPAS_MODE_P2P_GO)
+               return -1;
+
        if (wpas_p2p_init_go_params(wpa_s, &params, freq, ht40, vht, channels))
                return -1;
 
index 48e94b6122343fb1d3f7e02ff676feff3d73f8ae..1d4e6e5ba356be1551308ee4d8bf436fded3c5e1 100644 (file)
@@ -326,6 +326,32 @@ static void wpa_supplicant_optimize_freqs(
                }
                wpa_s->p2p_in_provisioning++;
        }
+
+       if (params->freqs == NULL && wpa_s->p2p_in_invitation) {
+               /*
+                * Optimize scan based on GO information during persistent
+                * group reinvocation
+                */
+               if (wpa_s->p2p_in_invitation < 5 ||
+                   wpa_s->p2p_invite_go_freq > 0) {
+                       wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only GO preferred frequency %d MHz during invitation",
+                               wpa_s->p2p_invite_go_freq);
+                       params->freqs = os_zalloc(2 * sizeof(int));
+                       if (params->freqs)
+                               params->freqs[0] = wpa_s->p2p_invite_go_freq;
+               }
+               wpa_s->p2p_in_invitation++;
+               if (wpa_s->p2p_in_invitation > 20) {
+                       /*
+                        * This should not really happen since the variable is
+                        * cleared on group removal, but if it does happen, make
+                        * sure we do not get stuck in special invitation scan
+                        * mode.
+                        */
+                       wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Clear p2p_in_invitation");
+                       wpa_s->p2p_in_invitation = 0;
+               }
+       }
 #endif /* CONFIG_P2P */
 
 #ifdef CONFIG_WPS
@@ -639,6 +665,19 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
                params.num_ssids = 1;
                goto ssid_list_set;
        }
+
+       if (wpa_s->p2p_in_invitation) {
+               if (wpa_s->current_ssid) {
+                       wpa_printf(MSG_DEBUG, "P2P: Use specific SSID for scan during invitation");
+                       params.ssids[0].ssid = wpa_s->current_ssid->ssid;
+                       params.ssids[0].ssid_len =
+                               wpa_s->current_ssid->ssid_len;
+                       params.num_ssids = 1;
+               } else {
+                       wpa_printf(MSG_DEBUG, "P2P: No specific SSID known for scan during invitation");
+               }
+               goto ssid_list_set;
+       }
 #endif /* CONFIG_P2P */
 
        /* Find the starting point from which to continue scanning */
index 8a3328661d94d379e5be29e12758ef11cd226783..b5e137cfcad79c1022df262e3fc329f6eae4210a 100644 (file)
@@ -687,6 +687,8 @@ struct wpa_supplicant {
        u8 p2p_auth_invite[ETH_ALEN];
        int p2p_sd_over_ctrl_iface;
        int p2p_in_provisioning;
+       int p2p_in_invitation;
+       int p2p_invite_go_freq;
        int pending_invite_ssid_id;
        int show_group_started;
        u8 go_dev_addr[ETH_ALEN];