aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorDaniel Drake <dsd@gentoo.org>2007-07-27 09:43:24 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:47:38 -0400
commit7e9ed18874f0df84b6651f0636e1cfdac43bc610 (patch)
tree7bac6083031a48e488c0de5bf71e7f9398e0e011 /net/mac80211
parentd5d08def9216c445339c5a24a2cdc9cc2c8c13f7 (diff)
[MAC80211]: improved short preamble handling
Similarly to CTS protection, whether short preambles are used for 802.11b transmissions should be a per-subif setting, not device global. For STAs, this patch makes short preamble handling automatic based on the ERP IE. For APs, hostapd still uses the prism ioctls, but the write ioctl has been restricted to AP-only subifs. ieee80211_txrx_data.short_preamble (an unused field) was removed. Unfortunately, some API changes were required for the following functions: - ieee80211_generic_frame_duration - ieee80211_rts_duration - ieee80211_ctstoself_duration - ieee80211_rts_get - ieee80211_ctstoself_get Affected drivers were updated accordingly. Signed-off-by: Daniel Drake <dsd@gentoo.org> Signed-off-by: Jiri Benc <jbenc@suse.cz> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/ieee80211_i.h7
-rw-r--r--net/mac80211/ieee80211_ioctl.c7
-rw-r--r--net/mac80211/ieee80211_sta.c16
-rw-r--r--net/mac80211/tx.c31
-rw-r--r--net/mac80211/util.c37
5 files changed, 74 insertions, 24 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index e76a58678959..b0af6e9f5319 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -127,7 +127,6 @@ struct ieee80211_txrx_data {
127 struct ieee80211_tx_control *control; 127 struct ieee80211_tx_control *control;
128 unsigned int unicast:1; 128 unsigned int unicast:1;
129 unsigned int ps_buffered:1; 129 unsigned int ps_buffered:1;
130 unsigned int short_preamble:1;
131 unsigned int probe_last_frag:1; 130 unsigned int probe_last_frag:1;
132 struct ieee80211_hw_mode *mode; 131 struct ieee80211_hw_mode *mode;
133 struct ieee80211_rate *rate; 132 struct ieee80211_rate *rate;
@@ -286,6 +285,11 @@ struct ieee80211_sub_if_data {
286 unsigned int promisc:1; 285 unsigned int promisc:1;
287 unsigned int use_protection:1; /* CTS protect ERP frames */ 286 unsigned int use_protection:1; /* CTS protect ERP frames */
288 287
288 /* use short preamble with IEEE 802.11b: this flag is set when the AP
289 * or beacon generator reports that there are no present stations that
290 * cannot support short preambles */
291 unsigned int short_preamble:1;
292
289 struct net_device_stats stats; 293 struct net_device_stats stats;
290 int drop_unencrypted; 294 int drop_unencrypted;
291 int eapol; /* 0 = process EAPOL frames as normal data frames, 295 int eapol; /* 0 = process EAPOL frames as normal data frames,
@@ -447,7 +451,6 @@ struct ieee80211_local {
447 int fragmentation_threshold; 451 int fragmentation_threshold;
448 int short_retry_limit; /* dot11ShortRetryLimit */ 452 int short_retry_limit; /* dot11ShortRetryLimit */
449 int long_retry_limit; /* dot11LongRetryLimit */ 453 int long_retry_limit; /* dot11LongRetryLimit */
450 int short_preamble; /* use short preamble with IEEE 802.11b */
451 454
452 struct crypto_blkcipher *wep_tx_tfm; 455 struct crypto_blkcipher *wep_tx_tfm;
453 struct crypto_blkcipher *wep_rx_tfm; 456 struct crypto_blkcipher *wep_rx_tfm;
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c
index e7904db55325..8292431ac48f 100644
--- a/net/mac80211/ieee80211_ioctl.c
+++ b/net/mac80211/ieee80211_ioctl.c
@@ -1061,7 +1061,10 @@ static int ieee80211_ioctl_prism2_param(struct net_device *dev,
1061 break; 1061 break;
1062 1062
1063 case PRISM2_PARAM_PREAMBLE: 1063 case PRISM2_PARAM_PREAMBLE:
1064 local->short_preamble = value; 1064 if (sdata->type != IEEE80211_IF_TYPE_AP)
1065 ret = -ENOENT;
1066 else
1067 sdata->short_preamble = value;
1065 break; 1068 break;
1066 1069
1067 case PRISM2_PARAM_STAT_TIME: 1070 case PRISM2_PARAM_STAT_TIME:
@@ -1184,7 +1187,7 @@ static int ieee80211_ioctl_get_prism2_param(struct net_device *dev,
1184 break; 1187 break;
1185 1188
1186 case PRISM2_PARAM_PREAMBLE: 1189 case PRISM2_PARAM_PREAMBLE:
1187 *param = local->short_preamble; 1190 *param = sdata->short_preamble;
1188 break; 1191 break;
1189 1192
1190 case PRISM2_PARAM_STAT_TIME: 1193 case PRISM2_PARAM_STAT_TIME:
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index 8e6548974a9f..0f5f8131bd71 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -318,6 +318,7 @@ static void ieee80211_handle_erp_ie(struct net_device *dev, u8 erp_value)
318 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 318 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
319 struct ieee80211_if_sta *ifsta = &sdata->u.sta; 319 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
320 int use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0; 320 int use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
321 int preamble_mode = (erp_value & WLAN_ERP_BARKER_PREAMBLE) != 0;
321 322
322 if (use_protection != sdata->use_protection) { 323 if (use_protection != sdata->use_protection) {
323 if (net_ratelimit()) { 324 if (net_ratelimit()) {
@@ -329,6 +330,18 @@ static void ieee80211_handle_erp_ie(struct net_device *dev, u8 erp_value)
329 } 330 }
330 sdata->use_protection = use_protection; 331 sdata->use_protection = use_protection;
331 } 332 }
333
334 if (!preamble_mode != sdata->short_preamble) {
335 if (net_ratelimit()) {
336 printk(KERN_DEBUG "%s: switched to %s barker preamble"
337 " (BSSID=" MAC_FMT ")\n",
338 dev->name,
339 (preamble_mode == WLAN_ERP_PREAMBLE_SHORT) ?
340 "short" : "long",
341 MAC_ARG(ifsta->bssid));
342 }
343 sdata->short_preamble = !preamble_mode;
344 }
332} 345}
333 346
334 347
@@ -415,6 +428,7 @@ static void ieee80211_set_associated(struct net_device *dev,
415 ieee80211_sta_send_associnfo(dev, ifsta); 428 ieee80211_sta_send_associnfo(dev, ifsta);
416 } else { 429 } else {
417 netif_carrier_off(dev); 430 netif_carrier_off(dev);
431 sdata->short_preamble = 0;
418 sdata->use_protection = 0; 432 sdata->use_protection = 0;
419 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); 433 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
420 } 434 }
@@ -2281,7 +2295,7 @@ static int ieee80211_sta_join_ibss(struct net_device *dev,
2281 "for IBSS beacon\n", dev->name); 2295 "for IBSS beacon\n", dev->name);
2282 break; 2296 break;
2283 } 2297 }
2284 control.tx_rate = (local->short_preamble && 2298 control.tx_rate = (sdata->short_preamble &&
2285 (rate->flags & IEEE80211_RATE_PREAMBLE2)) ? 2299 (rate->flags & IEEE80211_RATE_PREAMBLE2)) ?
2286 rate->val2 : rate->val; 2300 rate->val2 : rate->val;
2287 control.antenna_sel_tx = local->hw.conf.antenna_sel_tx; 2301 control.antenna_sel_tx = local->hw.conf.antenna_sel_tx;
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 532cf5127b70..36761c7139bc 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -173,7 +173,7 @@ static u16 ieee80211_duration(struct ieee80211_txrx_data *tx, int group_addr,
173 * to closest integer */ 173 * to closest integer */
174 174
175 dur = ieee80211_frame_duration(local, 10, rate, erp, 175 dur = ieee80211_frame_duration(local, 10, rate, erp,
176 local->short_preamble); 176 tx->sdata->short_preamble);
177 177
178 if (next_frag_len) { 178 if (next_frag_len) {
179 /* Frame is fragmented: duration increases with time needed to 179 /* Frame is fragmented: duration increases with time needed to
@@ -182,7 +182,7 @@ static u16 ieee80211_duration(struct ieee80211_txrx_data *tx, int group_addr,
182 /* next fragment */ 182 /* next fragment */
183 dur += ieee80211_frame_duration(local, next_frag_len, 183 dur += ieee80211_frame_duration(local, next_frag_len,
184 txrate->rate, erp, 184 txrate->rate, erp,
185 local->short_preamble); 185 tx->sdata->short_preamble);
186 } 186 }
187 187
188 return dur; 188 return dur;
@@ -627,12 +627,6 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_txrx_data *tx)
627 tx->u.tx.control->rate = tx->u.tx.rate; 627 tx->u.tx.control->rate = tx->u.tx.rate;
628 } 628 }
629 tx->u.tx.control->tx_rate = tx->u.tx.rate->val; 629 tx->u.tx.control->tx_rate = tx->u.tx.rate->val;
630 if ((tx->u.tx.rate->flags & IEEE80211_RATE_PREAMBLE2) &&
631 tx->local->short_preamble &&
632 (!tx->sta || (tx->sta->flags & WLAN_STA_SHORT_PREAMBLE))) {
633 tx->u.tx.short_preamble = 1;
634 tx->u.tx.control->tx_rate = tx->u.tx.rate->val2;
635 }
636 630
637 return TXRX_CONTINUE; 631 return TXRX_CONTINUE;
638} 632}
@@ -641,6 +635,7 @@ static ieee80211_txrx_result
641ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx) 635ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx)
642{ 636{
643 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; 637 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
638 u16 fc = le16_to_cpu(hdr->frame_control);
644 u16 dur; 639 u16 dur;
645 struct ieee80211_tx_control *control = tx->u.tx.control; 640 struct ieee80211_tx_control *control = tx->u.tx.control;
646 struct ieee80211_hw_mode *mode = tx->u.tx.mode; 641 struct ieee80211_hw_mode *mode = tx->u.tx.mode;
@@ -677,6 +672,16 @@ ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx)
677 !(control->flags & IEEE80211_TXCTL_USE_RTS_CTS)) 672 !(control->flags & IEEE80211_TXCTL_USE_RTS_CTS))
678 control->flags |= IEEE80211_TXCTL_USE_CTS_PROTECT; 673 control->flags |= IEEE80211_TXCTL_USE_CTS_PROTECT;
679 674
675 /* Transmit data frames using short preambles if the driver supports
676 * short preambles at the selected rate and short preambles are
677 * available on the network at the current point in time. */
678 if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
679 (tx->u.tx.rate->flags & IEEE80211_RATE_PREAMBLE2) &&
680 tx->sdata->short_preamble &&
681 (!tx->sta || (tx->sta->flags & WLAN_STA_SHORT_PREAMBLE))) {
682 tx->u.tx.control->tx_rate = tx->u.tx.rate->val2;
683 }
684
680 /* Setup duration field for the first fragment of the frame. Duration 685 /* Setup duration field for the first fragment of the frame. Duration
681 * for remaining fragments will be updated when they are being sent 686 * for remaining fragments will be updated when they are being sent
682 * to low-level driver in ieee80211_tx(). */ 687 * to low-level driver in ieee80211_tx(). */
@@ -1750,7 +1755,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, int if_id,
1750 return NULL; 1755 return NULL;
1751 } 1756 }
1752 1757
1753 control->tx_rate = (local->short_preamble && 1758 control->tx_rate = (sdata->short_preamble &&
1754 (rate->flags & IEEE80211_RATE_PREAMBLE2)) ? 1759 (rate->flags & IEEE80211_RATE_PREAMBLE2)) ?
1755 rate->val2 : rate->val; 1760 rate->val2 : rate->val;
1756 control->antenna_sel_tx = local->hw.conf.antenna_sel_tx; 1761 control->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
@@ -1765,7 +1770,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, int if_id,
1765} 1770}
1766EXPORT_SYMBOL(ieee80211_beacon_get); 1771EXPORT_SYMBOL(ieee80211_beacon_get);
1767 1772
1768void ieee80211_rts_get(struct ieee80211_hw *hw, 1773void ieee80211_rts_get(struct ieee80211_hw *hw, int if_id,
1769 const void *frame, size_t frame_len, 1774 const void *frame, size_t frame_len,
1770 const struct ieee80211_tx_control *frame_txctl, 1775 const struct ieee80211_tx_control *frame_txctl,
1771 struct ieee80211_rts *rts) 1776 struct ieee80211_rts *rts)
@@ -1775,13 +1780,13 @@ void ieee80211_rts_get(struct ieee80211_hw *hw,
1775 1780
1776 fctl = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS; 1781 fctl = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS;
1777 rts->frame_control = cpu_to_le16(fctl); 1782 rts->frame_control = cpu_to_le16(fctl);
1778 rts->duration = ieee80211_rts_duration(hw, frame_len, frame_txctl); 1783 rts->duration = ieee80211_rts_duration(hw, if_id, frame_len, frame_txctl);
1779 memcpy(rts->ra, hdr->addr1, sizeof(rts->ra)); 1784 memcpy(rts->ra, hdr->addr1, sizeof(rts->ra));
1780 memcpy(rts->ta, hdr->addr2, sizeof(rts->ta)); 1785 memcpy(rts->ta, hdr->addr2, sizeof(rts->ta));
1781} 1786}
1782EXPORT_SYMBOL(ieee80211_rts_get); 1787EXPORT_SYMBOL(ieee80211_rts_get);
1783 1788
1784void ieee80211_ctstoself_get(struct ieee80211_hw *hw, 1789void ieee80211_ctstoself_get(struct ieee80211_hw *hw, int if_id,
1785 const void *frame, size_t frame_len, 1790 const void *frame, size_t frame_len,
1786 const struct ieee80211_tx_control *frame_txctl, 1791 const struct ieee80211_tx_control *frame_txctl,
1787 struct ieee80211_cts *cts) 1792 struct ieee80211_cts *cts)
@@ -1791,7 +1796,7 @@ void ieee80211_ctstoself_get(struct ieee80211_hw *hw,
1791 1796
1792 fctl = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS; 1797 fctl = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS;
1793 cts->frame_control = cpu_to_le16(fctl); 1798 cts->frame_control = cpu_to_le16(fctl);
1794 cts->duration = ieee80211_ctstoself_duration(hw, frame_len, frame_txctl); 1799 cts->duration = ieee80211_ctstoself_duration(hw, if_id, frame_len, frame_txctl);
1795 memcpy(cts->ra, hdr->addr1, sizeof(cts->ra)); 1800 memcpy(cts->ra, hdr->addr1, sizeof(cts->ra));
1796} 1801}
1797EXPORT_SYMBOL(ieee80211_ctstoself_get); 1802EXPORT_SYMBOL(ieee80211_ctstoself_get);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index c45658309472..091ac0d634a5 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -314,31 +314,46 @@ int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
314} 314}
315 315
316/* Exported duration function for driver use */ 316/* Exported duration function for driver use */
317__le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, 317__le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, int if_id,
318 size_t frame_len, int rate) 318 size_t frame_len, int rate)
319{ 319{
320 struct ieee80211_local *local = hw_to_local(hw); 320 struct ieee80211_local *local = hw_to_local(hw);
321 struct net_device *bdev = dev_get_by_index(if_id);
322 struct ieee80211_sub_if_data *sdata;
321 u16 dur; 323 u16 dur;
322 int erp; 324 int erp;
323 325
326 if (unlikely(!bdev))
327 return 0;
328
329 sdata = IEEE80211_DEV_TO_SUB_IF(bdev);
324 erp = ieee80211_is_erp_rate(hw->conf.phymode, rate); 330 erp = ieee80211_is_erp_rate(hw->conf.phymode, rate);
325 dur = ieee80211_frame_duration(local, frame_len, rate, 331 dur = ieee80211_frame_duration(local, frame_len, rate,
326 erp, local->short_preamble); 332 erp, sdata->short_preamble);
327 333
334 dev_put(bdev);
328 return cpu_to_le16(dur); 335 return cpu_to_le16(dur);
329} 336}
330EXPORT_SYMBOL(ieee80211_generic_frame_duration); 337EXPORT_SYMBOL(ieee80211_generic_frame_duration);
331 338
332__le16 ieee80211_rts_duration(struct ieee80211_hw *hw, 339__le16 ieee80211_rts_duration(struct ieee80211_hw *hw, int if_id,
333 size_t frame_len, 340 size_t frame_len,
334 const struct ieee80211_tx_control *frame_txctl) 341 const struct ieee80211_tx_control *frame_txctl)
335{ 342{
336 struct ieee80211_local *local = hw_to_local(hw); 343 struct ieee80211_local *local = hw_to_local(hw);
337 struct ieee80211_rate *rate; 344 struct ieee80211_rate *rate;
338 int short_preamble = local->short_preamble; 345 struct net_device *bdev = dev_get_by_index(if_id);
346 struct ieee80211_sub_if_data *sdata;
347 int short_preamble;
339 int erp; 348 int erp;
340 u16 dur; 349 u16 dur;
341 350
351 if (unlikely(!bdev))
352 return 0;
353
354 sdata = IEEE80211_DEV_TO_SUB_IF(bdev);
355 short_preamble = sdata->short_preamble;
356
342 rate = frame_txctl->rts_rate; 357 rate = frame_txctl->rts_rate;
343 erp = !!(rate->flags & IEEE80211_RATE_ERP); 358 erp = !!(rate->flags & IEEE80211_RATE_ERP);
344 359
@@ -352,20 +367,29 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
352 dur += ieee80211_frame_duration(local, 10, rate->rate, 367 dur += ieee80211_frame_duration(local, 10, rate->rate,
353 erp, short_preamble); 368 erp, short_preamble);
354 369
370 dev_put(bdev);
355 return cpu_to_le16(dur); 371 return cpu_to_le16(dur);
356} 372}
357EXPORT_SYMBOL(ieee80211_rts_duration); 373EXPORT_SYMBOL(ieee80211_rts_duration);
358 374
359__le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, 375__le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, int if_id,
360 size_t frame_len, 376 size_t frame_len,
361 const struct ieee80211_tx_control *frame_txctl) 377 const struct ieee80211_tx_control *frame_txctl)
362{ 378{
363 struct ieee80211_local *local = hw_to_local(hw); 379 struct ieee80211_local *local = hw_to_local(hw);
364 struct ieee80211_rate *rate; 380 struct ieee80211_rate *rate;
365 int short_preamble = local->short_preamble; 381 struct net_device *bdev = dev_get_by_index(if_id);
382 struct ieee80211_sub_if_data *sdata;
383 int short_preamble;
366 int erp; 384 int erp;
367 u16 dur; 385 u16 dur;
368 386
387 if (unlikely(!bdev))
388 return 0;
389
390 sdata = IEEE80211_DEV_TO_SUB_IF(bdev);
391 short_preamble = sdata->short_preamble;
392
369 rate = frame_txctl->rts_rate; 393 rate = frame_txctl->rts_rate;
370 erp = !!(rate->flags & IEEE80211_RATE_ERP); 394 erp = !!(rate->flags & IEEE80211_RATE_ERP);
371 395
@@ -378,6 +402,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
378 erp, short_preamble); 402 erp, short_preamble);
379 } 403 }
380 404
405 dev_put(bdev);
381 return cpu_to_le16(dur); 406 return cpu_to_le16(dur);
382} 407}
383EXPORT_SYMBOL(ieee80211_ctstoself_duration); 408EXPORT_SYMBOL(ieee80211_ctstoself_duration);