378-mac80211-fix-memory-accounting-with-A-MSDU-aggregati.patch 1.7 KB

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