svn commit: r225720 - user/adrian/if_ath_tx/sys/dev/ath

Adrian Chadd adrian at FreeBSD.org
Wed Sep 21 23:48:20 UTC 2011


Author: adrian
Date: Wed Sep 21 23:48:19 2011
New Revision: 225720
URL: http://svn.freebsd.org/changeset/base/225720

Log:
  Work around some issues seen with the AR9160 when RX'ing aggregate frames.
  
  It seems that the AR9160 in STA mode will occasionally pass A-MPDU subframes
  up to the driver which aren't destined for it. There's nothing obviously
  wrong - it's not occuring during scanning, AR_RX_FILTER is correct, AID
  is now being set correct, the STA ID and BSSID values are correct.
  
  It only occurs on aggregate frame RX. I've not seen it occur on normal
  MPDU RX.
  
  This commit:
  
  * backs out some previous debugging that snuck in;
  * adds some local debugging (which I'll make more useful, but still
    leave commented out by default) to dump descriptors which aren't
    for us;
  * removes the use of the crypto key cache id for determining the
    peer, as it's possible a valid looking frame will come in on a key
    id that is active.
  
  As an example of the last one:
  
  R[ 0] (DS.V:0xa0a13780 DS.P:0xa13780) L:00a137e0 D:045fb800 *
    00000000 00000800 8d2a282a 000b806c
    3e60da94 00000103 052c163d 00000000 00000000 00000000 80030143
  
  FRDS 00:1c:c0:43:87:2b->d4:9a:20:5a:db:0c(00:1b:b1:58:f6:f0) data QoS [TID 0]
      WEP [IV ca 9c 00 e0 08 00 KID 0] 70M +5
  8842 2c00 d49a 205a db0c 001b b158 f6f0 001c c043 872b c0c6 0000 c0ca ca9c
  0020 e008 0000 aec7 45d1 e2b8 b6c2 cb04 ef91 f063 9fc6 8f61 f491 fc5e db4b
  cd0e a2c7 5ccc 9aaa ced2 0024 dcd9 d744 f9ba 0e2e d09d f43e 0f87 7ae6 5ff0
  191c c7fb 2e38 0bc7 f78c 0f87 17e8 f63d fe71
  
  That frame is to a STA address that isn't me. It's marked as valid and
  completed. The EVM values are all whacked though (see how they're all
  marked as 0x00000000 in the receive status) even though the received rate
  is an MCS rate (0x8d, high byte of the third status word.)
  
  This frame ends up being bumped to the BSS node for the VAP; it updates
  the CCMP crypto state:
  
  ccmp_decap: tid=0, keyix=4, wk_rxkeyix=4
  
  (local debugging)
  
  .. and that causes subsequent frames to fail.
  
  This is only going to be merged back to -HEAD if I discover it's a hardware
  issue rather than a driver bug somewhere else.
  
  Finally, I've not yet seen this surface on Merlin (AR9280.) I've not yet
  tested the AR5416 but if it's a hardware bug, it's likely it has the same
  issue.

Modified:
  user/adrian/if_ath_tx/sys/dev/ath/if_ath.c

Modified: user/adrian/if_ath_tx/sys/dev/ath/if_ath.c
==============================================================================
--- user/adrian/if_ath_tx/sys/dev/ath/if_ath.c	Wed Sep 21 23:38:15 2011	(r225719)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_ath.c	Wed Sep 21 23:48:19 2011	(r225720)
@@ -3606,6 +3606,36 @@ ath_handle_micerror(struct ieee80211com 
 	}
 }
 
+/*
+ * It seems that occasionally we receive packets for a sta
+ * that isn't us. This only occurs in aggregation mode.
+ *
+ * This is just a local hack I'm using to sniff an instance
+ * of these out.
+ */
+static void
+ath_rx_dump_wtf(struct ath_softc *sc, struct ath_rx_status *rs,
+    struct ath_buf *bf, struct mbuf *m, int status)
+{
+#if 0
+	const HAL_RATE_TABLE *rt = sc->sc_currates;
+	uint8_t rix = rt->rateCodeToIndex[rs->rs_rate];
+	const struct ieee80211_frame *wh;
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = ifp->if_l2com;
+
+	wh = mtod(m, const struct ieee80211_frame *);
+	if (wh->i_addr1[0] == 0xd4) {
+		device_printf(sc->sc_dev,
+		    "%s: XXX shouldn't see this! keyidx=%d\n",
+		    __func__, rs->rs_keyix);
+		ieee80211_dump_pkt(ic, mtod(m, caddr_t), m->m_len,
+		    sc->sc_hwmap[rix].ieeerate, rs->rs_rssi);
+		ath_printrxbuf(sc, bf, 0, status == HAL_OK);
+	}
+#endif
+}
+
 static void
 ath_rx_proc(void *arg, int npending)
 {
@@ -3682,8 +3712,21 @@ ath_rx_proc(void *arg, int npending)
 #endif
 		if (status == HAL_EINPROGRESS)
 			break;
+
 		TAILQ_REMOVE(&sc->sc_rxbuf, bf, bf_list);
 
+		/*
+		 * If the datalen is greater than the buffer itself,
+		 * it's a corrupted status descriptor; skip.
+		 * Yes, it may actually have data in it.
+		 */
+		if (rs->rs_datalen > m->m_len) {
+			device_printf(sc->sc_dev,
+			     "%s: corrupt descriptor: datalen=%d, m_len=%d\n",
+			    __func__, rs->rs_datalen, m->m_len);
+			goto rx_error;
+		}
+
 		/* These aren't specifically errors */
 		if (rs->rs_flags & HAL_RX_GI)
 			sc->sc_stats.ast_rx_halfgi++;
@@ -3760,6 +3803,11 @@ rx_error:
 			 * Cleanup any pending partial frame.
 			 */
 			if (sc->sc_rxpending != NULL) {
+#if 0
+				device_printf(sc->sc_dev,
+				    "%s: error: rs_status=0x%.08x, len=%d, cleaning up pending frame\n",
+				    __func__, rs->rs_status, rs->rs_datalen);
+#endif
 				m_freem(sc->sc_rxpending);
 				sc->sc_rxpending = NULL;
 			}
@@ -3776,6 +3824,9 @@ rx_error:
 				/* NB: bpf needs the mbuf length setup */
 				len = rs->rs_datalen;
 				m->m_pkthdr.len = m->m_len = len;
+
+				ath_rx_dump_wtf(sc, rs, bf, m, status);
+
 				ath_rx_tap(ifp, m, rs, tsf, nf);
 				ieee80211_radiotap_rx_all(ic, m);
 			}
@@ -3798,7 +3849,13 @@ rx_accept:
 		len = rs->rs_datalen;
 		m->m_len = len;
 
+		ath_rx_dump_wtf(sc, rs, bf, m, status);
+
 		if (rs->rs_more) {
+#if 0
+			device_printf(sc->sc_dev, "%s: rs_more set; status=0x%.08x, datalen=%d?\n",
+			    __func__, rs->rs_status, rs->rs_datalen);
+#endif
 			/*
 			 * Frame spans multiple descriptors; save
 			 * it for the next completed descriptor, it
@@ -3814,6 +3871,10 @@ rx_accept:
 			sc->sc_rxpending = m;
 			goto rx_next;
 		} else if (sc->sc_rxpending != NULL) {
+#if 0
+			device_printf(sc->sc_dev, "%s: second half? status=0x%.08x, datalen=%d\n",
+			    __func__, rs->rs_status, rs->rs_datalen);
+#endif
 			/*
 			 * This is the second part of a jumbogram,
 			 * chain it to the first mbuf, adjust the
@@ -3877,10 +3938,17 @@ rx_accept:
 		 * pass the (referenced) node up to the 802.11 layer
 		 * for its use.
 		 */
-		ni = ieee80211_find_rxnode_withkey(ic,
-			mtod(m, const struct ieee80211_frame_min *),
-			rs->rs_keyix == HAL_RXKEYIX_INVALID ?
-				IEEE80211_KEYIX_NONE : rs->rs_keyix);
+
+		/*
+		 * For some reason, the MAC (AR9160?) returns frames
+		 * destined for other STA's when in STA, non-promisc
+		 * mode. Since sometimes these frames seem to look
+		 * quite valid (including completed status, valid
+		 * looking key entry, etc) let's not use the keyix
+		 * as a shortcut.
+		 */
+		ni = ieee80211_find_rxnode(ic,
+			mtod(m, const struct ieee80211_frame_min *));
 		sc->sc_lastrs = rs;
 
 		if (rs->rs_isaggr)


More information about the svn-src-user mailing list