aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-02-05 10:54:31 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-02-11 12:44:59 -0500
commit8cef2c9df88fdd13f518e6607de9d664b31f26cc (patch)
treef8a4d29db6012ad3468a5d9435562fc1f383209a
parent83c7aa1a1475ae1c42640ab6e4559016142efc67 (diff)
cfg80211: move TSF into IEs
While technically the TSF isn't an IE, it can be necessary to distinguish between the TSF from a beacon and a probe response, in particular in order to know the next DTIM TBTT, as not all APs are spec compliant wrt. TSF==0 being a DTIM TBTT and thus the DTIM count needs to be taken into account as well. To allow this, move the TSF into the IE struct so it can be known whence it came. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--drivers/net/wireless/mwifiex/sta_ioctl.c2
-rw-r--r--include/net/cfg80211.h5
-rw-r--r--net/mac80211/ibss.c14
-rw-r--r--net/mac80211/mlme.c6
-rw-r--r--net/wireless/nl80211.c27
-rw-r--r--net/wireless/scan.c7
6 files changed, 37 insertions, 24 deletions
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index 8866a2b69c94..0d018460daf9 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -164,6 +164,7 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
164 ies = rcu_dereference(bss->ies); 164 ies = rcu_dereference(bss->ies);
165 beacon_ie = kmemdup(ies->data, ies->len, GFP_ATOMIC); 165 beacon_ie = kmemdup(ies->data, ies->len, GFP_ATOMIC);
166 beacon_ie_len = ies->len; 166 beacon_ie_len = ies->len;
167 bss_desc->timestamp = ies->tsf;
167 rcu_read_unlock(); 168 rcu_read_unlock();
168 169
169 if (!beacon_ie) { 170 if (!beacon_ie) {
@@ -179,7 +180,6 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
179 bss_desc->cap_info_bitmap = bss->capability; 180 bss_desc->cap_info_bitmap = bss->capability;
180 bss_desc->bss_band = bss_priv->band; 181 bss_desc->bss_band = bss_priv->band;
181 bss_desc->fw_tsf = bss_priv->fw_tsf; 182 bss_desc->fw_tsf = bss_priv->fw_tsf;
182 bss_desc->timestamp = bss->tsf;
183 if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) { 183 if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) {
184 dev_dbg(priv->adapter->dev, "info: InterpretIE: AP WEP enabled\n"); 184 dev_dbg(priv->adapter->dev, "info: InterpretIE: AP WEP enabled\n");
185 bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP; 185 bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP;
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index fb766314b3a1..77686ca28948 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1266,11 +1266,13 @@ enum cfg80211_signal_type {
1266 1266
1267/** 1267/**
1268 * struct cfg80211_bss_ie_data - BSS entry IE data 1268 * struct cfg80211_bss_ie_data - BSS entry IE data
1269 * @tsf: TSF contained in the frame that carried these IEs
1269 * @rcu_head: internal use, for freeing 1270 * @rcu_head: internal use, for freeing
1270 * @len: length of the IEs 1271 * @len: length of the IEs
1271 * @data: IE data 1272 * @data: IE data
1272 */ 1273 */
1273struct cfg80211_bss_ies { 1274struct cfg80211_bss_ies {
1275 u64 tsf;
1274 struct rcu_head rcu_head; 1276 struct rcu_head rcu_head;
1275 int len; 1277 int len;
1276 u8 data[]; 1278 u8 data[];
@@ -1284,7 +1286,6 @@ struct cfg80211_bss_ies {
1284 * 1286 *
1285 * @channel: channel this BSS is on 1287 * @channel: channel this BSS is on
1286 * @bssid: BSSID of the BSS 1288 * @bssid: BSSID of the BSS
1287 * @tsf: timestamp of last received update
1288 * @beacon_interval: the beacon interval as from the frame 1289 * @beacon_interval: the beacon interval as from the frame
1289 * @capability: the capability field in host byte order 1290 * @capability: the capability field in host byte order
1290 * @ies: the information elements (Note that there is no guarantee that these 1291 * @ies: the information elements (Note that there is no guarantee that these
@@ -1304,8 +1305,6 @@ struct cfg80211_bss_ies {
1304 * @priv: private area for driver use, has at least wiphy->bss_priv_size bytes 1305 * @priv: private area for driver use, has at least wiphy->bss_priv_size bytes
1305 */ 1306 */
1306struct cfg80211_bss { 1307struct cfg80211_bss {
1307 u64 tsf;
1308
1309 struct ieee80211_channel *channel; 1308 struct ieee80211_channel *channel;
1310 1309
1311 const struct cfg80211_bss_ies __rcu *ies; 1310 const struct cfg80211_bss_ies __rcu *ies;
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 71c55cc0f7b6..055fa9436e95 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -242,6 +242,8 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
242 u32 basic_rates; 242 u32 basic_rates;
243 int i, j; 243 int i, j;
244 u16 beacon_int = cbss->beacon_interval; 244 u16 beacon_int = cbss->beacon_interval;
245 const struct cfg80211_bss_ies *ies;
246 u64 tsf;
245 247
246 lockdep_assert_held(&sdata->u.ibss.mtx); 248 lockdep_assert_held(&sdata->u.ibss.mtx);
247 249
@@ -265,13 +267,17 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
265 } 267 }
266 } 268 }
267 269
270 rcu_read_lock();
271 ies = rcu_dereference(cbss->ies);
272 tsf = ies->tsf;
273 rcu_read_unlock();
274
268 __ieee80211_sta_join_ibss(sdata, cbss->bssid, 275 __ieee80211_sta_join_ibss(sdata, cbss->bssid,
269 beacon_int, 276 beacon_int,
270 cbss->channel, 277 cbss->channel,
271 basic_rates, 278 basic_rates,
272 cbss->capability, 279 cbss->capability,
273 cbss->tsf, 280 tsf, false);
274 false);
275} 281}
276 282
277static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta, 283static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta,
@@ -535,8 +541,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
535 541
536 cbss = container_of((void *)bss, struct cfg80211_bss, priv); 542 cbss = container_of((void *)bss, struct cfg80211_bss, priv);
537 543
538 /* was just updated in ieee80211_bss_info_update */ 544 /* same for beacon and probe response */
539 beacon_timestamp = cbss->tsf; 545 beacon_timestamp = le64_to_cpu(mgmt->u.beacon.timestamp);
540 546
541 /* check if we need to merge IBSS */ 547 /* check if we need to merge IBSS */
542 548
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 40ce00c6d4ca..51eca5a0cdaa 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3667,6 +3667,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
3667 bool have_higher_than_11mbit; 3667 bool have_higher_than_11mbit;
3668 int min_rate = INT_MAX, min_rate_index = -1; 3668 int min_rate = INT_MAX, min_rate_index = -1;
3669 struct ieee80211_supported_band *sband; 3669 struct ieee80211_supported_band *sband;
3670 const struct cfg80211_bss_ies *ies;
3670 3671
3671 sband = local->hw.wiphy->bands[cbss->channel->band]; 3672 sband = local->hw.wiphy->bands[cbss->channel->band];
3672 3673
@@ -3710,7 +3711,10 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
3710 3711
3711 /* set timing information */ 3712 /* set timing information */
3712 sdata->vif.bss_conf.beacon_int = cbss->beacon_interval; 3713 sdata->vif.bss_conf.beacon_int = cbss->beacon_interval;
3713 sdata->vif.bss_conf.sync_tsf = cbss->tsf; 3714 rcu_read_lock();
3715 ies = rcu_dereference(cbss->ies);
3716 sdata->vif.bss_conf.sync_tsf = ies->tsf;
3717 rcu_read_unlock();
3714 sdata->vif.bss_conf.sync_device_ts = bss->device_ts; 3718 sdata->vif.bss_conf.sync_device_ts = bss->device_ts;
3715 3719
3716 /* tell driver about BSSID, basic rates and timing */ 3720 /* tell driver about BSSID, basic rates and timing */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 807d448e702e..93bc63eae076 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -4997,6 +4997,7 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
4997 const struct cfg80211_bss_ies *ies; 4997 const struct cfg80211_bss_ies *ies;
4998 void *hdr; 4998 void *hdr;
4999 struct nlattr *bss; 4999 struct nlattr *bss;
5000 bool tsf = false;
5000 5001
5001 ASSERT_WDEV_LOCK(wdev); 5002 ASSERT_WDEV_LOCK(wdev);
5002 5003
@@ -5020,22 +5021,24 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
5020 5021
5021 rcu_read_lock(); 5022 rcu_read_lock();
5022 ies = rcu_dereference(res->ies); 5023 ies = rcu_dereference(res->ies);
5023 if (ies && ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS, 5024 if (ies) {
5024 ies->len, ies->data)) { 5025 if (nla_put_u64(msg, NL80211_BSS_TSF, ies->tsf))
5025 rcu_read_unlock(); 5026 goto fail_unlock_rcu;
5026 goto nla_put_failure; 5027 tsf = true;
5028 if (ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS,
5029 ies->len, ies->data))
5030 goto fail_unlock_rcu;
5027 } 5031 }
5028 ies = rcu_dereference(res->beacon_ies); 5032 ies = rcu_dereference(res->beacon_ies);
5029 if (ies && ies->len && nla_put(msg, NL80211_BSS_BEACON_IES, 5033 if (ies) {
5030 ies->len, ies->data)) { 5034 if (!tsf && nla_put_u64(msg, NL80211_BSS_TSF, ies->tsf))
5031 rcu_read_unlock(); 5035 goto fail_unlock_rcu;
5032 goto nla_put_failure; 5036 if (ies->len && nla_put(msg, NL80211_BSS_BEACON_IES,
5037 ies->len, ies->data))
5038 goto fail_unlock_rcu;
5033 } 5039 }
5034 rcu_read_unlock(); 5040 rcu_read_unlock();
5035 5041
5036 if (res->tsf &&
5037 nla_put_u64(msg, NL80211_BSS_TSF, res->tsf))
5038 goto nla_put_failure;
5039 if (res->beacon_interval && 5042 if (res->beacon_interval &&
5040 nla_put_u16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval)) 5043 nla_put_u16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval))
5041 goto nla_put_failure; 5044 goto nla_put_failure;
@@ -5080,6 +5083,8 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
5080 5083
5081 return genlmsg_end(msg, hdr); 5084 return genlmsg_end(msg, hdr);
5082 5085
5086 fail_unlock_rcu:
5087 rcu_read_unlock();
5083 nla_put_failure: 5088 nla_put_failure:
5084 genlmsg_cancel(msg, hdr); 5089 genlmsg_cancel(msg, hdr);
5085 return -EMSGSIZE; 5090 return -EMSGSIZE;
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 02a238329c83..b7a167984986 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -695,7 +695,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
695 695
696 if (found) { 696 if (found) {
697 found->pub.beacon_interval = tmp->pub.beacon_interval; 697 found->pub.beacon_interval = tmp->pub.beacon_interval;
698 found->pub.tsf = tmp->pub.tsf;
699 found->pub.signal = tmp->pub.signal; 698 found->pub.signal = tmp->pub.signal;
700 found->pub.capability = tmp->pub.capability; 699 found->pub.capability = tmp->pub.capability;
701 found->ts = tmp->ts; 700 found->ts = tmp->ts;
@@ -880,7 +879,6 @@ cfg80211_inform_bss(struct wiphy *wiphy,
880 memcpy(tmp.pub.bssid, bssid, ETH_ALEN); 879 memcpy(tmp.pub.bssid, bssid, ETH_ALEN);
881 tmp.pub.channel = channel; 880 tmp.pub.channel = channel;
882 tmp.pub.signal = signal; 881 tmp.pub.signal = signal;
883 tmp.pub.tsf = tsf;
884 tmp.pub.beacon_interval = beacon_interval; 882 tmp.pub.beacon_interval = beacon_interval;
885 tmp.pub.capability = capability; 883 tmp.pub.capability = capability;
886 /* 884 /*
@@ -895,6 +893,7 @@ cfg80211_inform_bss(struct wiphy *wiphy,
895 if (!ies) 893 if (!ies)
896 return NULL; 894 return NULL;
897 ies->len = ielen; 895 ies->len = ielen;
896 ies->tsf = tsf;
898 memcpy(ies->data, ie, ielen); 897 memcpy(ies->data, ie, ielen);
899 898
900 rcu_assign_pointer(tmp.pub.beacon_ies, ies); 899 rcu_assign_pointer(tmp.pub.beacon_ies, ies);
@@ -951,6 +950,7 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
951 if (!ies) 950 if (!ies)
952 return NULL; 951 return NULL;
953 ies->len = ielen; 952 ies->len = ielen;
953 ies->tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp);
954 memcpy(ies->data, mgmt->u.probe_resp.variable, ielen); 954 memcpy(ies->data, mgmt->u.probe_resp.variable, ielen);
955 955
956 if (ieee80211_is_probe_resp(mgmt->frame_control)) 956 if (ieee80211_is_probe_resp(mgmt->frame_control))
@@ -962,7 +962,6 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
962 memcpy(tmp.pub.bssid, mgmt->bssid, ETH_ALEN); 962 memcpy(tmp.pub.bssid, mgmt->bssid, ETH_ALEN);
963 tmp.pub.channel = channel; 963 tmp.pub.channel = channel;
964 tmp.pub.signal = signal; 964 tmp.pub.signal = signal;
965 tmp.pub.tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp);
966 tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); 965 tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
967 tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); 966 tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
968 967
@@ -1409,7 +1408,7 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
1409 if (buf) { 1408 if (buf) {
1410 memset(&iwe, 0, sizeof(iwe)); 1409 memset(&iwe, 0, sizeof(iwe));
1411 iwe.cmd = IWEVCUSTOM; 1410 iwe.cmd = IWEVCUSTOM;
1412 sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->pub.tsf)); 1411 sprintf(buf, "tsf=%016llx", (unsigned long long)(ies->tsf));
1413 iwe.u.data.length = strlen(buf); 1412 iwe.u.data.length = strlen(buf);
1414 current_ev = iwe_stream_add_point(info, current_ev, end_buf, 1413 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
1415 &iwe, buf); 1414 &iwe, buf);