Add ignore_old_scan_res configuration parameter

This can be used to configure wpa_supplicant to ignore old scan results
from the driver cache in cases where such results were not updated after
the scan trigger from wpa_supplicant. This can be useful in some cases
where the driver may cache information for a significant time and the AP
configuration is changing. Many such cases are for testing scripts, but
this could potentially be useful for some WPS use cases, too.

Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2013-03-31 17:52:23 +03:00
parent 9599ccc2dd
commit 4342326fc7
8 changed files with 67 additions and 13 deletions

View file

@ -224,11 +224,27 @@ struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid,
} }
static void wpa_bss_copy_res(struct wpa_bss *dst, struct wpa_scan_res *src, static void calculate_update_time(const struct os_time *fetch_time,
struct os_time *fetch_time) unsigned int age_ms,
struct os_time *update_time)
{ {
os_time_t usec; os_time_t usec;
update_time->sec = fetch_time->sec;
update_time->usec = fetch_time->usec;
update_time->sec -= age_ms / 1000;
usec = (age_ms % 1000) * 1000;
if (update_time->usec < usec) {
update_time->sec--;
update_time->usec += 1000000;
}
update_time->usec -= usec;
}
static void wpa_bss_copy_res(struct wpa_bss *dst, struct wpa_scan_res *src,
struct os_time *fetch_time)
{
dst->flags = src->flags; dst->flags = src->flags;
os_memcpy(dst->bssid, src->bssid, ETH_ALEN); os_memcpy(dst->bssid, src->bssid, ETH_ALEN);
dst->freq = src->freq; dst->freq = src->freq;
@ -239,15 +255,7 @@ static void wpa_bss_copy_res(struct wpa_bss *dst, struct wpa_scan_res *src,
dst->level = src->level; dst->level = src->level;
dst->tsf = src->tsf; dst->tsf = src->tsf;
dst->last_update.sec = fetch_time->sec; calculate_update_time(fetch_time, src->age, &dst->last_update);
dst->last_update.usec = fetch_time->usec;
dst->last_update.sec -= src->age / 1000;
usec = (src->age % 1000) * 1000;
if (dst->last_update.usec < usec) {
dst->last_update.sec--;
dst->last_update.usec += 1000000;
}
dst->last_update.usec -= usec;
} }
@ -567,6 +575,21 @@ void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s,
const u8 *ssid, *p2p; const u8 *ssid, *p2p;
struct wpa_bss *bss; struct wpa_bss *bss;
if (wpa_s->conf->ignore_old_scan_res) {
struct os_time update;
calculate_update_time(fetch_time, res->age, &update);
if (os_time_before(&update, &wpa_s->scan_trigger_time)) {
struct os_time age;
os_time_sub(&wpa_s->scan_trigger_time, &update, &age);
wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Ignore driver BSS "
"table entry that is %u.%06u seconds older "
"than our scan trigger",
(unsigned int) age.sec,
(unsigned int) age.usec);
return;
}
}
ssid = wpa_scan_get_ie(res, WLAN_EID_SSID); ssid = wpa_scan_get_ie(res, WLAN_EID_SSID);
if (ssid == NULL) { if (ssid == NULL) {
wpa_dbg(wpa_s, MSG_DEBUG, "BSS: No SSID IE included for " wpa_dbg(wpa_s, MSG_DEBUG, "BSS: No SSID IE included for "

View file

@ -3089,6 +3089,7 @@ static const struct global_parse_data global_fields[] = {
{ INT(dtim_period), 0 }, { INT(dtim_period), 0 },
{ INT(beacon_int), 0 }, { INT(beacon_int), 0 },
{ FUNC(ap_vendor_elements), 0 }, { FUNC(ap_vendor_elements), 0 },
{ INT_RANGE(ignore_old_scan_res, 0, 1), 0 },
}; };
#undef FUNC #undef FUNC

View file

@ -844,6 +844,16 @@ struct wpa_config {
* elements (id+len+payload for one or more elements). * elements (id+len+payload for one or more elements).
*/ */
struct wpabuf *ap_vendor_elements; struct wpabuf *ap_vendor_elements;
/**
* ignore_old_scan_res - Ignore scan results older than request
*
* The driver may have a cache of scan results that makes it return
* information that is older than our scan trigger. This parameter can
* be used to configure such old information to be ignored instead of
* allowing it to update the internal BSS table.
*/
int ignore_old_scan_res;
}; };

View file

@ -1004,6 +1004,10 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
fprintf(f, "\n"); fprintf(f, "\n");
} }
} }
if (config->ignore_old_scan_res)
fprintf(f, "ignore_old_scan_res=%d\n",
config->ignore_old_scan_res);
} }
#endif /* CONFIG_NO_CONFIG_WRITE */ #endif /* CONFIG_NO_CONFIG_WRITE */

View file

@ -216,8 +216,10 @@ static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
break; break;
} }
} }
} else } else {
os_get_time(&wpa_s->scan_trigger_time);
wpa_s->scan_res_handler = wpas_p2p_scan_res_handler; wpa_s->scan_res_handler = wpas_p2p_scan_res_handler;
}
return ret; return ret;
} }
@ -970,6 +972,7 @@ static void wpas_p2p_clone_config(struct wpa_supplicant *dst,
d->persistent_reconnect = s->persistent_reconnect; d->persistent_reconnect = s->persistent_reconnect;
d->max_num_sta = s->max_num_sta; d->max_num_sta = s->max_num_sta;
d->pbc_in_m1 = s->pbc_in_m1; d->pbc_in_m1 = s->pbc_in_m1;
d->ignore_old_scan_res = s->ignore_old_scan_res;
} }
@ -3550,8 +3553,10 @@ static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq)
* the new scan results become available. * the new scan results become available.
*/ */
ret = wpa_drv_scan(wpa_s, &params); ret = wpa_drv_scan(wpa_s, &params);
if (!ret) if (!ret) {
os_get_time(&wpa_s->scan_trigger_time);
wpa_s->scan_res_handler = wpas_p2p_scan_res_join; wpa_s->scan_res_handler = wpas_p2p_scan_res_join;
}
wpabuf_free(ies); wpabuf_free(ies);

View file

@ -227,6 +227,7 @@ int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s,
wpa_supplicant_notify_scanning(wpa_s, 0); wpa_supplicant_notify_scanning(wpa_s, 0);
wpas_notify_scan_done(wpa_s, 0); wpas_notify_scan_done(wpa_s, 0);
} else { } else {
os_get_time(&wpa_s->scan_trigger_time);
wpa_s->scan_runs++; wpa_s->scan_runs++;
wpa_s->normal_scans++; wpa_s->normal_scans++;
} }

View file

@ -302,6 +302,15 @@ fast_reauth=1
# one or more elements). This is used in AP and P2P GO modes. # one or more elements). This is used in AP and P2P GO modes.
#ap_vendor_elements=dd0411223301 #ap_vendor_elements=dd0411223301
# Ignore scan results older than request
#
# The driver may have a cache of scan results that makes it return
# information that is older than our scan trigger. This parameter can
# be used to configure such old information to be ignored instead of
# allowing it to update the internal BSS table.
#ignore_old_scan_res=0
# Interworking (IEEE 802.11u) # Interworking (IEEE 802.11u)
# Enable Interworking # Enable Interworking

View file

@ -444,6 +444,7 @@ struct wpa_supplicant {
*/ */
MANUAL_SCAN_REQ MANUAL_SCAN_REQ
} scan_req; } scan_req;
struct os_time scan_trigger_time;
int scan_runs; /* number of scan runs since WPS was started */ int scan_runs; /* number of scan runs since WPS was started */
int *next_scan_freqs; int *next_scan_freqs;
int scan_interval; /* time in sec between scans to find suitable AP */ int scan_interval; /* time in sec between scans to find suitable AP */