54bb114f65fc9730b6abe9e4b65b2e91e012e84d
[openwrt/staging/aparcar.git] /
1 From: Felix Fietkau <nbd@nbd.name>
2 Date: Thu, 8 Mar 2018 21:00:56 +0100
3 Subject: [PATCH] mac80211: fix memory accounting with A-MSDU aggregation
4
5 fq uses skb->truesize for memory usage tracking. Increments/decrements
6 are done on enqueue/dequeue.
7 When A-MSDU aggregation is performed on tx side, the packet is
8 aggregated with the last packet in the queue belonging to the same flow.
9 There are multiple bugs here:
10 - The truesize field of the aggregated packet isn't updated, so memory
11 usage is underestimated
12 - fq->memory_usage isn't adjusted.
13
14 Because of the combination of both bugs, this only causes tx issues in
15 rare cases, mainly when the A-MSDU head needs to be reallocated.
16
17 Fix this by adjusting both truesize of the A-MSDU head and adding the
18 truesize delta to fq->memory_usage.
19
20 Signed-off-by: Felix Fietkau <nbd@nbd.name>
21 ---
22
23 --- a/net/mac80211/tx.c
24 +++ b/net/mac80211/tx.c
25 @@ -3184,6 +3184,7 @@ static bool ieee80211_amsdu_aggregate(st
26 u8 max_subframes = sta->sta.max_amsdu_subframes;
27 int max_frags = local->hw.max_tx_fragments;
28 int max_amsdu_len = sta->sta.max_amsdu_len;
29 + int orig_truesize;
30 __be16 len;
31 void *data;
32 bool ret = false;
33 @@ -3215,12 +3216,13 @@ static bool ieee80211_amsdu_aggregate(st
34 flow = fq_flow_classify(fq, tin, skb, fq_flow_get_default_func);
35 head = skb_peek_tail(&flow->queue);
36 if (!head)
37 - goto out;
38 + goto unlock;
39
40 + orig_truesize = head->truesize;
41 orig_len = head->len;
42
43 if (skb->len + head->len > max_amsdu_len)
44 - goto out;
45 + goto unlock;
46
47 nfrags = 1 + skb_shinfo(skb)->nr_frags;
48 nfrags += 1 + skb_shinfo(head)->nr_frags;
49 @@ -3278,6 +3280,9 @@ out_recalc:
50 fq_recalc_backlog(fq, tin, flow);
51 }
52 out:
53 + fq->memory_usage += head->truesize - orig_truesize;
54 +
55 +unlock:
56 spin_unlock_bh(&fq->lock);
57
58 return ret;