From owner-svn-src-head@freebsd.org Fri Mar 3 01:06:29 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 6606ECF5CD9; Fri, 3 Mar 2017 01:06:29 +0000 (UTC) (envelope-from avos@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 409AB1C38; Fri, 3 Mar 2017 01:06:29 +0000 (UTC) (envelope-from avos@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v2316Slk082667; Fri, 3 Mar 2017 01:06:28 GMT (envelope-from avos@FreeBSD.org) Received: (from avos@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v2316RPn082661; Fri, 3 Mar 2017 01:06:27 GMT (envelope-from avos@FreeBSD.org) Message-Id: <201703030106.v2316RPn082661@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: avos set sender to avos@FreeBSD.org using -f From: Andriy Voskoboinyk Date: Fri, 3 Mar 2017 01:06:27 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r314575 - head/sys/net80211 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 03 Mar 2017 01:06:29 -0000 Author: avos Date: Fri Mar 3 01:06:27 2017 New Revision: 314575 URL: https://svnweb.freebsd.org/changeset/base/314575 Log: net80211: fix ieee80211_htrateset setup, return EINVAL for an unsupported ucast/mcast/mgmt HT rate. - Init global ieee80211_htrateset only once; neither ic_htcaps nor ic_txstream is changed when device is attached; - Move global ieee80211_htrateset structure to ieee80211com; there was a possible data race when more than 1 wireless device is used simultaneously; - Discard unsupported rates in ieee80211_ioctl_settxparams(); otherwise, an unsupported value may break connectivity (actually, 'ifconfig wlan0 ucastrate 8' for RTL8188EU results in immediate disconnect + infinite 'device timeout's after it). Tested with: - Intel 6205, STA mode. - RTL8821AU, STA mode. Reviewed by: adrian Differential Revision: https://reviews.freebsd.org/D9871 Modified: head/sys/net80211/ieee80211.c head/sys/net80211/ieee80211_ht.c head/sys/net80211/ieee80211_ht.h head/sys/net80211/ieee80211_ioctl.c head/sys/net80211/ieee80211_var.h Modified: head/sys/net80211/ieee80211.c ============================================================================== --- head/sys/net80211/ieee80211.c Fri Mar 3 00:47:42 2017 (r314574) +++ head/sys/net80211/ieee80211.c Fri Mar 3 01:06:27 2017 (r314575) @@ -242,6 +242,8 @@ ieee80211_chan_init(struct ieee80211com if (ic->ic_txstream == 0) ic->ic_txstream = 2; + ieee80211_init_suphtrates(ic); + /* * Set auto mode to reset active channel state and any desired channel. */ @@ -1905,6 +1907,14 @@ ieee80211_get_suprates(struct ieee80211c return &ic->ic_sup_rates[ieee80211_chan2mode(c)]; } +/* XXX inline or eliminate? */ +const struct ieee80211_htrateset * +ieee80211_get_suphtrates(struct ieee80211com *ic, + const struct ieee80211_channel *c) +{ + return &ic->ic_sup_htrates; +} + void ieee80211_announce(struct ieee80211com *ic) { Modified: head/sys/net80211/ieee80211_ht.c ============================================================================== --- head/sys/net80211/ieee80211_ht.c Fri Mar 3 00:47:42 2017 (r314574) +++ head/sys/net80211/ieee80211_ht.c Fri Mar 3 01:06:27 2017 (r314575) @@ -421,19 +421,17 @@ ieee80211_ht_announce(struct ieee80211co ht_announce(ic, IEEE80211_MODE_11NG); } -static struct ieee80211_htrateset htrateset; - -const struct ieee80211_htrateset * -ieee80211_get_suphtrates(struct ieee80211com *ic, - const struct ieee80211_channel *c) +void +ieee80211_init_suphtrates(struct ieee80211com *ic) { #define ADDRATE(x) do { \ - htrateset.rs_rates[htrateset.rs_nrates] = x; \ - htrateset.rs_nrates++; \ + htrateset->rs_rates[htrateset->rs_nrates] = x; \ + htrateset->rs_nrates++; \ } while (0) + struct ieee80211_htrateset *htrateset = &ic->ic_sup_htrates; int i; - memset(&htrateset, 0, sizeof(struct ieee80211_htrateset)); + memset(htrateset, 0, sizeof(struct ieee80211_htrateset)); for (i = 0; i < ic->ic_txstream * 8; i++) ADDRATE(i); if ((ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40) && @@ -453,7 +451,6 @@ ieee80211_get_suphtrates(struct ieee8021 ADDRATE(i); } } - return &htrateset; #undef ADDRATE } Modified: head/sys/net80211/ieee80211_ht.h ============================================================================== --- head/sys/net80211/ieee80211_ht.h Fri Mar 3 00:47:42 2017 (r314574) +++ head/sys/net80211/ieee80211_ht.h Fri Mar 3 01:06:27 2017 (r314575) @@ -177,8 +177,7 @@ struct ieee80211_mcs_rates { uint16_t ht40_rate_400ns; }; extern const struct ieee80211_mcs_rates ieee80211_htrates[]; -const struct ieee80211_htrateset *ieee80211_get_suphtrates( - struct ieee80211com *, const struct ieee80211_channel *); +void ieee80211_init_suphtrates(struct ieee80211com *); struct ieee80211_node; int ieee80211_setup_htrates(struct ieee80211_node *, Modified: head/sys/net80211/ieee80211_ioctl.c ============================================================================== --- head/sys/net80211/ieee80211_ioctl.c Fri Mar 3 00:47:42 2017 (r314574) +++ head/sys/net80211/ieee80211_ioctl.c Fri Mar 3 01:06:27 2017 (r314575) @@ -2226,13 +2226,19 @@ checkrate(const struct ieee80211_rateset } static int -checkmcs(int mcs) +checkmcs(const struct ieee80211_htrateset *rs, int mcs) { + int rate_val = IEEE80211_RV(mcs); + int i; + if (mcs == IEEE80211_FIXED_RATE_NONE) return 1; if ((mcs & IEEE80211_RATE_MCS) == 0) /* MCS always have 0x80 set */ return 0; - return (mcs & 0x7f) <= 31; /* XXX could search ht rate set */ + for (i = 0; i < rs->rs_nrates; i++) + if (IEEE80211_RV(rs->rs_rates[i]) == rate_val) + return 1; + return 0; } static int @@ -2242,6 +2248,7 @@ ieee80211_ioctl_settxparams(struct ieee8 struct ieee80211com *ic = vap->iv_ic; struct ieee80211_txparams_req parms; /* XXX stack use? */ struct ieee80211_txparam *src, *dst; + const struct ieee80211_htrateset *rs_ht; const struct ieee80211_rateset *rs; int error, mode, changed, is11n, nmodes; @@ -2260,23 +2267,24 @@ ieee80211_ioctl_settxparams(struct ieee8 src = &parms.params[mode]; dst = &vap->iv_txparms[mode]; rs = &ic->ic_sup_rates[mode]; /* NB: 11n maps to legacy */ + rs_ht = &ic->ic_sup_htrates; is11n = (mode == IEEE80211_MODE_11NA || mode == IEEE80211_MODE_11NG); if (src->ucastrate != dst->ucastrate) { if (!checkrate(rs, src->ucastrate) && - (!is11n || !checkmcs(src->ucastrate))) + (!is11n || !checkmcs(rs_ht, src->ucastrate))) return EINVAL; changed++; } if (src->mcastrate != dst->mcastrate) { if (!checkrate(rs, src->mcastrate) && - (!is11n || !checkmcs(src->mcastrate))) + (!is11n || !checkmcs(rs_ht, src->mcastrate))) return EINVAL; changed++; } if (src->mgmtrate != dst->mgmtrate) { if (!checkrate(rs, src->mgmtrate) && - (!is11n || !checkmcs(src->mgmtrate))) + (!is11n || !checkmcs(rs_ht, src->mgmtrate))) return EINVAL; changed++; } Modified: head/sys/net80211/ieee80211_var.h ============================================================================== --- head/sys/net80211/ieee80211_var.h Fri Mar 3 00:47:42 2017 (r314574) +++ head/sys/net80211/ieee80211_var.h Fri Mar 3 01:06:27 2017 (r314575) @@ -175,6 +175,7 @@ struct ieee80211com { uint16_t ic_holdover; /* PM hold over duration */ uint16_t ic_txpowlimit; /* global tx power limit */ struct ieee80211_rateset ic_sup_rates[IEEE80211_MODE_MAX]; + struct ieee80211_htrateset ic_sup_htrates; /* * Channel state: @@ -692,6 +693,8 @@ int ieee80211_vap_attach(struct ieee8021 void ieee80211_vap_detach(struct ieee80211vap *); const struct ieee80211_rateset *ieee80211_get_suprates(struct ieee80211com *ic, const struct ieee80211_channel *); +const struct ieee80211_htrateset *ieee80211_get_suphtrates( + struct ieee80211com *, const struct ieee80211_channel *); void ieee80211_announce(struct ieee80211com *); void ieee80211_announce_channels(struct ieee80211com *); void ieee80211_drain(struct ieee80211com *);