Skip to content

Commit

Permalink
mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue
Browse files Browse the repository at this point in the history
The TXQ intermediate queues can cause packet reordering when more than
one flow is active to a single station. Since some of the wifi-specific
packet handling (notably sequence number and encryption handling) is
sensitive to re-ordering, things break if they are applied before the
TXQ.

This splits up the TX handlers and fast_xmit logic into two parts: An
early part and a late part. The former is applied before TXQ enqueue,
and the latter after dequeue. The non-TXQ path just applies both parts
at once.

Because fragments shouldn't be split up or reordered, the fragmentation
handler is run after dequeue. Any fragments are then kept in the TXQ and
on subsequent dequeues they take precedence over dequeueing from the FQ
structure.

This approach avoids having to scatter special cases all over the place
for when TXQ is enabled, at the cost of making the fast_xmit and TX
handler code slightly more complex.

Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
[fix a few code-style nits, make ieee80211_xmit_fast_finish void,
 remove a useless txq->sta check]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  • Loading branch information
Toke Høiland-Jørgensen authored and Johannes Berg committed Sep 30, 2016
1 parent 3a53731 commit bb42f2d
Show file tree
Hide file tree
Showing 6 changed files with 230 additions and 90 deletions.
2 changes: 2 additions & 0 deletions include/net/mac80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,7 @@ enum mac80211_tx_info_flags {
* frame (PS-Poll or uAPSD).
* @IEEE80211_TX_CTRL_RATE_INJECT: This frame is injected with rate information
* @IEEE80211_TX_CTRL_AMSDU: This frame is an A-MSDU frame
* @IEEE80211_TX_CTRL_FAST_XMIT: This frame is going through the fast_xmit path
*
* These flags are used in tx_info->control.flags.
*/
Expand All @@ -723,6 +724,7 @@ enum mac80211_tx_control_flags {
IEEE80211_TX_CTRL_PS_RESPONSE = BIT(1),
IEEE80211_TX_CTRL_RATE_INJECT = BIT(2),
IEEE80211_TX_CTRL_AMSDU = BIT(3),
IEEE80211_TX_CTRL_FAST_XMIT = BIT(4),
};

/*
Expand Down
9 changes: 9 additions & 0 deletions net/mac80211/ieee80211_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -815,12 +815,14 @@ enum txq_info_flags {
* @def_flow: used as a fallback flow when a packet destined to @tin hashes to
* a fq_flow which is already owned by a different tin
* @def_cvars: codel vars for @def_flow
* @frags: used to keep fragments created after dequeue
*/
struct txq_info {
struct fq_tin tin;
struct fq_flow def_flow;
struct codel_vars def_cvars;
struct codel_stats cstats;
struct sk_buff_head frags;
unsigned long flags;

/* keep last! */
Expand Down Expand Up @@ -1498,6 +1500,13 @@ static inline struct txq_info *to_txq_info(struct ieee80211_txq *txq)
return container_of(txq, struct txq_info, txq);
}

static inline bool txq_has_queue(struct ieee80211_txq *txq)
{
struct txq_info *txqi = to_txq_info(txq);

return !(skb_queue_empty(&txqi->frags) && !txqi->tin.backlog_packets);
}

static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr)
{
return ether_addr_equal(raddr, addr) ||
Expand Down
4 changes: 1 addition & 3 deletions net/mac80211/rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1323,9 +1323,7 @@ static void sta_ps_start(struct sta_info *sta)
return;

for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) {
struct txq_info *txqi = to_txq_info(sta->sta.txq[tid]);

if (txqi->tin.backlog_packets)
if (txq_has_queue(sta->sta.txq[tid]))
set_bit(tid, &sta->txq_buffered_tids);
else
clear_bit(tid, &sta->txq_buffered_tids);
Expand Down
10 changes: 3 additions & 7 deletions net/mac80211/sta_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -1212,12 +1212,10 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)

if (sta->sta.txq[0]) {
for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
struct txq_info *txqi = to_txq_info(sta->sta.txq[i]);

if (!txqi->tin.backlog_packets)
if (!txq_has_queue(sta->sta.txq[i]))
continue;

drv_wake_tx_queue(local, txqi);
drv_wake_tx_queue(local, to_txq_info(sta->sta.txq[i]));
}
}

Expand Down Expand Up @@ -1649,9 +1647,7 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
return;

for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) {
struct txq_info *txqi = to_txq_info(sta->sta.txq[tid]);

if (!(tids & BIT(tid)) || txqi->tin.backlog_packets)
if (!(tids & BIT(tid)) || txq_has_queue(sta->sta.txq[tid]))
continue;

sta_info_recalc_tim(sta);
Expand Down
Loading

0 comments on commit bb42f2d

Please sign in to comment.