aboutsummaryrefslogtreecommitdiffstats
path: root/package/kernel/mac80211/patches/subsys/310-net-fq_impl-bulk-free-packets-from-a-flow-on-overmem.patch
diff options
context:
space:
mode:
Diffstat (limited to 'package/kernel/mac80211/patches/subsys/310-net-fq_impl-bulk-free-packets-from-a-flow-on-overmem.patch')
-rw-r--r--package/kernel/mac80211/patches/subsys/310-net-fq_impl-bulk-free-packets-from-a-flow-on-overmem.patch95
1 files changed, 95 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/subsys/310-net-fq_impl-bulk-free-packets-from-a-flow-on-overmem.patch b/package/kernel/mac80211/patches/subsys/310-net-fq_impl-bulk-free-packets-from-a-flow-on-overmem.patch
new file mode 100644
index 0000000000..05a888006e
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/310-net-fq_impl-bulk-free-packets-from-a-flow-on-overmem.patch
@@ -0,0 +1,95 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Wed, 25 Nov 2020 18:03:46 +0100
+Subject: [PATCH] net/fq_impl: bulk-free packets from a flow on overmemory
+
+This is similar to what sch_fq_codel does. It also amortizes the worst
+case cost of a follow-up patch that changes the selection of the biggest
+flow for dropping packets
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/include/net/fq_impl.h
++++ b/include/net/fq_impl.h
+@@ -11,17 +11,25 @@
+
+ /* functions that are embedded into includer */
+
++
++static void
++__fq_adjust_removal(struct fq *fq, struct fq_flow *flow, unsigned int packets,
++ unsigned int bytes, unsigned int truesize)
++{
++ struct fq_tin *tin = flow->tin;
++
++ tin->backlog_bytes -= bytes;
++ tin->backlog_packets -= packets;
++ flow->backlog -= bytes;
++ fq->backlog -= packets;
++ fq->memory_usage -= truesize;
++}
++
+ static void fq_adjust_removal(struct fq *fq,
+ struct fq_flow *flow,
+ struct sk_buff *skb)
+ {
+- struct fq_tin *tin = flow->tin;
+-
+- tin->backlog_bytes -= skb->len;
+- tin->backlog_packets--;
+- flow->backlog -= skb->len;
+- fq->backlog--;
+- fq->memory_usage -= skb->truesize;
++ __fq_adjust_removal(fq, flow, 1, skb->len, skb->truesize);
+ }
+
+ static void fq_rejigger_backlog(struct fq *fq, struct fq_flow *flow)
+@@ -59,6 +67,34 @@ static struct sk_buff *fq_flow_dequeue(s
+ return skb;
+ }
+
++static int fq_flow_drop(struct fq *fq, struct fq_flow *flow,
++ fq_skb_free_t free_func)
++{
++ unsigned int packets = 0, bytes = 0, truesize = 0;
++ struct fq_tin *tin = flow->tin;
++ struct sk_buff *skb;
++ int pending;
++
++ lockdep_assert_held(&fq->lock);
++
++ pending = min_t(int, 32, skb_queue_len(&flow->queue) / 2);
++ do {
++ skb = __skb_dequeue(&flow->queue);
++ if (!skb)
++ break;
++
++ packets++;
++ bytes += skb->len;
++ truesize += skb->truesize;
++ free_func(fq, tin, flow, skb);
++ } while (packets < pending);
++
++ __fq_adjust_removal(fq, flow, packets, bytes, truesize);
++ fq_rejigger_backlog(fq, flow);
++
++ return packets;
++}
++
+ static struct sk_buff *fq_tin_dequeue(struct fq *fq,
+ struct fq_tin *tin,
+ fq_tin_dequeue_t dequeue_func)
+@@ -190,12 +226,9 @@ static void fq_tin_enqueue(struct fq *fq
+ if (!flow)
+ return;
+
+- skb = fq_flow_dequeue(fq, flow);
+- if (!skb)
++ if (!fq_flow_drop(fq, flow, free_func))
+ return;
+
+- free_func(fq, flow->tin, flow, skb);
+-
+ flow->tin->overlimit++;
+ fq->overlimit++;
+ if (oom) {