Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0cfcefef authored by Michal Kazior's avatar Michal Kazior Committed by Johannes Berg
Browse files

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: default avatarMichal Kazior <michal.kazior@tieto.com>
[johannes: add braces that were missing even before]
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 15e230ab
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -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
+2 −1
Original line number Diff line number Diff line
@@ -995,9 +995,10 @@ 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)) {
		I802_DEBUG_INC(rx->local->rx_handlers_drop_short);