aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Drake <dsd@gentoo.org>2007-07-10 13:32:10 -0400
committerJohn W. Linville <linville@tuxdriver.com>2007-07-12 16:07:26 -0400
commit5628221caf88e2a052782b042e12da7cd34111b0 (patch)
treeb4dbee3be1aa2b39e3d4c6f384b28d07740465fd
parent1fd5e589d8c7d3cd42ddd39358338766cfcedec8 (diff)
[PATCH] mac80211: ERP IE handling improvements
The "protection needed" flag is currently parsed out of the ERP IE in beacons. This patch allows the ERP IE to be available at assocation time and causes the appropriate actions to be performed earlier. It is slightly complicated by the fact that most APs don't include the ERP IE in association responses. To work around this, we store ERP values in the ieee80211_sta_bss structure. Also added some WLAN_ERP defines for use by upcoming patches. Signed-off-by: Jiri Benc <jbenc@suse.cz> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--include/linux/ieee80211.h11
-rw-r--r--net/mac80211/ieee80211_i.h6
-rw-r--r--net/mac80211/ieee80211_sta.c69
3 files changed, 67 insertions, 19 deletions
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index ecd61e8438a5..272f8c8c90da 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -227,6 +227,17 @@ struct ieee80211_cts {
227#define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10) 227#define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10)
228#define WLAN_CAPABILITY_DSSS_OFDM (1<<13) 228#define WLAN_CAPABILITY_DSSS_OFDM (1<<13)
229 229
230/* 802.11g ERP information element */
231#define WLAN_ERP_NON_ERP_PRESENT (1<<0)
232#define WLAN_ERP_USE_PROTECTION (1<<1)
233#define WLAN_ERP_BARKER_PREAMBLE (1<<2)
234
235/* WLAN_ERP_BARKER_PREAMBLE values */
236enum {
237 WLAN_ERP_PREAMBLE_SHORT = 0,
238 WLAN_ERP_PREAMBLE_LONG = 1,
239};
240
230/* Status codes */ 241/* Status codes */
231enum ieee80211_statuscode { 242enum ieee80211_statuscode {
232 WLAN_STATUS_SUCCESS = 0, 243 WLAN_STATUS_SUCCESS = 0,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index b222a9afd4e9..99ff7c5e9204 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -99,6 +99,12 @@ struct ieee80211_sta_bss {
99 int probe_resp; 99 int probe_resp;
100 unsigned long last_update; 100 unsigned long last_update;
101 101
102 /* during assocation, we save an ERP value from a probe response so
103 * that we can feed ERP info to the driver when handling the
104 * association completes. these fields probably won't be up-to-date
105 * otherwise, you probably don't want to use them. */
106 int has_erp_value;
107 u8 erp_value;
102}; 108};
103 109
104 110
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index f3ca83743b48..df6c410de161 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -314,6 +314,27 @@ static void ieee80211_sta_wmm_params(struct net_device *dev,
314} 314}
315 315
316 316
317static void ieee80211_handle_erp_ie(struct net_device *dev, u8 erp_value)
318{
319 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
320 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
321 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
322 int use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
323
324 if (use_protection != !!ifsta->use_protection) {
325 if (net_ratelimit()) {
326 printk(KERN_DEBUG "%s: CTS protection %s (BSSID="
327 MAC_FMT ")\n",
328 dev->name,
329 use_protection ? "enabled" : "disabled",
330 MAC_ARG(ifsta->bssid));
331 }
332 ifsta->use_protection = use_protection ? 1 : 0;
333 local->cts_protect_erp_frames = use_protection;
334 }
335}
336
337
317static void ieee80211_sta_send_associnfo(struct net_device *dev, 338static void ieee80211_sta_send_associnfo(struct net_device *dev,
318 struct ieee80211_if_sta *ifsta) 339 struct ieee80211_if_sta *ifsta)
319{ 340{
@@ -377,9 +398,18 @@ static void ieee80211_set_associated(struct net_device *dev,
377 398
378 if (assoc) { 399 if (assoc) {
379 struct ieee80211_sub_if_data *sdata; 400 struct ieee80211_sub_if_data *sdata;
401 struct ieee80211_sta_bss *bss;
380 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 402 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
381 if (sdata->type != IEEE80211_IF_TYPE_STA) 403 if (sdata->type != IEEE80211_IF_TYPE_STA)
382 return; 404 return;
405
406 bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
407 if (bss) {
408 if (bss->has_erp_value)
409 ieee80211_handle_erp_ie(dev, bss->erp_value);
410 ieee80211_rx_bss_put(dev, bss);
411 }
412
383 netif_carrier_on(dev); 413 netif_carrier_on(dev);
384 ifsta->prev_bssid_set = 1; 414 ifsta->prev_bssid_set = 1;
385 memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN); 415 memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN);
@@ -1177,6 +1207,18 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
1177 return; 1207 return;
1178 } 1208 }
1179 1209
1210 /* it probably doesn't, but if the frame includes an ERP value then
1211 * update our stored copy */
1212 if (elems.erp_info && elems.erp_info_len >= 1) {
1213 struct ieee80211_sta_bss *bss
1214 = ieee80211_rx_bss_get(dev, ifsta->bssid);
1215 if (bss) {
1216 bss->erp_value = elems.erp_info[0];
1217 bss->has_erp_value = 1;
1218 ieee80211_rx_bss_put(dev, bss);
1219 }
1220 }
1221
1180 printk(KERN_DEBUG "%s: associated\n", dev->name); 1222 printk(KERN_DEBUG "%s: associated\n", dev->name);
1181 ifsta->aid = aid; 1223 ifsta->aid = aid;
1182 ifsta->ap_capab = capab_info; 1224 ifsta->ap_capab = capab_info;
@@ -1499,6 +1541,12 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
1499 return; 1541 return;
1500 } 1542 }
1501 1543
1544 /* save the ERP value so that it is available at association time */
1545 if (elems.erp_info && elems.erp_info_len >= 1) {
1546 bss->erp_value = elems.erp_info[0];
1547 bss->has_erp_value = 1;
1548 }
1549
1502 bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); 1550 bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
1503 bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); 1551 bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
1504 if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) { 1552 if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) {
@@ -1614,10 +1662,8 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
1614 size_t len, 1662 size_t len,
1615 struct ieee80211_rx_status *rx_status) 1663 struct ieee80211_rx_status *rx_status)
1616{ 1664{
1617 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
1618 struct ieee80211_sub_if_data *sdata; 1665 struct ieee80211_sub_if_data *sdata;
1619 struct ieee80211_if_sta *ifsta; 1666 struct ieee80211_if_sta *ifsta;
1620 int use_protection;
1621 size_t baselen; 1667 size_t baselen;
1622 struct ieee802_11_elems elems; 1668 struct ieee802_11_elems elems;
1623 1669
@@ -1641,23 +1687,8 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
1641 &elems) == ParseFailed) 1687 &elems) == ParseFailed)
1642 return; 1688 return;
1643 1689
1644 use_protection = 0; 1690 if (elems.erp_info && elems.erp_info_len >= 1)
1645 if (elems.erp_info && elems.erp_info_len >= 1) { 1691 ieee80211_handle_erp_ie(dev, elems.erp_info[0]);
1646 use_protection =
1647 (elems.erp_info[0] & ERP_INFO_USE_PROTECTION) != 0;
1648 }
1649
1650 if (use_protection != !!ifsta->use_protection) {
1651 if (net_ratelimit()) {
1652 printk(KERN_DEBUG "%s: CTS protection %s (BSSID="
1653 MAC_FMT ")\n",
1654 dev->name,
1655 use_protection ? "enabled" : "disabled",
1656 MAC_ARG(ifsta->bssid));
1657 }
1658 ifsta->use_protection = use_protection ? 1 : 0;
1659 local->cts_protect_erp_frames = use_protection;
1660 }
1661 1692
1662 if (elems.wmm_param && ifsta->wmm_enabled) { 1693 if (elems.wmm_param && ifsta->wmm_enabled) {
1663 ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, 1694 ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,