3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2024-12-22 21:22:37 +01:00

station: Trigger autoconnect only on last subset

DBus scan is performed in several subsets.  In certain corner-case
circumstances it would be possible for autoconnect to run after each
subset scan.  Instead, trigger autoconnect only after the dbus scan
completes.

This also works around a condition where ANQP results could trigger
autoconnect too early.
This commit is contained in:
Denis Kenzior 2021-09-16 14:00:01 -05:00
parent 17827f1ff9
commit 64923913c2

View File

@ -114,6 +114,7 @@ struct station {
bool ap_directed_roaming : 1; bool ap_directed_roaming : 1;
bool scanning : 1; bool scanning : 1;
bool autoconnect : 1; bool autoconnect : 1;
bool autoconnect_can_start : 1;
}; };
struct anqp_entry { struct anqp_entry {
@ -244,6 +245,9 @@ static void station_autoconnect_start(struct station *station)
{ {
l_debug(""); l_debug("");
if (!station->autoconnect_can_start)
return;
if (!station_is_autoconnecting(station)) if (!station_is_autoconnecting(station))
return; return;
@ -256,6 +260,7 @@ static void station_autoconnect_start(struct station *station)
station->autoconnect_list = l_queue_new(); station->autoconnect_list = l_queue_new();
station_network_foreach(station, network_add_foreach, station); station_network_foreach(station, network_add_foreach, station);
station_autoconnect_next(station); station_autoconnect_next(station);
station->autoconnect_can_start = false;
} }
static void bss_free(void *data) static void bss_free(void *data)
@ -724,7 +729,7 @@ void station_set_scan_results(struct station *station,
l_hashmap_foreach_remove(station->networks, process_network, station); l_hashmap_foreach_remove(station->networks, process_network, station);
if (trigger_autoconnect) station->autoconnect_can_start = trigger_autoconnect;
station_autoconnect_start(station); station_autoconnect_start(station);
} }
@ -3144,10 +3149,16 @@ static struct l_dbus_message *station_dbus_get_hidden_access_points(
return reply; return reply;
} }
static void station_dbus_scan_done(struct station *station) static void station_dbus_scan_done(struct station *station,
bool try_autoconnect)
{ {
station->dbus_scan_id = 0; station->dbus_scan_id = 0;
station_property_set_scanning(station, false); station_property_set_scanning(station, false);
if (try_autoconnect) {
station->autoconnect_can_start = true;
station_autoconnect_start(station);
}
} }
static void station_dbus_scan_triggered(int err, void *user_data) static void station_dbus_scan_triggered(int err, void *user_data)
@ -3164,7 +3175,7 @@ static void station_dbus_scan_triggered(int err, void *user_data)
dbus_pending_reply(&station->scan_pending, reply); dbus_pending_reply(&station->scan_pending, reply);
} }
station_dbus_scan_done(station); station_dbus_scan_done(station, true);
return; return;
} }
@ -3192,18 +3203,18 @@ static bool station_dbus_scan_results(int err, struct l_queue *bss_list,
bool last_subset; bool last_subset;
if (err) { if (err) {
station_dbus_scan_done(station); station_dbus_scan_done(station, true);
return false; return false;
} }
station_set_scan_results(station, bss_list, freqs, true);
last_subset = next_idx >= L_ARRAY_SIZE(station->scan_freqs_order) || last_subset = next_idx >= L_ARRAY_SIZE(station->scan_freqs_order) ||
station->scan_freqs_order[next_idx] == NULL; station->scan_freqs_order[next_idx] == NULL;
station->dbus_scan_subset_idx = next_idx; station->dbus_scan_subset_idx = next_idx;
station_set_scan_results(station, bss_list, freqs, false);
if (last_subset || !station_dbus_scan_subset(station)) if (last_subset || !station_dbus_scan_subset(station))
station_dbus_scan_done(station); station_dbus_scan_done(station, true);
return true; return true;
} }
@ -3941,7 +3952,7 @@ static void station_debug_scan_triggered(int err, void *user_data)
dbus_pending_reply(&station->scan_pending, reply); dbus_pending_reply(&station->scan_pending, reply);
} }
station_dbus_scan_done(station); station_dbus_scan_done(station, false);
return; return;
} }
@ -3964,12 +3975,12 @@ static bool station_debug_scan_results(int err, struct l_queue *bss_list,
struct station *station = userdata; struct station *station = userdata;
if (err) { if (err) {
station_dbus_scan_done(station); station_dbus_scan_done(station, false);
return false; return false;
} }
station_set_scan_results(station, bss_list, freqs, false); station_set_scan_results(station, bss_list, freqs, false);
station_dbus_scan_done(station); station_dbus_scan_done(station, false);
return true; return true;
} }