12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758 |
- 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
- @@ -3188,6 +3188,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;
- @@ -3219,12 +3220,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;
- @@ -3282,6 +3284,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;
|