Try to avoid some unnecessary roaming
When multiple APs are present in scan results with similar signal strength, wpa_supplicant may end up bounching between them frequently whenever new scan results are available (e.g., due to periodic scans requested by NetworkManager). This can result in unnecessary roaming and in case of the current cfg80211 version, to frequent network disconnections. Do not request a roam if the current BSS is still present in the scan results and the selected BSS is in the same ESS and has only a slighly stronger signal strength.
This commit is contained in:
parent
8856462d61
commit
48563d86b2
1 changed files with 73 additions and 1 deletions
|
@ -776,6 +776,72 @@ static void wpa_supplicant_rsn_preauth_scan_results(
|
|||
}
|
||||
|
||||
|
||||
static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_bss *selected,
|
||||
struct wpa_ssid *ssid,
|
||||
struct wpa_scan_results *scan_res)
|
||||
{
|
||||
size_t i;
|
||||
struct wpa_scan_res *current_bss = NULL;
|
||||
int min_diff;
|
||||
|
||||
if (wpa_s->reassociate)
|
||||
return 1; /* explicit request to reassociate */
|
||||
if (wpa_s->wpa_state < WPA_ASSOCIATED)
|
||||
return 1; /* we are not associated; continue */
|
||||
if (wpa_s->current_ssid == NULL)
|
||||
return 1; /* unknown current SSID */
|
||||
if (wpa_s->current_ssid != ssid)
|
||||
return 1; /* different network block */
|
||||
|
||||
for (i = 0; i < scan_res->num; i++) {
|
||||
struct wpa_scan_res *res = scan_res->res[i];
|
||||
const u8 *ie;
|
||||
if (os_memcmp(res->bssid, wpa_s->bssid, ETH_ALEN) != 0)
|
||||
continue;
|
||||
|
||||
ie = wpa_scan_get_ie(res, WLAN_EID_SSID);
|
||||
if (ie == NULL)
|
||||
continue;
|
||||
if (ie[1] != wpa_s->current_ssid->ssid_len ||
|
||||
os_memcmp(ie + 2, wpa_s->current_ssid->ssid, ie[1]) != 0)
|
||||
continue;
|
||||
current_bss = res;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!current_bss)
|
||||
return 1; /* current BSS not seen in scan results */
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Considering within-ESS reassociation");
|
||||
wpa_printf(MSG_DEBUG, "Current BSS: " MACSTR " level=%d",
|
||||
MAC2STR(current_bss->bssid), current_bss->level);
|
||||
wpa_printf(MSG_DEBUG, "Selected BSS: " MACSTR " level=%d",
|
||||
MAC2STR(selected->bssid), selected->level);
|
||||
|
||||
min_diff = 2;
|
||||
if (current_bss->level < 0) {
|
||||
if (current_bss->level < -85)
|
||||
min_diff = 1;
|
||||
else if (current_bss->level < -80)
|
||||
min_diff = 2;
|
||||
else if (current_bss->level < -75)
|
||||
min_diff = 3;
|
||||
else if (current_bss->level < -70)
|
||||
min_diff = 4;
|
||||
else
|
||||
min_diff = 5;
|
||||
}
|
||||
if (abs(current_bss->level - selected->level) < min_diff) {
|
||||
wpa_printf(MSG_DEBUG, "Skip roam - too small difference in "
|
||||
"signal level");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
|
||||
union wpa_event_data *data)
|
||||
{
|
||||
|
@ -832,11 +898,17 @@ static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
|
|||
wpa_supplicant_rsn_preauth_scan_results(wpa_s, scan_res);
|
||||
|
||||
selected = wpa_supplicant_pick_network(wpa_s, scan_res, &ssid);
|
||||
wpa_scan_results_free(scan_res);
|
||||
|
||||
if (selected) {
|
||||
int skip;
|
||||
skip = !wpa_supplicant_need_to_roam(wpa_s, selected, ssid,
|
||||
scan_res);
|
||||
wpa_scan_results_free(scan_res);
|
||||
if (skip)
|
||||
return;
|
||||
wpa_supplicant_connect(wpa_s, selected, ssid);
|
||||
} else {
|
||||
wpa_scan_results_free(scan_res);
|
||||
wpa_printf(MSG_DEBUG, "No suitable network found");
|
||||
ssid = wpa_supplicant_pick_new_network(wpa_s);
|
||||
if (ssid) {
|
||||
|
|
Loading…
Reference in a new issue