Maintain a history of data associated with received frames and use this to
calculate smoothed signal quality data for each node. o add a 16-deep history buffer to each driver-private node storage that holds rssi and antenna info for received frames o override the default per-node "get rssi" method to return an average rssi value based on samples collected over the last second o enable beacon reception so even idle systems maintain a running history of signal quality This data may also be useful for improving the rate control algorithm. Based on work by Tom Marshall <tommy@home.tig-grr.com> for MADWIFI.
This commit is contained in:
parent
d1e61976a0
commit
de5af70460
@ -114,6 +114,8 @@ static struct ieee80211_node *ath_node_alloc(struct ieee80211com *);
|
|||||||
static void ath_node_free(struct ieee80211com *, struct ieee80211_node *);
|
static void ath_node_free(struct ieee80211com *, struct ieee80211_node *);
|
||||||
static void ath_node_copy(struct ieee80211com *,
|
static void ath_node_copy(struct ieee80211com *,
|
||||||
struct ieee80211_node *, const struct ieee80211_node *);
|
struct ieee80211_node *, const struct ieee80211_node *);
|
||||||
|
static u_int8_t ath_node_getrssi(struct ieee80211com *,
|
||||||
|
struct ieee80211_node *);
|
||||||
static int ath_rxbuf_init(struct ath_softc *, struct ath_buf *);
|
static int ath_rxbuf_init(struct ath_softc *, struct ath_buf *);
|
||||||
static void ath_rx_proc(void *, int);
|
static void ath_rx_proc(void *, int);
|
||||||
static int ath_tx_start(struct ath_softc *, struct ieee80211_node *,
|
static int ath_tx_start(struct ath_softc *, struct ieee80211_node *,
|
||||||
@ -290,6 +292,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
|
|||||||
ic->ic_node_alloc = ath_node_alloc;
|
ic->ic_node_alloc = ath_node_alloc;
|
||||||
ic->ic_node_free = ath_node_free;
|
ic->ic_node_free = ath_node_free;
|
||||||
ic->ic_node_copy = ath_node_copy;
|
ic->ic_node_copy = ath_node_copy;
|
||||||
|
ic->ic_node_getrssi = ath_node_getrssi;
|
||||||
sc->sc_newstate = ic->ic_newstate;
|
sc->sc_newstate = ic->ic_newstate;
|
||||||
ic->ic_newstate = ath_newstate;
|
ic->ic_newstate = ath_newstate;
|
||||||
/* complete initialization */
|
/* complete initialization */
|
||||||
@ -922,7 +925,8 @@ ath_mode_init(struct ath_softc *sc)
|
|||||||
if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
|
if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
|
||||||
(ifp->if_flags & IFF_PROMISC))
|
(ifp->if_flags & IFF_PROMISC))
|
||||||
rfilt |= HAL_RX_FILTER_PROM;
|
rfilt |= HAL_RX_FILTER_PROM;
|
||||||
if (ic->ic_state == IEEE80211_S_SCAN)
|
if (ic->ic_opmode == IEEE80211_M_STA ||
|
||||||
|
ic->ic_state == IEEE80211_S_SCAN)
|
||||||
rfilt |= HAL_RX_FILTER_BEACON;
|
rfilt |= HAL_RX_FILTER_BEACON;
|
||||||
ath_hal_setrxfilter(ah, rfilt);
|
ath_hal_setrxfilter(ah, rfilt);
|
||||||
|
|
||||||
@ -1387,7 +1391,14 @@ ath_node_alloc(struct ieee80211com *ic)
|
|||||||
{
|
{
|
||||||
struct ath_node *an =
|
struct ath_node *an =
|
||||||
malloc(sizeof(struct ath_node), M_DEVBUF, M_NOWAIT | M_ZERO);
|
malloc(sizeof(struct ath_node), M_DEVBUF, M_NOWAIT | M_ZERO);
|
||||||
return an ? &an->an_node : NULL;
|
if (an) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < ATH_RHIST_SIZE; i++)
|
||||||
|
an->an_rx_hist[i].arh_ticks = ATH_RHIST_NOTIME;
|
||||||
|
an->an_rx_hist_next = ATH_RHIST_SIZE-1;
|
||||||
|
return &an->an_node;
|
||||||
|
} else
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1410,6 +1421,41 @@ ath_node_copy(struct ieee80211com *ic,
|
|||||||
*(struct ath_node *)dst = *(const struct ath_node *)src;
|
*(struct ath_node *)dst = *(const struct ath_node *)src;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static u_int8_t
|
||||||
|
ath_node_getrssi(struct ieee80211com *ic, struct ieee80211_node *ni)
|
||||||
|
{
|
||||||
|
struct ath_node *an = ATH_NODE(ni);
|
||||||
|
int i, now, nsamples, rssi;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate the average over the last second of sampled data.
|
||||||
|
*/
|
||||||
|
now = ticks;
|
||||||
|
nsamples = 0;
|
||||||
|
rssi = 0;
|
||||||
|
i = an->an_rx_hist_next;
|
||||||
|
do {
|
||||||
|
struct ath_recv_hist *rh = &an->an_rx_hist[i];
|
||||||
|
if (rh->arh_ticks == ATH_RHIST_NOTIME)
|
||||||
|
goto done;
|
||||||
|
if (now - rh->arh_ticks > hz)
|
||||||
|
goto done;
|
||||||
|
rssi += rh->arh_rssi;
|
||||||
|
nsamples++;
|
||||||
|
if (i == 0)
|
||||||
|
i = ATH_RHIST_SIZE-1;
|
||||||
|
else
|
||||||
|
i--;
|
||||||
|
} while (i != an->an_rx_hist_next);
|
||||||
|
done:
|
||||||
|
/*
|
||||||
|
* Return either the average or the last known
|
||||||
|
* value if there is no recent data.
|
||||||
|
*/
|
||||||
|
return (nsamples ? rssi / nsamples : an->an_rx_hist[i].arh_rssi);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ath_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
|
ath_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
|
||||||
{
|
{
|
||||||
@ -1478,6 +1524,8 @@ ath_rx_proc(void *arg, int npending)
|
|||||||
struct mbuf *m;
|
struct mbuf *m;
|
||||||
struct ieee80211_frame *wh, whbuf;
|
struct ieee80211_frame *wh, whbuf;
|
||||||
struct ieee80211_node *ni;
|
struct ieee80211_node *ni;
|
||||||
|
struct ath_node *an;
|
||||||
|
struct ath_recv_hist *rh;
|
||||||
int len;
|
int len;
|
||||||
u_int phyerr;
|
u_int phyerr;
|
||||||
HAL_STATUS status;
|
HAL_STATUS status;
|
||||||
@ -1588,12 +1636,24 @@ ath_rx_proc(void *arg, int npending)
|
|||||||
ni = ieee80211_ref_node(ic->ic_bss);
|
ni = ieee80211_ref_node(ic->ic_bss);
|
||||||
} else
|
} else
|
||||||
ni = ieee80211_ref_node(ic->ic_bss);
|
ni = ieee80211_ref_node(ic->ic_bss);
|
||||||
ATH_NODE(ni)->an_rx_antenna = ds->ds_rxstat.rs_antenna;
|
|
||||||
|
/*
|
||||||
|
* Record driver-specific state.
|
||||||
|
*/
|
||||||
|
an = ATH_NODE(ni);
|
||||||
|
if (++(an->an_rx_hist_next) == ATH_RHIST_SIZE)
|
||||||
|
an->an_rx_hist_next = 0;
|
||||||
|
rh = &an->an_rx_hist[an->an_rx_hist_next];
|
||||||
|
rh->arh_ticks = ticks;
|
||||||
|
rh->arh_rssi = ds->ds_rxstat.rs_rssi;
|
||||||
|
rh->arh_antenna = ds->ds_rxstat.rs_antenna;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send frame up for processing.
|
* Send frame up for processing.
|
||||||
*/
|
*/
|
||||||
ieee80211_input(ifp, m, ni,
|
ieee80211_input(ifp, m, ni,
|
||||||
ds->ds_rxstat.rs_rssi, ds->ds_rxstat.rs_tstamp);
|
ds->ds_rxstat.rs_rssi, ds->ds_rxstat.rs_tstamp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The frame may have caused the node to be marked for
|
* The frame may have caused the node to be marked for
|
||||||
* reclamation (e.g. in response to a DEAUTH message)
|
* reclamation (e.g. in response to a DEAUTH message)
|
||||||
@ -1859,7 +1919,7 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf
|
|||||||
if (an->an_tx_antenna)
|
if (an->an_tx_antenna)
|
||||||
antenna = an->an_tx_antenna;
|
antenna = an->an_tx_antenna;
|
||||||
else
|
else
|
||||||
antenna = an->an_rx_antenna;
|
antenna = an->an_rx_hist[an->an_rx_hist_next].arh_antenna;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Formulate first tx descriptor with tx controls.
|
* Formulate first tx descriptor with tx controls.
|
||||||
@ -2288,11 +2348,13 @@ ath_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
|
|||||||
if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
|
if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
|
||||||
(ifp->if_flags & IFF_PROMISC))
|
(ifp->if_flags & IFF_PROMISC))
|
||||||
rfilt |= HAL_RX_FILTER_PROM;
|
rfilt |= HAL_RX_FILTER_PROM;
|
||||||
|
if (ic->ic_opmode == IEEE80211_M_STA ||
|
||||||
|
ic->ic_state == IEEE80211_S_SCAN)
|
||||||
|
rfilt |= HAL_RX_FILTER_BEACON;
|
||||||
if (nstate == IEEE80211_S_SCAN) {
|
if (nstate == IEEE80211_S_SCAN) {
|
||||||
callout_reset(&sc->sc_scan_ch, (hz * ath_dwelltime) / 1000,
|
callout_reset(&sc->sc_scan_ch, (hz * ath_dwelltime) / 1000,
|
||||||
ath_next_scan, sc);
|
ath_next_scan, sc);
|
||||||
bssid = ifp->if_broadcastaddr;
|
bssid = ifp->if_broadcastaddr;
|
||||||
rfilt |= HAL_RX_FILTER_BEACON;
|
|
||||||
} else {
|
} else {
|
||||||
callout_stop(&sc->sc_scan_ch);
|
callout_stop(&sc->sc_scan_ch);
|
||||||
bssid = ni->ni_bssid;
|
bssid = ni->ni_bssid;
|
||||||
|
@ -54,6 +54,14 @@
|
|||||||
#define ATH_TXBUF 60 /* number of TX buffers */
|
#define ATH_TXBUF 60 /* number of TX buffers */
|
||||||
#define ATH_TXDESC 8 /* number of descriptors per buffer */
|
#define ATH_TXDESC 8 /* number of descriptors per buffer */
|
||||||
|
|
||||||
|
struct ath_recv_hist {
|
||||||
|
int arh_ticks; /* sample time by system clock */
|
||||||
|
u_int8_t arh_rssi; /* rssi */
|
||||||
|
u_int8_t arh_antenna; /* antenna */
|
||||||
|
};
|
||||||
|
#define ATH_RHIST_SIZE 16 /* number of samples */
|
||||||
|
#define ATH_RHIST_NOTIME (~0)
|
||||||
|
|
||||||
/* driver-specific node */
|
/* driver-specific node */
|
||||||
struct ath_node {
|
struct ath_node {
|
||||||
struct ieee80211_node an_node; /* base class */
|
struct ieee80211_node an_node; /* base class */
|
||||||
@ -63,6 +71,8 @@ struct ath_node {
|
|||||||
int an_tx_upper; /* tx upper rate req cnt */
|
int an_tx_upper; /* tx upper rate req cnt */
|
||||||
u_int an_tx_antenna; /* antenna for last good frame */
|
u_int an_tx_antenna; /* antenna for last good frame */
|
||||||
u_int an_rx_antenna; /* antenna for last rcvd frame */
|
u_int an_rx_antenna; /* antenna for last rcvd frame */
|
||||||
|
struct ath_recv_hist an_rx_hist[ATH_RHIST_SIZE];
|
||||||
|
u_int an_rx_hist_next;/* index of next ``free entry'' */
|
||||||
};
|
};
|
||||||
#define ATH_NODE(_n) ((struct ath_node *)(_n))
|
#define ATH_NODE(_n) ((struct ath_node *)(_n))
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user