Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

nl80211: support beacon report scanning

Beacon report radio measurement requires reporting observed BSSs
on the channels specified in the beacon request. If the measurement
mode is set to passive or active, it requires actually performing a
scan (passive or active, accordingly), and reporting the time that
the scan was started and the time each beacon/probe was received
(both in terms of TSF of the BSS of the requesting AP). If the
request mode is table, this information is optional.
In addition, the radio measurement request specifies the channel
dwell time for the measurement.

In order to use scan for beacon report when the mode is active or
passive, add a parameter to scan request that specifies the
channel dwell time, and add scan start time and beacon received time
to scan results information.

Supporting beacon report is required for Multi Band Operation (MBO).

Signed-off-by: Assaf Krauss <assaf.krauss@intel.com>
Signed-off-by: David Spinadel <david.spinadel@intel.com>
Signed-off-by: Avraham Stern <avraham.stern@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Avraham Stern and committed by
Johannes Berg
1d76250b f1724b02

+278 -51
+14 -3
drivers/net/wireless/ath/ath6kl/cfg80211.c
··· 859 859 struct ath6kl *ar = vif->ar; 860 860 861 861 if (vif->scan_req) { 862 - cfg80211_scan_done(vif->scan_req, true); 862 + struct cfg80211_scan_info info = { 863 + .aborted = true, 864 + }; 865 + 866 + cfg80211_scan_done(vif->scan_req, &info); 863 867 vif->scan_req = NULL; 864 868 } 865 869 ··· 1073 1069 void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted) 1074 1070 { 1075 1071 struct ath6kl *ar = vif->ar; 1072 + struct cfg80211_scan_info info = { 1073 + .aborted = aborted, 1074 + }; 1076 1075 int i; 1077 1076 1078 1077 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: status%s\n", __func__, ··· 1096 1089 } 1097 1090 1098 1091 out: 1099 - cfg80211_scan_done(vif->scan_req, aborted); 1092 + cfg80211_scan_done(vif->scan_req, &info); 1100 1093 vif->scan_req = NULL; 1101 1094 } 1102 1095 ··· 3621 3614 } 3622 3615 3623 3616 if (vif->scan_req) { 3624 - cfg80211_scan_done(vif->scan_req, true); 3617 + struct cfg80211_scan_info info = { 3618 + .aborted = true, 3619 + }; 3620 + 3621 + cfg80211_scan_done(vif->scan_req, &info); 3625 3622 vif->scan_req = NULL; 3626 3623 } 3627 3624
+5 -1
drivers/net/wireless/ath/wil6210/cfg80211.c
··· 1369 1369 mutex_lock(&wil->mutex); 1370 1370 started = wil_p2p_stop_discovery(wil); 1371 1371 if (started && wil->scan_request) { 1372 - cfg80211_scan_done(wil->scan_request, 1); 1372 + struct cfg80211_scan_info info = { 1373 + .aborted = true, 1374 + }; 1375 + 1376 + cfg80211_scan_done(wil->scan_request, &info); 1373 1377 wil->scan_request = NULL; 1374 1378 wil->radio_wdev = wil->wdev; 1375 1379 }
+10 -2
drivers/net/wireless/ath/wil6210/main.c
··· 850 850 mutex_unlock(&wil->wmi_mutex); 851 851 852 852 if (wil->scan_request) { 853 + struct cfg80211_scan_info info = { 854 + .aborted = true, 855 + }; 856 + 853 857 wil_dbg_misc(wil, "Abort scan_request 0x%p\n", 854 858 wil->scan_request); 855 859 del_timer_sync(&wil->scan_timer); 856 - cfg80211_scan_done(wil->scan_request, true); 860 + cfg80211_scan_done(wil->scan_request, &info); 857 861 wil->scan_request = NULL; 858 862 } 859 863 ··· 1053 1049 (void)wil_p2p_stop_discovery(wil); 1054 1050 1055 1051 if (wil->scan_request) { 1052 + struct cfg80211_scan_info info = { 1053 + .aborted = true, 1054 + }; 1055 + 1056 1056 wil_dbg_misc(wil, "Abort scan_request 0x%p\n", 1057 1057 wil->scan_request); 1058 1058 del_timer_sync(&wil->scan_timer); 1059 - cfg80211_scan_done(wil->scan_request, true); 1059 + cfg80211_scan_done(wil->scan_request, &info); 1060 1060 wil->scan_request = NULL; 1061 1061 } 1062 1062
+5 -1
drivers/net/wireless/ath/wil6210/p2p.c
··· 252 252 mutex_unlock(&wil->mutex); 253 253 254 254 if (started) { 255 + struct cfg80211_scan_info info = { 256 + .aborted = false, 257 + }; 258 + 255 259 mutex_lock(&wil->p2p_wdev_mutex); 256 - cfg80211_scan_done(wil->scan_request, 0); 260 + cfg80211_scan_done(wil->scan_request, &info); 257 261 wil->scan_request = NULL; 258 262 wil->radio_wdev = wil->wdev; 259 263 mutex_unlock(&wil->p2p_wdev_mutex);
+5 -3
drivers/net/wireless/ath/wil6210/wmi.c
··· 426 426 { 427 427 if (wil->scan_request) { 428 428 struct wmi_scan_complete_event *data = d; 429 - bool aborted = (data->status != WMI_SCAN_SUCCESS); 429 + struct cfg80211_scan_info info = { 430 + .aborted = (data->status != WMI_SCAN_SUCCESS), 431 + }; 430 432 431 433 wil_dbg_wmi(wil, "SCAN_COMPLETE(0x%08x)\n", data->status); 432 434 wil_dbg_misc(wil, "Complete scan_request 0x%p aborted %d\n", 433 - wil->scan_request, aborted); 435 + wil->scan_request, info.aborted); 434 436 435 437 del_timer_sync(&wil->scan_timer); 436 438 mutex_lock(&wil->p2p_wdev_mutex); 437 - cfg80211_scan_done(wil->scan_request, aborted); 439 + cfg80211_scan_done(wil->scan_request, &info); 438 440 wil->radio_wdev = wil->wdev; 439 441 mutex_unlock(&wil->p2p_wdev_mutex); 440 442 wil->scan_request = NULL;
+5 -1
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
··· 775 775 if (!aborted) 776 776 cfg80211_sched_scan_results(cfg_to_wiphy(cfg)); 777 777 } else if (scan_request) { 778 + struct cfg80211_scan_info info = { 779 + .aborted = aborted, 780 + }; 781 + 778 782 brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n", 779 783 aborted ? "Aborted" : "Done"); 780 - cfg80211_scan_done(scan_request, aborted); 784 + cfg80211_scan_done(scan_request, &info); 781 785 } 782 786 if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) 783 787 brcmf_dbg(SCAN, "Scan complete, probably P2P scan\n");
+10 -2
drivers/net/wireless/intersil/orinoco/scan.c
··· 237 237 238 238 scan_abort: 239 239 if (priv->scan_request) { 240 - cfg80211_scan_done(priv->scan_request, abort); 240 + struct cfg80211_scan_info info = { 241 + .aborted = abort, 242 + }; 243 + 244 + cfg80211_scan_done(priv->scan_request, &info); 241 245 priv->scan_request = NULL; 242 246 } 243 247 } ··· 249 245 void orinoco_scan_done(struct orinoco_private *priv, bool abort) 250 246 { 251 247 if (priv->scan_request) { 252 - cfg80211_scan_done(priv->scan_request, abort); 248 + struct cfg80211_scan_info info = { 249 + .aborted = abort, 250 + }; 251 + 252 + cfg80211_scan_done(priv->scan_request, &info); 253 253 priv->scan_request = NULL; 254 254 } 255 255 }
+8 -3
drivers/net/wireless/marvell/libertas/cfg.c
··· 796 796 { 797 797 WARN_ON(!priv->scan_req); 798 798 799 - if (priv->internal_scan) 799 + if (priv->internal_scan) { 800 800 kfree(priv->scan_req); 801 - else 802 - cfg80211_scan_done(priv->scan_req, false); 801 + } else { 802 + struct cfg80211_scan_info info = { 803 + .aborted = false, 804 + }; 805 + 806 + cfg80211_scan_done(priv->scan_req, &info); 807 + } 803 808 804 809 priv->scan_req = NULL; 805 810 }
+10 -2
drivers/net/wireless/marvell/mwifiex/cmdevt.c
··· 1057 1057 if (!priv) 1058 1058 continue; 1059 1059 if (priv->scan_request) { 1060 + struct cfg80211_scan_info info = { 1061 + .aborted = true, 1062 + }; 1063 + 1060 1064 mwifiex_dbg(adapter, WARN, "info: aborting scan\n"); 1061 - cfg80211_scan_done(priv->scan_request, 1); 1065 + cfg80211_scan_done(priv->scan_request, &info); 1062 1066 priv->scan_request = NULL; 1063 1067 } 1064 1068 } ··· 1116 1112 if (!priv) 1117 1113 continue; 1118 1114 if (priv->scan_request) { 1115 + struct cfg80211_scan_info info = { 1116 + .aborted = true, 1117 + }; 1118 + 1119 1119 mwifiex_dbg(adapter, WARN, "info: aborting scan\n"); 1120 - cfg80211_scan_done(priv->scan_request, 1); 1120 + cfg80211_scan_done(priv->scan_request, &info); 1121 1121 priv->scan_request = NULL; 1122 1122 } 1123 1123 }
+5 -1
drivers/net/wireless/marvell/mwifiex/main.c
··· 697 697 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); 698 698 699 699 if (priv->scan_request) { 700 + struct cfg80211_scan_info info = { 701 + .aborted = true, 702 + }; 703 + 700 704 mwifiex_dbg(priv->adapter, INFO, 701 705 "aborting scan on ndo_stop\n"); 702 - cfg80211_scan_done(priv->scan_request, 1); 706 + cfg80211_scan_done(priv->scan_request, &info); 703 707 priv->scan_request = NULL; 704 708 priv->scan_aborting = true; 705 709 }
+10 -2
drivers/net/wireless/marvell/mwifiex/scan.c
··· 1956 1956 mwifiex_complete_scan(priv); 1957 1957 1958 1958 if (priv->scan_request) { 1959 + struct cfg80211_scan_info info = { 1960 + .aborted = false, 1961 + }; 1962 + 1959 1963 mwifiex_dbg(adapter, INFO, 1960 1964 "info: notifying scan done\n"); 1961 - cfg80211_scan_done(priv->scan_request, 0); 1965 + cfg80211_scan_done(priv->scan_request, &info); 1962 1966 priv->scan_request = NULL; 1963 1967 } else { 1964 1968 priv->scan_aborting = false; ··· 1981 1977 1982 1978 if (!adapter->active_scan_triggered) { 1983 1979 if (priv->scan_request) { 1980 + struct cfg80211_scan_info info = { 1981 + .aborted = true, 1982 + }; 1983 + 1984 1984 mwifiex_dbg(adapter, INFO, 1985 1985 "info: aborting scan\n"); 1986 - cfg80211_scan_done(priv->scan_request, 1); 1986 + cfg80211_scan_done(priv->scan_request, &info); 1987 1987 priv->scan_request = NULL; 1988 1988 } else { 1989 1989 priv->scan_aborting = false;
+8 -2
drivers/net/wireless/rndis_wlan.c
··· 2134 2134 struct rndis_wlan_private *priv = 2135 2135 container_of(work, struct rndis_wlan_private, scan_work.work); 2136 2136 struct usbnet *usbdev = priv->usbdev; 2137 + struct cfg80211_scan_info info = {}; 2137 2138 int ret; 2138 2139 2139 2140 netdev_dbg(usbdev->net, "get_scan_results\n"); ··· 2144 2143 2145 2144 ret = rndis_check_bssid_list(usbdev, NULL, NULL); 2146 2145 2147 - cfg80211_scan_done(priv->scan_request, ret < 0); 2146 + info.aborted = ret < 0; 2147 + cfg80211_scan_done(priv->scan_request, &info); 2148 2148 2149 2149 priv->scan_request = NULL; 2150 2150 } ··· 3576 3574 flush_workqueue(priv->workqueue); 3577 3575 3578 3576 if (priv->scan_request) { 3579 - cfg80211_scan_done(priv->scan_request, true); 3577 + struct cfg80211_scan_info info = { 3578 + .aborted = true, 3579 + }; 3580 + 3581 + cfg80211_scan_done(priv->scan_request, &info); 3580 3582 priv->scan_request = NULL; 3581 3583 } 3582 3584
+8 -3
drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c
··· 1256 1256 DBG_8723A("%s with scan req\n", __func__); 1257 1257 1258 1258 if (pwdev_priv->scan_request->wiphy != 1259 - pwdev_priv->rtw_wdev->wiphy) 1259 + pwdev_priv->rtw_wdev->wiphy) { 1260 1260 DBG_8723A("error wiphy compare\n"); 1261 - else 1262 - cfg80211_scan_done(pwdev_priv->scan_request, aborted); 1261 + } else { 1262 + struct cfg80211_scan_info info = { 1263 + .aborted = aborted, 1264 + }; 1265 + 1266 + cfg80211_scan_done(pwdev_priv->scan_request, &info); 1267 + } 1263 1268 1264 1269 pwdev_priv->scan_request = NULL; 1265 1270 } else {
+10 -2
drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
··· 454 454 mutex_lock(&priv->scan_req_lock); 455 455 456 456 if (priv->pstrScanReq) { 457 - cfg80211_scan_done(priv->pstrScanReq, false); 457 + struct cfg80211_scan_info info = { 458 + .aborted = false, 459 + }; 460 + 461 + cfg80211_scan_done(priv->pstrScanReq, &info); 458 462 priv->u32RcvdChCount = 0; 459 463 priv->bCfgScanning = false; 460 464 priv->pstrScanReq = NULL; ··· 468 464 mutex_lock(&priv->scan_req_lock); 469 465 470 466 if (priv->pstrScanReq) { 467 + struct cfg80211_scan_info info = { 468 + .aborted = false, 469 + }; 470 + 471 471 update_scan_time(); 472 472 refresh_scan(priv, 1, false); 473 473 474 - cfg80211_scan_done(priv->pstrScanReq, false); 474 + cfg80211_scan_done(priv->pstrScanReq, &info); 475 475 priv->bCfgScanning = false; 476 476 priv->pstrScanReq = NULL; 477 477 }
+4 -1
drivers/staging/wlan-ng/cfg80211.c
··· 338 338 struct p80211msg_dot11req_scan msg1; 339 339 struct p80211msg_dot11req_scan_results msg2; 340 340 struct cfg80211_bss *bss; 341 + struct cfg80211_scan_info info = {}; 342 + 341 343 int result; 342 344 int err = 0; 343 345 int numbss = 0; ··· 442 440 err = prism2_result2err(msg2.resultcode.data); 443 441 444 442 exit: 445 - cfg80211_scan_done(request, err ? 1 : 0); 443 + info.aborted = !!(err); 444 + cfg80211_scan_done(request, &info); 446 445 priv->scan_request = NULL; 447 446 return err; 448 447 }
+35 -5
include/net/cfg80211.h
··· 1424 1424 }; 1425 1425 1426 1426 /** 1427 + * struct cfg80211_scan_info - information about completed scan 1428 + * @scan_start_tsf: scan start time in terms of the TSF of the BSS that the 1429 + * wireless device that requested the scan is connected to. If this 1430 + * information is not available, this field is left zero. 1431 + * @tsf_bssid: the BSSID according to which %scan_start_tsf is set. 1432 + * @aborted: set to true if the scan was aborted for any reason, 1433 + * userspace will be notified of that 1434 + */ 1435 + struct cfg80211_scan_info { 1436 + u64 scan_start_tsf; 1437 + u8 tsf_bssid[ETH_ALEN] __aligned(2); 1438 + bool aborted; 1439 + }; 1440 + 1441 + /** 1427 1442 * struct cfg80211_scan_request - scan request description 1428 1443 * 1429 1444 * @ssids: SSIDs to scan for (active scan only) ··· 1448 1433 * @scan_width: channel width for scanning 1449 1434 * @ie: optional information element(s) to add into Probe Request or %NULL 1450 1435 * @ie_len: length of ie in octets 1436 + * @duration: how long to listen on each channel, in TUs. If 1437 + * %duration_mandatory is not set, this is the maximum dwell time and 1438 + * the actual dwell time may be shorter. 1439 + * @duration_mandatory: if set, the scan duration must be as specified by the 1440 + * %duration field. 1451 1441 * @flags: bit field of flags controlling operation 1452 1442 * @rates: bitmap of rates to advertise for each band 1453 1443 * @wiphy: the wiphy this was for 1454 1444 * @scan_start: time (in jiffies) when the scan started 1455 1445 * @wdev: the wireless device to scan for 1456 - * @aborted: (internal) scan request was notified as aborted 1446 + * @info: (internal) information about completed scan 1457 1447 * @notified: (internal) scan request was notified as done or aborted 1458 1448 * @no_cck: used to send probe requests at non CCK rate in 2GHz band 1459 1449 * @mac_addr: MAC address used with randomisation ··· 1474 1454 enum nl80211_bss_scan_width scan_width; 1475 1455 const u8 *ie; 1476 1456 size_t ie_len; 1457 + u16 duration; 1458 + bool duration_mandatory; 1477 1459 u32 flags; 1478 1460 1479 1461 u32 rates[NUM_NL80211_BANDS]; ··· 1489 1467 /* internal */ 1490 1468 struct wiphy *wiphy; 1491 1469 unsigned long scan_start; 1492 - bool aborted, notified; 1470 + struct cfg80211_scan_info info; 1471 + bool notified; 1493 1472 bool no_cck; 1494 1473 1495 1474 /* keep last */ ··· 1623 1600 * buffered on the device) and be accurate to about 10ms. 1624 1601 * If the frame isn't buffered, just passing the return value of 1625 1602 * ktime_get_boot_ns() is likely appropriate. 1603 + * @parent_tsf: the time at the start of reception of the first octet of the 1604 + * timestamp field of the frame. The time is the TSF of the BSS specified 1605 + * by %parent_bssid. 1606 + * @parent_bssid: the BSS according to which %parent_tsf is set. This is set to 1607 + * the BSS that requested the scan in which the beacon/probe was received. 1626 1608 */ 1627 1609 struct cfg80211_inform_bss { 1628 1610 struct ieee80211_channel *chan; 1629 1611 enum nl80211_bss_scan_width scan_width; 1630 1612 s32 signal; 1631 1613 u64 boottime_ns; 1614 + u64 parent_tsf; 1615 + u8 parent_bssid[ETH_ALEN] __aligned(2); 1632 1616 }; 1633 1617 1634 1618 /** ··· 4097 4067 * cfg80211_scan_done - notify that scan finished 4098 4068 * 4099 4069 * @request: the corresponding scan request 4100 - * @aborted: set to true if the scan was aborted for any reason, 4101 - * userspace will be notified of that 4070 + * @info: information about the completed scan 4102 4071 */ 4103 - void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted); 4072 + void cfg80211_scan_done(struct cfg80211_scan_request *request, 4073 + struct cfg80211_scan_info *info); 4104 4074 4105 4075 /** 4106 4076 * cfg80211_sched_scan_results - notify that new scan results are available
+42
include/uapi/linux/nl80211.h
··· 1848 1848 * to turn that feature off set an invalid mac address 1849 1849 * (e.g. FF:FF:FF:FF:FF:FF) 1850 1850 * 1851 + * @NL80211_ATTR_SCAN_START_TIME_TSF: The time at which the scan was actually 1852 + * started (u64). The time is the TSF of the BSS the interface that 1853 + * requested the scan is connected to (if available, otherwise this 1854 + * attribute must not be included). 1855 + * @NL80211_ATTR_SCAN_START_TIME_TSF_BSSID: The BSS according to which 1856 + * %NL80211_ATTR_SCAN_START_TIME_TSF is set. 1857 + * @NL80211_ATTR_MEASUREMENT_DURATION: measurement duration in TUs (u16). If 1858 + * %NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY is not set, this is the 1859 + * maximum measurement duration allowed. This attribute is used with 1860 + * measurement requests. It can also be used with %NL80211_CMD_TRIGGER_SCAN 1861 + * if the scan is used for beacon report radio measurement. 1862 + * @NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY: flag attribute that indicates 1863 + * that the duration specified with %NL80211_ATTR_MEASUREMENT_DURATION is 1864 + * mandatory. If this flag is not set, the duration is the maximum duration 1865 + * and the actual measurement duration may be shorter. 1866 + * 1851 1867 * @NUM_NL80211_ATTR: total number of nl80211_attrs available 1852 1868 * @NL80211_ATTR_MAX: highest attribute number currently defined 1853 1869 * @__NL80211_ATTR_AFTER_LAST: internal use ··· 2250 2234 2251 2235 NL80211_ATTR_MU_MIMO_GROUP_DATA, 2252 2236 NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR, 2237 + 2238 + NL80211_ATTR_SCAN_START_TIME_TSF, 2239 + NL80211_ATTR_SCAN_START_TIME_TSF_BSSID, 2240 + NL80211_ATTR_MEASUREMENT_DURATION, 2241 + NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY, 2253 2242 2254 2243 /* add attributes here, update the policy in nl80211.c */ 2255 2244 ··· 3517 3496 * was last updated by a received frame. The value is expected to be 3518 3497 * accurate to about 10ms. (u64, nanoseconds) 3519 3498 * @NL80211_BSS_PAD: attribute used for padding for 64-bit alignment 3499 + * @NL80211_BSS_PARENT_TSF: the time at the start of reception of the first 3500 + * octet of the timestamp field of the last beacon/probe received for 3501 + * this BSS. The time is the TSF of the BSS specified by 3502 + * @NL80211_BSS_PARENT_BSSID. (u64). 3503 + * @NL80211_BSS_PARENT_BSSID: the BSS according to which @NL80211_BSS_PARENT_TSF 3504 + * is set. 3520 3505 * @__NL80211_BSS_AFTER_LAST: internal 3521 3506 * @NL80211_BSS_MAX: highest BSS attribute 3522 3507 */ ··· 3544 3517 NL80211_BSS_PRESP_DATA, 3545 3518 NL80211_BSS_LAST_SEEN_BOOTTIME, 3546 3519 NL80211_BSS_PAD, 3520 + NL80211_BSS_PARENT_TSF, 3521 + NL80211_BSS_PARENT_BSSID, 3547 3522 3548 3523 /* keep last */ 3549 3524 __NL80211_BSS_AFTER_LAST, ··· 4536 4507 * %NL80211_ATTR_MU_MIMO_GROUP_DATA attribute, 4537 4508 * or can be configured to follow a station by configuring the 4538 4509 * %NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR attribute. 4510 + * @NL80211_EXT_FEATURE_SCAN_START_TIME: This driver includes the actual 4511 + * time the scan started in scan results event. The time is the TSF of 4512 + * the BSS that the interface that requested the scan is connected to 4513 + * (if available). 4514 + * @NL80211_EXT_FEATURE_BSS_PARENT_TSF: Per BSS, this driver reports the 4515 + * time the last beacon/probe was received. The time is the TSF of the 4516 + * BSS that the interface that requested the scan is connected to 4517 + * (if available). 4518 + * @NL80211_EXT_FEATURE_SET_SCAN_DWELL: This driver supports configuration of 4519 + * channel dwell time. 4539 4520 * 4540 4521 * @NUM_NL80211_EXT_FEATURES: number of extended features. 4541 4522 * @MAX_NL80211_EXT_FEATURES: highest extended feature index. ··· 4554 4515 NL80211_EXT_FEATURE_VHT_IBSS, 4555 4516 NL80211_EXT_FEATURE_RRM, 4556 4517 NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER, 4518 + NL80211_EXT_FEATURE_SCAN_START_TIME, 4519 + NL80211_EXT_FEATURE_BSS_PARENT_TSF, 4520 + NL80211_EXT_FEATURE_SET_SCAN_DWELL, 4557 4521 4558 4522 /* add new features before the definition below */ 4559 4523 NUM_NL80211_EXT_FEATURES,
+7 -2
net/mac80211/scan.c
··· 353 353 scan_req = rcu_dereference_protected(local->scan_req, 354 354 lockdep_is_held(&local->mtx)); 355 355 356 - if (scan_req != local->int_scan_req) 357 - cfg80211_scan_done(scan_req, aborted); 356 + if (scan_req != local->int_scan_req) { 357 + struct cfg80211_scan_info info = { 358 + .aborted = aborted, 359 + }; 360 + 361 + cfg80211_scan_done(scan_req, &info); 362 + } 358 363 RCU_INIT_POINTER(local->scan_req, NULL); 359 364 360 365 scan_sdata = rcu_dereference_protected(local->scan_sdata,
+2 -2
net/wireless/core.c
··· 220 220 221 221 if (rdev->scan_req && rdev->scan_req->wdev == wdev) { 222 222 if (WARN_ON(!rdev->scan_req->notified)) 223 - rdev->scan_req->aborted = true; 223 + rdev->scan_req->info.aborted = true; 224 224 ___cfg80211_scan_done(rdev, false); 225 225 } 226 226 } ··· 1087 1087 cfg80211_update_iface_num(rdev, wdev->iftype, -1); 1088 1088 if (rdev->scan_req && rdev->scan_req->wdev == wdev) { 1089 1089 if (WARN_ON(!rdev->scan_req->notified)) 1090 - rdev->scan_req->aborted = true; 1090 + rdev->scan_req->info.aborted = true; 1091 1091 ___cfg80211_scan_done(rdev, false); 1092 1092 } 1093 1093
+12
net/wireless/core.h
··· 141 141 unsigned long refcount; 142 142 atomic_t hold; 143 143 144 + /* time at the start of the reception of the first octet of the 145 + * timestamp field of the last beacon/probe received for this BSS. 146 + * The time is the TSF of the BSS specified by %parent_bssid. 147 + */ 148 + u64 parent_tsf; 149 + 150 + /* the BSS according to which %parent_tsf is set. This is set to 151 + * the BSS that the interface that requested the scan was connected to 152 + * when the beacon/probe was received. 153 + */ 154 + u8 parent_bssid[ETH_ALEN] __aligned(2); 155 + 144 156 /* must be last because of priv member */ 145 157 struct cfg80211_bss pub; 146 158 };
+27
net/wireless/nl80211.c
··· 6223 6223 } 6224 6224 } 6225 6225 6226 + if (info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]) { 6227 + if (!wiphy_ext_feature_isset(wiphy, 6228 + NL80211_EXT_FEATURE_SET_SCAN_DWELL)) { 6229 + err = -EOPNOTSUPP; 6230 + goto out_free; 6231 + } 6232 + 6233 + request->duration = 6234 + nla_get_u16(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]); 6235 + request->duration_mandatory = 6236 + nla_get_flag(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY]); 6237 + } 6238 + 6226 6239 if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) { 6227 6240 request->flags = nla_get_u32( 6228 6241 info->attrs[NL80211_ATTR_SCAN_FLAGS]); ··· 7067 7054 nla_put_u32(msg, NL80211_BSS_CHAN_WIDTH, res->scan_width) || 7068 7055 nla_put_u32(msg, NL80211_BSS_SEEN_MS_AGO, 7069 7056 jiffies_to_msecs(jiffies - intbss->ts))) 7057 + goto nla_put_failure; 7058 + 7059 + if (intbss->parent_tsf && 7060 + (nla_put_u64_64bit(msg, NL80211_BSS_PARENT_TSF, 7061 + intbss->parent_tsf, NL80211_BSS_PAD) || 7062 + nla_put(msg, NL80211_BSS_PARENT_BSSID, ETH_ALEN, 7063 + intbss->parent_bssid))) 7070 7064 goto nla_put_failure; 7071 7065 7072 7066 if (intbss->ts_boottime && ··· 11847 11827 11848 11828 if (req->flags && 11849 11829 nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags)) 11830 + goto nla_put_failure; 11831 + 11832 + if (req->info.scan_start_tsf && 11833 + (nla_put_u64_64bit(msg, NL80211_ATTR_SCAN_START_TIME_TSF, 11834 + req->info.scan_start_tsf, NL80211_BSS_PAD) || 11835 + nla_put(msg, NL80211_ATTR_SCAN_START_TIME_TSF_BSSID, ETH_ALEN, 11836 + req->info.tsf_bssid))) 11850 11837 goto nla_put_failure; 11851 11838 11852 11839 return 0;
+12 -6
net/wireless/scan.c
··· 3 3 * 4 4 * Copyright 2008 Johannes Berg <johannes@sipsolutions.net> 5 5 * Copyright 2013-2014 Intel Mobile Communications GmbH 6 + * Copyright 2016 Intel Deutschland GmbH 6 7 */ 7 8 #include <linux/kernel.h> 8 9 #include <linux/slab.h> ··· 195 194 if (wdev->netdev) 196 195 cfg80211_sme_scan_done(wdev->netdev); 197 196 198 - if (!request->aborted && 197 + if (!request->info.aborted && 199 198 request->flags & NL80211_SCAN_FLAG_FLUSH) { 200 199 /* flush entries from previous scans */ 201 200 spin_lock_bh(&rdev->bss_lock); ··· 203 202 spin_unlock_bh(&rdev->bss_lock); 204 203 } 205 204 206 - msg = nl80211_build_scan_msg(rdev, wdev, request->aborted); 205 + msg = nl80211_build_scan_msg(rdev, wdev, request->info.aborted); 207 206 208 207 #ifdef CONFIG_CFG80211_WEXT 209 - if (wdev->netdev && !request->aborted) { 208 + if (wdev->netdev && !request->info.aborted) { 210 209 memset(&wrqu, 0, sizeof(wrqu)); 211 210 212 211 wireless_send_event(wdev->netdev, SIOCGIWSCAN, &wrqu, NULL); ··· 237 236 rtnl_unlock(); 238 237 } 239 238 240 - void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) 239 + void cfg80211_scan_done(struct cfg80211_scan_request *request, 240 + struct cfg80211_scan_info *info) 241 241 { 242 - trace_cfg80211_scan_done(request, aborted); 242 + trace_cfg80211_scan_done(request, info); 243 243 WARN_ON(request != wiphy_to_rdev(request->wiphy)->scan_req); 244 244 245 - request->aborted = aborted; 245 + request->info = *info; 246 246 request->notified = true; 247 247 queue_work(cfg80211_wq, &wiphy_to_rdev(request->wiphy)->scan_done_wk); 248 248 } ··· 845 843 found->pub.capability = tmp->pub.capability; 846 844 found->ts = tmp->ts; 847 845 found->ts_boottime = tmp->ts_boottime; 846 + found->parent_tsf = tmp->parent_tsf; 847 + ether_addr_copy(found->parent_bssid, tmp->parent_bssid); 848 848 } else { 849 849 struct cfg80211_internal_bss *new; 850 850 struct cfg80211_internal_bss *hidden; ··· 1090 1086 tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); 1091 1087 tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); 1092 1088 tmp.ts_boottime = data->boottime_ns; 1089 + tmp.parent_tsf = data->parent_tsf; 1090 + ether_addr_copy(tmp.parent_bssid, data->parent_bssid); 1093 1091 1094 1092 signal_valid = abs(data->chan->center_freq - channel->center_freq) <= 1095 1093 wiphy->max_adj_channel_rssi_comp;
+24 -7
net/wireless/trace.h
··· 2642 2642 ); 2643 2643 2644 2644 TRACE_EVENT(cfg80211_scan_done, 2645 - TP_PROTO(struct cfg80211_scan_request *request, bool aborted), 2646 - TP_ARGS(request, aborted), 2645 + TP_PROTO(struct cfg80211_scan_request *request, 2646 + struct cfg80211_scan_info *info), 2647 + TP_ARGS(request, info), 2647 2648 TP_STRUCT__entry( 2648 2649 __field(u32, n_channels) 2649 2650 __dynamic_array(u8, ie, request ? request->ie_len : 0) ··· 2653 2652 MAC_ENTRY(wiphy_mac) 2654 2653 __field(bool, no_cck) 2655 2654 __field(bool, aborted) 2655 + __field(u64, scan_start_tsf) 2656 + MAC_ENTRY(tsf_bssid) 2656 2657 ), 2657 2658 TP_fast_assign( 2658 2659 if (request) { ··· 2669 2666 request->wiphy->perm_addr); 2670 2667 __entry->no_cck = request->no_cck; 2671 2668 } 2672 - __entry->aborted = aborted; 2669 + if (info) { 2670 + __entry->aborted = info->aborted; 2671 + __entry->scan_start_tsf = info->scan_start_tsf; 2672 + MAC_ASSIGN(tsf_bssid, info->tsf_bssid); 2673 + } 2673 2674 ), 2674 - TP_printk("aborted: %s", BOOL_TO_STR(__entry->aborted)) 2675 + TP_printk("aborted: %s, scan start (TSF): %llu, tsf_bssid: " MAC_PR_FMT, 2676 + BOOL_TO_STR(__entry->aborted), 2677 + (unsigned long long)__entry->scan_start_tsf, 2678 + MAC_PR_ARG(tsf_bssid)) 2675 2679 ); 2676 2680 2677 2681 DEFINE_EVENT(wiphy_only_evt, cfg80211_sched_scan_results, ··· 2731 2721 __dynamic_array(u8, mgmt, len) 2732 2722 __field(s32, signal) 2733 2723 __field(u64, ts_boottime) 2724 + __field(u64, parent_tsf) 2725 + MAC_ENTRY(parent_bssid) 2734 2726 ), 2735 2727 TP_fast_assign( 2736 2728 WIPHY_ASSIGN; ··· 2742 2730 memcpy(__get_dynamic_array(mgmt), mgmt, len); 2743 2731 __entry->signal = data->signal; 2744 2732 __entry->ts_boottime = data->boottime_ns; 2733 + __entry->parent_tsf = data->parent_tsf; 2734 + MAC_ASSIGN(parent_bssid, data->parent_bssid); 2745 2735 ), 2746 - TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT "(scan_width: %d) signal: %d, tsb:%llu", 2747 - WIPHY_PR_ARG, CHAN_PR_ARG, __entry->scan_width, 2748 - __entry->signal, (unsigned long long)__entry->ts_boottime) 2736 + TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT 2737 + "(scan_width: %d) signal: %d, tsb:%llu, detect_tsf:%llu, tsf_bssid: " 2738 + MAC_PR_FMT, WIPHY_PR_ARG, CHAN_PR_ARG, __entry->scan_width, 2739 + __entry->signal, (unsigned long long)__entry->ts_boottime, 2740 + (unsigned long long)__entry->parent_tsf, 2741 + MAC_PR_ARG(parent_bssid)) 2749 2742 ); 2750 2743 2751 2744 DECLARE_EVENT_CLASS(cfg80211_bss_evt,