iwx: tag RX frames as A_MPDU RX; tag A-MSDU frames appropriately

* tag packets for 11n/11ac associated nodes with A_MPDU so they
  get passed into the reordering logic

* tag A-MSDU frames with AMSDU and AMSDU_MORE so they don't get
  dropped due to duplicate sequence numbers.

Note: I haven't yet elicited A-MSDU in A-MPDU to fully test this,
but I do see the net80211 reordering logic kick in (which you can
see via wlanstats -i wlan0 -o ampdu 1).

I've checked with Johannes Berg at Intel (who maintains the linux
iwlwifi stuff); he replied saying none of the firmware versions are
doing AMPDU reorder offloading.

Differential Revision:	https://reviews.freebsd.org/D53781

Locally tested:

 * AX210, STA mode, > 200mbit bidirectional traffic testing on
   5GHz VHT/40.
This commit is contained in:
Adrian Chadd
2025-11-15 20:26:22 -08:00
parent 2ead091715
commit 4d29178e71
+32 -30
View File
@@ -4607,37 +4607,39 @@ iwx_rx_mpdu_mq(struct iwx_softc *sc, struct mbuf *m, void *pktdata,
pad = 1;
}
// /*
// * Hardware de-aggregates A-MSDUs and copies the same MAC header
// * in place for each subframe. But it leaves the 'A-MSDU present'
// * bit set in the frame header. We need to clear this bit ourselves.
// * (XXX This workaround is not required on AX200/AX201 devices that
// * have been tested by me, but it's unclear when this problem was
// * fixed in the hardware. It definitely affects the 9k generation.
// * Leaving this in place for now since some 9k/AX200 hybrids seem
// * to exist that we may eventually add support for.)
// *
// * And we must allow the same CCMP PN for subframes following the
// * first subframe. Otherwise they would be discarded as replays.
// */
/* If it's a HT node then perform re-order processing */
if (ni->ni_flags & IEEE80211_NODE_HT)
m->m_flags |= M_AMPDU;
/*
* Hardware de-aggregates A-MSDUs and copies the same MAC header
* in place for each subframe. But it leaves the 'A-MSDU present'
* bit set in the frame header. We need to clear this bit ourselves.
* (XXX This workaround is not required on AX200/AX201 devices that
* have been tested by me, but it's unclear when this problem was
* fixed in the hardware. It definitely affects the 9k generation.
* Leaving this in place for now since some 9k/AX200 hybrids seem
* to exist that we may eventually add support for.)
*
* And we must allow the same CCMP PN for subframes following the
* first subframe. Otherwise they would be discarded as replays.
*/
if (desc->mac_flags2 & IWX_RX_MPDU_MFLG2_AMSDU) {
DPRINTF(("%s: === IWX_RX_MPDU_MFLG2_AMSDU\n", __func__));
// struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
// uint8_t subframe_idx = (desc->amsdu_info &
// IWX_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK);
// if (subframe_idx > 0)
// rxi.rxi_flags |= IEEE80211_RXI_HWDEC_SAME_PN;
// if (ieee80211_has_qos(wh) && ieee80211_has_addr4(wh) &&
// m->m_len >= sizeof(struct ieee80211_qosframe_addr4)) {
// struct ieee80211_qosframe_addr4 *qwh4 = mtod(m,
// struct ieee80211_qosframe_addr4 *);
// qwh4->i_qos[0] &= htole16(~IEEE80211_QOS_AMSDU);
// } else if (ieee80211_has_qos(wh) &&
// m->m_len >= sizeof(struct ieee80211_qosframe)) {
// struct ieee80211_qosframe *qwh = mtod(m,
// struct ieee80211_qosframe *);
// qwh->i_qos[0] &= htole16(~IEEE80211_QOS_AMSDU);
// }
struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
uint8_t subframe_idx = (desc->amsdu_info &
IWX_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK);
uint8_t *qos;
rxs.c_pktflags |= IEEE80211_RX_F_AMSDU;
if (subframe_idx > 0)
rxs.c_pktflags |= IEEE80211_RX_F_AMSDU_MORE;
/* XXX should keep driver statistics about this */
IWX_DPRINTF(sc, IWX_DEBUG_AMPDU_MGMT,
"%s: === IWX_RX_MPDU_MFLG2_AMSDU\n", __func__);
qos = ieee80211_getqos(wh);
qos[0] &= ~IEEE80211_QOS_AMSDU;
}
/*