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

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

Change 35736 by sam@sam_ebb on 2003/08/07 14:36:26

	o revamp input path to pass reference'd node up to wlan layer
	o add radiotap packet capture support
	o add device-specific rssi conversion support for converting
	  rssi values to dbm for recording in radiotap captured frames

Affected files ...

.. //depot/projects/netperf/sys/dev/wi/if_wi.c#2 edit
.. //depot/projects/netperf/sys/dev/wi/if_wi_pccard.c#2 edit
.. //depot/projects/netperf/sys/dev/wi/if_wi_pci.c#3 edit
.. //depot/projects/netperf/sys/dev/wi/if_wireg.h#2 edit
.. //depot/projects/netperf/sys/dev/wi/if_wivar.h#2 edit

Differences ...

==== //depot/projects/netperf/sys/dev/wi/if_wi.c#2 (text+ko) ====

@@ -100,6 +100,7 @@
 
 #include <net80211/ieee80211_var.h>
 #include <net80211/ieee80211_ioctl.h>
+#include <net80211/ieee80211_radiotap.h>
 
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
@@ -110,8 +111,8 @@
 #include <net/bpf.h>
 
 #include <dev/wi/if_wavelan_ieee.h>
+#include <dev/wi/if_wireg.h>
 #include <dev/wi/if_wivar.h>
-#include <dev/wi/if_wireg.h>
 
 #define IF_POLL(ifq, m)		((m) = (ifq)->ifq_head)
 #define	IFQ_POLL(ifq, m)	IF_POLL((ifq), (m))
@@ -372,6 +373,10 @@
 			ic->ic_caps |= IEEE80211_C_MONITOR;
 		}
 		sc->sc_ibss_port = htole16(1);
+
+		sc->sc_min_rssi = WI_LUCENT_MIN_RSSI;
+		sc->sc_max_rssi = WI_LUCENT_MAX_RSSI;
+		sc->sc_dbm_offset = WI_LUCENT_DBM_OFFSET;
 		break;
 
 	case WI_INTERSIL:
@@ -393,6 +398,10 @@
 		if (sc->sc_sta_firmware_ver >= 803)
 			ic->ic_caps |= IEEE80211_C_HOSTAP;
 		sc->sc_ibss_port = htole16(0);
+
+		sc->sc_min_rssi = WI_PRISM_MIN_RSSI;
+		sc->sc_max_rssi = WI_PRISM_MAX_RSSI;
+		sc->sc_dbm_offset = WI_PRISM_DBM_OFFSET;
 		break;
 
 	case WI_SYMBOL:
@@ -401,6 +410,10 @@
 		if (sc->sc_sta_firmware_ver >= 25000)
 			ic->ic_caps |= IEEE80211_C_IBSS;
 		sc->sc_ibss_port = htole16(4);
+
+		sc->sc_min_rssi = WI_PRISM_MIN_RSSI;
+		sc->sc_max_rssi = WI_PRISM_MAX_RSSI;
+		sc->sc_dbm_offset = WI_PRISM_DBM_OFFSET;
 		break;
 	}
 
@@ -431,9 +444,8 @@
 	buflen = sizeof(val);
 	if ((sc->sc_flags & WI_FLAGS_HAS_DBMADJUST) &&
 	    wi_read_rid(sc, WI_RID_DBM_ADJUST, &val, &buflen) == 0) {
-		sc->sc_dbm_adjust = le16toh(val);
-	} else
-		sc->sc_dbm_adjust = 100;	/* default */
+		sc->sc_dbm_offset = le16toh(val);
+	}
 
 	sc->sc_max_datalen = 2304;
 	sc->sc_system_scale = 1;
@@ -460,6 +472,23 @@
 	ic->ic_newstate = wi_newstate;
 	ieee80211_media_init(ifp, wi_media_change, wi_media_status);
 
+#if NBPFILTER > 0
+	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 = WI_TX_RADIOTAP_PRESENT;
+
+	sc->sc_rx_th.wr_ihdr.it_len = sizeof(sc->sc_rx_th);
+	sc->sc_rx_th.wr_ihdr.it_present = WI_RX_RADIOTAP_PRESENT0;
+	sc->sc_rx_th.wr_present1 = WI_RX_RADIOTAP_PRESENT1;
+#endif
 	return (0);
 }
 
@@ -901,10 +930,9 @@
 
 			MGETHDR(mb, M_DONTWAIT, m0->m_type);
 			if (mb != NULL) {
-				(void) m_dup_pkthdr(mb, m0, M_DONTWAIT);
 				mb->m_next = m0;
-				mb->m_data = (caddr_t)&frmhdr;
-				mb->m_len = sizeof(frmhdr);
+				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);
@@ -1355,6 +1383,7 @@
 	struct wi_frame frmhdr;
 	struct mbuf *m;
 	struct ieee80211_frame *wh;
+	struct ieee80211_node *ni;
 	int fid, len, off, rssi;
 	u_int8_t dir;
 	u_int16_t status;
@@ -1445,12 +1474,23 @@
 	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) {
+			/* XXX replace divide by table */
+			sc->sc_rx_th.wr_rate = frmhdr.wi_rx_rate / 5;
+			sc->sc_rx_th.wr_antsignal =
+				WI_RSSI_TO_DBM(sc, frmhdr.wi_rx_signal);
+			sc->sc_rx_th.wr_antnoise =
+				WI_RSSI_TO_DBM(sc, frmhdr.wi_rx_silence);
+			sc->sc_rx_th.wr_time =
+				htole32((frmhdr.wi_rx_tstamp1 << 16) |
+					frmhdr.wi_rx_tstamp0);
+
 			(void) m_dup_pkthdr(mb, m, M_DONTWAIT);
 			mb->m_next = m;
-			mb->m_data = (caddr_t)&frmhdr;
-			mb->m_len = sizeof(frmhdr);
+			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);
@@ -1471,7 +1511,32 @@
 	if (ic->ic_opmode == IEEE80211_M_IBSS && dir == IEEE80211_FC1_DIR_NODS)
 		wi_sync_bssid(sc, wh->i_addr3);
 
-	ieee80211_input(ifp, m, rssi, rstamp, 0);
+	/*
+	 * 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 fallback 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);
+	/*
+	 * Send frame up for processing.
+	 */
+	ieee80211_input(ifp, m, ni, rssi, rstamp);
+	/*
+	 * 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);
 }
 
 static void
@@ -1808,7 +1873,7 @@
 			    &len);
 			break;
 		}
-		wreq.wi_val[0] = htole16(sc->sc_dbm_adjust);
+		wreq.wi_val[0] = htole16(sc->sc_dbm_offset);
 		len = sizeof(u_int16_t);
 		break;
 
@@ -2579,6 +2644,12 @@
 		wi_read_rid(sc, WI_RID_CURRENT_CHAN, &val, &buflen);
 		/* XXX validate channel */
 		ni->ni_chan = &ic->ic_channels[le16toh(val)];
+#if NBPFILTER > 0
+		sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
+			htole16(ni->ni_chan->ic_freq);
+		sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
+			htole16(ni->ni_chan->ic_flags);
+#endif
 
 		if (IEEE80211_ADDR_EQ(old_bssid, ni->ni_bssid))
 			sc->sc_false_syns++;

==== //depot/projects/netperf/sys/dev/wi/if_wi_pccard.c#2 (text+ko) ====

@@ -62,6 +62,7 @@
 #include <net/if_types.h>
 
 #include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_radiotap.h>
 
 #include <dev/pccard/pccardvar.h>
 #if __FreeBSD_version >= 500000
@@ -69,8 +70,8 @@
 #endif
 
 #include <dev/wi/if_wavelan_ieee.h>
+#include <dev/wi/if_wireg.h>
 #include <dev/wi/if_wivar.h>
-#include <dev/wi/if_wireg.h>
 #ifdef WI_SYMBOL_FIRMWARE
 #include <dev/wi/spectrum24t_cf.h>
 #endif

==== //depot/projects/netperf/sys/dev/wi/if_wi_pci.c#3 (text+ko) ====

@@ -62,10 +62,11 @@
 #include <net/if_types.h>
 
 #include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_radiotap.h>
 
 #include <dev/wi/if_wavelan_ieee.h>
+#include <dev/wi/if_wireg.h>
 #include <dev/wi/if_wivar.h>
-#include <dev/wi/if_wireg.h>
 
 static int wi_pci_probe(device_t);
 static int wi_pci_attach(device_t);

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

@@ -679,3 +679,37 @@
  */
 #define WI_HFA386X_CR_A_D_TEST_MODES2 0x1A
 #define WI_HFA386X_CR_MANUAL_TX_POWER 0x3E
+
+/*
+ * Radio capture format for Prism.
+ */
+#define WI_RX_RADIOTAP_PRESENT0 \
+	((1 << IEEE80211_RADIOTAP_FLAGS) | \
+	 (1 << IEEE80211_RADIOTAP_RATE) | \
+	 (1 << IEEE80211_RADIOTAP_CHANNEL) | \
+	 (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) | \
+	 (1 << IEEE80211_RADIOTAP_DB_ANTNOISE) | \
+	 (1 << IEEE80211_RADIOTAP_EXT))
+
+#define WI_RX_RADIOTAP_PRESENT1	(1 << (IEEE80211_RADIOTAP_TIME - 32))
+
+struct wi_rx_radiotap_header {
+	struct ieee80211_radiotap_header wr_ihdr;
+	u_int32_t	wr_present1;
+	u_int8_t	wr_flags;
+	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_antnoise;
+	u_int32_t	wr_time;
+};
+
+#define WI_TX_RADIOTAP_PRESENT \
+	((1 << IEEE80211_RADIOTAP_CHANNEL))
+
+struct wi_tx_radiotap_header {
+	struct ieee80211_radiotap_header wt_ihdr;
+	u_int16_t	wt_chan_freq;
+	u_int16_t	wt_chan_flags;
+};

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

@@ -106,7 +106,11 @@
 	u_int16_t		sc_procframe;
 	u_int16_t		sc_portnum;
 
-	u_int16_t		sc_dbm_adjust;
+	/* RSSI interpretation */
+	u_int16_t		sc_min_rssi;	/* clamp sc_min_rssi < RSSI */
+	u_int16_t		sc_max_rssi;	/* clamp RSSI < sc_max_rssi */
+	u_int16_t		sc_dbm_offset;	/* dBm ~ RSSI - sc_dbm_offset */
+
 	u_int16_t		sc_max_datalen;
 	u_int16_t		sc_system_scale;
 	u_int16_t		sc_cnfauthmode;
@@ -158,8 +162,19 @@
 	int			sc_false_syns;
 
 	u_int16_t		sc_txbuf[IEEE80211_MAX_LEN/2];
+
+	union {
+		struct wi_tx_radiotap_header th;
+		u_int8_t	pad[64];
+	} u_tx_rt;
+	union {
+		struct wi_rx_radiotap_header th;
+		u_int8_t	pad[64];
+	} u_rx_rt;
 };
 #define	sc_if			sc_ic.ic_if
+#define	sc_tx_th		u_tx_rt.th
+#define	sc_rx_th		u_rx_rt.th
 
 /* maximum consecutive false change-of-BSSID indications */
 #define	WI_MAX_FALSE_SYNS		10	
@@ -184,6 +199,17 @@
 	u_int8_t	firm_type;
 };
 
+#define	WI_PRISM_MIN_RSSI	0x1b
+#define	WI_PRISM_MAX_RSSI	0x9a
+#define	WI_PRISM_DBM_OFFSET	100 /* XXX */
+
+#define	WI_LUCENT_MIN_RSSI	47
+#define	WI_LUCENT_MAX_RSSI	138
+#define	WI_LUCENT_DBM_OFFSET	149
+
+#define	WI_RSSI_TO_DBM(sc, rssi) (MIN((sc)->sc_max_rssi, \
+    MAX((sc)->sc_min_rssi, (rssi))) - (sc)->sc_dbm_offset)
+
 #if __FreeBSD_version < 500000
 /*
  * Various compat hacks/kludges



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