| 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) { |