[net80211] begin handling multiple hardware decap'ed A-MSDU in the RX path.
The duplicate detection code currently expects A-MSDU frames to be encaped - they're decap'ed /after/ duplicate detection. However for ath10k (and iwm hardware later on) the firmware supports doing A-MSDU decap in hardware - which shows up as multiple frames with the same sequence number and IV. This is the first part of decap handling - if we see a stretch of A-MSDU frames from the driver with the MORE bit set, then don't treat them as duplicates. This isn't 100% complete as crypto sequence number handling and "A-MSDU in A-MPDU" needs handling, but it's a start. This should be a glorified no-op for everyone. Please tell me if it isn't.
This commit is contained in:
parent
3b5aa97c10
commit
48f95a360e
@ -131,6 +131,38 @@ ishtinfooui(const uint8_t *frm)
|
|||||||
return frm[1] > 3 && le32dec(frm+2) == ((BCM_OUI_HTINFO<<24)|BCM_OUI);
|
return frm[1] > 3 && le32dec(frm+2) == ((BCM_OUI_HTINFO<<24)|BCM_OUI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static __inline int
|
||||||
|
ieee80211_check_rxseq_amsdu(const struct ieee80211_rx_stats *rxs)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (!! (rxs->c_pktflags & IEEE80211_RX_F_AMSDU));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return 1 if the rxseq check should increment the sequence
|
||||||
|
* number. Return 0 if it's part of an AMSDU batch and it isn't
|
||||||
|
* the final frame in the decap'ed burst.
|
||||||
|
*/
|
||||||
|
static __inline int
|
||||||
|
ieee80211_check_rxseq_amsdu_more(const struct ieee80211_rx_stats *rxs)
|
||||||
|
{
|
||||||
|
/* No state? ok */
|
||||||
|
if (rxs == NULL)
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
/* State but no AMSDU set? ok */
|
||||||
|
if ((rxs->c_pktflags & IEEE80211_RX_F_AMSDU) == 0)
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
/* State, AMSDU set, then _MORE means "don't inc yet" */
|
||||||
|
if (rxs->c_pktflags & IEEE80211_RX_F_AMSDU_MORE) {
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Both are set, so return ok */
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check the current frame sequence number against the current TID
|
* Check the current frame sequence number against the current TID
|
||||||
* state and return whether it's in sequence or should be dropped.
|
* state and return whether it's in sequence or should be dropped.
|
||||||
@ -238,7 +270,20 @@ ieee80211_check_rxseq(struct ieee80211_node *ni, struct ieee80211_frame *wh,
|
|||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
ok:
|
ok:
|
||||||
|
/*
|
||||||
|
* Only bump the sequence number if it's the last frame
|
||||||
|
* in a batch. That way frames in the rest of the batch
|
||||||
|
* get included, and the last frame in the batch kicks
|
||||||
|
* it next.
|
||||||
|
*/
|
||||||
|
if (ieee80211_check_rxseq_amsdu_more(rxs)) {
|
||||||
ni->ni_rxseqs[tid] = rxseq;
|
ni->ni_rxseqs[tid] = rxseq;
|
||||||
|
if (ieee80211_check_rxseq_amsdu(rxs))
|
||||||
|
IEEE80211_NODE_STAT(ni, rx_amsdu_more_end);
|
||||||
|
} else {
|
||||||
|
/* .. still waiting */
|
||||||
|
IEEE80211_NODE_STAT(ni, rx_amsdu_more);
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -84,7 +84,11 @@ struct ieee80211_nodestats {
|
|||||||
uint32_t ns_tx_deauth_code; /* last deauth reason */
|
uint32_t ns_tx_deauth_code; /* last deauth reason */
|
||||||
uint32_t ns_tx_disassoc; /* disassociations */
|
uint32_t ns_tx_disassoc; /* disassociations */
|
||||||
uint32_t ns_tx_disassoc_code; /* last disassociation reason */
|
uint32_t ns_tx_disassoc_code; /* last disassociation reason */
|
||||||
uint32_t ns_spare[8];
|
|
||||||
|
/* Hardware A-MSDU decode */
|
||||||
|
uint32_t ns_rx_amsdu_more; /* RX decap A-MSDU, more coming from A-MSDU */
|
||||||
|
uint32_t ns_rx_amsdu_more_end; /* RX decap A-MSDU (or any other frame), no more coming */
|
||||||
|
uint32_t ns_spare[6];
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user