]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Optimize internal BSS table updates based on a specific BSSID
authorJouni Malinen <quic_jouni@quicinc.com>
Wed, 20 Mar 2024 09:20:43 +0000 (11:20 +0200)
committerJouni Malinen <j@w1.fi>
Wed, 20 Mar 2024 10:00:46 +0000 (12:00 +0200)
When wpa_supplicant needed to update the internal BSS table with the
latest scan results from the driver, it fetched all BSSs and processed
them all. This is unnecessary for cases where an update is needed only
for a specific BSS. Optimize this by filtering out the unnecessary
entries from the results.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
16 files changed:
src/ap/ap_drv_ops.c
src/drivers/driver.h
src/drivers/driver_nl80211.c
src/drivers/driver_nl80211.h
src/drivers/driver_nl80211_scan.c
wpa_supplicant/driver_i.h
wpa_supplicant/events.c
wpa_supplicant/p2p_supplicant.c
wpa_supplicant/pasn_supplicant.c
wpa_supplicant/scan.c
wpa_supplicant/scan.h
wpa_supplicant/sme.c
wpa_supplicant/wnm_sta.c
wpa_supplicant/wpa_priv.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpas_glue.c

index e89f53060658c300018ea8505d53e1fa0a5471ae..6d910aa5aafe02dc69e126595318bafc9d60067c 100644 (file)
@@ -758,6 +758,8 @@ int hostapd_driver_scan(struct hostapd_data *hapd,
 struct wpa_scan_results * hostapd_driver_get_scan_results(
        struct hostapd_data *hapd)
 {
+       if (hapd->driver && hapd->driver->get_scan_results)
+               return hapd->driver->get_scan_results(hapd->drv_priv, NULL);
        if (hapd->driver && hapd->driver->get_scan_results2)
                return hapd->driver->get_scan_results2(hapd->drv_priv);
        return NULL;
index eedc3f647dd9206f21c4b4ea743e75c83f9c835d..72446fac1433d762597471fcc9eb7eca23ac1579 100644 (file)
@@ -3366,6 +3366,17 @@ struct wpa_driver_ops {
        int (*update_ft_ies)(void *priv, const u8 *md, const u8 *ies,
                             size_t ies_len);
 
+       /**
+        * get_scan_results - Fetch the latest scan results
+        * @priv: Private driver interface data
+        * @bssid: Return results only for the specified BSSID, %NULL for all
+        *
+        * Returns: Allocated buffer of scan results (caller is responsible for
+        * freeing the data structure) on success, NULL on failure
+        */
+       struct wpa_scan_results * (*get_scan_results)(void *priv,
+                                                     const u8 *bssid);
+
        /**
         * get_scan_results2 - Fetch the latest scan results
         * @priv: private driver interface data
index b3e9e6f2fe5e3e48525d3b336a6d3abf9c783b3a..e2c46c123a2bd139ae231f81ee7d7db32826f715 100644 (file)
@@ -13880,7 +13880,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
        .scan2 = driver_nl80211_scan2,
        .sched_scan = wpa_driver_nl80211_sched_scan,
        .stop_sched_scan = wpa_driver_nl80211_stop_sched_scan,
-       .get_scan_results2 = wpa_driver_nl80211_get_scan_results,
+       .get_scan_results = wpa_driver_nl80211_get_scan_results,
        .abort_scan = wpa_driver_nl80211_abort_scan,
        .deauthenticate = driver_nl80211_deauthenticate,
        .authenticate = driver_nl80211_authenticate,
index 43a6625bbf7ab08da72b5360ea3bbf2266791b20..32a1c8b1f92b2a28650e71934f56cdf9959605fa 100644 (file)
@@ -401,7 +401,8 @@ int wpa_driver_nl80211_scan(struct i802_bss *bss,
 int wpa_driver_nl80211_sched_scan(void *priv,
                                  struct wpa_driver_scan_params *params);
 int wpa_driver_nl80211_stop_sched_scan(void *priv);
-struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv);
+struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv,
+                                                             const u8 *bssid);
 void nl80211_dump_scan(struct wpa_driver_nl80211_data *drv);
 int wpa_driver_nl80211_abort_scan(void *priv, u64 scan_cookie);
 int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
index 68ae5799c60846a8c05bfae34ad9b630b71447ee..577f84fefc29941197fecf9f649b35db4fa7509d 100644 (file)
@@ -728,7 +728,7 @@ static int nl80211_scan_filtered(struct wpa_driver_nl80211_data *drv,
 
 static struct wpa_scan_res *
 nl80211_parse_bss_info(struct wpa_driver_nl80211_data *drv,
-                      struct nl_msg *msg)
+                      struct nl_msg *msg, const u8 *bssid)
 {
        struct nlattr *tb[NL80211_ATTR_MAX + 1];
        struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
@@ -762,6 +762,9 @@ nl80211_parse_bss_info(struct wpa_driver_nl80211_data *drv,
        if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS],
                             bss_policy))
                return NULL;
+       if (bssid && bss[NL80211_BSS_BSSID] &&
+           !ether_addr_equal(bssid, nla_data(bss[NL80211_BSS_BSSID])))
+               return NULL;
        if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) {
                ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
                ie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
@@ -866,6 +869,7 @@ nl80211_parse_bss_info(struct wpa_driver_nl80211_data *drv,
 struct nl80211_bss_info_arg {
        struct wpa_driver_nl80211_data *drv;
        struct wpa_scan_results *res;
+       const u8 *bssid;
 };
 
 static int bss_info_handler(struct nl_msg *msg, void *arg)
@@ -875,7 +879,7 @@ static int bss_info_handler(struct nl_msg *msg, void *arg)
        struct wpa_scan_res **tmp;
        struct wpa_scan_res *r;
 
-       r = nl80211_parse_bss_info(_arg->drv, msg);
+       r = nl80211_parse_bss_info(_arg->drv, msg, _arg->bssid);
        if (!r)
                return NL_SKIP;
 
@@ -973,7 +977,7 @@ static void nl80211_update_scan_res_noise(struct wpa_scan_res *res,
 
 
 static struct wpa_scan_results *
-nl80211_get_scan_results(struct wpa_driver_nl80211_data *drv)
+nl80211_get_scan_results(struct wpa_driver_nl80211_data *drv, const u8 *bssid)
 {
        struct nl_msg *msg;
        struct wpa_scan_results *res;
@@ -993,6 +997,7 @@ try_again:
 
        arg.drv = drv;
        arg.res = res;
+       arg.bssid = bssid;
        ret = send_and_recv_resp(drv, msg, bss_info_handler, &arg);
        if (ret == -EAGAIN) {
                count++;
@@ -1029,16 +1034,18 @@ try_again:
 
 /**
  * wpa_driver_nl80211_get_scan_results - Fetch the latest scan results
- * @priv: Pointer to private wext data from wpa_driver_nl80211_init()
+ * @priv: Pointer to private nl80211 data from wpa_driver_nl80211_init()
+ * @bssid: Return results only for the specified BSSID, %NULL for all
  * Returns: Scan results on success, -1 on failure
  */
-struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv)
+struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv,
+                                                             const u8 *bssid)
 {
        struct i802_bss *bss = priv;
        struct wpa_driver_nl80211_data *drv = bss->drv;
        struct wpa_scan_results *res;
 
-       res = nl80211_get_scan_results(drv);
+       res = nl80211_get_scan_results(drv, bssid);
        if (res)
                wpa_driver_nl80211_check_bss_status(drv, res);
        return res;
@@ -1055,7 +1062,7 @@ static int nl80211_dump_scan_handler(struct nl_msg *msg, void *arg)
        struct nl80211_dump_scan_ctx *ctx = arg;
        struct wpa_scan_res *r;
 
-       r = nl80211_parse_bss_info(ctx->drv, msg);
+       r = nl80211_parse_bss_info(ctx->drv, msg, NULL);
        if (!r)
                return NL_SKIP;
        wpa_printf(MSG_DEBUG, "nl80211: %d " MACSTR " %d%s",
index 9a4c2353712716bd89a5d049b3e05885e028df67..0322b71507058e7ba2b64b980c08cf81e33c9ff9 100644 (file)
@@ -128,7 +128,7 @@ static inline int wpa_drv_stop_sched_scan(struct wpa_supplicant *wpa_s)
 }
 
 struct wpa_scan_results *
-wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s);
+wpa_drv_get_scan_results(struct wpa_supplicant *wpa_s, const u8 *bssid);
 
 static inline int wpa_drv_get_bssid(struct wpa_supplicant *wpa_s, u8 *bssid)
 {
index c32610f9fd2426d690acd577766a0661073a3f88..ca27946384b695528377df618e84742b51e7882a 100644 (file)
@@ -163,7 +163,7 @@ wpa_supplicant_update_current_bss(struct wpa_supplicant *wpa_s, const u8 *bssid)
        struct wpa_bss *bss = wpa_supplicant_get_new_bss(wpa_s, bssid);
 
        if (!bss) {
-               wpa_supplicant_update_scan_results(wpa_s);
+               wpa_supplicant_update_scan_results(wpa_s, bssid);
 
                /* Get the BSS from the new scan results */
                bss = wpa_supplicant_get_new_bss(wpa_s, bssid);
@@ -182,7 +182,7 @@ static void wpa_supplicant_update_link_bss(struct wpa_supplicant *wpa_s,
        struct wpa_bss *bss = wpa_supplicant_get_new_bss(wpa_s, bssid);
 
        if (!bss) {
-               wpa_supplicant_update_scan_results(wpa_s);
+               wpa_supplicant_update_scan_results(wpa_s, bssid);
                bss = wpa_supplicant_get_new_bss(wpa_s, bssid);
        }
 
@@ -2404,7 +2404,7 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
 
        scan_res = wpa_supplicant_get_scan_results(wpa_s,
                                                   data ? &data->scan_info :
-                                                  NULL, 1);
+                                                  NULL, 1, NULL);
        if (scan_res == NULL) {
                if (wpa_s->conf->ap_scan == 2 || ap ||
                    wpa_s->scan_res_handler == scan_only_handler)
@@ -3635,7 +3635,7 @@ no_pfs:
                        wpa_printf(MSG_DEBUG,
                                   "Operating frequency changed from %u to %u MHz",
                                   wpa_s->assoc_freq, data->assoc_info.freq);
-                       wpa_supplicant_update_scan_results(wpa_s);
+                       wpa_supplicant_update_scan_results(wpa_s, bssid);
                }
        }
 
@@ -4046,7 +4046,8 @@ static int wpa_sm_set_ml_info(struct wpa_supplicant *wpa_s)
 
                bss = wpa_supplicant_get_new_bss(wpa_s, drv_mlo.links[i].bssid);
                if (!bss) {
-                       wpa_supplicant_update_scan_results(wpa_s);
+                       wpa_supplicant_update_scan_results(
+                               wpa_s, drv_mlo.links[i].bssid);
                        bss = wpa_supplicant_get_new_bss(
                                wpa_s, drv_mlo.links[i].bssid);
                }
index cfa4f4c88dc97369203b8ea9be5de1855d5294c3..70025f1e4a56cc6629f0079769c8021cf9aad727 100644 (file)
@@ -7012,7 +7012,7 @@ static int wpas_start_p2p_client(struct wpa_supplicant *wpa_s,
         * fetch time on the same radio so it reflects the actual time the last
         * scan result event occurred.
         */
-       wpa_supplicant_update_scan_results(wpa_s);
+       wpa_supplicant_update_scan_results(wpa_s, go_bssid);
        dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
                         radio_list) {
                if (ifs == wpa_s)
index 2e65cf085b97fadd96b5ca8545040eedaaaf03f5..3da9c7462dace7b1854a354c531dff8a4a1bf90c 100644 (file)
@@ -166,7 +166,7 @@ static int wpas_pasn_get_params_from_bss(struct wpa_supplicant *wpa_s,
 
        bss = wpa_bss_get_bssid(wpa_s, peer_addr);
        if (!bss) {
-               wpa_supplicant_update_scan_results(wpa_s);
+               wpa_supplicant_update_scan_results(wpa_s, peer_addr);
                bss = wpa_bss_get_bssid(wpa_s, peer_addr);
                if (!bss) {
                        wpa_printf(MSG_DEBUG, "PASN: BSS not found");
index 5c6f71f9f265f97b5e839081f6de322b24540ae8..2db4d8b910bb13888a11f7068eccd12d67995972 100644 (file)
@@ -3166,6 +3166,7 @@ void scan_est_throughput(struct wpa_supplicant *wpa_s,
  * @wpa_s: Pointer to wpa_supplicant data
  * @info: Information about what was scanned or %NULL if not available
  * @new_scan: Whether a new scan was performed
+ * @bssid: Return BSS entries only for a single BSSID, %NULL for all
  * Returns: Scan results, %NULL on failure
  *
  * This function request the current scan results from the driver and updates
@@ -3174,13 +3175,14 @@ void scan_est_throughput(struct wpa_supplicant *wpa_s,
  */
 struct wpa_scan_results *
 wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s,
-                               struct scan_info *info, int new_scan)
+                               struct scan_info *info, int new_scan,
+                               const u8 *bssid)
 {
        struct wpa_scan_results *scan_res;
        size_t i;
        int (*compar)(const void *, const void *) = wpa_scan_result_compar;
 
-       scan_res = wpa_drv_get_scan_results2(wpa_s);
+       scan_res = wpa_drv_get_scan_results(wpa_s, bssid);
        if (scan_res == NULL) {
                wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get scan results");
                return NULL;
@@ -3238,6 +3240,7 @@ wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s,
 /**
  * wpa_supplicant_update_scan_results - Update scan results from the driver
  * @wpa_s: Pointer to wpa_supplicant data
+ * @bssid: Update BSS entries only for a single BSSID, %NULL for all
  * Returns: 0 on success, -1 on failure
  *
  * This function updates the BSS table within wpa_supplicant based on the
@@ -3247,10 +3250,11 @@ wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s,
  * needed information to complete the connection (e.g., to perform validation
  * steps in 4-way handshake).
  */
-int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s)
+int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s,
+                                      const u8 *bssid)
 {
        struct wpa_scan_results *scan_res;
-       scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
+       scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0, bssid);
        if (scan_res == NULL)
                return -1;
        wpa_scan_results_free(scan_res);
index cc9d1a3faf950698ed07b69c965803391d30cf59..d4c06c1aed4034b0e746c01d6aec5b2fed4df347 100644 (file)
@@ -54,8 +54,10 @@ int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s,
                                bool default_ies, bool next);
 struct wpa_scan_results *
 wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s,
-                               struct scan_info *info, int new_scan);
-int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s);
+                               struct scan_info *info, int new_scan,
+                               const u8 *bssid);
+int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s,
+                                      const u8 *bssid);
 const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie);
 const u8 * wpa_scan_get_ml_ie(const struct wpa_scan_res *res, u8 type);
 const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res,
index 887dde5c76bc4be8f89a747f14302dd72e1cf25a..f08184f9810515fc9ac3103b61dafc3dc59b8084 100644 (file)
@@ -182,7 +182,7 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s,
        if (!bss) {
                wpa_printf(MSG_DEBUG,
                           "SAE: BSS not available, update scan result to get BSS");
-               wpa_supplicant_update_scan_results(wpa_s);
+               wpa_supplicant_update_scan_results(wpa_s, bssid);
                bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
        }
        if (bss) {
index 1672224d89a8ab78724d13d268608889e2ef4efb..7dc93ebff55336c06bf66a3451d3b758ed3e0e4f 100644 (file)
@@ -1602,7 +1602,7 @@ static void ieee802_11_rx_bss_trans_mgmt_req(struct wpa_supplicant *wpa_s,
                * It is not a new scan, this does not update the last_scan
                * timestamp nor will it expire old BSSs.
                */
-               wpa_supplicant_update_scan_results(wpa_s);
+               wpa_supplicant_update_scan_results(wpa_s, NULL);
                if (wnm_scan_process(wpa_s, true) > 0)
                        return;
                wpa_printf(MSG_DEBUG,
index 31a9af6503aeac3ea0e3011ea3ad7e1862057e1b..88f3f2a523568c17f107b529d40e8659ba6004a7 100644 (file)
@@ -187,7 +187,10 @@ static void wpa_priv_get_scan_results2(struct wpa_priv_interface *iface,
        int val;
        size_t i;
 
-       res = iface->driver->get_scan_results2(iface->drv_priv);
+       if (iface->driver->get_scan_results)
+               res = iface->driver->get_scan_results(iface->drv_priv, NULL);
+       else
+               res = iface->driver->get_scan_results2(iface->drv_priv);
        if (res == NULL)
                goto fail;
 
@@ -231,7 +234,7 @@ static void wpa_priv_cmd_get_scan_results(struct wpa_priv_interface *iface,
        if (iface->drv_priv == NULL)
                return;
 
-       if (iface->driver->get_scan_results2)
+       if (iface->driver->get_scan_results || iface->driver->get_scan_results2)
                wpa_priv_get_scan_results2(iface, from, fromlen);
        else
                sendto(iface->fd, "", 0, 0, (struct sockaddr *) from, fromlen);
index d52ce1efd3edbf665059cfe63179a2679a380ce9..ab71e2f2736b798d0805deb022b2b21617daa3fb 100644 (file)
@@ -890,7 +890,7 @@ void wpa_supplicant_reset_bgscan(struct wpa_supplicant *wpa_s)
                        struct wpa_scan_results *scan_res;
                        wpa_s->bgscan_ssid = wpa_s->current_ssid;
                        scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
-                                                                  0);
+                                                                  0, NULL);
                        if (scan_res) {
                                bgscan_notify_scan(wpa_s, scan_res);
                                wpa_scan_results_free(scan_res);
@@ -2900,7 +2900,8 @@ static void ibss_mesh_select_40mhz(struct wpa_supplicant *wpa_s,
        if (obss_scan) {
                struct wpa_scan_results *scan_res;
 
-               scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
+               scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0,
+                                                          NULL);
                if (scan_res == NULL) {
                        /* Back to HT20 */
                        freq->sec_channel_offset = 0;
@@ -9301,17 +9302,21 @@ int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
 
 
 struct wpa_scan_results *
-wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
+wpa_drv_get_scan_results(struct wpa_supplicant *wpa_s, const u8 *bssid)
 {
        struct wpa_scan_results *scan_res;
 #ifdef CONFIG_TESTING_OPTIONS
        size_t idx;
 #endif /* CONFIG_TESTING_OPTIONS */
 
-       if (!wpa_s->driver->get_scan_results2)
+       if (wpa_s->driver->get_scan_results)
+               scan_res = wpa_s->driver->get_scan_results(wpa_s->drv_priv,
+                                                          bssid);
+       else if (wpa_s->driver->get_scan_results2)
+               scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
+       else
                return NULL;
 
-       scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
 
 #ifdef CONFIG_TESTING_OPTIONS
        for (idx = 0; scan_res && idx < scan_res->num; idx++) {
index 16463a47c52f432e701f0f966514c47245f778c5..eea854899665f7d6c933bc2354aff757b00e54bc 100644 (file)
@@ -449,7 +449,7 @@ static int wpa_supplicant_get_beacon_ie(void *ctx)
 
        /* No WPA/RSN IE found in the cached scan results. Try to get updated
         * scan results from the driver. */
-       if (wpa_supplicant_update_scan_results(wpa_s) < 0)
+       if (wpa_supplicant_update_scan_results(wpa_s, wpa_s->bssid) < 0)
                return -1;
 
        return wpa_get_beacon_ie(wpa_s);