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)
This commit is contained in:
sam 2008-09-21 23:00:19 +00:00
parent 50dd888a5f
commit 7a8139bec3
7 changed files with 78 additions and 62 deletions

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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];

View File

@ -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 =

View File

@ -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) {

View File

@ -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;