svn commit: r298919 - head/sys/dev/otus

Adrian Chadd adrian at FreeBSD.org
Mon May 2 05:43:48 UTC 2016


Author: adrian
Date: Mon May  2 05:43:46 2016
New Revision: 298919
URL: https://svnweb.freebsd.org/changeset/base/298919

Log:
  [otus] implement monitor mode.
  
  * break out the operating mode and rx filter into new functions, rather
    than them being hard-coded
  * if we're in sniffer mode or not associated, set the BSS MAC to all zero,
    rather than relying on a chip reset to do it for us
  * add comments about .. how interestingly buggy the chip is.
  
  Tested:
  
  * AR9170 + AR9102, STA+monitor mode
  
  Obtained from:	linux carl9170 (general chip workings, constant definitions)

Modified:
  head/sys/dev/otus/if_otus.c

Modified: head/sys/dev/otus/if_otus.c
==============================================================================
--- head/sys/dev/otus/if_otus.c	Mon May  2 05:37:25 2016	(r298918)
+++ head/sys/dev/otus/if_otus.c	Mon May  2 05:43:46 2016	(r298919)
@@ -181,6 +181,8 @@ int		otus_set_multi(struct otus_softc *)
 static int	otus_updateedca(struct ieee80211com *);
 static void	otus_updateedca_locked(struct otus_softc *);
 static void	otus_updateslot(struct otus_softc *);
+static void	otus_set_operating_mode(struct otus_softc *sc);
+static void	otus_set_rx_filter(struct otus_softc *sc);
 int		otus_init_mac(struct otus_softc *);
 uint32_t	otus_phy_get_def(struct otus_softc *, uint32_t);
 int		otus_set_board_values(struct otus_softc *,
@@ -964,7 +966,7 @@ otus_alloc_cmd_list(struct otus_softc *s
 
 	for (i = 0; i < ndata; i++) {
 		struct otus_tx_cmd *dp = &cmd[i];
-		dp->buf = malloc(maxsz, M_USBDEV, M_NOWAIT);
+		dp->buf = malloc(maxsz, M_USBDEV, M_NOWAIT | M_ZERO);
 		dp->odata = NULL;
 		if (dp->buf == NULL) {
 			device_printf(sc->sc_dev,
@@ -1028,7 +1030,7 @@ otus_alloc_list(struct otus_softc *sc, s
 		struct otus_data *dp = &data[i];
 		dp->sc = sc;
 		dp->m = NULL;
-		dp->buf = malloc(maxsz, M_USBDEV, M_NOWAIT);
+		dp->buf = malloc(maxsz, M_USBDEV, M_NOWAIT | M_ZERO);
 		if (dp->buf == NULL) {
 			device_printf(sc->sc_dev,
 			    "could not allocate buffer\n");
@@ -1142,6 +1144,7 @@ _otus_getbuf(struct otus_softc *sc)
 		STAILQ_REMOVE_HEAD(&sc->sc_tx_inactive, next);
 	else
 		bf = NULL;
+	/* XXX bzero? */
 	return (bf);
 }
 
@@ -1224,7 +1227,6 @@ otus_newstate(struct ieee80211vap *vap, 
 	struct otus_vap *uvp = OTUS_VAP(vap);
 	struct ieee80211com *ic = vap->iv_ic;
 	struct otus_softc *sc = ic->ic_softc;
-	struct ieee80211_node *ni;
 	enum ieee80211_state ostate;
 
 	ostate = vap->iv_state;
@@ -1239,18 +1241,20 @@ otus_newstate(struct ieee80211vap *vap, 
 	/* XXX TODO: more fleshing out! */
 
 	switch (nstate) {
+	case IEEE80211_S_INIT:
+		otus_set_operating_mode(sc);
+		otus_set_rx_filter(sc);
+		break;
 	case IEEE80211_S_RUN:
-		ni = ieee80211_ref_node(vap->iv_bss);
-
 		if (ic->ic_opmode == IEEE80211_M_STA) {
 			otus_updateslot(sc);
-			otus_set_bssid(sc, ni->ni_bssid);
+			otus_set_operating_mode(sc);
+			otus_set_rx_filter(sc);
 
 			/* Start calibration timer. */
 			taskqueue_enqueue_timeout(taskqueue_thread,
 			    &sc->calib_to, hz);
 		}
-		ieee80211_free_node(ni);
 		break;
 	default:
 		break;
@@ -2355,6 +2359,7 @@ otus_set_multi(struct otus_softc *sc)
 	otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_L, lo);
 	otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_H, hi);
 	r = otus_write_barrier(sc);
+	/* XXX operating mode? filter? */
 	OTUS_UNLOCK(sc);
 	return (r);
 }
@@ -2453,7 +2458,6 @@ otus_init_mac(struct otus_softc *sc)
 
 	otus_write(sc, AR_MAC_REG_ACK_EXTENSION, 0x40);
 	otus_write(sc, AR_MAC_REG_RETRY_MAX, 0);
-	otus_write(sc, AR_MAC_REG_SNIFFER, 0x2000000);
 	otus_write(sc, AR_MAC_REG_RX_THRESHOLD, 0xc1f80);
 	otus_write(sc, AR_MAC_REG_RX_PE_DELAY, 0x70);
 	otus_write(sc, AR_MAC_REG_EIFS_AND_SIFS, 0xa144000);
@@ -2465,13 +2469,14 @@ otus_init_mac(struct otus_softc *sc)
 	otus_write(sc, AR_MAC_REG_BCN_HT1, 0x8000170);
 	otus_write(sc, AR_MAC_REG_BACKOFF_PROTECT, 0x105);
 	otus_write(sc, AR_MAC_REG_AMPDU_FACTOR, 0x10000a);
-	/* Filter any control frames, BAR is bit 24. */
-//	otus_write(sc, AR_MAC_REG_FRAMETYPE_FILTER, 0x0500ffff);
-//	otus_write(sc, AR_MAC_REG_RX_CONTROL, 0x1);
+
+	otus_set_rx_filter(sc);
+
 	otus_write(sc, AR_MAC_REG_BASIC_RATE, 0x150f);
 	otus_write(sc, AR_MAC_REG_MANDATORY_RATE, 0x150f);
 	otus_write(sc, AR_MAC_REG_RTS_CTS_RATE, 0x10b01bb);
 	otus_write(sc, AR_MAC_REG_ACK_TPC, 0x4003c1e);
+
 	/* Enable LED0 and LED1. */
 	otus_write(sc, AR_GPIO_REG_PORT_TYPE, 0x3);
 	otus_write(sc, AR_GPIO_REG_PORT_DATA, 0x3);
@@ -3067,55 +3072,88 @@ otus_led_newstate_type3(struct otus_soft
 #endif
 }
 
+static uint8_t zero_macaddr[IEEE80211_ADDR_LEN] = { 0,0,0,0,0,0 };
+
 /*
- * TODO:
- *
- * + If in monitor mode, set BSSID to all zeros, else the node BSSID.
- * + Handle STA + monitor (eg tcpdump/promisc/radiotap) as well as
- *   pure monitor mode.
+ * Set up operating mode, MAC/BSS address and RX filter.
  */
-static int
+static void
 otus_set_operating_mode(struct otus_softc *sc)
 {
 	struct ieee80211com *ic = &sc->sc_ic;
-	uint32_t rx_ctrl;
-	uint32_t frm_filt;
-	uint32_t cam_mode;
-	uint32_t rx_sniffer;
+	struct ieee80211vap *vap;
+	uint32_t cam_mode = AR_MAC_CAM_DEFAULTS;
+	uint32_t rx_ctrl = AR_MAC_RX_CTRL_DEAGG | AR_MAC_RX_CTRL_SHORT_FILTER;
+	uint32_t sniffer = AR_MAC_SNIFFER_DEFAULTS;
+	uint32_t enc_mode = 0x78; /* XXX */
+	const uint8_t *macaddr;
+	uint8_t bssid[IEEE80211_ADDR_LEN];
+	struct ieee80211_node *ni;
 
 	OTUS_LOCK_ASSERT(sc);
 
-	/* XXX TODO: too many magic constants */
-	rx_ctrl = 0x1;
-	/* Filter any control frames, BAR is bit 24. */
-	frm_filt = 0x0500ffff;
-	cam_mode = 0x0f000002;	/* XXX STA */
-	rx_sniffer = 0x20000000;
+	/*
+	 * If we're in sniffer mode or we don't have a MAC
+	 * address assigned, ensure it gets reset to all-zero.
+	 */
+	IEEE80211_ADDR_COPY(bssid, zero_macaddr);
+	vap = TAILQ_FIRST(&ic->ic_vaps);
+	macaddr = ic->ic_macaddr;
 
 	switch (ic->ic_opmode) {
 	case IEEE80211_M_STA:
-		cam_mode = 0x0f000002;	/* XXX STA */
-		rx_ctrl = 0x1;
-		frm_filt = 0x0500ffff;
-		rx_sniffer = 0x20000000;
+		if (vap) {
+			ni = ieee80211_ref_node(vap->iv_bss);
+			IEEE80211_ADDR_COPY(bssid, ni->ni_bssid);
+			ieee80211_free_node(ni);
+		}
+		cam_mode |= AR_MAC_CAM_STA;
+		rx_ctrl |= AR_MAC_RX_CTRL_PASS_TO_HOST;
 		break;
 	case IEEE80211_M_MONITOR:
-		cam_mode = 0x0f000002;	/* XXX STA */
-		rx_ctrl = 0x1;
-		frm_filt = 0xffffffff;
-		rx_sniffer = 0x20000001;
-		break;
+		/*
+		 * Note: monitor mode ends up causing the MAC to
+		 * generate ACK frames for everything it sees.
+		 * So don't do that; instead just put it in STA mode
+		 * and disable RX filters.
+		 */
 	default:
+		cam_mode |= AR_MAC_CAM_STA;
+		rx_ctrl |= AR_MAC_RX_CTRL_PASS_TO_HOST;
 		break;
 	}
 
-	otus_write(sc, AR_MAC_REG_SNIFFER, rx_sniffer);
+	/*
+	 * TODO: if/when we do hardware encryption, ensure it's
+	 * disabled if the NIC is in monitor mode.
+	 */
+	otus_write(sc, AR_MAC_REG_SNIFFER, sniffer);
 	otus_write(sc, AR_MAC_REG_CAM_MODE, cam_mode);
-	otus_write(sc, AR_MAC_REG_FRAMETYPE_FILTER, frm_filt);
-	otus_write(sc, AR_MAC_REG_RX_CONTROL, cam_mode);
+	otus_write(sc, AR_MAC_REG_ENCRYPTION, enc_mode);
+	otus_write(sc, AR_MAC_REG_RX_CONTROL, rx_ctrl);
+	otus_set_macaddr(sc, macaddr);
+	otus_set_bssid(sc, bssid);
+	/* XXX barrier? */
+}
 
-	(void) otus_write_barrier(sc);
-	return (0);
+static void
+otus_set_rx_filter(struct otus_softc *sc)
+{
+//	struct ieee80211com *ic = &sc->sc_ic;
+
+	OTUS_LOCK_ASSERT(sc);
+
+#if 0
+	if (ic->ic_allmulti > 0 || ic->ic_promisc > 0 ||
+	    ic->ic_opmode == IEEE80211_M_MONITOR) {
+		otus_write(sc, AR_MAC_REG_FRAMETYPE_FILTER, 0xff00ffff);
+	} else {
+#endif
+		/* Filter any control frames, BAR is bit 24. */
+		otus_write(sc, AR_MAC_REG_FRAMETYPE_FILTER, 0x0500ffff);
+#if 0
+	}
+#endif
 }
 
 int
@@ -3139,7 +3177,8 @@ otus_init(struct otus_softc *sc)
 		return error;
 	}
 
-	(void) otus_set_macaddr(sc, ic->ic_macaddr);
+	otus_set_operating_mode(sc);
+	otus_set_rx_filter(sc);
 	(void) otus_set_operating_mode(sc);
 
 	sc->bb_reset = 1;	/* Force cold reset. */


More information about the svn-src-head mailing list