]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
nl80211: Move duplicate scan result removal to bss.c
authorJouni Malinen <j@w1.fi>
Sat, 3 Dec 2016 17:26:47 +0000 (19:26 +0200)
committerJouni Malinen <j@w1.fi>
Sat, 3 Dec 2016 17:26:47 +0000 (19:26 +0200)
The way the removal of duplicated (one per frequency) BSS entries in the
cfg80211 scan results were removed in driver_nl80211_scan.c
bss_info_handler() depended on having the full scan results available to
allow iteration through the other entries. This is problematic for the
goal of being able to optimize memory allocations for scan result
fetching in a manner that would not build the full result buffer in
memory.

Move this duplicate removal into bss.c since it has sufficient
information available for doing the same determination of which one of
two BSS entries is more current.

Signed-off-by: Jouni Malinen <j@w1.fi>
src/drivers/driver_nl80211_scan.c
wpa_supplicant/bss.c

index 4d16428f70861af31af2cce70871e279788d665b..f07ef874ecd0f9f9f6ae7493bd020e69ea72c9f1 100644 (file)
@@ -651,7 +651,6 @@ int bss_info_handler(struct nl_msg *msg, void *arg)
        const u8 *ie, *beacon_ie;
        size_t ie_len, beacon_ie_len;
        u8 *pos;
-       size_t i;
 
        nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
                  genlmsg_attrlen(gnlh, 0), NULL);
@@ -759,46 +758,6 @@ int bss_info_handler(struct nl_msg *msg, void *arg)
                }
        }
 
-       /*
-        * cfg80211 maintains separate BSS table entries for APs if the same
-        * BSSID,SSID pair is seen on multiple channels. wpa_supplicant does
-        * not use frequency as a separate key in the BSS table, so filter out
-        * duplicated entries. Prefer associated BSS entry in such a case in
-        * order to get the correct frequency into the BSS table. Similarly,
-        * prefer newer entries over older.
-        */
-       for (i = 0; i < res->num; i++) {
-               const u8 *s1, *s2;
-               if (os_memcmp(res->res[i]->bssid, r->bssid, ETH_ALEN) != 0)
-                       continue;
-
-               s1 = get_ie((u8 *) (res->res[i] + 1),
-                           res->res[i]->ie_len, WLAN_EID_SSID);
-               s2 = get_ie((u8 *) (r + 1), r->ie_len, WLAN_EID_SSID);
-               if (s1 == NULL || s2 == NULL || s1[1] != s2[1] ||
-                   os_memcmp(s1, s2, 2 + s1[1]) != 0)
-                       continue;
-
-               /* Same BSSID,SSID was already included in scan results */
-               wpa_printf(MSG_DEBUG,
-                          "nl80211: Remove duplicated scan result for " MACSTR
-                          " (assoc/age/freq prev=%d/%d/%d new=%d/%d/%d)",
-                          MAC2STR(r->bssid),
-                          !!(res->res[i]->flags & WPA_SCAN_ASSOCIATED),
-                          res->res[i]->age, res->res[i]->freq,
-                          !!(r->flags & WPA_SCAN_ASSOCIATED),
-                          r->age, r->freq);
-
-               if (((r->flags & WPA_SCAN_ASSOCIATED) &&
-                    !(res->res[i]->flags & WPA_SCAN_ASSOCIATED)) ||
-                   r->age < res->res[i]->age) {
-                       os_free(res->res[i]);
-                       res->res[i] = r;
-               } else
-                       os_free(r);
-               return NL_SKIP;
-       }
-
        tmp = os_realloc_array(res->res, res->num + 1,
                               sizeof(struct wpa_scan_res *));
        if (tmp == NULL) {
index 3a8778db9058d0852c9778391b2649d3cd677798..44a9a7b2c4a95731e716cb082dba37e375b28325 100644 (file)
@@ -595,6 +595,42 @@ wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
 {
        u32 changes;
 
+       if (bss->last_update_idx == wpa_s->bss_update_idx) {
+               struct os_reltime update_time;
+
+               /*
+                * Some drivers (e.g., cfg80211) include multiple BSS entries
+                * for the same BSS if that BSS's channel changes. The BSS list
+                * implementation in wpa_supplicant does not do that and we need
+                * to filter out the obsolete results here to make sure only the
+                * most current BSS information remains in the table.
+                */
+               wpa_printf(MSG_DEBUG, "BSS: " MACSTR
+                          " has multiple entries in the scan results - select the most current one",
+                          MAC2STR(bss->bssid));
+               calculate_update_time(fetch_time, res->age, &update_time);
+               wpa_printf(MSG_DEBUG,
+                          "Previous last_update: %u.%06u (freq %d%s)",
+                          (unsigned int) bss->last_update.sec,
+                          (unsigned int) bss->last_update.usec,
+                          bss->freq,
+                          (bss->flags & WPA_BSS_ASSOCIATED) ? " assoc" : "");
+               wpa_printf(MSG_DEBUG, "New last_update: %u.%06u (freq %d%s)",
+                          (unsigned int) update_time.sec,
+                          (unsigned int) update_time.usec,
+                          res->freq,
+                          (res->flags & WPA_SCAN_ASSOCIATED) ? " assoc" : "");
+               if ((bss->flags & WPA_BSS_ASSOCIATED) ||
+                   (!(res->flags & WPA_SCAN_ASSOCIATED) &&
+                    !os_reltime_before(&bss->last_update, &update_time))) {
+                       wpa_printf(MSG_DEBUG,
+                                  "Ignore this BSS entry since the previous update looks more current");
+                       return bss;
+               }
+               wpa_printf(MSG_DEBUG,
+                          "Accept this BSS entry since it looks more current than the previous update");
+       }
+
        changes = wpa_bss_compare_res(bss, res);
        if (changes & WPA_BSS_FREQ_CHANGED_FLAG)
                wpa_printf(MSG_DEBUG, "BSS: " MACSTR " changed freq %d --> %d",