From owner-p4-projects@FreeBSD.ORG Sun Jan 27 20:24:55 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id C051A16A419; Sun, 27 Jan 2008 20:24:54 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 53B6016A41B for ; Sun, 27 Jan 2008 20:24:54 +0000 (UTC) (envelope-from sam@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 43BEE13C45A for ; Sun, 27 Jan 2008 20:24:54 +0000 (UTC) (envelope-from sam@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id m0RKOswX037695 for ; Sun, 27 Jan 2008 20:24:54 GMT (envelope-from sam@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id m0RKOrJP037692 for perforce@freebsd.org; Sun, 27 Jan 2008 20:24:53 GMT (envelope-from sam@freebsd.org) Date: Sun, 27 Jan 2008 20:24:53 GMT Message-Id: <200801272024.m0RKOrJP037692@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to sam@freebsd.org using -f From: Sam Leffler To: Perforce Change Reviews Cc: Subject: PERFORCE change 134234 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 27 Jan 2008 20:24:55 -0000 http://perforce.freebsd.org/chv.cgi?CH=134234 Change 134234 by sam@sam_ebb on 2008/01/27 20:24:31 Add support for mixed ht/legacy ap vaps: o ic_bsschan now holds the promoted bss channel shared by all ap vaps and iv_bss->ni_chan now holds the bss channel for all ap vaps; adjust references appropriaately o adjust bss channel on CSA state change for ap vaps o don't do direct channel change of WDS vaps; it is now necessary to go through the state machine to adjust the bss node's channel o promote htchanflags to ieee80211_htchanflags for use in per-opmode code when handling channel changes o move legacy wds setup work to new ieee80211_node_create_wds routine o make ieee80211_setcurchan set ic_bsschan and remove set from callers o encapsulate idiomatic ioctl code Note: drivers need adjusting only if they support HT operation; for legacy operation you can still safely reference ic_bsschan Affected files ... .. //depot/projects/vap/sys/net80211/ieee80211_hostap.c#8 edit .. //depot/projects/vap/sys/net80211/ieee80211_ht.c#6 edit .. //depot/projects/vap/sys/net80211/ieee80211_ht.h#5 edit .. //depot/projects/vap/sys/net80211/ieee80211_ioctl.c#23 edit .. //depot/projects/vap/sys/net80211/ieee80211_node.c#22 edit .. //depot/projects/vap/sys/net80211/ieee80211_node.h#15 edit .. //depot/projects/vap/sys/net80211/ieee80211_output.c#25 edit .. //depot/projects/vap/sys/net80211/ieee80211_proto.c#19 edit .. //depot/projects/vap/sys/net80211/ieee80211_var.h#24 edit .. //depot/projects/vap/sys/net80211/ieee80211_wds.c#4 edit Differences ... ==== //depot/projects/vap/sys/net80211/ieee80211_hostap.c#8 (text+ko) ==== @@ -242,9 +242,18 @@ * clear the CAC timer as it's already expired. */ /* fall thru... */ + case IEEE80211_S_CSA: + /* + * Update bss node channel to reflect where + * we landed after CSA. + */ + ieee80211_node_set_chan(vap->iv_bss, + ieee80211_ht_adjust_channel(ic, ic->ic_curchan, + ieee80211_htchanflags(vap->iv_bss->ni_chan))); + /* XXX bypass debug msgs */ + break; case IEEE80211_S_SCAN: case IEEE80211_S_RUN: - case IEEE80211_S_CSA: #ifdef IEEE80211_DEBUG if (ieee80211_msg_debug(vap)) { struct ieee80211_node *ni = vap->iv_bss; @@ -2044,7 +2053,8 @@ /* * Do HT rate set handling and setup HT node state. */ - if (IEEE80211_IS_CHAN_HT(ic->ic_bsschan) && htcap != NULL) { + ni->ni_chan = vap->iv_bss->ni_chan; + if (IEEE80211_IS_CHAN_HT(ni->ni_chan) && htcap != NULL) { rate = ieee80211_setup_htrates(ni, htcap, IEEE80211_F_DOFMCS | IEEE80211_F_DONEGO | IEEE80211_F_DOBRS); @@ -2089,7 +2099,6 @@ ni->ni_rstamp = rstamp; ni->ni_intval = lintval; ni->ni_capinfo = capinfo; - ni->ni_chan = ic->ic_bsschan; ni->ni_fhdwell = vap->iv_bss->ni_fhdwell; ni->ni_fhindex = vap->iv_bss->ni_fhindex; /* ==== //depot/projects/vap/sys/net80211/ieee80211_ht.c#6 (text+ko) ==== @@ -859,7 +859,7 @@ * for the extension channel). */ ni->ni_chan = ieee80211_ht_adjust_channel(ni->ni_ic, - ni->ni_chan, vap->iv_flags_ext); + ni->ni_chan, ieee80211_htchanflags(ni->ni_chan)); ni->ni_htcap = 0; if (vap->iv_flags_ext & IEEE80211_FEXT_SHORTGI20) @@ -1762,9 +1762,9 @@ IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, "send HT txchwidth: width %d", - IEEE80211_IS_CHAN_HT40(ic->ic_bsschan) ? 40 : 20 + IEEE80211_IS_CHAN_HT40(ni->ni_chan) ? 40 : 20 ); - *frm++ = IEEE80211_IS_CHAN_HT40(ic->ic_bsschan) ? + *frm++ = IEEE80211_IS_CHAN_HT40(ni->ni_chan) ? IEEE80211_A_HT_TXCHWIDTH_2040 : IEEE80211_A_HT_TXCHWIDTH_20; break; @@ -1823,7 +1823,6 @@ frm += 2; \ } while (0) struct ieee80211vap *vap = ni->ni_vap; - struct ieee80211com *ic = ni->ni_ic; uint16_t caps; int rxmax, density; @@ -1848,7 +1847,7 @@ density = MS(ni->ni_htparam, IEEE80211_HTCAP_MPDUDENSITY); } else { /* override 20/40 use based on current channel */ - if (IEEE80211_IS_CHAN_HT40(ic->ic_bsschan)) + if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) caps |= IEEE80211_HTCAP_CHWIDTH40; else caps &= ~IEEE80211_HTCAP_CHWIDTH40; @@ -1942,20 +1941,21 @@ struct ieee80211_beacon_offsets *bo) { #define PROTMODE (IEEE80211_HTINFO_OPMODE|IEEE80211_HTINFO_NONHT_PRESENT) + const struct ieee80211_channel *bsschan = vap->iv_bss->ni_chan; struct ieee80211com *ic = vap->iv_ic; struct ieee80211_ie_htinfo *ht = (struct ieee80211_ie_htinfo *) bo->bo_htinfo; /* XXX only update on channel change */ - ht->hi_ctrlchannel = ieee80211_chan2ieee(ic, ic->ic_bsschan); + ht->hi_ctrlchannel = ieee80211_chan2ieee(ic, bsschan); ht->hi_byte1 = IEEE80211_HTINFO_RIFSMODE_PROH; - if (IEEE80211_IS_CHAN_HT40U(ic->ic_bsschan)) + if (IEEE80211_IS_CHAN_HT40U(bsschan)) ht->hi_byte1 |= IEEE80211_HTINFO_2NDCHAN_ABOVE; - else if (IEEE80211_IS_CHAN_HT40D(ic->ic_bsschan)) + else if (IEEE80211_IS_CHAN_HT40D(bsschan)) ht->hi_byte1 |= IEEE80211_HTINFO_2NDCHAN_BELOW; else ht->hi_byte1 |= IEEE80211_HTINFO_2NDCHAN_NONE; - if (IEEE80211_IS_CHAN_HT40(ic->ic_bsschan)) + if (IEEE80211_IS_CHAN_HT40(bsschan)) ht->hi_byte1 |= IEEE80211_HTINFO_TXWIDTH_2040; /* protection mode */ @@ -1981,16 +1981,16 @@ memset(frm, 0, sizeof(struct ieee80211_ie_htinfo) - 2); /* primary/control channel center */ - *frm++ = ieee80211_chan2ieee(ic, ic->ic_bsschan); + *frm++ = ieee80211_chan2ieee(ic, ni->ni_chan); frm[0] = IEEE80211_HTINFO_RIFSMODE_PROH; - if (IEEE80211_IS_CHAN_HT40U(ic->ic_bsschan)) + if (IEEE80211_IS_CHAN_HT40U(ni->ni_chan)) frm[0] |= IEEE80211_HTINFO_2NDCHAN_ABOVE; - else if (IEEE80211_IS_CHAN_HT40D(ic->ic_bsschan)) + else if (IEEE80211_IS_CHAN_HT40D(ni->ni_chan)) frm[0] |= IEEE80211_HTINFO_2NDCHAN_BELOW; else frm[0] |= IEEE80211_HTINFO_2NDCHAN_NONE; - if (IEEE80211_IS_CHAN_HT40(ic->ic_bsschan)) + if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) frm[0] |= IEEE80211_HTINFO_TXWIDTH_2040; frm[1] = ic->ic_curhtprotmode; ==== //depot/projects/vap/sys/net80211/ieee80211_ht.h#5 (text+ko) ==== @@ -99,6 +99,7 @@ void ieee80211_recv_bar(struct ieee80211_node *, struct mbuf *); void ieee80211_ht_node_init(struct ieee80211_node *, const uint8_t *); void ieee80211_ht_node_cleanup(struct ieee80211_node *); + struct ieee80211_channel *ieee80211_ht_adjust_channel(struct ieee80211com *, struct ieee80211_channel *, int); void ieee80211_ht_wds_init(struct ieee80211_node *); ==== //depot/projects/vap/sys/net80211/ieee80211_ioctl.c#23 (text+ko) ==== @@ -592,17 +592,11 @@ /* * vap's may have different operating channels when HT is * in use. When in RUN state report the vap-specific channel. - * Otherwise return curchan. Note that vap's that beacon use - * ic_bsschan while other vap's use ni_chan. This won't - * work for multiple ap's and must be fixed. + * Otherwise return curchan. */ - if (vap->iv_state == IEEE80211_S_RUN) { - if (vap->iv_opmode == IEEE80211_M_WDS || - vap->iv_opmode == IEEE80211_M_STA) - c = vap->iv_bss->ni_chan; - else - c = ic->ic_bsschan; - } else + if (vap->iv_state == IEEE80211_S_RUN) + c = vap->iv_bss->ni_chan; + else c = ic->ic_curchan; return copyout(c, ireq->i_data, sizeof(*c)); } @@ -1730,22 +1724,21 @@ if (IEEE80211_IS_CHAN_NOADHOC(c)) return EINVAL; } - if (vap->iv_state == IEEE80211_S_RUN && c == ic->ic_bsschan) + if (vap->iv_state == IEEE80211_S_RUN && + vap->iv_bss->ni_chan == c) return 0; /* NB: nothing to do */ } vap->iv_des_chan = c; error = 0; - if ((vap->iv_opmode == IEEE80211_M_MONITOR || - vap->iv_opmode == IEEE80211_M_WDS) && + if (vap->iv_opmode == IEEE80211_M_MONITOR && vap->iv_des_chan != IEEE80211_CHAN_ANYC) { /* - * Monitor and wds modes can switch directly. + * Monitor mode can switch directly. */ - ic->ic_curchan = vap->iv_des_chan; - /* XXX ieee80211_setcurchan? */ - if (vap->iv_state == IEEE80211_S_RUN) - ic->ic_set_channel(ic); + ieee80211_setcurchan(ic, vap->iv_des_chan); + vap->iv_bss->ni_chan = ic->ic_curchan; + /* XXX kick other vap's to follow */ } else { /* * Need to go through the state machine in case we @@ -2390,6 +2383,22 @@ } static int +isvap11g(const struct ieee80211vap *vap) +{ + const struct ieee80211_node *bss = vap->iv_bss; + return bss->ni_chan != IEEE80211_CHAN_ANYC && + IEEE80211_IS_CHAN_ANYG(bss->ni_chan); +} + +static int +isvapht(const struct ieee80211vap *vap) +{ + const struct ieee80211_node *bss = vap->iv_bss; + return bss->ni_chan != IEEE80211_CHAN_ANYC && + IEEE80211_IS_CHAN_HT(bss->ni_chan); +} + +static int ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211req *ireq) { static const uint8_t zerobssid[IEEE80211_ADDR_LEN]; @@ -2754,8 +2763,7 @@ else vap->iv_flags &= ~IEEE80211_F_PUREG; /* NB: reset only if we're operating on an 11g channel */ - if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && - IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan)) + if (isvap11g(vap)) error = ENETRESET; break; case IEEE80211_IOC_FF: @@ -2859,8 +2867,7 @@ else vap->iv_flags_ext &= ~IEEE80211_FEXT_AMPDU_RX; /* NB: reset only if we're operating on an 11n channel */ - if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && - IEEE80211_IS_CHAN_HT(ic->ic_bsschan)) + if (isvapht(vap)) error = ERESTART; /* XXX ENETRESET? */ break; case IEEE80211_IOC_AMPDU_LIMIT: @@ -2892,8 +2899,7 @@ else vap->iv_flags_ext &= ~IEEE80211_FEXT_AMSDU_RX; /* NB: reset only if we're operating on an 11n channel */ - if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && - IEEE80211_IS_CHAN_HT(ic->ic_bsschan)) + if (isvapht(vap)) error = ERESTART; /* XXX ENETRESET? */ break; case IEEE80211_IOC_AMSDU_LIMIT: @@ -2908,8 +2914,7 @@ } else vap->iv_flags_ext &= ~IEEE80211_FEXT_PUREN; /* NB: reset only if we're operating on an 11n channel */ - if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && - IEEE80211_IS_CHAN_HT(ic->ic_bsschan)) + if (isvapht(vap)) error = ERESTART; /* XXX ENETRESET? */ break; case IEEE80211_IOC_DOTH: @@ -2941,8 +2946,7 @@ } else vap->iv_flags_ext &= ~IEEE80211_FEXT_HTCOMPAT; /* NB: reset only if we're operating on an 11n channel */ - if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && - IEEE80211_IS_CHAN_HT(ic->ic_bsschan)) + if (isvapht(vap)) error = ERESTART; /* XXX ENETRESET? */ break; case IEEE80211_IOC_DWDS: @@ -3014,8 +3018,7 @@ ic->ic_htprotmode = ireq->i_val ? IEEE80211_PROT_RTSCTS : IEEE80211_PROT_NONE; /* NB: if not operating in 11n this can wait */ - if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && - IEEE80211_IS_CHAN_HT(ic->ic_bsschan)) + if (isvapht(vap)) error = ERESTART; break; default: ==== //depot/projects/vap/sys/net80211/ieee80211_node.c#22 (text+ko) ==== @@ -504,20 +504,8 @@ } /* - * Calculate HT channel promotion flags for a channel. - */ -static __inline int -htchanflags(const struct ieee80211_channel *c) -{ - return IEEE80211_IS_CHAN_HT40(c) ? - IEEE80211_FEXT_HT | IEEE80211_FEXT_USEHT40 : - IEEE80211_IS_CHAN_HT(c) ? IEEE80211_FEXT_HT : 0; -} - -/* * Calculate HT channel promotion flags for all vaps. - * This assumes ic_bsschan and ni_chan have been setup - * for each vap. + * This assumes ni_chan have been setup for each vap. */ static int gethtadjustflags(struct ieee80211com *ic) @@ -534,11 +522,9 @@ case IEEE80211_M_WDS: case IEEE80211_M_STA: case IEEE80211_M_AHDEMO: - flags |= htchanflags(vap->iv_bss->ni_chan); - break; case IEEE80211_M_HOSTAP: case IEEE80211_M_IBSS: - flags |= htchanflags(ic->ic_bsschan); + flags |= ieee80211_htchanflags(vap->iv_bss->ni_chan); break; default: break; @@ -577,13 +563,13 @@ /* * Check for channel promotion required to support the * set of running vap's. This assumes we are called - * after ic_bsschan and ni_chan are setup for each vap. + * after ni_chan is setup for each vap. */ /* NB: this assumes IEEE80211_FEXT_USEHT40 > IEEE80211_FEXT_HT */ - if (flags > htchanflags(c)) + if (flags > ieee80211_htchanflags(c)) c = ieee80211_ht_adjust_channel(ic, c, flags); } - ic->ic_curchan = c; + ic->ic_bsschan = ic->ic_curchan = c; ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan); ic->ic_set_channel(ic); } @@ -624,8 +610,6 @@ ieee80211_fix_rate(vap->iv_bss, &vap->iv_bss->ni_rates, IEEE80211_F_DODEL | IEEE80211_F_JOIN); - /* NB: ic_bsschan may not equal ic_curchan due to HT promotion */ - ic->ic_bsschan = selbs->ni_chan; ieee80211_setcurchan(ic, selbs->ni_chan); /* * Set the erp state (mostly the slot time) to deal with @@ -992,7 +976,7 @@ IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_bss->ni_bssid); ieee80211_node_initref(ni); /* mark referenced */ /* NB: required by ieee80211_fix_rate */ - ieee80211_node_set_chan(ni, ic->ic_bsschan); + ieee80211_node_set_chan(ni, vap->iv_bss->ni_chan); ni->ni_txpower = vap->iv_bss->ni_txpower; ieee80211_crypto_resetkey(vap, &ni->ni_ucastkey, IEEE80211_KEYIX_NONE); @@ -1021,7 +1005,69 @@ ni->ni_txpower = vap->iv_bss->ni_txpower; ni->ni_vlan = vap->iv_bss->ni_vlan; /* XXX?? */ IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_bss->ni_bssid); - ieee80211_node_set_chan(ni, ic->ic_bsschan); + ieee80211_node_set_chan(ni, vap->iv_bss->ni_chan); + } + return ni; +} + +/* + * Create a bss node for a legacy WDS vap. The far end does + * not associate so we just create create a new node and + * simulate an association. The caller is responsible for + * installing the node as the bss node and handling any further + * setup work like authorizing the port. + */ +struct ieee80211_node * +ieee80211_node_create_wds(struct ieee80211vap *vap, + const uint8_t bssid[IEEE80211_ADDR_LEN], struct ieee80211_channel *chan) +{ + struct ieee80211com *ic = vap->iv_ic; + struct ieee80211_node *ni; + + /* XXX check if node already in sta table? */ + ni = ieee80211_alloc_node(&ic->ic_sta, vap, bssid); + if (ni != NULL) { + ni->ni_wdsvap = vap; + IEEE80211_ADDR_COPY(ni->ni_bssid, bssid); + /* + * Inherit any manually configured settings. + */ + ni->ni_authmode = vap->iv_bss->ni_authmode; + ni->ni_txpower = vap->iv_bss->ni_txpower; + ni->ni_vlan = vap->iv_bss->ni_vlan; + ieee80211_node_set_chan(ni, chan); + /* NB: propagate ssid so available to WPA supplicant */ + ni->ni_esslen = vap->iv_des_ssid[0].len; + memcpy(ni->ni_essid, vap->iv_des_ssid[0].ssid, ni->ni_esslen); + /* NB: no associd for peer */ + /* + * There are no management frames to use to + * discover neighbor capabilities, so blindly + * propagate the local configuration. + */ + if (vap->iv_flags & IEEE80211_F_WME) + ni->ni_flags |= IEEE80211_NODE_QOS; + if (vap->iv_flags & IEEE80211_F_FF) + ni->ni_flags |= IEEE80211_NODE_FF; + if ((ic->ic_htcaps & IEEE80211_HTC_HT) && + (vap->iv_flags_ext & IEEE80211_FEXT_HT)) { + /* + * Device is HT-capable and HT is enabled for + * the vap; setup HT operation. On return + * ni_chan will be adjusted to an HT channel. + */ + ieee80211_ht_wds_init(ni); + } else { + struct ieee80211_channel *c = ni->ni_chan; + /* + * Force a legacy channel to be used. + */ + c = ieee80211_find_channel(ic, + c->ic_freq, c->ic_flags &~ IEEE80211_CHAN_HT); + KASSERT(c != NULL, ("no legacy channel, %u/%x", + ni->ni_chan->ic_freq, ni->ni_chan->ic_flags)); + ni->ni_chan = c; + } } return ni; } ==== //depot/projects/vap/sys/net80211/ieee80211_node.h#15 (text+ko) ==== @@ -313,6 +313,9 @@ const uint8_t macaddr[IEEE80211_ADDR_LEN]); struct ieee80211_node *ieee80211_dup_bss(struct ieee80211vap *, const uint8_t macaddr[IEEE80211_ADDR_LEN]); +struct ieee80211_node *ieee80211_node_create_wds(struct ieee80211vap *, + const uint8_t bssid[IEEE80211_ADDR_LEN], + struct ieee80211_channel *); #ifdef IEEE80211_DEBUG_REFCNT void ieee80211_free_node_debug(struct ieee80211_node *, const char *func, int line); ==== //depot/projects/vap/sys/net80211/ieee80211_output.c#25 (text+ko) ==== @@ -1492,14 +1492,15 @@ * Add an 11h Power Constraint element to a frame. */ static uint8_t * -ieee80211_add_powerconstraint(uint8_t *frm, struct ieee80211com *ic) +ieee80211_add_powerconstraint(uint8_t *frm, struct ieee80211vap *vap) { - int8_t limit = ic->ic_txpowlimit / 2; + const struct ieee80211_channel *c = vap->iv_bss->ni_chan; + /* XXX per-vap tx power limit? */ + int8_t limit = vap->iv_ic->ic_txpowlimit / 2; frm[0] = IEEE80211_ELEMID_PWRCNSTR; frm[1] = 1; - frm[2] = ic->ic_bsschan->ic_maxregpower > limit ? - ic->ic_bsschan->ic_maxregpower - limit : 0; + frm[2] = c->ic_maxregpower > limit ? c->ic_maxregpower - limit : 0; return frm + 3; } @@ -1507,12 +1508,12 @@ * Add an 11h Power Capability element to a frame. */ static uint8_t * -ieee80211_add_powercapability(uint8_t *frm, struct ieee80211com *ic) +ieee80211_add_powercapability(uint8_t *frm, const struct ieee80211_channel *c) { frm[0] = IEEE80211_ELEMID_PWRCAP; frm[1] = 2; - frm[2] = ic->ic_bsschan->ic_minpower; - frm[3] = ic->ic_bsschan->ic_maxpower; + frm[2] = c->ic_minpower; + frm[3] = c->ic_maxpower; return frm + 4; } @@ -1692,6 +1693,7 @@ #define senderr(_x, _v) do { ic->ic_stats._v++; ret = _x; goto bad; } while (0) struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = ni->ni_ic; + struct ieee80211_node *bss = vap->iv_bss; const struct ieee80211_rateset *rs; struct mbuf *m; uint8_t *frm; @@ -1767,31 +1769,30 @@ memset(frm, 0, 8); /* timestamp should be filled later */ frm += 8; - *(uint16_t *)frm = htole16(vap->iv_bss->ni_intval); + *(uint16_t *)frm = htole16(bss->ni_intval); frm += 2; - capinfo = getcapinfo(vap, ic->ic_curchan); + capinfo = getcapinfo(vap, bss->ni_chan); *(uint16_t *)frm = htole16(capinfo); frm += 2; - frm = ieee80211_add_ssid(frm, vap->iv_bss->ni_essid, - vap->iv_bss->ni_esslen); - rs = ieee80211_get_suprates(ic, ic->ic_curchan); + frm = ieee80211_add_ssid(frm, bss->ni_essid, bss->ni_esslen); + rs = ieee80211_get_suprates(ic, bss->ni_chan); frm = ieee80211_add_rates(frm, rs); - if (IEEE80211_IS_CHAN_FHSS(ic->ic_curchan)) { + if (IEEE80211_IS_CHAN_FHSS(bss->ni_chan)) { *frm++ = IEEE80211_ELEMID_FHPARMS; *frm++ = 5; *frm++ = ni->ni_fhdwell & 0x00ff; *frm++ = (ni->ni_fhdwell >> 8) & 0x00ff; *frm++ = IEEE80211_FH_CHANSET( - ieee80211_chan2ieee(ic, ic->ic_curchan)); + ieee80211_chan2ieee(ic, bss->ni_chan)); *frm++ = IEEE80211_FH_CHANPAT( - ieee80211_chan2ieee(ic, ic->ic_curchan)); + ieee80211_chan2ieee(ic, bss->ni_chan)); *frm++ = ni->ni_fhindex; } else { *frm++ = IEEE80211_ELEMID_DSPARMS; *frm++ = 1; - *frm++ = ieee80211_chan2ieee(ic, ic->ic_curchan); + *frm++ = ieee80211_chan2ieee(ic, bss->ni_chan); } if (vap->iv_opmode == IEEE80211_M_IBSS) { @@ -1807,12 +1808,12 @@ /* XXX else complain? */ } if (vap->iv_flags & IEEE80211_F_DOTH) { - if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) - frm = ieee80211_add_powerconstraint(frm, ic); + if (IEEE80211_IS_CHAN_5GHZ(bss->ni_chan)) + frm = ieee80211_add_powerconstraint(frm, vap); if (ic->ic_flags & IEEE80211_F_CSAPENDING) frm = ieee80211_add_csa(frm, vap); } - if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) + if (IEEE80211_IS_CHAN_ANYG(bss->ni_chan)) frm = ieee80211_add_erp(frm, ic); frm = ieee80211_add_xrates(frm, rs); /* @@ -1821,10 +1822,10 @@ * a token in arg to us. Could expand this to be * any legacy client for stuff like HT ie's. */ - if (IEEE80211_IS_CHAN_HT(ic->ic_bsschan) && + if (IEEE80211_IS_CHAN_HT(bss->ni_chan) && arg != IEEE80211_SEND_LEGACY_11B) { - frm = ieee80211_add_htcap(frm, ni); - frm = ieee80211_add_htinfo(frm, ni); + frm = ieee80211_add_htcap(frm, bss); + frm = ieee80211_add_htinfo(frm, bss); } if (vap->iv_flags & IEEE80211_F_WPA1) { if (vap->iv_wpa_ie != NULL) @@ -1833,11 +1834,11 @@ } if (vap->iv_flags & IEEE80211_F_WME) frm = ieee80211_add_wme_param(frm, &ic->ic_wme); - if (IEEE80211_IS_CHAN_HT(ic->ic_bsschan) && + if (IEEE80211_IS_CHAN_HT(bss->ni_chan) && (vap->iv_flags_ext & IEEE80211_FEXT_HTCOMPAT) && arg != IEEE80211_SEND_LEGACY_11B) { - frm = ieee80211_add_htcap_vendor(frm, ni); - frm = ieee80211_add_htinfo_vendor(frm, ni); + frm = ieee80211_add_htcap_vendor(frm, bss); + frm = ieee80211_add_htinfo_vendor(frm, bss); } if (ni->ni_ies.ath_ie != NULL) frm = ieee80211_add_ath(frm, ni->ni_ath_flags, @@ -1864,7 +1865,7 @@ is_shared_key = has_challenge || arg >= IEEE80211_AUTH_SHARED_RESPONSE || (arg == IEEE80211_AUTH_SHARED_REQUEST && - vap->iv_bss->ni_authmode == IEEE80211_AUTH_SHARED); + bss->ni_authmode == IEEE80211_AUTH_SHARED); m = ieee80211_getmgtframe(&frm, ic->ic_headroom + sizeof(struct ieee80211_frame), @@ -1986,14 +1987,13 @@ *(uint16_t *)frm = htole16(capinfo); frm += 2; - KASSERT(vap->iv_bss->ni_intval != 0, - ("beacon interval is zero!")); + KASSERT(bss->ni_intval != 0, ("beacon interval is zero!")); *(uint16_t *)frm = htole16(howmany(ic->ic_lintval, - vap->iv_bss->ni_intval)); + bss->ni_intval)); frm += 2; if (type == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) { - IEEE80211_ADDR_COPY(frm, vap->iv_bss->ni_bssid); + IEEE80211_ADDR_COPY(frm, bss->ni_bssid); frm += IEEE80211_ADDR_LEN; } @@ -2006,7 +2006,8 @@ } frm = ieee80211_add_xrates(frm, &ni->ni_rates); if (capinfo & IEEE80211_CAPINFO_SPECTRUM_MGMT) { - frm = ieee80211_add_powercapability(frm, ic); + frm = ieee80211_add_powercapability(frm, + ic->ic_curchan); frm = ieee80211_add_supportedchannels(frm, ic); } if ((vap->iv_flags_ext & IEEE80211_FEXT_HT) && @@ -2074,7 +2075,7 @@ if (m == NULL) senderr(ENOMEM, is_tx_nobuf); - capinfo = getcapinfo(vap, ic->ic_curchan); + capinfo = getcapinfo(vap, bss->ni_chan); *(uint16_t *)frm = htole16(capinfo); frm += 2; @@ -2222,7 +2223,7 @@ frm += 8; *(uint16_t *)frm = htole16(ni->ni_intval); frm += 2; - capinfo = getcapinfo(vap, ic->ic_bsschan); + capinfo = getcapinfo(vap, ni->ni_chan); bo->bo_caps = (uint16_t *)frm; *(uint16_t *)frm = htole16(capinfo); frm += 2; @@ -2234,10 +2235,10 @@ } else *frm++ = 0; frm = ieee80211_add_rates(frm, rs); - if (!IEEE80211_IS_CHAN_FHSS(ic->ic_bsschan)) { + if (!IEEE80211_IS_CHAN_FHSS(ni->ni_chan)) { *frm++ = IEEE80211_ELEMID_DSPARMS; *frm++ = 1; - *frm++ = ieee80211_chan2ieee(ic, ic->ic_bsschan); + *frm++ = ieee80211_chan2ieee(ic, ni->ni_chan); } if (ic->ic_flags & IEEE80211_F_PCF) { bo->bo_cfp = frm; @@ -2270,19 +2271,19 @@ /* XXX else complain */ } if (vap->iv_flags & IEEE80211_F_DOTH) { - if (IEEE80211_IS_CHAN_5GHZ(ic->ic_bsschan)) - frm = ieee80211_add_powerconstraint(frm, ic); + if (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)) + frm = ieee80211_add_powerconstraint(frm, vap); bo->bo_csa = frm; if (ic->ic_flags & IEEE80211_F_CSAPENDING) frm = ieee80211_add_csa(frm, vap); } else bo->bo_csa = frm; - if (IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan)) { + if (IEEE80211_IS_CHAN_ANYG(ni->ni_chan)) { bo->bo_erp = frm; frm = ieee80211_add_erp(frm, ic); } frm = ieee80211_add_xrates(frm, rs); - if (IEEE80211_IS_CHAN_HT(ic->ic_bsschan)) { + if (IEEE80211_IS_CHAN_HT(ni->ni_chan)) { frm = ieee80211_add_htcap(frm, ni); bo->bo_htinfo = frm; frm = ieee80211_add_htinfo(frm, ni); @@ -2296,7 +2297,7 @@ bo->bo_wme = frm; frm = ieee80211_add_wme_param(frm, &ic->ic_wme); } - if (IEEE80211_IS_CHAN_HT(ic->ic_bsschan) && + if (IEEE80211_IS_CHAN_HT(ni->ni_chan) && (vap->iv_flags_ext & IEEE80211_FEXT_HTCOMPAT)) { frm = ieee80211_add_htcap_vendor(frm, ni); frm = ieee80211_add_htinfo_vendor(frm, ni); @@ -2425,7 +2426,7 @@ vap->iv_csa_count = 0; /* * Effect channel change before reconstructing the beacon - * frame contents as many places reference ic_bsschan. + * frame contents as many places reference ni_chan. */ if (ic->ic_csa_newchan != NULL) ieee80211_csa_completeswitch(ic); @@ -2443,7 +2444,7 @@ } /* XXX faster to recalculate entirely or just changes? */ - capinfo = getcapinfo(vap, ic->ic_bsschan); + capinfo = getcapinfo(vap, ni->ni_chan); *bo->bo_caps = htole16(capinfo); if (vap->iv_flags & IEEE80211_F_WME) { ==== //depot/projects/vap/sys/net80211/ieee80211_proto.c#19 (text+ko) ==== @@ -1356,7 +1356,6 @@ KASSERT(ic->ic_flags & IEEE80211_F_CSAPENDING, ("csa not pending")); - ic->ic_bsschan = ic->ic_csa_newchan; ieee80211_setcurchan(ic, ic->ic_csa_newchan); ic->ic_csa_newchan = NULL; ic->ic_flags &= ~IEEE80211_F_CSAPENDING; ==== //depot/projects/vap/sys/net80211/ieee80211_var.h#24 (text+ko) ==== @@ -607,6 +607,18 @@ } /* + * Calculate HT channel promotion flags for a channel. + * XXX belongs in ieee80211_ht.h but needs IEEE80211_FEXT_* + */ +static __inline int +ieee80211_htchanflags(const struct ieee80211_channel *c) +{ + return IEEE80211_IS_CHAN_HT40(c) ? + IEEE80211_FEXT_HT | IEEE80211_FEXT_USEHT40 : + IEEE80211_IS_CHAN_HT(c) ? IEEE80211_FEXT_HT : 0; +} + +/* * Debugging facilities compiled in when IEEE80211_DEBUG is defined. * * The intent is that any problem in the net80211 layer can be ==== //depot/projects/vap/sys/net80211/ieee80211_wds.c#4 (text+ko) ==== @@ -171,50 +171,13 @@ * authorize the port for traffic to flow. * XXX check if node already in sta table? */ - ni = ieee80211_dup_bss(vap, vap->iv_des_bssid); + ni = ieee80211_node_create_wds(vap, vap->iv_des_bssid, chan); if (ni != NULL) { - ni->ni_wdsvap = vap; - /* NB: ieee80211_dup_bss installs the vap's bssid */ - IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_des_bssid); - /* NB: propagate ssid so available to WPA supplicant */ - ni->ni_esslen = vap->iv_des_ssid[0].len; - memcpy(ni->ni_essid, vap->iv_des_ssid[0].ssid, - ni->ni_esslen); - /* NB: no associd for peer */ - obss = vap->iv_bss; vap->iv_bss = ieee80211_ref_node(ni); ni->ni_flags |= IEEE80211_NODE_AREF; if (obss != NULL) ieee80211_free_node(obss); - /* - * There are no management frames to use to - * discover neighbor capabilities, so blindly - * propagate the local configuration. - */ - if (vap->iv_flags & IEEE80211_F_WME) - ni->ni_flags |= IEEE80211_NODE_QOS; - if (vap->iv_flags & IEEE80211_F_FF) - ni->ni_flags |= IEEE80211_NODE_FF; - if ((ic->ic_htcaps & IEEE80211_HTC_HT) && - (vap->iv_flags_ext & IEEE80211_FEXT_HT)) { - /* - * Device is HT-capable and HT is enabled for - * the vap; setup HT operation. On return - * ni_chan will be adjusted to an HT channel. - */ - ieee80211_ht_wds_init(ni); - } else { - struct ieee80211_channel *c = ni->ni_chan; - /* - * Force a legacy channel to be used. - */ - c = ieee80211_find_channel(ic, - c->ic_freq, c->ic_flags &~ IEEE80211_CHAN_HT); - KASSERT(c != NULL, ("no legacy channel, %u/%x", - ni->ni_chan->ic_freq, ni->ni_chan->ic_flags)); - ni->ni_chan = c; - } /* give driver a chance to setup state like ni_txrate */ if (ic->ic_newassoc != NULL) ic->ic_newassoc(ni, 1);