diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2017-04-04 09:36:57 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2017-04-04 14:46:23 +0200 |
commit | de8a76da2f374792594ce03a203b3f30e4889f6f (patch) | |
tree | 12b5e1e59358005c3c522955c08aee4795e4829c /freebsd/sys/net80211/ieee80211_node.c | |
parent | Enable bridging by default (diff) | |
download | rtems-libbsd-de8a76da2f374792594ce03a203b3f30e4889f6f.tar.bz2 |
Update to FreeBSD head 2017-04-04
Git mirror commit 642b174daddbd0efd9bb5f242c43f4ab4db6869f.
Diffstat (limited to 'freebsd/sys/net80211/ieee80211_node.c')
-rw-r--r-- | freebsd/sys/net80211/ieee80211_node.c | 169 |
1 files changed, 158 insertions, 11 deletions
diff --git a/freebsd/sys/net80211/ieee80211_node.c b/freebsd/sys/net80211/ieee80211_node.c index c9c6df96..b15a782f 100644 --- a/freebsd/sys/net80211/ieee80211_node.c +++ b/freebsd/sys/net80211/ieee80211_node.c @@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$"); #include <net80211/ieee80211_wds.h> #include <net80211/ieee80211_mesh.h> #include <net80211/ieee80211_ratectl.h> +#include <net80211/ieee80211_vht.h> #include <net/bpf.h> @@ -350,7 +351,6 @@ ieee80211_create_ibss(struct ieee80211vap* vap, struct ieee80211_channel *chan) ni->ni_fhindex = 1; } if (vap->iv_opmode == IEEE80211_M_IBSS) { - vap->iv_flags |= IEEE80211_F_SIBSS; ni->ni_capinfo |= IEEE80211_CAPINFO_IBSS; /* XXX */ if (vap->iv_flags & IEEE80211_F_DESBSSID) IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_des_bssid); @@ -414,7 +414,11 @@ ieee80211_create_ibss(struct ieee80211vap* vap, struct ieee80211_channel *chan) /* XXX TODO: other bits and pieces - eg fast-frames? */ /* If we're an 11n channel then initialise the 11n bits */ - if (IEEE80211_IS_CHAN_HT(ni->ni_chan)) { + if (IEEE80211_IS_CHAN_VHT(ni->ni_chan)) { + /* XXX what else? */ + ieee80211_ht_node_init(ni); + ieee80211_vht_node_init(ni); + } else if (IEEE80211_IS_CHAN_HT(ni->ni_chan)) { /* XXX what else? */ ieee80211_ht_node_init(ni); } @@ -710,9 +714,42 @@ gethtadjustflags(struct ieee80211com *ic) } /* + * Calculate VHT channel promotion flags for all vaps. + * This assumes ni_chan have been setup for each vap. + */ +static int +getvhtadjustflags(struct ieee80211com *ic) +{ + struct ieee80211vap *vap; + int flags; + + flags = 0; + /* XXX locking */ + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { + if (vap->iv_state < IEEE80211_S_RUN) + continue; + switch (vap->iv_opmode) { + case IEEE80211_M_WDS: + case IEEE80211_M_STA: + case IEEE80211_M_AHDEMO: + case IEEE80211_M_HOSTAP: + case IEEE80211_M_IBSS: + case IEEE80211_M_MBSS: + flags |= ieee80211_vhtchanflags(vap->iv_bss->ni_chan); + break; + default: + break; + } + } + return flags; +} + +/* * Check if the current channel needs to change based on whether * any vap's are using HT20/HT40. This is used to sync the state * of ic_curchan after a channel width change on a running vap. + * + * Same applies for VHT. */ void ieee80211_sync_curchan(struct ieee80211com *ic) @@ -720,6 +757,8 @@ ieee80211_sync_curchan(struct ieee80211com *ic) struct ieee80211_channel *c; c = ieee80211_ht_adjust_channel(ic, ic->ic_curchan, gethtadjustflags(ic)); + c = ieee80211_vht_adjust_channel(ic, c, getvhtadjustflags(ic)); + if (c != ic->ic_curchan) { ic->ic_curchan = c; ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan); @@ -745,10 +784,23 @@ ieee80211_setupcurchan(struct ieee80211com *ic, struct ieee80211_channel *c) * set of running vap's. This assumes we are called * after ni_chan is setup for each vap. */ + /* XXX VHT? */ /* NB: this assumes IEEE80211_FHT_USEHT40 > IEEE80211_FHT_HT */ if (flags > ieee80211_htchanflags(c)) c = ieee80211_ht_adjust_channel(ic, c, flags); } + + /* + * VHT promotion - this will at least promote to VHT20/40 + * based on what HT has done; it may further promote the + * channel to VHT80 or above. + */ + if (ic->ic_vhtcaps != 0) { + int flags = getvhtadjustflags(ic); + if (flags > ieee80211_vhtchanflags(c)) + c = ieee80211_vht_adjust_channel(ic, c, flags); + } + ic->ic_bsschan = ic->ic_curchan = c; ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan); ic->ic_rt = ieee80211_get_ratetable(ic->ic_curchan); @@ -851,6 +903,7 @@ ieee80211_sta_join(struct ieee80211vap *vap, struct ieee80211_channel *chan, { struct ieee80211com *ic = vap->iv_ic; struct ieee80211_node *ni; + int do_ht = 0; ni = ieee80211_alloc_node(&ic->ic_sta, vap, se->se_macaddr); if (ni == NULL) { @@ -898,9 +951,13 @@ ieee80211_sta_join(struct ieee80211vap *vap, struct ieee80211_channel *chan, if (ni->ni_ies.tdma_ie != NULL) ieee80211_parse_tdma(ni, ni->ni_ies.tdma_ie); #endif + if (ni->ni_ies.vhtcap_ie != NULL) + ieee80211_parse_vhtcap(ni, ni->ni_ies.vhtcap_ie); + if (ni->ni_ies.vhtopmode_ie != NULL) + ieee80211_parse_vhtopmode(ni, ni->ni_ies.vhtopmode_ie); - /* XXX parse VHT IEs */ /* XXX parse BSSLOAD IE */ + /* XXX parse TXPWRENV IE */ /* XXX parse APCHANREP IE */ } @@ -928,10 +985,43 @@ ieee80211_sta_join(struct ieee80211vap *vap, struct ieee80211_channel *chan, ieee80211_ht_updateparams(ni, ni->ni_ies.htcap_ie, ni->ni_ies.htinfo_ie); + do_ht = 1; + } + + /* + * Setup VHT state for this node if it's available. + * Same as the above. + * + * For now, don't allow 2GHz VHT operation. + */ + if (ni->ni_ies.vhtopmode_ie != NULL && + ni->ni_ies.vhtcap_ie != NULL && + vap->iv_flags_vht & IEEE80211_FVHT_VHT) { + if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) { + printf("%s: BSS %6D: 2GHz channel, VHT info; ignoring\n", + __func__, + ni->ni_macaddr, + ":"); + } else { + ieee80211_vht_node_init(ni); + ieee80211_vht_updateparams(ni, + ni->ni_ies.vhtcap_ie, + ni->ni_ies.vhtopmode_ie); + ieee80211_setup_vht_rates(ni, ni->ni_ies.vhtcap_ie, + ni->ni_ies.vhtopmode_ie); + do_ht = 1; + } + } + + /* Finally do the node channel change */ + if (do_ht) { + ieee80211_ht_updateparams_final(ni, ni->ni_ies.htcap_ie, + ni->ni_ies.htinfo_ie); ieee80211_setup_htrates(ni, ni->ni_ies.htcap_ie, IEEE80211_F_JOIN | IEEE80211_F_DOBRS); ieee80211_setup_basic_htrates(ni, ni->ni_ies.htinfo_ie); } + /* XXX else check for ath FF? */ /* XXX QoS? Difficult given that WME config is specific to a master */ @@ -1104,8 +1194,10 @@ node_cleanup(struct ieee80211_node *ni) "power save mode off, %u sta's in ps mode", vap->iv_ps_sta); } /* - * Cleanup any HT-related state. + * Cleanup any VHT and HT-related state. */ + if (ni->ni_flags & IEEE80211_NODE_VHT) + ieee80211_vht_node_cleanup(ni); if (ni->ni_flags & IEEE80211_NODE_HT) ieee80211_ht_node_cleanup(ni); #ifdef IEEE80211_SUPPORT_SUPERG @@ -1228,15 +1320,16 @@ node_getmimoinfo(const struct ieee80211_node *ni, bzero(info, sizeof(*info)); - for (i = 0; i < ni->ni_mimo_chains; i++) { + for (i = 0; i < MIN(IEEE80211_MAX_CHAINS, ni->ni_mimo_chains); i++) { + /* Note: for now, just pri20 channel info */ avgrssi = ni->ni_mimo_rssi_ctl[i]; if (avgrssi == IEEE80211_RSSI_DUMMY_MARKER) { - info->rssi[i] = 0; + info->ch[i].rssi[0] = 0; } else { rssi = IEEE80211_RSSI_GET(avgrssi); - info->rssi[i] = rssi < 0 ? 0 : rssi > 127 ? 127 : rssi; + info->ch[i].rssi[0] = rssi < 0 ? 0 : rssi > 127 ? 127 : rssi; } - info->noise[i] = ni->ni_mimo_noise_ctl[i]; + info->ch[i].noise[0] = ni->ni_mimo_noise_ctl[i]; } /* XXX ext radios? */ @@ -1425,6 +1518,7 @@ ieee80211_node_create_wds(struct ieee80211vap *vap, if (vap->iv_flags & IEEE80211_F_FF) ni->ni_flags |= IEEE80211_NODE_FF; #endif + /* XXX VHT */ if ((ic->ic_htcaps & IEEE80211_HTC_HT) && (vap->iv_flags_ht & IEEE80211_FHT_HT)) { /* @@ -1433,6 +1527,9 @@ ieee80211_node_create_wds(struct ieee80211vap *vap, * ni_chan will be adjusted to an HT channel. */ ieee80211_ht_wds_init(ni); + if (vap->iv_flags_vht & IEEE80211_FVHT_VHT) { + printf("%s: TODO: vht_wds_init\n", __func__); + } } else { struct ieee80211_channel *c = ni->ni_chan; /* @@ -1640,7 +1737,7 @@ ieee80211_init_neighbor(struct ieee80211_node *ni, const struct ieee80211_frame *wh, const struct ieee80211_scanparams *sp) { - int do_ht_setup = 0; + int do_ht_setup = 0, do_vht_setup = 0; ni->ni_esslen = sp->ssid[1]; memcpy(ni->ni_essid, sp->ssid + 2, sp->ssid[1]); @@ -1672,11 +1769,23 @@ ieee80211_init_neighbor(struct ieee80211_node *ni, if (ni->ni_ies.htinfo_ie != NULL) ieee80211_parse_htinfo(ni, ni->ni_ies.htinfo_ie); + if (ni->ni_ies.vhtcap_ie != NULL) + ieee80211_parse_vhtcap(ni, ni->ni_ies.vhtcap_ie); + if (ni->ni_ies.vhtopmode_ie != NULL) + ieee80211_parse_vhtopmode(ni, ni->ni_ies.vhtopmode_ie); + if ((ni->ni_ies.htcap_ie != NULL) && (ni->ni_ies.htinfo_ie != NULL) && (ni->ni_vap->iv_flags_ht & IEEE80211_FHT_HT)) { do_ht_setup = 1; } + + if ((ni->ni_ies.vhtcap_ie != NULL) && + (ni->ni_ies.vhtopmode_ie != NULL) && + (ni->ni_vap->iv_flags_vht & IEEE80211_FVHT_VHT)) { + do_vht_setup = 1; + } + } /* NB: must be after ni_chan is setup */ @@ -1694,15 +1803,40 @@ ieee80211_init_neighbor(struct ieee80211_node *ni, ieee80211_ht_updateparams(ni, ni->ni_ies.htcap_ie, ni->ni_ies.htinfo_ie); + + if (do_vht_setup) { + if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) { + printf("%s: BSS %6D: 2GHz channel, VHT info; ignoring\n", + __func__, + ni->ni_macaddr, + ":"); + } else { + ieee80211_vht_node_init(ni); + ieee80211_vht_updateparams(ni, + ni->ni_ies.vhtcap_ie, + ni->ni_ies.vhtopmode_ie); + ieee80211_setup_vht_rates(ni, + ni->ni_ies.vhtcap_ie, + ni->ni_ies.vhtopmode_ie); + } + } + + /* + * Finally do the channel upgrade/change based + * on the HT/VHT configuration. + */ + ieee80211_ht_updateparams_final(ni, ni->ni_ies.htcap_ie, + ni->ni_ies.htinfo_ie); ieee80211_setup_htrates(ni, ni->ni_ies.htcap_ie, IEEE80211_F_JOIN | IEEE80211_F_DOBRS); ieee80211_setup_basic_htrates(ni, ni->ni_ies.htinfo_ie); + ieee80211_node_setuptxparms(ni); ieee80211_ratectl_node_init(ni); - /* Reassociate; we're now 11n */ + /* Reassociate; we're now 11n/11ac */ /* * XXX TODO: this is the wrong thing to do - * we're calling it with isnew=1 so the ath(4) @@ -2367,6 +2501,7 @@ ieee80211_node_timeout(void *arg) IEEE80211_LOCK(ic); ieee80211_erp_timeout(ic); ieee80211_ht_timeout(ic); + ieee80211_vht_timeout(ic); IEEE80211_UNLOCK(ic); } callout_reset(&ic->ic_inact, IEEE80211_INACT_WAIT*hz, @@ -2464,8 +2599,12 @@ ieee80211_dump_node(struct ieee80211_node_table *nt, struct ieee80211_node *ni) printf("\thtcap %x htparam %x htctlchan %u ht2ndchan %u\n", ni->ni_htcap, ni->ni_htparam, ni->ni_htctlchan, ni->ni_ht2ndchan); - printf("\thtopmode %x htstbc %x chw %u\n", + printf("\thtopmode %x htstbc %x htchw %u\n", ni->ni_htopmode, ni->ni_htstbc, ni->ni_chw); + printf("\tvhtcap %x freq1 %d freq2 %d vhtbasicmcs %x\n", + ni->ni_vhtcap, (int) ni->ni_vht_chan1, (int) ni->ni_vht_chan2, + (int) ni->ni_vht_basicmcs); + /* XXX VHT state */ } void @@ -2596,6 +2735,8 @@ ieee80211_node_join(struct ieee80211_node *ni, int resp) if (IEEE80211_IS_CHAN_HT(ic->ic_bsschan)) ieee80211_ht_node_join(ni); + if (IEEE80211_IS_CHAN_VHT(ic->ic_bsschan)) + ieee80211_vht_node_join(ni); if (IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan) && IEEE80211_IS_CHAN_FULL(ic->ic_bsschan)) ieee80211_node_join_11g(ni); @@ -2605,6 +2746,9 @@ ieee80211_node_join(struct ieee80211_node *ni, int resp) } else newassoc = 0; + /* + * XXX VHT - should log VHT channel width, etc + */ IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG, ni, "station associated at aid %d: %s preamble, %s slot time%s%s%s%s%s%s%s%s", IEEE80211_NODE_AID(ni), @@ -2612,6 +2756,7 @@ ieee80211_node_join(struct ieee80211_node *ni, int resp) ic->ic_flags & IEEE80211_F_SHSLOT ? "short" : "long", ic->ic_flags & IEEE80211_F_USEPROT ? ", protection" : "", ni->ni_flags & IEEE80211_NODE_QOS ? ", QoS" : "", + /* XXX update for VHT string */ ni->ni_flags & IEEE80211_NODE_HT ? (ni->ni_chw == 40 ? ", HT40" : ", HT20") : "", ni->ni_flags & IEEE80211_NODE_AMPDU ? " (+AMPDU)" : "", @@ -2776,6 +2921,8 @@ ieee80211_node_leave(struct ieee80211_node *ni) vap->iv_sta_assoc--; ic->ic_sta_assoc--; + if (IEEE80211_IS_CHAN_VHT(ic->ic_bsschan)) + ieee80211_vht_node_leave(ni); if (IEEE80211_IS_CHAN_HT(ic->ic_bsschan)) ieee80211_ht_node_leave(ni); if (IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan) && |