aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorSimon Wunderlich <simon.wunderlich@s2003.tu-chemnitz.de>2013-08-09 10:35:17 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-08-16 06:25:34 -0400
commitd51b70ff5122d31e27733ba03c3afd62bb86bd63 (patch)
treef2b3f1c6cdb381645ac4cf1e4bdee9935eb95235 /net/mac80211
parent86c228a7627f3f2776893da47592234140fbfba8 (diff)
mac80211: move ibss presp generation in own function
Channel Switch will later require to generate beacons without setting them immediately. Therefore split the presp generation in an own function. Splitting the original very long function might be a good idea anyway. Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> Signed-off-by: Mathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/ibss.c185
1 files changed, 109 insertions, 76 deletions
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 79e294e9b5cc..74de0f10558a 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -34,13 +34,12 @@
34 34
35#define IEEE80211_IBSS_MAX_STA_ENTRIES 128 35#define IEEE80211_IBSS_MAX_STA_ENTRIES 128
36 36
37 37static struct beacon_data *
38static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, 38ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata,
39 const u8 *bssid, const int beacon_int, 39 const int beacon_int, const u32 basic_rates,
40 struct ieee80211_channel *chan, 40 const u16 capability, u64 tsf,
41 const u32 basic_rates, 41 struct cfg80211_chan_def *chandef,
42 const u16 capability, u64 tsf, 42 bool *have_higher_than_11mbit)
43 bool creator)
44{ 43{
45 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 44 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
46 struct ieee80211_local *local = sdata->local; 45 struct ieee80211_local *local = sdata->local;
@@ -48,70 +47,11 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
48 struct ieee80211_mgmt *mgmt; 47 struct ieee80211_mgmt *mgmt;
49 u8 *pos; 48 u8 *pos;
50 struct ieee80211_supported_band *sband; 49 struct ieee80211_supported_band *sband;
51 struct cfg80211_bss *bss; 50 u32 rate_flags, rates = 0, rates_added = 0;
52 u32 bss_change, rate_flags, rates = 0, rates_added = 0;
53 struct cfg80211_chan_def chandef;
54 enum nl80211_bss_scan_width scan_width;
55 bool have_higher_than_11mbit = false;
56 struct beacon_data *presp; 51 struct beacon_data *presp;
57 int frame_len; 52 int frame_len;
58 int shift; 53 int shift;
59 54
60 sdata_assert_lock(sdata);
61
62 /* Reset own TSF to allow time synchronization work. */
63 drv_reset_tsf(local, sdata);
64
65 if (!ether_addr_equal(ifibss->bssid, bssid))
66 sta_info_flush(sdata);
67
68 /* if merging, indicate to driver that we leave the old IBSS */
69 if (sdata->vif.bss_conf.ibss_joined) {
70 sdata->vif.bss_conf.ibss_joined = false;
71 sdata->vif.bss_conf.ibss_creator = false;
72 sdata->vif.bss_conf.enable_beacon = false;
73 netif_carrier_off(sdata->dev);
74 ieee80211_bss_info_change_notify(sdata,
75 BSS_CHANGED_IBSS |
76 BSS_CHANGED_BEACON_ENABLED);
77 }
78
79 presp = rcu_dereference_protected(ifibss->presp,
80 lockdep_is_held(&sdata->wdev.mtx));
81 rcu_assign_pointer(ifibss->presp, NULL);
82 if (presp)
83 kfree_rcu(presp, rcu_head);
84
85 sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
86
87 chandef = ifibss->chandef;
88 if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) {
89 if (chandef.width == NL80211_CHAN_WIDTH_5 ||
90 chandef.width == NL80211_CHAN_WIDTH_10 ||
91 chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
92 chandef.width == NL80211_CHAN_WIDTH_20) {
93 sdata_info(sdata,
94 "Failed to join IBSS, beacons forbidden\n");
95 return;
96 }
97 chandef.width = NL80211_CHAN_WIDTH_20;
98 chandef.center_freq1 = chan->center_freq;
99 }
100
101 ieee80211_vif_release_channel(sdata);
102 if (ieee80211_vif_use_channel(sdata, &chandef,
103 ifibss->fixed_channel ?
104 IEEE80211_CHANCTX_SHARED :
105 IEEE80211_CHANCTX_EXCLUSIVE)) {
106 sdata_info(sdata, "Failed to join IBSS, no channel context\n");
107 return;
108 }
109
110 memcpy(ifibss->bssid, bssid, ETH_ALEN);
111
112 sband = local->hw.wiphy->bands[chan->band];
113 shift = ieee80211_vif_get_shift(&sdata->vif);
114
115 /* Build IBSS probe response */ 55 /* Build IBSS probe response */
116 frame_len = sizeof(struct ieee80211_hdr_3addr) + 56 frame_len = sizeof(struct ieee80211_hdr_3addr) +
117 12 /* struct ieee80211_mgmt.u.beacon */ + 57 12 /* struct ieee80211_mgmt.u.beacon */ +
@@ -125,7 +65,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
125 ifibss->ie_len; 65 ifibss->ie_len;
126 presp = kzalloc(sizeof(*presp) + frame_len, GFP_KERNEL); 66 presp = kzalloc(sizeof(*presp) + frame_len, GFP_KERNEL);
127 if (!presp) 67 if (!presp)
128 return; 68 return NULL;
129 69
130 presp->head = (void *)(presp + 1); 70 presp->head = (void *)(presp + 1);
131 71
@@ -146,12 +86,19 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
146 memcpy(pos, ifibss->ssid, ifibss->ssid_len); 86 memcpy(pos, ifibss->ssid, ifibss->ssid_len);
147 pos += ifibss->ssid_len; 87 pos += ifibss->ssid_len;
148 88
149 rate_flags = ieee80211_chandef_rate_flags(&chandef); 89 sband = local->hw.wiphy->bands[chandef->chan->band];
90 rate_flags = ieee80211_chandef_rate_flags(chandef);
91 shift = ieee80211_chandef_get_shift(chandef);
92 rates_n = 0;
93 if (have_higher_than_11mbit)
94 *have_higher_than_11mbit = false;
95
150 for (i = 0; i < sband->n_bitrates; i++) { 96 for (i = 0; i < sband->n_bitrates; i++) {
151 if ((rate_flags & sband->bitrates[i].flags) != rate_flags) 97 if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
152 continue; 98 continue;
153 if (sband->bitrates[i].bitrate > 110) 99 if (sband->bitrates[i].bitrate > 110 &&
154 have_higher_than_11mbit = true; 100 have_higher_than_11mbit)
101 *have_higher_than_11mbit = true;
155 102
156 rates |= BIT(i); 103 rates |= BIT(i);
157 rates_n++; 104 rates_n++;
@@ -178,7 +125,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
178 if (sband->band == IEEE80211_BAND_2GHZ) { 125 if (sband->band == IEEE80211_BAND_2GHZ) {
179 *pos++ = WLAN_EID_DS_PARAMS; 126 *pos++ = WLAN_EID_DS_PARAMS;
180 *pos++ = 1; 127 *pos++ = 1;
181 *pos++ = ieee80211_frequency_to_channel(chan->center_freq); 128 *pos++ = ieee80211_frequency_to_channel(
129 chandef->chan->center_freq);
182 } 130 }
183 131
184 *pos++ = WLAN_EID_IBSS_PARAMS; 132 *pos++ = WLAN_EID_IBSS_PARAMS;
@@ -210,9 +158,9 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
210 } 158 }
211 159
212 /* add HT capability and information IEs */ 160 /* add HT capability and information IEs */
213 if (chandef.width != NL80211_CHAN_WIDTH_20_NOHT && 161 if (chandef->width != NL80211_CHAN_WIDTH_20_NOHT &&
214 chandef.width != NL80211_CHAN_WIDTH_5 && 162 chandef->width != NL80211_CHAN_WIDTH_5 &&
215 chandef.width != NL80211_CHAN_WIDTH_10 && 163 chandef->width != NL80211_CHAN_WIDTH_10 &&
216 sband->ht_cap.ht_supported) { 164 sband->ht_cap.ht_supported) {
217 struct ieee80211_sta_ht_cap ht_cap; 165 struct ieee80211_sta_ht_cap ht_cap;
218 166
@@ -226,7 +174,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
226 * keep them at 0 174 * keep them at 0
227 */ 175 */
228 pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap, 176 pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap,
229 &chandef, 0); 177 chandef, 0);
230 } 178 }
231 179
232 if (local->hw.queues >= IEEE80211_NUM_ACS) { 180 if (local->hw.queues >= IEEE80211_NUM_ACS) {
@@ -243,9 +191,94 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
243 191
244 presp->head_len = pos - presp->head; 192 presp->head_len = pos - presp->head;
245 if (WARN_ON(presp->head_len > frame_len)) 193 if (WARN_ON(presp->head_len > frame_len))
194 goto error;
195
196 return presp;
197error:
198 kfree(presp);
199 return NULL;
200}
201
202static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
203 const u8 *bssid, const int beacon_int,
204 struct ieee80211_channel *chan,
205 const u32 basic_rates,
206 const u16 capability, u64 tsf,
207 bool creator)
208{
209 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
210 struct ieee80211_local *local = sdata->local;
211 struct ieee80211_supported_band *sband;
212 struct ieee80211_mgmt *mgmt;
213 struct cfg80211_bss *bss;
214 u32 bss_change;
215 struct cfg80211_chan_def chandef;
216 struct beacon_data *presp;
217 enum nl80211_bss_scan_width scan_width;
218 bool have_higher_than_11mbit;
219
220 sdata_assert_lock(sdata);
221
222 /* Reset own TSF to allow time synchronization work. */
223 drv_reset_tsf(local, sdata);
224
225 if (!ether_addr_equal(ifibss->bssid, bssid))
226 sta_info_flush(sdata);
227
228 /* if merging, indicate to driver that we leave the old IBSS */
229 if (sdata->vif.bss_conf.ibss_joined) {
230 sdata->vif.bss_conf.ibss_joined = false;
231 sdata->vif.bss_conf.ibss_creator = false;
232 sdata->vif.bss_conf.enable_beacon = false;
233 netif_carrier_off(sdata->dev);
234 ieee80211_bss_info_change_notify(sdata,
235 BSS_CHANGED_IBSS |
236 BSS_CHANGED_BEACON_ENABLED);
237 }
238
239 presp = rcu_dereference_protected(ifibss->presp,
240 lockdep_is_held(&sdata->wdev.mtx));
241 rcu_assign_pointer(ifibss->presp, NULL);
242 if (presp)
243 kfree_rcu(presp, rcu_head);
244
245 sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
246
247 chandef = ifibss->chandef;
248 if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) {
249 if (chandef.width == NL80211_CHAN_WIDTH_5 ||
250 chandef.width == NL80211_CHAN_WIDTH_10 ||
251 chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
252 chandef.width == NL80211_CHAN_WIDTH_20) {
253 sdata_info(sdata,
254 "Failed to join IBSS, beacons forbidden\n");
255 return;
256 }
257 chandef.width = NL80211_CHAN_WIDTH_20;
258 chandef.center_freq1 = chan->center_freq;
259 }
260
261 ieee80211_vif_release_channel(sdata);
262 if (ieee80211_vif_use_channel(sdata, &chandef,
263 ifibss->fixed_channel ?
264 IEEE80211_CHANCTX_SHARED :
265 IEEE80211_CHANCTX_EXCLUSIVE)) {
266 sdata_info(sdata, "Failed to join IBSS, no channel context\n");
267 return;
268 }
269
270 memcpy(ifibss->bssid, bssid, ETH_ALEN);
271
272 sband = local->hw.wiphy->bands[chan->band];
273
274 presp = ieee80211_ibss_build_presp(sdata, beacon_int, basic_rates,
275 capability, tsf, &chandef,
276 &have_higher_than_11mbit);
277 if (!presp)
246 return; 278 return;
247 279
248 rcu_assign_pointer(ifibss->presp, presp); 280 rcu_assign_pointer(ifibss->presp, presp);
281 mgmt = (void *)presp->head;
249 282
250 sdata->vif.bss_conf.enable_beacon = true; 283 sdata->vif.bss_conf.enable_beacon = true;
251 sdata->vif.bss_conf.beacon_int = beacon_int; 284 sdata->vif.bss_conf.beacon_int = beacon_int;