Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 7 Aug 2003 14:38:45 -0700 (PDT)
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 35739 for review
Message-ID:  <200308072138.h77LcjK5020799@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=35739

Change 35739 by sam@sam_ebb on 2003/08/07 14:38:31

	o record rx antenna state in driver-private node state
	o revamp input path to pass (referenced) node up into the wlan layer
	  and to capture the rx antenna state
	o add radiotap packet capture support
	o delay interrupt re-enable on channel change until all state
	  has been changed

Affected files ...

.. //depot/projects/netperf/sys/dev/ath/if_ath.c#5 edit
.. //depot/projects/netperf/sys/dev/ath/if_athioctl.h#2 edit
.. //depot/projects/netperf/sys/dev/ath/if_athvar.h#2 edit

Differences ...

==== //depot/projects/netperf/sys/dev/ath/if_ath.c#5 (text+ko) ====

@@ -70,10 +70,6 @@
 #include <net/ethernet.h>
 #include <net/if_llc.h>
 
-#include <net80211/ieee80211.h>
-#include <net80211/ieee80211_crypto.h>
-#include <net80211/ieee80211_node.h>
-#include <net80211/ieee80211_proto.h>
 #include <net80211/ieee80211_var.h>
 
 #include <net/bpf.h>
@@ -302,6 +298,21 @@
 	/* complete initialization */
 	ieee80211_media_init(ifp, ath_media_change, ieee80211_media_status);
 
+	bpfattach2(ifp, DLT_IEEE802_11_RADIO,
+		sizeof(struct ieee80211_frame) + sizeof(sc->sc_tx_th),
+		&sc->sc_drvbpf);
+	/*
+	 * Initialize constant fields.
+	 *
+	 * NB: the channel is setup each time we transition to the
+	 *     RUN state to avoid filling it in for each frame.
+	 */
+	sc->sc_tx_th.wt_ihdr.it_len = sizeof(sc->sc_tx_th);
+	sc->sc_tx_th.wt_ihdr.it_present = ATH_TX_RADIOTAP_PRESENT;
+
+	sc->sc_rx_th.wr_ihdr.it_len = sizeof(sc->sc_rx_th);
+	sc->sc_rx_th.wr_ihdr.it_present = ATH_RX_RADIOTAP_PRESENT;
+
 	if_printf(ifp, "802.11 address: %s\n", ether_sprintf(ic->ic_myaddr));
 
 	return 0;
@@ -744,6 +755,23 @@
 		} else
 			ni = ic->ic_bss;
 
+		if (sc->sc_drvbpf) {
+			struct mbuf *mb;
+
+			MGETHDR(mb, M_DONTWAIT, m->m_type);
+			if (mb != NULL) {
+				sc->sc_tx_th.wt_rate =
+					ni->ni_rates.rs_rates[ni->ni_txrate];
+
+				mb->m_next = m;
+				mb->m_data = (caddr_t)&sc->sc_tx_th;
+				mb->m_len = sizeof(sc->sc_tx_th);
+				mb->m_pkthdr.len += mb->m_len;
+				bpf_mtap(sc->sc_drvbpf, mb);
+				m_free(mb);
+			}
+		}
+
 		/*
 		 * TODO:
 		 * The duration field of 802.11 header should be filled.
@@ -751,12 +779,6 @@
 		 *     doesn't know the detail of parameters such as IFS
 		 *     for now..
 		 */
-
-		if (IFF_DUMPPKTS(ifp))
-			ieee80211_dump_pkt(mtod(m, u_int8_t *), m->m_len,
-			    ni->ni_rates.rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL,
-			    -1);
-
 		if (ath_tx_start(sc, ni, bf, m)) {
 	bad:
 			mtx_lock(&sc->sc_txbuflock);
@@ -1371,7 +1393,7 @@
 {
 	struct ath_node *an =
 		malloc(sizeof(struct ath_node), M_DEVBUF, M_NOWAIT | M_ZERO);
-	return an ? &an->st_node : NULL;
+	return an ? &an->an_node : NULL;
 }
 
 static void
@@ -1455,11 +1477,13 @@
 {
 	struct ath_softc *sc = arg;
 	struct ath_buf *bf;
-	struct ifnet *ifp = &sc->sc_ic.ic_if;
+	struct ieee80211com *ic = &sc->sc_ic;
+	struct ifnet *ifp = &ic->ic_if;
 	struct ath_hal *ah = sc->sc_ah;
 	struct ath_desc *ds;
 	struct mbuf *m;
 	struct ieee80211_frame *wh, whbuf;
+	struct ieee80211_node *ni;
 	int len;
 	u_int phyerr;
 	HAL_STATUS status;
@@ -1524,12 +1548,29 @@
 		bf->bf_m = NULL;
 		m->m_pkthdr.rcvif = ifp;
 		m->m_pkthdr.len = m->m_len = len;
-		if (IFF_DUMPPKTS(ifp)) {
-			struct ieee80211com *ic = &sc->sc_ic;
-			const HAL_RATE_TABLE *rt = sc->sc_rates[ic->ic_curmode];
-			ieee80211_dump_pkt(mtod(m, u_int8_t *), len,
-				rt ? rt->info[rt->rateCodeToIndex[ds->ds_rxstat.rs_rate]].dot11Rate & IEEE80211_RATE_VAL : 0,
-				ds->ds_rxstat.rs_rssi);
+
+		if (sc->sc_drvbpf) {
+			struct mbuf *mb;
+
+			/* XXX pre-allocate space when setting up recv's */
+			MGETHDR(mb, M_DONTWAIT, m->m_type);
+			if (mb != NULL) {
+				sc->sc_rx_th.wr_rate =
+					sc->sc_hwmap[ds->ds_rxstat.rs_rate];
+				sc->sc_rx_th.wr_antsignal =
+					ds->ds_rxstat.rs_rssi;
+				sc->sc_rx_th.wr_antenna =
+					ds->ds_rxstat.rs_antenna;
+				/* XXX TSF */
+
+				(void) m_dup_pkthdr(mb, m, M_DONTWAIT);
+				mb->m_next = m;
+				mb->m_data = (caddr_t)&sc->sc_rx_th;
+				mb->m_len = sizeof(sc->sc_rx_th);
+				mb->m_pkthdr.len += mb->m_len;
+				bpf_mtap(sc->sc_drvbpf, mb);
+				m_free(mb);
+			}
 		}
 		m_adj(m, -IEEE80211_CRC_LEN);
 		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
@@ -1546,10 +1587,35 @@
 			 */
 			m_adj(m, -IEEE80211_WEP_CRCLEN);
 		}
-		ieee80211_input(ifp, m,
-			ds->ds_rxstat.rs_rssi,
-			ds->ds_rxstat.rs_tstamp,
-			ds->ds_rxstat.rs_antenna);
+
+		/*
+		 * Locate the node for sender, track state, and
+		 * then pass this node (referenced) up to the 802.11
+		 * layer for its use.  We are required to pass
+		 * something so we fall back to ic_bss when this frame
+		 * is from an unknown sender.
+		 */
+		if (ic->ic_opmode != IEEE80211_M_STA) {
+			ni = ieee80211_find_node(ic, wh->i_addr2);
+			if (ni == NULL)
+				ni = ieee80211_ref_node(ic->ic_bss);
+		} else
+			ni = ieee80211_ref_node(ic->ic_bss);
+		ATH_NODE(ni)->an_rx_antenna = ds->ds_rxstat.rs_antenna;
+		/*
+		 * Send frame up for processing.
+		 */
+		ieee80211_input(ifp, m, ni,
+			ds->ds_rxstat.rs_rssi, ds->ds_rxstat.rs_tstamp);
+		/*
+		 * The frame may have caused the node to be marked for
+		 * reclamation (e.g. in response to a DEAUTH message)
+		 * so use free_node here instead of unref_node.
+		 */
+		if (ni == ic->ic_bss)
+			ieee80211_unref_node(&ni);
+		else
+			ieee80211_free_node(ic, ni);
   rx_next:
 		TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
 	} while (ath_rxbuf_init(sc, bf) == 0);
@@ -1790,7 +1856,7 @@
 	if (an->an_tx_antenna)
 		antenna = an->an_tx_antenna;
 	else
-		antenna = ni->ni_rantenna;
+		antenna = an->an_rx_antenna;
 
 	/*
 	 * Formulate first tx descriptor with tx controls.
@@ -2091,9 +2157,12 @@
 		}
 
 		/*
-		 * Re-enable interrupts.
+		 * Update BPF state.
 		 */
-		ath_hal_intrset(ah, sc->sc_imask);
+		sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
+			htole16(chan->ic_freq);
+		sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
+			htole16(chan->ic_flags);
 
 		/*
 		 * Change channels and update the h/w rate map
@@ -2103,6 +2172,11 @@
 		mode = ieee80211_chan2mode(ic, chan);
 		if (mode != sc->sc_curmode)
 			ath_setcurmode(sc, mode);
+
+		/*
+		 * Re-enable interrupts.
+		 */
+		ath_hal_intrset(ah, sc->sc_imask);
 	}
 	return 0;
 }
@@ -2397,6 +2471,9 @@
 	KASSERT(rt != NULL, ("no h/w rate set for phy mode %u", mode));
 	for (i = 0; i < rt->rateCount; i++)
 		sc->sc_rixmap[rt->info[i].dot11Rate & IEEE80211_RATE_VAL] = i;
+	memset(sc->sc_hwmap, 0, sizeof(sc->sc_hwmap));
+	for (i = 0; i < 32; i++)
+		sc->sc_hwmap[i] = rt->info[rt->rateCodeToIndex[i]].dot11Rate;
 	sc->sc_currates = rt;
 	sc->sc_curmode = mode;
 }

==== //depot/projects/netperf/sys/dev/ath/if_athioctl.h#2 (text+ko) ====

@@ -90,4 +90,39 @@
 
 #define	SIOCGATHSTATS	_IOWR('i', 137, struct ifreq)
 
+/*
+ * Radio capture format.
+ */
+#define ATH_RX_RADIOTAP_PRESENT (		\
+	(1 << IEEE80211_RADIOTAP_FLAGS)		| \
+	(1 << IEEE80211_RADIOTAP_RATE)		| \
+	(1 << IEEE80211_RADIOTAP_CHANNEL)	| \
+	(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL)	| \
+	(1 << IEEE80211_RADIOTAP_ANTENNA)	| \
+	0)
+
+struct ath_rx_radiotap_header {
+	struct ieee80211_radiotap_header wr_ihdr;
+	u_int8_t	wr_flags;		/* XXX for padding */
+	u_int8_t	wr_rate;
+	u_int16_t	wr_chan_freq;
+	u_int16_t	wr_chan_flags;
+	u_int8_t	wr_antsignal;
+	u_int8_t	wr_antenna;
+};
+
+#define ATH_TX_RADIOTAP_PRESENT (		\
+	(1 << IEEE80211_RADIOTAP_FLAGS)		| \
+	(1 << IEEE80211_RADIOTAP_RATE)		| \
+	(1 << IEEE80211_RADIOTAP_CHANNEL)	| \
+	0)
+
+struct ath_tx_radiotap_header {
+	struct ieee80211_radiotap_header wt_ihdr;
+	u_int8_t	wt_flags;		/* XXX for padding */
+	u_int8_t	wt_rate;
+	u_int16_t	wt_chan_freq;
+	u_int16_t	wt_chan_flags;
+};
+
 #endif /* _DEV_ATH_ATHIOCTL_H */

==== //depot/projects/netperf/sys/dev/ath/if_athvar.h#2 (text+ko) ====

@@ -45,6 +45,7 @@
 #include <sys/taskqueue.h>
 
 #include <contrib/dev/ath/ah.h>
+#include <net80211/ieee80211_radiotap.h>
 #include <dev/ath/if_athioctl.h>
 
 #define	ATH_TIMEOUT		1000
@@ -55,13 +56,15 @@
 
 /* driver-specific node */
 struct ath_node {
-	struct ieee80211_node st_node;	/* base class */
+	struct ieee80211_node an_node;	/* base class */
 	u_int		an_tx_ok;	/* tx ok pkt */
 	u_int		an_tx_err;	/* tx !ok pkt */
 	u_int		an_tx_retr;	/* tx retry count */
 	int		an_tx_upper;	/* tx upper rate req cnt */
 	u_int		an_tx_antenna;	/* antenna for last good frame */
+	u_int		an_rx_antenna;	/* antenna for last rcvd frame */
 };
+#define	ATH_NODE(_n)	((struct ath_node *)(_n))
 
 struct ath_buf {
 	TAILQ_ENTRY(ath_buf)	bf_list;
@@ -95,8 +98,19 @@
 	const HAL_RATE_TABLE	*sc_currates;	/* current rate table */
 	enum ieee80211_phymode	sc_curmode;	/* current phy mode */
 	u_int8_t		sc_rixmap[256];	/* IEEE to h/w rate table ix */
+	u_int8_t		sc_hwmap[32];	/* h/w rate ix to IEEE table */
 	HAL_INT			sc_imask;	/* interrupt mask copy */
 
+	struct bpf_if		*sc_drvbpf;
+	union {
+		struct ath_tx_radiotap_header th;
+		u_int8_t	pad[64];
+	} u_tx_rt;
+	union {
+		struct ath_rx_radiotap_header th;
+		u_int8_t	pad[64];
+	} u_rx_rt;
+
 	struct ath_desc		*sc_desc;	/* TX/RX descriptors */
 	bus_dma_segment_t	sc_dseg;
 	bus_dmamap_t		sc_ddmamap;	/* DMA map for descriptors */
@@ -129,6 +143,8 @@
 	struct callout		sc_scan_ch;	/* callout handle for scan */
 	struct ath_stats	sc_stats;	/* interface statistics */
 };
+#define	sc_tx_th		u_tx_rt.th
+#define	sc_rx_th		u_rx_rt.th
 
 int	ath_attach(u_int16_t, struct ath_softc *);
 int	ath_detach(struct ath_softc *);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200308072138.h77LcjK5020799>