Commit d51b70ff5122d31e27733ba03c3afd62bb86bd63

Authored by Simon Wunderlich
Committed by Johannes Berg
1 parent 86c228a762

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>

Showing 1 changed file with 109 additions and 76 deletions Side-by-side Diff

... ... @@ -34,13 +34,12 @@
34 34  
35 35 #define IEEE80211_IBSS_MAX_STA_ENTRIES 128
36 36  
37   -
38   -static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
39   - const u8 *bssid, const int beacon_int,
40   - struct ieee80211_channel *chan,
41   - const u32 basic_rates,
42   - const u16 capability, u64 tsf,
43   - bool creator)
  37 +static struct beacon_data *
  38 +ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata,
  39 + const int beacon_int, const u32 basic_rates,
  40 + const u16 capability, u64 tsf,
  41 + struct cfg80211_chan_def *chandef,
  42 + bool *have_higher_than_11mbit)
44 43 {
45 44 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
46 45 struct ieee80211_local *local = sdata->local;
47 46  
... ... @@ -48,70 +47,11 @@
48 47 struct ieee80211_mgmt *mgmt;
49 48 u8 *pos;
50 49 struct ieee80211_supported_band *sband;
51   - struct cfg80211_bss *bss;
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;
  50 + u32 rate_flags, rates = 0, rates_added = 0;
56 51 struct beacon_data *presp;
57 52 int frame_len;
58 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 55 /* Build IBSS probe response */
116 56 frame_len = sizeof(struct ieee80211_hdr_3addr) +
117 57 12 /* struct ieee80211_mgmt.u.beacon */ +
... ... @@ -125,7 +65,7 @@
125 65 ifibss->ie_len;
126 66 presp = kzalloc(sizeof(*presp) + frame_len, GFP_KERNEL);
127 67 if (!presp)
128   - return;
  68 + return NULL;
129 69  
130 70 presp->head = (void *)(presp + 1);
131 71  
132 72  
... ... @@ -146,12 +86,19 @@
146 86 memcpy(pos, ifibss->ssid, ifibss->ssid_len);
147 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 96 for (i = 0; i < sband->n_bitrates; i++) {
151 97 if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
152 98 continue;
153   - if (sband->bitrates[i].bitrate > 110)
154   - have_higher_than_11mbit = true;
  99 + if (sband->bitrates[i].bitrate > 110 &&
  100 + have_higher_than_11mbit)
  101 + *have_higher_than_11mbit = true;
155 102  
156 103 rates |= BIT(i);
157 104 rates_n++;
... ... @@ -178,7 +125,8 @@
178 125 if (sband->band == IEEE80211_BAND_2GHZ) {
179 126 *pos++ = WLAN_EID_DS_PARAMS;
180 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 132 *pos++ = WLAN_EID_IBSS_PARAMS;
... ... @@ -210,9 +158,9 @@
210 158 }
211 159  
212 160 /* add HT capability and information IEs */
213   - if (chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
214   - chandef.width != NL80211_CHAN_WIDTH_5 &&
215   - chandef.width != NL80211_CHAN_WIDTH_10 &&
  161 + if (chandef->width != NL80211_CHAN_WIDTH_20_NOHT &&
  162 + chandef->width != NL80211_CHAN_WIDTH_5 &&
  163 + chandef->width != NL80211_CHAN_WIDTH_10 &&
216 164 sband->ht_cap.ht_supported) {
217 165 struct ieee80211_sta_ht_cap ht_cap;
218 166  
... ... @@ -226,7 +174,7 @@
226 174 * keep them at 0
227 175 */
228 176 pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap,
229   - &chandef, 0);
  177 + chandef, 0);
230 178 }
231 179  
232 180 if (local->hw.queues >= IEEE80211_NUM_ACS) {
233 181  
234 182  
235 183  
... ... @@ -243,9 +191,94 @@
243 191  
244 192 presp->head_len = pos - presp->head;
245 193 if (WARN_ON(presp->head_len > frame_len))
  194 + goto error;
  195 +
  196 + return presp;
  197 +error:
  198 + kfree(presp);
  199 + return NULL;
  200 +}
  201 +
  202 +static 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");
246 267 return;
  268 + }
247 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)
  278 + return;
  279 +
248 280 rcu_assign_pointer(ifibss->presp, presp);
  281 + mgmt = (void *)presp->head;
249 282  
250 283 sdata->vif.bss_conf.enable_beacon = true;
251 284 sdata->vif.bss_conf.beacon_int = beacon_int;