From 5558235c6bade6662e6f257a35f2dfdc8a742147 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 10 Jul 2007 19:32:09 +0200 Subject: [PATCH] mac80211: conserve stack space due to padding This patch reorders some fields in struct ieee802_11_elems to save 17*7 or 17*3 bytes (on 64/32-bit machines respectively) stack space in a few functions. Signed-off-by: Johannes Berg Signed-off-by: Jiri Benc Signed-off-by: John W. Linville --- net/mac80211/ieee80211_sta.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) (limited to 'net/mac80211/ieee80211_sta.c') diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index 91b545c144c..f3ca83743b4 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c @@ -76,33 +76,36 @@ static int ieee80211_sta_config_auth(struct net_device *dev, /* Parsed Information Elements */ struct ieee802_11_elems { + /* pointers to IEs */ u8 *ssid; - u8 ssid_len; u8 *supp_rates; - u8 supp_rates_len; u8 *fh_params; - u8 fh_params_len; u8 *ds_params; - u8 ds_params_len; u8 *cf_params; - u8 cf_params_len; u8 *tim; - u8 tim_len; u8 *ibss_params; - u8 ibss_params_len; u8 *challenge; - u8 challenge_len; u8 *wpa; - u8 wpa_len; u8 *rsn; - u8 rsn_len; u8 *erp_info; - u8 erp_info_len; u8 *ext_supp_rates; - u8 ext_supp_rates_len; u8 *wmm_info; - u8 wmm_info_len; u8 *wmm_param; + + /* length of them, respectively */ + u8 ssid_len; + u8 supp_rates_len; + u8 fh_params_len; + u8 ds_params_len; + u8 cf_params_len; + u8 tim_len; + u8 ibss_params_len; + u8 challenge_len; + u8 wpa_len; + u8 rsn_len; + u8 erp_info_len; + u8 ext_supp_rates_len; + u8 wmm_info_len; u8 wmm_param_len; }; -- cgit v1.2.3-70-g09d2 From 5628221caf88e2a052782b042e12da7cd34111b0 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Tue, 10 Jul 2007 19:32:10 +0200 Subject: [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 Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 11 +++++++ net/mac80211/ieee80211_i.h | 6 ++++ net/mac80211/ieee80211_sta.c | 69 ++++++++++++++++++++++++++++++++------------ 3 files changed, 67 insertions(+), 19 deletions(-) (limited to 'net/mac80211/ieee80211_sta.c') diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index ecd61e8438a..272f8c8c90d 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -227,6 +227,17 @@ struct ieee80211_cts { #define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10) #define WLAN_CAPABILITY_DSSS_OFDM (1<<13) +/* 802.11g ERP information element */ +#define WLAN_ERP_NON_ERP_PRESENT (1<<0) +#define WLAN_ERP_USE_PROTECTION (1<<1) +#define WLAN_ERP_BARKER_PREAMBLE (1<<2) + +/* WLAN_ERP_BARKER_PREAMBLE values */ +enum { + WLAN_ERP_PREAMBLE_SHORT = 0, + WLAN_ERP_PREAMBLE_LONG = 1, +}; + /* Status codes */ enum ieee80211_statuscode { WLAN_STATUS_SUCCESS = 0, diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index b222a9afd4e..99ff7c5e920 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -99,6 +99,12 @@ struct ieee80211_sta_bss { int probe_resp; unsigned long last_update; + /* during assocation, we save an ERP value from a probe response so + * that we can feed ERP info to the driver when handling the + * association completes. these fields probably won't be up-to-date + * otherwise, you probably don't want to use them. */ + int has_erp_value; + u8 erp_value; }; diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index f3ca83743b4..df6c410de16 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, } +static void ieee80211_handle_erp_ie(struct net_device *dev, u8 erp_value) +{ + struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_if_sta *ifsta = &sdata->u.sta; + int use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0; + + if (use_protection != !!ifsta->use_protection) { + if (net_ratelimit()) { + printk(KERN_DEBUG "%s: CTS protection %s (BSSID=" + MAC_FMT ")\n", + dev->name, + use_protection ? "enabled" : "disabled", + MAC_ARG(ifsta->bssid)); + } + ifsta->use_protection = use_protection ? 1 : 0; + local->cts_protect_erp_frames = use_protection; + } +} + + static void ieee80211_sta_send_associnfo(struct net_device *dev, struct ieee80211_if_sta *ifsta) { @@ -377,9 +398,18 @@ static void ieee80211_set_associated(struct net_device *dev, if (assoc) { struct ieee80211_sub_if_data *sdata; + struct ieee80211_sta_bss *bss; sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->type != IEEE80211_IF_TYPE_STA) return; + + bss = ieee80211_rx_bss_get(dev, ifsta->bssid); + if (bss) { + if (bss->has_erp_value) + ieee80211_handle_erp_ie(dev, bss->erp_value); + ieee80211_rx_bss_put(dev, bss); + } + netif_carrier_on(dev); ifsta->prev_bssid_set = 1; 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, return; } + /* it probably doesn't, but if the frame includes an ERP value then + * update our stored copy */ + if (elems.erp_info && elems.erp_info_len >= 1) { + struct ieee80211_sta_bss *bss + = ieee80211_rx_bss_get(dev, ifsta->bssid); + if (bss) { + bss->erp_value = elems.erp_info[0]; + bss->has_erp_value = 1; + ieee80211_rx_bss_put(dev, bss); + } + } + printk(KERN_DEBUG "%s: associated\n", dev->name); ifsta->aid = aid; ifsta->ap_capab = capab_info; @@ -1499,6 +1541,12 @@ static void ieee80211_rx_bss_info(struct net_device *dev, return; } + /* save the ERP value so that it is available at association time */ + if (elems.erp_info && elems.erp_info_len >= 1) { + bss->erp_value = elems.erp_info[0]; + bss->has_erp_value = 1; + } + bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) { @@ -1614,10 +1662,8 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, size_t len, struct ieee80211_rx_status *rx_status) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sub_if_data *sdata; struct ieee80211_if_sta *ifsta; - int use_protection; size_t baselen; struct ieee802_11_elems elems; @@ -1641,23 +1687,8 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, &elems) == ParseFailed) return; - use_protection = 0; - if (elems.erp_info && elems.erp_info_len >= 1) { - use_protection = - (elems.erp_info[0] & ERP_INFO_USE_PROTECTION) != 0; - } - - if (use_protection != !!ifsta->use_protection) { - if (net_ratelimit()) { - printk(KERN_DEBUG "%s: CTS protection %s (BSSID=" - MAC_FMT ")\n", - dev->name, - use_protection ? "enabled" : "disabled", - MAC_ARG(ifsta->bssid)); - } - ifsta->use_protection = use_protection ? 1 : 0; - local->cts_protect_erp_frames = use_protection; - } + if (elems.erp_info && elems.erp_info_len >= 1) + ieee80211_handle_erp_ie(dev, elems.erp_info[0]); if (elems.wmm_param && ifsta->wmm_enabled) { ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, -- cgit v1.2.3-70-g09d2 From 63fc33ceb0ccc08b3f62d7bfe56a33eb33ca9427 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Tue, 10 Jul 2007 19:32:11 +0200 Subject: [PATCH] mac80211: improved 802.11g CTS protection Currently, CTS protection is partially implemented twice: 1. via prism2 ioctls, only used by hostapd 2. via STA beacon parsing, recorded in sta.use_protection but never used (other than printed in debugfs) Protection control should be implemented on a per-subif basis. For example, a single physical device may be running a soft AP on one channel, and a STA on another. The AP interface should use protection based on what hostapd told it, and the STA interface should use protection based on beacon parsing. These should operate independantly: one subif using protection should not influence the other. To implement this, I moved the use_protection flag into ieee80211_sub_if_data and removed the device-global cts_protect_erp_frames flag. I also made the PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES write operation only available for AP interfaces, to avoid any possibility of the user messing with the behaviour of a STA. Signed-off-by: Daniel Drake Signed-off-by: Jiri Benc Signed-off-by: John W. Linville --- net/mac80211/debugfs_netdev.c | 2 +- net/mac80211/ieee80211.c | 5 ++--- net/mac80211/ieee80211_i.h | 3 +-- net/mac80211/ieee80211_ioctl.c | 7 +++++-- net/mac80211/ieee80211_sta.c | 8 ++++---- 5 files changed, 13 insertions(+), 12 deletions(-) (limited to 'net/mac80211/ieee80211_sta.c') diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 9e3964638ba..a3e01d76d50 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -118,7 +118,7 @@ static ssize_t ieee80211_if_fmt_flags( sdata->u.sta.authenticated ? "AUTH\n" : "", sdata->u.sta.associated ? "ASSOC\n" : "", sdata->u.sta.probereq_poll ? "PROBEREQ POLL\n" : "", - sdata->u.sta.use_protection ? "CTS prot\n" : ""); + sdata->use_protection ? "CTS prot\n" : ""); } __IEEE80211_IF_FILE(flags); diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index fe32a2d1605..2ddf4ef4065 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c @@ -442,7 +442,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_txrx_data *tx) if (!tx->u.tx.rate) return TXRX_DROP; if (tx->u.tx.mode->mode == MODE_IEEE80211G && - tx->local->cts_protect_erp_frames && tx->fragmented && + tx->sdata->use_protection && tx->fragmented && extra.nonerp) { tx->u.tx.last_frag_rate = tx->u.tx.rate; tx->u.tx.probe_last_frag = extra.probe ? 1 : 0; @@ -868,8 +868,7 @@ ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx) * for the frame. */ if (mode->mode == MODE_IEEE80211G && (tx->u.tx.rate->flags & IEEE80211_RATE_ERP) && - tx->u.tx.unicast && - tx->local->cts_protect_erp_frames && + tx->u.tx.unicast && tx->sdata->use_protection && !(control->flags & IEEE80211_TXCTL_USE_RTS_CTS)) control->flags |= IEEE80211_TXCTL_USE_CTS_PROTECT; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 99ff7c5e920..055a2a91218 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -241,7 +241,6 @@ struct ieee80211_if_sta { unsigned int authenticated:1; unsigned int associated:1; unsigned int probereq_poll:1; - unsigned int use_protection:1; unsigned int create_ibss:1; unsigned int mixed_cell:1; unsigned int wmm_enabled:1; @@ -284,6 +283,7 @@ struct ieee80211_sub_if_data { int mc_count; unsigned int allmulti:1; unsigned int promisc:1; + unsigned int use_protection:1; /* CTS protect ERP frames */ struct net_device_stats stats; int drop_unencrypted; @@ -444,7 +444,6 @@ struct ieee80211_local { int *basic_rates[NUM_IEEE80211_MODES]; int rts_threshold; - int cts_protect_erp_frames; int fragmentation_threshold; int short_retry_limit; /* dot11ShortRetryLimit */ int long_retry_limit; /* dot11LongRetryLimit */ diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c index 9bc209b72d4..5918dd079e1 100644 --- a/net/mac80211/ieee80211_ioctl.c +++ b/net/mac80211/ieee80211_ioctl.c @@ -1180,7 +1180,10 @@ static int ieee80211_ioctl_prism2_param(struct net_device *dev, break; case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES: - local->cts_protect_erp_frames = value; + if (sdata->type != IEEE80211_IF_TYPE_AP) + ret = -ENOENT; + else + sdata->use_protection = value; break; case PRISM2_PARAM_PREAMBLE: @@ -1303,7 +1306,7 @@ static int ieee80211_ioctl_get_prism2_param(struct net_device *dev, break; case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES: - *param = local->cts_protect_erp_frames; + *param = sdata->use_protection; break; case PRISM2_PARAM_PREAMBLE: diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index df6c410de16..ba2bf8f0a34 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c @@ -316,12 +316,11 @@ static void ieee80211_sta_wmm_params(struct net_device *dev, static void ieee80211_handle_erp_ie(struct net_device *dev, u8 erp_value) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta = &sdata->u.sta; int use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0; - if (use_protection != !!ifsta->use_protection) { + if (use_protection != sdata->use_protection) { if (net_ratelimit()) { printk(KERN_DEBUG "%s: CTS protection %s (BSSID=" MAC_FMT ")\n", @@ -329,8 +328,7 @@ static void ieee80211_handle_erp_ie(struct net_device *dev, u8 erp_value) use_protection ? "enabled" : "disabled", MAC_ARG(ifsta->bssid)); } - ifsta->use_protection = use_protection ? 1 : 0; - local->cts_protect_erp_frames = use_protection; + sdata->use_protection = use_protection; } } @@ -390,6 +388,7 @@ static void ieee80211_set_associated(struct net_device *dev, struct ieee80211_if_sta *ifsta, int assoc) { union iwreq_data wrqu; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (ifsta->associated == assoc) return; @@ -417,6 +416,7 @@ static void ieee80211_set_associated(struct net_device *dev, ieee80211_sta_send_associnfo(dev, ifsta); } else { netif_carrier_off(dev); + sdata->use_protection = 0; memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); } wrqu.ap_addr.sa_family = ARPHRD_ETHER; -- cgit v1.2.3-70-g09d2