aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/mac80211.h4
-rw-r--r--net/mac80211/status.c32
-rw-r--r--net/mac80211/tx.c7
3 files changed, 15 insertions, 28 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index c90047d..f03f97b 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -271,6 +271,9 @@ struct ieee80211_bss_conf {
* transmit function after the current frame, this can be used
* by drivers to kick the DMA queue only if unset or when the
* queue gets full.
+ * @IEEE80211_TX_INTFL_RETRANSMISSION: This frame is being retransmitted
+ * after TX status because the destination was asleep, it must not
+ * be modified again (no seqno assignment, crypto, etc.)
*/
enum mac80211_tx_control_flags {
IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0),
@@ -291,6 +294,7 @@ enum mac80211_tx_control_flags {
IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(16),
IEEE80211_TX_CTL_PSPOLL_RESPONSE = BIT(17),
IEEE80211_TX_CTL_MORE_FRAMES = BIT(18),
+ IEEE80211_TX_INTFL_RETRANSMISSION = BIT(19),
};
/**
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 9e171b1..800b677 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -45,37 +45,16 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
/*
- * XXX: This is temporary!
- *
- * The problem here is that when we get here, the driver will
- * quite likely have pretty much overwritten info->control by
- * using info->driver_data or info->rate_driver_data. Thus,
- * when passing out the frame to the driver again, we would be
- * passing completely bogus data since the driver would then
- * expect a properly filled info->control. In mac80211 itself
- * the same problem occurs, since we need info->control.vif
- * internally.
- *
- * To fix this, we should send the frame through TX processing
- * again. However, it's not that simple, since the frame will
- * have been software-encrypted (if applicable) already, and
- * encrypting it again doesn't do much good. So to properly do
- * that, we not only have to skip the actual 'raw' encryption
- * (key selection etc. still has to be done!) but also the
- * sequence number assignment since that impacts the crypto
- * encapsulation, of course.
- *
- * Hence, for now, fix the bug by just dropping the frame.
- */
- goto drop;
-
- /*
* This skb 'survived' a round-trip through the driver, and
* hopefully the driver didn't mangle it too badly. However,
* we can definitely not rely on the the control information
- * being correct. Clear it so we don't get junk there.
+ * being correct. Clear it so we don't get junk there, and
+ * indicate that it needs new processing, but must not be
+ * modified/encrypted again.
*/
memset(&info->control, 0, sizeof(info->control));
+ info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING |
+ IEEE80211_TX_INTFL_RETRANSMISSION;
sta->tx_filtered_count++;
@@ -130,7 +109,6 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
return;
}
- drop:
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
if (net_ratelimit())
printk(KERN_DEBUG "%s: dropped TX filtered frame, "
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index e3d8ff5..da557b0 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1285,6 +1285,7 @@ static int __ieee80211_tx(struct ieee80211_local *local,
static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
{
struct sk_buff *skb = tx->skb;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
ieee80211_tx_result res = TX_DROP;
#define CALL_TXH(txh) \
@@ -1299,9 +1300,13 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
CALL_TXH(ieee80211_tx_h_ps_buf);
CALL_TXH(ieee80211_tx_h_select_key);
CALL_TXH(ieee80211_tx_h_sta);
- CALL_TXH(ieee80211_tx_h_michael_mic_add);
if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL))
CALL_TXH(ieee80211_tx_h_rate_ctrl);
+
+ if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION))
+ goto txh_done;
+
+ CALL_TXH(ieee80211_tx_h_michael_mic_add);
CALL_TXH(ieee80211_tx_h_sequence);
CALL_TXH(ieee80211_tx_h_fragment);
/* handlers after fragment must be aware of tx info fragmentation! */