diff mbox series

[2/2] Interpolate rate calculation functions

Message ID 20200316211106.131858-2-matthewmwang@chromium.org
State Accepted
Headers show
Series [1/2] Adjust max bitrate SNR floors | expand

Commit Message

Matthew Wang March 16, 2020, 9:11 p.m. UTC
Make max_*_rate functions and rate calculation at the beginning of
wpas_get_est_tpt more continuous. In wpa_supplicant_need_to_roam, we
compare these values to make a roaming decision. However, at certain
SNRs, we see unrealistically large jumps in estimated throughput
according to these functions, leading us to make incorrect roaming
decisions. Perform linear interpolation where applicable to more
accurately reflect actual throughput.

Example:
wlan0: Current BSS: 88:3d:24:b4:95:d2 freq=2412 level=-69 snr=20 est_throughput=54000
wlan0: Selected BSS: 88:3d:24:b4:89:9e freq=2417 level=-67 snr=22 est_throughput=63500
wlan0: Using signal poll values for the current BSS: level=-69 snr=20 est_throughput=54000
wlan0: Allow reassociation - selected BSS has better estimated throughput

2dBm increase in RSSI likely isn't responsible for a 17% increase in
throughput.

Signed-off-by: Matthew Wang <matthewmwang@chromium.org>
---
 wpa_supplicant/scan.c | 94 ++++++++++++++++++++++++++++---------------
 1 file changed, 61 insertions(+), 33 deletions(-)

Comments

Jouni Malinen March 21, 2020, 10:01 p.m. UTC | #1
On Mon, Mar 16, 2020 at 02:11:06PM -0700, Matthew Wang wrote:
> Make max_*_rate functions and rate calculation at the beginning of
> wpas_get_est_tpt more continuous. In wpa_supplicant_need_to_roam, we
> compare these values to make a roaming decision. However, at certain
> SNRs, we see unrealistically large jumps in estimated throughput
> according to these functions, leading us to make incorrect roaming
> decisions. Perform linear interpolation where applicable to more
> accurately reflect actual throughput.

Thanks, both patches applied.

> diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
> @@ -2187,76 +2187,86 @@ void scan_snr(struct wpa_scan_res *res)
>  static unsigned int max_ht20_rate(int snr, int vht)
>  {
> -	if (snr < 2)
> +	if (snr < 0)
>  		return 0;
> +	if (snr < 2)
> +		return 0 + (snr - 0.0) / (2 - 0) * (6500 - 0); /* HT20 MCS0 */
>  	if (snr < 5)
> -		return 6500; /* HT20 MCS0 */
> +		return 6500 + (snr - 2.0) / (5 - 2) * (13000 - 6500); /* HT20 MCS1 */

I changed these to use a macro to make it clearer that the operations
were identical and to avoid having to specify the same values multiple
times. In addition, I replaced floating point arithmetic with integers
since that seemed to provide same results in practice.
diff mbox series

Patch

diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index 98b0408d8..2b7957490 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -2187,76 +2187,86 @@  void scan_snr(struct wpa_scan_res *res)
 
 static unsigned int max_ht20_rate(int snr, int vht)
 {
-	if (snr < 2)
+	if (snr < 0)
 		return 0;
+	if (snr < 2)
+		return 0 + (snr - 0.0) / (2 - 0) * (6500 - 0); /* HT20 MCS0 */
 	if (snr < 5)
-		return 6500; /* HT20 MCS0 */
+		return 6500 + (snr - 2.0) / (5 - 2) * (13000 - 6500); /* HT20 MCS1 */
 	if (snr < 9)
-		return 13000; /* HT20 MCS1 */
+		return 13000 + (snr - 5.0) / (9 - 5) * (19500 - 13000); /* HT20 MCS2 */
 	if (snr < 11)
-		return 19500; /* HT20 MCS2 */
+		return 19500 + (snr - 9.0) / (11 - 9) * (26000 - 19500); /* HT20 MCS3 */
 	if (snr < 15)
-		return 26000; /* HT20 MCS3 */
+		return 26000 + (snr - 11.0) / (15 - 11) * (39000 - 26000); /* HT20 MCS4 */
 	if (snr < 18)
-		return 39000; /* HT20 MCS4 */
+		return 39000 + (snr - 15.0) / (18 - 15) * (52000 - 39000); /* HT20 MCS5 */
 	if (snr < 20)
-		return 52000; /* HT20 MCS5 */
+		return 52000 + (snr - 18.0) / (20 - 18) * (58500 - 52000); /* HT20 MCS6 */
 	if (snr < 25)
-		return 58500; /* HT20 MCS6 */
-	if (snr < 29 || !vht)
-		return 65000; /* HT20 MCS7 */
-	return 78000; /* VHT20 MCS8 */
+		return 58500 + (snr - 20.0) / (25 - 20) * (65000 - 58500); /* HT20 MCS7 */
+	if (!vht)
+		return 65000;
+	if (snr < 29)
+		return 65000 + (snr - 25.0) / (29 - 25) * (78000 - 65000); /* VHT20 MCS8 */
+	return 78000;
 }
 
 
 static unsigned int max_ht40_rate(int snr, int vht)
 {
-	if (snr < 5)
+	if (snr < 0)
 		return 0;
+	if (snr < 5)
+		return 0 + (snr - 0.0) / (5 - 0) * (13500 - 0); /* HT40 MCS0 */
 	if (snr < 8)
-		return 13500; /* HT40 MCS0 */
+		return 13500 + (snr - 5.0) / (8 - 5) * (27000 - 13500); /* HT40 MCS1 */
 	if (snr < 12)
-		return 27000; /* HT40 MCS1 */
+		return 27000 + (snr - 8.0) / (12 - 8) * (40500 - 27000); /* HT40 MCS2 */
 	if (snr < 14)
-		return 40500; /* HT40 MCS2 */
+		return 40500 + (snr - 12.0) / (14 - 12) * (54000 - 40500); /* HT40 MCS3 */
 	if (snr < 18)
-		return 54000; /* HT40 MCS3 */
+		return 54000 + (snr - 14.0) / (18 - 14) * (81000 - 54000); /* HT40 MCS4 */
 	if (snr < 21)
-		return 81000; /* HT40 MCS4 */
+		return 81000 + (snr - 18.0) / (21 - 18) * (108000 - 81000); /* HT40 MCS5 */
 	if (snr < 23)
-		return 108000; /* HT40 MCS5 */
+		return 108000 + (snr - 21.0) / (23 - 21) * (121500 - 108000); /* HT40 MCS6 */
 	if (snr < 28)
-		return 121500; /* HT40 MCS6 */
-	if (snr < 32 || !vht)
-		return 135000; /* HT40 MCS7 */
+		return 121500 + (snr - 23.0) / (28 - 23) * (135000 - 121500); /* HT40 MCS7 */
+	if (!vht)
+		return 135000;
+	if (snr < 32)
+		return 135000 + (snr - 28.0) / (32 - 28) * (162000 - 135000); /* VHT40 MCS8 */
 	if (snr < 34)
-		return 162000; /* VHT40 MCS8 */
-	return 180000; /* VHT40 MCS9 */
+		return 162000 + (snr - 32.0) / (34 - 32) * (180000 - 162000); /* VHT40 MCS9 */
+	return 180000;
 }
 
 
 static unsigned int max_vht80_rate(int snr)
 {
-	if (snr < 8)
+	if (snr < 0)
 		return 0;
+	if (snr < 8)
+		return 0 + (snr - 0.0) / (8 - 0) * (29300 - 0); /* VHT80 MCS0 */
 	if (snr < 11)
-		return 29300; /* VHT80 MCS0 */
+		return 29300 + (snr - 8.0) / (11 - 8) * (58500 - 29300); /* VHT80 MCS1 */
 	if (snr < 15)
-		return 58500; /* VHT80 MCS1 */
+		return 58500 + (snr - 11.0) / (15 - 11) * (87800 - 58500); /* VHT80 MCS2 */
 	if (snr < 17)
-		return 87800; /* VHT80 MCS2 */
+		return 87800 + (snr - 15.0) / (17 - 15) * (117000 - 87800); /* VHT80 MCS3 */
 	if (snr < 21)
-		return 117000; /* VHT80 MCS3 */
+		return 117000 + (snr - 17.0) / (21 - 17) * (175500 - 117000); /* VHT80 MCS4 */
 	if (snr < 24)
-		return 175500; /* VHT80 MCS4 */
+		return 175500 + (snr - 21.0) / (24 - 21) * (234000 - 175500); /* VHT80 MCS5 */
 	if (snr < 26)
-		return 234000; /* VHT80 MCS5 */
+		return 234000 + (snr - 24.0) / (26 - 24) * (263300 - 234000); /* VHT80 MCS6 */
 	if (snr < 31)
-		return 263300; /* VHT80 MCS6 */
+		return 263300 + (snr - 26.0) / (31 - 26) * (292500 - 263300); /* VHT80 MCS7 */
 	if (snr < 35)
-		return 292500; /* VHT80 MCS7 */
+		return 292500 + (snr - 31.0) / (35 - 31) * (351000 - 292500); /* VHT80 MCS8 */
 	if (snr < 37)
-		return 351000; /* VHT80 MCS8 */
+		return 351000 + (snr - 35.0) / (37 - 35) * (390000 - 351000);
 	return 390000; /* VHT80 MCS9 */
 }
 
@@ -2280,14 +2290,32 @@  unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s,
 		rate = 9 * 2;
 	else if (rate > 12 * 2 && snr < 7)
 		rate = 12 * 2;
+	else if (rate > 12 * 2 && snr < 8)
+		rate = 14 * 2;
+	else if (rate > 12 * 2 && snr < 9)
+		rate = 16 * 2;
 	else if (rate > 18 * 2 && snr < 10)
 		rate = 18 * 2;
 	else if (rate > 24 * 2 && snr < 11)
 		rate = 24 * 2;
+	else if (rate > 24 * 2 && snr < 12)
+		rate = 27 * 2;
+	else if (rate > 24 * 2 && snr < 13)
+		rate = 30 * 2;
+	else if (rate > 24 * 2 && snr < 14)
+		rate = 33 * 2;
 	else if (rate > 36 * 2 && snr < 15)
 		rate = 36 * 2;
+	else if (rate > 36 * 2 && snr < 16)
+		rate = 39 * 2;
+	else if (rate > 36 * 2 && snr < 17)
+		rate = 42 * 2;
+	else if (rate > 36 * 2 && snr < 18)
+		rate = 45 * 2;
 	else if (rate > 48 * 2 && snr < 19)
 		rate = 48 * 2;
+	else if (rate > 48 * 2 && snr < 20)
+		rate = 51 * 2;
 	else if (rate > 54 * 2 && snr < 21)
 		rate = 54 * 2;
 	est = rate * 500;