Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 25 Oct 2008 01:10:07 GMT
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 151889 for review
Message-ID:  <200810250110.m9P1A7qj041833@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=151889

Change 151889 by sam@sam_ebb on 2008/10/25 01:09:25

	Fix joining an 11b BSS: scanning is normally done using 11g
	channels (unless explicitly locked to mode 11b) so when we
	join the bss the channel attached to the scan cache entry
	may need to be demoted.
	
	o demote to 11b if the ap is advertising 11b rates
	o skip the ap if it's 11b but we're locked to 11g (could consider this
	  advisory but for now treat it as mandatory)
	o handle an odd edge case, if there is a fixed transmit rate for 11g
	  then the rate check against the 11b ap will fail, try to demote to
	  11b and retry the rate check

Affected files ...

.. //depot/projects/vap/sys/net80211/ieee80211_scan_sta.c#28 edit

Differences ...

==== //depot/projects/vap/sys/net80211/ieee80211_scan_sta.c#28 (text+ko) ====

@@ -73,8 +73,7 @@
 	uint8_t		se_seen;		/* seen during current scan */
 	uint8_t		se_notseen;		/* not seen in previous scans */
 	uint8_t		se_flags;
-#define	STA_SSID_MATCH	0x01
-#define	STA_BSSID_MATCH	0x02
+#define	STA_DEMOTE11B	0x01			/* match w/ demoted 11b chan */
 	uint32_t	se_avgrssi;		/* LPF rssi state */
 	unsigned long	se_lastupdate;		/* time of last update */
 	unsigned long	se_lastfail;		/* time of last failure */
@@ -675,7 +674,27 @@
 	((uint16_t)					\
 	 ((((const uint8_t *)(p))[0]      ) |		\
 	  (((const uint8_t *)(p))[1] <<  8)))
+ 
+/*
+ * Demote any supplied 11g channel to 11b.  There should
+ * always be an 11b channel but we check anyway...
+ */
+static struct ieee80211_channel *
+demote11b(struct ieee80211vap *vap, struct ieee80211_channel *chan)
+{
+	struct ieee80211_channel *c;
 
+	if (IEEE80211_IS_CHAN_ANYG(chan) &&
+	    vap->iv_des_mode == IEEE80211_MODE_AUTO) {
+		c = ieee80211_find_channel(vap->iv_ic, chan->ic_freq,
+		    (chan->ic_flags &~ (IEEE80211_CHAN_PUREG | IEEE80211_CHAN_G)) |
+		    IEEE80211_CHAN_B);
+		if (c != NULL)
+			chan = c;
+	}
+	return chan;
+}
+
 static int
 maxrate(const struct ieee80211_scan_entry *se)
 {
@@ -774,7 +793,8 @@
  * XXX inspect MCS for HT
  */
 static int
-check_rate(struct ieee80211vap *vap, const struct ieee80211_scan_entry *se)
+check_rate(struct ieee80211vap *vap, const struct ieee80211_channel *chan,
+    const struct ieee80211_scan_entry *se)
 {
 #define	RV(v)	((v) & IEEE80211_RATE_VAL)
 	const struct ieee80211_rateset *srs;
@@ -783,11 +803,11 @@
 
 	okrate = badrate = 0;
 
-	srs = ieee80211_get_suprates(vap->iv_ic, se->se_chan);
+	srs = ieee80211_get_suprates(vap->iv_ic, chan);
 	nrs = se->se_rates[1];
 	rs = se->se_rates+2;
 	/* XXX MCS */
-	ucastrate = vap->iv_txparms[ieee80211_chan2mode(se->se_chan)].ucastrate;
+	ucastrate = vap->iv_txparms[ieee80211_chan2mode(chan)].ucastrate;
 	fixedrate = IEEE80211_FIXED_RATE_NONE;
 again:
 	for (i = 0; i < nrs; i++) {
@@ -903,9 +923,38 @@
 		if (se->se_capinfo & IEEE80211_CAPINFO_PRIVACY)
 			fail |= MATCH_PRIVACY;
 	}
-	rate = check_rate(vap, se);
-	if (rate & IEEE80211_RATE_BASIC)
+	se0->se_flags &= ~STA_DEMOTE11B;
+	rate = check_rate(vap, se->se_chan, se);
+	if (rate & IEEE80211_RATE_BASIC) {
 		fail |= MATCH_RATE;
+		/*
+		 * An 11b-only ap will give a rate mismatch if there is an
+		 * OFDM fixed tx rate for 11g.  Try downgrading the channel
+		 * in the scan list to 11b and retry the rate check.
+		 */
+		if (IEEE80211_IS_CHAN_ANYG(se->se_chan)) {
+			rate = check_rate(vap, demote11b(vap, se->se_chan), se);
+			if ((rate & IEEE80211_RATE_BASIC) == 0) {
+				fail &= ~MATCH_RATE;
+				se0->se_flags |= STA_DEMOTE11B;
+			}
+		}
+	} else if (rate < 2*24) {
+		/*
+		 * This is an 11b-only ap.  Check the desired mode in
+		 * case that needs to be honored (mode 11g filters out
+		 * 11b-only ap's).  Otherwise force any 11g channel used
+		 * in scanning to be demoted.
+		 *
+		 * NB: we cheat a bit here by looking at the max rate;
+		 *     we could/should check the rates.
+		 */
+		if (!(vap->iv_des_mode == IEEE80211_MODE_AUTO ||
+		      vap->iv_des_mode == IEEE80211_MODE_11B))
+			fail |= MATCH_RATE;
+		else
+			se0->se_flags |= STA_DEMOTE11B;
+	}
 	if (ss->ss_nssid != 0 &&
 	    !match_ssid(se->se_ssid, ss->ss_nssid, ss->ss_ssid))
 		fail |= MATCH_SSID;
@@ -1060,6 +1109,8 @@
 	if (selbs == NULL)
 		goto notfound;
 	chan = selbs->base.se_chan;
+	if (selbs->se_flags & STA_DEMOTE11B)
+		chan = demote11b(vap, chan);
 	if (!ieee80211_sta_join(vap, chan, &selbs->base))
 		goto notfound;
 	return 1;				/* terminate scan */
@@ -1151,6 +1202,8 @@
 			    curRate, roamRate, curRssi, roamRssi);
 
 			chan = selbs->base.se_chan;
+			if (selbs->se_flags & STA_DEMOTE11B)
+				chan = demote11b(vap, chan);
 			(void) ieee80211_sta_join(vap, chan, &selbs->base);
 		}
 	}
@@ -1430,6 +1483,8 @@
 	if (selbs == NULL)
 		goto notfound;
 	chan = selbs->base.se_chan;
+	if (selbs->se_flags & STA_DEMOTE11B)
+		chan = demote11b(vap, chan);
 	if (!ieee80211_sta_join(vap, chan, &selbs->base))
 		goto notfound;
 	return 1;				/* terminate scan */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200810250110.m9P1A7qj041833>