Add ignore_old_scan_res configuration parameter
authorJouni Malinen <j@w1.fi>
Sun, 31 Mar 2013 14:52:23 +0000 (17:52 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 31 Mar 2013 15:05:42 +0000 (18:05 +0300)
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>

wpa_supplicant/bss.c
wpa_supplicant/config.c
wpa_supplicant/config.h
wpa_supplicant/config_file.c
wpa_supplicant/p2p_supplicant.c
wpa_supplicant/scan.c
wpa_supplicant/wpa_supplicant.conf
wpa_supplicant/wpa_supplicant_i.h

index 602d349..0e1576b 100644 (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,
-                            struct os_time *fetch_time)
+static void calculate_update_time(const struct os_time *fetch_time,
+                                 unsigned int age_ms,
+                                 struct os_time *update_time)
 {
        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;
        os_memcpy(dst->bssid, src->bssid, ETH_ALEN);
        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->tsf = src->tsf;
 
-       dst->last_update.sec = fetch_time->sec;
-       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;
+       calculate_update_time(fetch_time, src->age, &dst->last_update);
 }
 
 
@@ -567,6 +575,21 @@ void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s,
        const u8 *ssid, *p2p;
        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);
        if (ssid == NULL) {
                wpa_dbg(wpa_s, MSG_DEBUG, "BSS: No SSID IE included for "
index 1b71ca7..0d98884 100644 (file)
@@ -3089,6 +3089,7 @@ static const struct global_parse_data global_fields[] = {
        { INT(dtim_period), 0 },
        { INT(beacon_int), 0 },
        { FUNC(ap_vendor_elements), 0 },
+       { INT_RANGE(ignore_old_scan_res, 0, 1), 0 },
 };
 
 #undef FUNC
index 00990cb..1315e7b 100644 (file)
@@ -844,6 +844,16 @@ struct wpa_config {
         * elements (id+len+payload for one or more 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;
 };
 
 
index d5de030..5ca6bf2 100644 (file)
@@ -1004,6 +1004,10 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
                        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 */
index f11d69e..ed235f1 100644 (file)
@@ -216,8 +216,10 @@ static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
                                break;
                        }
                }
-       } else
+       } else {
+               os_get_time(&wpa_s->scan_trigger_time);
                wpa_s->scan_res_handler = wpas_p2p_scan_res_handler;
+       }
 
        return ret;
 }
@@ -970,6 +972,7 @@ static void wpas_p2p_clone_config(struct wpa_supplicant *dst,
        d->persistent_reconnect = s->persistent_reconnect;
        d->max_num_sta = s->max_num_sta;
        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.
         */
        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;
+       }
 
        wpabuf_free(ies);
 
index 1a4f695..8f9449d 100644 (file)
@@ -227,6 +227,7 @@ int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s,
                wpa_supplicant_notify_scanning(wpa_s, 0);
                wpas_notify_scan_done(wpa_s, 0);
        } else {
+               os_get_time(&wpa_s->scan_trigger_time);
                wpa_s->scan_runs++;
                wpa_s->normal_scans++;
        }
index b407060..0935a06 100644 (file)
@@ -302,6 +302,15 @@ fast_reauth=1
 # one or more elements). This is used in AP and P2P GO modes.
 #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)
 
 # Enable Interworking
index 5465c4f..ac745d5 100644 (file)
@@ -444,6 +444,7 @@ struct wpa_supplicant {
                 */
                MANUAL_SCAN_REQ
        } scan_req;
+       struct os_time scan_trigger_time;
        int scan_runs; /* number of scan runs since WPS was started */
        int *next_scan_freqs;
        int scan_interval; /* time in sec between scans to find suitable AP */