1 From: Nicolas Escande <nico.escande@gmail.com>
2 Date: Mon, 14 Feb 2022 18:32:14 +0100
3 Subject: [PATCH] mac80211: fix forwarded mesh frames AC & queue selection
5 There are two problems with the current code that have been highlighted
6 with the AQL feature that is now enbaled by default.
8 First problem is in ieee80211_rx_h_mesh_fwding(),
9 ieee80211_select_queue_80211() is used on received packets to choose
10 the sending AC queue of the forwarding packet although this function
11 should only be called on TX packet (it uses ieee80211_tx_info).
12 This ends with forwarded mesh packets been sent on unrelated random AC
13 queue. To fix that, AC queue can directly be infered from skb->priority
14 which has been extracted from QOS info (see ieee80211_parse_qos()).
16 Second problem is the value of queue_mapping set on forwarded mesh
17 frames via skb_set_queue_mapping() is not the AC of the packet but a
18 hardware queue index. This may or may not work depending on AC to HW
19 queue mapping which is driver specific.
21 Both of these issues lead to improper AC selection while forwarding
22 mesh packets but more importantly due to improper airtime accounting
23 (which is done on a per STA, per AC basis) caused traffic stall with
24 the introduction of AQL.
26 Fixes: cf44012810cc ("mac80211: fix unnecessary frame drops in mesh fwding")
27 Fixes: d3c1597b8d1b ("mac80211: fix forwarded mesh frame queue mapping")
28 Co-developed-by: Remi Pommarel <repk@triplefau.lt>
29 Signed-off-by: Remi Pommarel <repk@triplefau.lt>
30 Signed-off-by: Nicolas Escande <nico.escande@gmail.com>
33 --- a/net/mac80211/rx.c
34 +++ b/net/mac80211/rx.c
35 @@ -2921,13 +2921,13 @@ ieee80211_rx_h_mesh_fwding(struct ieee80
36 ether_addr_equal(sdata->vif.addr, hdr->addr3))
39 - ac = ieee80211_select_queue_80211(sdata, skb, hdr);
40 + ac = ieee802_1d_to_ac[skb->priority];
41 q = sdata->vif.hw_queue[ac];
42 if (ieee80211_queue_stopped(&local->hw, q)) {
43 IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_congestion);
44 return RX_DROP_MONITOR;
46 - skb_set_queue_mapping(skb, q);
47 + skb_set_queue_mapping(skb, ac);
49 if (!--mesh_hdr->ttl) {
50 if (!is_multicast_ether_addr(hdr->addr1))