aboutsummaryrefslogtreecommitdiffstats
path: root/package/kernel/mac80211/patches/subsys/311-mac80211-fix-memory-accounting-with-A-MSDU-aggregati.patch
blob: 1fd2b25271b011af2ed873d4a3eed4914942fa35 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
From: Felix Fietkau <nbd@nbd.name>
Date: Thu, 8 Mar 2018 21:00:56 +0100
Subject: [PATCH] mac80211: fix memory accounting with A-MSDU aggregation

fq uses skb->truesize for memory usage tracking. Increments/decrements
are done on enqueue/dequeue.
When A-MSDU aggregation is performed on tx side, the packet is
aggregated with the last packet in the queue belonging to the same flow.
There are multiple bugs here:
- The truesize field of the aggregated packet isn't updated, so memory
usage is underestimated
- fq->memory_usage isn't adjusted.

Because of the combination of both bugs, this only causes tx issues in
rare cases, mainly when the A-MSDU head needs to be reallocated.

Fix this by adjusting both truesize of the A-MSDU head and adding the
truesize delta to fq->memory_usage.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---

--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -3185,6 +3185,7 @@ static bool ieee80211_amsdu_aggregate(st
 	u8 max_subframes = sta->sta.max_amsdu_subframes;
 	int max_frags = local->hw.max_tx_fragments;
 	int max_amsdu_len = sta->sta.max_amsdu_len;
+	int orig_truesize;
 	__be16 len;
 	void *data;
 	bool ret = false;
@@ -3216,12 +3217,13 @@ static bool ieee80211_amsdu_aggregate(st
 	flow = fq_flow_classify(fq, tin, skb, fq_flow_get_default_func);
 	head = skb_peek_tail(&flow->queue);
 	if (!head)
-		goto out;
+		goto unlock;
 
+	orig_truesize = head->truesize;
 	orig_len = head->len;
 
 	if (skb->len + head->len > max_amsdu_len)
-		goto out;
+		goto unlock;
 
 	nfrags = 1 + skb_shinfo(skb)->nr_frags;
 	nfrags += 1 + skb_shinfo(head)->nr_frags;
@@ -3279,6 +3281,9 @@ out_recalc:
 		fq_recalc_backlog(fq, tin, flow);
 	}
 out:
+	fq->memory_usage += head->truesize - orig_truesize;
+
+unlock:
 	spin_unlock_bh(&fq->lock);
 
 	return ret;