summaryrefslogtreecommitdiff
path: root/freebsd/sys/net80211/ieee80211_scan_sta.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/net80211/ieee80211_scan_sta.c')
-rw-r--r--freebsd/sys/net80211/ieee80211_scan_sta.c46
1 files changed, 40 insertions, 6 deletions
diff --git a/freebsd/sys/net80211/ieee80211_scan_sta.c b/freebsd/sys/net80211/ieee80211_scan_sta.c
index faaaf8a3..cbef5cd8 100644
--- a/freebsd/sys/net80211/ieee80211_scan_sta.c
+++ b/freebsd/sys/net80211/ieee80211_scan_sta.c
@@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$");
#include <net80211/ieee80211_mesh.h>
#endif
#include <net80211/ieee80211_ratectl.h>
+#include <net80211/ieee80211_vht.h>
#include <net/bpf.h>
@@ -327,14 +328,33 @@ found:
}
} else
ise->se_chan = curchan;
+
+ /* VHT demotion */
+ if (IEEE80211_IS_CHAN_VHT(ise->se_chan) && sp->vhtcap == NULL) {
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_11N,
+ "%s: demoting VHT->HT %d/0x%08x\n",
+ __func__, ise->se_chan->ic_freq, ise->se_chan->ic_flags);
+ /* Demote legacy networks to a non-VHT channel. */
+ c = ieee80211_find_channel(ic, ise->se_chan->ic_freq,
+ ise->se_chan->ic_flags & ~IEEE80211_CHAN_VHT);
+ KASSERT(c != NULL,
+ ("no non-VHT channel %u", ise->se_chan->ic_ieee));
+ ise->se_chan = c;
+ }
+
+ /* HT demotion */
if (IEEE80211_IS_CHAN_HT(ise->se_chan) && sp->htcap == NULL) {
/* Demote legacy networks to a non-HT channel. */
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_11N,
+ "%s: demoting HT->legacy %d/0x%08x\n",
+ __func__, ise->se_chan->ic_freq, ise->se_chan->ic_flags);
c = ieee80211_find_channel(ic, ise->se_chan->ic_freq,
ise->se_chan->ic_flags & ~IEEE80211_CHAN_HT);
KASSERT(c != NULL,
("no legacy channel %u", ise->se_chan->ic_ieee));
ise->se_chan = c;
}
+
ise->se_fhdwell = sp->fhdwell;
ise->se_fhindex = sp->fhindex;
ise->se_erp = sp->erp;
@@ -533,10 +553,11 @@ sweepchannels(struct ieee80211_scan_state *ss, struct ieee80211vap *vap,
/*
* Ignore dynamic turbo channels; we scan them
* in normal mode (i.e. not boosted). Likewise
- * for HT channels, they get scanned using
+ * for HT/VHT channels, they get scanned using
* legacy rates.
*/
- if (IEEE80211_IS_CHAN_DTURBO(c) || IEEE80211_IS_CHAN_HT(c))
+ if (IEEE80211_IS_CHAN_DTURBO(c) || IEEE80211_IS_CHAN_HT(c) ||
+ IEEE80211_IS_CHAN_VHT(c))
continue;
/*
@@ -821,6 +842,9 @@ maxrate(const struct ieee80211_scan_entry *se)
* that we assume compatibility/usability has already been checked
* so we don't need to (e.g. validate whether privacy is supported).
* Used to select the best scan candidate for association in a BSS.
+ *
+ * TODO: should we take 11n, 11ac into account when selecting the
+ * best? Right now it just compares frequency band and RSSI.
*/
static int
sta_compare(const struct sta_entry *a, const struct sta_entry *b)
@@ -1628,6 +1652,8 @@ notfound:
*/
chan = ieee80211_ht_adjust_channel(ic,
chan, vap->iv_flags_ht);
+ chan = ieee80211_vht_adjust_channel(ic,
+ chan, vap->iv_flags_vht);
ieee80211_create_ibss(vap, chan);
return 1;
}
@@ -1659,6 +1685,8 @@ notfound:
*/
chan = ieee80211_ht_adjust_channel(ic,
chan, vap->iv_flags_ht);
+ chan = ieee80211_vht_adjust_channel(ic,
+ chan, vap->iv_flags_vht);
if (!ieee80211_sta_join(vap, chan, &selbs->base))
goto notfound;
return 1; /* terminate scan */
@@ -1778,7 +1806,7 @@ static int
ap_end(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
{
struct ieee80211com *ic = vap->iv_ic;
- struct ieee80211_channel *bestchan;
+ struct ieee80211_channel *bestchan, *chan;
KASSERT(vap->iv_opmode == IEEE80211_M_HOSTAP,
("wrong opmode %u", vap->iv_opmode));
@@ -1810,8 +1838,10 @@ ap_end(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
ss->ss_flags &= ~IEEE80211_SCAN_NOPICK;
return 1;
}
- ieee80211_create_ibss(vap,
- ieee80211_ht_adjust_channel(ic, bestchan, vap->iv_flags_ht));
+ chan = ieee80211_ht_adjust_channel(ic, bestchan, vap->iv_flags_ht);
+ chan = ieee80211_vht_adjust_channel(ic, chan, vap->iv_flags_vht);
+ ieee80211_create_ibss(vap, chan);
+
return 1;
}
@@ -1883,10 +1913,14 @@ notfound:
IEEE80211_IS_CHAN_RADAR(vap->iv_des_chan)) {
struct ieee80211com *ic = vap->iv_ic;
+ /* XXX VHT */
chan = adhoc_pick_channel(ss, 0);
- if (chan != NULL)
+ if (chan != NULL) {
chan = ieee80211_ht_adjust_channel(ic,
chan, vap->iv_flags_ht);
+ chan = ieee80211_vht_adjust_channel(ic,
+ chan, vap->iv_flags_vht);
+ }
} else
chan = vap->iv_des_chan;
if (chan != NULL) {