station: Split autoconnect state into two sub states

The auto-connect state will now consist of the two phases:
STATION_STATE_AUTOCONNECT_QUICK and STATION_STATE_AUTOCONNECT_FULL.
The auto-connect will always start with STATION_STATE_AUTOCONNECT_QUICK
and then transition into STATION_STATE_AUTOCONNECT_FULL if no
connection has been established. During STATION_STATE_AUTOCONNECT_QUICK
phase we take advantage of the wireless scans with the limited number
of channels on which the known networks have been observed before.
This approach allows to shorten the time required for the network
sweeps, therefore decreases the connection latency if the connection
is possible. Thereafter, if no connection has been established after
the first phase we transition into STATION_STATE_AUTOCONNECT_FULL and
do the periodic scan just like we did before the split in
STATION_STATE_AUTOCONNECT state.
This commit is contained in:
Tim Kourt 2019-03-22 14:17:45 -07:00 committed by Denis Kenzior
parent 405785cd0b
commit 734c9ad2f6
3 changed files with 37 additions and 20 deletions

View File

@ -105,12 +105,19 @@ struct network *station_get_connected_network(struct station *station)
bool station_is_busy(struct station *station)
{
if (station->state != STATION_STATE_DISCONNECTED &&
station->state != STATION_STATE_AUTOCONNECT)
station->state != STATION_STATE_AUTOCONNECT_FULL &&
station->state != STATION_STATE_AUTOCONNECT_QUICK)
return true;
return false;
}
static bool station_is_autoconnecting(struct station *station)
{
return station->state == STATION_STATE_AUTOCONNECT_FULL ||
station->state == STATION_STATE_AUTOCONNECT_QUICK;
}
struct autoconnect_entry {
uint16_t rank;
struct network *network;
@ -615,7 +622,7 @@ static bool new_scan_results(int err, struct l_queue *bss_list, void *userdata)
if (err)
return false;
autoconnect = station_get_state(station) == STATION_STATE_AUTOCONNECT;
autoconnect = station_is_autoconnecting(station);
station_set_scan_results(station, bss_list, autoconnect);
if (autoconnect)
@ -679,8 +686,10 @@ static const char *station_state_to_string(enum station_state state)
switch (state) {
case STATION_STATE_DISCONNECTED:
return "disconnected";
case STATION_STATE_AUTOCONNECT:
return "autoconnect";
case STATION_STATE_AUTOCONNECT_QUICK:
return "autoconnect_quick";
case STATION_STATE_AUTOCONNECT_FULL:
return "autoconnect_full";
case STATION_STATE_CONNECTING:
return "connecting";
case STATION_STATE_CONNECTED:
@ -705,15 +714,16 @@ static void station_enter_state(struct station *station,
station_state_to_string(station->state),
station_state_to_string(state));
disconnected = station->state <= STATION_STATE_AUTOCONNECT;
disconnected = !station_is_busy(station);
if ((disconnected && state > STATION_STATE_AUTOCONNECT) ||
if ((disconnected && state > STATION_STATE_AUTOCONNECT_FULL) ||
(!disconnected && state != station->state))
l_dbus_property_changed(dbus, netdev_get_path(station->netdev),
IWD_STATION_INTERFACE, "State");
switch (state) {
case STATION_STATE_AUTOCONNECT:
case STATION_STATE_AUTOCONNECT_QUICK:
case STATION_STATE_AUTOCONNECT_FULL:
scan_periodic_start(index, periodic_scan_trigger,
new_scan_results, station);
break;
@ -765,9 +775,9 @@ bool station_set_autoconnect(struct station *station, bool autoconnect)
station->autoconnect = autoconnect;
if (station->state == STATION_STATE_DISCONNECTED && autoconnect)
station_enter_state(station, STATION_STATE_AUTOCONNECT);
station_enter_state(station, STATION_STATE_AUTOCONNECT_QUICK);
if (station->state == STATION_STATE_AUTOCONNECT && !autoconnect)
if (station_is_autoconnecting(station) && !autoconnect)
station_enter_state(station, STATION_STATE_DISCONNECTED);
return true;
@ -819,7 +829,7 @@ static void station_disassociated(struct station *station)
station_enter_state(station, STATION_STATE_DISCONNECTED);
if (station->autoconnect)
station_enter_state(station, STATION_STATE_AUTOCONNECT);
station_enter_state(station, STATION_STATE_AUTOCONNECT_QUICK);
}
static void station_connect_cb(struct netdev *netdev, enum netdev_result result,
@ -2002,7 +2012,7 @@ static void station_disconnect_cb(struct netdev *netdev, bool success,
station_enter_state(station, STATION_STATE_DISCONNECTED);
if (station->autoconnect)
station_enter_state(station, STATION_STATE_AUTOCONNECT);
station_enter_state(station, STATION_STATE_AUTOCONNECT_QUICK);
}
int station_disconnect(struct station *station)
@ -2044,8 +2054,7 @@ static struct l_dbus_message *station_dbus_disconnect(struct l_dbus *dbus,
*/
station_set_autoconnect(station, false);
if (station->state == STATION_STATE_AUTOCONNECT ||
station->state == STATION_STATE_DISCONNECTED)
if (!station_is_busy(station))
return l_dbus_message_new_method_return(message);
result = station_disconnect(station);
@ -2389,11 +2398,13 @@ static bool station_property_get_state(struct l_dbus *dbus,
void *user_data)
{
struct station *station = user_data;
const char *statestr = station_state_to_string(station->state);
const char *statestr;
/* Special case. For now we treat AUTOCONNECT as disconnected */
if (station->state == STATION_STATE_AUTOCONNECT)
if (!station_is_busy(station))
/* Special case. For now we treat AUTOCONNECT as disconnected */
statestr = "disconnected";
else
statestr = station_state_to_string(station->state);
l_dbus_message_builder_append_basic(builder, 's', statestr);
return true;

View File

@ -30,9 +30,14 @@ struct scan_bss;
struct network;
enum station_state {
STATION_STATE_DISCONNECTED, /* Disconnected, no auto-connect */
STATION_STATE_AUTOCONNECT, /* Disconnected, try auto-connect */
STATION_STATE_CONNECTING, /* Connecting */
/* Disconnected, no auto-connect */
STATION_STATE_DISCONNECTED,
/* Disconnected, try auto-connect with quick scan */
STATION_STATE_AUTOCONNECT_QUICK,
/* Disconnected, try auto-connect with full scan */
STATION_STATE_AUTOCONNECT_FULL,
/* Connecting */
STATION_STATE_CONNECTING,
STATION_STATE_CONNECTED,
STATION_STATE_DISCONNECTING,
STATION_STATE_ROAMING

View File

@ -517,7 +517,8 @@ static void wsc_check_can_connect(struct wsc *wsc, struct scan_bss *target)
station_state_watch,
wsc, NULL);
return;
case STATION_STATE_AUTOCONNECT:
case STATION_STATE_AUTOCONNECT_QUICK:
case STATION_STATE_AUTOCONNECT_FULL:
case STATION_STATE_ROAMING:
l_warn("wsc_check_can_connect: invalid station state");
break;