summaryrefslogtreecommitdiffstats
path: root/sys/net80211
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2008-09-21 23:00:19 +0000
committersam <sam@FreeBSD.org>2008-09-21 23:00:19 +0000
commit7a8139bec34979455320162a624d9f5762a864d0 (patch)
tree24722386b7e72f294b811c4f1cbee461b32b26ae /sys/net80211
parent50dd888a5f6605eebf5956acf6ab3c87e4e8a81e (diff)
downloadFreeBSD-src-7a8139bec34979455320162a624d9f5762a864d0.zip
FreeBSD-src-7a8139bec34979455320162a624d9f5762a864d0.tar.gz
Cleanup AMPDU handling:
For receive: o explicitly tag rx frames w/ M_AMPDU instead of passing frames through the reorder processing according to the node having HT and the frame being QoS data o relax ieee80211_ampdu_reorder asserts to allow any frame to be passed in, unsuitable frames are returned to the caller for normal processing; this permits drivers that cannot inspect the PLCP to mark all data frames as potential ampdu candidates with only a small penalty o add M_AMPDU_MPDU to identify frames resubmitted from the reorder q For transmit: o tag aggregation candidates with M_AMPDU_MPDU o fix the QoS ack policy set in ampdu subframes; we only support immediate BA streams which should be marked for "normal ack" to get implicit block ack behaviour; interestingly certain vendor parts BA'd frames with the 11e BA ack policy set o do not assign a sequence # to aggregation candidates; this must be done when frames are submitted for transmit (NB: this can/will be handled better when aggregation is pulled up to net80211)
Diffstat (limited to 'sys/net80211')
-rw-r--r--sys/net80211/ieee80211_adhoc.c22
-rw-r--r--sys/net80211/ieee80211_freebsd.h10
-rw-r--r--sys/net80211/ieee80211_hostap.c22
-rw-r--r--sys/net80211/ieee80211_ht.c16
-rw-r--r--sys/net80211/ieee80211_output.c26
-rw-r--r--sys/net80211/ieee80211_sta.c22
-rw-r--r--sys/net80211/ieee80211_wds.c22
7 files changed, 78 insertions, 62 deletions
diff --git a/sys/net80211/ieee80211_adhoc.c b/sys/net80211/ieee80211_adhoc.c
index e0a5bdf..32de8cc 100644
--- a/sys/net80211/ieee80211_adhoc.c
+++ b/sys/net80211/ieee80211_adhoc.c
@@ -262,14 +262,14 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m,
uint8_t *bssid;
uint16_t rxseq;
- if (m->m_flags & M_AMPDU) {
+ if (m->m_flags & M_AMPDU_MPDU) {
/*
* Fastpath for A-MPDU reorder q resubmission. Frames
- * w/ M_AMPDU marked have already passed through here
- * but were received out of order and been held on the
- * reorder queue. When resubmitted they are marked
- * with the M_AMPDU flag and we can bypass most of the
- * normal processing.
+ * w/ M_AMPDU_MPDU marked have already passed through
+ * here but were received out of order and been held on
+ * the reorder queue. When resubmitted they are marked
+ * with the M_AMPDU_MPDU flag and we can bypass most of
+ * the normal processing.
*/
wh = mtod(m, struct ieee80211_frame *);
type = IEEE80211_FC0_TYPE_DATA;
@@ -406,16 +406,12 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m,
/* XXX no power-save support */
/*
- * Handle A-MPDU re-ordering. The station must be
- * associated and negotiated HT. The frame must be
- * a QoS frame (not QoS null data) and not previously
- * processed for A-MPDU re-ordering. If the frame is
- * to be processed directly then ieee80211_ampdu_reorder
+ * Handle A-MPDU re-ordering. If the frame is to be
+ * processed directly then ieee80211_ampdu_reorder
* will return 0; otherwise it has consumed the mbuf
* and we should do nothing more with it.
*/
- if ((ni->ni_flags & IEEE80211_NODE_HT) &&
- subtype == IEEE80211_FC0_SUBTYPE_QOS &&
+ if ((m->m_flags & M_AMPDU) &&
ieee80211_ampdu_reorder(ni, m) != 0) {
m = NULL;
goto out;
diff --git a/sys/net80211/ieee80211_freebsd.h b/sys/net80211/ieee80211_freebsd.h
index fcd1b3f..448bd78 100644
--- a/sys/net80211/ieee80211_freebsd.h
+++ b/sys/net80211/ieee80211_freebsd.h
@@ -246,13 +246,17 @@ struct mbuf *ieee80211_getmgtframe(uint8_t **frm, int headroom, int pktlen);
#define M_MORE_DATA M_PROTO5 /* more data frames to follow */
#define M_FF M_PROTO6 /* fast frame */
#define M_TXCB M_PROTO7 /* do tx complete callback */
+#define M_AMPDU_MPDU M_PROTO8 /* ok for A-MPDU aggregation */
#define M_80211_TX \
- (M_LINK0|M_WDS|M_EAPOL|M_PWR_SAV|M_MORE_DATA|M_FF|M_TXCB)
+ (M_LINK0|M_WDS|M_EAPOL|M_PWR_SAV|M_MORE_DATA|M_FF|M_TXCB|M_AMPDU_MPDU)
/* rx path usage */
-#define M_AMPDU M_PROTO1 /* A-MPDU processing done */
+#define M_AMPDU M_PROTO1 /* A-MPDU subframe */
#define M_WEP M_PROTO2 /* WEP done by hardware */
-#define M_80211_RX (M_AMPDU|M_WEP)
+#if 0
+#define M_AMPDU_MPDU M_PROTO8 /* A-MPDU re-order done */
+#endif
+#define M_80211_RX (M_AMPDU|M_WEP|M_AMPDU_MPDU)
/*
* Store WME access control bits in the vlan tag.
* This is safe since it's done after the packet is classified
diff --git a/sys/net80211/ieee80211_hostap.c b/sys/net80211/ieee80211_hostap.c
index 492ef13..c876dab 100644
--- a/sys/net80211/ieee80211_hostap.c
+++ b/sys/net80211/ieee80211_hostap.c
@@ -429,14 +429,14 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m,
uint8_t *bssid;
uint16_t rxseq;
- if (m->m_flags & M_AMPDU) {
+ if (m->m_flags & M_AMPDU_MPDU) {
/*
* Fastpath for A-MPDU reorder q resubmission. Frames
- * w/ M_AMPDU marked have already passed through here
- * but were received out of order and been held on the
- * reorder queue. When resubmitted they are marked
- * with the M_AMPDU flag and we can bypass most of the
- * normal processing.
+ * w/ M_AMPDU_MPDU marked have already passed through
+ * here but were received out of order and been held on
+ * the reorder queue. When resubmitted they are marked
+ * with the M_AMPDU_MPDU flag and we can bypass most of
+ * the normal processing.
*/
wh = mtod(m, struct ieee80211_frame *);
type = IEEE80211_FC0_TYPE_DATA;
@@ -616,16 +616,12 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m,
}
/*
- * Handle A-MPDU re-ordering. The station must be
- * associated and negotiated HT. The frame must be
- * a QoS frame (not QoS null data) and not previously
- * processed for A-MPDU re-ordering. If the frame is
- * to be processed directly then ieee80211_ampdu_reorder
+ * Handle A-MPDU re-ordering. If the frame is to be
+ * processed directly then ieee80211_ampdu_reorder
* will return 0; otherwise it has consumed the mbuf
* and we should do nothing more with it.
*/
- if ((ni->ni_flags & IEEE80211_NODE_HT) &&
- subtype == IEEE80211_FC0_SUBTYPE_QOS &&
+ if ((m->m_flags & M_AMPDU) &&
ieee80211_ampdu_reorder(ni, m) != 0) {
m = NULL;
goto out;
diff --git a/sys/net80211/ieee80211_ht.c b/sys/net80211/ieee80211_ht.c
index 5356a66..f3c0adf 100644
--- a/sys/net80211/ieee80211_ht.c
+++ b/sys/net80211/ieee80211_ht.c
@@ -335,14 +335,14 @@ ampdu_rx_stop(struct ieee80211_rx_ampdu *rap)
/*
* Dispatch a frame from the A-MPDU reorder queue. The
* frame is fed back into ieee80211_input marked with an
- * M_AMPDU flag so it doesn't come back to us (it also
+ * M_AMPDU_MPDU flag so it doesn't come back to us (it also
* permits ieee80211_input to optimize re-processing).
*/
static __inline void
ampdu_dispatch(struct ieee80211_node *ni, struct mbuf *m)
{
- m->m_flags |= M_AMPDU; /* bypass normal processing */
- /* NB: rssi, noise, and rstamp are ignored w/ M_AMPDU set */
+ m->m_flags |= M_AMPDU_MPDU; /* bypass normal processing */
+ /* NB: rssi, noise, and rstamp are ignored w/ M_AMPDU_MPDU set */
(void) ieee80211_input(ni, m, 0, 0, 0);
}
@@ -517,11 +517,19 @@ ieee80211_ampdu_reorder(struct ieee80211_node *ni, struct mbuf *m)
uint8_t tid;
int off;
+ KASSERT((m->m_flags & (M_AMPDU | M_AMPDU_MPDU)) == M_AMPDU,
+ ("!a-mpdu or already re-ordered, flags 0x%x", m->m_flags));
KASSERT(ni->ni_flags & IEEE80211_NODE_HT, ("not an HT sta"));
/* NB: m_len known to be sufficient */
wh = mtod(m, struct ieee80211_qosframe *);
- KASSERT(wh->i_fc[0] == IEEE80211_FC0_QOSDATA, ("not QoS data"));
+ if (wh->i_fc[0] != IEEE80211_FC0_QOSDATA) {
+ /*
+ * Not QoS data, shouldn't get here but just
+ * return it to the caller for processing.
+ */
+ return PROCESS;
+ }
if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
tid = ((struct ieee80211_qosframe_addr4 *)wh)->i_qos[0];
diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c
index b1488ca..9df35f3 100644
--- a/sys/net80211/ieee80211_output.c
+++ b/sys/net80211/ieee80211_output.c
@@ -1050,8 +1050,13 @@ ieee80211_encap(struct ieee80211_node *ni, struct mbuf *m)
if (IEEE80211_AMPDU_RUNNING(tap)) {
/*
* Operational, mark frame for aggregation.
+ *
+ * NB: We support only immediate BA's for
+ * AMPDU which means we set the QoS control
+ * field to "normal ack" (0) to get "implicit
+ * block ack" behaviour.
*/
- qos[0] |= IEEE80211_QOS_ACKPOLICY_BA;
+ m->m_flags |= M_AMPDU_MPDU;
} else if (!IEEE80211_AMPDU_REQUESTED(tap) &&
ic->ic_ampdu_enable(ni, tap)) {
/*
@@ -1066,8 +1071,23 @@ ieee80211_encap(struct ieee80211_node *ni, struct mbuf *m)
qos[1] = 0;
wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_QOS;
- *(uint16_t *)wh->i_seq =
- htole16(ni->ni_txseqs[tid] << IEEE80211_SEQ_SEQ_SHIFT);
+ if ((m->m_flags & M_AMPDU_MPDU) == 0) {
+ /*
+ * NB: don't assign a sequence # to potential
+ * aggregates; we expect this happens at the
+ * point the frame comes off any aggregation q
+ * as otherwise we may introduce holes in the
+ * BA sequence space and/or make window accouting
+ * more difficult.
+ *
+ * XXX may want to control this with a driver
+ * capability; this may also change when we pull
+ * aggregation up into net80211
+ */
+ *(uint16_t *)wh->i_seq =
+ htole16(ni->ni_txseqs[tid] << IEEE80211_SEQ_SEQ_SHIFT);
+ ni->ni_txseqs[tid]++;
+ }
ni->ni_txseqs[tid]++;
} else {
*(uint16_t *)wh->i_seq =
diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c
index af25bb6..d98c6dd 100644
--- a/sys/net80211/ieee80211_sta.c
+++ b/sys/net80211/ieee80211_sta.c
@@ -494,14 +494,14 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m,
uint8_t *bssid;
uint16_t rxseq;
- if (m->m_flags & M_AMPDU) {
+ if (m->m_flags & M_AMPDU_MPDU) {
/*
* Fastpath for A-MPDU reorder q resubmission. Frames
- * w/ M_AMPDU marked have already passed through here
- * but were received out of order and been held on the
- * reorder queue. When resubmitted they are marked
- * with the M_AMPDU flag and we can bypass most of the
- * normal processing.
+ * w/ M_AMPDU_MPDU marked have already passed through
+ * here but were received out of order and been held on
+ * the reorder queue. When resubmitted they are marked
+ * with the M_AMPDU_MPDU flag and we can bypass most of
+ * the normal processing.
*/
wh = mtod(m, struct ieee80211_frame *);
type = IEEE80211_FC0_TYPE_DATA;
@@ -595,16 +595,12 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m,
goto out; /* XXX */
}
/*
- * Handle A-MPDU re-ordering. The station must be
- * associated and negotiated HT. The frame must be
- * a QoS frame (not QoS null data) and not previously
- * processed for A-MPDU re-ordering. If the frame is
- * to be processed directly then ieee80211_ampdu_reorder
+ * Handle A-MPDU re-ordering. If the frame is to be
+ * processed directly then ieee80211_ampdu_reorder
* will return 0; otherwise it has consumed the mbuf
* and we should do nothing more with it.
*/
- if ((ni->ni_flags & IEEE80211_NODE_HT) &&
- subtype == IEEE80211_FC0_SUBTYPE_QOS &&
+ if ((m->m_flags & M_AMPDU) &&
(dir == IEEE80211_FC1_DIR_FROMDS ||
dir == IEEE80211_FC1_DIR_DSTODS) &&
ieee80211_ampdu_reorder(ni, m) != 0) {
diff --git a/sys/net80211/ieee80211_wds.c b/sys/net80211/ieee80211_wds.c
index ede739d..ff55ed7 100644
--- a/sys/net80211/ieee80211_wds.c
+++ b/sys/net80211/ieee80211_wds.c
@@ -468,14 +468,14 @@ wds_input(struct ieee80211_node *ni, struct mbuf *m,
uint8_t dir, type, subtype, qos;
uint16_t rxseq;
- if (m->m_flags & M_AMPDU) {
+ if (m->m_flags & M_AMPDU_MPDU) {
/*
* Fastpath for A-MPDU reorder q resubmission. Frames
- * w/ M_AMPDU marked have already passed through here
- * but were received out of order and been held on the
- * reorder queue. When resubmitted they are marked
- * with the M_AMPDU flag and we can bypass most of the
- * normal processing.
+ * w/ M_AMPDU_MPDU marked have already passed through
+ * here but were received out of order and been held on
+ * the reorder queue. When resubmitted they are marked
+ * with the M_AMPDU_MPDU flag and we can bypass most of
+ * the normal processing.
*/
wh = mtod(m, struct ieee80211_frame *);
type = IEEE80211_FC0_TYPE_DATA;
@@ -590,16 +590,12 @@ wds_input(struct ieee80211_node *ni, struct mbuf *m,
if (!IEEE80211_IS_MULTICAST(wh->i_addr1))
ni->ni_inact = ni->ni_inact_reload;
/*
- * Handle A-MPDU re-ordering. The station must be
- * associated and negotiated HT. The frame must be
- * a QoS frame (not QoS null data) and not previously
- * processed for A-MPDU re-ordering. If the frame is
- * to be processed directly then ieee80211_ampdu_reorder
+ * Handle A-MPDU re-ordering. If the frame is to be
+ * processed directly then ieee80211_ampdu_reorder
* will return 0; otherwise it has consumed the mbuf
* and we should do nothing more with it.
*/
- if ((ni->ni_flags & IEEE80211_NODE_HT) &&
- subtype == IEEE80211_FC0_SUBTYPE_QOS &&
+ if ((m->m_flags & M_AMPDU) &&
ieee80211_ampdu_reorder(ni, m) != 0) {
m = NULL;
goto out;
OpenPOWER on IntegriCloud