summaryrefslogtreecommitdiffstats
path: root/sys/dev/wi
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2009-05-20 20:00:40 +0000
committersam <sam@FreeBSD.org>2009-05-20 20:00:40 +0000
commit68f7a1034ab73897585652ceedd3727d57150c12 (patch)
treec9b0cc01e080db542eb19f65236177aacfa14b5d /sys/dev/wi
parentdf90a80062bff5ee7300c9b15aaeeaa9c1b49b5e (diff)
downloadFreeBSD-src-68f7a1034ab73897585652ceedd3727d57150c12.zip
FreeBSD-src-68f7a1034ab73897585652ceedd3727d57150c12.tar.gz
Overhaul monitor mode handling:
o replace DLT_IEEE802_11 support in net80211 with DLT_IEEE802_11_RADIO and remove explicit bpf support from wireless drivers; drivers now use ieee80211_radiotap_attach to setup shared data structures that hold the radiotap header for each packet tx/rx o remove rx timestamp from the rx path; it was used only by the tdma support for debugging and was mostly useless due to it being 32-bits and mostly unavailable o track DLT_IEEE80211_RADIO bpf attachments and maintain per-vap and per-com state when there are active taps o track the number of monitor mode vaps o use bpf tap and monitor mode vap state to decide when to collect radiotap state and dispatch frames; drivers no longer explicitly directly check bpf state or use bpf calls to tap frames o handle radiotap state updates on channel change in net80211; drivers should not do this (unless they bypass net80211 which is almost always a mistake) o update various drivers to be more consistent/correct in handling radiotap o update ral to include TSF in radiotap'd frames o add promisc mode callback to wi Reviewed by: cbzimmer, rpaulo, thompsa
Diffstat (limited to 'sys/dev/wi')
-rw-r--r--sys/dev/wi/if_wi.c99
-rw-r--r--sys/dev/wi/if_wireg.h4
-rw-r--r--sys/dev/wi/if_wivar.h6
3 files changed, 55 insertions, 54 deletions
diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c
index 3dc329b..5cdec5f 100644
--- a/sys/dev/wi/if_wi.c
+++ b/sys/dev/wi/if_wi.c
@@ -121,9 +121,10 @@ static int wi_start_tx(struct ifnet *ifp, struct wi_frame *frmhdr,
static int wi_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static int wi_newstate_sta(struct ieee80211vap *, enum ieee80211_state, int);
-static int wi_newstate_hostap(struct ieee80211vap *, enum ieee80211_state, int);
+static int wi_newstate_hostap(struct ieee80211vap *, enum ieee80211_state,
+ int);
static void wi_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
- int subtype, int rssi, int noise, u_int32_t rstamp);
+ int subtype, int rssi, int nf);
static int wi_reset(struct wi_softc *);
static void wi_watchdog(void *);
static int wi_ioctl(struct ifnet *, u_long, caddr_t);
@@ -139,6 +140,7 @@ static int wi_write_txrate(struct wi_softc *, struct ieee80211vap *);
static int wi_write_wep(struct wi_softc *, struct ieee80211vap *);
static int wi_write_multi(struct wi_softc *);
static void wi_update_mcast(struct ifnet *);
+static void wi_update_promisc(struct ifnet *);
static int wi_alloc_fid(struct wi_softc *, int, int *);
static void wi_read_nicid(struct wi_softc *);
static int wi_write_ssid(struct wi_softc *, int, u_int8_t *, int);
@@ -455,25 +457,13 @@ wi_attach(device_t dev)
ic->ic_vap_create = wi_vap_create;
ic->ic_vap_delete = wi_vap_delete;
ic->ic_update_mcast = wi_update_mcast;
+ ic->ic_update_promisc = wi_update_promisc;
- bpfattach(ifp, DLT_IEEE802_11_RADIO,
- sizeof(struct ieee80211_frame) + sizeof(sc->sc_tx_th));
- /*
- * Initialize constant fields.
- * XXX make header lengths a multiple of 32-bits so subsequent
- * headers are properly aligned; this is a kludge to keep
- * certain applications happy.
- *
- * 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_len = roundup(sizeof(sc->sc_tx_th), sizeof(u_int32_t));
- sc->sc_tx_th.wt_ihdr.it_len = htole16(sc->sc_tx_th_len);
- sc->sc_tx_th.wt_ihdr.it_present = htole32(WI_TX_RADIOTAP_PRESENT);
-
- sc->sc_rx_th_len = roundup(sizeof(sc->sc_rx_th), sizeof(u_int32_t));
- sc->sc_rx_th.wr_ihdr.it_len = htole16(sc->sc_rx_th_len);
- sc->sc_rx_th.wr_ihdr.it_present = htole32(WI_RX_RADIOTAP_PRESENT);
+ ieee80211_radiotap_attach(ic,
+ &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
+ WI_TX_RADIOTAP_PRESENT,
+ &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
+ WI_RX_RADIOTAP_PRESENT);
if (bootverbose)
ieee80211_announce(ic);
@@ -482,7 +472,6 @@ wi_attach(device_t dev)
NULL, wi_intr, sc, &sc->wi_intrhand);
if (error) {
device_printf(dev, "bus_setup_intr() failed! (%d)\n", error);
- bpfdetach(ifp);
ieee80211_ifdetach(ic);
if_free(sc->sc_ifp);
wi_free(dev);
@@ -506,7 +495,6 @@ wi_detach(device_t dev)
wi_stop_locked(sc, 0);
WI_UNLOCK(sc);
- bpfdetach(ifp);
ieee80211_ifdetach(ic);
bus_teardown_intr(dev, sc->irq, sc->wi_intrhand);
@@ -761,11 +749,6 @@ wi_set_channel(struct ieee80211com *ic)
WI_LOCK(sc);
wi_write_val(sc, WI_RID_OWN_CHNL,
ieee80211_chan2ieee(ic, ic->ic_curchan));
-
- sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
- htole16(ic->ic_curchan->ic_freq);
- sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
- htole16(ic->ic_curchan->ic_flags);
WI_UNLOCK(sc);
}
@@ -812,7 +795,7 @@ wi_scan_end(struct ieee80211com *ic)
static void
wi_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
- int subtype, int rssi, int noise, u_int32_t rstamp)
+ int subtype, int rssi, int nf)
{
struct ieee80211vap *vap = ni->ni_vap;
@@ -823,7 +806,7 @@ wi_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
/* NB: filter frames that trigger state changes */
return;
}
- WI_VAP(vap)->wv_recv_mgmt(ni, m, subtype, rssi, noise, rstamp);
+ WI_VAP(vap)->wv_recv_mgmt(ni, m, subtype, rssi, nf);
}
static int
@@ -1025,10 +1008,9 @@ wi_start_locked(struct ifnet *ifp)
frmhdr.wi_tx_ctl |= htole16(WI_TXCNTL_NOCRYPT);
}
- if (bpf_peers_present(ifp->if_bpf)) {
+ if (ieee80211_radiotap_active_vap(ni->ni_vap)) {
sc->sc_tx_th.wt_rate = ni->ni_txrate;
- bpf_mtap2(ifp->if_bpf,
- &sc->sc_tx_th, sc->sc_tx_th_len, m0);
+ ieee80211_radiotap_tx(ni->ni_vap, m0);
}
m_copydata(m0, 0, sizeof(struct ieee80211_frame),
@@ -1088,6 +1070,7 @@ wi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m0,
{
struct ieee80211com *ic = ni->ni_ic;
struct ifnet *ifp = ic->ic_ifp;
+ struct ieee80211vap *vap = ni->ni_vap;
struct wi_softc *sc = ifp->if_softc;
struct ieee80211_key *k;
struct ieee80211_frame *wh;
@@ -1127,9 +1110,9 @@ wi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m0,
}
frmhdr.wi_tx_ctl |= htole16(WI_TXCNTL_NOCRYPT);
}
- if (bpf_peers_present(ifp->if_bpf)) {
+ if (ieee80211_radiotap_active_vap(vap)) {
sc->sc_tx_th.wt_rate = ni->ni_txrate;
- bpf_mtap2(ifp->if_bpf, &sc->sc_tx_th, sc->sc_tx_th_len, m0);
+ ieee80211_radiotap_tx(vap, m0);
}
m_copydata(m0, 0, sizeof(struct ieee80211_frame),
(caddr_t)&frmhdr.wi_whdr);
@@ -1328,10 +1311,10 @@ wi_rx_intr(struct wi_softc *sc)
struct mbuf *m;
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
- int fid, len, off, rssi;
+ int fid, len, off;
u_int8_t dir;
u_int16_t status;
- u_int32_t rstamp;
+ int8_t rssi, nf;
fid = CSR_READ_2(sc, WI_RX_FID);
@@ -1353,9 +1336,6 @@ wi_rx_intr(struct wi_softc *sc)
DPRINTF(("wi_rx_intr: fid %x error status %x\n", fid, status));
return;
}
- rssi = frmhdr.wi_rx_signal;
- rstamp = (le16toh(frmhdr.wi_rx_tstamp0) << 16) |
- le16toh(frmhdr.wi_rx_tstamp1);
len = le16toh(frmhdr.wi_dat_len);
off = ALIGN(sizeof(struct ieee80211_frame));
@@ -1393,17 +1373,24 @@ wi_rx_intr(struct wi_softc *sc)
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
- if (bpf_peers_present(ifp->if_bpf)) {
+ rssi = frmhdr.wi_rx_signal;
+ nf = frmhdr.wi_rx_silence;
+ if (ieee80211_radiotap_active(ic)) {
+ struct wi_rx_radiotap_header *tap = &sc->sc_rx_th;
+ uint32_t rstamp;
+
+ rstamp = (le16toh(frmhdr.wi_rx_tstamp0) << 16) |
+ le16toh(frmhdr.wi_rx_tstamp1);
+ tap->wr_tsf = htole64(rstamp);
/* XXX replace divide by table */
- sc->sc_rx_th.wr_rate = frmhdr.wi_rx_rate / 5;
- sc->sc_rx_th.wr_antsignal = frmhdr.wi_rx_signal;
- sc->sc_rx_th.wr_antnoise = frmhdr.wi_rx_silence;
- sc->sc_rx_th.wr_flags = 0;
+ tap->wr_rate = frmhdr.wi_rx_rate / 5;
+ tap->wr_flags = 0;
if (frmhdr.wi_status & WI_STAT_PCF)
- sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_CFP;
+ tap->wr_flags |= IEEE80211_RADIOTAP_F_CFP;
if (m->m_flags & M_WEP)
- sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
- bpf_mtap2(ifp->if_bpf, &sc->sc_rx_th, sc->sc_rx_th_len, m);
+ tap->wr_flags |= IEEE80211_RADIOTAP_F_WEP;
+ tap->wr_antsignal = rssi;
+ tap->wr_antnoise = nf;
}
/* synchronize driver's BSSID with firmware's BSSID */
@@ -1416,10 +1403,10 @@ wi_rx_intr(struct wi_softc *sc)
ni = ieee80211_find_rxnode(ic, mtod(m, struct ieee80211_frame_min *));
if (ni != NULL) {
- (void) ieee80211_input(ni, m, rssi, -95/*XXX*/, rstamp);
+ (void) ieee80211_input(ni, m, rssi, nf);
ieee80211_free_node(ni);
} else
- (void) ieee80211_input_all(ic, m, rssi, -95/*XXX*/, rstamp);
+ (void) ieee80211_input_all(ic, m, rssi, nf);
WI_LOCK(sc);
}
@@ -1615,6 +1602,20 @@ wi_update_mcast(struct ifnet *ifp)
}
static void
+wi_update_promisc(struct ifnet *ifp)
+{
+ struct wi_softc *sc = ifp->if_softc;
+ struct ieee80211com *ic = ifp->if_l2com;
+
+ WI_LOCK(sc);
+ /* XXX handle WEP special case handling? */
+ wi_write_val(sc, WI_RID_PROMISC,
+ (ic->ic_opmode == IEEE80211_M_MONITOR ||
+ (ifp->if_flags & IFF_PROMISC)));
+ WI_UNLOCK(sc);
+}
+
+static void
wi_read_nicid(struct wi_softc *sc)
{
struct wi_card_ident *id;
diff --git a/sys/dev/wi/if_wireg.h b/sys/dev/wi/if_wireg.h
index 176e4a0..d99e597 100644
--- a/sys/dev/wi/if_wireg.h
+++ b/sys/dev/wi/if_wireg.h
@@ -691,7 +691,8 @@ struct wi_frame {
* Radio capture format for Prism.
*/
#define WI_RX_RADIOTAP_PRESENT \
- ((1 << IEEE80211_RADIOTAP_FLAGS) | \
+ ((1 << IEEE80211_RADIOTAP_TSFT) | \
+ (1 << IEEE80211_RADIOTAP_FLAGS) | \
(1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_CHANNEL) | \
(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) | \
@@ -699,6 +700,7 @@ struct wi_frame {
struct wi_rx_radiotap_header {
struct ieee80211_radiotap_header wr_ihdr;
+ u_int64_t wr_tsf;
u_int8_t wr_flags;
u_int8_t wr_rate;
u_int16_t wr_chan_freq;
diff --git a/sys/dev/wi/if_wivar.h b/sys/dev/wi/if_wivar.h
index 3739a8e..c5bc139 100644
--- a/sys/dev/wi/if_wivar.h
+++ b/sys/dev/wi/if_wivar.h
@@ -60,8 +60,8 @@ struct wi_vap {
struct ieee80211vap wv_vap;
struct ieee80211_beacon_offsets wv_bo;
- void (*wv_recv_mgmt)(struct ieee80211_node *,
- struct mbuf *, int, int, int, u_int32_t);
+ void (*wv_recv_mgmt)(struct ieee80211_node *, struct mbuf *,
+ int, int, int);
int (*wv_newstate)(struct ieee80211vap *,
enum ieee80211_state, int);
};
@@ -141,9 +141,7 @@ struct wi_softc {
u_int16_t sc_txbuf[IEEE80211_MAX_LEN/2];
struct wi_tx_radiotap_header sc_tx_th;
- int sc_tx_th_len;
struct wi_rx_radiotap_header sc_rx_th;
- int sc_rx_th_len;
};
/* maximum consecutive false change-of-BSSID indications */
OpenPOWER on IntegriCloud