diff options
author | sam <sam@FreeBSD.org> | 2007-11-05 17:24:28 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2007-11-05 17:24:28 +0000 |
commit | 41cdb1440091fb8588854d7bc2337c9397979b11 (patch) | |
tree | 4bc2e263da250057be1528f9db75154292208940 /sys/net80211/ieee80211_scan_sta.c | |
parent | 9d42dea98fc43e1447f753c94fd699f31d741b20 (diff) | |
download | FreeBSD-src-41cdb1440091fb8588854d7bc2337c9397979b11.zip FreeBSD-src-41cdb1440091fb8588854d7bc2337c9397979b11.tar.gz |
Correct handling of off-channel frames:
o do not override the home channel recorded for the sta when the frame is
received off-channel; this fixes a problem where we might think the sta
was operating on the channel the frame was received on causing association
requests to be ignored/rejected (likely cause of kern/99036)
o don't include rssi of off-channel frames in the avg rssi used to select
a bss; this gives us a better estimate of the signal we will see for the
station when on-channel
PR: kern/99036
Found by: Yubin Gong
Reviewed by: sephe
MFC after: 1 week
Diffstat (limited to 'sys/net80211/ieee80211_scan_sta.c')
-rw-r--r-- | sys/net80211/ieee80211_scan_sta.c | 49 |
1 files changed, 37 insertions, 12 deletions
diff --git a/sys/net80211/ieee80211_scan_sta.c b/sys/net80211/ieee80211_scan_sta.c index 7a8ad06..7cdcf1e 100644 --- a/sys/net80211/ieee80211_scan_sta.c +++ b/sys/net80211/ieee80211_scan_sta.c @@ -61,10 +61,12 @@ __FBSDID("$FreeBSD$"); #define STA_RSSI_MIN 8 /* min acceptable rssi */ #define STA_RSSI_MAX 40 /* max rssi for comparison */ -#define RSSI_LPF_LEN 10 +#define RSSI_LPF_LEN 10 +#define RSSI_DUMMY_MARKER 0x127 #define RSSI_EP_MULTIPLIER (1<<7) /* pow2 to optimize out * and / */ #define RSSI_IN(x) ((x) * RSSI_EP_MULTIPLIER) -#define LPF_RSSI(x, y, len) (((x) * ((len) - 1) + (y)) / (len)) +#define LPF_RSSI(x, y, len) \ + ((x != RSSI_DUMMY_MARKER) ? (((x) * ((len) - 1) + (y)) / (len)) : (y)) #define RSSI_LPF(x, y) do { \ if ((y) >= -20) \ x = LPF_RSSI((x), RSSI_IN((y)), RSSI_LPF_LEN); \ @@ -222,7 +224,7 @@ sta_add(struct ieee80211_scan_state *ss, struct ieee80211com *ic = ss->ss_ic; struct sta_entry *se; struct ieee80211_scan_entry *ise; - int hash; + int hash, offchan; hash = STA_HASH(macaddr); @@ -237,6 +239,7 @@ sta_add(struct ieee80211_scan_state *ss, return 0; } se->se_scangen = st->st_scangen-1; + se->se_avgrssi = RSSI_DUMMY_MARKER; IEEE80211_ADDR_COPY(se->base.se_macaddr, macaddr); TAILQ_INSERT_TAIL(&st->st_entry, se, se_list); LIST_INSERT_HEAD(&st->st_hash[hash], se, se_hash); @@ -257,20 +260,42 @@ found: } else ise->se_xrates[1] = 0; IEEE80211_ADDR_COPY(ise->se_bssid, wh->i_addr3); - /* - * Record rssi data using extended precision LPF filter. - */ - if (se->se_lastupdate == 0) /* first sample */ - se->se_avgrssi = RSSI_IN(rssi); - else /* avg w/ previous samples */ + offchan = (IEEE80211_CHAN2IEEE(sp->curchan) != sp->bchan && + ic->ic_phytype != IEEE80211_T_FH); + if (!offchan) { + /* + * Record rssi data using extended precision LPF filter. + * + * NB: use only on-channel data to insure we get a good + * estimate of the signal we'll see when associated. + */ RSSI_LPF(se->se_avgrssi, rssi); - se->base.se_rssi = RSSI_GET(se->se_avgrssi); - se->base.se_noise = noise; + ise->se_rssi = RSSI_GET(se->se_avgrssi); + ise->se_noise = noise; + } ise->se_rstamp = rstamp; memcpy(ise->se_tstamp.data, sp->tstamp, sizeof(ise->se_tstamp)); ise->se_intval = sp->bintval; ise->se_capinfo = sp->capinfo; - ise->se_chan = sp->curchan; + /* + * Beware of overriding se_chan for frames seen + * off-channel; this can cause us to attempt an + * assocation on the wrong channel. + */ + if (ise->se_chan == NULL || !offchan) { + /* + * NB: this is not right when the frame is received + * off-channel but se_chan is assumed set by code + * elsewhere so we must assign something; the scan + * entry should be ignored because the rssi will be + * zero (because the frames are received off-channel). + * + * We could locate the correct channel using sp->chan + * but it's not clear we should join an ap that we + * never see on-channel during a scan. + */ + ise->se_chan = sp->curchan; + } ise->se_fhdwell = sp->fhdwell; ise->se_fhindex = sp->fhindex; ise->se_erp = sp->erp; |