aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2016-12-03 17:26:47 (GMT)
committerJouni Malinen <j@w1.fi>2016-12-03 17:26:47 (GMT)
commitcfadab269f78e1f7f197d07dded70c138f651be1 (patch)
tree670fe4239adb5359e58618ddf528ca0c15d7d117
parent2a1cf26ecf08060572c4023a55d9c6f9d91de539 (diff)
downloadhostap-cfadab269f78e1f7f197d07dded70c138f651be1.zip
hostap-cfadab269f78e1f7f197d07dded70c138f651be1.tar.gz
hostap-cfadab269f78e1f7f197d07dded70c138f651be1.tar.bz2
nl80211: Move duplicate scan result removal to bss.c
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>
-rw-r--r--src/drivers/driver_nl80211_scan.c41
-rw-r--r--wpa_supplicant/bss.c36
2 files changed, 36 insertions, 41 deletions
diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c
index 4d16428..f07ef87 100644
--- a/src/drivers/driver_nl80211_scan.c
+++ b/src/drivers/driver_nl80211_scan.c
@@ -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) {
diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c
index 3a8778d..44a9a7b 100644
--- a/wpa_supplicant/bss.c
+++ b/wpa_supplicant/bss.c
@@ -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",