Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 1 Mar 2018 08:05:53 +0000 (UTC)
From:      Eitan Adler <eadler@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r330233 - stable/11/sys/net80211
Message-ID:  <201803010805.w2185r4A004640@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: eadler
Date: Thu Mar  1 08:05:52 2018
New Revision: 330233
URL: https://svnweb.freebsd.org/changeset/base/330233

Log:
  MFC r324570,r324580:
  
  [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:
  stable/11/sys/net80211/ieee80211_input.h
  stable/11/sys/net80211/ieee80211_ioctl.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/net80211/ieee80211_input.h
==============================================================================
--- stable/11/sys/net80211/ieee80211_input.h	Thu Mar  1 07:59:14 2018	(r330232)
+++ stable/11/sys/net80211/ieee80211_input.h	Thu Mar  1 08:05:52 2018	(r330233)
@@ -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.
  *
@@ -225,7 +257,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 ((rxs != NULL) && 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: stable/11/sys/net80211/ieee80211_ioctl.h
==============================================================================
--- stable/11/sys/net80211/ieee80211_ioctl.h	Thu Mar  1 07:59:14 2018	(r330232)
+++ stable/11/sys/net80211/ieee80211_ioctl.h	Thu Mar  1 08:05:52 2018	(r330233)
@@ -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?201803010805.w2185r4A004640>