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>
Link: https://lore.kernel.org/r/20201218184718.93650-1-nbd@nbd.name
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Felix Fietkau 2020-12-18 19:47:13 +01:00 committed by Johannes Berg
parent 9e8789c85d
commit 07be2fed5e
1 changed files with 44 additions and 11 deletions

View File

@ -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(struct fq *fq,
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) {