Radiotap fixups:
o catch one place where we were not using ath_chan_change to switch channels; this fixes a problem where the channel settings were not being correctly reported in captured packets o return unique channel identification in the channel flags; ethereal gets confused if you return merged flags (e.g. ofdm, cck, and 2Ghz) (this is workaround and should be removed if we can ever cleanup radiotap consumers) o correct short/long preamble flag state for rx and treat tx the same--use a new hwflags array that gives us the data based on the h/w rate index/cookie o add gross hack to handle radiotap capture of frames that come in with hardware padding; should be replaced by a flag in the radiotap header and more smarts in the apps that decode radiotap data
This commit is contained in:
parent
0ab4040a27
commit
16b4851a16
@ -821,7 +821,6 @@ ath_init(void *arg)
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = &sc->sc_if;
|
||||
struct ieee80211_node *ni;
|
||||
enum ieee80211_phymode mode;
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
HAL_STATUS status;
|
||||
|
||||
@ -893,9 +892,7 @@ ath_init(void *arg)
|
||||
*/
|
||||
ni = ic->ic_bss;
|
||||
ni->ni_chan = ic->ic_ibss_chan;
|
||||
mode = ieee80211_chan2mode(ic, ni->ni_chan);
|
||||
if (mode != sc->sc_curmode)
|
||||
ath_setcurmode(sc, mode);
|
||||
ath_chan_change(sc, ni->ni_chan);
|
||||
if (ic->ic_opmode != IEEE80211_M_MONITOR) {
|
||||
if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL)
|
||||
ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
|
||||
@ -2614,6 +2611,10 @@ ath_rx_proc(void *arg, int npending)
|
||||
sc->sc_stats.ast_ant_rx[ds->ds_rxstat.rs_antenna]++;
|
||||
|
||||
if (sc->sc_drvbpf) {
|
||||
const void *data;
|
||||
int hdrsize, hdrspace;
|
||||
u_int8_t rix;
|
||||
|
||||
/*
|
||||
* Discard anything shorter than an ack or cts.
|
||||
*/
|
||||
@ -2625,14 +2626,40 @@ ath_rx_proc(void *arg, int npending)
|
||||
m_freem(m);
|
||||
goto rx_next;
|
||||
}
|
||||
sc->sc_rx_th.wr_rate =
|
||||
sc->sc_hwmap[ds->ds_rxstat.rs_rate];
|
||||
rix = ds->ds_rxstat.rs_rate;
|
||||
sc->sc_rx_th.wr_flags = sc->sc_hwflags[rix];
|
||||
sc->sc_rx_th.wr_rate = sc->sc_hwmap[rix];
|
||||
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);
|
||||
/*
|
||||
* Gag, deal with hardware padding of headers. This
|
||||
* only happens for QoS frames. We copy the 802.11
|
||||
* header out-of-line and supply it separately, then
|
||||
* adjust the mbuf chain. It would be better if we
|
||||
* could just flag the packet in the radiotap header
|
||||
* and have applications DTRT.
|
||||
*/
|
||||
if (len > sizeof(struct ieee80211_qosframe)) {
|
||||
data = mtod(m, const void *);
|
||||
hdrsize = ieee80211_anyhdrsize(data);
|
||||
if (hdrsize & 3) {
|
||||
bcopy(data, &sc->sc_rx_wh, hdrsize);
|
||||
hdrspace = roundup(hdrsize,
|
||||
sizeof(u_int32_t));
|
||||
m->m_data += hdrspace;
|
||||
m->m_len -= hdrspace;
|
||||
bpf_mtap2(sc->sc_drvbpf, &sc->sc_rx,
|
||||
sc->sc_rx_rt_len + hdrsize, m);
|
||||
m->m_data -= hdrspace;
|
||||
m->m_len += hdrspace;
|
||||
} else
|
||||
bpf_mtap2(sc->sc_drvbpf,
|
||||
&sc->sc_rx, sc->sc_rx_rt_len, m);
|
||||
} else
|
||||
bpf_mtap2(sc->sc_drvbpf,
|
||||
&sc->sc_rx, sc->sc_rx_rt_len, m);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3194,12 +3221,10 @@ 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) {
|
||||
sc->sc_tx_th.wt_flags = 0;
|
||||
if (shortPreamble)
|
||||
sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
|
||||
sc->sc_tx_th.wt_flags = sc->sc_hwflags[txrate];
|
||||
if (iswep)
|
||||
sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
|
||||
sc->sc_tx_th.wt_rate = ni->ni_rates.rs_rates[ni->ni_txrate];
|
||||
sc->sc_tx_th.wt_rate = sc->sc_hwmap[txrate];
|
||||
sc->sc_tx_th.wt_txpower = ni->ni_txpower;
|
||||
sc->sc_tx_th.wt_antenna = sc->sc_txantenna;
|
||||
|
||||
@ -3649,6 +3674,7 @@ ath_chan_change(struct ath_softc *sc, struct ieee80211_channel *chan)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
enum ieee80211_phymode mode;
|
||||
u_int16_t flags;
|
||||
|
||||
/*
|
||||
* Change channels and update the h/w rate map
|
||||
@ -3658,12 +3684,23 @@ ath_chan_change(struct ath_softc *sc, struct ieee80211_channel *chan)
|
||||
if (mode != sc->sc_curmode)
|
||||
ath_setcurmode(sc, mode);
|
||||
/*
|
||||
* Update BPF state.
|
||||
* Update BPF state. NB: ethereal et. al. don't handle
|
||||
* merged flags well so pick a unique mode for their use.
|
||||
*/
|
||||
if (IEEE80211_IS_CHAN_A(chan))
|
||||
flags = IEEE80211_CHAN_A;
|
||||
/* XXX 11g schizophrenia */
|
||||
else if (IEEE80211_IS_CHAN_G(chan) ||
|
||||
IEEE80211_IS_CHAN_PUREG(chan))
|
||||
flags = IEEE80211_CHAN_G;
|
||||
else
|
||||
flags = IEEE80211_CHAN_B;
|
||||
if (IEEE80211_IS_CHAN_T(chan))
|
||||
flags |= IEEE80211_CHAN_TURBO;
|
||||
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);
|
||||
htole16(flags);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4066,10 +4103,15 @@ ath_setcurmode(struct ath_softc *sc, enum ieee80211_phymode 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));
|
||||
memset(sc->sc_hwflags, 0, sizeof(sc->sc_hwflags));
|
||||
for (i = 0; i < 32; i++) {
|
||||
u_int8_t ix = rt->rateCodeToIndex[i];
|
||||
if (ix != 0xff)
|
||||
sc->sc_hwmap[i] = rt->info[ix].dot11Rate & IEEE80211_RATE_VAL;
|
||||
if (ix == 0xff)
|
||||
continue;
|
||||
sc->sc_hwmap[i] = rt->info[ix].dot11Rate & IEEE80211_RATE_VAL;
|
||||
if (rt->info[ix].shortPreamble ||
|
||||
rt->info[ix].phy == IEEE80211_T_OFDM)
|
||||
sc->sc_hwflags[i] |= IEEE80211_RADIOTAP_F_SHORTPRE;
|
||||
}
|
||||
sc->sc_currates = rt;
|
||||
sc->sc_curmode = mode;
|
||||
@ -4488,8 +4530,8 @@ ath_bpfattach(struct ath_softc *sc)
|
||||
sc->sc_tx_th.wt_ihdr.it_len = htole16(sc->sc_tx_th_len);
|
||||
sc->sc_tx_th.wt_ihdr.it_present = htole32(ATH_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_rt_len = roundup(sizeof(sc->sc_rx_th), sizeof(u_int32_t));
|
||||
sc->sc_rx_th.wr_ihdr.it_len = htole16(sc->sc_rx_rt_len);
|
||||
sc->sc_rx_th.wr_ihdr.it_present = htole32(ATH_RX_RADIOTAP_PRESENT);
|
||||
}
|
||||
|
||||
|
@ -182,6 +182,7 @@ struct ath_softc {
|
||||
HAL_CHANNEL sc_curchan; /* current h/w channel */
|
||||
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 */
|
||||
u_int8_t sc_hwflags[32]; /* " " " to radiotap flags */
|
||||
u_int8_t sc_protrix; /* protection rate index */
|
||||
u_int sc_txantenna; /* tx antenna (fixed or auto) */
|
||||
HAL_INT sc_imask; /* interrupt mask copy */
|
||||
@ -199,10 +200,13 @@ struct ath_softc {
|
||||
} u_tx_rt;
|
||||
int sc_tx_th_len;
|
||||
union {
|
||||
struct ath_rx_radiotap_header th;
|
||||
struct {
|
||||
struct ath_rx_radiotap_header th;
|
||||
struct ieee80211_qosframe wh;
|
||||
} u;
|
||||
u_int8_t pad[64];
|
||||
} u_rx_rt;
|
||||
int sc_rx_th_len;
|
||||
int sc_rx_rt_len;
|
||||
|
||||
struct task sc_fataltask; /* fatal int processing */
|
||||
|
||||
@ -244,7 +248,9 @@ struct ath_softc {
|
||||
};
|
||||
#define sc_if sc_arp.ac_if
|
||||
#define sc_tx_th u_tx_rt.th
|
||||
#define sc_rx_th u_rx_rt.th
|
||||
#define sc_rx u_rx_rt.u
|
||||
#define sc_rx_th sc_rx.th
|
||||
#define sc_rx_wh sc_rx.wh
|
||||
|
||||
#define ATH_LOCK_INIT(_sc) \
|
||||
mtx_init(&(_sc)->sc_mtx, device_get_nameunit((_sc)->sc_dev), \
|
||||
|
Loading…
Reference in New Issue
Block a user