aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorAvraham Stern <avraham.stern@intel.com>2016-07-05 10:10:13 -0400
committerJohannes Berg <johannes.berg@intel.com>2016-07-06 08:51:31 -0400
commit1d76250bd34af86c6498fc51e50cab3bfbbeceaa (patch)
tree36b75a19f179f9225619d6ca28ff10df90956805 /net/wireless
parentf1724b0258b412144964f2074b9b6edcf0dce87c (diff)
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>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/core.c4
-rw-r--r--net/wireless/core.h12
-rw-r--r--net/wireless/nl80211.c27
-rw-r--r--net/wireless/scan.c18
-rw-r--r--net/wireless/trace.h33
5 files changed, 78 insertions, 16 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 39d9abd309ea..7645e97362c0 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -220,7 +220,7 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
220 220
221 if (rdev->scan_req && rdev->scan_req->wdev == wdev) { 221 if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
222 if (WARN_ON(!rdev->scan_req->notified)) 222 if (WARN_ON(!rdev->scan_req->notified))
223 rdev->scan_req->aborted = true; 223 rdev->scan_req->info.aborted = true;
224 ___cfg80211_scan_done(rdev, false); 224 ___cfg80211_scan_done(rdev, false);
225 } 225 }
226} 226}
@@ -1087,7 +1087,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
1087 cfg80211_update_iface_num(rdev, wdev->iftype, -1); 1087 cfg80211_update_iface_num(rdev, wdev->iftype, -1);
1088 if (rdev->scan_req && rdev->scan_req->wdev == wdev) { 1088 if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
1089 if (WARN_ON(!rdev->scan_req->notified)) 1089 if (WARN_ON(!rdev->scan_req->notified))
1090 rdev->scan_req->aborted = true; 1090 rdev->scan_req->info.aborted = true;
1091 ___cfg80211_scan_done(rdev, false); 1091 ___cfg80211_scan_done(rdev, false);
1092 } 1092 }
1093 1093
diff --git a/net/wireless/core.h b/net/wireless/core.h
index a4d547f99f8d..eee91443924d 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -141,6 +141,18 @@ struct cfg80211_internal_bss {
141 unsigned long refcount; 141 unsigned long refcount;
142 atomic_t hold; 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 /* must be last because of priv member */ 156 /* must be last because of priv member */
145 struct cfg80211_bss pub; 157 struct cfg80211_bss pub;
146}; 158};
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 447026f8cc76..c53b5462ed00 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6223,6 +6223,19 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
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 if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) { 6239 if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
6227 request->flags = nla_get_u32( 6240 request->flags = nla_get_u32(
6228 info->attrs[NL80211_ATTR_SCAN_FLAGS]); 6241 info->attrs[NL80211_ATTR_SCAN_FLAGS]);
@@ -7056,6 +7069,13 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
7056 jiffies_to_msecs(jiffies - intbss->ts))) 7069 jiffies_to_msecs(jiffies - intbss->ts)))
7057 goto nla_put_failure; 7070 goto nla_put_failure;
7058 7071
7072 if (intbss->parent_tsf &&
7073 (nla_put_u64_64bit(msg, NL80211_BSS_PARENT_TSF,
7074 intbss->parent_tsf, NL80211_BSS_PAD) ||
7075 nla_put(msg, NL80211_BSS_PARENT_BSSID, ETH_ALEN,
7076 intbss->parent_bssid)))
7077 goto nla_put_failure;
7078
7059 if (intbss->ts_boottime && 7079 if (intbss->ts_boottime &&
7060 nla_put_u64_64bit(msg, NL80211_BSS_LAST_SEEN_BOOTTIME, 7080 nla_put_u64_64bit(msg, NL80211_BSS_LAST_SEEN_BOOTTIME,
7061 intbss->ts_boottime, NL80211_BSS_PAD)) 7081 intbss->ts_boottime, NL80211_BSS_PAD))
@@ -11829,6 +11849,13 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
11829 nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags)) 11849 nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags))
11830 goto nla_put_failure; 11850 goto nla_put_failure;
11831 11851
11852 if (req->info.scan_start_tsf &&
11853 (nla_put_u64_64bit(msg, NL80211_ATTR_SCAN_START_TIME_TSF,
11854 req->info.scan_start_tsf, NL80211_BSS_PAD) ||
11855 nla_put(msg, NL80211_ATTR_SCAN_START_TIME_TSF_BSSID, ETH_ALEN,
11856 req->info.tsf_bssid)))
11857 goto nla_put_failure;
11858
11832 return 0; 11859 return 0;
11833 nla_put_failure: 11860 nla_put_failure:
11834 return -ENOBUFS; 11861 return -ENOBUFS;
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index ef2955c89a00..0358e12be54b 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -3,6 +3,7 @@
3 * 3 *
4 * Copyright 2008 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2008 Johannes Berg <johannes@sipsolutions.net>
5 * Copyright 2013-2014 Intel Mobile Communications GmbH 5 * Copyright 2013-2014 Intel Mobile Communications GmbH
6 * Copyright 2016 Intel Deutschland GmbH
6 */ 7 */
7#include <linux/kernel.h> 8#include <linux/kernel.h>
8#include <linux/slab.h> 9#include <linux/slab.h>
@@ -194,7 +195,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
194 if (wdev->netdev) 195 if (wdev->netdev)
195 cfg80211_sme_scan_done(wdev->netdev); 196 cfg80211_sme_scan_done(wdev->netdev);
196 197
197 if (!request->aborted && 198 if (!request->info.aborted &&
198 request->flags & NL80211_SCAN_FLAG_FLUSH) { 199 request->flags & NL80211_SCAN_FLAG_FLUSH) {
199 /* flush entries from previous scans */ 200 /* flush entries from previous scans */
200 spin_lock_bh(&rdev->bss_lock); 201 spin_lock_bh(&rdev->bss_lock);
@@ -202,10 +203,10 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
202 spin_unlock_bh(&rdev->bss_lock); 203 spin_unlock_bh(&rdev->bss_lock);
203 } 204 }
204 205
205 msg = nl80211_build_scan_msg(rdev, wdev, request->aborted); 206 msg = nl80211_build_scan_msg(rdev, wdev, request->info.aborted);
206 207
207#ifdef CONFIG_CFG80211_WEXT 208#ifdef CONFIG_CFG80211_WEXT
208 if (wdev->netdev && !request->aborted) { 209 if (wdev->netdev && !request->info.aborted) {
209 memset(&wrqu, 0, sizeof(wrqu)); 210 memset(&wrqu, 0, sizeof(wrqu));
210 211
211 wireless_send_event(wdev->netdev, SIOCGIWSCAN, &wrqu, NULL); 212 wireless_send_event(wdev->netdev, SIOCGIWSCAN, &wrqu, NULL);
@@ -236,12 +237,13 @@ void __cfg80211_scan_done(struct work_struct *wk)
236 rtnl_unlock(); 237 rtnl_unlock();
237} 238}
238 239
239void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) 240void cfg80211_scan_done(struct cfg80211_scan_request *request,
241 struct cfg80211_scan_info *info)
240{ 242{
241 trace_cfg80211_scan_done(request, aborted); 243 trace_cfg80211_scan_done(request, info);
242 WARN_ON(request != wiphy_to_rdev(request->wiphy)->scan_req); 244 WARN_ON(request != wiphy_to_rdev(request->wiphy)->scan_req);
243 245
244 request->aborted = aborted; 246 request->info = *info;
245 request->notified = true; 247 request->notified = true;
246 queue_work(cfg80211_wq, &wiphy_to_rdev(request->wiphy)->scan_done_wk); 248 queue_work(cfg80211_wq, &wiphy_to_rdev(request->wiphy)->scan_done_wk);
247} 249}
@@ -843,6 +845,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
843 found->pub.capability = tmp->pub.capability; 845 found->pub.capability = tmp->pub.capability;
844 found->ts = tmp->ts; 846 found->ts = tmp->ts;
845 found->ts_boottime = tmp->ts_boottime; 847 found->ts_boottime = tmp->ts_boottime;
848 found->parent_tsf = tmp->parent_tsf;
849 ether_addr_copy(found->parent_bssid, tmp->parent_bssid);
846 } else { 850 } else {
847 struct cfg80211_internal_bss *new; 851 struct cfg80211_internal_bss *new;
848 struct cfg80211_internal_bss *hidden; 852 struct cfg80211_internal_bss *hidden;
@@ -1086,6 +1090,8 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
1086 tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); 1090 tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
1087 tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); 1091 tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
1088 tmp.ts_boottime = data->boottime_ns; 1092 tmp.ts_boottime = data->boottime_ns;
1093 tmp.parent_tsf = data->parent_tsf;
1094 ether_addr_copy(tmp.parent_bssid, data->parent_bssid);
1089 1095
1090 signal_valid = abs(data->chan->center_freq - channel->center_freq) <= 1096 signal_valid = abs(data->chan->center_freq - channel->center_freq) <=
1091 wiphy->max_adj_channel_rssi_comp; 1097 wiphy->max_adj_channel_rssi_comp;
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 3c1091ae6c36..72b5255cefe2 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -2642,8 +2642,9 @@ TRACE_EVENT(cfg80211_tdls_oper_request,
2642 ); 2642 );
2643 2643
2644TRACE_EVENT(cfg80211_scan_done, 2644TRACE_EVENT(cfg80211_scan_done,
2645 TP_PROTO(struct cfg80211_scan_request *request, bool aborted), 2645 TP_PROTO(struct cfg80211_scan_request *request,
2646 TP_ARGS(request, aborted), 2646 struct cfg80211_scan_info *info),
2647 TP_ARGS(request, info),
2647 TP_STRUCT__entry( 2648 TP_STRUCT__entry(
2648 __field(u32, n_channels) 2649 __field(u32, n_channels)
2649 __dynamic_array(u8, ie, request ? request->ie_len : 0) 2650 __dynamic_array(u8, ie, request ? request->ie_len : 0)
@@ -2652,6 +2653,8 @@ TRACE_EVENT(cfg80211_scan_done,
2652 MAC_ENTRY(wiphy_mac) 2653 MAC_ENTRY(wiphy_mac)
2653 __field(bool, no_cck) 2654 __field(bool, no_cck)
2654 __field(bool, aborted) 2655 __field(bool, aborted)
2656 __field(u64, scan_start_tsf)
2657 MAC_ENTRY(tsf_bssid)
2655 ), 2658 ),
2656 TP_fast_assign( 2659 TP_fast_assign(
2657 if (request) { 2660 if (request) {
@@ -2666,9 +2669,16 @@ TRACE_EVENT(cfg80211_scan_done,
2666 request->wiphy->perm_addr); 2669 request->wiphy->perm_addr);
2667 __entry->no_cck = request->no_cck; 2670 __entry->no_cck = request->no_cck;
2668 } 2671 }
2669 __entry->aborted = aborted; 2672 if (info) {
2673 __entry->aborted = info->aborted;
2674 __entry->scan_start_tsf = info->scan_start_tsf;
2675 MAC_ASSIGN(tsf_bssid, info->tsf_bssid);
2676 }
2670 ), 2677 ),
2671 TP_printk("aborted: %s", BOOL_TO_STR(__entry->aborted)) 2678 TP_printk("aborted: %s, scan start (TSF): %llu, tsf_bssid: " MAC_PR_FMT,
2679 BOOL_TO_STR(__entry->aborted),
2680 (unsigned long long)__entry->scan_start_tsf,
2681 MAC_PR_ARG(tsf_bssid))
2672); 2682);
2673 2683
2674DEFINE_EVENT(wiphy_only_evt, cfg80211_sched_scan_results, 2684DEFINE_EVENT(wiphy_only_evt, cfg80211_sched_scan_results,
@@ -2721,6 +2731,8 @@ TRACE_EVENT(cfg80211_inform_bss_frame,
2721 __dynamic_array(u8, mgmt, len) 2731 __dynamic_array(u8, mgmt, len)
2722 __field(s32, signal) 2732 __field(s32, signal)
2723 __field(u64, ts_boottime) 2733 __field(u64, ts_boottime)
2734 __field(u64, parent_tsf)
2735 MAC_ENTRY(parent_bssid)
2724 ), 2736 ),
2725 TP_fast_assign( 2737 TP_fast_assign(
2726 WIPHY_ASSIGN; 2738 WIPHY_ASSIGN;
@@ -2730,10 +2742,15 @@ TRACE_EVENT(cfg80211_inform_bss_frame,
2730 memcpy(__get_dynamic_array(mgmt), mgmt, len); 2742 memcpy(__get_dynamic_array(mgmt), mgmt, len);
2731 __entry->signal = data->signal; 2743 __entry->signal = data->signal;
2732 __entry->ts_boottime = data->boottime_ns; 2744 __entry->ts_boottime = data->boottime_ns;
2733 ), 2745 __entry->parent_tsf = data->parent_tsf;
2734 TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT "(scan_width: %d) signal: %d, tsb:%llu", 2746 MAC_ASSIGN(parent_bssid, data->parent_bssid);
2735 WIPHY_PR_ARG, CHAN_PR_ARG, __entry->scan_width, 2747 ),
2736 __entry->signal, (unsigned long long)__entry->ts_boottime) 2748 TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT
2749 "(scan_width: %d) signal: %d, tsb:%llu, detect_tsf:%llu, tsf_bssid: "
2750 MAC_PR_FMT, WIPHY_PR_ARG, CHAN_PR_ARG, __entry->scan_width,
2751 __entry->signal, (unsigned long long)__entry->ts_boottime,
2752 (unsigned long long)__entry->parent_tsf,
2753 MAC_PR_ARG(parent_bssid))
2737); 2754);
2738 2755
2739DECLARE_EVENT_CLASS(cfg80211_bss_evt, 2756DECLARE_EVENT_CLASS(cfg80211_bss_evt,