Changeset View
Changeset View
Standalone View
Standalone View
sys/net80211/ieee80211_ht.c
Show First 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | |||||
#include <net/if_var.h> | #include <net/if_var.h> | ||||
#include <net/if_media.h> | #include <net/if_media.h> | ||||
#include <net/ethernet.h> | #include <net/ethernet.h> | ||||
#include <net80211/ieee80211_var.h> | #include <net80211/ieee80211_var.h> | ||||
#include <net80211/ieee80211_action.h> | #include <net80211/ieee80211_action.h> | ||||
#include <net80211/ieee80211_input.h> | #include <net80211/ieee80211_input.h> | ||||
/* define here, used throughout file */ | |||||
#define MS(_v, _f) (((_v) & _f) >> _f##_S) | |||||
#define SM(_v, _f) (((_v) << _f##_S) & _f) | |||||
const struct ieee80211_mcs_rates ieee80211_htrates[IEEE80211_HTRATE_MAXSIZE] = { | const struct ieee80211_mcs_rates ieee80211_htrates[IEEE80211_HTRATE_MAXSIZE] = { | ||||
{ 13, 14, 27, 30 }, /* MCS 0 */ | { 13, 14, 27, 30 }, /* MCS 0 */ | ||||
{ 26, 29, 54, 60 }, /* MCS 1 */ | { 26, 29, 54, 60 }, /* MCS 1 */ | ||||
{ 39, 43, 81, 90 }, /* MCS 2 */ | { 39, 43, 81, 90 }, /* MCS 2 */ | ||||
{ 52, 58, 108, 120 }, /* MCS 3 */ | { 52, 58, 108, 120 }, /* MCS 3 */ | ||||
{ 78, 87, 162, 180 }, /* MCS 4 */ | { 78, 87, 162, 180 }, /* MCS 4 */ | ||||
{ 104, 116, 216, 240 }, /* MCS 5 */ | { 104, 116, 216, 240 }, /* MCS 5 */ | ||||
{ 117, 130, 243, 270 }, /* MCS 6 */ | { 117, 130, 243, 270 }, /* MCS 6 */ | ||||
▲ Show 20 Lines • Show All 629 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Start A-MPDU rx/re-order processing for the specified TID. | * Start A-MPDU rx/re-order processing for the specified TID. | ||||
*/ | */ | ||||
static int | static int | ||||
ampdu_rx_start(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap, | ampdu_rx_start(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap, | ||||
int baparamset, int batimeout, int baseqctl) | int baparamset, int batimeout, int baseqctl) | ||||
{ | { | ||||
struct ieee80211vap *vap = ni->ni_vap; | struct ieee80211vap *vap = ni->ni_vap; | ||||
int bufsiz = MS(baparamset, IEEE80211_BAPS_BUFSIZ); | int bufsiz = _IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_BUFSIZ); | ||||
if (rap->rxa_flags & IEEE80211_AGGR_RUNNING) { | if (rap->rxa_flags & IEEE80211_AGGR_RUNNING) { | ||||
/* | /* | ||||
* AMPDU previously setup and not terminated with a DELBA, | * AMPDU previously setup and not terminated with a DELBA, | ||||
* flush the reorder q's in case anything remains. | * flush the reorder q's in case anything remains. | ||||
*/ | */ | ||||
ampdu_rx_purge(rap); | ampdu_rx_purge(rap); | ||||
} | } | ||||
ieee80211_ampdu_rx_init_rap(ni, rap); | ieee80211_ampdu_rx_init_rap(ni, rap); | ||||
rap->rxa_wnd = (bufsiz == 0) ? | rap->rxa_wnd = (bufsiz == 0) ? | ||||
IEEE80211_AGGR_BAWMAX : min(bufsiz, IEEE80211_AGGR_BAWMAX); | IEEE80211_AGGR_BAWMAX : min(bufsiz, IEEE80211_AGGR_BAWMAX); | ||||
rap->rxa_start = MS(baseqctl, IEEE80211_BASEQ_START); | rap->rxa_start = _IEEE80211_MASKSHIFT(baseqctl, IEEE80211_BASEQ_START); | ||||
rap->rxa_flags |= IEEE80211_AGGR_RUNNING | IEEE80211_AGGR_XCHGPEND; | rap->rxa_flags |= IEEE80211_AGGR_RUNNING | IEEE80211_AGGR_XCHGPEND; | ||||
/* XXX this should be a configuration flag */ | /* XXX this should be a configuration flag */ | ||||
if ((vap->iv_htcaps & IEEE80211_HTC_RX_AMSDU_AMPDU) && | if ((vap->iv_htcaps & IEEE80211_HTC_RX_AMSDU_AMPDU) && | ||||
(MS(baparamset, IEEE80211_BAPS_AMSDU))) | (_IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_AMSDU))) | ||||
rap->rxa_flags |= IEEE80211_AGGR_AMSDU; | rap->rxa_flags |= IEEE80211_AGGR_AMSDU; | ||||
else | else | ||||
rap->rxa_flags &= ~IEEE80211_AGGR_AMSDU; | rap->rxa_flags &= ~IEEE80211_AGGR_AMSDU; | ||||
return 0; | return 0; | ||||
} | } | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 510 Lines • ▼ Show 20 Lines | #if 0 | ||||
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_11N, | IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_11N, | ||||
ni->ni_macaddr, "BAR", "%s", "processing disabled"); | ni->ni_macaddr, "BAR", "%s", "processing disabled"); | ||||
#endif | #endif | ||||
vap->iv_stats.is_ampdu_bar_bad++; | vap->iv_stats.is_ampdu_bar_bad++; | ||||
return; | return; | ||||
} | } | ||||
wh = mtod(m0, struct ieee80211_frame_bar *); | wh = mtod(m0, struct ieee80211_frame_bar *); | ||||
/* XXX check basic BAR */ | /* XXX check basic BAR */ | ||||
tid = MS(le16toh(wh->i_ctl), IEEE80211_BAR_TID); | tid = _IEEE80211_MASKSHIFT(le16toh(wh->i_ctl), IEEE80211_BAR_TID); | ||||
rap = &ni->ni_rx_ampdu[tid]; | rap = &ni->ni_rx_ampdu[tid]; | ||||
if ((rap->rxa_flags & IEEE80211_AGGR_XCHGPEND) == 0) { | if ((rap->rxa_flags & IEEE80211_AGGR_XCHGPEND) == 0) { | ||||
/* | /* | ||||
* No ADDBA request yet, don't touch. | * No ADDBA request yet, don't touch. | ||||
*/ | */ | ||||
IEEE80211_DISCARD_MAC(vap, | IEEE80211_DISCARD_MAC(vap, | ||||
IEEE80211_MSG_INPUT | IEEE80211_MSG_11N, | IEEE80211_MSG_INPUT | IEEE80211_MSG_11N, | ||||
ni->ni_macaddr, "BAR", "no BA stream, tid %u", tid); | ni->ni_macaddr, "BAR", "no BA stream, tid %u", tid); | ||||
▲ Show 20 Lines • Show All 363 Lines • ▼ Show 20 Lines | |||||
* change PROTOPT -> MIXED; only MIXED -> PROTOPT). This | * change PROTOPT -> MIXED; only MIXED -> PROTOPT). This | ||||
* corresponds to how we handle things in htinfo_update. | * corresponds to how we handle things in htinfo_update. | ||||
* | * | ||||
*/ | */ | ||||
void | void | ||||
ieee80211_htprot_update(struct ieee80211vap *vap, int protmode) | ieee80211_htprot_update(struct ieee80211vap *vap, int protmode) | ||||
{ | { | ||||
struct ieee80211com *ic = vap->iv_ic; | struct ieee80211com *ic = vap->iv_ic; | ||||
#define OPMODE(x) SM(x, IEEE80211_HTINFO_OPMODE) | #define OPMODE(x) _IEEE80211_SHIFTMASK(x, IEEE80211_HTINFO_OPMODE) | ||||
IEEE80211_LOCK(ic); | IEEE80211_LOCK(ic); | ||||
/* track non-HT station presence */ | /* track non-HT station presence */ | ||||
KASSERT(protmode & IEEE80211_HTINFO_NONHT_PRESENT, | KASSERT(protmode & IEEE80211_HTINFO_NONHT_PRESENT, | ||||
("protmode 0x%x", protmode)); | ("protmode 0x%x", protmode)); | ||||
vap->iv_flags_ht |= IEEE80211_FHT_NONHT_PR; | vap->iv_flags_ht |= IEEE80211_FHT_NONHT_PR; | ||||
vap->iv_lastnonht = ticks; | vap->iv_lastnonht = ticks; | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
htinfo_parse(struct ieee80211_node *ni, | htinfo_parse(struct ieee80211_node *ni, | ||||
const struct ieee80211_ie_htinfo *htinfo) | const struct ieee80211_ie_htinfo *htinfo) | ||||
{ | { | ||||
uint16_t w; | uint16_t w; | ||||
ni->ni_htctlchan = htinfo->hi_ctrlchannel; | ni->ni_htctlchan = htinfo->hi_ctrlchannel; | ||||
ni->ni_ht2ndchan = SM(htinfo->hi_byte1, IEEE80211_HTINFO_2NDCHAN); | ni->ni_ht2ndchan = _IEEE80211_SHIFTMASK(htinfo->hi_byte1, IEEE80211_HTINFO_2NDCHAN); | ||||
w = le16dec(&htinfo->hi_byte2); | w = le16dec(&htinfo->hi_byte2); | ||||
ni->ni_htopmode = SM(w, IEEE80211_HTINFO_OPMODE); | ni->ni_htopmode = _IEEE80211_SHIFTMASK(w, IEEE80211_HTINFO_OPMODE); | ||||
w = le16dec(&htinfo->hi_byte45); | w = le16dec(&htinfo->hi_byte45); | ||||
ni->ni_htstbc = SM(w, IEEE80211_HTINFO_BASIC_STBCMCS); | ni->ni_htstbc = _IEEE80211_SHIFTMASK(w, IEEE80211_HTINFO_BASIC_STBCMCS); | ||||
} | } | ||||
/* | /* | ||||
* Parse an 802.11n HT info ie and save useful information | * Parse an 802.11n HT info ie and save useful information | ||||
* to the node state. Note this does not effect any state | * to the node state. Note this does not effect any state | ||||
* changes such as for channel width change. | * changes such as for channel width change. | ||||
*/ | */ | ||||
void | void | ||||
▲ Show 20 Lines • Show All 222 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
struct ieee80211vap *vap = ni->ni_vap; | struct ieee80211vap *vap = ni->ni_vap; | ||||
uint32_t vhtflags = 0; | uint32_t vhtflags = 0; | ||||
vhtflags = 0; | vhtflags = 0; | ||||
if (ni->ni_flags & IEEE80211_NODE_VHT && vap->iv_flags_vht & IEEE80211_FVHT_VHT) { | if (ni->ni_flags & IEEE80211_NODE_VHT && vap->iv_flags_vht & IEEE80211_FVHT_VHT) { | ||||
if ((ni->ni_vht_chanwidth == IEEE80211_VHT_CHANWIDTH_160MHZ) && | if ((ni->ni_vht_chanwidth == IEEE80211_VHT_CHANWIDTH_160MHZ) && | ||||
/* XXX 2 means "160MHz and 80+80MHz", 1 means "160MHz" */ | /* XXX 2 means "160MHz and 80+80MHz", 1 means "160MHz" */ | ||||
(MS(vap->iv_vhtcaps, | (_IEEE80211_MASKSHIFT(vap->iv_vhtcaps, | ||||
IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK) >= 1) && | IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK) >= 1) && | ||||
(vap->iv_flags_vht & IEEE80211_FVHT_USEVHT160)) { | (vap->iv_flags_vht & IEEE80211_FVHT_USEVHT160)) { | ||||
vhtflags = IEEE80211_CHAN_VHT160; | vhtflags = IEEE80211_CHAN_VHT160; | ||||
/* Mirror the HT40 flags */ | /* Mirror the HT40 flags */ | ||||
if (htflags == IEEE80211_CHAN_HT40U) { | if (htflags == IEEE80211_CHAN_HT40U) { | ||||
vhtflags |= IEEE80211_CHAN_HT40U; | vhtflags |= IEEE80211_CHAN_HT40U; | ||||
} else if (htflags == IEEE80211_CHAN_HT40D) { | } else if (htflags == IEEE80211_CHAN_HT40D) { | ||||
vhtflags |= IEEE80211_CHAN_HT40D; | vhtflags |= IEEE80211_CHAN_HT40D; | ||||
} | } | ||||
} else if ((ni->ni_vht_chanwidth == IEEE80211_VHT_CHANWIDTH_80P80MHZ) && | } else if ((ni->ni_vht_chanwidth == IEEE80211_VHT_CHANWIDTH_80P80MHZ) && | ||||
/* XXX 2 means "160MHz and 80+80MHz" */ | /* XXX 2 means "160MHz and 80+80MHz" */ | ||||
(MS(vap->iv_vhtcaps, | (_IEEE80211_MASKSHIFT(vap->iv_vhtcaps, | ||||
IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK) == 2) && | IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK) == 2) && | ||||
(vap->iv_flags_vht & IEEE80211_FVHT_USEVHT80P80)) { | (vap->iv_flags_vht & IEEE80211_FVHT_USEVHT80P80)) { | ||||
vhtflags = IEEE80211_CHAN_VHT80P80; | vhtflags = IEEE80211_CHAN_VHT80P80; | ||||
/* Mirror the HT40 flags */ | /* Mirror the HT40 flags */ | ||||
if (htflags == IEEE80211_CHAN_HT40U) { | if (htflags == IEEE80211_CHAN_HT40U) { | ||||
vhtflags |= IEEE80211_CHAN_HT40U; | vhtflags |= IEEE80211_CHAN_HT40U; | ||||
} else if (htflags == IEEE80211_CHAN_HT40D) { | } else if (htflags == IEEE80211_CHAN_HT40D) { | ||||
vhtflags |= IEEE80211_CHAN_HT40D; | vhtflags |= IEEE80211_CHAN_HT40D; | ||||
▲ Show 20 Lines • Show All 316 Lines • ▼ Show 20 Lines | ieee80211_addba_request(struct ieee80211_node *ni, | ||||
struct ieee80211_tx_ampdu *tap, | struct ieee80211_tx_ampdu *tap, | ||||
int dialogtoken, int baparamset, int batimeout) | int dialogtoken, int baparamset, int batimeout) | ||||
{ | { | ||||
int bufsiz; | int bufsiz; | ||||
/* XXX locking */ | /* XXX locking */ | ||||
tap->txa_token = dialogtoken; | tap->txa_token = dialogtoken; | ||||
tap->txa_flags |= IEEE80211_AGGR_IMMEDIATE; | tap->txa_flags |= IEEE80211_AGGR_IMMEDIATE; | ||||
bufsiz = MS(baparamset, IEEE80211_BAPS_BUFSIZ); | bufsiz = _IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_BUFSIZ); | ||||
tap->txa_wnd = (bufsiz == 0) ? | tap->txa_wnd = (bufsiz == 0) ? | ||||
IEEE80211_AGGR_BAWMAX : min(bufsiz, IEEE80211_AGGR_BAWMAX); | IEEE80211_AGGR_BAWMAX : min(bufsiz, IEEE80211_AGGR_BAWMAX); | ||||
addba_start_timeout(tap); | addba_start_timeout(tap); | ||||
return 1; | return 1; | ||||
} | } | ||||
/* | /* | ||||
* Called by drivers that wish to request an ADDBA session be | * Called by drivers that wish to request an ADDBA session be | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | ieee80211_addba_response(struct ieee80211_node *ni, | ||||
int status, int baparamset, int batimeout) | int status, int baparamset, int batimeout) | ||||
{ | { | ||||
struct ieee80211vap *vap = ni->ni_vap; | struct ieee80211vap *vap = ni->ni_vap; | ||||
int bufsiz, tid; | int bufsiz, tid; | ||||
/* XXX locking */ | /* XXX locking */ | ||||
addba_stop_timeout(tap); | addba_stop_timeout(tap); | ||||
if (status == IEEE80211_STATUS_SUCCESS) { | if (status == IEEE80211_STATUS_SUCCESS) { | ||||
bufsiz = MS(baparamset, IEEE80211_BAPS_BUFSIZ); | bufsiz = _IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_BUFSIZ); | ||||
/* XXX override our request? */ | /* XXX override our request? */ | ||||
tap->txa_wnd = (bufsiz == 0) ? | tap->txa_wnd = (bufsiz == 0) ? | ||||
IEEE80211_AGGR_BAWMAX : min(bufsiz, IEEE80211_AGGR_BAWMAX); | IEEE80211_AGGR_BAWMAX : min(bufsiz, IEEE80211_AGGR_BAWMAX); | ||||
tid = MS(baparamset, IEEE80211_BAPS_TID); | tid = _IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_TID); | ||||
tap->txa_flags |= IEEE80211_AGGR_RUNNING; | tap->txa_flags |= IEEE80211_AGGR_RUNNING; | ||||
tap->txa_attempts = 0; | tap->txa_attempts = 0; | ||||
/* TODO: this should be a vap flag */ | /* TODO: this should be a vap flag */ | ||||
if ((vap->iv_htcaps & IEEE80211_HTC_TX_AMSDU_AMPDU) && | if ((vap->iv_htcaps & IEEE80211_HTC_TX_AMSDU_AMPDU) && | ||||
(ni->ni_flags & IEEE80211_NODE_AMSDU_TX) && | (ni->ni_flags & IEEE80211_NODE_AMSDU_TX) && | ||||
(MS(baparamset, IEEE80211_BAPS_AMSDU))) | (_IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_AMSDU))) | ||||
tap->txa_flags |= IEEE80211_AGGR_AMSDU; | tap->txa_flags |= IEEE80211_AGGR_AMSDU; | ||||
else | else | ||||
tap->txa_flags &= ~IEEE80211_AGGR_AMSDU; | tap->txa_flags &= ~IEEE80211_AGGR_AMSDU; | ||||
} else { | } else { | ||||
/* mark tid so we don't try again */ | /* mark tid so we don't try again */ | ||||
tap->txa_flags |= IEEE80211_AGGR_NAK; | tap->txa_flags |= IEEE80211_AGGR_NAK; | ||||
} | } | ||||
return 1; | return 1; | ||||
Show All 34 Lines | ht_recv_action_ba_addba_request(struct ieee80211_node *ni, | ||||
uint16_t args[5]; | uint16_t args[5]; | ||||
int tid; | int tid; | ||||
dialogtoken = frm[2]; | dialogtoken = frm[2]; | ||||
baparamset = le16dec(frm+3); | baparamset = le16dec(frm+3); | ||||
batimeout = le16dec(frm+5); | batimeout = le16dec(frm+5); | ||||
baseqctl = le16dec(frm+7); | baseqctl = le16dec(frm+7); | ||||
tid = MS(baparamset, IEEE80211_BAPS_TID); | tid = _IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_TID); | ||||
IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, | IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, | ||||
"recv ADDBA request: dialogtoken %u baparamset 0x%x " | "recv ADDBA request: dialogtoken %u baparamset 0x%x " | ||||
"(tid %d bufsiz %d) batimeout %d baseqctl %d:%d amsdu %d", | "(tid %d bufsiz %d) batimeout %d baseqctl %d:%d amsdu %d", | ||||
dialogtoken, baparamset, | dialogtoken, baparamset, | ||||
tid, MS(baparamset, IEEE80211_BAPS_BUFSIZ), | tid, _IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_BUFSIZ), | ||||
batimeout, | batimeout, | ||||
MS(baseqctl, IEEE80211_BASEQ_START), | _IEEE80211_MASKSHIFT(baseqctl, IEEE80211_BASEQ_START), | ||||
MS(baseqctl, IEEE80211_BASEQ_FRAG), | _IEEE80211_MASKSHIFT(baseqctl, IEEE80211_BASEQ_FRAG), | ||||
MS(baparamset, IEEE80211_BAPS_AMSDU)); | _IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_AMSDU)); | ||||
rap = &ni->ni_rx_ampdu[tid]; | rap = &ni->ni_rx_ampdu[tid]; | ||||
/* Send ADDBA response */ | /* Send ADDBA response */ | ||||
args[0] = dialogtoken; | args[0] = dialogtoken; | ||||
/* | /* | ||||
* NB: We ack only if the sta associated with HT and | * NB: We ack only if the sta associated with HT and | ||||
* the ap is configured to do AMPDU rx (the latter | * the ap is configured to do AMPDU rx (the latter | ||||
Show All 12 Lines | IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, | ||||
ni->ni_flags & IEEE80211_NODE_AMPDU_RX ? | ni->ni_flags & IEEE80211_NODE_AMPDU_RX ? | ||||
"administratively disabled" : | "administratively disabled" : | ||||
"not negotiated for station"); | "not negotiated for station"); | ||||
vap->iv_stats.is_addba_reject++; | vap->iv_stats.is_addba_reject++; | ||||
args[1] = IEEE80211_STATUS_UNSPECIFIED; | args[1] = IEEE80211_STATUS_UNSPECIFIED; | ||||
} | } | ||||
/* XXX honor rap flags? */ | /* XXX honor rap flags? */ | ||||
args[2] = IEEE80211_BAPS_POLICY_IMMEDIATE | args[2] = IEEE80211_BAPS_POLICY_IMMEDIATE | ||||
| SM(tid, IEEE80211_BAPS_TID) | | _IEEE80211_SHIFTMASK(tid, IEEE80211_BAPS_TID) | ||||
| SM(rap->rxa_wnd, IEEE80211_BAPS_BUFSIZ) | | _IEEE80211_SHIFTMASK(rap->rxa_wnd, IEEE80211_BAPS_BUFSIZ) | ||||
; | ; | ||||
/* | /* | ||||
* TODO: we're out of iv_flags_ht fields; once | * TODO: we're out of iv_flags_ht fields; once | ||||
* this is extended we should make this configurable. | * this is extended we should make this configurable. | ||||
*/ | */ | ||||
if ((baparamset & IEEE80211_BAPS_AMSDU) && | if ((baparamset & IEEE80211_BAPS_AMSDU) && | ||||
(ni->ni_flags & IEEE80211_NODE_AMSDU_RX) && | (ni->ni_flags & IEEE80211_NODE_AMSDU_RX) && | ||||
Show All 18 Lines | ht_recv_action_ba_addba_response(struct ieee80211_node *ni, | ||||
uint8_t dialogtoken, policy; | uint8_t dialogtoken, policy; | ||||
uint16_t baparamset, batimeout, code; | uint16_t baparamset, batimeout, code; | ||||
int tid, bufsiz; | int tid, bufsiz; | ||||
int amsdu; | int amsdu; | ||||
dialogtoken = frm[2]; | dialogtoken = frm[2]; | ||||
code = le16dec(frm+3); | code = le16dec(frm+3); | ||||
baparamset = le16dec(frm+5); | baparamset = le16dec(frm+5); | ||||
tid = MS(baparamset, IEEE80211_BAPS_TID); | tid = _IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_TID); | ||||
bufsiz = MS(baparamset, IEEE80211_BAPS_BUFSIZ); | bufsiz = _IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_BUFSIZ); | ||||
policy = MS(baparamset, IEEE80211_BAPS_POLICY); | policy = _IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_POLICY); | ||||
amsdu = !! MS(baparamset, IEEE80211_BAPS_AMSDU); | amsdu = !! _IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_AMSDU); | ||||
batimeout = le16dec(frm+7); | batimeout = le16dec(frm+7); | ||||
tap = &ni->ni_tx_ampdu[tid]; | tap = &ni->ni_tx_ampdu[tid]; | ||||
if ((tap->txa_flags & IEEE80211_AGGR_XCHGPEND) == 0) { | if ((tap->txa_flags & IEEE80211_AGGR_XCHGPEND) == 0) { | ||||
IEEE80211_DISCARD_MAC(vap, | IEEE80211_DISCARD_MAC(vap, | ||||
IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, | IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, | ||||
ni->ni_macaddr, "ADDBA response", | ni->ni_macaddr, "ADDBA response", | ||||
"no pending ADDBA, tid %d dialogtoken %u " | "no pending ADDBA, tid %d dialogtoken %u " | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | ht_recv_action_ba_delba(struct ieee80211_node *ni, | ||||
struct ieee80211_rx_ampdu *rap; | struct ieee80211_rx_ampdu *rap; | ||||
struct ieee80211_tx_ampdu *tap; | struct ieee80211_tx_ampdu *tap; | ||||
uint16_t baparamset, code; | uint16_t baparamset, code; | ||||
int tid; | int tid; | ||||
baparamset = le16dec(frm+2); | baparamset = le16dec(frm+2); | ||||
code = le16dec(frm+4); | code = le16dec(frm+4); | ||||
tid = MS(baparamset, IEEE80211_DELBAPS_TID); | tid = _IEEE80211_MASKSHIFT(baparamset, IEEE80211_DELBAPS_TID); | ||||
IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, | IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, | ||||
"recv DELBA: baparamset 0x%x (tid %d initiator %d) " | "recv DELBA: baparamset 0x%x (tid %d initiator %d) " | ||||
"code %d", baparamset, tid, | "code %d", baparamset, tid, | ||||
MS(baparamset, IEEE80211_DELBAPS_INIT), code); | _IEEE80211_MASKSHIFT(baparamset, IEEE80211_DELBAPS_INIT), code); | ||||
if ((baparamset & IEEE80211_DELBAPS_INIT) == 0) { | if ((baparamset & IEEE80211_DELBAPS_INIT) == 0) { | ||||
tap = &ni->ni_tx_ampdu[tid]; | tap = &ni->ni_tx_ampdu[tid]; | ||||
ic->ic_addba_stop(ni, tap); | ic->ic_addba_stop(ni, tap); | ||||
} else { | } else { | ||||
rap = &ni->ni_rx_ampdu[tid]; | rap = &ni->ni_rx_ampdu[tid]; | ||||
ic->ic_ampdu_rx_stop(ni, rap); | ic->ic_ampdu_rx_stop(ni, rap); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 112 Lines • ▼ Show 20 Lines | ieee80211_ampdu_request(struct ieee80211_node *ni, | ||||
/* | /* | ||||
* XXX TODO: This is racy with any other parallel TX going on. :( | * XXX TODO: This is racy with any other parallel TX going on. :( | ||||
*/ | */ | ||||
tap->txa_start = ni->ni_txseqs[tid]; | tap->txa_start = ni->ni_txseqs[tid]; | ||||
args[0] = dialogtoken; | args[0] = dialogtoken; | ||||
args[1] = 0; /* NB: status code not used */ | args[1] = 0; /* NB: status code not used */ | ||||
args[2] = IEEE80211_BAPS_POLICY_IMMEDIATE | args[2] = IEEE80211_BAPS_POLICY_IMMEDIATE | ||||
| SM(tid, IEEE80211_BAPS_TID) | | _IEEE80211_SHIFTMASK(tid, IEEE80211_BAPS_TID) | ||||
| SM(IEEE80211_AGGR_BAWMAX, IEEE80211_BAPS_BUFSIZ) | | _IEEE80211_SHIFTMASK(IEEE80211_AGGR_BAWMAX, IEEE80211_BAPS_BUFSIZ) | ||||
; | ; | ||||
/* XXX TODO: this should be a flag, not iv_htcaps */ | /* XXX TODO: this should be a flag, not iv_htcaps */ | ||||
if ((ni->ni_flags & IEEE80211_NODE_AMSDU_TX) && | if ((ni->ni_flags & IEEE80211_NODE_AMSDU_TX) && | ||||
(ni->ni_vap->iv_htcaps & IEEE80211_HTC_TX_AMSDU_AMPDU)) | (ni->ni_vap->iv_htcaps & IEEE80211_HTC_TX_AMSDU_AMPDU)) | ||||
args[2] |= IEEE80211_BAPS_AMSDU; | args[2] |= IEEE80211_BAPS_AMSDU; | ||||
args[3] = 0; /* batimeout */ | args[3] = 0; /* batimeout */ | ||||
/* NB: do first so there's no race against reply */ | /* NB: do first so there's no race against reply */ | ||||
if (!ic->ic_addba_request(ni, tap, dialogtoken, args[2], args[3])) { | if (!ic->ic_addba_request(ni, tap, dialogtoken, args[2], args[3])) { | ||||
/* unable to setup state, don't make request */ | /* unable to setup state, don't make request */ | ||||
IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N, | IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N, | ||||
ni, "%s: could not setup BA stream for TID %d AC %d", | ni, "%s: could not setup BA stream for TID %d AC %d", | ||||
__func__, tap->txa_tid, TID_TO_WME_AC(tap->txa_tid)); | __func__, tap->txa_tid, TID_TO_WME_AC(tap->txa_tid)); | ||||
/* defer next try so we don't slam the driver with requests */ | /* defer next try so we don't slam the driver with requests */ | ||||
tap->txa_attempts = ieee80211_addba_maxtries; | tap->txa_attempts = ieee80211_addba_maxtries; | ||||
/* NB: check in case driver wants to override */ | /* NB: check in case driver wants to override */ | ||||
if (tap->txa_nextrequest <= ticks) | if (tap->txa_nextrequest <= ticks) | ||||
tap->txa_nextrequest = ticks + ieee80211_addba_backoff; | tap->txa_nextrequest = ticks + ieee80211_addba_backoff; | ||||
return 0; | return 0; | ||||
} | } | ||||
tokens = dialogtoken; /* allocate token */ | tokens = dialogtoken; /* allocate token */ | ||||
/* NB: after calling ic_addba_request so driver can set txa_start */ | /* NB: after calling ic_addba_request so driver can set txa_start */ | ||||
args[4] = SM(tap->txa_start, IEEE80211_BASEQ_START) | args[4] = _IEEE80211_SHIFTMASK(tap->txa_start, IEEE80211_BASEQ_START) | ||||
| SM(0, IEEE80211_BASEQ_FRAG) | | _IEEE80211_SHIFTMASK(0, IEEE80211_BASEQ_FRAG) | ||||
; | ; | ||||
return ic->ic_send_action(ni, IEEE80211_ACTION_CAT_BA, | return ic->ic_send_action(ni, IEEE80211_ACTION_CAT_BA, | ||||
IEEE80211_ACTION_BA_ADDBA_REQUEST, args); | IEEE80211_ACTION_BA_ADDBA_REQUEST, args); | ||||
} | } | ||||
/* | /* | ||||
* Terminate an AMPDU tx stream. State is reclaimed | * Terminate an AMPDU tx stream. State is reclaimed | ||||
* and the peer notified with a DelBA Action frame. | * and the peer notified with a DelBA Action frame. | ||||
▲ Show 20 Lines • Show All 202 Lines • ▼ Show 20 Lines | #define senderr(_x, _v) do { vap->iv_stats._v++; ret = _x; goto bad; } while (0) | ||||
bar->i_fc[1] = 0; | bar->i_fc[1] = 0; | ||||
IEEE80211_ADDR_COPY(bar->i_ra, ni->ni_macaddr); | IEEE80211_ADDR_COPY(bar->i_ra, ni->ni_macaddr); | ||||
IEEE80211_ADDR_COPY(bar->i_ta, vap->iv_myaddr); | IEEE80211_ADDR_COPY(bar->i_ta, vap->iv_myaddr); | ||||
tid = tap->txa_tid; | tid = tap->txa_tid; | ||||
barctl = (tap->txa_flags & IEEE80211_AGGR_IMMEDIATE ? | barctl = (tap->txa_flags & IEEE80211_AGGR_IMMEDIATE ? | ||||
0 : IEEE80211_BAR_NOACK) | 0 : IEEE80211_BAR_NOACK) | ||||
| IEEE80211_BAR_COMP | | IEEE80211_BAR_COMP | ||||
| SM(tid, IEEE80211_BAR_TID) | | _IEEE80211_SHIFTMASK(tid, IEEE80211_BAR_TID) | ||||
; | ; | ||||
barseqctl = SM(seq, IEEE80211_BAR_SEQ_START); | barseqctl = _IEEE80211_SHIFTMASK(seq, IEEE80211_BAR_SEQ_START); | ||||
/* NB: known to have proper alignment */ | /* NB: known to have proper alignment */ | ||||
bar->i_ctl = htole16(barctl); | bar->i_ctl = htole16(barctl); | ||||
bar->i_seq = htole16(barseqctl); | bar->i_seq = htole16(barseqctl); | ||||
m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame_bar); | m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame_bar); | ||||
M_WME_SETAC(m, WME_AC_VO); | M_WME_SETAC(m, WME_AC_VO); | ||||
IEEE80211_NODE_STAT(ni, tx_mgmt); /* XXX tx_ctl? */ | IEEE80211_NODE_STAT(ni, tx_mgmt); /* XXX tx_ctl? */ | ||||
▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | ht_send_action_ba_addba(struct ieee80211_node *ni, | ||||
struct mbuf *m; | struct mbuf *m; | ||||
uint8_t *frm; | uint8_t *frm; | ||||
IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, | IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, | ||||
"send ADDBA %s: dialogtoken %d status %d " | "send ADDBA %s: dialogtoken %d status %d " | ||||
"baparamset 0x%x (tid %d amsdu %d) batimeout 0x%x baseqctl 0x%x", | "baparamset 0x%x (tid %d amsdu %d) batimeout 0x%x baseqctl 0x%x", | ||||
(action == IEEE80211_ACTION_BA_ADDBA_REQUEST) ? | (action == IEEE80211_ACTION_BA_ADDBA_REQUEST) ? | ||||
"request" : "response", | "request" : "response", | ||||
args[0], args[1], args[2], MS(args[2], IEEE80211_BAPS_TID), | args[0], args[1], args[2], _IEEE80211_MASKSHIFT(args[2], IEEE80211_BAPS_TID), | ||||
MS(args[2], IEEE80211_BAPS_AMSDU), args[3], args[4]); | _IEEE80211_MASKSHIFT(args[2], IEEE80211_BAPS_AMSDU), args[3], args[4]); | ||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, | IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, | ||||
"ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__, | "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__, | ||||
ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1); | ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1); | ||||
ieee80211_ref_node(ni); | ieee80211_ref_node(ni); | ||||
m = ieee80211_getmgtframe(&frm, | m = ieee80211_getmgtframe(&frm, | ||||
ic->ic_headroom + sizeof(struct ieee80211_frame), | ic->ic_headroom + sizeof(struct ieee80211_frame), | ||||
Show All 26 Lines | |||||
{ | { | ||||
struct ieee80211vap *vap = ni->ni_vap; | struct ieee80211vap *vap = ni->ni_vap; | ||||
struct ieee80211com *ic = ni->ni_ic; | struct ieee80211com *ic = ni->ni_ic; | ||||
uint16_t *args = arg0; | uint16_t *args = arg0; | ||||
struct mbuf *m; | struct mbuf *m; | ||||
uint16_t baparamset; | uint16_t baparamset; | ||||
uint8_t *frm; | uint8_t *frm; | ||||
baparamset = SM(args[0], IEEE80211_DELBAPS_TID) | baparamset = _IEEE80211_SHIFTMASK(args[0], IEEE80211_DELBAPS_TID) | ||||
| args[1] | | args[1] | ||||
; | ; | ||||
IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, | IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, | ||||
"send DELBA action: tid %d, initiator %d reason %d (%s)", | "send DELBA action: tid %d, initiator %d reason %d (%s)", | ||||
args[0], args[1], args[2], ieee80211_reason_to_string(args[2])); | args[0], args[1], args[2], ieee80211_reason_to_string(args[2])); | ||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, | IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, | ||||
"ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__, | "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__, | ||||
▲ Show 20 Lines • Show All 135 Lines • ▼ Show 20 Lines | #define ADDSHORT(frm, v) do { \ | ||||
if (vap->iv_opmode == IEEE80211_M_STA) { | if (vap->iv_opmode == IEEE80211_M_STA) { | ||||
/* override 20/40 use based on config */ | /* override 20/40 use based on config */ | ||||
if (vap->iv_flags_ht & IEEE80211_FHT_USEHT40) | if (vap->iv_flags_ht & IEEE80211_FHT_USEHT40) | ||||
caps |= IEEE80211_HTCAP_CHWIDTH40; | caps |= IEEE80211_HTCAP_CHWIDTH40; | ||||
else | else | ||||
caps &= ~IEEE80211_HTCAP_CHWIDTH40; | caps &= ~IEEE80211_HTCAP_CHWIDTH40; | ||||
/* Start by using the advertised settings */ | /* Start by using the advertised settings */ | ||||
rxmax = MS(ni->ni_htparam, IEEE80211_HTCAP_MAXRXAMPDU); | rxmax = _IEEE80211_MASKSHIFT(ni->ni_htparam, IEEE80211_HTCAP_MAXRXAMPDU); | ||||
density = MS(ni->ni_htparam, IEEE80211_HTCAP_MPDUDENSITY); | density = _IEEE80211_MASKSHIFT(ni->ni_htparam, IEEE80211_HTCAP_MPDUDENSITY); | ||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_11N, | IEEE80211_DPRINTF(vap, IEEE80211_MSG_11N, | ||||
"%s: advertised rxmax=%d, density=%d, vap rxmax=%d, density=%d\n", | "%s: advertised rxmax=%d, density=%d, vap rxmax=%d, density=%d\n", | ||||
__func__, | __func__, | ||||
rxmax, | rxmax, | ||||
density, | density, | ||||
vap->iv_ampdu_rxmax, | vap->iv_ampdu_rxmax, | ||||
vap->iv_ampdu_density); | vap->iv_ampdu_density); | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | #define ADDSHORT(frm, v) do { \ | ||||
/* adjust LDPC based on receive capabilites */ | /* adjust LDPC based on receive capabilites */ | ||||
if ((vap->iv_flags_ht & IEEE80211_FHT_LDPC_RX) == 0) | if ((vap->iv_flags_ht & IEEE80211_FHT_LDPC_RX) == 0) | ||||
caps &= ~IEEE80211_HTCAP_LDPC; | caps &= ~IEEE80211_HTCAP_LDPC; | ||||
ADDSHORT(frm, caps); | ADDSHORT(frm, caps); | ||||
/* HT parameters */ | /* HT parameters */ | ||||
*frm = SM(rxmax, IEEE80211_HTCAP_MAXRXAMPDU) | *frm = _IEEE80211_SHIFTMASK(rxmax, IEEE80211_HTCAP_MAXRXAMPDU) | ||||
| SM(density, IEEE80211_HTCAP_MPDUDENSITY) | | _IEEE80211_SHIFTMASK(density, IEEE80211_HTCAP_MPDUDENSITY) | ||||
; | ; | ||||
frm++; | frm++; | ||||
/* pre-zero remainder of ie */ | /* pre-zero remainder of ie */ | ||||
memset(frm, 0, sizeof(struct ieee80211_ie_htcap) - | memset(frm, 0, sizeof(struct ieee80211_ie_htcap) - | ||||
__offsetof(struct ieee80211_ie_htcap, hc_mcsset)); | __offsetof(struct ieee80211_ie_htcap, hc_mcsset)); | ||||
/* supported MCS set */ | /* supported MCS set */ | ||||
▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | #define ADDSHORT(frm, v) do { \ | ||||
if ((vap->iv_flags_ht & IEEE80211_FHT_SHORTGI20) == 0) | if ((vap->iv_flags_ht & IEEE80211_FHT_SHORTGI20) == 0) | ||||
caps &= ~IEEE80211_HTCAP_SHORTGI20; | caps &= ~IEEE80211_HTCAP_SHORTGI20; | ||||
if ((vap->iv_flags_ht & IEEE80211_FHT_SHORTGI40) == 0 || | if ((vap->iv_flags_ht & IEEE80211_FHT_SHORTGI40) == 0 || | ||||
(caps & IEEE80211_HTCAP_CHWIDTH40) == 0) | (caps & IEEE80211_HTCAP_CHWIDTH40) == 0) | ||||
caps &= ~IEEE80211_HTCAP_SHORTGI40; | caps &= ~IEEE80211_HTCAP_SHORTGI40; | ||||
ADDSHORT(frm, caps); | ADDSHORT(frm, caps); | ||||
/* HT parameters */ | /* HT parameters */ | ||||
*frm = SM(rxmax, IEEE80211_HTCAP_MAXRXAMPDU) | *frm = _IEEE80211_SHIFTMASK(rxmax, IEEE80211_HTCAP_MAXRXAMPDU) | ||||
| SM(density, IEEE80211_HTCAP_MPDUDENSITY) | | _IEEE80211_SHIFTMASK(density, IEEE80211_HTCAP_MPDUDENSITY) | ||||
; | ; | ||||
frm++; | frm++; | ||||
/* pre-zero remainder of ie */ | /* pre-zero remainder of ie */ | ||||
memset(frm, 0, sizeof(struct ieee80211_ie_htcap) - | memset(frm, 0, sizeof(struct ieee80211_ie_htcap) - | ||||
__offsetof(struct ieee80211_ie_htcap, hc_mcsset)); | __offsetof(struct ieee80211_ie_htcap, hc_mcsset)); | ||||
/* supported MCS set */ | /* supported MCS set */ | ||||
▲ Show 20 Lines • Show All 190 Lines • Show Last 20 Lines |