Use estimated throughput to avoid signal based roaming decision

Previously, the estimated throughput was used to enable roaming to a
better AP. However, this information was not used when considering a
roam to an AP that has better signal strength, but smaller estimated
throughput. This could result in allowing roaming from 5 GHz band to 2.4
GHz band in cases where 2.4 GHz band has significantly higher signal
strength, but still a lower throughput estimate.

Make this less likely to happen by increasing/reducing the minimum
required signal strength difference based on the estimated throughputs
of the current and selected AP. In addition, add more details about the
selection process to the debug log to make it easier to determine whaty
happened and why.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2016-11-13 17:46:00 +02:00
parent fde3a53132
commit 8d1e693186

View file

@ -1396,8 +1396,9 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
{ {
struct wpa_bss *current_bss = NULL; struct wpa_bss *current_bss = NULL;
#ifndef CONFIG_NO_ROAMING #ifndef CONFIG_NO_ROAMING
int min_diff; int min_diff, diff;
int to_5ghz; int to_5ghz;
int cur_est, sel_est;
#endif /* CONFIG_NO_ROAMING */ #endif /* CONFIG_NO_ROAMING */
if (wpa_s->reassociate) if (wpa_s->reassociate)
@ -1431,12 +1432,13 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
#ifndef CONFIG_NO_ROAMING #ifndef CONFIG_NO_ROAMING
wpa_dbg(wpa_s, MSG_DEBUG, "Considering within-ESS reassociation"); wpa_dbg(wpa_s, MSG_DEBUG, "Considering within-ESS reassociation");
wpa_dbg(wpa_s, MSG_DEBUG, "Current BSS: " MACSTR wpa_dbg(wpa_s, MSG_DEBUG, "Current BSS: " MACSTR
" level=%d snr=%d est_throughput=%u", " freq=%d level=%d snr=%d est_throughput=%u",
MAC2STR(current_bss->bssid), current_bss->level, MAC2STR(current_bss->bssid),
current_bss->freq, current_bss->level,
current_bss->snr, current_bss->est_throughput); current_bss->snr, current_bss->est_throughput);
wpa_dbg(wpa_s, MSG_DEBUG, "Selected BSS: " MACSTR wpa_dbg(wpa_s, MSG_DEBUG, "Selected BSS: " MACSTR
" level=%d snr=%d est_throughput=%u", " freq=%d level=%d snr=%d est_throughput=%u",
MAC2STR(selected->bssid), selected->level, MAC2STR(selected->bssid), selected->freq, selected->level,
selected->snr, selected->est_throughput); selected->snr, selected->est_throughput);
if (wpa_s->current_ssid->bssid_set && if (wpa_s->current_ssid->bssid_set &&
@ -1462,6 +1464,14 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
return 0; return 0;
} }
if (current_bss->est_throughput > selected->est_throughput + 5000) {
wpa_dbg(wpa_s, MSG_DEBUG,
"Skip roam - Current BSS has better estimated throughput");
return 1;
}
cur_est = current_bss->est_throughput;
sel_est = selected->est_throughput;
min_diff = 2; min_diff = 2;
if (current_bss->level < 0) { if (current_bss->level < 0) {
if (current_bss->level < -85) if (current_bss->level < -85)
@ -1474,20 +1484,42 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
min_diff = 4; min_diff = 4;
else else
min_diff = 5; min_diff = 5;
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)
min_diff += 2;
else if (cur_est > sel_est)
min_diff++;
} }
if (to_5ghz) { if (to_5ghz) {
int reduce = 2;
/* Make it easier to move to 5 GHz band */ /* Make it easier to move to 5 GHz band */
if (min_diff > 2) if (sel_est > cur_est * 1.5)
min_diff -= 2; reduce = 5;
else if (sel_est > cur_est * 1.2)
reduce = 4;
else if (sel_est > cur_est * 1.1)
reduce = 3;
if (min_diff > reduce)
min_diff -= reduce;
else else
min_diff = 0; min_diff = 0;
} }
if (abs(current_bss->level - selected->level) < min_diff) { diff = abs(current_bss->level - selected->level);
wpa_dbg(wpa_s, MSG_DEBUG, "Skip roam - too small difference " if (diff < min_diff) {
"in signal level"); wpa_dbg(wpa_s, MSG_DEBUG,
"Skip roam - too small difference in signal level (%d < %d)",
diff, min_diff);
return 0; return 0;
} }
wpa_dbg(wpa_s, MSG_DEBUG,
"Allow reassociation due to difference in signal level (%d >= %d)",
diff, min_diff);
return 1; return 1;
#else /* CONFIG_NO_ROAMING */ #else /* CONFIG_NO_ROAMING */
return 0; return 0;