All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/7] station: factor out logic for choosing FT
@ 2021-05-12 19:21 James Prestwood
  2021-05-12 19:21 ` [PATCH 2/7] station: remove ap_directed_roam check for over-DS James Prestwood
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: James Prestwood @ 2021-05-12 19:21 UTC (permalink / raw)
  To: iwd

[-- Attachment #1: Type: text/plain, Size: 1778 bytes --]

---
 src/station.c | 25 +++++++++++++++++++------
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/src/station.c b/src/station.c
index 479f81f5..bdb8859a 100644
--- a/src/station.c
+++ b/src/station.c
@@ -1823,13 +1823,30 @@ static void station_preauthenticate_cb(struct netdev *netdev,
 	station_transition_reassociate(station, bss, new_hs);
 }
 
+static bool station_can_fast_transition(struct handshake_state *hs,
+					struct scan_bss *bss)
+{
+	uint16_t mdid;
+
+	if (!hs->mde)
+		return false;
+
+	if (ie_parse_mobility_domain_from_data(hs->mde, hs->mde[1] + 2,
+						&mdid, NULL, NULL) < 0)
+		return false;
+
+	if (bss->mde_present && l_get_le16(bss->mde) == mdid)
+		return true;
+
+	return false;
+}
+
 static void station_transition_start(struct station *station,
 							struct scan_bss *bss)
 {
 	struct handshake_state *hs = netdev_get_handshake(station->netdev);
 	struct network *connected = station->connected_network;
 	enum security security = network_get_security(connected);
-	uint16_t mdid;
 	struct handshake_state *new_hs;
 	struct ie_rsn_info cur_rsne, target_rsne;
 
@@ -1839,12 +1856,8 @@ static void station_transition_start(struct station *station,
 	/* Reset AP roam flag, at this point the roaming behaves the same */
 	station->ap_directed_roaming = false;
 
-	if (hs->mde)
-		ie_parse_mobility_domain_from_data(hs->mde, hs->mde[1] + 2,
-							&mdid, NULL, NULL);
-
 	/* Can we use Fast Transition? */
-	if (hs->mde && bss->mde_present && l_get_le16(bss->mde) == mdid) {
+	if (station_can_fast_transition(hs, bss)) {
 		/* Rebuild handshake RSN for target AP */
 		if (station_build_handshake_rsn(hs, station->wiphy,
 				station->connected_network, bss) < 0) {
-- 
2.31.1

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

* [PATCH 2/7] station: remove ap_directed_roam check for over-DS
  2021-05-12 19:21 [PATCH 1/7] station: factor out logic for choosing FT James Prestwood
@ 2021-05-12 19:21 ` James Prestwood
  2021-05-12 19:21 ` [PATCH 3/7] ft: break up FT action parsing into two steps James Prestwood
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: James Prestwood @ 2021-05-12 19:21 UTC (permalink / raw)
  To: iwd

[-- Attachment #1: Type: text/plain, Size: 703 bytes --]

This flag was being checked but it is explicitly being set to
false prior.
---
 src/station.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/station.c b/src/station.c
index bdb8859a..b9368ef2 100644
--- a/src/station.c
+++ b/src/station.c
@@ -1867,8 +1867,7 @@ static void station_transition_start(struct station *station,
 		}
 
 		/* FT-over-DS can be better suited for these situations */
-		if ((hs->mde[4] & 1) && (station->ap_directed_roaming ||
-				station->signal_low)) {
+		if ((hs->mde[4] & 1) && station->signal_low) {
 			if (netdev_fast_transition_over_ds_action(
 					station->netdev, bss,
 					station_fast_transition_ds_cb,
-- 
2.31.1

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

* [PATCH 3/7] ft: break up FT action parsing into two steps
  2021-05-12 19:21 [PATCH 1/7] station: factor out logic for choosing FT James Prestwood
  2021-05-12 19:21 ` [PATCH 2/7] station: remove ap_directed_roam check for over-DS James Prestwood
@ 2021-05-12 19:21 ` James Prestwood
  2021-05-12 19:21 ` [PATCH 4/7] netdev: handle multiple concurrent FT-over-DS action frames James Prestwood
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: James Prestwood @ 2021-05-12 19:21 UTC (permalink / raw)
  To: iwd

[-- Attachment #1: Type: text/plain, Size: 3951 bytes --]

This is to prepare for multiple concurrent FT-over-DS action frames.
A list will be kept in netdev and for lookup reasons it needs to
parse the start of the frame to grab the aa/spa addresses. In this
call the IEs are also returned and passed to the new
ft_over_ds_parse_action_response.

For now the address checks have been moved into netdev, but this will
eventually turn into a queue lookup.
---
 src/ft.c     | 30 ++++++++++++++++++++----------
 src/ft.h     | 10 ++++++++--
 src/netdev.c | 18 ++++++++++++++++--
 3 files changed, 44 insertions(+), 14 deletions(-)

diff --git a/src/ft.c b/src/ft.c
index de754fd8..13733019 100644
--- a/src/ft.c
+++ b/src/ft.c
@@ -452,7 +452,7 @@ static bool mde_equal(const uint8_t *mde1, const uint8_t *mde2)
 	return memcmp(mde1, mde1, mde1[1] + 2) == 0;
 }
 
-static bool ft_over_ds_process_ies(struct ft_ds_info *info,
+bool ft_over_ds_parse_action_ies(struct ft_ds_info *info,
 					struct handshake_state *hs,
 					const uint8_t *ies,
 					size_t ies_len)
@@ -523,11 +523,15 @@ ft_error:
 	return -EBADMSG;
 }
 
-int ft_over_ds_parse_action_response(struct ft_ds_info *info,
-					struct handshake_state *hs,
-					const uint8_t *frame, size_t frame_len)
+int ft_over_ds_parse_action_response(const uint8_t *frame, size_t frame_len,
+					const uint8_t **spa_out,
+					const uint8_t **aa_out,
+					const uint8_t **ies_out,
+					size_t *ies_len)
 {
 	uint16_t status;
+	const uint8_t *aa;
+	const uint8_t *spa;
 
 	if (frame_len < 16)
 		return -EINVAL;
@@ -540,17 +544,23 @@ int ft_over_ds_parse_action_response(struct ft_ds_info *info,
 	if (frame[1] != 2)
 		return -EINVAL;
 
-	if (memcmp(frame + 2, info->spa, 6))
-		return -ENOENT;
-	if (memcmp(frame + 8, info->aa, 6))
-		return -ENOENT;
+	spa = frame + 2;
+	aa = frame + 8;
 
 	status = l_get_le16(frame + 14);
 	if (status != 0)
 		return (int)status;
 
-	if (!ft_over_ds_process_ies(info, hs, frame + 16, frame_len - 16))
-		return -EBADMSG;
+	if (spa_out)
+		*spa_out = spa;
+
+	if (aa_out)
+		*aa_out = aa;
+
+	if (ies_out && ies_len) {
+		*ies_out = frame + 16;
+		*ies_len = frame_len - 16;
+	}
 
 	return 0;
 }
diff --git a/src/ft.h b/src/ft.h
index 3d1cfe30..6167e0d7 100644
--- a/src/ft.h
+++ b/src/ft.h
@@ -47,9 +47,15 @@ bool ft_build_authenticate_ies(struct handshake_state *hs,
 				const uint8_t *new_snonce, uint8_t *buf,
 				size_t *len);
 
-int ft_over_ds_parse_action_response(struct ft_ds_info *info,
+int ft_over_ds_parse_action_response(const uint8_t *frame, size_t frame_len,
+					const uint8_t **spa_out,
+					const uint8_t **aa_out,
+					const uint8_t **ies_out,
+					size_t *ies_len);
+bool ft_over_ds_parse_action_ies(struct ft_ds_info *info,
 					struct handshake_state *hs,
-					const uint8_t *frame, size_t frame_len);
+					const uint8_t *ies,
+					size_t ies_len);
 
 struct auth_proto *ft_over_air_sm_new(struct handshake_state *hs,
 				ft_tx_authenticate_func_t tx_auth,
diff --git a/src/netdev.c b/src/netdev.c
index 9e7fc821..65627b9f 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -3769,12 +3769,26 @@ static void netdev_ft_response_frame_event(const struct mmpdu_header *hdr,
 	struct netdev_ft_over_ds_info *info = netdev->ft_ds_info;
 	int ret;
 	uint16_t status_code = MMPDU_STATUS_CODE_UNSPECIFIED;
+	const uint8_t *aa;
+	const uint8_t *spa;
+	const uint8_t *ies;
+	size_t ies_len;
 
 	if (!info)
 		return;
 
-	ret = ft_over_ds_parse_action_response(&info->super, netdev->handshake,
-						body, body_len);
+	ret = ft_over_ds_parse_action_response(body, body_len, &spa, &aa,
+						&ies, &ies_len);
+	if (ret != 0)
+		return;
+
+	if (memcmp(spa, info->super.spa, 6))
+		return;
+	if (memcmp(aa, info->super.aa, 6))
+		return;
+
+	ret = ft_over_ds_parse_action_ies(&info->super, netdev->handshake,
+						ies, ies_len);
 	if (ret < 0)
 		return;
 
-- 
2.31.1

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

* [PATCH 4/7] netdev: handle multiple concurrent FT-over-DS action frames
  2021-05-12 19:21 [PATCH 1/7] station: factor out logic for choosing FT James Prestwood
  2021-05-12 19:21 ` [PATCH 2/7] station: remove ap_directed_roam check for over-DS James Prestwood
  2021-05-12 19:21 ` [PATCH 3/7] ft: break up FT action parsing into two steps James Prestwood
@ 2021-05-12 19:21 ` James Prestwood
  2021-05-12 19:21 ` [PATCH 5/7] station: send FT-over-DS actions upon connection James Prestwood
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: James Prestwood @ 2021-05-12 19:21 UTC (permalink / raw)
  To: iwd

[-- Attachment #1: Type: text/plain, Size: 7261 bytes --]

The beauty of FT-over-DS is that a station can send and receive
action frames to many APs to prepare for a future roam. Each
AP authenticates the station and when a roam happens the station
can immediately move to reassociation.

To handle this a queue of netdev_ft_over_ds_info structs is used
instead of a single entry. Using the new ft.c parser APIs these
info structs can be looked up when responses come in. For now
the timeouts/callbacks are kept but these will be removed as it
really does not matter if the AP sends a response (keeps station
happy until the next patch).
---
 src/netdev.c | 112 ++++++++++++++++++++++++++++++++-------------------
 1 file changed, 71 insertions(+), 41 deletions(-)

diff --git a/src/netdev.c b/src/netdev.c
index 65627b9f..c194e78f 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -169,7 +169,7 @@ struct netdev {
 	struct l_genl_msg *auth_cmd;
 	struct wiphy_radio_work_item work;
 
-	struct netdev_ft_over_ds_info *ft_ds_info;
+	struct l_queue *ft_ds_list;
 
 	bool connected : 1;
 	bool associated : 1;
@@ -687,6 +687,13 @@ static void netdev_preauth_destroy(void *data)
 	l_free(state);
 }
 
+static void netdev_ft_ds_entry_free(void *data)
+{
+	struct netdev_ft_over_ds_info *info = data;
+
+	ft_ds_info_free(&info->super);
+}
+
 static void netdev_connect_free(struct netdev *netdev)
 {
 	if (netdev->work.id)
@@ -754,8 +761,10 @@ static void netdev_connect_free(struct netdev *netdev)
 		netdev->disconnect_cmd_id = 0;
 	}
 
-	if (netdev->ft_ds_info)
-		ft_ds_info_free(&netdev->ft_ds_info->super);
+	if (netdev->ft_ds_list) {
+		l_queue_destroy(netdev->ft_ds_list, netdev_ft_ds_entry_free);
+		netdev->ft_ds_list = NULL;
+	}
 }
 
 static void netdev_connect_failed(struct netdev *netdev,
@@ -854,6 +863,11 @@ static void netdev_free(void *data)
 		netdev->disconnect_idle = NULL;
 	}
 
+	if (netdev->ft_ds_list) {
+		l_queue_destroy(netdev->ft_ds_list, netdev_ft_ds_entry_free);
+		netdev->ft_ds_list = NULL;
+	}
+
 	if (netdev->events_ready)
 		WATCHLIST_NOTIFY(&netdev_watches, netdev_watch_func_t,
 					netdev, NETDEV_WATCH_EVENT_DEL);
@@ -1286,6 +1300,11 @@ static void netdev_connect_ok(struct netdev *netdev)
 		netdev->fw_roam_bss = NULL;
 	}
 
+	if (netdev->ft_ds_list) {
+		l_queue_destroy(netdev->ft_ds_list, netdev_ft_ds_entry_free);
+		netdev->ft_ds_list = NULL;
+	}
+
 	if (netdev->connect_cb) {
 		netdev->connect_cb(netdev, NETDEV_RESULT_OK, NULL,
 					netdev->user_data);
@@ -3442,12 +3461,6 @@ int netdev_reassociate(struct netdev *netdev, struct scan_bss *target_bss,
 	if (err < 0)
 		return err;
 
-	/* In case of a previous failed over-DS attempt */
-	if (netdev->ft_ds_info) {
-		ft_ds_info_free(&netdev->ft_ds_info->super);
-		netdev->ft_ds_info = NULL;
-	}
-
 	memcpy(netdev->prev_bssid, orig_bss->addr, ETH_ALEN);
 
 	netdev->associated = false;
@@ -3676,12 +3689,6 @@ static int netdev_ft_tx_associate(struct iovec *ie_iov, size_t iov_len,
 		return -EIO;
 	}
 
-	/* No need to keep this around at this point */
-	if (netdev->ft_ds_info) {
-		ft_ds_info_free(&netdev->ft_ds_info->super);
-		netdev->ft_ds_info = NULL;
-	}
-
 	return 0;
 }
 
@@ -3756,9 +3763,26 @@ static void netdev_ft_over_ds_auth_failed(struct netdev_ft_over_ds_info *info,
 	if (info->cb)
 		info->cb(info->netdev, status, info->super.aa, info->user_data);
 
+	l_queue_remove(info->netdev->ft_ds_list, info);
 	ft_ds_info_free(&info->super);
+}
 
-	info->netdev->ft_ds_info = NULL;
+struct ft_ds_finder {
+	const uint8_t *spa;
+	const uint8_t *aa;
+};
+
+static bool match_ft_ds_info(const void *a, const void *b)
+{
+	const struct netdev_ft_over_ds_info *info = a;
+	const struct ft_ds_finder *finder = b;
+
+	if (memcmp(info->super.spa, finder->spa, 6))
+		return false;
+	if (memcmp(info->super.aa, finder->aa, 6))
+		return false;
+
+	return true;
 }
 
 static void netdev_ft_response_frame_event(const struct mmpdu_header *hdr,
@@ -3766,41 +3790,41 @@ static void netdev_ft_response_frame_event(const struct mmpdu_header *hdr,
 					int rssi, void *user_data)
 {
 	struct netdev *netdev = user_data;
-	struct netdev_ft_over_ds_info *info = netdev->ft_ds_info;
+	struct netdev_ft_over_ds_info *info;
 	int ret;
 	uint16_t status_code = MMPDU_STATUS_CODE_UNSPECIFIED;
 	const uint8_t *aa;
 	const uint8_t *spa;
 	const uint8_t *ies;
 	size_t ies_len;
-
-	if (!info)
-		return;
+	struct ft_ds_finder finder;
 
 	ret = ft_over_ds_parse_action_response(body, body_len, &spa, &aa,
 						&ies, &ies_len);
-	if (ret != 0)
+	if (ret < 0)
 		return;
 
-	if (memcmp(spa, info->super.spa, 6))
-		return;
-	if (memcmp(aa, info->super.aa, 6))
+	finder.spa = spa;
+	finder.aa = aa;
+
+	info = l_queue_find(netdev->ft_ds_list, match_ft_ds_info, &finder);
+	if (!info)
 		return;
 
+	/* Lookup successful, now check the status code */
+	if (ret > 0) {
+		status_code = (uint16_t)ret;
+		goto ft_error;
+	}
+
 	ret = ft_over_ds_parse_action_ies(&info->super, netdev->handshake,
 						ies, ies_len);
 	if (ret < 0)
-		return;
+		goto ft_error;
 
 	l_timeout_remove(info->timeout);
 	info->timeout = NULL;
 
-	/* Now make sure the packet contained a success status code */
-	if (ret > 0) {
-		status_code = (uint16_t)ret;
-		goto ft_error;
-	}
-
 	info->parsed = true;
 
 	if (info->cb)
@@ -3809,7 +3833,8 @@ static void netdev_ft_response_frame_event(const struct mmpdu_header *hdr,
 	return;
 
 ft_error:
-	l_debug("FT-over-DS to "MAC" failed", MAC_STR(info->super.aa));
+	l_debug("FT-over-DS to "MAC" failed (%d)", MAC_STR(info->super.aa),
+			status_code);
 
 	netdev_ft_over_ds_auth_failed(info, status_code);
 }
@@ -3887,10 +3912,8 @@ int netdev_fast_transition_over_ds(struct netdev *netdev,
 					struct scan_bss *target_bss,
 					netdev_connect_cb_t cb)
 {
-	struct netdev_ft_over_ds_info *info = netdev->ft_ds_info;
-
-	if (!info || !info->parsed)
-		return -ENOENT;
+	struct netdev_ft_over_ds_info *info;
+	struct ft_ds_finder finder;
 
 	if (!netdev->operational)
 		return -ENOTCONN;
@@ -3900,6 +3923,14 @@ int netdev_fast_transition_over_ds(struct netdev *netdev,
 			l_get_le16(target_bss->mde))
 		return -EINVAL;
 
+	finder.spa = netdev->addr;
+	finder.aa = target_bss->addr;
+
+	info = l_queue_find(netdev->ft_ds_list, match_ft_ds_info, &finder);
+
+	if (!info || !info->parsed)
+		return -ENOENT;
+
 	prepare_ft(netdev, target_bss);
 
 	ft_over_ds_prepare_handshake(&info->super, netdev->handshake);
@@ -3963,10 +3994,6 @@ int netdev_fast_transition_over_ds_action(struct netdev *netdev,
 	uint8_t buf[512];
 	size_t len;
 
-	/* TODO: Just allow single outstanding action frame for now */
-	if (netdev->ft_ds_info)
-		return -EALREADY;
-
 	if (!netdev->operational)
 		return -ENOTCONN;
 
@@ -4005,7 +4032,10 @@ int netdev_fast_transition_over_ds_action(struct netdev *netdev,
 
 	iovs[2].iov_base = NULL;
 
-	netdev->ft_ds_info = info;
+	if (!netdev->ft_ds_list)
+		netdev->ft_ds_list = l_queue_new();
+
+	l_queue_push_head(netdev->ft_ds_list, info);
 
 	info->timeout = l_timeout_create_ms(300, netdev_ft_over_ds_timeout,
 						info, NULL);
-- 
2.31.1

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

* [PATCH 5/7] station: send FT-over-DS actions upon connection
  2021-05-12 19:21 [PATCH 1/7] station: factor out logic for choosing FT James Prestwood
                   ` (2 preceding siblings ...)
  2021-05-12 19:21 ` [PATCH 4/7] netdev: handle multiple concurrent FT-over-DS action frames James Prestwood
@ 2021-05-12 19:21 ` James Prestwood
  2021-05-12 19:21 ` [PATCH 6/7] netdev: remove callback/userdata/timeout from FT-over-DS action James Prestwood
  2021-05-12 19:21 ` [PATCH 7/7] auto-t: update FT-over-DS test for new behavior James Prestwood
  5 siblings, 0 replies; 7+ messages in thread
From: James Prestwood @ 2021-05-12 19:21 UTC (permalink / raw)
  To: iwd

[-- Attachment #1: Type: text/plain, Size: 5270 bytes --]

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.
---
 src/station.c | 97 +++++++++++++++++++++++++--------------------------
 1 file changed, 48 insertions(+), 49 deletions(-)

diff --git a/src/station.c b/src/station.c
index b9368ef2..9e1b9cc0 100644
--- a/src/station.c
+++ b/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));
 }
 
-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,
 					enum netdev_result result,
 					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);
 	struct handshake_state *new_hs;
 	struct ie_rsn_info cur_rsne, target_rsne;
+	int ret;
 
 	l_debug("%u, target %s", netdev_get_ifindex(station->netdev),
 			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 */
 		if ((hs->mde[4] & 1) && station->signal_low) {
-			if (netdev_fast_transition_over_ds_action(
-					station->netdev, bss,
-					station_fast_transition_ds_cb,
-					station) < 0) {
+			ret = netdev_fast_transition_over_ds(station->netdev,
+					bss, station_fast_transition_cb);
+			/* No action responses from this BSS, try over air */
+			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);
+				return;
 			}
-
-			/*
-			 * Set connected_bss/preparing_roam/state only on a
-			 * successful FT-over-DS action frame response
-			 */
-			return;
 		} else {
+try_over_air:
 			if (netdev_fast_transition(station->netdev, bss,
 					station_fast_transition_cb) < 0) {
 				station_roam_failed(station);
@@ -2512,10 +2476,36 @@ static void station_connect_dbus_reply(struct station *station,
 	dbus_pending_reply(&station->connect_pending, reply);
 }
 
+static void foreach_over_ds_action(void *data, void *user_data)
+{
+	struct scan_bss *bss = data;
+	struct station *station = user_data;
+	struct handshake_state *hs = netdev_get_handshake(station->netdev);
+	const char *ssid = network_get_ssid(station->connected_network);
+
+	if (bss->ssid_len != strlen(ssid))
+		return;
+
+	if (memcmp(bss->ssid, ssid, bss->ssid_len))
+		return;
+
+	if (bss == station->connected_bss)
+		return;
+
+	/*
+	 * Fire and forget. Netdev will maintain a cache of responses and
+	 * when the time comes these can be referenced for a roam
+	 */
+	if (station_can_fast_transition(hs, bss))
+		netdev_fast_transition_over_ds_action(station->netdev, bss,
+							NULL, NULL);
+}
+
 static void station_connect_cb(struct netdev *netdev, enum netdev_result result,
 					void *event_data, void *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);
 
@@ -2566,6 +2556,15 @@ static void station_connect_cb(struct netdev *netdev, enum netdev_result result,
 			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))
+		l_queue_foreach(station->bss_list, foreach_over_ds_action,
+					station);
+
 	network_connected(station->connected_network);
 
 	if (station->netconfig)
-- 
2.31.1

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

* [PATCH 6/7] netdev: remove callback/userdata/timeout from FT-over-DS action
  2021-05-12 19:21 [PATCH 1/7] station: factor out logic for choosing FT James Prestwood
                   ` (3 preceding siblings ...)
  2021-05-12 19:21 ` [PATCH 5/7] station: send FT-over-DS actions upon connection James Prestwood
@ 2021-05-12 19:21 ` James Prestwood
  2021-05-12 19:21 ` [PATCH 7/7] auto-t: update FT-over-DS test for new behavior James Prestwood
  5 siblings, 0 replies; 7+ messages in thread
From: James Prestwood @ 2021-05-12 19:21 UTC (permalink / raw)
  To: iwd

[-- Attachment #1: Type: text/plain, Size: 4397 bytes --]

Since netdev maintains the list of FT over DS info structs there is not
any need for station to get callbacks when the initial action frame
is received, or not. This removes the need for the callback handler,
user data, and response timeout.
---
 src/netdev.c  | 38 +-------------------------------------
 src/netdev.h  |  4 +---
 src/station.c |  3 +--
 3 files changed, 3 insertions(+), 42 deletions(-)

diff --git a/src/netdev.c b/src/netdev.c
index c194e78f..55a63dd2 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -95,9 +95,6 @@ struct netdev_handshake_state {
 struct netdev_ft_over_ds_info {
 	struct ft_ds_info super;
 	struct netdev *netdev;
-	struct l_timeout *timeout;
-	netdev_ft_over_ds_cb_t cb;
-	void *user_data;
 
 	bool parsed : 1;
 };
@@ -3760,9 +3757,6 @@ static void prepare_ft(struct netdev *netdev, struct scan_bss *target_bss)
 static void netdev_ft_over_ds_auth_failed(struct netdev_ft_over_ds_info *info,
 						uint16_t status)
 {
-	if (info->cb)
-		info->cb(info->netdev, status, info->super.aa, info->user_data);
-
 	l_queue_remove(info->netdev->ft_ds_list, info);
 	ft_ds_info_free(&info->super);
 }
@@ -3822,14 +3816,8 @@ static void netdev_ft_response_frame_event(const struct mmpdu_header *hdr,
 	if (ret < 0)
 		goto ft_error;
 
-	l_timeout_remove(info->timeout);
-	info->timeout = NULL;
-
 	info->parsed = true;
 
-	if (info->cb)
-		info->cb(netdev, 0, info->super.aa, info->user_data);
-
 	return;
 
 ft_error:
@@ -3958,34 +3946,16 @@ static void netdev_ft_request_cb(struct l_genl_msg *msg, void *user_data)
 	}
 }
 
-static void netdev_ft_over_ds_timeout(struct l_timeout *timeout,
-					void *user_data)
-{
-	struct netdev_ft_over_ds_info *info = user_data;
-
-	l_timeout_remove(info->timeout);
-	info->timeout = NULL;
-
-	l_debug("");
-
-	netdev_ft_over_ds_auth_failed(info, MMPDU_STATUS_CODE_UNSPECIFIED);
-}
-
 static void netdev_ft_ds_info_free(struct ft_ds_info *ft)
 {
 	struct netdev_ft_over_ds_info *info = l_container_of(ft,
 					struct netdev_ft_over_ds_info, super);
 
-	if (info->timeout)
-		l_timeout_remove(info->timeout);
-
 	l_free(info);
 }
 
 int netdev_fast_transition_over_ds_action(struct netdev *netdev,
-					const struct scan_bss *target_bss,
-					netdev_ft_over_ds_cb_t cb,
-					void *user_data)
+					const struct scan_bss *target_bss)
 {
 	struct netdev_ft_over_ds_info *info;
 	uint8_t ft_req[14];
@@ -4013,9 +3983,6 @@ int netdev_fast_transition_over_ds_action(struct netdev *netdev,
 	l_getrandom(info->super.snonce, 32);
 	info->super.free = netdev_ft_ds_info_free;
 
-	info->cb = cb;
-	info->user_data = user_data;
-
 	ft_req[0] = 6; /* FT category */
 	ft_req[1] = 1; /* FT Request action */
 	memcpy(ft_req + 2, netdev->addr, 6);
@@ -4037,9 +4004,6 @@ int netdev_fast_transition_over_ds_action(struct netdev *netdev,
 
 	l_queue_push_head(netdev->ft_ds_list, info);
 
-	info->timeout = l_timeout_create_ms(300, netdev_ft_over_ds_timeout,
-						info, NULL);
-
 	netdev_send_action_framev(netdev, netdev->handshake->aa, iovs, 2,
 					netdev->frequency,
 					netdev_ft_request_cb,
diff --git a/src/netdev.h b/src/netdev.h
index 987504f6..f625957b 100644
--- a/src/netdev.h
+++ b/src/netdev.h
@@ -163,9 +163,7 @@ int netdev_reassociate(struct netdev *netdev, struct scan_bss *target_bss,
 int netdev_fast_transition(struct netdev *netdev, struct scan_bss *target_bss,
 				netdev_connect_cb_t cb);
 int netdev_fast_transition_over_ds_action(struct netdev *netdev,
-					const struct scan_bss *target_bss,
-					netdev_ft_over_ds_cb_t cb,
-					void *user_data);
+					const struct scan_bss *target_bss);
 int netdev_fast_transition_over_ds(struct netdev *netdev,
 					struct scan_bss *target_bss,
 					netdev_connect_cb_t cb);
diff --git a/src/station.c b/src/station.c
index 9e1b9cc0..352a485e 100644
--- a/src/station.c
+++ b/src/station.c
@@ -2497,8 +2497,7 @@ static void foreach_over_ds_action(void *data, void *user_data)
 	 * when the time comes these can be referenced for a roam
 	 */
 	if (station_can_fast_transition(hs, bss))
-		netdev_fast_transition_over_ds_action(station->netdev, bss,
-							NULL, NULL);
+		netdev_fast_transition_over_ds_action(station->netdev, bss);
 }
 
 static void station_connect_cb(struct netdev *netdev, enum netdev_result result,
-- 
2.31.1

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

* [PATCH 7/7] auto-t: update FT-over-DS test for new behavior
  2021-05-12 19:21 [PATCH 1/7] station: factor out logic for choosing FT James Prestwood
                   ` (4 preceding siblings ...)
  2021-05-12 19:21 ` [PATCH 6/7] netdev: remove callback/userdata/timeout from FT-over-DS action James Prestwood
@ 2021-05-12 19:21 ` James Prestwood
  5 siblings, 0 replies; 7+ messages in thread
From: James Prestwood @ 2021-05-12 19:21 UTC (permalink / raw)
  To: iwd

[-- Attachment #1: Type: text/plain, Size: 1404 bytes --]

The FT-over-DS procedure now authenticates with multiple BSS's
upon connecting. This causes list_sta() to return our address for
any authenticated APs. It has now been changed to work with this
new behavior, as well as a check that the station fully connected
to the expected AP initially.
---
 autotests/testFT-PSK-over-DS/connection_test.py | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/autotests/testFT-PSK-over-DS/connection_test.py b/autotests/testFT-PSK-over-DS/connection_test.py
index 4c751841..47104b69 100644
--- a/autotests/testFT-PSK-over-DS/connection_test.py
+++ b/autotests/testFT-PSK-over-DS/connection_test.py
@@ -62,8 +62,13 @@ class Test(unittest.TestCase):
         condition = 'obj.state == DeviceState.connected'
         wd.wait_for_object_condition(device, condition)
 
+        self.bss_hostapd[0].wait_for_event('AP-STA-CONNECTED %s' % device.address)
+
+        # list_sta actually reports any authenticated stations. Due to the
+        # nature of FT-over-DS IWD should authenticate to all stations with
+        # the same mobility domain. This means both APs should show our station.
         self.assertTrue(self.bss_hostapd[0].list_sta())
-        self.assertFalse(self.bss_hostapd[1].list_sta())
+        self.assertTrue(self.bss_hostapd[1].list_sta())
 
         wd.unregister_psk_agent(psk_agent)
 
-- 
2.31.1

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

end of thread, other threads:[~2021-05-12 19:21 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-05-12 19:21 [PATCH 1/7] station: factor out logic for choosing FT James Prestwood
2021-05-12 19:21 ` [PATCH 2/7] station: remove ap_directed_roam check for over-DS James Prestwood
2021-05-12 19:21 ` [PATCH 3/7] ft: break up FT action parsing into two steps James Prestwood
2021-05-12 19:21 ` [PATCH 4/7] netdev: handle multiple concurrent FT-over-DS action frames James Prestwood
2021-05-12 19:21 ` [PATCH 5/7] station: send FT-over-DS actions upon connection James Prestwood
2021-05-12 19:21 ` [PATCH 6/7] netdev: remove callback/userdata/timeout from FT-over-DS action James Prestwood
2021-05-12 19:21 ` [PATCH 7/7] auto-t: update FT-over-DS test for new behavior James Prestwood

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.