mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-12-22 21:22:37 +01:00
station: Start removing scan results based on age
Previously, the scan results were disregarded once the new ones were available. To enable the scan scenarios where the new scan results are delivered in parts, we introduce a concept of aging BSSs and will remove them based on retention time.
This commit is contained in:
parent
170125aa01
commit
8881910662
@ -94,6 +94,7 @@ struct scan_results {
|
||||
uint32_t ifindex;
|
||||
struct l_queue *bss_list;
|
||||
struct scan_freq_set *freqs;
|
||||
uint64_t time_stamp;
|
||||
};
|
||||
|
||||
static bool start_next_scan_request(struct scan_context *sc);
|
||||
@ -1130,6 +1131,8 @@ static void get_scan_callback(struct l_genl_msg *msg, void *user_data)
|
||||
return;
|
||||
}
|
||||
|
||||
bss->time_stamp = results->time_stamp;
|
||||
|
||||
scan_bss_compute_rank(bss);
|
||||
l_queue_insert(results->bss_list, bss, scan_bss_rank_compare, NULL);
|
||||
}
|
||||
@ -1364,6 +1367,7 @@ static void scan_notify(struct l_genl_msg *msg, void *user_data)
|
||||
results = l_new(struct scan_results, 1);
|
||||
results->wiphy = attr_wiphy;
|
||||
results->ifindex = attr_ifindex;
|
||||
results->time_stamp = l_time_now();
|
||||
|
||||
scan_parse_new_scan_results(msg, results);
|
||||
|
||||
|
@ -60,6 +60,7 @@ struct scan_bss {
|
||||
uint16_t rank;
|
||||
uint8_t ht_ie[28];
|
||||
uint8_t vht_ie[14];
|
||||
uint64_t time_stamp;
|
||||
bool mde_present : 1;
|
||||
bool cc_present : 1;
|
||||
bool cap_rm_neighbor_report : 1;
|
||||
|
117
src/station.c
117
src/station.c
@ -287,7 +287,7 @@ static struct network *station_add_seen_bss(struct station *station,
|
||||
const char *path;
|
||||
char ssid[33];
|
||||
|
||||
l_debug("Found BSS '%s' with SSID: %s, freq: %u, rank: %u, "
|
||||
l_debug("Processing BSS '%s' with SSID: %s, freq: %u, rank: %u, "
|
||||
"strength: %i",
|
||||
util_address_to_string(bss->addr),
|
||||
util_ssid_to_utf8(bss->ssid_len, bss->ssid),
|
||||
@ -354,58 +354,101 @@ static bool bss_match(const void *a, const void *b)
|
||||
return !memcmp(bss_a->addr, bss_b->addr, sizeof(bss_a->addr));
|
||||
}
|
||||
|
||||
/*
|
||||
* Used when scan results were obtained; either from passive scan running
|
||||
* inside station module or active scans running in other state machines, e.g.
|
||||
* wsc
|
||||
*/
|
||||
void station_set_scan_results(struct station *station, struct l_queue *bss_list,
|
||||
bool add_to_autoconnect)
|
||||
struct bss_expiration_data {
|
||||
struct scan_bss *connected_bss;
|
||||
uint64_t now;
|
||||
};
|
||||
|
||||
#define SCAN_RESULT_BSS_RETENTION_TIME (30 * 1000000)
|
||||
|
||||
static bool bss_free_if_expired(void *data, void *user_data)
|
||||
{
|
||||
struct scan_bss *bss = data;
|
||||
struct bss_expiration_data *expiration_data = user_data;
|
||||
|
||||
if (bss == expiration_data->connected_bss)
|
||||
/* Do not expire the currently connected BSS. */
|
||||
return false;
|
||||
|
||||
if (l_time_before(expiration_data->now,
|
||||
bss->time_stamp + SCAN_RESULT_BSS_RETENTION_TIME))
|
||||
return false;
|
||||
|
||||
bss_free(bss);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void station_bss_list_remove_expired_bsses(struct station *station)
|
||||
{
|
||||
struct bss_expiration_data data = {
|
||||
.now = l_time_now(),
|
||||
.connected_bss = station->connected_bss,
|
||||
};
|
||||
|
||||
l_queue_foreach_remove(station->bss_list, bss_free_if_expired, &data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Used when scan results were obtained; either from scan running
|
||||
* inside station module or scans running in other state machines, e.g. wsc
|
||||
*/
|
||||
void station_set_scan_results(struct station *station,
|
||||
struct l_queue *new_bss_list,
|
||||
bool add_to_autoconnect)
|
||||
{
|
||||
struct l_queue *old_bss_list = station->bss_list;
|
||||
struct network *network;
|
||||
const struct l_queue_entry *bss_entry;
|
||||
|
||||
station->bss_list = bss_list;
|
||||
|
||||
l_queue_clear(station->hidden_bss_list_sorted, NULL);
|
||||
struct network *network;
|
||||
|
||||
while ((network = l_queue_pop_head(station->networks_sorted)))
|
||||
network_bss_list_clear(network);
|
||||
|
||||
l_queue_clear(station->hidden_bss_list_sorted, NULL);
|
||||
|
||||
l_queue_destroy(station->autoconnect_list, l_free);
|
||||
station->autoconnect_list = l_queue_new();
|
||||
|
||||
for (bss_entry = l_queue_get_entries(bss_list); bss_entry;
|
||||
bss_entry = bss_entry->next) {
|
||||
station_bss_list_remove_expired_bsses(station);
|
||||
|
||||
for (bss_entry = l_queue_get_entries(station->bss_list); bss_entry;
|
||||
bss_entry = bss_entry->next) {
|
||||
struct scan_bss *old_bss = bss_entry->data;
|
||||
struct scan_bss *new_bss;
|
||||
|
||||
new_bss = l_queue_find(new_bss_list, bss_match, old_bss);
|
||||
if (new_bss) {
|
||||
if (old_bss == station->connected_bss)
|
||||
station->connected_bss = new_bss;
|
||||
|
||||
bss_free(old_bss);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (old_bss == station->connected_bss) {
|
||||
l_warn("Connected BSS not in scan results");
|
||||
station->connected_bss->rank = 0;
|
||||
}
|
||||
|
||||
l_queue_push_tail(new_bss_list, old_bss);
|
||||
}
|
||||
|
||||
l_queue_destroy(station->bss_list, NULL);
|
||||
|
||||
for (bss_entry = l_queue_get_entries(new_bss_list); bss_entry;
|
||||
bss_entry = bss_entry->next) {
|
||||
struct scan_bss *bss = bss_entry->data;
|
||||
struct network *network = station_add_seen_bss(station, bss);
|
||||
|
||||
if (network && add_to_autoconnect)
|
||||
station_add_autoconnect_bss(station, network, bss);
|
||||
if (!network || !add_to_autoconnect)
|
||||
continue;
|
||||
|
||||
station_add_autoconnect_bss(station, network, bss);
|
||||
}
|
||||
|
||||
if (station->connected_bss) {
|
||||
struct scan_bss *bss;
|
||||
|
||||
bss = l_queue_find(station->bss_list, bss_match,
|
||||
station->connected_bss);
|
||||
|
||||
if (!bss) {
|
||||
l_warn("Connected BSS not in scan results!");
|
||||
station->connected_bss->rank = 0;
|
||||
l_queue_push_tail(station->bss_list,
|
||||
station->connected_bss);
|
||||
network_bss_add(station->connected_network,
|
||||
station->connected_bss);
|
||||
l_queue_remove(old_bss_list, station->connected_bss);
|
||||
} else
|
||||
station->connected_bss = bss;
|
||||
}
|
||||
station->bss_list = new_bss_list;
|
||||
|
||||
l_hashmap_foreach_remove(station->networks, process_network, station);
|
||||
|
||||
l_queue_destroy(old_bss_list, bss_free);
|
||||
}
|
||||
|
||||
static void station_reconnect(struct station *station);
|
||||
|
Loading…
Reference in New Issue
Block a user