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>