sync 11n support with vap code base; many changes based on interop
testing with all major vendors MFC after: 1 week
This commit is contained in:
parent
cd9a2dab49
commit
1b6167d239
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=173273
@ -169,6 +169,10 @@ struct ieee80211_qosframe_addr4 {
|
||||
#define IEEE80211_SEQ_SUB(a, b) \
|
||||
(((a) + IEEE80211_SEQ_RANGE - (b)) & (IEEE80211_SEQ_RANGE-1))
|
||||
|
||||
#define IEEE80211_SEQ_BA_RANGE 2048 /* 2^11 */
|
||||
#define IEEE80211_SEQ_BA_BEFORE(a, b) \
|
||||
(IEEE80211_SEQ_SUB(b, a+1) < IEEE80211_SEQ_BA_RANGE-1)
|
||||
|
||||
#define IEEE80211_NWID_LEN 32
|
||||
|
||||
#define IEEE80211_QOS_TXOP 0x00ff
|
||||
@ -546,20 +550,20 @@ struct ieee80211_ie_htcap {
|
||||
/* HT parameters (hc_param) */
|
||||
#define IEEE80211_HTCAP_MAXRXAMPDU 0x03 /* max rx A-MPDU factor */
|
||||
#define IEEE80211_HTCAP_MAXRXAMPDU_S 0
|
||||
#define IEEE80211_HTCAP_MAXRXAMPDU_8K 0x00
|
||||
#define IEEE80211_HTCAP_MAXRXAMPDU_16K 0x01
|
||||
#define IEEE80211_HTCAP_MAXRXAMPDU_32K 0x02
|
||||
#define IEEE80211_HTCAP_MAXRXAMPDU_64K 0x03
|
||||
#define IEEE80211_HTCAP_MAXRXAMPDU_8K 0
|
||||
#define IEEE80211_HTCAP_MAXRXAMPDU_16K 1
|
||||
#define IEEE80211_HTCAP_MAXRXAMPDU_32K 2
|
||||
#define IEEE80211_HTCAP_MAXRXAMPDU_64K 3
|
||||
#define IEEE80211_HTCAP_MPDUDENSITY 0x1c /* min MPDU start spacing */
|
||||
#define IEEE80211_HTCAP_MPDUDENSITY_S 2
|
||||
#define IEEE80211_HTCAP_MPDUDENSITY_NA 0x00 /* no time restriction */
|
||||
#define IEEE80211_HTCAP_MPDUDENSITY_025 0x04 /* 1/4 us */
|
||||
#define IEEE80211_HTCAP_MPDUDENSITY_05 0x08 /* 1/2 us */
|
||||
#define IEEE80211_HTCAP_MPDUDENSITY_1 0x0c /* 1 us */
|
||||
#define IEEE80211_HTCAP_MPDUDENSITY_2 0x10 /* 2 us */
|
||||
#define IEEE80211_HTCAP_MPDUDENSITY_4 0x14 /* 4 us */
|
||||
#define IEEE80211_HTCAP_MPDUDENSITY_8 0x18 /* 8 us */
|
||||
#define IEEE80211_HTCAP_MPDUDENSITY_16 0x1c /* 16 us */
|
||||
#define IEEE80211_HTCAP_MPDUDENSITY_NA 0 /* no time restriction */
|
||||
#define IEEE80211_HTCAP_MPDUDENSITY_025 1 /* 1/4 us */
|
||||
#define IEEE80211_HTCAP_MPDUDENSITY_05 2 /* 1/2 us */
|
||||
#define IEEE80211_HTCAP_MPDUDENSITY_1 3 /* 1 us */
|
||||
#define IEEE80211_HTCAP_MPDUDENSITY_2 4 /* 2 us */
|
||||
#define IEEE80211_HTCAP_MPDUDENSITY_4 5 /* 4 us */
|
||||
#define IEEE80211_HTCAP_MPDUDENSITY_8 6 /* 8 us */
|
||||
#define IEEE80211_HTCAP_MPDUDENSITY_16 7 /* 16 us */
|
||||
|
||||
/* HT extended capabilities (hc_extcap) */
|
||||
#define IEEE80211_HTCAP_PCO 0x0001 /* PCO capable */
|
||||
@ -686,7 +690,7 @@ struct ieee80211_country_ie {
|
||||
uint8_t schan; /* starting channel */
|
||||
uint8_t nchan; /* number channels */
|
||||
uint8_t maxtxpwr; /* tx power cap */
|
||||
} __packed band[4]; /* up to 4 sub bands */
|
||||
} __packed band[10]; /* sub bands */
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
|
@ -54,6 +54,27 @@ int ieee80211_debug = 0;
|
||||
SYSCTL_INT(_net_wlan, OID_AUTO, debug, CTLFLAG_RW, &ieee80211_debug,
|
||||
0, "debugging printfs");
|
||||
#endif
|
||||
extern int ieee80211_recv_bar_ena;
|
||||
SYSCTL_INT(_net_wlan, OID_AUTO, recv_bar, CTLFLAG_RW, &ieee80211_recv_bar_ena,
|
||||
0, "BAR frame processing (ena/dis)");
|
||||
|
||||
#ifdef IEEE80211_AMPDU_AGE
|
||||
static int
|
||||
ieee80211_sysctl_ampdu_age(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
extern int ieee80211_ampdu_age;
|
||||
int ampdu_age = ticks_to_msecs(ieee80211_ampdu_age);
|
||||
int error;
|
||||
|
||||
error = sysctl_handle_int(oidp, &du_age, 0, req);
|
||||
if (error || !req->newptr)
|
||||
return error;
|
||||
ieee80211_ampdu_age = msecs_to_ticks(ampdu_age);
|
||||
return 0;
|
||||
}
|
||||
SYSCTL_PROC(_net_wlan, OID_AUTO, "ampdu_age", CTLFLAG_RW, NULL, 0,
|
||||
ieee80211_sysctl_ampdu_age, "A", "AMPDU max reorder age (ms)");
|
||||
#endif
|
||||
|
||||
static int
|
||||
ieee80211_sysctl_inact(SYSCTL_HANDLER_ARGS)
|
||||
|
@ -125,6 +125,13 @@ typedef struct mtx ieee80211_scan_lock_t;
|
||||
(_qlen) = ++(_ni)->ni_savedq.ifq_len; \
|
||||
} while (0)
|
||||
|
||||
#define IEEE80211_TAPQ_INIT(_tap) do { \
|
||||
mtx_init(&(tap)->txa_q.ifq_mtx, "ampdu tx queue", NULL, MTX_DEF); \
|
||||
(_tap)->txa_q.ifq_maxlen = IEEE80211_AGGR_BAWMAX; \
|
||||
} while (0)
|
||||
#define IEEE80211_TAPQ_DESTROY(_tap) \
|
||||
mtx_destroy(&(_tap)->txa_q.ifq_mtx)
|
||||
|
||||
#ifndef IF_PREPEND_LIST
|
||||
#define _IF_PREPEND_LIST(ifq, mhead, mtail, mcount) do { \
|
||||
(mtail)->m_nextpkt = (ifq)->ifq_head; \
|
||||
@ -178,6 +185,7 @@ struct ifqueue;
|
||||
void ieee80211_drain_ifq(struct ifqueue *);
|
||||
|
||||
#define msecs_to_ticks(ms) (((ms)*hz)/1000)
|
||||
#define ticks_to_msecs(t) ((t) / hz)
|
||||
#define time_after(a,b) ((long)(b) - (long)(a) < 0)
|
||||
#define time_before(a,b) time_after(b,a)
|
||||
#define time_after_eq(a,b) ((long)(a) - (long)(b) >= 0)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -31,10 +31,9 @@
|
||||
* 802.11n protocol implementation definitions.
|
||||
*/
|
||||
|
||||
#define IEEE80211_SEND_ACTION(_ni,_cat, _act, _args) \
|
||||
((*(_ic)->ic_send_action)(_ni, _cat, _act, _args))
|
||||
|
||||
#define IEEE80211_AGGR_BAWMAX 64 /* max block ack window size */
|
||||
/* threshold for aging overlapping non-HT bss */
|
||||
#define IEEE80211_NONHT_PRESENT_AGE msecs_to_ticks(60*1000)
|
||||
|
||||
typedef uint16_t ieee80211_seq;
|
||||
|
||||
@ -44,6 +43,7 @@ struct ieee80211_tx_ampdu {
|
||||
#define IEEE80211_AGGR_XCHGPEND 0x0002 /* ADDBA response pending */
|
||||
#define IEEE80211_AGGR_RUNNING 0x0004 /* ADDBA response received */
|
||||
#define IEEE80211_AGGR_SETUP 0x0008 /* deferred state setup */
|
||||
#define IEEE80211_AGGR_NAK 0x0010 /* peer NAK'd ADDBA request */
|
||||
uint8_t txa_ac;
|
||||
uint8_t txa_token; /* dialog token */
|
||||
int txa_qbytes; /* data queued (bytes) */
|
||||
@ -64,7 +64,7 @@ struct ieee80211_tx_ampdu {
|
||||
/* return non-zero if AMPDU tx for the TID is running or started */
|
||||
#define IEEE80211_AMPDU_REQUESTED(tap) \
|
||||
(((tap)->txa_flags & \
|
||||
(IEEE80211_AGGR_RUNNING|IEEE80211_AGGR_XCHGPEND)) != 0)
|
||||
(IEEE80211_AGGR_RUNNING|IEEE80211_AGGR_XCHGPEND|IEEE80211_AGGR_NAK)) != 0)
|
||||
|
||||
struct ieee80211_rx_ampdu {
|
||||
int rxa_flags;
|
||||
@ -72,8 +72,9 @@ struct ieee80211_rx_ampdu {
|
||||
short rxa_qframes; /* data queued (frames) */
|
||||
ieee80211_seq rxa_seqstart;
|
||||
ieee80211_seq rxa_start; /* start of current BA window */
|
||||
ieee80211_seq rxa_nxt; /* next seq# in BA window */
|
||||
uint16_t rxa_wnd; /* BA window size */
|
||||
int rxa_age; /* age of oldest frame in window */
|
||||
int rxa_nframes; /* frames since ADDBA */
|
||||
struct mbuf *rxa_m[IEEE80211_AGGR_BAWMAX];
|
||||
};
|
||||
|
||||
@ -96,12 +97,21 @@ int ieee80211_ampdu_reorder(struct ieee80211_node *, struct mbuf *);
|
||||
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 *);
|
||||
void ieee80211_ht_node_join(struct ieee80211_node *);
|
||||
void ieee80211_ht_node_leave(struct ieee80211_node *);
|
||||
void ieee80211_htinfo_update(struct ieee80211com *, int protmode);
|
||||
void ieee80211_ht_timeout(struct ieee80211com *);
|
||||
void ieee80211_parse_htcap(struct ieee80211_node *, const uint8_t *);
|
||||
void ieee80211_parse_htinfo(struct ieee80211_node *, const uint8_t *);
|
||||
void ieee80211_recv_action(struct ieee80211_node *,
|
||||
const uint8_t *, const uint8_t *);
|
||||
int ieee80211_ampdu_request(struct ieee80211_node *,
|
||||
struct ieee80211_tx_ampdu *);
|
||||
void ieee80211_ampdu_stop(struct ieee80211_node *,
|
||||
struct ieee80211_tx_ampdu *);
|
||||
int ieee80211_send_bar(struct ieee80211_node *,
|
||||
const struct ieee80211_tx_ampdu *);
|
||||
int ieee80211_send_action(struct ieee80211_node *,
|
||||
|
@ -2037,6 +2037,19 @@ capinfomismatch(struct ieee80211_node *ni, const struct ieee80211_frame *wh,
|
||||
ic->ic_stats.is_rx_assoc_capmismatch++;
|
||||
}
|
||||
|
||||
static void
|
||||
htcapmismatch(struct ieee80211_node *ni, const struct ieee80211_frame *wh,
|
||||
int reassoc, int resp)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
|
||||
IEEE80211_NOTE_MAC(ic, IEEE80211_MSG_ANY, wh->i_addr2,
|
||||
"deny %s request, %s missing HT ie", reassoc ? "reassoc" : "assoc");
|
||||
/* XXX no better code */
|
||||
IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_OTHER);
|
||||
ieee80211_node_leave(ic, ni);
|
||||
}
|
||||
|
||||
void
|
||||
ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
struct ieee80211_node *ni,
|
||||
@ -2046,7 +2059,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
#define ISREASSOC(_st) ((_st) == IEEE80211_FC0_SUBTYPE_REASSOC_RESP)
|
||||
struct ieee80211_frame *wh;
|
||||
uint8_t *frm, *efrm;
|
||||
uint8_t *ssid, *rates, *xrates, *wpa, *rsn, *wme, *ath, *htcap;
|
||||
uint8_t *ssid, *rates, *xrates, *wpa, *rsn, *wme, *ath, *htcap, *htinfo;
|
||||
int reassoc, resp, allocbs;
|
||||
uint8_t rate;
|
||||
|
||||
@ -2311,8 +2324,17 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
ieee80211_parse_athparams(ni, scan.ath, wh);
|
||||
if (scan.htcap != NULL)
|
||||
ieee80211_parse_htcap(ni, scan.htcap);
|
||||
if (scan.htinfo != NULL)
|
||||
if (scan.htinfo != NULL) {
|
||||
ieee80211_parse_htinfo(ni, scan.htinfo);
|
||||
if (ni->ni_chan != ic->ic_bsschan) {
|
||||
/*
|
||||
* Channel has been adjusted based on
|
||||
* negotiated HT parameters; force the
|
||||
* channel state to follow.
|
||||
*/
|
||||
ieee80211_setbsschan(ic, ni->ni_chan);
|
||||
}
|
||||
}
|
||||
if (scan.tim != NULL) {
|
||||
struct ieee80211_tim_ie *tim =
|
||||
(struct ieee80211_tim_ie *) scan.tim;
|
||||
@ -2789,6 +2811,37 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
ieee80211_ht_node_init(ni, htcap);
|
||||
} else if (ni->ni_flags & IEEE80211_NODE_HT)
|
||||
ieee80211_ht_node_cleanup(ni);
|
||||
/*
|
||||
* Allow AMPDU operation only with unencrypted traffic
|
||||
* or AES-CCM; the 11n spec only specifies these ciphers
|
||||
* so permitting any others is undefined and can lead
|
||||
* to interoperability problems.
|
||||
*
|
||||
* NB: We check for AES by looking at the GTK cipher
|
||||
* since the WPA/11i specs say the PTK cipher has
|
||||
* to be "as good or better".
|
||||
*/
|
||||
if ((ni->ni_flags & IEEE80211_NODE_HT) &&
|
||||
(((ic->ic_flags & IEEE80211_F_WPA) &&
|
||||
rsnparms.rsn_mcastcipher != IEEE80211_CIPHER_AES_CCM) ||
|
||||
(ic->ic_flags & (IEEE80211_F_WPA|IEEE80211_F_PRIVACY)) == IEEE80211_F_PRIVACY)) {
|
||||
IEEE80211_NOTE(ic,
|
||||
IEEE80211_MSG_ASSOC | IEEE80211_MSG_11N, ni,
|
||||
"disallow HT use because WEP or TKIP requested, "
|
||||
"capinfo 0x%x mcastcipher %d", capinfo,
|
||||
rsnparms.rsn_mcastcipher);
|
||||
ieee80211_ht_node_cleanup(ni);
|
||||
ic->ic_stats.is_ht_assoc_downgrade++;
|
||||
}
|
||||
/*
|
||||
* If constrained to 11n-only stations reject legacy stations.
|
||||
*/
|
||||
if ((ic->ic_flags_ext & IEEE80211_FEXT_PUREN) &&
|
||||
(ni->ni_flags & IEEE80211_NODE_HT) == 0) {
|
||||
htcapmismatch(ni, wh, reassoc, resp);
|
||||
ic->ic_stats.is_ht_assoc_nohtcap++;
|
||||
return;
|
||||
}
|
||||
ni->ni_rssi = rssi;
|
||||
ni->ni_noise = noise;
|
||||
ni->ni_rstamp = rstamp;
|
||||
@ -2884,6 +2937,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
* [tlv] extended supported rates
|
||||
* [tlv] WME
|
||||
* [tlv] HT capabilities
|
||||
* [tlv] HT info
|
||||
*/
|
||||
IEEE80211_VERIFY_LENGTH(efrm - frm, 6, return);
|
||||
ni = ic->ic_bss;
|
||||
@ -2904,7 +2958,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
associd = le16toh(*(uint16_t *)frm);
|
||||
frm += 2;
|
||||
|
||||
rates = xrates = wme = htcap = NULL;
|
||||
rates = xrates = wme = htcap = htinfo = NULL;
|
||||
while (efrm - frm > 1) {
|
||||
IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2, return);
|
||||
switch (*frm) {
|
||||
@ -2917,9 +2971,25 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
case IEEE80211_ELEMID_HTCAP:
|
||||
htcap = frm;
|
||||
break;
|
||||
case IEEE80211_ELEMID_HTINFO:
|
||||
htinfo = frm;
|
||||
break;
|
||||
case IEEE80211_ELEMID_VENDOR:
|
||||
if (iswmeoui(frm))
|
||||
wme = frm;
|
||||
else if (ic->ic_flags_ext & IEEE80211_FEXT_HTCOMPAT) {
|
||||
/*
|
||||
* Accept pre-draft HT ie's if the
|
||||
* standard ones have not been seen.
|
||||
*/
|
||||
if (ishtcapoui(frm)) {
|
||||
if (htcap == NULL)
|
||||
htcap = frm;
|
||||
} else if (ishtinfooui(frm)) {
|
||||
if (htinfo == NULL)
|
||||
htcap = frm;
|
||||
}
|
||||
}
|
||||
/* XXX Atheros OUI support */
|
||||
break;
|
||||
}
|
||||
@ -2955,6 +3025,25 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
ieee80211_wme_updateparams(ic);
|
||||
} else
|
||||
ni->ni_flags &= ~IEEE80211_NODE_QOS;
|
||||
/*
|
||||
* Setup HT state according to the negotiation.
|
||||
*/
|
||||
if ((ic->ic_htcaps & IEEE80211_HTC_HT) &&
|
||||
htcap != NULL && htinfo != NULL) {
|
||||
ieee80211_ht_node_init(ni, htcap);
|
||||
ieee80211_parse_htinfo(ni, htinfo);
|
||||
ieee80211_setup_htrates(ni,
|
||||
htcap, IEEE80211_F_JOIN | IEEE80211_F_DOBRS);
|
||||
ieee80211_setup_basic_htrates(ni, htinfo);
|
||||
if (ni->ni_chan != ic->ic_bsschan) {
|
||||
/*
|
||||
* Channel has been adjusted based on
|
||||
* negotiated HT parameters; force the
|
||||
* channel state to follow.
|
||||
*/
|
||||
ieee80211_setbsschan(ic, ni->ni_chan);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Configure state now that we are associated.
|
||||
*
|
||||
@ -2989,6 +3078,9 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
ic->ic_flags&IEEE80211_F_SHSLOT ? "short" : "long",
|
||||
ic->ic_flags&IEEE80211_F_USEPROT ? ", protection" : "",
|
||||
ni->ni_flags & IEEE80211_NODE_QOS ? ", QoS" : "",
|
||||
ni->ni_flags & IEEE80211_NODE_HT ?
|
||||
(ni->ni_chw == 20 ? ", HT20" : ", HT40") : "",
|
||||
ni->ni_flags & IEEE80211_NODE_AMPDU ? " (+AMPDU)" : "",
|
||||
IEEE80211_ATH_CAP(ic, ni, IEEE80211_NODE_FF) ?
|
||||
", fast-frames" : "",
|
||||
IEEE80211_ATH_CAP(ic, ni, IEEE80211_NODE_TURBOP) ?
|
||||
|
@ -1108,6 +1108,17 @@ ieee80211_ioctl_get80211(struct ieee80211com *ic, u_long cmd, struct ieee80211re
|
||||
case IEEE80211_IOC_INACTIVITY:
|
||||
ireq->i_val = (ic->ic_flags_ext & IEEE80211_FEXT_INACT) != 0;
|
||||
break;
|
||||
case IEEE80211_IOC_HTPROTMODE:
|
||||
ireq->i_val = ic->ic_htprotmode;
|
||||
break;
|
||||
case IEEE80211_IOC_HTCONF:
|
||||
if (ic->ic_flags_ext & IEEE80211_FEXT_HT) {
|
||||
ireq->i_val = 1;
|
||||
if (ic->ic_flags_ext & IEEE80211_FEXT_USEHT40)
|
||||
ireq->i_val |= 2;
|
||||
} else
|
||||
ireq->i_val = 0;
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
@ -2479,6 +2490,27 @@ ieee80211_ioctl_set80211(struct ieee80211com *ic, u_long cmd, struct ieee80211re
|
||||
else
|
||||
ic->ic_flags_ext &= ~IEEE80211_FEXT_INACT;
|
||||
break;
|
||||
case IEEE80211_IOC_HTPROTMODE:
|
||||
if (ireq->i_val > IEEE80211_PROT_RTSCTS)
|
||||
return EINVAL;
|
||||
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))
|
||||
error = ERESTART;
|
||||
break;
|
||||
case IEEE80211_IOC_HTCONF:
|
||||
if (ireq->i_val & 1)
|
||||
ic->ic_flags_ext |= IEEE80211_FEXT_HT;
|
||||
else
|
||||
ic->ic_flags_ext &= ~IEEE80211_FEXT_HT;
|
||||
if (ireq->i_val & 2)
|
||||
ic->ic_flags_ext |= IEEE80211_FEXT_USEHT40;
|
||||
else
|
||||
ic->ic_flags_ext &= ~IEEE80211_FEXT_USEHT40;
|
||||
error = ENETRESET;
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
|
@ -60,6 +60,7 @@ struct ieee80211_nodestats {
|
||||
uint32_t ns_rx_decryptcrc; /* rx decrypt failed on crc */
|
||||
uint32_t ns_rx_unauth; /* rx on unauthorized port */
|
||||
uint32_t ns_rx_unencrypted; /* rx unecrypted w/ privacy */
|
||||
uint32_t ns_rx_drop; /* rx discard other reason */
|
||||
|
||||
uint32_t ns_tx_data; /* tx data frames */
|
||||
uint32_t ns_tx_mgmt; /* tx management frames */
|
||||
@ -186,11 +187,28 @@ struct ieee80211_stats {
|
||||
uint32_t is_amsdu_encap; /* A-MSDU encap'd for tx */
|
||||
uint32_t is_ampdu_bar_bad; /* A-MPDU BAR out of window */
|
||||
uint32_t is_ampdu_bar_oow; /* A-MPDU BAR before ADDBA */
|
||||
uint32_t is_ampdu_bar_move; /* A-MPDU BAR moved window */
|
||||
uint32_t is_ampdu_bar_rx; /* A-MPDU BAR frames handled */
|
||||
uint32_t is_ampdu_rx_flush; /* A-MPDU frames flushed */
|
||||
uint32_t is_ampdu_rx_oor; /* A-MPDU frames out-of-order */
|
||||
uint32_t is_ampdu_rx_copy; /* A-MPDU frames copied down */
|
||||
uint32_t is_spare[32];
|
||||
uint32_t is_ampdu_rx_drop; /* A-MPDU frames dropped */
|
||||
uint32_t is_tx_badstate; /* tx discard state != RUN */
|
||||
uint32_t is_tx_notassoc; /* tx failed, sta not assoc */
|
||||
uint32_t is_tx_classify; /* tx classification failed */
|
||||
uint32_t is_ht_assoc_nohtcap; /* non-HT sta rejected */
|
||||
uint32_t is_ht_assoc_downgrade; /* HT sta forced to legacy */
|
||||
uint32_t is_ht_assoc_norate; /* HT assoc w/ rate mismatch */
|
||||
uint32_t is_ampdu_rx_age; /* A-MPDU sent up 'cuz of age */
|
||||
uint32_t is_ampdu_rx_move; /* A-MPDU MSDU moved window */
|
||||
uint32_t is_addba_reject; /* ADDBA reject 'cuz disabled */
|
||||
uint32_t is_addba_norequest; /* ADDBA response w/o ADDBA */
|
||||
uint32_t is_addba_badtoken; /* ADDBA response w/ wrong
|
||||
dialogtoken */
|
||||
uint32_t is_ampdu_stop; /* A-MPDU stream stopped */
|
||||
uint32_t is_ampdu_stop_failed; /* A-MPDU stream not running */
|
||||
uint32_t is_ampdu_rx_reorder; /* A-MPDU held for rx reorder */
|
||||
uint32_t is_spare[16];
|
||||
};
|
||||
|
||||
/*
|
||||
@ -208,7 +226,7 @@ struct ieee80211_stats {
|
||||
* Otherwise a unicast/pairwise key is specified by the bssid
|
||||
* (on a station) or mac address (on an ap). They key length
|
||||
* must include any MIC key data; otherwise it should be no
|
||||
more than IEEE80211_KEYBUF_SIZE.
|
||||
* more than IEEE80211_KEYBUF_SIZE.
|
||||
*/
|
||||
struct ieee80211req_key {
|
||||
uint8_t ik_type; /* key/cipher type */
|
||||
@ -493,6 +511,8 @@ struct ieee80211req {
|
||||
#define IEEE80211_IOC_LOCATION 91 /* indoor/outdoor/anywhere */
|
||||
#define IEEE80211_IOC_HTCOMPAT 92 /* support pre-D1.10 HT ie's */
|
||||
#define IEEE80211_IOC_INACTIVITY 94 /* sta inactivity handling */
|
||||
#define IEEE80211_IOC_HTPROTMODE 102 /* HT protection (off, rts) */
|
||||
#define IEEE80211_IOC_HTCONF 105 /* HT config (off, HT20, HT40)*/
|
||||
|
||||
/*
|
||||
* Scan result data returned for IEEE80211_IOC_SCAN_RESULTS.
|
||||
|
@ -535,6 +535,18 @@ ieee80211_ibss_merge(struct ieee80211_node *ni)
|
||||
return ieee80211_sta_join1(ieee80211_ref_node(ni));
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the bss channel.
|
||||
*/
|
||||
void
|
||||
ieee80211_setbsschan(struct ieee80211com *ic, struct ieee80211_channel *c)
|
||||
{
|
||||
ic->ic_bsschan = c;
|
||||
ic->ic_curchan = ic->ic_bsschan;
|
||||
ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan);
|
||||
ic->ic_set_channel(ic);
|
||||
}
|
||||
|
||||
/*
|
||||
* Join the specified IBSS/BSS network. The node is assumed to
|
||||
* be passed in with a held reference.
|
||||
@ -584,10 +596,7 @@ ieee80211_sta_join1(struct ieee80211_node *selbs)
|
||||
ieee80211_fix_rate(ic->ic_bss, &ic->ic_bss->ni_rates,
|
||||
IEEE80211_F_DODEL | IEEE80211_F_JOIN);
|
||||
|
||||
ic->ic_bsschan = selbs->ni_chan;
|
||||
ic->ic_curchan = ic->ic_bsschan;
|
||||
ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan);
|
||||
ic->ic_set_channel(ic);
|
||||
ieee80211_setbsschan(ic, selbs->ni_chan);
|
||||
/*
|
||||
* Set the erp state (mostly the slot time) to deal with
|
||||
* the auto-select case; this should be redundant if the
|
||||
@ -637,7 +646,6 @@ ieee80211_sta_join(struct ieee80211com *ic,
|
||||
ni->ni_tstamp.tsf = se->se_tstamp.tsf;
|
||||
ni->ni_intval = se->se_intval;
|
||||
ni->ni_capinfo = se->se_capinfo;
|
||||
/* XXX shift to 11n channel if htinfo present */
|
||||
ni->ni_chan = se->se_chan;
|
||||
ni->ni_timoff = se->se_timoff;
|
||||
ni->ni_fhdwell = se->se_fhdwell;
|
||||
@ -646,9 +654,7 @@ ieee80211_sta_join(struct ieee80211com *ic,
|
||||
ni->ni_rssi = se->se_rssi;
|
||||
ni->ni_noise = se->se_noise;
|
||||
if (se->se_htcap_ie != NULL)
|
||||
ieee80211_ht_node_init(ni, se->se_htcap_ie);
|
||||
if (se->se_htinfo_ie != NULL)
|
||||
ieee80211_parse_htinfo(ni, se->se_htinfo_ie);
|
||||
ieee80211_saveie(&ni->ni_htcap_ie, se->se_htcap_ie);
|
||||
if (se->se_wpa_ie != NULL)
|
||||
ieee80211_saveie(&ni->ni_wpa_ie, se->se_wpa_ie);
|
||||
if (se->se_rsn_ie != NULL)
|
||||
@ -664,10 +670,6 @@ ieee80211_sta_join(struct ieee80211com *ic,
|
||||
/* NB: must be after ni_chan is setup */
|
||||
ieee80211_setup_rates(ni, se->se_rates, se->se_xrates,
|
||||
IEEE80211_F_DOSORT);
|
||||
if (se->se_htcap_ie != NULL)
|
||||
ieee80211_setup_htrates(ni, se->se_htcap_ie, IEEE80211_F_JOIN);
|
||||
if (se->se_htinfo_ie != NULL)
|
||||
ieee80211_setup_basic_htrates(ni, se->se_htinfo_ie);
|
||||
|
||||
return ieee80211_sta_join1(ieee80211_ref_node(ni));
|
||||
}
|
||||
@ -715,6 +717,11 @@ node_cleanup(struct ieee80211_node *ni)
|
||||
"[%s] power save mode off, %u sta's in ps mode\n",
|
||||
ether_sprintf(ni->ni_macaddr), ic->ic_ps_sta);
|
||||
}
|
||||
/*
|
||||
* Cleanup any HT-related state.
|
||||
*/
|
||||
if (ni->ni_flags & IEEE80211_NODE_HT)
|
||||
ieee80211_ht_node_cleanup(ni);
|
||||
/*
|
||||
* Clear AREF flag that marks the authorization refcnt bump
|
||||
* has happened. This is probably not needed as the node
|
||||
@ -1577,6 +1584,7 @@ ieee80211_node_timeout(void *arg)
|
||||
|
||||
IEEE80211_LOCK(ic);
|
||||
ieee80211_erp_timeout(ic);
|
||||
ieee80211_ht_timeout(ic);
|
||||
IEEE80211_UNLOCK(ic);
|
||||
|
||||
callout_reset(&ic->ic_inact, IEEE80211_INACT_WAIT*hz,
|
||||
@ -1659,6 +1667,8 @@ static void
|
||||
ieee80211_node_join_11g(struct ieee80211com *ic, struct ieee80211_node *ni)
|
||||
{
|
||||
|
||||
IEEE80211_LOCK_ASSERT(ic);
|
||||
|
||||
/*
|
||||
* Station isn't capable of short slot time. Bump
|
||||
* the count of long slot time stations and disable
|
||||
@ -1724,6 +1734,7 @@ ieee80211_node_join(struct ieee80211com *ic, struct ieee80211_node *ni, int resp
|
||||
if (ni->ni_associd == 0) {
|
||||
uint16_t aid;
|
||||
|
||||
IEEE80211_LOCK(ic);
|
||||
/*
|
||||
* It would be good to search the bitmap
|
||||
* more efficiently, but this will do for now.
|
||||
@ -1734,23 +1745,30 @@ ieee80211_node_join(struct ieee80211com *ic, struct ieee80211_node *ni, int resp
|
||||
break;
|
||||
}
|
||||
if (aid >= ic->ic_max_aid) {
|
||||
IEEE80211_UNLOCK(ic);
|
||||
IEEE80211_SEND_MGMT(ic, ni, resp,
|
||||
IEEE80211_REASON_ASSOC_TOOMANY);
|
||||
ieee80211_node_leave(ic, ni);
|
||||
return;
|
||||
}
|
||||
ni->ni_associd = aid | 0xc000;
|
||||
ni->ni_jointime = time_uptime;
|
||||
IEEE80211_AID_SET(ni->ni_associd, ic->ic_aid_bitmap);
|
||||
ic->ic_sta_assoc++;
|
||||
newassoc = 1;
|
||||
|
||||
if (IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
|
||||
ieee80211_ht_node_join(ni);
|
||||
if (IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan) &&
|
||||
IEEE80211_IS_CHAN_FULL(ic->ic_bsschan))
|
||||
ieee80211_node_join_11g(ic, ni);
|
||||
IEEE80211_UNLOCK(ic);
|
||||
|
||||
newassoc = 1;
|
||||
} else
|
||||
newassoc = 0;
|
||||
|
||||
IEEE80211_NOTE(ic, IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG, ni,
|
||||
"station %sassociated at aid %d: %s preamble, %s slot time%s%s%s%s%s",
|
||||
"station %sassociated at aid %d: %s preamble, %s slot time%s%s%s%s%s%s",
|
||||
newassoc ? "" : "re",
|
||||
IEEE80211_NODE_AID(ni),
|
||||
ic->ic_flags & IEEE80211_F_SHPREAMBLE ? "short" : "long",
|
||||
@ -1759,6 +1777,7 @@ ieee80211_node_join(struct ieee80211com *ic, struct ieee80211_node *ni, int resp
|
||||
ni->ni_flags & IEEE80211_NODE_QOS ? ", QoS" : "",
|
||||
ni->ni_flags & IEEE80211_NODE_HT ?
|
||||
(ni->ni_chw == 20 ? ", HT20" : ", HT40") : "",
|
||||
ni->ni_flags & IEEE80211_NODE_AMPDU ? " (+AMPDU)" : "",
|
||||
IEEE80211_ATH_CAP(ic, ni, IEEE80211_NODE_FF) ?
|
||||
", fast-frames" : "",
|
||||
IEEE80211_ATH_CAP(ic, ni, IEEE80211_NODE_TURBOP) ?
|
||||
@ -1799,6 +1818,8 @@ static void
|
||||
ieee80211_node_leave_11g(struct ieee80211com *ic, struct ieee80211_node *ni)
|
||||
{
|
||||
|
||||
IEEE80211_LOCK_ASSERT(ic);
|
||||
|
||||
KASSERT(IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan),
|
||||
("not in 11g, bss %u:0x%x, curmode %u", ic->ic_bsschan->ic_freq,
|
||||
ic->ic_bsschan->ic_flags, ic->ic_curmode));
|
||||
@ -1900,13 +1921,18 @@ ieee80211_node_leave(struct ieee80211com *ic, struct ieee80211_node *ni)
|
||||
*/
|
||||
if (ic->ic_auth->ia_node_leave != NULL)
|
||||
ic->ic_auth->ia_node_leave(ic, ni);
|
||||
|
||||
IEEE80211_LOCK(ic);
|
||||
IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
|
||||
ni->ni_associd = 0;
|
||||
ic->ic_sta_assoc--;
|
||||
|
||||
if (IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
|
||||
ieee80211_ht_node_leave(ni);
|
||||
if (IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan) &&
|
||||
IEEE80211_IS_CHAN_FULL(ic->ic_bsschan))
|
||||
ieee80211_node_leave_11g(ic, ni);
|
||||
IEEE80211_UNLOCK(ic);
|
||||
/*
|
||||
* Cleanup station state. In particular clear various
|
||||
* state that might otherwise be reused if the node
|
||||
|
@ -111,10 +111,13 @@ struct ieee80211_node {
|
||||
#define IEEE80211_NODE_AREF 0x0020 /* authentication ref held */
|
||||
#define IEEE80211_NODE_HT 0x0040 /* HT enabled */
|
||||
#define IEEE80211_NODE_HTCOMPAT 0x0080 /* HT setup w/ vendor OUI's */
|
||||
#define IEEE80211_NODE_AMPDU_RX 0x0400 /* AMPDU rx enabled */
|
||||
#define IEEE80211_NODE_AMPDU_TX 0x0800 /* AMPDU tx enabled */
|
||||
uint16_t ni_ath_defkeyix;/* Atheros def key index */
|
||||
uint16_t ni_associd; /* assoc response */
|
||||
uint16_t ni_txpower; /* current transmit power */
|
||||
uint16_t ni_vlan; /* vlan tag */
|
||||
uint32_t ni_jointime; /* time of join (secs) */
|
||||
uint32_t *ni_challenge; /* shared-key challenge */
|
||||
uint8_t *ni_wpa_ie; /* captured WPA ie */
|
||||
uint8_t *ni_rsn_ie; /* captured RSN ie */
|
||||
@ -157,6 +160,7 @@ struct ieee80211_node {
|
||||
uint8_t ni_dtim_count; /* DTIM count for last bcn */
|
||||
|
||||
/* 11n state */
|
||||
uint8_t *ni_htcap_ie; /* captured HTCAP ie */
|
||||
uint16_t ni_htcap; /* HT capabilities */
|
||||
uint8_t ni_htparam; /* HT params */
|
||||
uint8_t ni_htctlchan; /* HT control channel */
|
||||
@ -180,6 +184,8 @@ struct ieee80211_node {
|
||||
MALLOC_DECLARE(M_80211_NODE);
|
||||
|
||||
#define IEEE80211_NODE_ATH (IEEE80211_NODE_FF | IEEE80211_NODE_TURBOP)
|
||||
#define IEEE80211_NODE_AMPDU \
|
||||
(IEEE80211_NODE_AMPDU_RX | IEEE80211_NODE_AMPDU_TX)
|
||||
|
||||
#define IEEE80211_NODE_AID(ni) IEEE80211_AID(ni->ni_associd)
|
||||
|
||||
@ -219,6 +225,7 @@ void ieee80211_node_unauthorize(struct ieee80211_node *);
|
||||
void ieee80211_probe_curchan(struct ieee80211com *, int);
|
||||
void ieee80211_create_ibss(struct ieee80211com*, struct ieee80211_channel *);
|
||||
void ieee80211_reset_bss(struct ieee80211com *);
|
||||
void ieee80211_setbsschan(struct ieee80211com *, struct ieee80211_channel *);
|
||||
int ieee80211_ibss_merge(struct ieee80211_node *);
|
||||
struct ieee80211_scan_entry;
|
||||
int ieee80211_sta_join(struct ieee80211com *,
|
||||
|
@ -819,7 +819,7 @@ ieee80211_encap(struct ieee80211com *ic, struct mbuf *m,
|
||||
* in case the receiver NAK's us or we are otherwise
|
||||
* unable to establish a BA stream.
|
||||
*/
|
||||
if ((ni->ni_flags & IEEE80211_NODE_HT) &&
|
||||
if ((ni->ni_flags & IEEE80211_NODE_AMPDU_TX) &&
|
||||
(ic->ic_flags_ext & IEEE80211_FEXT_AMPDU_TX)) {
|
||||
struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[ac];
|
||||
|
||||
@ -1583,7 +1583,9 @@ int
|
||||
ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
|
||||
int type, int arg)
|
||||
{
|
||||
#define HTFLAGS (IEEE80211_NODE_HT | IEEE80211_NODE_HTCOMPAT)
|
||||
#define senderr(_x, _v) do { ic->ic_stats._v++; ret = _x; goto bad; } while (0)
|
||||
const struct ieee80211_rateset *rs;
|
||||
struct mbuf *m;
|
||||
uint8_t *frm;
|
||||
uint16_t capinfo;
|
||||
@ -1657,7 +1659,8 @@ ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
|
||||
|
||||
frm = ieee80211_add_ssid(frm, ic->ic_bss->ni_essid,
|
||||
ic->ic_bss->ni_esslen);
|
||||
frm = ieee80211_add_rates(frm, &ni->ni_rates);
|
||||
rs = ieee80211_get_suprates(ic, ic->ic_curchan);
|
||||
frm = ieee80211_add_rates(frm, rs);
|
||||
|
||||
if (IEEE80211_IS_CHAN_FHSS(ic->ic_curchan)) {
|
||||
*frm++ = IEEE80211_ELEMID_FHPARMS;
|
||||
@ -1684,16 +1687,25 @@ ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
|
||||
frm = ieee80211_add_wpa(frm, ic);
|
||||
if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan))
|
||||
frm = ieee80211_add_erp(frm, ic);
|
||||
frm = ieee80211_add_xrates(frm, &ni->ni_rates);
|
||||
if (ic->ic_flags & IEEE80211_F_WME)
|
||||
frm = ieee80211_add_wme_param(frm, &ic->ic_wme);
|
||||
if (IEEE80211_IS_CHAN_HT(ic->ic_curchan)) {
|
||||
frm = ieee80211_add_xrates(frm, rs);
|
||||
/*
|
||||
* NB: legacy 11b clients do not get certain ie's.
|
||||
* The caller identifies such clients by passing
|
||||
* 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_curchan) &&
|
||||
arg != IEEE80211_SEND_LEGACY_11B) {
|
||||
frm = ieee80211_add_htcap(frm, ni);
|
||||
frm = ieee80211_add_htinfo(frm, ni);
|
||||
if (ic->ic_flags_ext & IEEE80211_FEXT_HTCOMPAT) {
|
||||
frm = ieee80211_add_htcap_vendor(frm, ni);
|
||||
frm = ieee80211_add_htinfo_vendor(frm, ni);
|
||||
}
|
||||
}
|
||||
if (ic->ic_flags & IEEE80211_F_WME)
|
||||
frm = ieee80211_add_wme_param(frm, &ic->ic_wme);
|
||||
if (IEEE80211_IS_CHAN_HT(ic->ic_curchan) &&
|
||||
(ic->ic_flags_ext & IEEE80211_FEXT_HTCOMPAT) &&
|
||||
arg != IEEE80211_SEND_LEGACY_11B) {
|
||||
frm = ieee80211_add_htcap_vendor(frm, ni);
|
||||
frm = ieee80211_add_htinfo_vendor(frm, ni);
|
||||
}
|
||||
if (ni->ni_ath_ie != NULL)
|
||||
frm = ieee80211_add_ath(frm, ni->ni_ath_flags,
|
||||
@ -1828,6 +1840,9 @@ ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
|
||||
if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan) &&
|
||||
(ic->ic_caps & IEEE80211_C_SHSLOT))
|
||||
capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;
|
||||
if ((ni->ni_capinfo & IEEE80211_CAPINFO_SPECTRUM_MGMT) &&
|
||||
(ic->ic_flags & IEEE80211_F_DOTH))
|
||||
capinfo |= IEEE80211_CAPINFO_SPECTRUM_MGMT;
|
||||
*(uint16_t *)frm = htole16(capinfo);
|
||||
frm += 2;
|
||||
|
||||
@ -1845,13 +1860,16 @@ ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
|
||||
frm = ieee80211_add_ssid(frm, ni->ni_essid, ni->ni_esslen);
|
||||
frm = ieee80211_add_rates(frm, &ni->ni_rates);
|
||||
frm = ieee80211_add_xrates(frm, &ni->ni_rates);
|
||||
if ((ic->ic_flags_ext & IEEE80211_FEXT_HT) &&
|
||||
ni->ni_htcap_ie != NULL &&
|
||||
ni->ni_htcap_ie[0] == IEEE80211_ELEMID_HTCAP)
|
||||
frm = ieee80211_add_htcap(frm, ni);
|
||||
if ((ic->ic_flags & IEEE80211_F_WME) && ni->ni_wme_ie != NULL)
|
||||
frm = ieee80211_add_wme_info(frm, &ic->ic_wme);
|
||||
if (IEEE80211_IS_CHAN_HT(ic->ic_curchan)) {
|
||||
frm = ieee80211_add_htcap(frm, ni);
|
||||
if (ic->ic_flags_ext & IEEE80211_FEXT_HTCOMPAT)
|
||||
frm = ieee80211_add_htcap_vendor(frm, ni);
|
||||
}
|
||||
if ((ic->ic_flags_ext & IEEE80211_FEXT_HT) &&
|
||||
ni->ni_htcap_ie != NULL &&
|
||||
ni->ni_htcap_ie[0] == IEEE80211_ELEMID_VENDOR)
|
||||
frm = ieee80211_add_htcap_vendor(frm, ni);
|
||||
if (IEEE80211_ATH_CAP(ic, ni, IEEE80211_F_ATHEROS))
|
||||
frm = ieee80211_add_ath(frm,
|
||||
IEEE80211_ATH_CAP(ic, ni, IEEE80211_F_ATHEROS),
|
||||
@ -1914,17 +1932,16 @@ ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
|
||||
|
||||
frm = ieee80211_add_rates(frm, &ni->ni_rates);
|
||||
frm = ieee80211_add_xrates(frm, &ni->ni_rates);
|
||||
/* NB: respond according to what we received */
|
||||
if ((ni->ni_flags & HTFLAGS) == IEEE80211_NODE_HT) {
|
||||
frm = ieee80211_add_htcap(frm, ni);
|
||||
frm = ieee80211_add_htinfo(frm, ni);
|
||||
}
|
||||
if ((ic->ic_flags & IEEE80211_F_WME) && ni->ni_wme_ie != NULL)
|
||||
frm = ieee80211_add_wme_param(frm, &ic->ic_wme);
|
||||
if (IEEE80211_IS_CHAN_HT(ic->ic_curchan)) {
|
||||
/* NB: respond according to what we received */
|
||||
if (ni->ni_flags & IEEE80211_NODE_HTCOMPAT) {
|
||||
frm = ieee80211_add_htcap_vendor(frm, ni);
|
||||
frm = ieee80211_add_htinfo_vendor(frm, ni);
|
||||
} else {
|
||||
frm = ieee80211_add_htcap(frm, ni);
|
||||
frm = ieee80211_add_htinfo(frm, ni);
|
||||
}
|
||||
if ((ni->ni_flags & HTFLAGS) == HTFLAGS) {
|
||||
frm = ieee80211_add_htcap_vendor(frm, ni);
|
||||
frm = ieee80211_add_htinfo_vendor(frm, ni);
|
||||
}
|
||||
if (IEEE80211_ATH_CAP(ic, ni, IEEE80211_F_ATHEROS))
|
||||
frm = ieee80211_add_ath(frm,
|
||||
@ -1965,6 +1982,7 @@ ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
|
||||
ieee80211_free_node(ni);
|
||||
return ret;
|
||||
#undef senderr
|
||||
#undef HTFLAGS
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2072,6 +2090,8 @@ ieee80211_beacon_alloc(struct ieee80211_node *ni,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(bo, 0, sizeof(*bo));
|
||||
|
||||
memset(frm, 0, 8); /* XXX timestamp is set by hardware/driver */
|
||||
frm += 8;
|
||||
*(uint16_t *)frm = htole16(ni->ni_intval);
|
||||
@ -2115,29 +2135,27 @@ ieee80211_beacon_alloc(struct ieee80211_node *ni,
|
||||
if (ic->ic_flags & IEEE80211_F_DOTH)
|
||||
frm = ieee80211_add_countryie(frm, ic,
|
||||
ic->ic_countrycode, ic->ic_location);
|
||||
if (ic->ic_flags & IEEE80211_F_WME) {
|
||||
bo->bo_wme = frm;
|
||||
frm = ieee80211_add_wme_param(frm, &ic->ic_wme);
|
||||
} else
|
||||
bo->bo_wme = NULL;
|
||||
if (ic->ic_flags & IEEE80211_F_WPA)
|
||||
frm = ieee80211_add_wpa(frm, ic);
|
||||
if (IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan)) {
|
||||
bo->bo_erp = frm;
|
||||
frm = ieee80211_add_erp(frm, ic);
|
||||
} else
|
||||
bo->bo_erp = NULL;
|
||||
}
|
||||
frm = ieee80211_add_xrates(frm, rs);
|
||||
if (IEEE80211_IS_CHAN_HT(ic->ic_bsschan)) {
|
||||
frm = ieee80211_add_htcap(frm, ni);
|
||||
bo->bo_htinfo = frm;
|
||||
frm = ieee80211_add_htinfo(frm, ni);
|
||||
if (ic->ic_flags_ext & IEEE80211_FEXT_HTCOMPAT) {
|
||||
frm = ieee80211_add_htcap_vendor(frm, ni);
|
||||
frm = ieee80211_add_htinfo_vendor(frm, ni);
|
||||
}
|
||||
} else
|
||||
bo->bo_htinfo = NULL;
|
||||
}
|
||||
if (ic->ic_flags & IEEE80211_F_WME) {
|
||||
bo->bo_wme = frm;
|
||||
frm = ieee80211_add_wme_param(frm, &ic->ic_wme);
|
||||
}
|
||||
if (IEEE80211_IS_CHAN_HT(ic->ic_bsschan) &&
|
||||
(ic->ic_flags_ext & IEEE80211_FEXT_HTCOMPAT)) {
|
||||
frm = ieee80211_add_htcap_vendor(frm, ni);
|
||||
frm = ieee80211_add_htinfo_vendor(frm, ni);
|
||||
}
|
||||
bo->bo_tim_trailer_len = frm - bo->bo_tim_trailer;
|
||||
m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
|
||||
|
||||
|
@ -1306,7 +1306,9 @@ ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg
|
||||
* of this explicitly sync the scanner state.
|
||||
*/
|
||||
ieee80211_scan_update(ic);
|
||||
ieee80211_create_ibss(ic, ic->ic_curchan);
|
||||
ieee80211_create_ibss(ic,
|
||||
ieee80211_ht_adjust_channel(ic,
|
||||
ic->ic_curchan, ic->ic_flags_ext));
|
||||
break;
|
||||
}
|
||||
/* fall thru... */
|
||||
|
@ -47,6 +47,16 @@ enum ieee80211_state {
|
||||
#define IEEE80211_SEND_MGMT(_ic,_ni,_type,_arg) \
|
||||
((*(_ic)->ic_send_mgmt)(_ic, _ni, _type, _arg))
|
||||
|
||||
/*
|
||||
* The formation of some management frames requires guidance to
|
||||
* deal with legacy clients. When the client is identified as
|
||||
* "legacy 11b" this parameter can be passed in the arg param of a
|
||||
* IEEE80211_SEND_MGMT call.
|
||||
*/
|
||||
#define IEEE80211_SEND_LEGACY_11B 0x1 /* legacy 11b client */
|
||||
#define IEEE80211_SEND_LEGACY_11 0x2 /* other legacy client */
|
||||
#define IEEE80211_SEND_LEGACY 0x3 /* any legacy client */
|
||||
|
||||
extern const char *ieee80211_mgt_subtype_name[];
|
||||
extern const char *ieee80211_phymode_name[];
|
||||
|
||||
|
@ -325,7 +325,8 @@ ap_end(struct ieee80211_scan_state *ss, struct ieee80211com *ic)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ieee80211_create_ibss(ic, c);
|
||||
ieee80211_create_ibss(ic,
|
||||
ieee80211_ht_adjust_channel(ic, c, ic->ic_flags_ext));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -1352,7 +1352,8 @@ adhoc_pick_bss(struct ieee80211_scan_state *ss, struct ieee80211com *ic)
|
||||
* specified, try to select a channel.
|
||||
*/
|
||||
if (ic->ic_des_chan == IEEE80211_CHAN_ANYC)
|
||||
chan = adhoc_pick_channel(ss);
|
||||
chan = ieee80211_ht_adjust_channel(ic,
|
||||
adhoc_pick_channel(ss), ic->ic_flags_ext);
|
||||
else
|
||||
chan = ic->ic_des_chan;
|
||||
if (chan != NULL) {
|
||||
|
@ -105,7 +105,9 @@ struct ieee80211com {
|
||||
|
||||
uint32_t ic_flags; /* state flags */
|
||||
uint32_t ic_flags_ext; /* extended state flags */
|
||||
uint32_t ic_flags_ven; /* vendor state flags */
|
||||
uint32_t ic_caps; /* capabilities */
|
||||
uint32_t ic_htcaps; /* HT capabilities */
|
||||
uint8_t ic_modecaps[2]; /* set of mode capabilities */
|
||||
uint16_t ic_curmode; /* current mode */
|
||||
struct ieee80211_rateset ic_sup_rates[IEEE80211_MODE_MAX];
|
||||
@ -113,7 +115,6 @@ struct ieee80211com {
|
||||
uint16_t ic_lintval; /* listen interval */
|
||||
uint16_t ic_holdover; /* PM hold over duration */
|
||||
uint16_t ic_txpowlimit; /* global tx power limit */
|
||||
uint32_t ic_htcaps; /* HT capabilities */
|
||||
int ic_ampdu_rxmax; /* A-MPDU rx limit (bytes) */
|
||||
int ic_ampdu_density;/* A-MPDU density */
|
||||
int ic_ampdu_limit; /* A-MPDU tx limit (bytes) */
|
||||
@ -175,8 +176,12 @@ struct ieee80211com {
|
||||
uint16_t ic_nonerpsta; /* # non-ERP stations */
|
||||
uint16_t ic_longslotsta; /* # long slot time stations */
|
||||
uint16_t ic_sta_assoc; /* stations associated */
|
||||
uint16_t ic_ht_sta_assoc;/* HT stations associated */
|
||||
uint16_t ic_ht40_sta_assoc;/* HT40 stations associated */
|
||||
uint8_t ic_curhtprotmode;/* HTINFO bss state */
|
||||
enum ieee80211_protmode ic_htprotmode; /* HT protection mode */
|
||||
int ic_lastnonerp; /* last time non-ERP sta noted*/
|
||||
int ic_lastnonht; /* last time non-HT sta noted */
|
||||
|
||||
struct ifqueue ic_mgtq;
|
||||
enum ieee80211_state ic_state; /* 802.11 state */
|
||||
@ -334,7 +339,7 @@ struct ieee80211com {
|
||||
((ic)->ic_flags & (ni)->ni_ath_flags & (bit))
|
||||
|
||||
/* ic_flags_ext */
|
||||
#define IEEE80211_FEXT_WDS 0x00000001 /* CONF: 4 addr allowed */
|
||||
#define IEEE80211_FEXT_NONHT_PR 0x00000001 /* STATUS: non-HT sta present */
|
||||
#define IEEE80211_FEXT_INACT 0x00000002 /* CONF: sta inact handling */
|
||||
/* 0x00000006 reserved */
|
||||
#define IEEE80211_FEXT_BGSCAN 0x00000008 /* STATUS: complete bgscan */
|
||||
@ -391,6 +396,8 @@ struct ieee80211com {
|
||||
*/
|
||||
#define IEEE80211_HTC_AMPDU 0x00010000 /* CAPABILITY: A-MPDU tx */
|
||||
#define IEEE80211_HTC_AMSDU 0x00020000 /* CAPABILITY: A-MSDU tx */
|
||||
/* NB: HT40 is implied by IEEE80211_HTCAP_CHWIDTH40 */
|
||||
#define IEEE80211_HTC_HT 0x00040000 /* CAPABILITY: HT operation */
|
||||
|
||||
void ieee80211_ifattach(struct ieee80211com *);
|
||||
void ieee80211_ifdetach(struct ieee80211com *);
|
||||
@ -472,6 +479,16 @@ ieee80211_beacon_notify(struct ieee80211com *ic, int what)
|
||||
ic->ic_update_beacon(ic, what);
|
||||
}
|
||||
|
||||
/*
|
||||
* Debugging facilities compiled in when IEEE80211_DEBUG is defined.
|
||||
*
|
||||
* The intent is that any problem in the net80211 layer can be
|
||||
* diagnosed by inspecting the statistics (dumped by the wlanstats
|
||||
* program) and/or the msgs generated by net80211. Messages are
|
||||
* broken into functional classes and can be controlled with the
|
||||
* wlandebug program. Certain of these msg groups are for facilities
|
||||
* that are no longer part of net80211 (e.g. IEEE80211_MSG_DOT1X).
|
||||
*/
|
||||
#define IEEE80211_MSG_11N 0x80000000 /* 11n mode debug */
|
||||
#define IEEE80211_MSG_DEBUG 0x40000000 /* IFF_DEBUG equivalent */
|
||||
#define IEEE80211_MSG_DUMPPKTS 0x20000000 /* IFF_LINK2 equivalant */
|
||||
@ -500,6 +517,8 @@ ieee80211_beacon_notify(struct ieee80211com *ic, int what)
|
||||
#define IEEE80211_MSG_ROAM 0x00000040 /* sta-mode roaming */
|
||||
#define IEEE80211_MSG_RATECTL 0x00000020 /* tx rate control */
|
||||
#define IEEE80211_MSG_ACTION 0x00000010 /* action frame handling */
|
||||
#define IEEE80211_MSG_WDS 0x00000008 /* WDS handling */
|
||||
#define IEEE80211_MSG_IOCTL 0x00000004 /* ioctl handling */
|
||||
|
||||
#define IEEE80211_MSG_ANY 0xffffffff /* anything */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user