All of lore.kernel.org
 help / color / mirror / Atom feed
From: James Prestwood <prestwoj@gmail.com>
To: iwd@lists.linux.dev
Cc: James Prestwood <prestwoj@gmail.com>
Subject: [PATCH v4 08/15] station: create list of roam candidates
Date: Wed, 21 Sep 2022 15:31:51 -0700	[thread overview]
Message-ID: <20220921223158.704658-8-prestwoj@gmail.com> (raw)
In-Reply-To: <20220921223158.704658-1-prestwoj@gmail.com>

The current behavior is to only find the best roam candidate, which
generally is fine. But if for whatever reason IWD fails to roam it
would be nice having a few backup BSS's rather than having to
re-scan, or worse disassociate and reconnect entirely.

This patch doesn't change the roam behavior, just prepares for
using a roam candidate list. One difference though is any roam
candidates are added to station->bss_list, rather than just the
best BSS. This shouldn't effect any external behavior.

The candidate list is built based on scan_bss rank. First we establish
a base rank, the rank of the current BSS (or zero if AP roaming). Any
BSS in the results with a higher rank, excluding the current BSS, will
be added to the sorted station->roam_bss_list as well as stations
overall BSS list. If the resulting list is empty there were no better
BSS's, otherwise station can now try to roam starting with the best
candidate (head of the roam list).
---
 src/station.c | 84 +++++++++++++++++++++++++++++++++------------------
 1 file changed, 54 insertions(+), 30 deletions(-)

diff --git a/src/station.c b/src/station.c
index 868bb725..df54936e 100644
--- a/src/station.c
+++ b/src/station.c
@@ -107,6 +107,7 @@ struct station {
 
 	/* Set of frequencies to scan first when attempting a roam */
 	struct scan_freq_set *roam_freqs;
+	struct l_queue *roam_bss_list;
 
 	/* Frequencies split into subsets by priority */
 	struct scan_freq_set *scan_freqs_order[3];
@@ -1640,6 +1641,11 @@ static void station_roam_state_clear(struct station *station)
 		scan_freq_set_free(station->roam_freqs);
 		station->roam_freqs = NULL;
 	}
+
+	if (station->roam_bss_list) {
+		l_queue_destroy(station->roam_bss_list, NULL);
+		station->roam_bss_list = NULL;
+	}
 }
 
 static void station_reset_connection_state(struct station *station)
@@ -1981,6 +1987,11 @@ static void station_roamed(struct station *station)
 			l_warn("Could not request neighbor report");
 	}
 
+	if (station->roam_bss_list) {
+		l_queue_destroy(station->roam_bss_list, NULL);
+		station->roam_bss_list = NULL;
+	}
+
 	station_ft_ds_action_start(station);
 
 	station_enter_state(station, STATION_STATE_CONNECTED);
@@ -2005,6 +2016,11 @@ static void station_roam_failed(struct station *station)
 {
 	l_debug("%u", netdev_get_ifindex(station->netdev));
 
+	if (station->roam_bss_list) {
+		l_queue_destroy(station->roam_bss_list, NULL);
+		station->roam_bss_list = NULL;
+	}
+
 	/*
 	 * If we attempted a reassociation or a fast transition, and ended up
 	 * here then we are now disconnected.
@@ -2186,8 +2202,7 @@ static void station_preauthenticate_cb(struct netdev *netdev,
 	station_transition_reassociate(station, bss, new_hs);
 }
 
-static void station_transition_start(struct station *station,
-							struct scan_bss *bss)
+static void station_transition_start(struct station *station)
 {
 	struct handshake_state *hs = netdev_get_handshake(station->netdev);
 	struct network *connected = station->connected_network;
@@ -2195,6 +2210,7 @@ static void station_transition_start(struct station *station,
 	struct handshake_state *new_hs;
 	struct ie_rsn_info cur_rsne, target_rsne;
 	int ret;
+	struct scan_bss *bss = l_queue_peek_head(station->roam_bss_list);
 
 	l_debug("%u, target %s", netdev_get_ifindex(station->netdev),
 			util_address_to_string(bss->addr));
@@ -2334,12 +2350,10 @@ static bool station_roam_scan_notify(int err, struct l_queue *bss_list,
 	struct handshake_state *hs = netdev_get_handshake(station->netdev);
 	struct scan_bss *current_bss = station->connected_bss;
 	struct scan_bss *bss;
-	struct scan_bss *best_bss = NULL;
-	double best_bss_rank = 0.0;
+	double cur_bss_rank = 0.0;
 	static const double RANK_FT_FACTOR = 1.3;
 	uint16_t mdid;
 	enum security orig_security, security;
-	bool seen = false;
 
 	if (err) {
 		station_roam_failed(station);
@@ -2358,6 +2372,21 @@ static bool station_roam_scan_notify(int err, struct l_queue *bss_list,
 		ie_parse_mobility_domain_from_data(hs->mde, hs->mde[1] + 2,
 							&mdid, NULL, NULL);
 
+	station->roam_bss_list = l_queue_new();
+
+	/*
+	 * Find the current BSS rank, use the updated result if it exists. If
+	 * this is an AP roam keep the current rank as zero to force the roam
+	 * to occur.
+	 */
+	bss = l_queue_find(bss_list, bss_match_bssid, current_bss->addr);
+	if (bss && !station->ap_directed_roaming) {
+		cur_bss_rank = bss->rank;
+
+		if (hs->mde && bss->mde_present && l_get_le16(bss->mde) == mdid)
+			cur_bss_rank *= RANK_FT_FACTOR;
+	}
+
 	/*
 	 * BSSes in the bss_list come already ranked with their initial
 	 * association preference rank value.  We only need to add preference
@@ -2379,9 +2408,8 @@ static bool station_roam_scan_notify(int err, struct l_queue *bss_list,
 				bss->frequency, bss->rank, bss->signal_strength,
 				kbps100 / 10, kbps100 % 10);
 
-		/* Skip the BSS we are connected to if doing an AP roam */
-		if (station->ap_directed_roaming && !memcmp(bss->addr,
-				station->connected_bss->addr, 6))
+		/* Skip the BSS we are connected to */
+		if (!memcmp(bss->addr, station->connected_bss->addr, 6))
 			goto next;
 
 		/* Skip result if it is not part of the ESS */
@@ -2395,8 +2423,6 @@ static bool station_roam_scan_notify(int err, struct l_queue *bss_list,
 		if (security != orig_security)
 			goto next;
 
-		seen = true;
-
 		if (network_can_connect_bss(network, bss) < 0)
 			goto next;
 
@@ -2408,15 +2434,19 @@ static bool station_roam_scan_notify(int err, struct l_queue *bss_list,
 		if (hs->mde && bss->mde_present && l_get_le16(bss->mde) == mdid)
 			rank *= RANK_FT_FACTOR;
 
-		if (rank > best_bss_rank) {
-			if (best_bss)
-				scan_bss_free(best_bss);
+		if (rank <= cur_bss_rank)
+			goto next;
 
-			best_bss = bss;
-			best_bss_rank = rank;
+		/*
+		 * We need to update/add any potential roam candidate so
+		 * station/network know it exists.
+		 */
+		station_update_roam_bss(station, bss);
 
-			continue;
-		}
+		l_queue_insert(station->roam_bss_list, bss,
+				scan_bss_rank_compare, NULL);
+
+		continue;
 
 next:
 		scan_bss_free(bss);
@@ -2424,25 +2454,17 @@ next:
 
 	l_queue_destroy(bss_list, NULL);
 
-	if (!seen)
-		goto fail_free_bss;
-
 	/* See if we have anywhere to roam to */
-	if (!best_bss || scan_bss_addr_eq(best_bss, station->connected_bss)) {
+	if (l_queue_isempty(station->roam_bss_list)) {
 		station_debug_event(station, "no-roam-candidates");
-		goto fail_free_bss;
+		goto fail;
 	}
 
-	station_update_roam_bss(station, best_bss);
-
-	station_transition_start(station, best_bss);
+	station_transition_start(station);
 
 	return true;
 
-fail_free_bss:
-	if (best_bss)
-		scan_bss_free(best_bss);
-
+fail:
 	station_roam_failed(station);
 
 	return true;
@@ -4398,10 +4420,12 @@ static bool station_force_roam_scan_notify(int err, struct l_queue *bss_list,
 
 	/* The various roam routines expect this to be set from scanning */
 	station->preparing_roam = true;
+	station->roam_bss_list = l_queue_new();
+	l_queue_push_tail(station->roam_bss_list, target);
 
 	station_update_roam_bss(station, target);
 
-	station_transition_start(station, target);
+	station_transition_start(station);
 
 	reply = l_dbus_message_new_method_return(data->pending);
 
-- 
2.34.3


  parent reply	other threads:[~2022-09-21 22:32 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-09-21 22:31 [PATCH v4 01/15] netdev: add NETDEV_EVENT_FT_ROAMED James Prestwood
2022-09-21 22:31 ` [PATCH v4 02/15] nl80211util: include frame type with build_cmd_frame James Prestwood
2022-09-21 22:31 ` [PATCH v4 03/15] wiphy: add new work priority for FT James Prestwood
2022-09-21 22:31 ` [PATCH v4 04/15] offchannel: add priority to start call James Prestwood
2022-09-21 22:31 ` [PATCH v4 05/15] ft: netdev: prep for FT isolation into ft.c James Prestwood
2022-09-22  2:40   ` Denis Kenzior
2022-09-22 15:42     ` James Prestwood
2022-09-22 16:18       ` Denis Kenzior
2022-09-21 22:31 ` [PATCH v4 06/15] netdev: add FT TX frame hook James Prestwood
2022-09-21 22:31 ` [PATCH v4 07/15] ft: implement offchannel authentication James Prestwood
2022-09-21 22:31 ` James Prestwood [this message]
2022-09-22  3:09   ` [PATCH v4 08/15] station: create list of roam candidates Denis Kenzior
2022-09-21 22:31 ` [PATCH v4 09/15] netdev: hook in RX for FT-Action/Authentication/Association James Prestwood
2022-09-21 22:31 ` [PATCH v4 10/15] ft: update action response parsing to include header James Prestwood
2022-09-21 22:31 ` [PATCH v4 11/15] station: handle NETDEV_EVENT_FT_ROAMED James Prestwood
2022-09-21 22:31 ` [PATCH v4 12/15] station: try multiple roam candidates James Prestwood
2022-09-21 22:31 ` [PATCH v4 13/15] netdev: ft: complete FT refactor James Prestwood
2022-09-21 22:31 ` [PATCH v4 14/15] netdev: remove FT auth proto James Prestwood
2022-09-21 22:31 ` [PATCH v4 15/15] ft: remove auth-proto/ft_sm James Prestwood
2022-09-22  2:25 ` [PATCH v4 01/15] netdev: add NETDEV_EVENT_FT_ROAMED Denis Kenzior

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220921223158.704658-8-prestwoj@gmail.com \
    --to=prestwoj@gmail.com \
    --cc=iwd@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.