Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 27 Jan 2008 20:24:53 GMT
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 134234 for review
Message-ID:  <200801272024.m0RKOrJP037692@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);



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