From 5c5f8f488cf34cef8cab1e8aa770cb60ac00e7cc Mon Sep 17 00:00:00 2001 From: dyoung Date: Fri, 16 Nov 2007 23:35:19 +0000 Subject: [PATCH] Accommodate the variety of RF front-ends when radiotapping frames: tap only RSSI when there is a Philips RF front-end. Tap both Barker lock quality and RSSI when there is any other RF front-end. Provide radiotap listeners a more complete picture of channel activity: in promiscuous mode, tap frames who do not pass the CRC32 check. Flag packets that were received with a short preamble. Ask the NIC to pass us 802.11 Control frames. Pass frames to radiotap listeners before stripping the FCS. Re-order operations in rtw_intr_rx() in order to accomplish all of this, taking care not to pass a broken packet to net80211! Do not provide a flags field when tapping xmitted frames. Assert sane Rx packet lengths. Really should check and drop instead of KASSERTing. I will revisit this, soon. Update copyright. --- sys/dev/ic/rtw.c | 66 ++++++++++++++++++++++++++++++--------------- sys/dev/ic/rtwreg.h | 3 ++- sys/dev/ic/rtwvar.h | 32 +++++++++++++++------- 3 files changed, 69 insertions(+), 32 deletions(-) diff --git a/sys/dev/ic/rtw.c b/sys/dev/ic/rtw.c index b5fccda8e4c9..24dccfec2303 100644 --- a/sys/dev/ic/rtw.c +++ b/sys/dev/ic/rtw.c @@ -1,6 +1,7 @@ -/* $NetBSD: rtw.c,v 1.92 2007/11/15 22:55:50 dyoung Exp $ */ +/* $NetBSD: rtw.c,v 1.93 2007/11/16 23:35:19 dyoung Exp $ */ /*- - * Copyright (c) 2004, 2005 David Young. All rights reserved. + * Copyright (c) 2004, 2005, 2006, 2007 David Young. All rights + * reserved. * * Programmed for NetBSD by David Young. * @@ -34,7 +35,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: rtw.c,v 1.92 2007/11/15 22:55:50 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rtw.c,v 1.93 2007/11/16 23:35:19 dyoung Exp $"); #include "bpfilter.h" @@ -1450,7 +1451,7 @@ rtw_intr_rx(struct rtw_softc *sc, uint16_t isr) for (next = rdb->rdb_next; ; next = rdb->rdb_next) { KASSERT(next < rdb->rdb_ndesc); - + rtw_rxdescs_sync(rdb, next, 1, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); rd = &rdb->rdb_desc[next]; @@ -1517,9 +1518,8 @@ rtw_intr_rx(struct rtw_softc *sc, uint16_t isr) sc->sc_ic.ic_stats.is_rx_tooshort++; goto next; } - - /* CRC is included with the packet; trim it off. */ - len -= IEEE80211_CRC_LEN; + KASSERT(len <= m->m_pkthdr.len); + KASSERT(len <= m->m_len); hwrate = __SHIFTOUT(hstat, RTW_RXSTAT_RATE_MASK); if (hwrate >= __arraycount(ratetbl)) { @@ -1537,10 +1537,6 @@ rtw_intr_rx(struct rtw_softc *sc, uint16_t isr) (rate * 5) % 10, htsfth, htsftl)); #endif /* RTW_DEBUG */ - if ((hstat & RTW_RXSTAT_RES) != 0 && - sc->sc_ic.ic_opmode != IEEE80211_M_MONITOR) - goto next; - /* if bad flags, skip descriptor */ if ((hstat & RTW_RXSTAT_ONESEG) != RTW_RXSTAT_ONESEG) { printf("%s: too many rx segments, " @@ -1568,8 +1564,10 @@ rtw_intr_rx(struct rtw_softc *sc, uint16_t isr) sc->sc_dev.dv_xname); } + sq = __SHIFTOUT(hrssi, RTW_RXRSSI_SQ); + if (sc->sc_rfchipid == RTW_RFCHIPID_PHILIPS) - rssi = __SHIFTOUT(hrssi, RTW_RXRSSI_RSSI); + rssi = UINT8_MAX - sq; else { rssi = __SHIFTOUT(hrssi, RTW_RXRSSI_IMR_RSSI); /* TBD find out each front-end's LNA gain in the @@ -1578,7 +1576,6 @@ rtw_intr_rx(struct rtw_softc *sc, uint16_t isr) if ((hrssi & RTW_RXRSSI_IMR_LNA) == 0) rssi |= 0x80; } - sq = __SHIFTOUT(hrssi, RTW_RXRSSI_SQ); /* Note well: now we cannot recycle the rs_mbuf unless * we restore its original length. @@ -1590,8 +1587,6 @@ rtw_intr_rx(struct rtw_softc *sc, uint16_t isr) if (!IS_BEACON(wh->i_fc[0])) sc->sc_led_state.ls_event |= RTW_LED_S_RX; - /* TBD use _MAR, _BAR, _PAR flags as hints to _find_rxnode? */ - ni = ieee80211_find_rxnode(&sc->sc_ic, wh); sc->sc_tsfth = htsfth; @@ -1610,19 +1605,38 @@ rtw_intr_rx(struct rtw_softc *sc, uint16_t isr) rr->rr_tsft = htole64(((uint64_t)htsfth << 32) | htsftl); + rr->rr_flags = IEEE80211_RADIOTAP_F_FCS; + if ((hstat & RTW_RXSTAT_SPLCP) != 0) - rr->rr_flags = IEEE80211_RADIOTAP_F_SHORTPRE; + rr->rr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; + if ((hstat & RTW_RXSTAT_CRC32) != 0) + rr->rr_flags |= IEEE80211_RADIOTAP_F_BADFCS; - rr->rr_flags = 0; rr->rr_rate = rate; - rr->rr_antsignal = rssi; - rr->rr_barker_lock = htole16(sq); - bpf_mtap2(sc->sc_radiobpf, (void *)rr, + if (sc->sc_rfchipid == RTW_RFCHIPID_PHILIPS) + rr->rr_u.u_philips.p_antsignal = rssi; + else { + rr->rr_u.u_other.o_antsignal = rssi; + rr->rr_u.u_other.o_barker_lock = + htole16(UINT8_MAX - sq); + } + + bpf_mtap2(sc->sc_radiobpf, rr, sizeof(sc->sc_rxtapu), m); } #endif /* NBPFILTER > 0 */ + if ((hstat & RTW_RXSTAT_RES) != 0) { + m_freem(m); + goto next; + } + + /* CRC is included with the packet; trim it off. */ + m_adj(m, -IEEE80211_CRC_LEN); + + /* TBD use _MAR, _BAR, _PAR flags as hints to _find_rxnode? */ + ni = ieee80211_find_rxnode(&sc->sc_ic, wh); ieee80211_input(&sc->sc_ic, m, ni, rssi, htsftl); ieee80211_free_node(ni); next: @@ -2626,6 +2640,8 @@ rtw_pktfilt_load(struct rtw_softc *sc) if (ifp->if_flags & IFF_PROMISC) { sc->sc_rcr |= RTW_RCR_AB; /* accept all broadcast */ + sc->sc_rcr |= RTW_RCR_ACRC32; /* accept frames failing CRC */ + sc->sc_rcr |= RTW_RCR_AICV; /* accept frames failing ICV */ ifp->if_flags |= IFF_ALLMULTI; } @@ -3332,7 +3348,6 @@ rtw_start(struct ifnet *ifp) if (sc->sc_radiobpf != NULL) { struct rtw_tx_radiotap_header *rt = &sc->sc_txtap; - rt->rt_flags = 0; rt->rt_rate = rate; bpf_mtap2(sc->sc_radiobpf, (void *)rt, @@ -3816,9 +3831,16 @@ rtw_disestablish_hooks(struct rtw_hooks *hooks, const char *dvname, static inline void rtw_init_radiotap(struct rtw_softc *sc) { + uint32_t present; + memset(&sc->sc_rxtapu, 0, sizeof(sc->sc_rxtapu)); sc->sc_rxtap.rr_ihdr.it_len = htole16(sizeof(sc->sc_rxtapu)); - sc->sc_rxtap.rr_ihdr.it_present = htole32(RTW_RX_RADIOTAP_PRESENT); + + if (sc->sc_rfchipid == RTW_RFCHIPID_PHILIPS) + present = htole32(RTW_PHILIPS_RX_RADIOTAP_PRESENT); + else + present = htole32(RTW_RX_RADIOTAP_PRESENT); + sc->sc_rxtap.rr_ihdr.it_present = present; memset(&sc->sc_txtapu, 0, sizeof(sc->sc_txtapu)); sc->sc_txtap.rt_ihdr.it_len = htole16(sizeof(sc->sc_txtapu)); diff --git a/sys/dev/ic/rtwreg.h b/sys/dev/ic/rtwreg.h index 0df509b6fc6f..af4489e98078 100644 --- a/sys/dev/ic/rtwreg.h +++ b/sys/dev/ic/rtwreg.h @@ -1,4 +1,4 @@ -/* $NetBSD: rtwreg.h,v 1.23 2007/01/06 08:27:53 dyoung Exp $ */ +/* $NetBSD: rtwreg.h,v 1.24 2007/11/16 23:35:19 dyoung Exp $ */ /*- * Copyright (c) 2004, 2005 David Young. All rights reserved. * @@ -283,6 +283,7 @@ /* Receive power-management frames and mgmt/ctrl/data frames. */ #define RTW_RCR_PKTFILTER_DEFAULT ( \ + RTW_RCR_ACF | \ RTW_RCR_ADF | \ RTW_RCR_AMF | \ RTW_RCR_APM | \ diff --git a/sys/dev/ic/rtwvar.h b/sys/dev/ic/rtwvar.h index e38b45a6fb92..4e79273a9e57 100644 --- a/sys/dev/ic/rtwvar.h +++ b/sys/dev/ic/rtwvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: rtwvar.h,v 1.31 2007/03/04 06:02:01 christos Exp $ */ +/* $NetBSD: rtwvar.h,v 1.32 2007/11/16 23:35:19 dyoung Exp $ */ /*- * Copyright (c) 2004, 2005 David Young. All rights reserved. * @@ -236,27 +236,41 @@ struct rtw_descs { (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) | \ 0) +#define RTW_PHILIPS_RX_RADIOTAP_PRESENT \ + ((1 << IEEE80211_RADIOTAP_TSFT) | \ + (1 << IEEE80211_RADIOTAP_FLAGS) | \ + (1 << IEEE80211_RADIOTAP_RATE) | \ + (1 << IEEE80211_RADIOTAP_CHANNEL) | \ + (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) | \ + 0) + struct rtw_rx_radiotap_header { struct ieee80211_radiotap_header rr_ihdr; uint64_t rr_tsft; - uint8_t rr_flags; - uint8_t rr_rate; + uint8_t rr_flags; + uint8_t rr_rate; uint16_t rr_chan_freq; uint16_t rr_chan_flags; - uint16_t rr_barker_lock; - uint8_t rr_antsignal; + union { + struct { + uint16_t o_barker_lock; + uint8_t o_antsignal; + } u_other; + struct { + uint8_t p_antsignal; + } u_philips; + } rr_u; } __attribute__((__packed__)); #define RTW_TX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_RATE) | \ + ((1 << IEEE80211_RADIOTAP_RATE) | \ (1 << IEEE80211_RADIOTAP_CHANNEL) | \ 0) struct rtw_tx_radiotap_header { struct ieee80211_radiotap_header rt_ihdr; - uint8_t rt_flags; - uint8_t rt_rate; + uint8_t rt_rate; + uint8_t rt_pad; uint16_t rt_chan_freq; uint16_t rt_chan_flags; } __attribute__((__packed__));