mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-23 07:22:33 +00:00
96 lines
2.4 KiB
Diff
96 lines
2.4 KiB
Diff
|
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) {
|