Date: Thu, 12 Oct 2017 21:56:58 +0000 (UTC) From: Adrian Chadd <adrian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r324570 - head/sys/net80211 Message-ID: <201710122156.v9CLuwH4017132@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: adrian Date: Thu Oct 12 21:56:58 2017 New Revision: 324570 URL: https://svnweb.freebsd.org/changeset/base/324570 Log: [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. Modified: head/sys/net80211/ieee80211_input.h head/sys/net80211/ieee80211_ioctl.h Modified: head/sys/net80211/ieee80211_input.h ============================================================================== --- head/sys/net80211/ieee80211_input.h Thu Oct 12 21:26:52 2017 (r324569) +++ head/sys/net80211/ieee80211_input.h Thu Oct 12 21:56:58 2017 (r324570) @@ -131,7 +131,39 @@ ishtinfooui(const uint8_t *frm) 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 * state and return whether it's in sequence or should be dropped. * @@ -238,7 +270,20 @@ ieee80211_check_rxseq(struct ieee80211_node *ni, struc goto fail; ok: - ni->ni_rxseqs[tid] = rxseq; + /* + * 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; + 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; Modified: head/sys/net80211/ieee80211_ioctl.h ============================================================================== --- head/sys/net80211/ieee80211_ioctl.h Thu Oct 12 21:26:52 2017 (r324569) +++ head/sys/net80211/ieee80211_ioctl.h Thu Oct 12 21:56:58 2017 (r324570) @@ -84,7 +84,11 @@ struct ieee80211_nodestats { uint32_t ns_tx_deauth_code; /* last deauth reason */ uint32_t ns_tx_disassoc; /* disassociations */ 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]; }; /*
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201710122156.v9CLuwH4017132>