iwd.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/3] ft: gate FT-over-DS with a wiphy work item
@ 2022-12-14 21:26 James Prestwood
  2022-12-14 21:26 ` [PATCH 2/3] station: remove early FT-over-DS action James Prestwood
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: James Prestwood @ 2022-12-14 21:26 UTC (permalink / raw)
  To: iwd; +Cc: James Prestwood

Queue the FT action just like we do with FT Authenticate which makes
it able to be used the same way, i.e. call ft_action() then queue
the ft_associate work right away.

A timer was added to end the work item in case the target never
responds.
---
 src/ft.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 49 insertions(+), 9 deletions(-)

diff --git a/src/ft.c b/src/ft.c
index c2607a1b..f173099d 100644
--- a/src/ft.c
+++ b/src/ft.c
@@ -54,8 +54,12 @@ struct ft_info {
 	uint8_t *authenticator_ie;
 	uint8_t prev_bssid[6];
 	uint32_t frequency;
+	uint32_t ds_frequency;
 	uint32_t offchannel_id;
 
+	struct l_timeout *timeout;
+	struct wiphy_radio_work_item work;
+
 	struct ie_ft_info ft_info;
 
 	bool parsed : 1;
@@ -830,6 +834,11 @@ void __ft_rx_action(uint32_t ifindex, const uint8_t *frame, size_t frame_len)
 
 	info->parsed = true;
 
+	l_timeout_remove(info->timeout);
+	info->timeout = NULL;
+
+	wiphy_radio_work_done(netdev_get_wiphy(netdev), info->work.id);
+
 	return;
 
 ft_error:
@@ -868,6 +877,9 @@ static void ft_info_destroy(void *data)
 	if (info->authenticator_ie)
 		l_free(info->authenticator_ie);
 
+	if (info->timeout)
+		l_timeout_remove(info->timeout);
+
 	l_free(info);
 }
 
@@ -900,19 +912,17 @@ static void ft_prepare_handshake(struct ft_info *info,
 	handshake_state_derive_ptk(hs);
 }
 
-int ft_action(uint32_t ifindex, uint32_t freq, const struct scan_bss *target)
+static bool ft_send_action(struct wiphy_radio_work_item *work)
 {
-	struct netdev *netdev = netdev_find(ifindex);
+	struct ft_info *info = l_container_of(work, struct ft_info, work);
+	struct netdev *netdev = netdev_find(info->ifindex);
 	struct handshake_state *hs = netdev_get_handshake(netdev);
-	struct ft_info *info;
 	uint8_t ft_req[14];
 	struct iovec iov[5];
 	uint8_t ies[512];
 	size_t len;
 	int ret = -EINVAL;
 
-	info = ft_info_new(hs, target);
-
 	ft_req[0] = 6; /* FT category */
 	ft_req[1] = 1; /* FT Request action */
 	memcpy(ft_req + 2, info->spa, 6);
@@ -928,17 +938,47 @@ int ft_action(uint32_t ifindex, uint32_t freq, const struct scan_bss *target)
 	iov[1].iov_base = ies;
 	iov[1].iov_len = len;
 
-	ret = tx_frame(hs->ifindex, 0x00d0, freq, hs->aa, iov, 2);
+	ret = tx_frame(hs->ifindex, 0x00d0, info->ds_frequency, hs->aa, iov, 2);
 	if (ret < 0)
 		goto failed;
 
 	l_queue_push_tail(info_list, info);
 
-	return 0;
+	return false;
 
 failed:
-	l_free(info);
-	return ret;
+	l_debug("FT-over-DS action failed to "MAC, MAC_STR(hs->aa));
+
+	ft_info_destroy(info);
+	return true;
+}
+
+struct wiphy_radio_work_item_ops ft_ops = {
+	.do_work = ft_send_action,
+};
+
+static void ft_ds_timeout(struct l_timeout *timeout, void *user_data)
+{
+	struct ft_info *info = user_data;
+	struct netdev *netdev = netdev_find(info->ifindex);
+
+	wiphy_radio_work_done(netdev_get_wiphy(netdev), info->work.id);
+}
+
+int ft_action(uint32_t ifindex, uint32_t freq, const struct scan_bss *target)
+{
+	struct netdev *netdev = netdev_find(ifindex);
+	struct handshake_state *hs = netdev_get_handshake(netdev);
+	struct ft_info *info;
+
+	info = ft_info_new(hs, target);
+	info->ds_frequency = freq;
+	info->timeout = l_timeout_create_ms(200, ft_ds_timeout, info, NULL);
+
+	wiphy_radio_work_insert(netdev_get_wiphy(netdev), &info->work,
+				WIPHY_WORK_PRIORITY_FT, &ft_ops);
+
+	return 0;
 }
 
 void __ft_rx_authenticate(uint32_t ifindex, const uint8_t *frame,
-- 
2.34.3


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/3] station: remove early FT-over-DS action
  2022-12-14 21:26 [PATCH 1/3] ft: gate FT-over-DS with a wiphy work item James Prestwood
@ 2022-12-14 21:26 ` James Prestwood
  2022-12-14 21:26 ` [PATCH 3/3] auto-t: update testPSK-roam with changed FT behavior James Prestwood
  2022-12-14 22:15 ` [PATCH 1/3] ft: gate FT-over-DS with a wiphy work item Denis Kenzior
  2 siblings, 0 replies; 4+ messages in thread
From: James Prestwood @ 2022-12-14 21:26 UTC (permalink / raw)
  To: iwd; +Cc: James Prestwood

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.
---
 src/station.c | 79 ++++++---------------------------------------------
 1 file changed, 8 insertions(+), 71 deletions(-)

diff --git a/src/station.c b/src/station.c
index a467b4e9..9a646934 100644
--- a/src/station.c
+++ b/src/station.c
@@ -1973,47 +1973,6 @@ static bool station_can_fast_transition(struct handshake_state *hs,
 	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)
 {
 	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);
 
-	station_ft_ds_action_start(station);
-
 	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);
 	if (ret == -ENOENT) {
-		station_debug_event(station, "ft-over-air-roam-failed");
+		station_debug_event(station, "ft-roam-failed");
 try_next:
 		station_transition_start(station);
 		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 iovec *vendor_ies;
 	size_t iov_elems = 0;
-	int ret;
 
 	/* Rebuild handshake RSN for target AP */
 	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);
 	handshake_state_set_vendor_ies(hs, vendor_ies, iov_elems);
 
-	if ((hs->mde[4] & 1)) {
-		ret = ft_associate(netdev_get_ifindex(station->netdev),
-					bss->addr);
-		/* No action responses from this BSS, try over air */
-		if (ret == -ENOENT) {
-			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
-		 */
+	/* Both ft_action/ft_authenticate will gate the associate work item */
+	if ((hs->mde[4] & 1))
+		ft_action(netdev_get_ifindex(station->netdev),
+				station->connected_bss->frequency, bss);
+	else
 		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);
 
-		return true;
-	}
+	return true;
 }
 
 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");
 	}
 
-	station_ft_ds_action_start(station);
-
 	network_connected(station->connected_network);
 
 	if (station->netconfig) {
-- 
2.34.3


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 3/3] auto-t: update testPSK-roam with changed FT behavior
  2022-12-14 21:26 [PATCH 1/3] ft: gate FT-over-DS with a wiphy work item James Prestwood
  2022-12-14 21:26 ` [PATCH 2/3] station: remove early FT-over-DS action James Prestwood
@ 2022-12-14 21:26 ` James Prestwood
  2022-12-14 22:15 ` [PATCH 1/3] ft: gate FT-over-DS with a wiphy work item Denis Kenzior
  2 siblings, 0 replies; 4+ messages in thread
From: James Prestwood @ 2022-12-14 21:26 UTC (permalink / raw)
  To: iwd; +Cc: James Prestwood

---
 autotests/testPSK-roam/failed_roam_test.py | 38 +---------------------
 1 file changed, 1 insertion(+), 37 deletions(-)

diff --git a/autotests/testPSK-roam/failed_roam_test.py b/autotests/testPSK-roam/failed_roam_test.py
index cac2ff4d..360c1de5 100644
--- a/autotests/testPSK-roam/failed_roam_test.py
+++ b/autotests/testPSK-roam/failed_roam_test.py
@@ -65,7 +65,7 @@ class Test(unittest.TestCase):
         device.roam(self.bss_hostapd[1].bssid)
 
         # Roam should fail...
-        device.wait_for_event('ft-over-air-roam-failed')
+        device.wait_for_event('ft-roam-failed')
         # ... but IWD should remain connected
         self.assertTrue(device.state == DeviceState.connected)
 
@@ -80,42 +80,6 @@ class Test(unittest.TestCase):
         condition = 'obj.state == DeviceState.disconnected'
         wd.wait_for_object_condition(device, condition)
 
-    # Network sets over-DS bit, but fails to authenticate. IWD should still be
-    # able to roam using FT-over-Air.
-    def test_fallback_to_over_air(self):
-        self.bss_hostapd[0].set_value('wpa_key_mgmt', 'FT-PSK')
-        self.bss_hostapd[0].set_value('ft_over_ds', '1')
-        self.bss_hostapd[0].reload()
-        self.bss_hostapd[0].wait_for_event("AP-ENABLED")
-
-        self.bss_hostapd[1].set_value('wpa_key_mgmt', 'FT-PSK')
-        self.bss_hostapd[1].set_value('ft_over_ds', '1')
-        self.bss_hostapd[1].reload()
-        self.bss_hostapd[1].wait_for_event("AP-ENABLED")
-
-        wd = IWD(True)
-
-        device = wd.list_devices(1)[0]
-
-        # Drop action frames, this will prevent FT-over-DS authentication
-        self.rule1.enabled = True
-
-        self.connect(wd, device, self.bss_hostapd[0])
-
-        device.roam(self.bss_hostapd[1].bssid)
-
-        self.rule1.enabled = False
-
-        # FT-over-DS should fail, and over-Air should take over leading to a
-        # successful roam
-        device.wait_for_event('try-ft-over-air')
-
-        self.verify_roam(wd, device, self.bss_hostapd[0], self.bss_hostapd[1])
-
-        self.bss_hostapd[1].deauthenticate(device.address)
-        condition = 'obj.state == DeviceState.disconnected'
-        wd.wait_for_object_condition(device, condition)
-
     def tearDown(self):
         os.system('ip link set "' + self.bss_hostapd[0].ifname + '" down')
         os.system('ip link set "' + self.bss_hostapd[1].ifname + '" down')
-- 
2.34.3


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/3] ft: gate FT-over-DS with a wiphy work item
  2022-12-14 21:26 [PATCH 1/3] ft: gate FT-over-DS with a wiphy work item James Prestwood
  2022-12-14 21:26 ` [PATCH 2/3] station: remove early FT-over-DS action James Prestwood
  2022-12-14 21:26 ` [PATCH 3/3] auto-t: update testPSK-roam with changed FT behavior James Prestwood
@ 2022-12-14 22:15 ` Denis Kenzior
  2 siblings, 0 replies; 4+ messages in thread
From: Denis Kenzior @ 2022-12-14 22:15 UTC (permalink / raw)
  To: James Prestwood, iwd

Hi James,

On 12/14/22 15:26, James Prestwood wrote:
> Queue the FT action just like we do with FT Authenticate which makes
> it able to be used the same way, i.e. call ft_action() then queue
> the ft_associate work right away.
> 
> A timer was added to end the work item in case the target never
> responds.
> ---
>   src/ft.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++---------
>   1 file changed, 49 insertions(+), 9 deletions(-)
> 

All applied, thanks.

Regards,
-Denis


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-12-14 22:26 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-12-14 21:26 [PATCH 1/3] ft: gate FT-over-DS with a wiphy work item James Prestwood
2022-12-14 21:26 ` [PATCH 2/3] station: remove early FT-over-DS action James Prestwood
2022-12-14 21:26 ` [PATCH 3/3] auto-t: update testPSK-roam with changed FT behavior James Prestwood
2022-12-14 22:15 ` [PATCH 1/3] ft: gate FT-over-DS with a wiphy work item Denis Kenzior

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).