mac80211: support reporting A-MSDU subframes individually
Some devices may not be able to report A-MSDUs in single buffers. Drivers for such devices were forced to re-assemble A-MSDUs which would then be eventually disassembled by mac80211. This could lead to CPU cache thrashing and poor performance. Since A-MSDU has a single sequence number all subframes share it. This was in conflict with retransmission/duplication recovery (IEEE802.11-2012: 9.3.2.10). Patch introduces a new flag that is meant to be set for all individually reported A-MSDU subframes except the last one. This ensures the last_seq_ctrl is updated after the last subframe is processed. If an A-MSDU is actually a duplicate transmission all reported subframes will be properly discarded. Signed-off-by: Michal Kazior <michal.kazior@tieto.com> [johannes: add braces that were missing even before] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
15e230abaa
commit
0cfcefef19
|
@ -829,6 +829,15 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
|
|||
* @RX_FLAG_STBC_MASK: STBC 2 bit bitmask. 1 - Nss=1, 2 - Nss=2, 3 - Nss=3
|
||||
* @RX_FLAG_10MHZ: 10 MHz (half channel) was used
|
||||
* @RX_FLAG_5MHZ: 5 MHz (quarter channel) was used
|
||||
* @RX_FLAG_AMSDU_MORE: Some drivers may prefer to report separate A-MSDU
|
||||
* subframes instead of a one huge frame for performance reasons.
|
||||
* All, but the last MSDU from an A-MSDU should have this flag set. E.g.
|
||||
* if an A-MSDU has 3 frames, the first 2 must have the flag set, while
|
||||
* the 3rd (last) one must not have this flag set. The flag is used to
|
||||
* deal with retransmission/duplication recovery properly since A-MSDU
|
||||
* subframes share the same sequence number. Reported subframes can be
|
||||
* either regular MSDU or singly A-MSDUs. Subframes must not be
|
||||
* interleaved with other frames.
|
||||
*/
|
||||
enum mac80211_rx_flags {
|
||||
RX_FLAG_MMIC_ERROR = BIT(0),
|
||||
|
@ -859,6 +868,7 @@ enum mac80211_rx_flags {
|
|||
RX_FLAG_STBC_MASK = BIT(26) | BIT(27),
|
||||
RX_FLAG_10MHZ = BIT(28),
|
||||
RX_FLAG_5MHZ = BIT(29),
|
||||
RX_FLAG_AMSDU_MORE = BIT(30),
|
||||
};
|
||||
|
||||
#define RX_FLAG_STBC_SHIFT 26
|
||||
|
|
|
@ -995,8 +995,9 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
|
|||
rx->sta->num_duplicates++;
|
||||
}
|
||||
return RX_DROP_UNUSABLE;
|
||||
} else
|
||||
} else if (!(status->flag & RX_FLAG_AMSDU_MORE)) {
|
||||
rx->sta->last_seq_ctrl[rx->seqno_idx] = hdr->seq_ctrl;
|
||||
}
|
||||
}
|
||||
|
||||
if (unlikely(rx->skb->len < 16)) {
|
||||
|
|
Loading…
Reference in New Issue