summaryrefslogtreecommitdiffstats
path: root/sys/net80211
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2007-11-05 17:24:28 +0000
committersam <sam@FreeBSD.org>2007-11-05 17:24:28 +0000
commit41cdb1440091fb8588854d7bc2337c9397979b11 (patch)
tree4bc2e263da250057be1528f9db75154292208940 /sys/net80211
parent9d42dea98fc43e1447f753c94fd699f31d741b20 (diff)
downloadFreeBSD-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')
-rw-r--r--sys/net80211/ieee80211_scan_sta.c49
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;
OpenPOWER on IntegriCloud