From 22f0318dbdbddca3dd8a82d0065bc8c93deb23d1 Mon Sep 17 00:00:00 2001 From: Matthew Wang Date: Mon, 16 Mar 2020 14:11:06 -0700 Subject: [PATCH] Interpolate rate calculation functions 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 2 dB increase in RSSI likely isn't responsible for a 17% increase in throughput. Signed-off-by: Matthew Wang --- wpa_supplicant/scan.c | 128 +++++++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 58 deletions(-) diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 98b0408d8..eef3517dc 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -2185,81 +2185,75 @@ void scan_snr(struct wpa_scan_res *res) } +static unsigned int interpolate_rate(int snr, int snr0, int snr1, + int rate0, int rate1) +{ + return rate0 + (snr - snr0) * (rate1 - rate0) / (snr1 - snr0); +} + + +#define INTERPOLATE_RATE(snr0, snr1, rate0, rate1) \ + if (snr < (snr1)) \ + return interpolate_rate(snr, (snr0), (snr1), (rate0), (rate1)) + static unsigned int max_ht20_rate(int snr, int vht) { - if (snr < 2) + if (snr < 0) return 0; - if (snr < 5) - return 6500; /* HT20 MCS0 */ - if (snr < 9) - return 13000; /* HT20 MCS1 */ - if (snr < 11) - return 19500; /* HT20 MCS2 */ - if (snr < 15) - return 26000; /* HT20 MCS3 */ - if (snr < 18) - return 39000; /* HT20 MCS4 */ - if (snr < 20) - return 52000; /* HT20 MCS5 */ - if (snr < 25) - return 58500; /* HT20 MCS6 */ - if (snr < 29 || !vht) - return 65000; /* HT20 MCS7 */ - return 78000; /* VHT20 MCS8 */ + INTERPOLATE_RATE(0, 2, 0, 6500); /* HT20 MCS0 */ + INTERPOLATE_RATE(2, 5, 6500, 13000); /* HT20 MCS1 */ + INTERPOLATE_RATE(5, 9, 13000, 19500); /* HT20 MCS2 */ + INTERPOLATE_RATE(9, 11, 19500, 26000); /* HT20 MCS3 */ + INTERPOLATE_RATE(11, 15, 26000, 39000); /* HT20 MCS4 */ + INTERPOLATE_RATE(15, 18, 39000, 52000); /* HT20 MCS5 */ + INTERPOLATE_RATE(18, 20, 52000, 58500); /* HT20 MCS6 */ + INTERPOLATE_RATE(20, 25, 58500, 65000); /* HT20 MCS7 */ + if (!vht) + return 65000; + INTERPOLATE_RATE(25, 29, 65000, 78000); /* VHT20 MCS8 */ + return 78000; } static unsigned int max_ht40_rate(int snr, int vht) { - if (snr < 5) + if (snr < 0) return 0; - if (snr < 8) - return 13500; /* HT40 MCS0 */ - if (snr < 12) - return 27000; /* HT40 MCS1 */ - if (snr < 14) - return 40500; /* HT40 MCS2 */ - if (snr < 18) - return 54000; /* HT40 MCS3 */ - if (snr < 21) - return 81000; /* HT40 MCS4 */ - if (snr < 23) - return 108000; /* HT40 MCS5 */ - if (snr < 28) - return 121500; /* HT40 MCS6 */ - if (snr < 32 || !vht) - return 135000; /* HT40 MCS7 */ - if (snr < 34) - return 162000; /* VHT40 MCS8 */ - return 180000; /* VHT40 MCS9 */ + INTERPOLATE_RATE(0, 5, 0, 13500); /* HT40 MCS0 */ + INTERPOLATE_RATE(5, 8, 13500, 27000); /* HT40 MCS1 */ + INTERPOLATE_RATE(8, 12, 27000, 40500); /* HT40 MCS2 */ + INTERPOLATE_RATE(12, 14, 40500, 54000); /* HT40 MCS3 */ + INTERPOLATE_RATE(14, 18, 54000, 81000); /* HT40 MCS4 */ + INTERPOLATE_RATE(18, 21, 81000, 108000); /* HT40 MCS5 */ + INTERPOLATE_RATE(21, 23, 108000, 121500); /* HT40 MCS6 */ + INTERPOLATE_RATE(23, 28, 121500, 135000); /* HT40 MCS7 */ + if (!vht) + return 135000; + INTERPOLATE_RATE(28, 32, 135000, 162000); /* VHT40 MCS8 */ + INTERPOLATE_RATE(32, 34, 162000, 180000); /* VHT40 MCS9 */ + return 180000; } static unsigned int max_vht80_rate(int snr) { - if (snr < 8) + if (snr < 0) return 0; - if (snr < 11) - return 29300; /* VHT80 MCS0 */ - if (snr < 15) - return 58500; /* VHT80 MCS1 */ - if (snr < 17) - return 87800; /* VHT80 MCS2 */ - if (snr < 21) - return 117000; /* VHT80 MCS3 */ - if (snr < 24) - return 175500; /* VHT80 MCS4 */ - if (snr < 26) - return 234000; /* VHT80 MCS5 */ - if (snr < 31) - return 263300; /* VHT80 MCS6 */ - if (snr < 35) - return 292500; /* VHT80 MCS7 */ - if (snr < 37) - return 351000; /* VHT80 MCS8 */ - return 390000; /* VHT80 MCS9 */ + INTERPOLATE_RATE(0, 8, 0, 29300); /* VHT80 MCS0 */ + INTERPOLATE_RATE(8, 11, 29300, 58500); /* VHT80 MCS1 */ + INTERPOLATE_RATE(11, 15, 58500, 87800); /* VHT80 MCS2 */ + INTERPOLATE_RATE(15, 17, 87800, 117000); /* VHT80 MCS3 */ + INTERPOLATE_RATE(17, 21, 117000, 175500); /* VHT80 MCS4 */ + INTERPOLATE_RATE(21, 24, 175500, 234000); /* VHT80 MCS5 */ + INTERPOLATE_RATE(24, 26, 234000, 263300); /* VHT80 MCS6 */ + INTERPOLATE_RATE(26, 31, 263300, 292500); /* VHT80 MCS7 */ + INTERPOLATE_RATE(31, 35, 292500, 351000); /* VHT80 MCS8 */ + INTERPOLATE_RATE(35, 37, 351000, 390000); /* VHT80 MCS9 */ + return 390000; } +#undef INTERPOLATE_RATE + unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, const u8 *ies, size_t ies_len, int rate, @@ -2280,14 +2274,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;