[PATCH 2/6] Rewrite roaming logic

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The roaming logic is currently too aggressive and full of holes. In
particular, the (arbitrary) values we currently assign to the roaming
difficulty are too small; an AP can reasonably move up or down 5dB in
RSSI in an enterprise environment even when the device is static. The
logic needs to be more resilient to these small fluctuations.

The following notes describe each of the changes made and the rationale
behind it.
1. Remove all short-circuiting and allow the roaming logic below to run
   its course. This way we avoid overlooking important factors.
2. Add a to_2ghz flag that indicates if we are moving from a 5ghz AP to
   a 2ghz AP. This should increase the difficulty to roam in that
   direction and mirror the to_5ghz flag.
3. Adjust the min_diff upward across the board. Originally, we would
   roam with a RSSI imporvement of 1dB in the weakest bucket and 5dB in
   the strongest bucket. RSSI is fairly fickle and APs can easily
   fluctuate by more than that in a normal enterprise environment.
   Additionally, there should be more buckets. We currently stop
   differentiating after the RSSI is at least -70dB. This is still
   pretty weak, and the difficulty should continue to increase above
   that. Move the threshold up to 4dB in the weakest bucket and 10dB in
   the strongest bucket, and add two more buckets (up to -60dB).
4. We adjust the roam difficulty up and down based on the estimated
   throughput of the selected AP relative to the estimated throughput of
   the current AP. Small gains or losses in estimated throughput should
   not be rewarded or penalized as heavily as they are now since
   estimated throughput is a hand-wavy measurement to begin with. Relax
   these adjustments.
5. At lower signal levels, we shouldn't care as much about estimated
   throughput gains. In particular, below a certain threshold, we should
   only be chasing RSSI gains in search of a more stable connection. For
   example, it doesn't matter that we gain 10% estimated throughput if
   our RSSI is bad. Introduce an adjust_factor so that we can weight
   estimated throughput differently.

Signed-off-by: Matthew Wang <matthewmwang@xxxxxxxxxxxx>
---
 wpa_supplicant/events.c | 103 +++++++++++++++++++---------------------
 1 file changed, 50 insertions(+), 53 deletions(-)

diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index f0f91892f..d6e4be3c7 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -1782,8 +1782,10 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
 	struct wpa_bss *current_bss = NULL;
 #ifndef CONFIG_NO_ROAMING
 	int min_diff, diff;
-	int to_5ghz;
+	int to_2ghz, to_5ghz;
 	int cur_level;
+	int adjust = 0;
+	double adjust_factor, est_ratio;
 	unsigned int cur_est, sel_est;
 	struct wpa_signal_info si;
 	int cur_snr = 0;
@@ -1871,65 +1873,60 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
 			cur_level, cur_snr, cur_est);
 	}
 
-	if (sel_est > cur_est + 5000) {
-		wpa_dbg(wpa_s, MSG_DEBUG,
-			"Allow reassociation - selected BSS has better estimated throughput");
-		return 1;
-	}
-
+	to_2ghz = current_bss->freq > 4000 && selected->freq < 4000;
 	to_5ghz = selected->freq > 4000 && current_bss->freq < 4000;
 
-	if (cur_level < 0 && cur_level > selected->level + to_5ghz * 2 &&
-	    sel_est < cur_est * 1.2) {
-		wpa_dbg(wpa_s, MSG_DEBUG, "Skip roam - Current BSS has better "
-			"signal level");
-		return 0;
-	}
-
-	if (cur_est > sel_est + 5000) {
-		wpa_dbg(wpa_s, MSG_DEBUG,
-			"Skip roam - Current BSS has better estimated throughput");
-		return 0;
+	/*
+	 * Set the minimum RSSI difference needed to roam (`min_diff`) and the
+	 * estimated throughput weight (`adjust_factor`) based on the RSSI of
+	 * the current AP. At low RSSI (< -70 dBm), we ignore estimated
+	 * throughput gains and only consider RSSI gains. At higher RSSI,
+	 * `adjust_factor` is multiplied by `adjust` (set below according to the
+	 * selected AP's estimated throughput relative to the current AP's
+	 * estimated throughput) to influence the `min_diff`.
+	 */
+	if (cur_level < -85) { /* ..-86 dBm */
+		min_diff = 4;
+		adjust_factor = 0;
+	} else if (cur_level < -80) { /* -85..-81 dBm */
+		min_diff = 5;
+		adjust_factor = 0.2;
+	} else if (cur_level < -75) { /* -80..-76 dBm */
+		min_diff = 6;
+		adjust_factor = 0.4;
+	} else if (cur_level < -70) { /* -75..-71 dBm */
+		min_diff = 7;
+		adjust_factor = 0.6;
+	} else if (cur_level < -65) { /* -70..-66 dBm */
+		min_diff = 8;
+		adjust_factor = 0.8;
+	} else if (cur_level < -60) { /* -65..-61 dBm */
+		min_diff = 9;
+		adjust_factor = 1.0;
+	} else if (cur_level < 0) { /* -60..-1 dBm */
+		min_diff = 10;
+		adjust_factor = 1.2;
+	} else { /* unspecified units (not in dBm) */
+		min_diff = 5;
+		adjust_factor = 1.0;
 	}
 
-	if (cur_snr > GREAT_SNR) {
-		wpa_dbg(wpa_s, MSG_DEBUG,
-			"Skip roam - Current BSS has good SNR (%u > %u)",
-			cur_snr, GREAT_SNR);
-		return 0;
+	sel_est = selected->est_throughput;
+	if (cur_est > sel_est) {
+		adjust = 1;
+		est_ratio = sel_est == 0 ? 2 : (double) cur_est / sel_est;
+	} else {
+		adjust = -1;
+		est_ratio = cur_est == 0 ? 2 : (double) sel_est / cur_est;
 	}
+	if (est_ratio > 2)
+		est_ratio = 2;
+	adjust *= (int) ((est_ratio - 1) * 10);
+	min_diff += adjust * adjust_factor;
 
-	if (cur_level < -85) /* ..-86 dBm */
-		min_diff = 1;
-	else if (cur_level < -80) /* -85..-81 dBm */
-		min_diff = 2;
-	else if (cur_level < -75) /* -80..-76 dBm */
-		min_diff = 3;
-	else if (cur_level < -70) /* -75..-71 dBm */
-		min_diff = 4;
-	else if (cur_level < 0) /* -70..-1 dBm */
-		min_diff = 5;
-	else /* unspecified units (not in dBm) */
-		min_diff = 2;
-
-	if (cur_est > sel_est * 1.5)
-		min_diff += 10;
-	else if (cur_est > sel_est * 1.2)
-		min_diff += 5;
-	else if (cur_est > sel_est * 1.1)
+	if (to_2ghz)
 		min_diff += 2;
-	else if (cur_est > sel_est)
-		min_diff++;
-	else if (sel_est > cur_est * 1.5)
-		min_diff -= 10;
-	else if (sel_est > cur_est * 1.2)
-		min_diff -= 5;
-	else if (sel_est > cur_est * 1.1)
-		min_diff -= 2;
-	else if (sel_est > cur_est)
-		min_diff--;
-
-	if (to_5ghz)
+	else if (to_5ghz)
 		min_diff -= 2;
 	diff = selected->level - cur_level;
 	if (diff < min_diff) {
-- 
2.27.0.rc0.183.gde8f92d652-goog


_______________________________________________
Hostap mailing list
Hostap@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/hostap



[Index of Archives]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux