From owner-p4-projects@FreeBSD.ORG Mon May 16 18:44:38 2005 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 89A2516A4D1; Mon, 16 May 2005 18:44:37 +0000 (GMT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 5D4D716A4CE for ; Mon, 16 May 2005 18:44:37 +0000 (GMT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 259FD43DB7 for ; Mon, 16 May 2005 18:44:37 +0000 (GMT) (envelope-from sam@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.1/8.13.1) with ESMTP id j4GIib3i033440 for ; Mon, 16 May 2005 18:44:37 GMT (envelope-from sam@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.1/8.13.1/Submit) id j4GIiaED033437 for perforce@freebsd.org; Mon, 16 May 2005 18:44:36 GMT (envelope-from sam@freebsd.org) Date: Mon, 16 May 2005 18:44:36 GMT Message-Id: <200505161844.j4GIiaED033437@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to sam@freebsd.org using -f From: Sam Leffler To: Perforce Change Reviews Subject: PERFORCE change 77074 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 16 May 2005 18:44:38 -0000 http://perforce.freebsd.org/chv.cgi?CH=77074 Change 77074 by sam@sam_laptop on 2005/05/16 18:44:27 First cut at background scanning; needs testing. Affected files ... .. //depot/projects/vap/sys/net80211/ieee80211.c#9 edit .. //depot/projects/vap/sys/net80211/ieee80211_input.c#10 edit .. //depot/projects/vap/sys/net80211/ieee80211_ioctl.c#9 edit .. //depot/projects/vap/sys/net80211/ieee80211_ioctl.h#6 edit .. //depot/projects/vap/sys/net80211/ieee80211_output.c#11 edit .. //depot/projects/vap/sys/net80211/ieee80211_proto.c#7 edit .. //depot/projects/vap/sys/net80211/ieee80211_scan.c#2 edit .. //depot/projects/vap/sys/net80211/ieee80211_scan.h#2 edit .. //depot/projects/vap/sys/net80211/ieee80211_scan_ap.c#3 edit .. //depot/projects/vap/sys/net80211/ieee80211_scan_sta.c#3 edit .. //depot/projects/vap/sys/net80211/ieee80211_var.h#10 edit Differences ... ==== //depot/projects/vap/sys/net80211/ieee80211.c#9 (text+ko) ==== @@ -278,6 +278,10 @@ vap->iv_flags |= IEEE80211_F_FF; if (vap->iv_caps & IEEE80211_C_TURBOP) vap->iv_flags |= IEEE80211_F_TURBOP; + /* NB: bg scanning only makes sense for station mode right now */ + if (ic->ic_opmode == IEEE80211_M_STA && + (vap->iv_caps & IEEE80211_C_BGSCAN)) + vap->iv_flags |= IEEE80211_F_BGSCAN; vap->iv_des_chan = IEEE80211_CHAN_ANYC; /* any channel is ok */ vap->iv_dtim_period = IEEE80211_DTIM_DEFAULT; ==== //depot/projects/vap/sys/net80211/ieee80211_input.c#10 (text+ko) ==== @@ -531,6 +531,7 @@ ifp->if_ipackets++; IEEE80211_NODE_STAT(ni, rx_data); IEEE80211_NODE_STAT_ADD(ni, rx_bytes, m->m_pkthdr.len); + ic->ic_lastdata = ticks; #define FF_LLC_SIZE (sizeof(struct ether_header) + sizeof(struct llc)) if (IEEE80211_ATH_CAP(vap, ni, FF) && @@ -2318,9 +2319,20 @@ } if (scan.doth != NULL) ieee80211_parse_dothparams(vap, scan.doth, wh); - /* NB: don't need the rest of this */ - if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) + if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) { + /* + * If no data frames have come through + * recently and it's been a while since the + * last background scan, kick off a new + * background scan. + */ + if ((vap->iv_flags & IEEE80211_F_BGSCAN) && + ticks - ic->ic_lastscan >= vap->iv_bgscanintvl && + ticks - ic->ic_lastdata >= vap->iv_bgscanidle) + ieee80211_bg_scan(vap); + /* NB: don't need the rest of this */ return; + } } /* * If scanning, just pass information to the scan module. ==== //depot/projects/vap/sys/net80211/ieee80211_ioctl.c#9 (text+ko) ==== @@ -905,6 +905,15 @@ case IEEE80211_IOC_TURBOP: ireq->i_val = (vap->iv_flags & IEEE80211_F_TURBOP) != 0; break; + case IEEE80211_IOC_BGSCAN: + ireq->i_val = (vap->iv_flags & IEEE80211_F_BGSCAN) != 0; + break; + case IEEE80211_IOC_BGSCAN_IDLE: + ireq->i_val = vap->iv_bgscanidle*1000/hz;/* ms */ + break; + case IEEE80211_IOC_BGSCAN_INTERVAL: + ireq->i_val = vap->iv_bgscanintvl/hz; /* seconds */ + break; default: error = EINVAL; break; @@ -1708,7 +1717,9 @@ break; case IEEE80211_IOC_SCAN_REQ: error = ieee80211_start_scan(vap, - IEEE80211_SCAN_NOPICK|IEEE80211_SCAN_ACTIVE); + IEEE80211_SCAN_ACTIVE | + IEEE80211_SCAN_NOPICK | + IEEE80211_SCAN_ONCE, IEEE80211_SCAN_FOREVER); break; case IEEE80211_IOC_ADDMAC: case IEEE80211_IOC_DELMAC: @@ -1768,6 +1779,26 @@ vap->iv_flags &= ~IEEE80211_F_TURBOP; error = ENETRESET; /* XXX maybe not for station? */ break; + case IEEE80211_IOC_BGSCAN: + if (ireq->i_val) { + if ((vap->iv_caps & IEEE80211_C_BGSCAN) == 0) + return EINVAL; + vap->iv_flags |= IEEE80211_F_BGSCAN; + } else + vap->iv_flags &= ~IEEE80211_F_BGSCAN; + break; + case IEEE80211_IOC_BGSCAN_IDLE: + if (ireq->i_val >= IEEE80211_BGSCAN_IDLE_MIN) + vap->iv_bgscanidle = ireq->i_val*hz/1000; + else + error = EINVAL; + break; + case IEEE80211_IOC_BGSCAN_INTERVAL: + if (ireq->i_val >= IEEE80211_BGSCAN_INTVAL_MIN) + vap->iv_bgscanintvl = ireq->i_val*hz; + else + error = EINVAL; + break; default: error = EINVAL; break; ==== //depot/projects/vap/sys/net80211/ieee80211_ioctl.h#6 (text+ko) ==== @@ -434,6 +434,9 @@ #define IEEE80211_IOC_TURBOP 57 /* ATH turbo' (on, off) */ #define IEEE80211_IOC_WDS 58 /* WDS/4-address handling */ #define IEEE80211_IOC_PUREG 59 /* pure 11g (no 11b stations) */ +#define IEEE80211_IOC_BGSCAN 60 /* bg scanning (on, off) */ +#define IEEE80211_IOC_BGSCAN_IDLE 61 /* bg scan idle threshold */ +#define IEEE80211_IOC_BGSCAN_INTERVAL 62 /* bg scan interval */ /* * Scan result data returned for IEEE80211_IOC_SCAN_RESULTS. ==== //depot/projects/vap/sys/net80211/ieee80211_output.c#11 (text+ko) ==== @@ -217,6 +217,9 @@ /* NB: parent must be up and running */ if ((parent->if_flags & (IFF_RUNNING|IFF_UP)) != (IFF_RUNNING|IFF_UP)) return; + if (vap->iv_state == IEEE80211_S_RUN && + (ic->ic_flags & IEEE80211_F_SCAN)) /* cancel bg scan */ + ieee80211_cancel_scan(vap); for (;;) { /* * No data frames go out unless we're running. @@ -290,6 +293,7 @@ } else ifp->if_opackets++; } + ic->ic_lastdata = ticks; } /* ==== //depot/projects/vap/sys/net80211/ieee80211_proto.c#7 (text+ko) ==== @@ -1136,6 +1136,9 @@ IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE, "%s: %s -> %s\n", __func__, ieee80211_state_name[ostate], ieee80211_state_name[nstate]); vap->iv_state = nstate; /* state transition */ + callout_stop(&vap->iv_mgtsend); + if (ostate != IEEE80211_S_SCAN) + ieee80211_cancel_scan(vap); /* background scan */ ni = vap->iv_bss; /* NB: no reference held */ switch (nstate) { case IEEE80211_S_INIT: @@ -1195,10 +1198,6 @@ goto reset; case IEEE80211_S_AUTH: reset: - callout_stop(&vap->iv_mgtsend); -#if 0 - IF_DRAIN(&ic->ic_mgtq); /* XXX multi-bss */ -#endif ieee80211_reset_bss(vap); break; } @@ -1220,7 +1219,8 @@ } else { ieee80211_check_scan(vap, IEEE80211_SCAN_ACTIVE | - IEEE80211_SCAN_FLUSH); + IEEE80211_SCAN_FLUSH, + IEEE80211_SCAN_FOREVER); } break; case IEEE80211_S_SCAN: @@ -1238,7 +1238,8 @@ case IEEE80211_S_ASSOC: /* timeout restart scan */ ieee80211_scan_assocfail(ic, vap->iv_bss->ni_macaddr); - ieee80211_check_scan(vap, IEEE80211_SCAN_ACTIVE | arg); + ieee80211_check_scan(vap, IEEE80211_SCAN_ACTIVE | arg, + IEEE80211_SCAN_FOREVER); break; } break; @@ -1309,7 +1310,6 @@ if (vap->iv_flags & IEEE80211_F_WPA) { /* XXX validate prerequisites */ } - callout_stop(&vap->iv_mgtsend); ifp->if_flags &= ~IFF_OACTIVE; switch (ostate) { case IEEE80211_S_INIT: @@ -1358,7 +1358,8 @@ * AP. We delay until here to allow configuration to * happen out of order. */ - if (vap->iv_opmode == IEEE80211_M_HOSTAP && /* XXX IBSS/AHDEMO */ + if (vap->iv_opmode == IEEE80211_M_HOSTAP && + /* XXX IBSS/AHDEMO */ vap->iv_auth->ia_attach != NULL) { /* XXX check failure */ vap->iv_auth->ia_attach(vap); ==== //depot/projects/vap/sys/net80211/ieee80211_scan.c#2 (text+ko) ==== @@ -78,6 +78,8 @@ void ieee80211_scan_vattach(struct ieee80211vap *vap) { + vap->iv_bgscanidle = (IEEE80211_BGSCAN_IDLE_DEFAULT*1000)/hz; + vap->iv_bgscanintvl = IEEE80211_BGSCAN_INTVAL_DEFAULT*hz; } void @@ -204,7 +206,7 @@ * Kick off the scanning thread. */ static void -start_timer(struct ieee80211_scan_state *ss) +start_timer(struct ieee80211_scan_state *ss, u_int duration) { int delay; @@ -215,9 +217,12 @@ * XXX 1ms is a lot, better to trigger scan * on tx complete. */ - delay = hz/100; + delay = hz/1000; + if (delay < 1) + delay = 1; } else delay = 1; + ss->ss_scanend = ticks + delay + duration; callout_reset(&ss->ss_scan_timer, delay, ieee80211_next_scan, ss); } @@ -225,7 +230,7 @@ * Start a scan unless one is already going. */ int -ieee80211_start_scan(struct ieee80211vap *vap, int flags) +ieee80211_start_scan(struct ieee80211vap *vap, int flags, u_int duration) { struct ieee80211com *ic = vap->iv_ic; const struct ieee80211_scanner *scan; @@ -243,12 +248,14 @@ IEEE80211_LOCK(ic); if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, - "%s: %s scan, desired mode %s, %s%s\n" + "%s: %s scan, duration %lu, desired mode %s, %s%s%s\n" , __func__ , flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive" + , duration , ieee80211_phymode_name[vap->iv_des_mode] , flags & IEEE80211_SCAN_FLUSH ? "flush" : "append" , flags & IEEE80211_SCAN_NOPICK ? ", nopick" : "" + , flags & IEEE80211_SCAN_ONCE ? ", once" : "" ); ss->ss_vap = vap; @@ -277,7 +284,7 @@ /* 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); + start_timer(ss, duration); ic->ic_flags |= IEEE80211_F_SCAN; } } else { @@ -296,7 +303,7 @@ * fails then kick off a new scan. */ int -ieee80211_check_scan(struct ieee80211vap *vap, int flags) +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; @@ -334,37 +341,76 @@ /* no ap, clear the flag before starting a scan */ ic->ic_flags &= ~IEEE80211_F_SCAN; } - return ieee80211_start_scan(vap, flags); + return ieee80211_start_scan(vap, flags, duration); } /* - * Restart a previous scan. The existing scan state is left - * untouched, we just restart the thread and it will pickup - * where we left off. + * Restart a previous scan. If the previous scan completed + * then we start again using the existing channel list. */ int -ieee80211_restart_scan(struct ieee80211vap *vap) +ieee80211_bg_scan(struct ieee80211vap *vap) { struct ieee80211com *ic = vap->iv_ic; struct ieee80211_scan_state *ss = &ic->ic_scan; IEEE80211_LOCK(ic); if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) { + u_int duration, fudge; + + /* + * Calculate the schedule for going off-channel. We + * need to return in time to receive the next beacon + * so we use the beacon interval minus the time required + * to be ready to rx the beacon. This is device-dependent + * but for now we use 1ms. Note that this only works + * because we are called on receipt of a beacon frame; + * otherwise we'd need to check TSF and calculate nexttbtt + * or (more likely) arrange to start at the next beacon. + */ + duration = IEEE80211_TU_TO_TICKS(vap->iv_bss->ni_intval); + fudge = hz/1000; + if (fudge == 0) + fudge = 1; + if (duration > fudge) + duration -= fudge; + /* XXX do we sanity check beacon interval anywhere? */ + IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, - "%s: %s scan\n", __func__, - ic->ic_flags & IEEE80211_F_SCAN ? "active" : "passive"); + "%s: %s scan, duration %lu\n", __func__, + ic->ic_flags & IEEE80211_F_SCAN ? "active" : "passive", + duration); if (ss->ss_ops != NULL) { - ss->ss_vap = vap; /* XXX temporary */ - if (ss->ss_flags & IEEE80211_SCAN_ACTIVE) - vap->iv_stats.is_scan_active++; - else - vap->iv_stats.is_scan_passive++; - + ss->ss_vap = vap; + /* + * A background scan does not select a new sta; it + * just refreshes the scan cache. Also, indicate + * the scan logic should follow the beacon schedule: + * we go off-channel and scan for as much of the + * beacon interval as we can, return to the bss channel + * to receive the beacon, then go off-channel again. + * All during this time we notify the ap we're in power + * save mode. When the scan is complete we leave power + * save mode. If any beacon indicates there are frames + * pending for us then we drop out of power save mode + * (and background scan) automatically by way of the + * usual sta power save logic. + */ + ss->ss_flags |= IEEE80211_SCAN_NOPICK + | IEEE80211_SCAN_BGSCAN; + /* if previous scan completed, restart */ + if (ss->ss_next >= ss->ss_last) { + ss->ss_next = 0; + if (ss->ss_flags & IEEE80211_SCAN_ACTIVE) + vap->iv_stats.is_scan_active++; + else + vap->iv_stats.is_scan_passive++; + } /* 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); + start_timer(ss, duration); ic->ic_flags |= IEEE80211_F_SCAN; } else { /* XXX msg+stat */ @@ -381,7 +427,7 @@ } /* - * Cancel any active scan. + * Cancel any scan currently going on. */ void ieee80211_cancel_scan(struct ieee80211vap *vap) @@ -396,6 +442,7 @@ IEEE80211_LOCK(ic); if (ic->ic_flags & IEEE80211_F_SCAN) { 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 */ @@ -405,7 +452,9 @@ /* XXX ieee80211_end_scan or otherwise notify? */ if (ss->ss_flags & IEEE80211_SCAN_PWRSAV) ieee80211_sta_pwrsave(vap, 0); - ss->ss_flags &= ~IEEE80211_SCAN_MINDWELL; + /* clear ephemeral state bits */ + ss->ss_flags &= ~(IEEE80211_SCAN_MINDWELL | + IEEE80211_SCAN_BGSCAN | IEEE80211_SCAN_ONCE); } IEEE80211_UNLOCK(ic); } @@ -421,7 +470,7 @@ struct ieee80211com *ic = vap->iv_ic; struct ieee80211_channel *chan; unsigned long maxdwell; - int scanning, i; + int scanning, scandone, i; IEEE80211_LOCK(ic); scanning = (ic->ic_flags & IEEE80211_F_SCAN) != 0; @@ -431,8 +480,8 @@ /* XXX if taking first candidate check for a valid result */ again: - if (ss->ss_next < ss->ss_last && - time_before(ticks + ss->ss_mindwell, ss->ss_scanend)) { + scandone = (ss->ss_next >= ss->ss_last); + if (!scandone && time_before(ticks + ss->ss_mindwell, ss->ss_scanend)) { chan = ss->ss_chans[ss->ss_next++]; /* @@ -444,7 +493,7 @@ maxdwell = ss->ss_maxdwell; IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, - "%s: chan %3d%c -> %3d%c [%s, dwell min %ld max %ld]\n", + "%s: chan %3d%c -> %3d%c [%s, dwell min %lu max %lu]\n", __func__, ieee80211_chan2ieee(ic, ic->ic_curchan), channel_type(ic->ic_curchan), @@ -506,13 +555,16 @@ * ss_scan_end may decide differently. */ ic->ic_scan_end(ic); /* notify driver */ + if (scandone) /* record scan complete time */ + ic->ic_lastscan = ticks; /* 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) && + (ss->ss_flags & IEEE80211_SCAN_ONCE) == 0 && time_before(ticks + ss->ss_mindwell, ss->ss_scanend)) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, - "%s: scan done, restart " + "%s: done, restart " "[ticks %lu, dwell min %lu scanend %lu]\n", __func__, ticks, ss->ss_mindwell, ss->ss_scanend); @@ -525,18 +577,34 @@ ic->ic_scan_start(ic); /* notify driver */ goto again; } else { + /* 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: scan done, completed " - "[ticks %lu, dwell min %lu scanend %lu]\n", - __func__, + "%s: %s, [ticks %lu, dwell min %lu scanend %lu]\n", + __func__, scandone ? "done" : "stopped", ticks, ss->ss_mindwell, ss->ss_scanend); - if (ss->ss_flags & IEEE80211_SCAN_PWRSAV) { - if (ss->ss_savchan != ic->ic_curchan) - change_channel(ic, ss->ss_savchan); + + /* return to the original channel */ + if (ss->ss_savchan != ic->ic_curchan) + change_channel(ic, ss->ss_savchan); + /* + * 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 + * the ap; we'll either return to scanning after we + * receive the beacon frame or we'll drop out of power + * save mode because the beacon indicates we have frames + * waiting for us. + */ + if (scandone && (ss->ss_flags & IEEE80211_SCAN_PWRSAV)) ieee80211_sta_pwrsave(vap, 0); - } ic->ic_flags &= ~IEEE80211_F_SCAN; - ieee80211_notify_scan_done(vap); + /* NB: suppress notification during bg scan */ + if (scandone) + ieee80211_notify_scan_done(vap); } } } ==== //depot/projects/vap/sys/net80211/ieee80211_scan.h#2 (text+ko) ==== @@ -43,6 +43,9 @@ 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 */ @@ -81,9 +84,10 @@ void ieee80211_scan_dump_channels(const struct ieee80211_scan_state *); -int ieee80211_start_scan(struct ieee80211vap *, int flags); -int ieee80211_check_scan(struct ieee80211vap *, int flags); -int ieee80211_restart_scan(struct ieee80211vap *); +#define IEEE80211_SCAN_FOREVER 0x7fffffff +int ieee80211_start_scan(struct ieee80211vap *, int flags, u_int duration); +int ieee80211_bg_scan(struct ieee80211vap *); +int ieee80211_check_scan(struct ieee80211vap *, int flags, u_int duration); void ieee80211_cancel_scan(struct ieee80211vap *); int ieee80211_match_bss(struct ieee80211vap *, struct ieee80211_node *); ==== //depot/projects/vap/sys/net80211/ieee80211_scan_ap.c#3 (text+ko) ==== @@ -294,15 +294,13 @@ /* XXX tunables */ ss->ss_mindwell = 200*hz/1000; /* 200ms */ ss->ss_maxdwell = 300*hz/1000; /* 300ms */ - /* arrange to scan only once */ - ss->ss_scanend = ticks + ss->ss_last * ss->ss_maxdwell; #ifdef IEEE80211_DEBUG if (ieee80211_msg_scan(vap)) { if_printf(&vap->iv_if, "scan set "); ieee80211_scan_dump_channels(ss); - printf(" dwell min %ld max %ld scanend %ld\n", - ss->ss_mindwell, ss->ss_maxdwell, ss->ss_scanend); + printf(" dwell min %ld max %ld\n", + ss->ss_mindwell, ss->ss_maxdwell); } #endif /* IEEE80211_DEBUG */ ==== //depot/projects/vap/sys/net80211/ieee80211_scan_sta.c#3 (text+ko) ==== @@ -88,6 +88,7 @@ }; static void sta_flush_table(struct sta_table *); +static int match_bss(struct ieee80211vap *, struct ieee80211_scan_entry *); /* * Attach prior to any scanning work. @@ -178,7 +179,8 @@ #define ISPROBE(_st) ((_st) == IEEE80211_FC0_SUBTYPE_PROBE_RESP) struct sta_table *st = ss->ss_priv; const u_int8_t *macaddr = wh->i_addr2; - struct ieee80211com *ic = ss->ss_vap->iv_ic; + struct ieee80211vap *vap = ss->ss_vap; + struct ieee80211com *ic = vap->iv_ic; struct sta_entry *se; struct ieee80211_scan_entry *ise; int hash; @@ -238,7 +240,17 @@ se->se_lastupdate = ticks; /* update time */ mtx_unlock(&st->st_lock); - +#if 0 + /* + * If scanning for the first acceptable candidate, + * check capabilities and verify the rssi is acceptable. + */ + if ((ss->ss_flags & IEEE80211_SCAN_PICK1ST) && + match_bss(vap, ise) == 0 && + RSSI_GET(se->se_avgrssi) >= RSSI_MINACCEPTABLE) { + /* arrange to terminate scan and associate */ + } +#endif return 1; #undef ISPROBE } @@ -253,9 +265,11 @@ if (vap->iv_opmode == IEEE80211_M_STA && vap->iv_state == IEEE80211_S_RUN) { - /* initiate power save before going off-channel */ - ieee80211_sta_pwrsave(vap, 1); - ss->ss_flags |= IEEE80211_SCAN_PWRSAV; + 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; @@ -447,14 +461,13 @@ /* XXX tunables */ ss->ss_mindwell = 20*hz/1000; /* 20ms */ ss->ss_maxdwell = 200*hz/1000; /* 200ms */ - ss->ss_scanend = ticks+0x7fffffff; /* scan ``forever'' */ #ifdef IEEE80211_DEBUG if (ieee80211_msg_scan(vap)) { if_printf(&vap->iv_if, "scan set "); ieee80211_scan_dump_channels(ss); - printf(" dwell min %ld max %ld scanend %ld\n", - ss->ss_mindwell, ss->ss_maxdwell, ss->ss_scanend); + printf(" dwell min %ld max %ld\n", + ss->ss_mindwell, ss->ss_maxdwell); } #endif /* IEEE80211_DEBUG */ ==== //depot/projects/vap/sys/net80211/ieee80211_var.h#10 (text+ko) ==== @@ -70,11 +70,18 @@ #define IEEE80211_BINTVAL_MIN 25 /* min beacon interval (TU's) */ #define IEEE80211_BINTVAL_DEFAULT 100 /* default beacon interval (TU's) */ +#define IEEE80211_BGSCAN_INTVAL_MIN 30 /* min bg scan intvl (secs) */ +#define IEEE80211_BGSCAN_INTVAL_DEFAULT (5*60) /* default bg scan intvl */ + +#define IEEE80211_BGSCAN_IDLE_MIN 500 /* min idle time (ms) */ +#define IEEE80211_BGSCAN_IDLE_DEFAULT (10*1000) /* default idle time (ms) */ + #define IEEE80211_PS_SLEEP 0x1 /* STA is in power saving mode */ #define IEEE80211_PS_MAX_QUEUE 50 /* maximum saved packets */ #define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) #define IEEE80211_TU_TO_MS(x) (((x) * 1024) / 1000) +#define IEEE80211_TU_TO_TICKS(x) ((IEEE80211_TU_TO_MS(x) * hz) / 1000) #define IEEE80211_PWRCONSTRAINT_VAL(ic) \ (((ic)->ic_bsschan->ic_maxregpower > (ic)->ic_curchanmaxpwr) ? \ @@ -151,6 +158,8 @@ /* scan-related 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 */ /* NB: this is the union of all vap stations/neighbors */ struct ieee80211_node_table ic_sta; /* stations/neighbors */ @@ -248,6 +257,8 @@ u_int16_t iv_des_mode; /* desired mode */ int iv_nicknamelen; /* XXX junk */ u_int8_t iv_nickname[IEEE80211_NWID_LEN]; + u_int iv_bgscanidle; /* bg scan idle threshold */ + u_int iv_bgscanintvl; /* bg scan min interval */ u_int32_t *iv_aid_bitmap; /* association id map */ u_int16_t iv_max_aid; @@ -305,6 +316,7 @@ #define IEEE80211_F_PMGTON 0x00000800 /* CONF: Power mgmt enable */ #define IEEE80211_F_DESBSSID 0x00001000 /* CONF: des_bssid is set */ #define IEEE80211_F_WME 0x00002000 /* CONF: enable WME use */ +#define IEEE80211_F_BGSCAN 0x00004000 /* CONF: bg scan enabled */ #define IEEE80211_F_SWRETRY 0x00008000 /* CONF: sw tx retry enabled */ #define IEEE80211_F_TXPOW_FIXED 0x00010000 /* TX Power: fixed rate */ #define IEEE80211_F_IBSSON 0x00020000 /* CONF: IBSS creation enable */ @@ -348,6 +360,7 @@ #define IEEE80211_C_BURST 0x02000000 /* CAPABILITY: frame bursting */ #define IEEE80211_C_WME 0x04000000 /* CAPABILITY: WME avail */ #define IEEE80211_C_WDS 0x08000000 /* CAPABILITY: 4-addr support */ +#define IEEE80211_C_BGSCAN 0x10000000 /* CAPABILITY: bg scanning */ /* XXX protection/barker? */ #define IEEE80211_C_CRYPTO 0x0000002f /* CAPABILITY: crypto alg's */ @@ -355,7 +368,8 @@ (IEEE80211_C_CRYPTO | IEEE80211_C_FF | IEEE80211_C_TURBOP | \ IEEE80211_C_PMGT | IEEE80211_C_SWRETRY | IEEE80211_C_TXPMGT | \ IEEE80211_C_SHSLOT | IEEE80211_C_SHPREAMBLE | IEEE80211_C_TKIPMIC | \ - IEEE80211_C_WPA | IEEE80211_C_BURST | IEEE80211_C_WME) + IEEE80211_C_WPA | IEEE80211_C_BURST | IEEE80211_C_WME | \ + IEEE80211_C_BGSCAN) /* check if a capability was negotiated for use */ #define IEEE80211_ATH_CAP(vap, ni, bit) \