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>
This commit is contained in:
Jouni Malinen 2016-12-03 19:26:47 +02:00
parent 2a1cf26ecf
commit cfadab269f
2 changed files with 36 additions and 41 deletions

View 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) {

View 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",