diff options
author | Sam Leffler <sam@FreeBSD.org> | 2006-01-09 17:13:20 +0000 |
---|---|---|
committer | Sam Leffler <sam@FreeBSD.org> | 2006-01-09 17:13:20 +0000 |
commit | 7b0c77eca9b0325f01b5c1eaa7888ab259e78911 (patch) | |
tree | 15a9aad7149918659a911fa33a19daf9b45f3557 /sys/dev/ath/if_ath.c | |
parent | 2204bcfd7cb4bfdff94512f42b328ebcdfc80b18 (diff) | |
download | src-7b0c77eca9b0325f01b5c1eaa7888ab259e78911.tar.gz src-7b0c77eca9b0325f01b5c1eaa7888ab259e78911.zip |
Update monitoring support:
o record tsf in tx+rx frames
o switch from raw rssi to dbm for signal data and record both
signal and noise floor data (hacked for now to assume a fixed
noise floor; is correct with new hal)
o add monpass sysctl to control which rx'd frames are passed
up with errors; especially useful to see frames with CRC errors
o mark 'd packets w/ a CRC error with radiotap's BADFCS flag
Also add placeholder code for calibrating the noise floor when
using newer hals.
Reviewed by: avatar
MFC after: 1 week
Notes
Notes:
svn path=/head/; revision=154140
Diffstat (limited to 'sys/dev/ath/if_ath.c')
-rw-r--r-- | sys/dev/ath/if_ath.c | 112 |
1 files changed, 76 insertions, 36 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 6e92a0592d2e..c8149470bf0a 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -2540,14 +2540,11 @@ ath_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf) /* * Extend 15-bit time stamp from rx descriptor to - * a full 64-bit TSF using the current h/w TSF. + * a full 64-bit TSF using the specified TSF. */ static __inline u_int64_t -ath_extend_tsf(struct ath_hal *ah, u_int32_t rstamp) +ath_extend_tsf(u_int32_t rstamp, u_int64_t tsf) { - u_int64_t tsf; - - tsf = ath_hal_gettsf64(ah); if ((tsf & 0x7fff) < rstamp) tsf -= 0x8000; return ((tsf &~ 0x7fff) | rstamp); @@ -2577,7 +2574,8 @@ ath_recv_mgmt(struct ieee80211com *ic, struct mbuf *m, case IEEE80211_FC0_SUBTYPE_PROBE_RESP: if (ic->ic_opmode == IEEE80211_M_IBSS && ic->ic_state == IEEE80211_S_RUN) { - u_int64_t tsf = ath_extend_tsf(sc->sc_ah, rstamp); + u_int64_t tsf = ath_extend_tsf(rstamp, + ath_hal_gettsf64(sc->sc_ah)); /* * Handle ibss merge as needed; check the tsf on the * frame before attempting the merge. The 802.11 spec @@ -2616,6 +2614,40 @@ ath_setdefantenna(struct ath_softc *sc, u_int antenna) sc->sc_rxotherant = 0; } +static int +ath_rx_tap(struct ath_softc *sc, struct mbuf *m, + const struct ath_desc *ds, u_int64_t tsf, int16_t nf) +{ + u_int8_t rix; + + KASSERT(sc->sc_drvbpf != NULL, ("no tap")); + + /* + * Discard anything shorter than an ack or cts. + */ + if (m->m_pkthdr.len < IEEE80211_ACK_LEN) { + DPRINTF(sc, ATH_DEBUG_RECV, "%s: runt packet %d\n", + __func__, m->m_pkthdr.len); + sc->sc_stats.ast_rx_tooshort++; + return 0; + } + sc->sc_rx_th.wr_tsf = htole64( + ath_extend_tsf(ds->ds_rxstat.rs_tstamp, tsf)); + rix = ds->ds_rxstat.rs_rate; + sc->sc_rx_th.wr_flags = sc->sc_hwmap[rix].rxflags; + if (ds->ds_rxstat.rs_status & HAL_RXERR_CRC) + sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_BADFCS; + /* XXX propagate other error flags from descriptor */ + sc->sc_rx_th.wr_rate = sc->sc_hwmap[rix].ieeerate; + sc->sc_rx_th.wr_antsignal = ds->ds_rxstat.rs_rssi + nf; + sc->sc_rx_th.wr_antnoise = nf; + sc->sc_rx_th.wr_antenna = ds->ds_rxstat.rs_antenna; + + bpf_mtap2(sc->sc_drvbpf, &sc->sc_rx_th, sc->sc_rx_th_len, m); + + return 1; +} + static void ath_rx_proc(void *arg, int npending) { @@ -2634,10 +2666,14 @@ ath_rx_proc(void *arg, int npending) int len, type; u_int phyerr; HAL_STATUS status; + int16_t nf; + u_int64_t tsf; NET_LOCK_GIANT(); /* XXX */ DPRINTF(sc, ATH_DEBUG_RX_PROC, "%s: pending %u\n", __func__, npending); + nf = ath_hal_getchannoise(ah, &sc->sc_curchan); + tsf = ath_hal_gettsf64(ah); do { bf = STAILQ_FIRST(&sc->sc_rxbuf); if (bf == NULL) { /* NB: shouldn't happen */ @@ -2735,14 +2771,22 @@ ath_rx_proc(void *arg, int npending) } ifp->if_ierrors++; /* - * Reject error frames, we normally don't want - * to see them in monitor mode (in monitor mode - * allow through packets that have crypto problems). + * When a tap is present pass error frames + * that have been requested. By default we + * pass decrypt+mic errors but others may be + * interesting (e.g. crc). */ - if ((ds->ds_rxstat.rs_status &~ - (HAL_RXERR_DECRYPT|HAL_RXERR_MIC)) || - sc->sc_ic.ic_opmode != IEEE80211_M_MONITOR) - goto rx_next; + if (sc->sc_drvbpf != NULL && + (ds->ds_rxstat.rs_status & sc->sc_monpass)) { + bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, + BUS_DMASYNC_POSTREAD); + /* NB: bpf needs the mbuf length setup */ + len = ds->ds_rxstat.rs_datalen; + m->m_pkthdr.len = m->m_len = len; + (void) ath_rx_tap(sc, m, ds, tsf, nf); + } + /* XXX pass MIC errors up for s/w reclaculation */ + goto rx_next; } rx_accept: /* @@ -2763,29 +2807,9 @@ rx_accept: sc->sc_stats.ast_ant_rx[ds->ds_rxstat.rs_antenna]++; - if (sc->sc_drvbpf) { - u_int8_t rix; - - /* - * Discard anything shorter than an ack or cts. - */ - if (len < IEEE80211_ACK_LEN) { - DPRINTF(sc, ATH_DEBUG_RECV, - "%s: runt packet %d\n", - __func__, len); - sc->sc_stats.ast_rx_tooshort++; - m_freem(m); - goto rx_next; - } - rix = ds->ds_rxstat.rs_rate; - sc->sc_rx_th.wr_flags = sc->sc_hwmap[rix].rxflags; - sc->sc_rx_th.wr_rate = sc->sc_hwmap[rix].ieeerate; - sc->sc_rx_th.wr_antsignal = ds->ds_rxstat.rs_rssi; - sc->sc_rx_th.wr_antenna = ds->ds_rxstat.rs_antenna; - /* XXX TSF */ - - bpf_mtap2(sc->sc_drvbpf, - &sc->sc_rx_th, sc->sc_rx_th_len, m); + if (sc->sc_drvbpf != NULL && !ath_rx_tap(sc, m, ds, tsf, nf)) { + m_freem(m); /* XXX reclaim */ + goto rx_next; } /* @@ -3442,6 +3466,9 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf if (ic->ic_rawbpf) bpf_mtap(ic->ic_rawbpf, m0); if (sc->sc_drvbpf) { + u_int64_t tsf = ath_hal_gettsf64(ah); + + sc->sc_tx_th.wt_tsf = htole64(tsf); sc->sc_tx_th.wt_flags = sc->sc_hwmap[txrate].txflags; if (iswep) sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP; @@ -4024,6 +4051,10 @@ ath_calibrate(void *arg) __func__, sc->sc_curchan.channel); sc->sc_stats.ast_per_calfail++; } + /* + * Calibrate noise floor data again in case of change. + */ + ath_hal_process_noisefloor(ah); callout_reset(&sc->sc_cal_ch, ath_calinterval * hz, ath_calibrate, sc); } @@ -4139,6 +4170,11 @@ ath_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) } /* + * Let the hal process statistics collected during a + * scan so it can provide calibrated noise floor data. + */ + ath_hal_process_noisefloor(ah); + /* * Configure the beacon and sleep timers. */ ath_beacon_config(sc); @@ -4861,6 +4897,10 @@ ath_sysctlattach(struct ath_softc *sc) SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "tpc", CTLTYPE_INT | CTLFLAG_RW, sc, 0, ath_sysctl_tpc, "I", "enable/disable per-packet TPC"); + sc->sc_monpass = HAL_RXERR_DECRYPT | HAL_RXERR_MIC; + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "monpass", CTLFLAG_RW, &sc->sc_monpass, 0, + "mask of error frames to pass when monitoring"); } static void |