diff options
author | Jouni Malinen <jkmaline@cc.hut.fi> | 2005-08-14 22:08:39 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-08-14 23:06:26 -0400 |
commit | 5bee720fd7fa5ed4eade96058acd3a684da30932 (patch) | |
tree | 916d3c4c880c64ba13edc4f890fa3b021be4ded8 /drivers | |
parent | 1e4adbdb3f0348dcf4fce92f1acc7c8386982c17 (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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/hostap/hostap_80211_tx.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/hostap/hostap_ap.c | 30 | ||||
-rw-r--r-- | drivers/net/wireless/hostap/hostap_ap.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/hostap/hostap_wlan.h | 17 |
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, | |||
1840 | static void pspoll_send_buffered(local_info_t *local, struct sta_info *sta, | 1840 | static 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 | */ | ||
946 | struct hostap_skb_tx_data { | 948 | struct 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 | ||