Date: Tue, 28 Jun 2011 10:55:38 +0800 From: Adrian Chadd <adrian@freebsd.org> To: freebsd-wireless@freebsd.org Subject: [PATCH] ath: enforce beacon expect when going CAC -> RUN Message-ID: <BANLkTi=0qkdy9yG46DT2U5ez=Ww=ScMkcw@mail.gmail.com>
index | next in thread | raw e-mail
[-- Attachment #1 --]
Hi,
Here's an initial patch for ath(4) to work around one of the DFS / CAC
issues in my previous post.
It enforces a 60 (+ 1) second "beacon expect" timer when the station
goes from CSA -> RUN.
This forces the beacon configuration to be re-written if a beacon
hasn't been heard by then.
If a beacon is received, it clears the callback.
What I don't like about it:
* CAC is hard-coded to 60 seconds here. It should yank the config from
net80211, but the net80211 NOL/CAC configuration values are static.
* 'stamode' doesn't include MBSS (mesh) and needs some testing. I'll
likely add a comment to that effect so it gets revisited when
IBSS/MBSS DFS support is written/tested.
* I think this belongs in net80211 rather than ath(4) so it can work
for any wireless NIC which participates in a DFS BSS. (The NIC doesn't
have to radar detection, it just has to receive/process a CSA and
change channel.) I'll revisit that at a later date once all the kinks
are worked out with ath(4).
Thanks,
Adrian
[-- Attachment #2 --]
Index: if_athvar.h
===================================================================
--- if_athvar.h (revision 223525)
+++ if_athvar.h (working copy)
@@ -254,7 +254,8 @@
sc_tdma : 1,/* TDMA in use */
sc_setcca : 1,/* set/clr CCA with TDMA */
sc_resetcal : 1,/* reset cal state next trip */
- sc_rxslink : 1;/* do self-linked final descriptor */
+ sc_rxslink : 1,/* do self-linked final descriptor */
+ sc_bexpect : 1;/* expecting becaons to be RXed */
uint32_t sc_eerd; /* regdomain from EEPROM */
uint32_t sc_eecc; /* country code from EEPROM */
/* rate tables */
@@ -358,6 +359,8 @@
int sc_txchainmask; /* currently configured TX chainmask */
int sc_rxchainmask; /* currently configured RX chainmask */
+ struct callout sc_bexpect_ch; /* beacon expect callout */
+
/* DFS related state */
void *sc_dfs; /* Used by an optional DFS module */
int sc_dodfs; /* Whether to enable DFS rx filter bits */
Index: if_ath.c
===================================================================
--- if_ath.c (revision 223568)
+++ if_ath.c (working copy)
@@ -184,6 +184,8 @@
static void ath_scan_start(struct ieee80211com *);
static void ath_scan_end(struct ieee80211com *);
static void ath_set_channel(struct ieee80211com *);
+static void ath_beacon_expect_reset(struct ath_softc *sc);
+static void ath_beacon_expect_schedule(struct ath_softc *sc, int when);
static void ath_calibrate(void *);
static int ath_newstate(struct ieee80211vap *, enum ieee80211_state, int);
static void ath_setup_stationkey(struct ieee80211_node *);
@@ -387,6 +389,7 @@
}
callout_init_mtx(&sc->sc_cal_ch, &sc->sc_mtx, 0);
callout_init_mtx(&sc->sc_wd_ch, &sc->sc_mtx, 0);
+ callout_init_mtx(&sc->sc_bexpect_ch, &sc->sc_mtx, 0);
ATH_TXBUF_LOCK_INIT(sc);
@@ -2746,6 +2749,9 @@
u_int32_t nexttbtt, intval, tsftu;
u_int64_t tsf;
+ /* Clear any pending beacon expect timer */
+ ath_beacon_expect_reset(sc);
+
if (vap == NULL)
vap = TAILQ_FIRST(&ic->ic_vaps); /* XXX */
ni = vap->iv_bss;
@@ -4666,6 +4672,58 @@
}
/*
+ * A beacon hasn't been heard in the given timeframe;
+ * write the last known beacon config to the hardware
+ * so beacon miss events begin occuring again.
+ */
+static void
+ath_beacon_expect(void *arg)
+{
+ struct ath_softc *sc = (struct ath_softc *) arg;
+ sc->sc_bexpect = 0;
+ DPRINTF(sc, ATH_DEBUG_BEACON, "%s: beacons not seen, kick!\n", __func__);
+ ath_beacon_config(sc, NULL);
+}
+
+/*
+ * Clear the beacon expect callout.
+ */
+static void
+ath_beacon_expect_reset(struct ath_softc *sc)
+{
+ if (! sc->sc_bexpect)
+ return;
+ sc->sc_bexpect = 0;
+ DPRINTF(sc, ATH_DEBUG_BEACON, "%s: clearing beacon expect\n", __func__);
+ callout_drain(&sc->sc_bexpect_ch);
+}
+
+/*
+ * Expect beacons in 'when' seconds.
+ *
+ * If they don't occur, begin the process of signalling
+ * the upper levels that beacons are being missed.
+ *
+ * This is done for now by simply writing the beacon config
+ * and letting the bmiss timer/interrupt handle things.
+ */
+static void
+ath_beacon_expect_schedule(struct ath_softc *sc, int when)
+{
+ sc->sc_bexpect = 1;
+ DPRINTF(sc, ATH_DEBUG_BEACON,
+ "%s: scheduling beacon config in %d seconds\n",
+ __func__, when);
+ callout_drain(&sc->sc_bexpect_ch);
+ /*
+ * Add 1 second to 'when' to ensure the hostap actually
+ * starts transmitting.
+ */
+ callout_reset(&sc->sc_bexpect_ch, (when + 1) * hz,
+ ath_beacon_expect, sc);
+}
+
+/*
* Walk the vap list and check if there any vap's in RUN state.
*/
static int
@@ -4748,6 +4806,28 @@
}
/*
+ * If there's been a state transition from CSA -> RUN,
+ * start a task to force reset the beacon timers
+ * after CAC (default to 60 seconds.) Do this for non-
+ * hostap modes.
+ *
+ * If we don't begin hearing beacons by then, we need
+ * start registering beacon misses with net80211 or
+ * rescanning won't occur and the interface will sit
+ * here forever.
+ *
+ * XXX this requires that an association actually
+ * XXX occured sometime in the past!
+ */
+ if (stamode && vap->iv_state == IEEE80211_S_CSA &&
+ nstate == IEEE80211_S_RUN) {
+ DPRINTF(sc, ATH_DEBUG_STATE | ATH_DEBUG_BEACON,
+ "%s: CSA->RUN detected; expecting beacons to appear"
+ " in 60 seconds\n", __func__);
+ ath_beacon_expect_schedule(sc, 60); /* XXX hard-coded CAC */
+ }
+
+ /*
* Invoke the parent method to do net80211 work.
*/
error = avp->av_newstate(vap, nstate, arg);
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?BANLkTi=0qkdy9yG46DT2U5ez=Ww=ScMkcw>
