diff options
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.patch | 95 |
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) { |