mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-29 22:19:23 +01:00
station: send FT-over-DS actions upon connection
Roam times can be slightly improved by sending out the FT-over-DS action frames to any BSS in the mobility domain immediately after connecting. This preauthenticates IWD to each AP which means Reassociation can happen right away when a roam is needed. When a roam is needed station_transition_start will first try FT-over-DS (if supported) via netdev_fast_transtion_over_ds. The return is checked and if netdev has no cached entries FT-over-Air will be used instead.
This commit is contained in:
parent
78fe1cc0ef
commit
7385e2c90e
109
src/station.c
109
src/station.c
@ -1720,45 +1720,6 @@ static bool bss_match_bssid(const void *a, const void *b)
|
|||||||
return !memcmp(bss->addr, bssid, sizeof(bss->addr));
|
return !memcmp(bss->addr, bssid, sizeof(bss->addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void station_fast_transition_ds_cb(struct netdev *netdev,
|
|
||||||
uint16_t status, const uint8_t *bssid,
|
|
||||||
void *user_data)
|
|
||||||
{
|
|
||||||
struct station *station = user_data;
|
|
||||||
struct scan_bss *bss;
|
|
||||||
|
|
||||||
if (status != 0)
|
|
||||||
goto failed;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO: In the future it may be desired to start sending out these
|
|
||||||
* FT-over-DS action frames at the time of connecting then be able to
|
|
||||||
* roam immediately when required. If this is being done we can simply
|
|
||||||
* bail out now as ft already caches the entires. But since this was
|
|
||||||
* initiated due to a need to roam, do so now.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Make sure we still have our BSS */
|
|
||||||
bss = l_queue_find(station->bss_list, bss_match_bssid, bssid);
|
|
||||||
if (!bss)
|
|
||||||
goto failed;
|
|
||||||
|
|
||||||
l_debug("Starting FT-over-DS roam");
|
|
||||||
|
|
||||||
if (netdev_fast_transition_over_ds(station->netdev, bss,
|
|
||||||
station_fast_transition_cb) < 0)
|
|
||||||
goto failed;
|
|
||||||
|
|
||||||
station->connected_bss = bss;
|
|
||||||
station->preparing_roam = false;
|
|
||||||
station_enter_state(station, STATION_STATE_ROAMING);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
failed:
|
|
||||||
station_roam_retry(station);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void station_preauthenticate_cb(struct netdev *netdev,
|
static void station_preauthenticate_cb(struct netdev *netdev,
|
||||||
enum netdev_result result,
|
enum netdev_result result,
|
||||||
const uint8_t *pmk, void *user_data)
|
const uint8_t *pmk, void *user_data)
|
||||||
@ -1849,6 +1810,7 @@ static void station_transition_start(struct station *station,
|
|||||||
enum security security = network_get_security(connected);
|
enum security security = network_get_security(connected);
|
||||||
struct handshake_state *new_hs;
|
struct handshake_state *new_hs;
|
||||||
struct ie_rsn_info cur_rsne, target_rsne;
|
struct ie_rsn_info cur_rsne, target_rsne;
|
||||||
|
int ret;
|
||||||
|
|
||||||
l_debug("%u, target %s", netdev_get_ifindex(station->netdev),
|
l_debug("%u, target %s", netdev_get_ifindex(station->netdev),
|
||||||
util_address_to_string(bss->addr));
|
util_address_to_string(bss->addr));
|
||||||
@ -1868,19 +1830,21 @@ static void station_transition_start(struct station *station,
|
|||||||
|
|
||||||
/* FT-over-DS can be better suited for these situations */
|
/* FT-over-DS can be better suited for these situations */
|
||||||
if ((hs->mde[4] & 1) && station->signal_low) {
|
if ((hs->mde[4] & 1) && station->signal_low) {
|
||||||
if (netdev_fast_transition_over_ds_action(
|
ret = netdev_fast_transition_over_ds(station->netdev,
|
||||||
station->netdev, bss,
|
bss, station_fast_transition_cb);
|
||||||
station_fast_transition_ds_cb,
|
/* No action responses from this BSS, try over air */
|
||||||
station) < 0) {
|
if (ret == -ENOENT)
|
||||||
|
goto try_over_air;
|
||||||
|
else if (ret < 0) {
|
||||||
|
/*
|
||||||
|
* If we are here FT-over-air will not work
|
||||||
|
* either (identical checks) so try again later.
|
||||||
|
*/
|
||||||
station_roam_retry(station);
|
station_roam_retry(station);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Set connected_bss/preparing_roam/state only on a
|
|
||||||
* successful FT-over-DS action frame response
|
|
||||||
*/
|
|
||||||
return;
|
|
||||||
} else {
|
} else {
|
||||||
|
try_over_air:
|
||||||
if (netdev_fast_transition(station->netdev, bss,
|
if (netdev_fast_transition(station->netdev, bss,
|
||||||
station_fast_transition_cb) < 0) {
|
station_fast_transition_cb) < 0) {
|
||||||
station_roam_failed(station);
|
station_roam_failed(station);
|
||||||
@ -2512,10 +2476,42 @@ static void station_connect_dbus_reply(struct station *station,
|
|||||||
dbus_pending_reply(&station->connect_pending, reply);
|
dbus_pending_reply(&station->connect_pending, reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void station_ft_ds_action_start(struct station *station, uint16_t mdid)
|
||||||
|
{
|
||||||
|
const struct l_queue_entry *entry;
|
||||||
|
struct scan_bss *bss;
|
||||||
|
struct ie_rsn_info rsn_info;
|
||||||
|
|
||||||
|
for (entry = network_bss_list_get_entries(station->connected_network);
|
||||||
|
entry; entry = entry->next) {
|
||||||
|
bss = entry->data;
|
||||||
|
|
||||||
|
if (bss == station->connected_bss)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (mdid != l_get_le16(bss->mde))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (scan_bss_get_rsn_info(bss, &rsn_info) < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!IE_AKM_IS_FT(rsn_info.akm_suites))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fire and forget. Netdev will maintain a cache of responses and
|
||||||
|
* when the time comes these can be referenced for a roam
|
||||||
|
*/
|
||||||
|
netdev_fast_transition_over_ds_action(station->netdev, bss,
|
||||||
|
NULL, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void station_connect_cb(struct netdev *netdev, enum netdev_result result,
|
static void station_connect_cb(struct netdev *netdev, enum netdev_result result,
|
||||||
void *event_data, void *user_data)
|
void *event_data, void *user_data)
|
||||||
{
|
{
|
||||||
struct station *station = user_data;
|
struct station *station = user_data;
|
||||||
|
struct handshake_state *hs = netdev_get_handshake(netdev);
|
||||||
|
|
||||||
l_debug("%u, result: %d", netdev_get_ifindex(station->netdev), result);
|
l_debug("%u, result: %d", netdev_get_ifindex(station->netdev), result);
|
||||||
|
|
||||||
@ -2566,6 +2562,21 @@ static void station_connect_cb(struct netdev *netdev, enum netdev_result result,
|
|||||||
l_warn("Could not request neighbor report");
|
l_warn("Could not request neighbor report");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this network supports FT-over-DS send initial action frames now
|
||||||
|
* to prepare for future roams.
|
||||||
|
*/
|
||||||
|
if (station_can_fast_transition(hs, station->connected_bss) &&
|
||||||
|
(hs->mde[4] & 1)) {
|
||||||
|
uint16_t mdid;
|
||||||
|
|
||||||
|
if (ie_parse_mobility_domain_from_data(hs->mde, hs->mde[1] + 2,
|
||||||
|
&mdid, NULL, NULL) < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
station_ft_ds_action_start(station, mdid);
|
||||||
|
}
|
||||||
|
|
||||||
network_connected(station->connected_network);
|
network_connected(station->connected_network);
|
||||||
|
|
||||||
if (station->netconfig)
|
if (station->netconfig)
|
||||||
|
Loading…
Reference in New Issue
Block a user