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:
parent
50dd888a5f
commit
7a8139bec3
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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];
|
||||
|
@ -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 =
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user