PERFORCE change 77276 for review
Sam Leffler
sam at FreeBSD.org
Sun May 22 04:02:24 GMT 2005
http://perforce.freebsd.org/chv.cgi?CH=77276
Change 77276 by sam at sam_ebb on 2005/05/22 04:01:39
Working sta mode bg scanning (mostly):
o hide scan implementation details from scan policy modules by
making ic_scan a pointer to a struct that has public+private
sections
o move power save work out of policy code and into the core
o change policy scan_restart callback to be invoked when a bg
scan is restarted with the first entry in the channel list
o change scan canceling to mark a flag, reset the time to fire
immediately, and let the work be done in the timer context
o eliminate IEEE80211_SCAN_PWRSAV, check the actual node state
to see if we're in power save mode to avoid inconsistent state
now that other code is futzing with ps state
o clear IEEE80211_F_SCAN before dropping out of power save mode
so any null data frame passing through ieee80211_start doesn't
cause us to try and cancel a bg scan
o change sta policy code to purge cache entries when there's been
no traffic from the sta for 2 complete scans
Still need to tweak the bg scan scheduling to leave more room
to return on-channel for beacons. Also need to improve behaviour
when traffic preempts a bg scan.
Affected files ...
.. //depot/projects/vap/sys/net80211/ieee80211_scan.c#5 edit
.. //depot/projects/vap/sys/net80211/ieee80211_scan.h#3 edit
.. //depot/projects/vap/sys/net80211/ieee80211_scan_ap.c#4 edit
.. //depot/projects/vap/sys/net80211/ieee80211_scan_sta.c#6 edit
.. //depot/projects/vap/sys/net80211/ieee80211_var.h#14 edit
Differences ...
==== //depot/projects/vap/sys/net80211/ieee80211_scan.c#5 (text+ko) ====
@@ -50,29 +50,49 @@
#include <net80211/ieee80211_var.h>
-static void ieee80211_next_scan(void *arg);
+struct scan_state {
+ struct ieee80211_scan_state base; /* public state */
+
+ struct ieee80211_channel *ss_savchan; /* saved channel setting */
+ unsigned long ss_scanend; /* time scan must stop */
+ unsigned long ss_chanmindwell; /* " " " on curchan */
+ struct callout ss_scan_timer; /* scan timer */
+};
+#define SCAN_PRIVATE(ss) ((struct scan_state *) ss)
+
+static void scan_next(void *arg);
MALLOC_DEFINE(M_80211_SCAN, "80211scan", "802.11 scan state");
void
ieee80211_scan_attach(struct ieee80211com *ic)
{
- struct ieee80211_scan_state *ss = &ic->ic_scan;
+ struct scan_state *ss;
- callout_init(&ss->ss_scan_timer, CALLOUT_MPSAFE);
+ MALLOC(ss, struct scan_state *, sizeof(struct scan_state),
+ M_80211_SCAN, M_NOWAIT | M_ZERO);
+ if (ss != NULL) {
+ callout_init(&ss->ss_scan_timer, CALLOUT_MPSAFE);
+ ic->ic_scan = &ss->base;
+ } else
+ ic->ic_scan = NULL;
}
void
ieee80211_scan_detach(struct ieee80211com *ic)
{
- struct ieee80211_scan_state *ss = &ic->ic_scan;
+ struct ieee80211_scan_state *ss = ic->ic_scan;
- callout_drain(&ss->ss_scan_timer);
- if (ss->ss_ops != NULL) {
- ss->ss_ops->scan_detach(ss);
- ss->ss_ops = NULL;
+ if (ss != NULL) {
+ callout_drain(&SCAN_PRIVATE(ss)->ss_scan_timer);
+ if (ss->ss_ops != NULL) {
+ ss->ss_ops->scan_detach(ss);
+ ss->ss_ops = NULL;
+ }
+ ic->ic_flags &= ~IEEE80211_F_SCAN;
+ ic->ic_scan = NULL;
+ FREE(SCAN_PRIVATE(ss), M_80211_SCAN);
}
- ic->ic_flags &= ~IEEE80211_F_SCAN;
}
void
@@ -86,12 +106,12 @@
ieee80211_scan_vdetach(struct ieee80211vap *vap)
{
struct ieee80211com *ic = vap->iv_ic;
- struct ieee80211_scan_state *ss = &ic->ic_scan;
+ struct ieee80211_scan_state *ss = ic->ic_scan;
IEEE80211_LOCK(ic);
if (ss->ss_vap == vap) {
if (ic->ic_flags & IEEE80211_F_SCAN) {
- callout_drain(&ss->ss_scan_timer);
+ callout_drain(&SCAN_PRIVATE(ss)->ss_scan_timer);
ic->ic_flags &= ~IEEE80211_F_SCAN;
}
if (ss->ss_ops != NULL) {
@@ -203,27 +223,37 @@
}
/*
- * Kick off the scanning thread.
+ * Start/restart scanning. If we're operating in station mode
+ * and associated notify the ap we're going into power save mode.
+ * Otherwise, start the scan directly.
*/
static void
-start_timer(struct ieee80211_scan_state *ss, u_int duration)
+scan_restart(struct scan_state *ss, u_int duration)
{
- int delay;
+ struct ieee80211vap *vap = ss->base.ss_vap;
+ struct ieee80211com *ic = vap->iv_ic;
+ int delay = 0;
+
+ if (vap->iv_opmode == IEEE80211_M_STA &&
+ vap->iv_state == IEEE80211_S_RUN) {
+ if ((vap->iv_bss->ni_flags & IEEE80211_NODE_PWR_MGT) == 0) {
+ /*
+ * Initiate power save before going off-channel.
+ * Use an initial 1ms delay to insure the null
+ * data frame has a chance to go out.
+ * XXX bogus, need to trigger on on tx complete.
+ */
+ ieee80211_sta_pwrsave(vap, 1);
+ delay = hz/1000;
+ if (delay < 1)
+ delay = 1;
+ }
+ }
- if (ss->ss_flags & IEEE80211_SCAN_PWRSAV) {
- /*
- * Use an initial 1ms delay to insure any
- * power save frame has a chance to go out.
- * XXX 1ms is a lot, better to trigger scan
- * on tx complete.
- */
- delay = hz/1000;
- if (delay < 1)
- delay = 1;
- } else
- delay = 1;
+ ss->ss_savchan = ic->ic_curchan;
+ ic->ic_scan_start(ic); /* notify driver */
ss->ss_scanend = ticks + delay + duration;
- callout_reset(&ss->ss_scan_timer, delay, ieee80211_next_scan, ss);
+ callout_reset(&ss->ss_scan_timer, delay, scan_next, &ss->base);
}
/*
@@ -234,7 +264,7 @@
{
struct ieee80211com *ic = vap->iv_ic;
const struct ieee80211_scanner *scan;
- struct ieee80211_scan_state *ss = &ic->ic_scan;
+ struct ieee80211_scan_state *ss = ic->ic_scan;
scan = ieee80211_scanner_get(vap->iv_opmode);
if (scan == NULL) {
@@ -277,14 +307,14 @@
vap->iv_stats.is_scan_active++;
else
vap->iv_stats.is_scan_passive++;
- ss->ss_savchan = ic->ic_curchan;
+ SCAN_PRIVATE(ss)->ss_savchan = ic->ic_curchan;
if (flags & IEEE80211_SCAN_FLUSH)
ss->ss_ops->scan_flush(ss);
/* NB: flush frames rx'd before 1st channel change */
ss->ss_flags |= IEEE80211_SCAN_DISCARD;
ss->ss_ops->scan_start(ss, vap);
- start_timer(ss, duration);
+ scan_restart(SCAN_PRIVATE(ss), duration);
ic->ic_flags |= IEEE80211_F_SCAN;
}
} else {
@@ -306,7 +336,7 @@
ieee80211_check_scan(struct ieee80211vap *vap, int flags, u_int duration)
{
struct ieee80211com *ic = vap->iv_ic;
- struct ieee80211_scan_state *ss = &ic->ic_scan;
+ struct ieee80211_scan_state *ss = ic->ic_scan;
int checkscanlist = 0;
/*
@@ -352,7 +382,7 @@
ieee80211_bg_scan(struct ieee80211vap *vap)
{
struct ieee80211com *ic = vap->iv_ic;
- struct ieee80211_scan_state *ss = &ic->ic_scan;
+ struct ieee80211_scan_state *ss = ic->ic_scan;
IEEE80211_LOCK(ic);
if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) {
@@ -378,7 +408,7 @@
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
"%s: %s scan, duration %lu\n", __func__,
- ic->ic_flags & IEEE80211_F_SCAN ? "active" : "passive",
+ ss->ss_flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive",
duration);
if (ss->ss_ops != NULL) {
@@ -406,11 +436,11 @@
vap->iv_stats.is_scan_active++;
else
vap->iv_stats.is_scan_passive++;
+ ss->ss_ops->scan_restart(ss, vap);
}
/* NB: flush frames rx'd before 1st channel change */
ss->ss_flags |= IEEE80211_SCAN_DISCARD;
- ss->ss_ops->scan_restart(ss, vap);
- start_timer(ss, duration);
+ scan_restart(SCAN_PRIVATE(ss), duration);
ic->ic_flags |= IEEE80211_F_SCAN;
} else {
/* XXX msg+stat */
@@ -433,30 +463,21 @@
ieee80211_cancel_scan(struct ieee80211vap *vap)
{
struct ieee80211com *ic = vap->iv_ic;
- struct ieee80211_scan_state *ss = &ic->ic_scan;
+ struct ieee80211_scan_state *ss = ic->ic_scan;
IEEE80211_LOCK(ic);
if (ic->ic_flags & IEEE80211_F_SCAN) {
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
"%s: cancel %s scan\n", __func__,
- ss->ss_flags&IEEE80211_SCAN_ACTIVE ? "active" : "passive");
+ ss->ss_flags & IEEE80211_SCAN_ACTIVE ?
+ "active" : "passive");
- callout_drain(&ss->ss_scan_timer);
- /* XXX maybe this should be handled in the timer routine? */
- ic->ic_flags &= ~IEEE80211_F_SCAN;
- ss->ss_ops->scan_cancel(ss, vap);
- /* return to previous channel if needed */
- if (ss->ss_savchan != ic->ic_curchan)
- change_channel(ic, ss->ss_savchan);
- ic->ic_scan_end(ic); /* notify driver */
- /* XXX ieee80211_end_scan or otherwise notify? */
- if (ss->ss_flags & IEEE80211_SCAN_PWRSAV) {
- ieee80211_sta_pwrsave(vap, 0);
- ss->ss_flags &= ~IEEE80211_SCAN_PWRSAV;
- }
- /* clear ephemeral state bits */
- ss->ss_flags &= ~(IEEE80211_SCAN_MINDWELL |
- IEEE80211_SCAN_BGSCAN | IEEE80211_SCAN_ONCE);
+ /* clear bg scan NOPICK and mark cancel request */
+ ss->ss_flags &= ~IEEE80211_SCAN_NOPICK;
+ ss->ss_flags |= IEEE80211_SCAN_CANCEL;
+ /* NB: trigger at next clock tick */
+ callout_reset(&SCAN_PRIVATE(ss)->ss_scan_timer, 1,
+ scan_next, ss);
}
IEEE80211_UNLOCK(ic);
}
@@ -465,13 +486,13 @@
* Switch to the next channel marked for scanning.
*/
static void
-ieee80211_next_scan(void *arg)
+scan_next(void *arg)
{
struct ieee80211_scan_state *ss = arg;
struct ieee80211vap *vap = ss->ss_vap;
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211_channel *chan;
- unsigned long maxdwell;
+ unsigned long maxdwell, scanend;
int scanning, scandone, i;
IEEE80211_LOCK(ic);
@@ -482,15 +503,17 @@
/* XXX if taking first candidate check for a valid result */
again:
- scandone = (ss->ss_next >= ss->ss_last);
- if (!scandone && time_before(ticks + ss->ss_mindwell, ss->ss_scanend)) {
+ scandone = (ss->ss_next >= ss->ss_last) ||
+ (ss->ss_flags & IEEE80211_SCAN_CANCEL) != 0;
+ scanend = SCAN_PRIVATE(ss)->ss_scanend;
+ if (!scandone && time_before(ticks + ss->ss_mindwell, scanend)) {
chan = ss->ss_chans[ss->ss_next++];
/*
* Watch for truncation due to the scan end time.
*/
- if (time_after(ticks + ss->ss_maxdwell, ss->ss_scanend))
- maxdwell = ss->ss_scanend - ticks;
+ if (time_after(ticks + ss->ss_maxdwell, scanend))
+ maxdwell = scanend - ticks;
else
maxdwell = ss->ss_maxdwell;
@@ -538,39 +561,44 @@
ss->ss_probe_ssid[i].len,
vap->iv_opt_ie, vap->iv_opt_ie_len);
}
- ss->ss_chanmindwell = ticks + ss->ss_mindwell;
- callout_reset(&ss->ss_scan_timer, maxdwell,
- ieee80211_next_scan, ss);
+ SCAN_PRIVATE(ss)->ss_chanmindwell = ticks + ss->ss_mindwell;
+ callout_reset(&SCAN_PRIVATE(ss)->ss_scan_timer, maxdwell,
+ scan_next, ss);
/* clear mindwell lock and initial channel change flush */
ss->ss_flags &=
~(IEEE80211_SCAN_MINDWELL | IEEE80211_SCAN_DISCARD);
} else {
+ ic->ic_scan_end(ic); /* notify driver */
/*
- * Scan completed, do post-processing. If the callback
- * function returns 0, then it wants to continue/restart
- * scanning. Unfortunately we need to notify the driver
- * to end the scan before we invoke the callback method
- * to avoid having rx frames alter the scan candidate
- * list (maybe we could use a flag to have them discarded?).
+ * Record scan complete time. Note that we also do
+ * this when canceled so any background scan will
+ * not be restarted for a while.
*/
- ic->ic_scan_end(ic); /* notify driver */
- if (scandone) /* record scan complete time */
+ if (scandone)
ic->ic_lastscan = ticks;
/* return to the original channel */
- if (ss->ss_savchan != ic->ic_curchan)
- change_channel(ic, ss->ss_savchan);
+ if (SCAN_PRIVATE(ss)->ss_savchan != ic->ic_curchan)
+ change_channel(ic, SCAN_PRIVATE(ss)->ss_savchan);
/* clear mindwell lock and initial channel change flush */
ss->ss_flags &=
~(IEEE80211_SCAN_MINDWELL | IEEE80211_SCAN_DISCARD);
- if (!ss->ss_ops->scan_end(ss, vap) &&
+ /*
+ * If not canceled and scan completed, do post-processing.
+ * If the callback function returns 0, then it wants to
+ * continue/restart scanning. Unfortunately we needed to
+ * notify the driver to end the scan above to avoid having
+ * rx frames alter the scan candidate list.
+ */
+ if ((ss->ss_flags & IEEE80211_SCAN_CANCEL) == 0 &&
+ !ss->ss_ops->scan_end(ss, vap) &&
(ss->ss_flags & IEEE80211_SCAN_ONCE) == 0 &&
- time_before(ticks + ss->ss_mindwell, ss->ss_scanend)) {
+ time_before(ticks + ss->ss_mindwell, scanend)) {
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
"%s: done, restart "
"[ticks %lu, dwell min %lu scanend %lu]\n",
__func__,
- ticks, ss->ss_mindwell, ss->ss_scanend);
+ ticks, ss->ss_mindwell, scanend);
ss->ss_next = 0; /* reset to begining */
if (ss->ss_flags & IEEE80211_SCAN_ACTIVE)
vap->iv_stats.is_scan_active++;
@@ -583,14 +611,20 @@
/* past here, scandone is ``true'' if not in bg mode */
if ((ss->ss_flags & IEEE80211_SCAN_BGSCAN) == 0)
scandone = 1;
- ss->ss_flags &= ~IEEE80211_SCAN_ONCE;
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
"%s: %s, [ticks %lu, dwell min %lu scanend %lu]\n",
__func__, scandone ? "done" : "stopped",
- ticks, ss->ss_mindwell, ss->ss_scanend);
+ ticks, ss->ss_mindwell, scanend);
/*
+ * Clear the SCAN bit first in case frames are
+ * pending on the station power save queue. If
+ * we defer this then the dispatch of the frames
+ * may generate a request to cancel scanning.
+ */
+ ic->ic_flags &= ~IEEE80211_F_SCAN;
+ /*
* Drop out of power save mode when a scan has
* completed. If this scan was prematurely terminated
* because it is a background scan then don't notify
@@ -599,15 +633,13 @@
* save mode because the beacon indicates we have frames
* waiting for us.
*/
- if (scandone &&
- (ss->ss_flags & IEEE80211_SCAN_PWRSAV)) {
+ if (scandone) {
ieee80211_sta_pwrsave(vap, 0);
- ss->ss_flags &= ~IEEE80211_SCAN_PWRSAV;
+ if (ss->ss_next >= ss->ss_last)
+ ieee80211_notify_scan_done(vap);
}
- ic->ic_flags &= ~IEEE80211_F_SCAN;
- /* NB: suppress notification during bg scan */
- if (scandone)
- ieee80211_notify_scan_done(vap);
+ ss->ss_flags &=
+ ~(IEEE80211_SCAN_CANCEL | IEEE80211_SCAN_ONCE);
}
}
}
@@ -720,7 +752,7 @@
int subtype, int rssi, int rstamp)
{
struct ieee80211com *ic = vap->iv_ic;
- struct ieee80211_scan_state *ss = &ic->ic_scan;
+ struct ieee80211_scan_state *ss = ic->ic_scan;
/*
* Frames received during startup are discarded to avoid
@@ -743,13 +775,13 @@
* the timer so we'll switch to the next channel.
*/
if ((ss->ss_flags & IEEE80211_SCAN_MINDWELL) == 0 &&
- time_after_eq(ticks, ss->ss_chanmindwell)) {
+ time_after_eq(ticks, SCAN_PRIVATE(ss)->ss_chanmindwell)) {
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
"%s: chan %3d%c min dwell met (%lu > %lu)\n",
__func__,
ieee80211_chan2ieee(ic, ic->ic_curchan),
channel_type(ic->ic_curchan),
- ticks, ss->ss_chanmindwell);
+ ticks, SCAN_PRIVATE(ss)->ss_chanmindwell);
/*
* XXX
* We want to just kick the timer and still
@@ -762,8 +794,8 @@
ss->ss_flags |= IEEE80211_SCAN_DISCARD;
#endif
/* NB: trigger at next clock tick */
- callout_reset(&ss->ss_scan_timer, 1,
- ieee80211_next_scan, ss);
+ callout_reset(&SCAN_PRIVATE(ss)->ss_scan_timer, 1,
+ scan_next, ss);
}
}
}
@@ -775,7 +807,7 @@
void
ieee80211_scan_timeout(struct ieee80211com *ic)
{
- struct ieee80211_scan_state *ss = &ic->ic_scan;
+ struct ieee80211_scan_state *ss = ic->ic_scan;
if (ss->ss_ops != NULL)
ss->ss_ops->scan_age(ss);
@@ -787,7 +819,7 @@
void
ieee80211_scan_assocfail(struct ieee80211com *ic, const u_int8_t mac[])
{
- struct ieee80211_scan_state *ss = &ic->ic_scan;
+ struct ieee80211_scan_state *ss = ic->ic_scan;
if (ss->ss_ops != NULL)
ss->ss_ops->scan_assocfail(ss, mac);
@@ -800,7 +832,7 @@
ieee80211_scan_iterate(struct ieee80211com *ic,
ieee80211_scan_iter_func *f, void *arg)
{
- struct ieee80211_scan_state *ss = &ic->ic_scan;
+ struct ieee80211_scan_state *ss = ic->ic_scan;
if (ss->ss_ops != NULL)
ss->ss_ops->scan_iterate(ss, f, arg);
==== //depot/projects/vap/sys/net80211/ieee80211_scan.h#3 (text+ko) ====
@@ -40,15 +40,16 @@
struct ieee80211_scan_state {
struct ieee80211vap *ss_vap;
const struct ieee80211_scanner *ss_ops; /* policy hookup, see below */
+ void *ss_priv; /* scanner private state */
u_int16_t ss_flags;
#define IEEE80211_SCAN_NOPICK 0x0001 /* scan only, no selection */
#define IEEE80211_SCAN_ACTIVE 0x0002 /* active scan (probe req) */
#define IEEE80211_SCAN_PICK1ST 0x0004 /* ``hey sailor'' mode */
#define IEEE80211_SCAN_BGSCAN 0x0008 /* bg scan, exit ps at end */
#define IEEE80211_SCAN_ONCE 0x0010 /* do one complete pass */
-#define IEEE80211_SCAN_PWRSAV 0x1000 /* exit power save mode */
-#define IEEE80211_SCAN_MINDWELL 0x2000 /* min dwell time reached */
-#define IEEE80211_SCAN_DISCARD 0x4000 /* discard rx'd frames */
+#define IEEE80211_SCAN_MINDWELL 0x1000 /* min dwell time reached */
+#define IEEE80211_SCAN_DISCARD 0x2000 /* discard rx'd frames */
+#define IEEE80211_SCAN_CANCEL 0x4000 /* cancel current scan */
u_int8_t ss_pad;
u_int8_t ss_nprobe_ssid; /* # ssid's to probe */
struct {
@@ -60,12 +61,8 @@
struct ieee80211_channel *ss_chans[IEEE80211_SCAN_MAX];
u_int16_t ss_next; /* ix of next chan to scan */
u_int16_t ss_last; /* ix+1 of last chan to scan */
- unsigned long ss_scanend; /* time scan must stop */
unsigned long ss_mindwell; /* min dwell on channel */
- unsigned long ss_chanmindwell; /* " " " on curchan */
unsigned long ss_maxdwell; /* max dwell on channel */
- struct callout ss_scan_timer; /* scan timer */
- void *ss_priv; /* scanner private state */
};
/*
==== //depot/projects/vap/sys/net80211/ieee80211_scan_ap.c#4 (text+ko) ====
@@ -97,21 +97,6 @@
return 0;
}
-/*
- * Restart a previous scan.
- */
-static int
-ap_restart(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
-{
- struct ieee80211com *ic = vap->iv_ic;
-
- ss->ss_flags &= ~IEEE80211_SCAN_PWRSAV;
- ss->ss_savchan = ic->ic_curchan;
- ic->ic_scan_start(ic); /* notify driver */
-
- return 0;
-}
-
static struct ieee80211_channel *
find11gchannel(struct ieee80211com *ic, int i, int freq)
{
@@ -304,11 +289,20 @@
}
#endif /* IEEE80211_DEBUG */
- return ap_restart(ss, vap);
+ return 0;
#undef N
}
/*
+ * Restart a previous scan.
+ */
+static int
+ap_restart(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
+{
+ return 0;
+}
+
+/*
* Cancel an ongoing scan.
*/
static int
==== //depot/projects/vap/sys/net80211/ieee80211_scan_sta.c#6 (text+ko) ====
@@ -60,7 +60,7 @@
* (background) scans is discarded
* o after STA_FAILS_AGE seconds we clear the failure count
*/
-#define STA_FAILS_MAX 2 /* assoc failures before purge */
+#define STA_FAILS_MAX 2 /* assoc failures before ignored */
#define STA_FAILS_AGE (2*60) /* time before clearing fails (secs) */
#define STA_PURGE_SCANS 2 /* age for purging entries (scans) */
@@ -81,6 +81,8 @@
TAILQ_ENTRY(sta_entry) se_list;
LIST_ENTRY(sta_entry) se_hash;
u_int8_t se_fails; /* failure to associate count */
+ u_int8_t se_seen; /* seen during current scan */
+ u_int8_t se_notseen; /* not seen in previous scans */
u_int32_t se_avgrssi; /* LPF rssi state */
u_int32_t se_lastupdate; /* time of last update */
u_int32_t se_lastfail; /* time of last failure */
@@ -98,6 +100,7 @@
LIST_HEAD(, sta_entry) st_hash[STA_HASHSIZE];
struct mtx st_scanlock; /* on st_scangen */
u_int st_scangen; /* gen# for iterator */
+ int st_newscan;
};
static void sta_flush_table(struct sta_table *);
@@ -254,6 +257,7 @@
se->se_fails = 0;
se->se_lastupdate = ticks; /* update time */
+ se->se_seen = 1;
mtx_unlock(&st->st_lock);
#if 0
@@ -271,28 +275,27 @@
#undef ISPROBE
}
-/*
- * Restart a previous scan.
- */
-static int
-sta_restart(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
+static void
+sta_clearseen(struct sta_table *st)
{
- struct ieee80211com *ic = vap->iv_ic;
+ struct sta_entry *se;
- if (vap->iv_opmode == IEEE80211_M_STA &&
- vap->iv_state == IEEE80211_S_RUN) {
- if ((ss->ss_flags & IEEE80211_SCAN_PWRSAV) == 0) {
- /* initiate power save before going off-channel */
- ieee80211_sta_pwrsave(vap, 1);
- ss->ss_flags |= IEEE80211_SCAN_PWRSAV;
- }
- } else
- ss->ss_flags &= ~IEEE80211_SCAN_PWRSAV;
+ mtx_lock(&st->st_lock);
+ TAILQ_FOREACH(se, &st->st_entry, se_list)
+ se->se_seen = 0;
+ mtx_unlock(&st->st_lock);
+}
- ss->ss_savchan = ic->ic_curchan;
- ic->ic_scan_start(ic); /* notify driver */
+static void
+sta_updateseen(struct sta_table *st)
+{
+ struct sta_entry *se;
- return 0;
+ mtx_lock(&st->st_lock);
+ TAILQ_FOREACH(se, &st->st_entry, se_list)
+ if (!se->se_seen)
+ se->se_notseen++;
+ mtx_unlock(&st->st_lock);
}
static struct ieee80211_channel *
@@ -423,6 +426,7 @@
{
#define N(a) (sizeof(a)/sizeof(a[0]))
struct ieee80211com *ic = vap->iv_ic;
+ struct sta_table *st = ss->ss_priv;
enum ieee80211_phymode mode;
int i;
@@ -487,11 +491,27 @@
}
#endif /* IEEE80211_DEBUG */
- return sta_restart(ss, vap);
+ sta_clearseen(st);
+ st->st_newscan = 1;
+
+ return 0;
#undef N
}
/*
+ * Restart a bg scan.
+ */
+static int
+sta_restart(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
+{
+ struct sta_table *st = ss->ss_priv;
+
+ sta_clearseen(st);
+ st->st_newscan = 1;
+ return 0;
+}
+
+/*
* Cancel an ongoing scan.
*/
static int
@@ -655,6 +675,8 @@
fail |= 0x20;
if (se0->se_fails >= STA_FAILS_MAX)
fail |= 0x40;
+ if (se0->se_notseen >= STA_PURGE_SCANS)
+ fail |= 0x80;
#ifdef IEEE80211_DEBUG
if (ieee80211_msg_scan(vap)) {
/* XXX se_fails */
@@ -696,6 +718,10 @@
KASSERT(vap->iv_opmode != IEEE80211_M_HOSTAP,
("wrong opmode %u", vap->iv_opmode));
+ if (st->st_newscan) {
+ sta_updateseen(st);
+ st->st_newscan = 0;
+ }
if (ss->ss_flags & IEEE80211_SCAN_NOPICK) {
/*
* Manual/background scan, don't select+join the
@@ -755,13 +781,10 @@
{
struct sta_table *st = ss->ss_priv;
struct sta_entry *se, *next;
- u_int32_t droptime;
- droptime = ticks - (STA_PURGE_SCANS * ss->ss_vap->iv_bgscanintvl);
-
mtx_lock(&st->st_lock);
TAILQ_FOREACH_SAFE(se, &st->st_entry, se_list, next) {
- if (time_before(se->se_lastupdate, droptime)) {
+ if (se->se_notseen > STA_PURGE_SCANS) {
TAILQ_REMOVE(&st->st_entry, se, se_list);
LIST_REMOVE(se, se_hash);
FREE(se, M_80211_SCAN);
==== //depot/projects/vap/sys/net80211/ieee80211_var.h#14 (text+ko) ====
@@ -156,7 +156,7 @@
struct ieee80211_channel *ic_prevchan; /* previous channel */
/* scan-related state */
- struct ieee80211_scan_state ic_scan; /* scan state */
+ struct ieee80211_scan_state *ic_scan; /* scan state */
enum ieee80211_roamingmode ic_roaming; /* roaming mode */
int ic_lastdata; /* time of last data frame */
int ic_lastscan; /* time last scan completed */
More information about the p4-projects
mailing list