All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] station: clear out roam frequencies after roam
@ 2021-03-29 19:07 James Prestwood
  2021-03-29 19:07 ` [PATCH 2/3] station: unify firmware/normal roaming James Prestwood
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: James Prestwood @ 2021-03-29 19:07 UTC (permalink / raw)
  To: iwd

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

---
 src/station.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/station.c b/src/station.c
index ba4483e6..0d4cd47d 100644
--- a/src/station.c
+++ b/src/station.c
@@ -1442,6 +1442,11 @@ static void station_roamed(struct station *station)
 	if (station->netconfig)
 		netconfig_reconfigure(station->netconfig);
 
+	if (station->roam_freqs) {
+		scan_freq_set_free(station->roam_freqs);
+		station->roam_freqs = NULL;
+	}
+
 	station_enter_state(station, STATION_STATE_CONNECTED);
 }
 
-- 
2.26.2

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

* [PATCH 2/3] station: unify firmware/normal roaming
  2021-03-29 19:07 [PATCH 1/3] station: clear out roam frequencies after roam James Prestwood
@ 2021-03-29 19:07 ` James Prestwood
  2021-03-29 19:07 ` [PATCH 3/3] station: get neighbor report after roaming James Prestwood
  2021-03-29 19:12 ` [PATCH 1/3] station: clear out roam frequencies after roam Denis Kenzior
  2 siblings, 0 replies; 4+ messages in thread
From: James Prestwood @ 2021-03-29 19:07 UTC (permalink / raw)
  To: iwd

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

This doesn't change much functionally but does unify the
two roaming paths by ending with 'station_roamed()'.
---
 src/station.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/station.c b/src/station.c
index 0d4cd47d..acf77ec8 100644
--- a/src/station.c
+++ b/src/station.c
@@ -2332,7 +2332,7 @@ static void station_event_roamed(struct station *station, struct scan_bss *new)
 
 	l_queue_insert(station->bss_list, new, scan_bss_rank_compare, NULL);
 
-	station_enter_state(station, STATION_STATE_CONNECTED);
+	station_roamed(station);
 }
 
 static void station_rssi_level_changed(struct station *station,
-- 
2.26.2

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

* [PATCH 3/3] station: get neighbor report after roaming
  2021-03-29 19:07 [PATCH 1/3] station: clear out roam frequencies after roam James Prestwood
  2021-03-29 19:07 ` [PATCH 2/3] station: unify firmware/normal roaming James Prestwood
@ 2021-03-29 19:07 ` James Prestwood
  2021-03-29 19:12 ` [PATCH 1/3] station: clear out roam frequencies after roam Denis Kenzior
  2 siblings, 0 replies; 4+ messages in thread
From: James Prestwood @ 2021-03-29 19:07 UTC (permalink / raw)
  To: iwd

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

In the same vein as requesting a neighbor report after
connecting for the first time, it should also be done
after a roam to obtain the latest neighbor information.
---
 src/station.c | 354 +++++++++++++++++++++++++-------------------------
 1 file changed, 180 insertions(+), 174 deletions(-)

diff --git a/src/station.c b/src/station.c
index acf77ec8..cf4dd2e7 100644
--- a/src/station.c
+++ b/src/station.c
@@ -1428,6 +1428,180 @@ static void station_roam_timeout_rearm(struct station *station, int seconds);
 static int station_roam_scan(struct station *station,
 				struct scan_freq_set *freq_set);
 
+static uint32_t station_freq_from_neighbor_report(const uint8_t *country,
+		struct ie_neighbor_report_info *info, enum scan_band *out_band)
+{
+	enum scan_band band;
+	uint32_t freq;
+
+	if (info->oper_class == 0) {
+		/*
+		 * Some Cisco APs report all operating class values as 0
+		 * in the Neighbor Report Responses.  Work around this by
+		 * using the most likely operating class for the channel
+		 * number as the 2.4GHz and 5GHz bands happen to mostly
+		 * use channels in two disjoint ranges.
+		 */
+		if (info->channel_num >= 1 && info->channel_num <= 14)
+			band = SCAN_BAND_2_4_GHZ;
+		else if (info->channel_num >= 36 && info->channel_num <= 169)
+			band = SCAN_BAND_5_GHZ;
+		else {
+			l_debug("Ignored: 0 oper class with an unusual "
+				"channel number");
+
+			return 0;
+		}
+	} else {
+		band = scan_oper_class_to_band(country, info->oper_class);
+		if (!band) {
+			l_debug("Ignored: unsupported oper class");
+
+			return 0;
+		}
+	}
+
+	freq = scan_channel_to_freq(info->channel_num, band);
+	if (!freq) {
+		l_debug("Ignored: unsupported channel");
+
+		return 0;
+	}
+
+	if (out_band)
+		*out_band = band;
+
+	return freq;
+}
+
+static void parse_neighbor_report(struct station *station,
+					const uint8_t *reports,
+					size_t reports_len,
+					struct scan_freq_set **set)
+{
+	struct ie_tlv_iter iter;
+	int count_md = 0, count_no_md = 0;
+	struct scan_freq_set *freq_set_md, *freq_set_no_md;
+	uint32_t current_freq = 0;
+	struct handshake_state *hs = netdev_get_handshake(station->netdev);
+
+	freq_set_md = scan_freq_set_new();
+	freq_set_no_md = scan_freq_set_new();
+
+	ie_tlv_iter_init(&iter, reports, reports_len);
+
+	/* First see if any of the reports contain the MD bit set */
+	while (ie_tlv_iter_next(&iter)) {
+		struct ie_neighbor_report_info info;
+		uint32_t freq;
+		enum scan_band band;
+		const uint8_t *cc = NULL;
+
+		if (ie_tlv_iter_get_tag(&iter) != IE_TYPE_NEIGHBOR_REPORT)
+			continue;
+
+		if (ie_parse_neighbor_report(&iter, &info) < 0)
+			continue;
+
+		l_debug("Neighbor report received for %s: ch %i "
+				"(oper class %i), %s",
+				util_address_to_string(info.addr),
+				(int) info.channel_num, (int) info.oper_class,
+				info.md ? "MD set" : "MD not set");
+
+		if (station->connected_bss->cc_present)
+			cc = station->connected_bss->cc;
+
+		freq = station_freq_from_neighbor_report(cc, &info, &band);
+		if (!freq)
+			continue;
+
+		/* Skip if the band is not supported */
+		if (!(band & wiphy_get_supported_bands(station->wiphy)))
+			continue;
+
+		if (!memcmp(info.addr,
+				station->connected_bss->addr, ETH_ALEN)) {
+			/*
+			 * If this report is for the current AP, don't add
+			 * it to any of the lists yet.  We will need to scan
+			 * its channel because it may still be the best ranked
+			 * or the only visible AP.
+			 */
+			current_freq = freq;
+
+			continue;
+		}
+
+		/* Add the frequency to one of the lists */
+		if (info.md && hs->mde) {
+			scan_freq_set_add(freq_set_md, freq);
+
+			count_md += 1;
+		} else {
+			scan_freq_set_add(freq_set_no_md, freq);
+
+			count_no_md += 1;
+		}
+	}
+
+	if (!current_freq)
+		current_freq = station->connected_bss->frequency;
+
+	/*
+	 * If there are neighbor reports with the MD bit set then the bit
+	 * is probably valid so scan only the frequencies of the neighbors
+	 * with that bit set, which will allow us to use Fast Transition.
+	 * Some APs, such as those based on hostapd do not set the MD bit
+	 * even if the neighbor is within the MD.
+	 *
+	 * In any case we only select the frequencies here and will check
+	 * the IEs in the scan results as the authoritative information
+	 * on whether we can use Fast Transition, and rank BSSes based on
+	 * that.
+	 *
+	 * TODO: possibly save the neighbors from outside the MD and if
+	 * none of the ones in the MD end up working, try a non-FT
+	 * transition to those neighbors.  We should be using a
+	 * blacklisting mechanism (for both initial connection and
+	 * transitions) so that cound_md would not count the
+	 * BSSes already used and when it goes down to 0 we'd
+	 * automatically fall back to the non-FT candidates and then to
+	 * full scan.
+	 */
+	if (count_md) {
+		scan_freq_set_add(freq_set_md, current_freq);
+		*set = freq_set_md;
+		scan_freq_set_free(freq_set_no_md);
+	} else if (count_no_md) {
+		scan_freq_set_add(freq_set_no_md, current_freq);
+		*set = freq_set_no_md;
+		scan_freq_set_free(freq_set_md);
+	} else {
+		scan_freq_set_free(freq_set_no_md);
+		scan_freq_set_free(freq_set_md);
+		*set = NULL;
+	}
+}
+
+static void station_early_neighbor_report_cb(struct netdev *netdev, int err,
+						const uint8_t *reports,
+						size_t reports_len,
+						void *user_data)
+{
+	struct station *station = user_data;
+
+	l_debug("ifindex: %u, error: %d(%s)",
+			netdev_get_ifindex(station->netdev),
+			err, err < 0 ? strerror(-err) : "");
+
+	if (!reports || err)
+		return;
+
+	parse_neighbor_report(station, reports, reports_len,
+				&station->roam_freqs);
+}
+
 static void station_roamed(struct station *station)
 {
 	station->roam_scan_full = false;
@@ -1447,6 +1621,12 @@ static void station_roamed(struct station *station)
 		station->roam_freqs = NULL;
 	}
 
+	if (station->connected_bss->cap_rm_neighbor_report) {
+		if (netdev_neighbor_report_req(station->netdev,
+					station_early_neighbor_report_cb) < 0)
+			l_warn("Could not request neighbor report");
+	}
+
 	station_enter_state(station, STATION_STATE_CONNECTED);
 }
 
@@ -1920,162 +2100,6 @@ static int station_roam_scan_known_freqs(struct station *station)
 	return r;
 }
 
-static uint32_t station_freq_from_neighbor_report(const uint8_t *country,
-		struct ie_neighbor_report_info *info, enum scan_band *out_band)
-{
-	enum scan_band band;
-	uint32_t freq;
-
-	if (info->oper_class == 0) {
-		/*
-		 * Some Cisco APs report all operating class values as 0
-		 * in the Neighbor Report Responses.  Work around this by
-		 * using the most likely operating class for the channel
-		 * number as the 2.4GHz and 5GHz bands happen to mostly
-		 * use channels in two disjoint ranges.
-		 */
-		if (info->channel_num >= 1 && info->channel_num <= 14)
-			band = SCAN_BAND_2_4_GHZ;
-		else if (info->channel_num >= 36 && info->channel_num <= 169)
-			band = SCAN_BAND_5_GHZ;
-		else {
-			l_debug("Ignored: 0 oper class with an unusual "
-				"channel number");
-
-			return 0;
-		}
-	} else {
-		band = scan_oper_class_to_band(country, info->oper_class);
-		if (!band) {
-			l_debug("Ignored: unsupported oper class");
-
-			return 0;
-		}
-	}
-
-	freq = scan_channel_to_freq(info->channel_num, band);
-	if (!freq) {
-		l_debug("Ignored: unsupported channel");
-
-		return 0;
-	}
-
-	if (out_band)
-		*out_band = band;
-
-	return freq;
-}
-
-static void parse_neighbor_report(struct station *station,
-					const uint8_t *reports,
-					size_t reports_len,
-					struct scan_freq_set **set)
-{
-	struct ie_tlv_iter iter;
-	int count_md = 0, count_no_md = 0;
-	struct scan_freq_set *freq_set_md, *freq_set_no_md;
-	uint32_t current_freq = 0;
-	struct handshake_state *hs = netdev_get_handshake(station->netdev);
-
-	freq_set_md = scan_freq_set_new();
-	freq_set_no_md = scan_freq_set_new();
-
-	ie_tlv_iter_init(&iter, reports, reports_len);
-
-	/* First see if any of the reports contain the MD bit set */
-	while (ie_tlv_iter_next(&iter)) {
-		struct ie_neighbor_report_info info;
-		uint32_t freq;
-		enum scan_band band;
-		const uint8_t *cc = NULL;
-
-		if (ie_tlv_iter_get_tag(&iter) != IE_TYPE_NEIGHBOR_REPORT)
-			continue;
-
-		if (ie_parse_neighbor_report(&iter, &info) < 0)
-			continue;
-
-		l_debug("Neighbor report received for %s: ch %i "
-				"(oper class %i), %s",
-				util_address_to_string(info.addr),
-				(int) info.channel_num, (int) info.oper_class,
-				info.md ? "MD set" : "MD not set");
-
-		if (station->connected_bss->cc_present)
-			cc = station->connected_bss->cc;
-
-		freq = station_freq_from_neighbor_report(cc, &info, &band);
-		if (!freq)
-			continue;
-
-		/* Skip if the band is not supported */
-		if (!(band & wiphy_get_supported_bands(station->wiphy)))
-			continue;
-
-		if (!memcmp(info.addr,
-				station->connected_bss->addr, ETH_ALEN)) {
-			/*
-			 * If this report is for the current AP, don't add
-			 * it to any of the lists yet.  We will need to scan
-			 * its channel because it may still be the best ranked
-			 * or the only visible AP.
-			 */
-			current_freq = freq;
-
-			continue;
-		}
-
-		/* Add the frequency to one of the lists */
-		if (info.md && hs->mde) {
-			scan_freq_set_add(freq_set_md, freq);
-
-			count_md += 1;
-		} else {
-			scan_freq_set_add(freq_set_no_md, freq);
-
-			count_no_md += 1;
-		}
-	}
-
-	if (!current_freq)
-		current_freq = station->connected_bss->frequency;
-
-	/*
-	 * If there are neighbor reports with the MD bit set then the bit
-	 * is probably valid so scan only the frequencies of the neighbors
-	 * with that bit set, which will allow us to use Fast Transition.
-	 * Some APs, such as those based on hostapd do not set the MD bit
-	 * even if the neighbor is within the MD.
-	 *
-	 * In any case we only select the frequencies here and will check
-	 * the IEs in the scan results as the authoritative information
-	 * on whether we can use Fast Transition, and rank BSSes based on
-	 * that.
-	 *
-	 * TODO: possibly save the neighbors from outside the MD and if
-	 * none of the ones in the MD end up working, try a non-FT
-	 * transition to those neighbors.  We should be using a
-	 * blacklisting mechanism (for both initial connection and
-	 * transitions) so that cound_md would not count the
-	 * BSSes already used and when it goes down to 0 we'd
-	 * automatically fall back to the non-FT candidates and then to
-	 * full scan.
-	 */
-	if (count_md) {
-		scan_freq_set_add(freq_set_md, current_freq);
-		*set = freq_set_md;
-		scan_freq_set_free(freq_set_no_md);
-	} else if (count_no_md) {
-		scan_freq_set_add(freq_set_no_md, current_freq);
-		*set = freq_set_no_md;
-		scan_freq_set_free(freq_set_md);
-	} else {
-		scan_freq_set_free(freq_set_no_md);
-		scan_freq_set_free(freq_set_md);
-		*set = NULL;
-	}
-}
-
 static void station_neighbor_report_cb(struct netdev *netdev, int err,
 					const uint8_t *reports,
 					size_t reports_len, void *user_data)
@@ -2461,24 +2485,6 @@ static void station_connect_dbus_reply(struct station *station,
 	dbus_pending_reply(&station->connect_pending, reply);
 }
 
-static void station_early_neighbor_report_cb(struct netdev *netdev, int err,
-						const uint8_t *reports,
-						size_t reports_len,
-						void *user_data)
-{
-	struct station *station = user_data;
-
-	l_debug("ifindex: %u, error: %d(%s)",
-			netdev_get_ifindex(station->netdev),
-			err, err < 0 ? strerror(-err) : "");
-
-	if (!reports || err)
-		return;
-
-	parse_neighbor_report(station, reports, reports_len,
-				&station->roam_freqs);
-}
-
 static void station_connect_cb(struct netdev *netdev, enum netdev_result result,
 					void *event_data, void *user_data)
 {
-- 
2.26.2

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

* Re: [PATCH 1/3] station: clear out roam frequencies after roam
  2021-03-29 19:07 [PATCH 1/3] station: clear out roam frequencies after roam James Prestwood
  2021-03-29 19:07 ` [PATCH 2/3] station: unify firmware/normal roaming James Prestwood
  2021-03-29 19:07 ` [PATCH 3/3] station: get neighbor report after roaming James Prestwood
@ 2021-03-29 19:12 ` Denis Kenzior
  2 siblings, 0 replies; 4+ messages in thread
From: Denis Kenzior @ 2021-03-29 19:12 UTC (permalink / raw)
  To: iwd

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

Hi James,

On 3/29/21 2:07 PM, James Prestwood wrote:
> ---
>   src/station.c | 5 +++++
>   1 file changed, 5 insertions(+)
> 

All applied, thanks.

Regards,
-Denis

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

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

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-29 19:07 [PATCH 1/3] station: clear out roam frequencies after roam James Prestwood
2021-03-29 19:07 ` [PATCH 2/3] station: unify firmware/normal roaming James Prestwood
2021-03-29 19:07 ` [PATCH 3/3] station: get neighbor report after roaming James Prestwood
2021-03-29 19:12 ` [PATCH 1/3] station: clear out roam frequencies after roam Denis Kenzior

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.