]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
RRM: Enable beacon report with active/passive scan for all drivers
authorJouni Malinen <j@w1.fi>
Mon, 2 Jan 2017 21:04:02 +0000 (23:04 +0200)
committerJouni Malinen <j@w1.fi>
Tue, 3 Jan 2017 17:53:03 +0000 (19:53 +0200)
The requested behavior can be approximated for most use cases even if
the driver does not support reporting exact TSF values for frames.
Enable this capability for all drivers to make beacon report processing
more useful for a common use case.

Signed-off-by: Jouni Malinen <j@w1.fi>
wpa_supplicant/bss.c
wpa_supplicant/bss.h
wpa_supplicant/rrm.c
wpa_supplicant/sme.c
wpa_supplicant/wpa_supplicant_i.h

index 37ac84475dbb7ad65629ac22b841d33c89c53d5d..914bd5d9bc58fbb36cfa0d07ca50a6afb83aa74f 100644 (file)
@@ -269,9 +269,9 @@ struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid,
 }
 
 
-static void calculate_update_time(const struct os_reltime *fetch_time,
-                                 unsigned int age_ms,
-                                 struct os_reltime *update_time)
+void calculate_update_time(const struct os_reltime *fetch_time,
+                          unsigned int age_ms,
+                          struct os_reltime *update_time)
 {
        os_time_t usec;
 
index 97ab0707e3c4fb6e678da495d16393bfd7a1a686..84505fa7caa9bfc5d1d899703ac2616f31d94023 100644 (file)
@@ -168,4 +168,8 @@ static inline void wpa_bss_update_level(struct wpa_bss *bss, int new_level)
                bss->level = new_level;
 }
 
+void calculate_update_time(const struct os_reltime *fetch_time,
+                          unsigned int age_ms,
+                          struct os_reltime *update_time);
+
 #endif /* BSS_H */
index 12a3a925cb439042ecfccadd0d044ffa7c746b63..085d613d7c56473c9c61686a47537e4dc4022aea 100644 (file)
@@ -900,13 +900,22 @@ static void wpas_rrm_scan_timeout(void *eloop_ctx, void *timeout_ctx)
        struct wpa_supplicant *wpa_s = eloop_ctx;
        struct wpa_driver_scan_params *params =
                &wpa_s->beacon_rep_data.scan_params;
+       u16 prev_duration = params->duration;
 
        if (!wpa_s->current_bss)
                return;
 
+       if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_SUPPORT_SET_SCAN_DWELL) &&
+           params->duration) {
+               wpa_printf(MSG_DEBUG,
+                          "RRM: Cannot set scan duration due to missing driver support");
+               params->duration = 0;
+       }
+       os_get_reltime(&wpa_s->beacon_rep_scan);
        if (wpa_s->scanning || wpas_p2p_in_progress(wpa_s) ||
            wpa_supplicant_trigger_scan(wpa_s, params))
                wpas_rrm_refuse_request(wpa_s);
+       params->duration = prev_duration;
 }
 
 
@@ -1033,8 +1042,9 @@ wpas_rm_handle_beacon_req(struct wpa_supplicant *wpa_s,
        if (len < sizeof(*req))
                return -1;
 
-       if (req->mode != BEACON_REPORT_MODE_TABLE &&
-           !(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_SUPPORT_BEACON_REPORT))
+       if (req->mode != BEACON_REPORT_MODE_PASSIVE &&
+           req->mode != BEACON_REPORT_MODE_ACTIVE &&
+           req->mode != BEACON_REPORT_MODE_TABLE)
                return 0;
 
        subelems = req->variable;
@@ -1142,6 +1152,13 @@ wpas_rrm_handle_msr_req_element(
        case MEASURE_TYPE_LCI:
                return wpas_rrm_build_lci_report(wpa_s, req, buf);
        case MEASURE_TYPE_BEACON:
+               if (duration_mandatory &&
+                   !(wpa_s->drv_rrm_flags &
+                     WPA_DRIVER_FLAGS_SUPPORT_SET_SCAN_DWELL)) {
+                       wpa_printf(MSG_DEBUG,
+                                  "RRM: Driver does not support dwell time configuration - reject beacon report with mandatory duration");
+                       goto reject;
+               }
                return wpas_rm_handle_beacon_req(wpa_s, req->token,
                                                 duration_mandatory,
                                                 (const void *) req->variable,
@@ -1341,9 +1358,13 @@ int wpas_beacon_rep_scan_process(struct wpa_supplicant *wpa_s,
        wpa_printf(MSG_DEBUG, "RRM: TSF BSSID: " MACSTR " current BSS: " MACSTR,
                   MAC2STR(info->scan_start_tsf_bssid),
                   MAC2STR(wpa_s->current_bss->bssid));
-       if (os_memcmp(info->scan_start_tsf_bssid, wpa_s->current_bss->bssid,
-                     ETH_ALEN) != 0)
+       if ((wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_SUPPORT_BEACON_REPORT) &&
+           os_memcmp(info->scan_start_tsf_bssid, wpa_s->current_bss->bssid,
+                     ETH_ALEN) != 0) {
+               wpa_printf(MSG_DEBUG,
+                          "RRM: Ignore scan results due to mismatching TSF BSSID");
                goto out;
+       }
 
        for (i = 0; i < scan_res->num; i++) {
                struct wpa_bss *bss =
@@ -1352,9 +1373,45 @@ int wpas_beacon_rep_scan_process(struct wpa_supplicant *wpa_s,
                if (!bss)
                        continue;
 
-               if (os_memcmp(scan_res->res[i]->tsf_bssid,
-                             wpa_s->current_bss->bssid, ETH_ALEN) != 0)
+               if ((wpa_s->drv_rrm_flags &
+                    WPA_DRIVER_FLAGS_SUPPORT_BEACON_REPORT) &&
+                   os_memcmp(scan_res->res[i]->tsf_bssid,
+                             wpa_s->current_bss->bssid, ETH_ALEN) != 0) {
+                       wpa_printf(MSG_DEBUG,
+                                  "RRM: Ignore scan result for " MACSTR
+                                  " due to mismatching TSF BSSID" MACSTR,
+                                  MAC2STR(scan_res->res[i]->bssid),
+                                  MAC2STR(scan_res->res[i]->tsf_bssid));
                        continue;
+               }
+
+               if (!(wpa_s->drv_rrm_flags &
+                     WPA_DRIVER_FLAGS_SUPPORT_BEACON_REPORT)) {
+                       struct os_reltime update_time, diff;
+
+                       /* For now, allow 8 ms older results due to some
+                        * unknown issue with cfg80211 BSS table updates during
+                        * a scan with the current BSS.
+                        * TODO: Fix this more properly to avoid having to have
+                        * this type of hacks in place. */
+                       calculate_update_time(&scan_res->fetch_time,
+                                             scan_res->res[i]->age,
+                                             &update_time);
+                       os_reltime_sub(&wpa_s->beacon_rep_scan,
+                                      &update_time, &diff);
+                       if (os_reltime_before(&update_time,
+                                             &wpa_s->beacon_rep_scan) &&
+                           (diff.sec || diff.usec >= 8000)) {
+                               wpa_printf(MSG_DEBUG,
+                                          "RRM: Ignore scan result for " MACSTR
+                                          " due to old update (age(ms) %u, calculated age %u.%06u seconds)",
+                                          MAC2STR(scan_res->res[i]->bssid),
+                                          scan_res->res[i]->age,
+                                          (unsigned int) diff.sec,
+                                          (unsigned int) diff.usec);
+                               continue;
+                       }
+               }
 
                /*
                 * Don't report results that were not received during the
index 18b1165d57082452dd920adef3f2e54cf4eb8a4d..f478836dbe3c9396538600a52c18ddf4d7442808 100644 (file)
@@ -187,10 +187,9 @@ static void sme_auth_handle_rrm(struct wpa_supplicant *wpa_s,
        if (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)
                *pos |= WLAN_RRM_CAPS_LINK_MEASUREMENT;
 
-       if (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_SUPPORT_BEACON_REPORT)
-               *pos |= WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
-                       WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE;
-       *pos |= WLAN_RRM_CAPS_BEACON_REPORT_TABLE;
+       *pos |= WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
+               WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE |
+               WLAN_RRM_CAPS_BEACON_REPORT_TABLE;
 
        if (wpa_s->lci)
                pos[1] |= WLAN_RRM_CAPS_LCI_MEASUREMENT;
index d911402c9353f02202fe4e5953f063826525d114..576f141b15b9b970cb89a9eb2fb389893dfd48b8 100644 (file)
@@ -1092,6 +1092,8 @@ struct wpa_supplicant {
         */
        struct wpabuf *lci;
        struct os_reltime lci_time;
+
+       struct os_reltime beacon_rep_scan;
 };