PERFORCE change 134234 for review
Sam Leffler
sam at FreeBSD.org
Sun Jan 27 12:24:55 PST 2008
http://perforce.freebsd.org/chv.cgi?CH=134234
Change 134234 by sam at 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);
More information about the p4-projects
mailing list