Skip to content

Commit bb42f2d

Browse files
tohojojmberg-intel
authored andcommitted
mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue
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 <[email protected]> [fix a few code-style nits, make ieee80211_xmit_fast_finish void, remove a useless txq->sta check] Signed-off-by: Johannes Berg <[email protected]>
1 parent 3a53731 commit bb42f2d

File tree

6 files changed

+230
-90
lines changed

6 files changed

+230
-90
lines changed

include/net/mac80211.h

+2
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,7 @@ enum mac80211_tx_info_flags {
715715
* frame (PS-Poll or uAPSD).
716716
* @IEEE80211_TX_CTRL_RATE_INJECT: This frame is injected with rate information
717717
* @IEEE80211_TX_CTRL_AMSDU: This frame is an A-MSDU frame
718+
* @IEEE80211_TX_CTRL_FAST_XMIT: This frame is going through the fast_xmit path
718719
*
719720
* These flags are used in tx_info->control.flags.
720721
*/
@@ -723,6 +724,7 @@ enum mac80211_tx_control_flags {
723724
IEEE80211_TX_CTRL_PS_RESPONSE = BIT(1),
724725
IEEE80211_TX_CTRL_RATE_INJECT = BIT(2),
725726
IEEE80211_TX_CTRL_AMSDU = BIT(3),
727+
IEEE80211_TX_CTRL_FAST_XMIT = BIT(4),
726728
};
727729

728730
/*

net/mac80211/ieee80211_i.h

+9
Original file line numberDiff line numberDiff line change
@@ -815,12 +815,14 @@ enum txq_info_flags {
815815
* @def_flow: used as a fallback flow when a packet destined to @tin hashes to
816816
* a fq_flow which is already owned by a different tin
817817
* @def_cvars: codel vars for @def_flow
818+
* @frags: used to keep fragments created after dequeue
818819
*/
819820
struct txq_info {
820821
struct fq_tin tin;
821822
struct fq_flow def_flow;
822823
struct codel_vars def_cvars;
823824
struct codel_stats cstats;
825+
struct sk_buff_head frags;
824826
unsigned long flags;
825827

826828
/* keep last! */
@@ -1498,6 +1500,13 @@ static inline struct txq_info *to_txq_info(struct ieee80211_txq *txq)
14981500
return container_of(txq, struct txq_info, txq);
14991501
}
15001502

1503+
static inline bool txq_has_queue(struct ieee80211_txq *txq)
1504+
{
1505+
struct txq_info *txqi = to_txq_info(txq);
1506+
1507+
return !(skb_queue_empty(&txqi->frags) && !txqi->tin.backlog_packets);
1508+
}
1509+
15011510
static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr)
15021511
{
15031512
return ether_addr_equal(raddr, addr) ||

net/mac80211/rx.c

+1-3
Original file line numberDiff line numberDiff line change
@@ -1323,9 +1323,7 @@ static void sta_ps_start(struct sta_info *sta)
13231323
return;
13241324

13251325
for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) {
1326-
struct txq_info *txqi = to_txq_info(sta->sta.txq[tid]);
1327-
1328-
if (txqi->tin.backlog_packets)
1326+
if (txq_has_queue(sta->sta.txq[tid]))
13291327
set_bit(tid, &sta->txq_buffered_tids);
13301328
else
13311329
clear_bit(tid, &sta->txq_buffered_tids);

net/mac80211/sta_info.c

+3-7
Original file line numberDiff line numberDiff line change
@@ -1212,12 +1212,10 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
12121212

12131213
if (sta->sta.txq[0]) {
12141214
for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
1215-
struct txq_info *txqi = to_txq_info(sta->sta.txq[i]);
1216-
1217-
if (!txqi->tin.backlog_packets)
1215+
if (!txq_has_queue(sta->sta.txq[i]))
12181216
continue;
12191217

1220-
drv_wake_tx_queue(local, txqi);
1218+
drv_wake_tx_queue(local, to_txq_info(sta->sta.txq[i]));
12211219
}
12221220
}
12231221

@@ -1649,9 +1647,7 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
16491647
return;
16501648

16511649
for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) {
1652-
struct txq_info *txqi = to_txq_info(sta->sta.txq[tid]);
1653-
1654-
if (!(tids & BIT(tid)) || txqi->tin.backlog_packets)
1650+
if (!(tids & BIT(tid)) || txq_has_queue(sta->sta.txq[tid]))
16551651
continue;
16561652

16571653
sta_info_recalc_tim(sta);

0 commit comments

Comments
 (0)