summaryrefslogtreecommitdiffstats
path: root/sys/net80211/ieee80211_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net80211/ieee80211_input.c')
-rw-r--r--sys/net80211/ieee80211_input.c164
1 files changed, 90 insertions, 74 deletions
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c
index 13afce16102..5140ccdf636 100644
--- a/sys/net80211/ieee80211_input.c
+++ b/sys/net80211/ieee80211_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_input.c,v 1.107 2009/01/26 19:09:41 damien Exp $ */
+/* $OpenBSD: ieee80211_input.c,v 1.108 2009/01/28 18:55:18 damien Exp $ */
/*-
* Copyright (c) 2001 Atsushi Onoe
@@ -364,7 +364,8 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni,
hasqos && (qos & IEEE80211_QOS_ACK_POLICY_MASK) ==
IEEE80211_QOS_ACK_POLICY_BA) {
/* check if we have a BA agreement for this RA/TID */
- if (ni->ni_ba[tid].ba_state != IEEE80211_BA_AGREED) {
+ if (ni->ni_rx_ba[tid].ba_state !=
+ IEEE80211_BA_AGREED) {
DPRINTF(("no BA agreement for %s, TID %d\n",
ether_sprintf(ni->ni_macaddr), tid));
/* send a DELBA with reason code UNKNOWN-BA */
@@ -558,7 +559,7 @@ void
ieee80211_input_ba(struct ifnet *ifp, struct mbuf *m,
struct ieee80211_node *ni, int tid, struct ieee80211_rxinfo *rxi)
{
- struct ieee80211_ba *ba = &ni->ni_ba[tid];
+ struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];
struct ieee80211_frame *wh;
int idx, count;
u_int16_t sn;
@@ -622,14 +623,14 @@ ieee80211_input_ba(struct ifnet *ifp, struct mbuf *m,
/*
* Change the value of WinStartB (move window forward) upon reception of a
- * Block Ack Request frame or an ADDBA Request (PBAC).
+ * BlockAckReq frame or an ADDBA Request (PBAC).
*/
void
ieee80211_ba_move_window(struct ieee80211com *ic, struct ieee80211_node *ni,
u_int8_t tid, u_int16_t ssn)
{
struct ifnet *ifp = &ic->ic_if;
- struct ieee80211_ba *ba = &ni->ni_ba[tid];
+ struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];
int count;
/* assert(WinStartB <= SSN) */
@@ -747,7 +748,7 @@ ieee80211_deliver_data(struct ieee80211com *ic, struct mbuf *m,
* always possible because 802.11 header length may vary (non-QoS+LLC
* is 32 bytes while QoS+LLC is 34 bytes). Some devices are smart and
* add 2 padding bytes after the 802.11 header in the QoS case so this
- * function is there for brain-dead devices only.
+ * function is there for stupid drivers/devices only.
*/
struct mbuf *
ieee80211_align_mbuf(struct mbuf *m)
@@ -1210,7 +1211,7 @@ ieee80211_save_ie(const u_int8_t *frm, u_int8_t **ie)
* [tlv] HT Operation (802.11n)
*/
void
-ieee80211_recv_probe_resp(struct ieee80211com *ic, struct mbuf *m0,
+ieee80211_recv_probe_resp(struct ieee80211com *ic, struct mbuf *m,
struct ieee80211_node *ni, struct ieee80211_rxinfo *rxi, int isprobe)
{
const struct ieee80211_frame *wh;
@@ -1244,13 +1245,13 @@ ieee80211_recv_probe_resp(struct ieee80211com *ic, struct mbuf *m0,
}
#endif
/* make sure all mandatory fixed fields are present */
- if (m0->m_len < sizeof(*wh) + 12) {
+ if (m->m_len < sizeof(*wh) + 12) {
DPRINTF(("frame too short\n"));
return;
}
- wh = mtod(m0, struct ieee80211_frame *);
+ wh = mtod(m, struct ieee80211_frame *);
frm = (const u_int8_t *)&wh[1];
- efrm = mtod(m0, u_int8_t *) + m0->m_len;
+ efrm = mtod(m, u_int8_t *) + m->m_len;
tstamp = frm; frm += 8;
bintval = LE_READ_2(frm); frm += 2;
@@ -1533,7 +1534,7 @@ ieee80211_recv_probe_resp(struct ieee80211com *ic, struct mbuf *m0,
* [tlv] HT Capabilities (802.11n)
*/
void
-ieee80211_recv_probe_req(struct ieee80211com *ic, struct mbuf *m0,
+ieee80211_recv_probe_req(struct ieee80211com *ic, struct mbuf *m,
struct ieee80211_node *ni, struct ieee80211_rxinfo *rxi)
{
const struct ieee80211_frame *wh;
@@ -1545,9 +1546,9 @@ ieee80211_recv_probe_req(struct ieee80211com *ic, struct mbuf *m0,
ic->ic_state != IEEE80211_S_RUN)
return;
- wh = mtod(m0, struct ieee80211_frame *);
+ wh = mtod(m, struct ieee80211_frame *);
frm = (const u_int8_t *)&wh[1];
- efrm = mtod(m0, u_int8_t *) + m0->m_len;
+ efrm = mtod(m, u_int8_t *) + m->m_len;
ssid = rates = xrates = htcaps = NULL;
while (frm + 2 <= efrm) {
@@ -1625,7 +1626,7 @@ ieee80211_recv_probe_req(struct ieee80211com *ic, struct mbuf *m0,
* [2] Status code
*/
void
-ieee80211_recv_auth(struct ieee80211com *ic, struct mbuf *m0,
+ieee80211_recv_auth(struct ieee80211com *ic, struct mbuf *m,
struct ieee80211_node *ni, struct ieee80211_rxinfo *rxi)
{
const struct ieee80211_frame *wh;
@@ -1633,11 +1634,11 @@ ieee80211_recv_auth(struct ieee80211com *ic, struct mbuf *m0,
u_int16_t algo, seq, status;
/* make sure all mandatory fixed fields are present */
- if (m0->m_len < sizeof(*wh) + 6) {
+ if (m->m_len < sizeof(*wh) + 6) {
DPRINTF(("frame too short\n"));
return;
}
- wh = mtod(m0, struct ieee80211_frame *);
+ wh = mtod(m, struct ieee80211_frame *);
frm = (const u_int8_t *)&wh[1];
algo = LE_READ_2(frm); frm += 2;
@@ -1678,7 +1679,7 @@ ieee80211_recv_auth(struct ieee80211com *ic, struct mbuf *m0,
* [tlv] HT Capabilities (802.11n)
*/
void
-ieee80211_recv_assoc_req(struct ieee80211com *ic, struct mbuf *m0,
+ieee80211_recv_assoc_req(struct ieee80211com *ic, struct mbuf *m,
struct ieee80211_node *ni, struct ieee80211_rxinfo *rxi, int reassoc)
{
const struct ieee80211_frame *wh;
@@ -1694,13 +1695,13 @@ ieee80211_recv_assoc_req(struct ieee80211com *ic, struct mbuf *m0,
return;
/* make sure all mandatory fixed fields are present */
- if (m0->m_len < sizeof(*wh) + (reassoc ? 10 : 4)) {
+ if (m->m_len < sizeof(*wh) + (reassoc ? 10 : 4)) {
DPRINTF(("frame too short\n"));
return;
}
- wh = mtod(m0, struct ieee80211_frame *);
+ wh = mtod(m, struct ieee80211_frame *);
frm = (const u_int8_t *)&wh[1];
- efrm = mtod(m0, u_int8_t *) + m0->m_len;
+ efrm = mtod(m, u_int8_t *) + m->m_len;
if (!IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_bss->ni_bssid)) {
DPRINTF(("ignore other bss from %s\n",
@@ -1972,7 +1973,7 @@ ieee80211_recv_assoc_req(struct ieee80211com *ic, struct mbuf *m0,
* [tlv] HT Operation (802.11n)
*/
void
-ieee80211_recv_assoc_resp(struct ieee80211com *ic, struct mbuf *m0,
+ieee80211_recv_assoc_resp(struct ieee80211com *ic, struct mbuf *m,
struct ieee80211_node *ni, int reassoc)
{
struct ifnet *ifp = &ic->ic_if;
@@ -1989,13 +1990,13 @@ ieee80211_recv_assoc_resp(struct ieee80211com *ic, struct mbuf *m0,
}
/* make sure all mandatory fixed fields are present */
- if (m0->m_len < sizeof(*wh) + 6) {
+ if (m->m_len < sizeof(*wh) + 6) {
DPRINTF(("frame too short\n"));
return;
}
- wh = mtod(m0, struct ieee80211_frame *);
+ wh = mtod(m, struct ieee80211_frame *);
frm = (const u_int8_t *)&wh[1];
- efrm = mtod(m0, u_int8_t *) + m0->m_len;
+ efrm = mtod(m, u_int8_t *) + m->m_len;
capinfo = LE_READ_2(frm); frm += 2;
status = LE_READ_2(frm); frm += 2;
@@ -2115,7 +2116,7 @@ ieee80211_recv_assoc_resp(struct ieee80211com *ic, struct mbuf *m0,
* [2] Reason code
*/
void
-ieee80211_recv_deauth(struct ieee80211com *ic, struct mbuf *m0,
+ieee80211_recv_deauth(struct ieee80211com *ic, struct mbuf *m,
struct ieee80211_node *ni)
{
const struct ieee80211_frame *wh;
@@ -2123,11 +2124,11 @@ ieee80211_recv_deauth(struct ieee80211com *ic, struct mbuf *m0,
u_int16_t reason;
/* make sure all mandatory fixed fields are present */
- if (m0->m_len < sizeof(*wh) + 2) {
+ if (m->m_len < sizeof(*wh) + 2) {
DPRINTF(("frame too short\n"));
return;
}
- wh = mtod(m0, struct ieee80211_frame *);
+ wh = mtod(m, struct ieee80211_frame *);
frm = (const u_int8_t *)&wh[1];
reason = LE_READ_2(frm);
@@ -2161,7 +2162,7 @@ ieee80211_recv_deauth(struct ieee80211com *ic, struct mbuf *m0,
* [2] Reason code
*/
void
-ieee80211_recv_disassoc(struct ieee80211com *ic, struct mbuf *m0,
+ieee80211_recv_disassoc(struct ieee80211com *ic, struct mbuf *m,
struct ieee80211_node *ni)
{
const struct ieee80211_frame *wh;
@@ -2169,11 +2170,11 @@ ieee80211_recv_disassoc(struct ieee80211com *ic, struct mbuf *m0,
u_int16_t reason;
/* make sure all mandatory fixed fields are present */
- if (m0->m_len < sizeof(*wh) + 2) {
+ if (m->m_len < sizeof(*wh) + 2) {
DPRINTF(("frame too short\n"));
return;
}
- wh = mtod(m0, struct ieee80211_frame *);
+ wh = mtod(m, struct ieee80211_frame *);
frm = (const u_int8_t *)&wh[1];
reason = LE_READ_2(frm);
@@ -2218,7 +2219,7 @@ ieee80211_recv_addba_req(struct ieee80211com *ic, struct mbuf *m,
{
const struct ieee80211_frame *wh;
const u_int8_t *frm;
- struct ieee80211_ba *ba;
+ struct ieee80211_rx_ba *ba;
u_int16_t params, ssn, bufsz, timeout, status;
u_int8_t token, tid;
@@ -2242,11 +2243,11 @@ ieee80211_recv_addba_req(struct ieee80211com *ic, struct mbuf *m,
timeout = LE_READ_2(&frm[5]);
ssn = LE_READ_2(&frm[7]) >> 4;
- ba = &ni->ni_ba[tid];
- /* check if we already have a BA agreement for this RA/TID */
+ ba = &ni->ni_rx_ba[tid];
+ /* check if we already have a Block Ack agreement for this RA/TID */
if (ba->ba_state == IEEE80211_BA_AGREED) {
/* XXX should we update the timeout value? */
- /* reset BA inactivity timer */
+ /* reset Block Ack inactivity timer */
timeout_add_usec(&ba->ba_to, ba->ba_timeout_val);
/* check if it's a Protected Block Ack agreement */
@@ -2254,7 +2255,7 @@ ieee80211_recv_addba_req(struct ieee80211com *ic, struct mbuf *m,
!(ni->ni_rsncaps & IEEE80211_RSNCAP_PBAC))
return; /* not a PBAC, ignore */
- /* PBAC: treat the ADDBA Request like a BAR */
+ /* PBAC: treat the ADDBA Request like a BlockAckReq */
if (SEQ_LT(ba->ba_winstart, ssn))
ieee80211_ba_move_window(ic, ni, tid, ssn);
return;
@@ -2283,13 +2284,12 @@ ieee80211_recv_addba_req(struct ieee80211com *ic, struct mbuf *m,
/* setup Block Ack agreement */
ba->ba_state = IEEE80211_BA_INIT;
- ba->ba_token = token; /* save Dialog Token for ADDBA Resp */
ba->ba_timeout_val = timeout * IEEE80211_DUR_TU;
if (ba->ba_timeout_val < IEEE80211_BA_MIN_TIMEOUT)
ba->ba_timeout_val = IEEE80211_BA_MIN_TIMEOUT;
else if (ba->ba_timeout_val > IEEE80211_BA_MAX_TIMEOUT)
ba->ba_timeout_val = IEEE80211_BA_MAX_TIMEOUT;
- timeout_set(&ba->ba_to, ieee80211_ba_timeout, ba);
+ timeout_set(&ba->ba_to, ieee80211_rx_ba_timeout, ba);
ba->ba_winsize = bufsz;
if (ba->ba_winsize == 0 || ba->ba_winsize > IEEE80211_BA_MAX_WINSZ)
ba->ba_winsize = IEEE80211_BA_MAX_WINSZ;
@@ -2305,8 +2305,8 @@ ieee80211_recv_addba_req(struct ieee80211com *ic, struct mbuf *m,
ba->ba_head = 0;
/* notify drivers of this new Block Ack agreement */
- if (ic->ic_htimmba_start != NULL &&
- ic->ic_htimmba_start(ic, ni, tid) != 0) {
+ if (ic->ic_ampdu_rx_start != NULL &&
+ ic->ic_ampdu_rx_start(ic, ni, tid) != 0) {
/* driver failed to setup, rollback */
free(ba->ba_buf, M_DEVBUF);
ba->ba_buf = NULL;
@@ -2320,7 +2320,7 @@ ieee80211_recv_addba_req(struct ieee80211com *ic, struct mbuf *m,
resp:
/* MLME-ADDBA.response */
IEEE80211_SEND_ACTION(ic, ni, IEEE80211_CATEG_BA,
- IEEE80211_ACTION_ADDBA_RESP, status << 16 | tid);
+ IEEE80211_ACTION_ADDBA_RESP, status << 16 | token << 8 | tid);
}
/*-
@@ -2338,7 +2338,7 @@ ieee80211_recv_addba_resp(struct ieee80211com *ic, struct mbuf *m,
{
const struct ieee80211_frame *wh;
const u_int8_t *frm;
- struct ieee80211_ba *ba;
+ struct ieee80211_tx_ba *ba;
u_int16_t status, params, bufsz, timeout;
u_int8_t token, tid;
@@ -2363,7 +2363,7 @@ ieee80211_recv_addba_resp(struct ieee80211com *ic, struct mbuf *m,
* Ignore if no ADDBA request has been sent for this RA/TID or
* if we already have a Block Ack agreement.
*/
- ba = &ni->ni_ba[tid];
+ ba = &ni->ni_tx_ba[tid];
if (ba->ba_state != IEEE80211_BA_REQUESTED) {
DPRINTF(("no matching ADDBA req found\n"));
return;
@@ -2385,11 +2385,12 @@ ieee80211_recv_addba_resp(struct ieee80211com *ic, struct mbuf *m,
ba->ba_state = IEEE80211_BA_AGREED;
/* notify drivers of this new Block Ack agreement */
- if (ic->ic_htimmba_start != NULL)
- (void)ic->ic_htimmba_start(ic, ni, tid);
+ if (ic->ic_ampdu_tx_start != NULL)
+ (void)ic->ic_ampdu_tx_start(ic, ni, tid);
/* start Block Ack inactivity timeout */
- timeout_add_usec(&ba->ba_to, ba->ba_timeout_val);
+ if (ba->ba_timeout_val != 0)
+ timeout_add_usec(&ba->ba_to, ba->ba_timeout_val);
}
/*-
@@ -2405,7 +2406,6 @@ ieee80211_recv_delba(struct ieee80211com *ic, struct mbuf *m,
{
const struct ieee80211_frame *wh;
const u_int8_t *frm;
- struct ieee80211_ba *ba;
u_int16_t params, reason;
u_int8_t tid;
int i;
@@ -2424,29 +2424,46 @@ ieee80211_recv_delba(struct ieee80211com *ic, struct mbuf *m,
DPRINTF(("received DELBA from %s, TID %d, reason %d\n",
ether_sprintf(ni->ni_macaddr), tid, reason));
- ba = &ni->ni_ba[tid];
- if (ba->ba_state != IEEE80211_BA_AGREED &&
- ba->ba_state != IEEE80211_BA_REQUESTED) {
- DPRINTF(("no matching BA agreement found\n"));
- return;
- }
- /* MLME-DELBA.indication */
+ if (params & IEEE80211_DELBA_INITIATOR) {
+ /* MLME-DELBA.indication(Originator) */
+ struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];
- /* notify drivers of the end of the Block Ack agreement */
- if (ic->ic_htimmba_stop != NULL)
- ic->ic_htimmba_stop(ic, ni, tid);
+ if (ba->ba_state != IEEE80211_BA_AGREED) {
+ DPRINTF(("no matching Block Ack agreement\n"));
+ return;
+ }
+ /* notify drivers of the end of the Block Ack agreement */
+ if (ic->ic_ampdu_rx_stop != NULL)
+ ic->ic_ampdu_rx_stop(ic, ni, tid);
- ba->ba_state = IEEE80211_BA_INIT;
- /* stop Block Ack inactivity timer */
- timeout_del(&ba->ba_to);
- if (ba->ba_buf != NULL) {
- /* free all MSDUs stored in reordering buffer */
- for (i = 0; i < IEEE80211_BA_MAX_WINSZ; i++)
- if (ba->ba_buf[i].m != NULL)
- m_freem(ba->ba_buf[i].m);
- /* free reordering buffer */
- free(ba->ba_buf, M_DEVBUF);
- ba->ba_buf = NULL;
+ ba->ba_state = IEEE80211_BA_INIT;
+ /* stop Block Ack inactivity timer */
+ timeout_del(&ba->ba_to);
+
+ if (ba->ba_buf != NULL) {
+ /* free all MSDUs stored in reordering buffer */
+ for (i = 0; i < IEEE80211_BA_MAX_WINSZ; i++)
+ if (ba->ba_buf[i].m != NULL)
+ m_freem(ba->ba_buf[i].m);
+ /* free reordering buffer */
+ free(ba->ba_buf, M_DEVBUF);
+ ba->ba_buf = NULL;
+ }
+ } else {
+ /* MLME-DELBA.indication(Recipient) */
+ struct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid];
+
+ if (ba->ba_state != IEEE80211_BA_AGREED) {
+ DPRINTF(("no matching Block Ack agreement\n"));
+ return;
+ }
+ /* notify drivers of the end of the Block Ack agreement */
+ if (ic->ic_ampdu_tx_stop != NULL)
+ ic->ic_ampdu_tx_stop(ic, ni, tid);
+
+ ba->ba_state = IEEE80211_BA_INIT;
+ /* stop Block Ack inactivity timer */
+ timeout_del(&ba->ba_to);
}
}
#endif /* !IEEE80211_NO_HT */
@@ -2684,7 +2701,7 @@ ieee80211_recv_pspoll(struct ieee80211com *ic, struct mbuf *m,
#ifndef IEEE80211_NO_HT
/*
- * Process an incoming Block Ack Request control frame (see 7.2.1.7).
+ * Process an incoming BlockAckReq control frame (see 7.2.1.7).
*/
void
ieee80211_recv_bar(struct ieee80211com *ic, struct mbuf *m,
@@ -2696,7 +2713,7 @@ ieee80211_recv_bar(struct ieee80211com *ic, struct mbuf *m,
u_int8_t tid, ntids;
if (!(ni->ni_flags & IEEE80211_NODE_HT)) {
- DPRINTF(("received BAR from non-HT STA %s\n",
+ DPRINTF(("received BlockAckReq from non-HT STA %s\n",
ether_sprintf(ni->ni_macaddr)));
return;
}
@@ -2707,7 +2724,7 @@ ieee80211_recv_bar(struct ieee80211com *ic, struct mbuf *m,
wh = mtod(m, struct ieee80211_frame_min *);
frm = (const u_int8_t *)&wh[1];
- /* read BAR Control field */
+ /* read BlockAckReq Control field */
ctl = LE_READ_2(&frm[0]);
tid = ctl >> 12;
@@ -2720,7 +2737,7 @@ ieee80211_recv_bar(struct ieee80211com *ic, struct mbuf *m,
DPRINTF(("MTBAR frame too short\n"));
return;
}
- frm += 2; /* skip BAR Control field */
+ frm += 2; /* skip BlockAckReq Control field */
while (ntids-- > 0) {
/* read MTBAR Information field */
tid = LE_READ_2(&frm[0]) >> 12;
@@ -2736,14 +2753,14 @@ ieee80211_recv_bar(struct ieee80211com *ic, struct mbuf *m,
}
/*
- * Process a Block Ack Request for a specific TID (see 9.10.7.6.3).
+ * Process a BlockAckReq for a specific TID (see 9.10.7.6.3).
* This is the common back-end for all BlockAckReq frame variants.
*/
void
ieee80211_bar_tid(struct ieee80211com *ic, struct ieee80211_node *ni,
u_int8_t tid, u_int16_t ssn)
{
- struct ieee80211_ba *ba = &ni->ni_ba[tid];
+ struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];
/* check if we have a Block Ack agreement for RA/TID */
if (ba->ba_state != IEEE80211_BA_AGREED) {
@@ -2770,4 +2787,3 @@ ieee80211_bar_tid(struct ieee80211com *ic, struct ieee80211_node *ni,
ieee80211_ba_move_window(ic, ni, tid, ssn);
}
#endif /* !IEEE80211_NO_HT */
-