summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2003-09-15 22:34:46 +0000
committersam <sam@FreeBSD.org>2003-09-15 22:34:46 +0000
commit20b102f1376bc7f96a430b460df9cbb3df0cfd18 (patch)
tree0fe027a167306632c11f507b0bb7a829870c6b77
parentc9c933e78b7f78237d8012aa7fd7e0f113823c5a (diff)
downloadFreeBSD-src-20b102f1376bc7f96a430b460df9cbb3df0cfd18.zip
FreeBSD-src-20b102f1376bc7f96a430b460df9cbb3df0cfd18.tar.gz
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.
-rw-r--r--sys/dev/ath/if_ath.c72
-rw-r--r--sys/dev/ath/if_athvar.h10
2 files changed, 77 insertions, 5 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
index aab78c0..61a86e0 100644
--- a/sys/dev/ath/if_ath.c
+++ b/sys/dev/ath/if_ath.c
@@ -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_copy(struct ieee80211com *,
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 void ath_rx_proc(void *, int);
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_free = ath_node_free;
ic->ic_node_copy = ath_node_copy;
+ ic->ic_node_getrssi = ath_node_getrssi;
sc->sc_newstate = ic->ic_newstate;
ic->ic_newstate = ath_newstate;
/* complete initialization */
@@ -922,7 +925,8 @@ ath_mode_init(struct ath_softc *sc)
if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
(ifp->if_flags & IFF_PROMISC))
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;
ath_hal_setrxfilter(ah, rfilt);
@@ -1387,7 +1391,14 @@ ath_node_alloc(struct ieee80211com *ic)
{
struct ath_node *an =
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
@@ -1410,6 +1421,41 @@ ath_node_copy(struct ieee80211com *ic,
*(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
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 ieee80211_frame *wh, whbuf;
struct ieee80211_node *ni;
+ struct ath_node *an;
+ struct ath_recv_hist *rh;
int len;
u_int phyerr;
HAL_STATUS status;
@@ -1588,12 +1636,24 @@ ath_rx_proc(void *arg, int npending)
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;
+
+ /*
+ * 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.
*/
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)
@@ -1859,7 +1919,7 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf
if (an->an_tx_antenna)
antenna = an->an_tx_antenna;
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.
@@ -2288,11 +2348,13 @@ ath_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
(ifp->if_flags & IFF_PROMISC))
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) {
callout_reset(&sc->sc_scan_ch, (hz * ath_dwelltime) / 1000,
ath_next_scan, sc);
bssid = ifp->if_broadcastaddr;
- rfilt |= HAL_RX_FILTER_BEACON;
} else {
callout_stop(&sc->sc_scan_ch);
bssid = ni->ni_bssid;
diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h
index 73a7887..43578f4 100644
--- a/sys/dev/ath/if_athvar.h
+++ b/sys/dev/ath/if_athvar.h
@@ -54,6 +54,14 @@
#define ATH_TXBUF 60 /* number of TX buffers */
#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 */
struct ath_node {
struct ieee80211_node an_node; /* base class */
@@ -63,6 +71,8 @@ struct ath_node {
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 */
+ 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))
OpenPOWER on IntegriCloud