Date: Sun, 22 May 2005 04:02:22 GMT From: Sam Leffler <sam@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 77276 for review Message-ID: <200505220402.j4M42Ml4007853@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=77276 Change 77276 by sam@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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200505220402.j4M42Ml4007853>
