]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
P2P: Optimize join scan frequency
authorMatthew Wang <matthewmwang@chromium.org>
Wed, 22 Feb 2023 00:46:16 +0000 (16:46 -0800)
committerJouni Malinen <j@w1.fi>
Wed, 22 Feb 2023 11:40:21 +0000 (13:40 +0200)
Allow clients to specify the BSSID of an auto GO. If the auto GO has been
discovered on another interface, optimize scan frequency by performing
a single channel scan first. Android and ChromeOS use this to streamline
auto GO discovery.

Signed-off-by: Matthew Wang <matthewmwang@chromium.org>
wpa_supplicant/bss.c
wpa_supplicant/ctrl_iface.c
wpa_supplicant/dbus/dbus_new_handlers_p2p.c
wpa_supplicant/events.c
wpa_supplicant/p2p_supplicant.c
wpa_supplicant/p2p_supplicant.h
wpa_supplicant/scan.c
wpa_supplicant/wpa_supplicant_i.h

index 043ec35807ef3d0800786931bc74a16a31a01365..320441426b64cafbfc2456f5e8015962c347ad76 100644 (file)
@@ -240,7 +240,7 @@ void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
 /**
  * wpa_bss_get - Fetch a BSS table entry based on BSSID and SSID
  * @wpa_s: Pointer to wpa_supplicant data
- * @bssid: BSSID
+ * @bssid: BSSID, or %NULL to match any BSSID
  * @ssid: SSID
  * @ssid_len: Length of @ssid
  * Returns: Pointer to the BSS entry or %NULL if not found
@@ -249,10 +249,11 @@ struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid,
                             const u8 *ssid, size_t ssid_len)
 {
        struct wpa_bss *bss;
-       if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid))
+
+       if (bssid && !wpa_supplicant_filter_bssid_match(wpa_s, bssid))
                return NULL;
        dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
-               if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0 &&
+               if ((!bssid || os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0) &&
                    bss->ssid_len == ssid_len &&
                    os_memcmp(bss->ssid, ssid, ssid_len) == 0)
                        return bss;
index 6588fd47b4a9099a23781d4cfa40ed24dff854fa..68a62da72fdff87d33e22328775003703edcdc2a 100644 (file)
@@ -7128,7 +7128,7 @@ static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
        return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq,
                                             vht_center_freq2, 0, ht40, vht,
                                             vht_chwidth, he, edmg,
-                                            NULL, 0, 0, allow_6ghz, 0);
+                                            NULL, 0, 0, allow_6ghz, 0, NULL);
 }
 
 
index 370aee278cfefcdf5eabd9d4f66090658cd6c5f7..a178d879ea2b427ce69775e374c8a38e683952af 100644 (file)
@@ -359,6 +359,7 @@ DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
        char *iface = NULL;
        unsigned int group_id = 0;
        struct wpa_ssid *ssid;
+       u8 go_bssid_buf[ETH_ALEN], *go_bssid = NULL;
 
        dbus_message_iter_init(message, &iter);
 
@@ -384,10 +385,16 @@ DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
                                goto inv_args_clear;
                } else if (os_strcmp(entry.key, "persistent_group_object") ==
                           0 &&
-                          entry.type == DBUS_TYPE_OBJECT_PATH)
+                          entry.type == DBUS_TYPE_OBJECT_PATH) {
                        pg_object_path = os_strdup(entry.str_value);
-               else
+               } else if (os_strcmp(entry.key, "go_bssid") == 0 &&
+                          entry.type == DBUS_TYPE_STRING) {
+                       if (hwaddr_aton(entry.str_value, go_bssid_buf))
+                               goto inv_args_clear;
+                       go_bssid = go_bssid_buf;
+               } else {
                        goto inv_args_clear;
+               }
 
                wpa_dbus_dict_entry_clear(&entry);
        }
@@ -432,7 +439,8 @@ DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
 
                if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, 0,
                                                  0, 0, 0, 0, NULL, 0, 0,
-                                                 false, retry_limit)) {
+                                                 false, retry_limit,
+                                                 go_bssid)) {
                        reply = wpas_dbus_error_unknown_error(
                                message,
                                "Failed to reinvoke a persistent group");
index e58a3da8356e6a6e6f265956d44dd0092a72153e..a9ff491330bea08cabd48a1285289b78d80d102e 100644 (file)
@@ -1163,7 +1163,7 @@ static void owe_trans_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
 }
 
 
-static int disabled_freq(struct wpa_supplicant *wpa_s, int freq)
+int disabled_freq(struct wpa_supplicant *wpa_s, int freq)
 {
        int i, j;
 
index b906c7736f9d9ba1ea7ffe2401baefff41da4cd8..4263ee9f33346fcac335b86ba8426d41b84dabc4 100644 (file)
@@ -3373,7 +3373,8 @@ static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid,
                                wpa_s->conf->p2p_go_he,
                                wpa_s->conf->p2p_go_edmg, NULL,
                                go ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0,
-                               1, is_p2p_allow_6ghz(wpa_s->global->p2p), 0);
+                               1, is_p2p_allow_6ghz(wpa_s->global->p2p), 0,
+                               NULL);
                } else if (bssid) {
                        wpa_s->user_initiated_pd = 0;
                        wpa_msg_global(wpa_s, MSG_INFO,
@@ -3603,7 +3604,8 @@ static void wpas_invitation_result(void *ctx, int status, const u8 *bssid,
                                      ssid->mode == WPAS_MODE_P2P_GO ?
                                      P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
                                      0, 1,
-                                     is_p2p_allow_6ghz(wpa_s->global->p2p), 0);
+                                     is_p2p_allow_6ghz(wpa_s->global->p2p), 0,
+                                     NULL);
 }
 
 
@@ -4689,7 +4691,7 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
                                        persistent_go->mode ==
                                        WPAS_MODE_P2P_GO ?
                                        P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
-                                       0, 0, false, 0);
+                                       0, 0, false, 0, NULL);
                        } else if (response_done) {
                                wpas_p2p_group_add(wpa_s, 1, freq,
                                                   0, 0, 0, 0, 0, 0, false);
@@ -4812,7 +4814,7 @@ static int wpas_prov_disc_resp_cb(void *ctx)
                        NULL,
                        persistent_go->mode == WPAS_MODE_P2P_GO ?
                        P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0, 0,
-                       is_p2p_allow_6ghz(wpa_s->global->p2p), 0);
+                       is_p2p_allow_6ghz(wpa_s->global->p2p), 0, NULL);
        } else {
                wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0, 0, 0,
                                   is_p2p_allow_6ghz(wpa_s->global->p2p));
@@ -6946,7 +6948,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,
-                                int freq, int force_scan, int retry_limit)
+                                int freq, int force_scan, int retry_limit,
+                                const u8 *go_bssid)
 {
        struct wpa_ssid *ssid;
        int other_iface_found = 0;
@@ -6999,6 +7002,11 @@ static int wpas_start_p2p_client(struct wpa_supplicant *wpa_s,
        if (params->passphrase)
                ssid->passphrase = os_strdup(params->passphrase);
 
+       if (go_bssid) {
+               ssid->bssid_set = 1;
+               os_memcpy(ssid->bssid, go_bssid, ETH_ALEN);
+       }
+
        wpa_s->show_group_started = 1;
        wpa_s->p2p_in_invitation = 1;
        wpa_s->p2p_retry_limit = retry_limit;
@@ -7045,7 +7053,8 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
                                  int edmg,
                                  const struct p2p_channels *channels,
                                  int connection_timeout, int force_scan,
-                                 bool allow_6ghz, int retry_limit)
+                                 bool allow_6ghz, int retry_limit,
+                                 const u8 *go_bssid)
 {
        struct p2p_go_neg_results params;
        int go = 0, freq;
@@ -7113,7 +7122,7 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
                }
 
                return wpas_start_p2p_client(wpa_s, ssid, addr_allocated, freq,
-                                            force_scan, retry_limit);
+                                            force_scan, retry_limit, go_bssid);
        } else {
                return -1;
        }
index 907ac8ccad718d4cb25603bf4012f5e835dd2382..d71f7701c159b3987ef3f9af3242a7b3fb182344 100644 (file)
@@ -52,7 +52,8 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
                                  int max_oper_chwidth, int he, int edmg,
                                  const struct p2p_channels *channels,
                                  int connection_timeout, int force_scan,
-                                 bool allow_6ghz, int retry_limit);
+                                 bool allow_6ghz, int retry_limit,
+                                 const u8 *go_bssid);
 struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
                                       struct wpa_ssid *ssid);
 enum wpas_p2p_prov_disc_use {
index cc9faf2a807572bbb41d4ab749ff8ac667dae1de..c3984a40c94c0d25294d6e91234a13edd6500a9b 100644 (file)
@@ -445,11 +445,43 @@ static void wpa_supplicant_optimize_freqs(
        }
 
        if (params->freqs == NULL && wpa_s->p2p_in_invitation) {
+               struct wpa_ssid *ssid = wpa_s->current_ssid;
+
+               /*
+                * Perform a single-channel scan if the GO has already been
+                * discovered on another non-P2P interface. Note that a scan
+                * initiated by a P2P interface (e.g., the device interface)
+                * should already have sufficient IEs and scan results will be
+                * fetched on interface creation in that case.
+                */
+               if (wpa_s->p2p_in_invitation == 1 && ssid) {
+                       struct wpa_supplicant *ifs;
+                       struct wpa_bss *bss = NULL;
+                       const u8 *bssid = ssid->bssid_set ? ssid->bssid : NULL;
+
+                       dl_list_for_each(ifs, &wpa_s->radio->ifaces,
+                                        struct wpa_supplicant, radio_list) {
+                               bss = wpa_bss_get(ifs, bssid, ssid->ssid,
+                                                 ssid->ssid_len);
+                               if (bss)
+                                       break;
+                       }
+                       if (bss && !disabled_freq(wpa_s, bss->freq)) {
+                               params->freqs = os_calloc(2, sizeof(int));
+                               if (params->freqs) {
+                                       wpa_dbg(wpa_s, MSG_DEBUG,
+                                               "P2P: Scan only the known GO frequency %d MHz during invitation",
+                                               bss->freq);
+                                       params->freqs[0] = bss->freq;
+                               }
+                       }
+               }
+
                /*
                 * Optimize scan based on GO information during persistent
                 * group reinvocation
                 */
-               if (wpa_s->p2p_in_invitation < 5 &&
+               if (!params->freqs && wpa_s->p2p_in_invitation < 5 &&
                    wpa_s->p2p_invite_go_freq > 0) {
                        if (wpa_s->p2p_invite_go_freq == 2 ||
                            wpa_s->p2p_invite_go_freq == 5) {
index cb7d5f5a1988ff6021228c7b51cfcccf8439947d..61d274a056b1a37606f8e581eb955bb4443ddbdb 100644 (file)
@@ -1826,6 +1826,7 @@ int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
 int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
                           int *freq_array, unsigned int len,
                           bool exclude_current);
+int disabled_freq(struct wpa_supplicant *wpa_s, int freq);
 
 void wpas_network_reenabled(void *eloop_ctx, void *timeout_ctx);