bgscan_simple: Refinements to fast-scan backoff

These changes account for situations where the CQM threshold
might be approximately the same as the currently received signal,
and thus CQM events are triggered often due to measurement
error/small fluctuations.  This results in scanning occurring
too frequently.

Firstly, inhibit the immediate scan when the short-scan count
is at the maximum.  This keeps bursts of CQM toggling from
causing a torrent of back-to-back scans.  This does not inhibit
immediate scans if the CQM triggers a second time (if the signal
falls lower past the hysteresis).  This reduces the scan rate in
the worst case (fast-rate toggling high/low CQM events) to the
short scan interval.

Secondly, change the behavior of the short scan count so it acts like
a "leaky bucket".  As we perform short-scans, the bucket fills until
it reaches a maximal short-scan count, at which we back-off and
revert to a long scan interval.  The short scan count decreases by
one (emptying the bucket) every time we complete a long scan interval
without a low-RSSI CQM event.

This reduces the impact of medium-rate toggling of high/low CQM
events, reducing the number of short-interval scans that occur before
returning to a long-interval if the system was recently doing
short scans.
This commit is contained in:
Paul Stewart 2012-02-05 18:43:06 +02:00 committed by Jouni Malinen
parent 0f4668ceac
commit 87343c2017

View file

@ -29,6 +29,7 @@ struct bgscan_simple_data {
int scan_interval;
int signal_threshold;
int short_scan_count; /* counter for scans using short scan interval */
int max_short_scans; /* maximum times we short-scan before back-off */
int short_interval; /* use if signal < threshold */
int long_interval; /* use if signal > threshold */
struct os_time last_bgscan;
@ -66,12 +67,19 @@ static void bgscan_simple_timeout(void *eloop_ctx, void *timeout_ctx)
* scanning at the short scan interval. After that,
* revert to the long scan interval.
*/
if (data->short_scan_count >
data->long_interval / data->short_interval + 1) {
if (data->short_scan_count > data->max_short_scans) {
data->scan_interval = data->long_interval;
wpa_printf(MSG_DEBUG, "bgscan simple: Backing "
"off to long scan interval");
}
} else if (data->short_scan_count > 0) {
/*
* If we lasted a long scan interval without any
* CQM triggers, decrease the short-scan count,
* which allows 1 more short-scan interval to
* occur in the future when CQM triggers.
*/
data->short_scan_count--;
}
os_get_time(&data->last_bgscan);
}
@ -138,6 +146,7 @@ static void * bgscan_simple_init(struct wpa_supplicant *wpa_s,
}
data->scan_interval = data->short_interval;
data->max_short_scans = data->long_interval / data->short_interval + 1;
if (data->signal_threshold) {
/* Poll for signal info to set initial scan interval */
struct wpa_signal_info siginfo;
@ -222,9 +231,15 @@ static void bgscan_simple_notify_signal_change(void *priv, int above,
wpa_printf(MSG_DEBUG, "bgscan simple: Start using short "
"bgscan interval");
data->scan_interval = data->short_interval;
data->short_scan_count = 0;
os_get_time(&now);
if (now.sec > data->last_bgscan.sec + 1)
if (now.sec > data->last_bgscan.sec + 1 &&
data->short_scan_count <= data->max_short_scans)
/*
* If we haven't just previously (<1 second ago)
* performed a scan, and we haven't depleted our
* budget for short-scans, perform a scan
* immediately.
*/
scan = 1;
else if (data->last_bgscan.sec + data->long_interval >
now.sec + data->scan_interval) {