aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <jkmaline@cc.hut.fi>2005-08-14 22:08:39 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-08-14 23:06:26 -0400
commit5bee720fd7fa5ed4eade96058acd3a684da30932 (patch)
tree916d3c4c880c64ba13edc4f890fa3b021be4ded8
parent1e4adbdb3f0348dcf4fce92f1acc7c8386982c17 (diff)
[PATCH] hostap: Fix skb->cb use for TX meta data
Old AP mode code for power saving was using skb->cb for couple of flags before the more generic 802.11 TX code started using the same buffer for struct hostap_skb_tx_data. This resulted in the power save code corrupting the magic value in beginning of the buffer and TX code dropping the power saved packets because of this for the case where STAs send PS-Poll frames with PwrMgmt flag set. This patch modifies the power save code to use the same struct hostap_skb_tx_data as rest of the TX path in order to avoid corrupting the data in skb->cb. In addition, this patch reorders fields in the structure and makes them use smaller types in order to make the structure fit in skb->cb on 64-bit hosts. Signed-off-by: Jouni Malinen <jkmaline@cc.hut.fi> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_tx.c6
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.c30
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.h9
-rw-r--r--drivers/net/wireless/hostap/hostap_wlan.h17
4 files changed, 30 insertions, 32 deletions
diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c
index 8f39871d6908..cfb3ecc783fa 100644
--- a/drivers/net/wireless/hostap/hostap_80211_tx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_tx.c
@@ -226,7 +226,8 @@ int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev)
226 meta = (struct hostap_skb_tx_data *) skb->cb; 226 meta = (struct hostap_skb_tx_data *) skb->cb;
227 memset(meta, 0, sizeof(*meta)); 227 memset(meta, 0, sizeof(*meta));
228 meta->magic = HOSTAP_SKB_TX_DATA_MAGIC; 228 meta->magic = HOSTAP_SKB_TX_DATA_MAGIC;
229 meta->wds = use_wds; 229 if (use_wds)
230 meta->flags |= HOSTAP_TX_FLAGS_WDS;
230 meta->ethertype = ethertype; 231 meta->ethertype = ethertype;
231 meta->iface = iface; 232 meta->iface = iface;
232 233
@@ -410,7 +411,8 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
410 case AP_TX_CONTINUE_NOT_AUTHORIZED: 411 case AP_TX_CONTINUE_NOT_AUTHORIZED:
411 if (local->ieee_802_1x && 412 if (local->ieee_802_1x &&
412 HOSTAP_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA && 413 HOSTAP_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA &&
413 meta->ethertype != ETH_P_PAE && !meta->wds) { 414 meta->ethertype != ETH_P_PAE &&
415 !(meta->flags & HOSTAP_TX_FLAGS_WDS)) {
414 printk(KERN_DEBUG "%s: dropped frame to unauthorized " 416 printk(KERN_DEBUG "%s: dropped frame to unauthorized "
415 "port (IEEE 802.1X): ethertype=0x%04x\n", 417 "port (IEEE 802.1X): ethertype=0x%04x\n",
416 dev->name, meta->ethertype); 418 dev->name, meta->ethertype);
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index c9aeefcd7612..550855a91509 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -1840,6 +1840,8 @@ static void ap_handle_dropped_data(local_info_t *local,
1840static void pspoll_send_buffered(local_info_t *local, struct sta_info *sta, 1840static void pspoll_send_buffered(local_info_t *local, struct sta_info *sta,
1841 struct sk_buff *skb) 1841 struct sk_buff *skb)
1842{ 1842{
1843 struct hostap_skb_tx_data *meta;
1844
1843 if (!(sta->flags & WLAN_STA_PS)) { 1845 if (!(sta->flags & WLAN_STA_PS)) {
1844 /* Station has moved to non-PS mode, so send all buffered 1846 /* Station has moved to non-PS mode, so send all buffered
1845 * frames using normal device queue. */ 1847 * frames using normal device queue. */
@@ -1849,11 +1851,11 @@ static void pspoll_send_buffered(local_info_t *local, struct sta_info *sta,
1849 1851
1850 /* add a flag for hostap_handle_sta_tx() to know that this skb should 1852 /* add a flag for hostap_handle_sta_tx() to know that this skb should
1851 * be passed through even though STA is using PS */ 1853 * be passed through even though STA is using PS */
1852 memcpy(skb->cb, AP_SKB_CB_MAGIC, AP_SKB_CB_MAGIC_LEN); 1854 meta = (struct hostap_skb_tx_data *) skb->cb;
1853 skb->cb[AP_SKB_CB_MAGIC_LEN] = AP_SKB_CB_BUFFERED_FRAME; 1855 meta->flags |= HOSTAP_TX_FLAGS_BUFFERED_FRAME;
1854 if (!skb_queue_empty(&sta->tx_buf)) { 1856 if (!skb_queue_empty(&sta->tx_buf)) {
1855 /* indicate to STA that more frames follow */ 1857 /* indicate to STA that more frames follow */
1856 skb->cb[AP_SKB_CB_MAGIC_LEN] |= AP_SKB_CB_ADD_MOREDATA; 1858 meta->flags |= HOSTAP_TX_FLAGS_ADD_MOREDATA;
1857 } 1859 }
1858 dev_queue_xmit(skb); 1860 dev_queue_xmit(skb);
1859} 1861}
@@ -2707,7 +2709,8 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx)
2707 atomic_inc(&sta->users); 2709 atomic_inc(&sta->users);
2708 spin_unlock(&local->ap->sta_table_lock); 2710 spin_unlock(&local->ap->sta_table_lock);
2709 2711
2710 if (local->iw_mode == IW_MODE_MASTER && sta == NULL && !meta->wds && 2712 if (local->iw_mode == IW_MODE_MASTER && sta == NULL &&
2713 !(meta->flags & HOSTAP_TX_FLAGS_WDS) &&
2711 meta->iface->type != HOSTAP_INTERFACE_MASTER && 2714 meta->iface->type != HOSTAP_INTERFACE_MASTER &&
2712 meta->iface->type != HOSTAP_INTERFACE_AP) { 2715 meta->iface->type != HOSTAP_INTERFACE_AP) {
2713#if 0 2716#if 0
@@ -2743,18 +2746,15 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx)
2743 if (!(sta->flags & WLAN_STA_PS)) 2746 if (!(sta->flags & WLAN_STA_PS))
2744 goto out; 2747 goto out;
2745 2748
2746 if (memcmp(skb->cb, AP_SKB_CB_MAGIC, AP_SKB_CB_MAGIC_LEN) == 0) { 2749 if (meta->flags & HOSTAP_TX_FLAGS_ADD_MOREDATA) {
2747 if (skb->cb[AP_SKB_CB_MAGIC_LEN] & AP_SKB_CB_ADD_MOREDATA) { 2750 /* indicate to STA that more frames follow */
2748 /* indicate to STA that more frames follow */ 2751 hdr->frame_control |= __constant_cpu_to_le16(WLAN_FC_MOREDATA);
2749 hdr->frame_control |= 2752 }
2750 __constant_cpu_to_le16(WLAN_FC_MOREDATA);
2751 }
2752 2753
2753 if (skb->cb[AP_SKB_CB_MAGIC_LEN] & AP_SKB_CB_BUFFERED_FRAME) { 2754 if (meta->flags & HOSTAP_TX_FLAGS_BUFFERED_FRAME) {
2754 /* packet was already buffered and now send due to 2755 /* packet was already buffered and now send due to
2755 * PS poll, so do not rebuffer it */ 2756 * PS poll, so do not rebuffer it */
2756 goto out; 2757 goto out;
2757 }
2758 } 2758 }
2759 2759
2760 if (skb_queue_len(&sta->tx_buf) >= STA_MAX_TX_BUFFER) { 2760 if (skb_queue_len(&sta->tx_buf) >= STA_MAX_TX_BUFFER) {
diff --git a/drivers/net/wireless/hostap/hostap_ap.h b/drivers/net/wireless/hostap/hostap_ap.h
index 137f78e4532b..512abc2c83a3 100644
--- a/drivers/net/wireless/hostap/hostap_ap.h
+++ b/drivers/net/wireless/hostap/hostap_ap.h
@@ -6,15 +6,6 @@
6/* maximum number of frames to buffer per STA */ 6/* maximum number of frames to buffer per STA */
7#define STA_MAX_TX_BUFFER 32 7#define STA_MAX_TX_BUFFER 32
8 8
9/* Flags used in skb->cb[6] to control how the packet is handled in TX path.
10 * skb->cb[0..5] must contain magic value 'hostap' to indicate that cb[6] is
11 * used. */
12#define AP_SKB_CB_MAGIC "hostap"
13#define AP_SKB_CB_MAGIC_LEN 6
14#define AP_SKB_CB_BUFFERED_FRAME BIT(0)
15#define AP_SKB_CB_ADD_MOREDATA BIT(1)
16
17
18/* STA flags */ 9/* STA flags */
19#define WLAN_STA_AUTH BIT(0) 10#define WLAN_STA_AUTH BIT(0)
20#define WLAN_STA_ASSOC BIT(1) 11#define WLAN_STA_ASSOC BIT(1)
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h
index a632d45f334d..6f5bea8a5c23 100644
--- a/drivers/net/wireless/hostap/hostap_wlan.h
+++ b/drivers/net/wireless/hostap/hostap_wlan.h
@@ -941,16 +941,21 @@ struct hostap_interface {
941 941
942#define HOSTAP_SKB_TX_DATA_MAGIC 0xf08a36a2 942#define HOSTAP_SKB_TX_DATA_MAGIC 0xf08a36a2
943 943
944/* TX meta data - stored in skb->cb buffer, so this must be not increase over 944/*
945 * 48-byte limit */ 945 * TX meta data - stored in skb->cb buffer, so this must not be increased over
946 * the 40-byte limit
947 */
946struct hostap_skb_tx_data { 948struct hostap_skb_tx_data {
947 unsigned int magic; /* HOSTAP_SKB_TX_DATA_MAGIC */ 949 u32 magic; /* HOSTAP_SKB_TX_DATA_MAGIC */
948 int rate; /* transmit rate */ 950 u8 rate; /* transmit rate */
951#define HOSTAP_TX_FLAGS_WDS BIT(0)
952#define HOSTAP_TX_FLAGS_BUFFERED_FRAME BIT(1)
953#define HOSTAP_TX_FLAGS_ADD_MOREDATA BIT(2)
954 u8 flags; /* HOSTAP_TX_FLAGS_* */
955 u16 tx_cb_idx;
949 struct hostap_interface *iface; 956 struct hostap_interface *iface;
950 unsigned long jiffies; /* queueing timestamp */ 957 unsigned long jiffies; /* queueing timestamp */
951 int wds;
952 unsigned short ethertype; 958 unsigned short ethertype;
953 int tx_cb_idx;
954}; 959};
955 960
956 961