Commit 07be2fed authored by Felix Fietkau's avatar Felix Fietkau Committed by Johannes Berg
Browse files

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: default avatarFelix Fietkau <nbd@nbd.name>
Link: https://lore.kernel.org/r/20201218184718.93650-1-nbd@nbd.name


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 9e8789c8
Loading
Loading
Loading
Loading
+44 −11
Original line number Diff line number Diff line
@@ -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) {