3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2024-11-22 14:49:24 +01:00

station: remove early FT-over-DS action

IWD was optimizing FT-over-DS by authenticating to multiple BSS's
at the time of connecting which then made future roams slightly
faster since they could jump right into association. So far this
hasn't posed a problem but it was reported that some AP's actually
enforce a reassociation timeout (included in 4-way handshake).

Hostapd itself does no such enforcement but anything external to
hostapd could monitor FT events and clear the cache if any exceeded
this timeout.

For now remove the early action frames and treat FT-over-DS the
same as FT-over-Air. In the future we could parse the reassociation
timeout, batch out FT-Action frames and track responses but for the
time being this just fix the issue at a small performance cost.
This commit is contained in:
James Prestwood 2022-12-14 13:26:57 -08:00 committed by Denis Kenzior
parent 6a616df125
commit a1d30fe1cb

View File

@ -1973,47 +1973,6 @@ static bool station_can_fast_transition(struct handshake_state *hs,
return true; return true;
} }
static void station_ft_ds_action_start(struct station *station)
{
struct handshake_state *hs = netdev_get_handshake(station->netdev);
uint16_t mdid;
const struct l_queue_entry *entry;
struct scan_bss *bss;
struct ie_rsn_info rsn_info;
if (!station_can_fast_transition(hs, station->connected_bss) ||
!(hs->mde[4] & 1))
return;
if (ie_parse_mobility_domain_from_data(hs->mde, hs->mde[1] + 2,
&mdid, NULL, NULL) < 0)
return;
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
*/
ft_action(netdev_get_ifindex(station->netdev),
station->connected_bss->frequency, bss);
}
}
static void station_roamed(struct station *station) static void station_roamed(struct station *station)
{ {
station->roam_scan_full = false; station->roam_scan_full = false;
@ -2042,8 +2001,6 @@ static void station_roamed(struct station *station)
l_queue_clear(station->roam_bss_list, l_free); l_queue_clear(station->roam_bss_list, l_free);
station_ft_ds_action_start(station);
station_enter_state(station, STATION_STATE_CONNECTED); station_enter_state(station, STATION_STATE_CONNECTED);
} }
@ -2297,7 +2254,7 @@ static bool station_ft_work_ready(struct wiphy_radio_work_item *item)
ret = ft_associate(netdev_get_ifindex(station->netdev), bss->addr); ret = ft_associate(netdev_get_ifindex(station->netdev), bss->addr);
if (ret == -ENOENT) { if (ret == -ENOENT) {
station_debug_event(station, "ft-over-air-roam-failed"); station_debug_event(station, "ft-roam-failed");
try_next: try_next:
station_transition_start(station); station_transition_start(station);
return true; return true;
@ -2327,7 +2284,6 @@ static bool station_fast_transition(struct station *station,
const struct network_info *info = network_get_info(connected); const struct network_info *info = network_get_info(connected);
const struct iovec *vendor_ies; const struct iovec *vendor_ies;
size_t iov_elems = 0; size_t iov_elems = 0;
int ret;
/* Rebuild handshake RSN for target AP */ /* Rebuild handshake RSN for target AP */
if (station_build_handshake_rsn(hs, station->wiphy, if (station_build_handshake_rsn(hs, station->wiphy,
@ -2338,34 +2294,17 @@ static bool station_fast_transition(struct station *station,
vendor_ies = network_info_get_extra_ies(info, bss, &iov_elems); vendor_ies = network_info_get_extra_ies(info, bss, &iov_elems);
handshake_state_set_vendor_ies(hs, vendor_ies, iov_elems); handshake_state_set_vendor_ies(hs, vendor_ies, iov_elems);
if ((hs->mde[4] & 1)) { /* Both ft_action/ft_authenticate will gate the associate work item */
ret = ft_associate(netdev_get_ifindex(station->netdev), if ((hs->mde[4] & 1))
bss->addr); ft_action(netdev_get_ifindex(station->netdev),
/* No action responses from this BSS, try over air */ station->connected_bss->frequency, bss);
if (ret == -ENOENT) { else
station_debug_event(station, "try-ft-over-air");
goto try_over_air;
} else if (ret < 0)
return false;
station->connected_bss = bss;
station->preparing_roam = false;
station_enter_state(station, STATION_STATE_FT_ROAMING);
return true;
} else {
try_over_air:
/*
* Send FT-Authenticate and insert a work item which will be
* gated until authentication completes
*/
ft_authenticate(netdev_get_ifindex(station->netdev), bss); ft_authenticate(netdev_get_ifindex(station->netdev), bss);
wiphy_radio_work_insert(station->wiphy, &station->ft_work, wiphy_radio_work_insert(station->wiphy, &station->ft_work,
WIPHY_WORK_PRIORITY_CONNECT, &ft_work_ops); WIPHY_WORK_PRIORITY_CONNECT, &ft_work_ops);
return true; return true;
}
} }
static bool station_try_next_transition(struct station *station, static bool station_try_next_transition(struct station *station,
@ -3117,8 +3056,6 @@ static void station_connect_ok(struct station *station)
l_warn("Could not request neighbor report"); l_warn("Could not request neighbor report");
} }
station_ft_ds_action_start(station);
network_connected(station->connected_network); network_connected(station->connected_network);
if (station->netconfig) { if (station->netconfig) {