aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/ibss.c
diff options
context:
space:
mode:
authorSimon Wunderlich <simon.wunderlich@s2003.tu-chemnitz.de>2013-07-08 10:55:53 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-07-16 02:58:06 -0400
commit2103dec14792be2c2194a454630b01120d30e5cb (patch)
tree6bc0cd39eb2fe5317f0383ed7c4c238fb98ec114 /net/mac80211/ibss.c
parenta5e70697d0c4836e69c60de92db27eac9ae71e05 (diff)
mac80211: select and adjust bitrates according to channel mode
The various components accessing the bitrates table must use consider the used channel bandwidth to select only available rates or calculate the bitrate correctly. There are some rates in reduced bandwidth modes which can't be represented as multiples of 500kbps, like 2.25 MBit/s in 5 MHz mode. The standard suggests to round up to the next multiple of 500kbps, just do that in mac80211 as well. Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> Signed-off-by: Mathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de> [make rate unsigned in ieee80211_add_tx_radiotap_header(), squash fix] Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Diffstat (limited to 'net/mac80211/ibss.c')
-rw-r--r--net/mac80211/ibss.c81
1 files changed, 62 insertions, 19 deletions
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 7f290a8562ef..272a3b37615c 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -43,16 +43,17 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
43{ 43{
44 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 44 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
45 struct ieee80211_local *local = sdata->local; 45 struct ieee80211_local *local = sdata->local;
46 int rates, i; 46 int rates_n = 0, i, ri;
47 struct ieee80211_mgmt *mgmt; 47 struct ieee80211_mgmt *mgmt;
48 u8 *pos; 48 u8 *pos;
49 struct ieee80211_supported_band *sband; 49 struct ieee80211_supported_band *sband;
50 struct cfg80211_bss *bss; 50 struct cfg80211_bss *bss;
51 u32 bss_change; 51 u32 bss_change, rate_flags, rates = 0, rates_added = 0;
52 u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; 52 u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
53 struct cfg80211_chan_def chandef; 53 struct cfg80211_chan_def chandef;
54 struct beacon_data *presp; 54 struct beacon_data *presp;
55 int frame_len; 55 int frame_len;
56 int shift;
56 57
57 sdata_assert_lock(sdata); 58 sdata_assert_lock(sdata);
58 59
@@ -99,6 +100,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
99 memcpy(ifibss->bssid, bssid, ETH_ALEN); 100 memcpy(ifibss->bssid, bssid, ETH_ALEN);
100 101
101 sband = local->hw.wiphy->bands[chan->band]; 102 sband = local->hw.wiphy->bands[chan->band];
103 shift = ieee80211_vif_get_shift(&sdata->vif);
102 104
103 /* Build IBSS probe response */ 105 /* Build IBSS probe response */
104 frame_len = sizeof(struct ieee80211_hdr_3addr) + 106 frame_len = sizeof(struct ieee80211_hdr_3addr) +
@@ -134,15 +136,29 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
134 memcpy(pos, ifibss->ssid, ifibss->ssid_len); 136 memcpy(pos, ifibss->ssid, ifibss->ssid_len);
135 pos += ifibss->ssid_len; 137 pos += ifibss->ssid_len;
136 138
137 rates = min_t(int, 8, sband->n_bitrates); 139 rate_flags = ieee80211_chandef_rate_flags(&chandef);
140 for (i = 0; i < sband->n_bitrates; i++) {
141 if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
142 continue;
143
144 rates |= BIT(i);
145 rates_n++;
146 }
147
138 *pos++ = WLAN_EID_SUPP_RATES; 148 *pos++ = WLAN_EID_SUPP_RATES;
139 *pos++ = rates; 149 *pos++ = min_t(int, 8, rates_n);
140 for (i = 0; i < rates; i++) { 150 for (ri = 0; ri < sband->n_bitrates; ri++) {
141 int rate = sband->bitrates[i].bitrate; 151 int rate = DIV_ROUND_UP(sband->bitrates[ri].bitrate,
152 5 * (1 << shift));
142 u8 basic = 0; 153 u8 basic = 0;
143 if (basic_rates & BIT(i)) 154 if (!(rates & BIT(ri)))
155 continue;
156
157 if (basic_rates & BIT(ri))
144 basic = 0x80; 158 basic = 0x80;
145 *pos++ = basic | (u8) (rate / 5); 159 *pos++ = basic | (u8) rate;
160 if (++rates_added == 8)
161 break;
146 } 162 }
147 163
148 if (sband->band == IEEE80211_BAND_2GHZ) { 164 if (sband->band == IEEE80211_BAND_2GHZ) {
@@ -157,15 +173,20 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
157 *pos++ = 0; 173 *pos++ = 0;
158 *pos++ = 0; 174 *pos++ = 0;
159 175
160 if (sband->n_bitrates > 8) { 176 /* put the remaining rates in WLAN_EID_EXT_SUPP_RATES */
177 if (rates_n > 8) {
161 *pos++ = WLAN_EID_EXT_SUPP_RATES; 178 *pos++ = WLAN_EID_EXT_SUPP_RATES;
162 *pos++ = sband->n_bitrates - 8; 179 *pos++ = rates_n - 8;
163 for (i = 8; i < sband->n_bitrates; i++) { 180 for (; ri < sband->n_bitrates; ri++) {
164 int rate = sband->bitrates[i].bitrate; 181 int rate = DIV_ROUND_UP(sband->bitrates[ri].bitrate,
182 5 * (1 << shift));
165 u8 basic = 0; 183 u8 basic = 0;
166 if (basic_rates & BIT(i)) 184 if (!(rates & BIT(ri)))
185 continue;
186
187 if (basic_rates & BIT(ri))
167 basic = 0x80; 188 basic = 0x80;
168 *pos++ = basic | (u8) (rate / 5); 189 *pos++ = basic | (u8) rate;
169 } 190 }
170 } 191 }
171 192
@@ -244,7 +265,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
244 sdata->vif.bss_conf.ibss_creator = creator; 265 sdata->vif.bss_conf.ibss_creator = creator;
245 ieee80211_bss_info_change_notify(sdata, bss_change); 266 ieee80211_bss_info_change_notify(sdata, bss_change);
246 267
247 ieee80211_sta_def_wmm_params(sdata, sband->n_bitrates, supp_rates); 268 ieee80211_sta_def_wmm_params(sdata, rates, supp_rates);
248 269
249 ifibss->state = IEEE80211_IBSS_MLME_JOINED; 270 ifibss->state = IEEE80211_IBSS_MLME_JOINED;
250 mod_timer(&ifibss->timer, 271 mod_timer(&ifibss->timer,
@@ -268,6 +289,8 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
268 u16 beacon_int = cbss->beacon_interval; 289 u16 beacon_int = cbss->beacon_interval;
269 const struct cfg80211_bss_ies *ies; 290 const struct cfg80211_bss_ies *ies;
270 u64 tsf; 291 u64 tsf;
292 u32 rate_flags;
293 int shift;
271 294
272 sdata_assert_lock(sdata); 295 sdata_assert_lock(sdata);
273 296
@@ -275,15 +298,24 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
275 beacon_int = 10; 298 beacon_int = 10;
276 299
277 sband = sdata->local->hw.wiphy->bands[cbss->channel->band]; 300 sband = sdata->local->hw.wiphy->bands[cbss->channel->band];
301 rate_flags = ieee80211_chandef_rate_flags(&sdata->u.ibss.chandef);
302 shift = ieee80211_vif_get_shift(&sdata->vif);
278 303
279 basic_rates = 0; 304 basic_rates = 0;
280 305
281 for (i = 0; i < bss->supp_rates_len; i++) { 306 for (i = 0; i < bss->supp_rates_len; i++) {
282 int rate = (bss->supp_rates[i] & 0x7f) * 5; 307 int rate = bss->supp_rates[i] & 0x7f;
283 bool is_basic = !!(bss->supp_rates[i] & 0x80); 308 bool is_basic = !!(bss->supp_rates[i] & 0x80);
284 309
285 for (j = 0; j < sband->n_bitrates; j++) { 310 for (j = 0; j < sband->n_bitrates; j++) {
286 if (sband->bitrates[j].bitrate == rate) { 311 int brate;
312 if ((rate_flags & sband->bitrates[j].flags)
313 != rate_flags)
314 continue;
315
316 brate = DIV_ROUND_UP(sband->bitrates[j].bitrate,
317 5 * (1 << shift));
318 if (brate == rate) {
287 if (is_basic) 319 if (is_basic)
288 basic_rates |= BIT(j); 320 basic_rates |= BIT(j);
289 break; 321 break;
@@ -465,7 +497,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
465 sta = sta_info_get(sdata, mgmt->sa); 497 sta = sta_info_get(sdata, mgmt->sa);
466 498
467 if (elems->supp_rates) { 499 if (elems->supp_rates) {
468 supp_rates = ieee80211_sta_get_rates(local, elems, 500 supp_rates = ieee80211_sta_get_rates(sdata, elems,
469 band, NULL); 501 band, NULL);
470 if (sta) { 502 if (sta) {
471 u32 prev_rates; 503 u32 prev_rates;
@@ -589,7 +621,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
589 "beacon TSF higher than local TSF - IBSS merge with BSSID %pM\n", 621 "beacon TSF higher than local TSF - IBSS merge with BSSID %pM\n",
590 mgmt->bssid); 622 mgmt->bssid);
591 ieee80211_sta_join_ibss(sdata, bss); 623 ieee80211_sta_join_ibss(sdata, bss);
592 supp_rates = ieee80211_sta_get_rates(local, elems, band, NULL); 624 supp_rates = ieee80211_sta_get_rates(sdata, elems, band, NULL);
593 ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, 625 ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa,
594 supp_rates); 626 supp_rates);
595 rcu_read_unlock(); 627 rcu_read_unlock();
@@ -1024,6 +1056,9 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
1024 struct cfg80211_ibss_params *params) 1056 struct cfg80211_ibss_params *params)
1025{ 1057{
1026 u32 changed = 0; 1058 u32 changed = 0;
1059 u32 rate_flags;
1060 struct ieee80211_supported_band *sband;
1061 int i;
1027 1062
1028 if (params->bssid) { 1063 if (params->bssid) {
1029 memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN); 1064 memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN);
@@ -1034,6 +1069,14 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
1034 sdata->u.ibss.privacy = params->privacy; 1069 sdata->u.ibss.privacy = params->privacy;
1035 sdata->u.ibss.control_port = params->control_port; 1070 sdata->u.ibss.control_port = params->control_port;
1036 sdata->u.ibss.basic_rates = params->basic_rates; 1071 sdata->u.ibss.basic_rates = params->basic_rates;
1072
1073 /* fix basic_rates if channel does not support these rates */
1074 rate_flags = ieee80211_chandef_rate_flags(&params->chandef);
1075 sband = sdata->local->hw.wiphy->bands[params->chandef.chan->band];
1076 for (i = 0; i < sband->n_bitrates; i++) {
1077 if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
1078 sdata->u.ibss.basic_rates &= ~BIT(i);
1079 }
1037 memcpy(sdata->vif.bss_conf.mcast_rate, params->mcast_rate, 1080 memcpy(sdata->vif.bss_conf.mcast_rate, params->mcast_rate,
1038 sizeof(params->mcast_rate)); 1081 sizeof(params->mcast_rate));
1039 1082