b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | From: Felix Fietkau <nbd@nbd.name> |
| 2 | Date: Wed, 25 Nov 2020 18:03:46 +0100 |
| 3 | Subject: [PATCH] net/fq_impl: bulk-free packets from a flow on overmemory |
| 4 | |
| 5 | This is similar to what sch_fq_codel does. It also amortizes the worst |
| 6 | case cost of a follow-up patch that changes the selection of the biggest |
| 7 | flow for dropping packets |
| 8 | |
| 9 | Signed-off-by: Felix Fietkau <nbd@nbd.name> |
| 10 | --- |
| 11 | |
| 12 | --- a/include/net/fq_impl.h |
| 13 | +++ b/include/net/fq_impl.h |
| 14 | @@ -11,17 +11,25 @@ |
| 15 | |
| 16 | /* functions that are embedded into includer */ |
| 17 | |
| 18 | + |
| 19 | +static void |
| 20 | +__fq_adjust_removal(struct fq *fq, struct fq_flow *flow, unsigned int packets, |
| 21 | + unsigned int bytes, unsigned int truesize) |
| 22 | +{ |
| 23 | + struct fq_tin *tin = flow->tin; |
| 24 | + |
| 25 | + tin->backlog_bytes -= bytes; |
| 26 | + tin->backlog_packets -= packets; |
| 27 | + flow->backlog -= bytes; |
| 28 | + fq->backlog -= packets; |
| 29 | + fq->memory_usage -= truesize; |
| 30 | +} |
| 31 | + |
| 32 | static void fq_adjust_removal(struct fq *fq, |
| 33 | struct fq_flow *flow, |
| 34 | struct sk_buff *skb) |
| 35 | { |
| 36 | - struct fq_tin *tin = flow->tin; |
| 37 | - |
| 38 | - tin->backlog_bytes -= skb->len; |
| 39 | - tin->backlog_packets--; |
| 40 | - flow->backlog -= skb->len; |
| 41 | - fq->backlog--; |
| 42 | - fq->memory_usage -= skb->truesize; |
| 43 | + __fq_adjust_removal(fq, flow, 1, skb->len, skb->truesize); |
| 44 | } |
| 45 | |
| 46 | static void fq_rejigger_backlog(struct fq *fq, struct fq_flow *flow) |
| 47 | @@ -59,6 +67,34 @@ static struct sk_buff *fq_flow_dequeue(s |
| 48 | return skb; |
| 49 | } |
| 50 | |
| 51 | +static int fq_flow_drop(struct fq *fq, struct fq_flow *flow, |
| 52 | + fq_skb_free_t free_func) |
| 53 | +{ |
| 54 | + unsigned int packets = 0, bytes = 0, truesize = 0; |
| 55 | + struct fq_tin *tin = flow->tin; |
| 56 | + struct sk_buff *skb; |
| 57 | + int pending; |
| 58 | + |
| 59 | + lockdep_assert_held(&fq->lock); |
| 60 | + |
| 61 | + pending = min_t(int, 32, skb_queue_len(&flow->queue) / 2); |
| 62 | + do { |
| 63 | + skb = __skb_dequeue(&flow->queue); |
| 64 | + if (!skb) |
| 65 | + break; |
| 66 | + |
| 67 | + packets++; |
| 68 | + bytes += skb->len; |
| 69 | + truesize += skb->truesize; |
| 70 | + free_func(fq, tin, flow, skb); |
| 71 | + } while (packets < pending); |
| 72 | + |
| 73 | + __fq_adjust_removal(fq, flow, packets, bytes, truesize); |
| 74 | + fq_rejigger_backlog(fq, flow); |
| 75 | + |
| 76 | + return packets; |
| 77 | +} |
| 78 | + |
| 79 | static struct sk_buff *fq_tin_dequeue(struct fq *fq, |
| 80 | struct fq_tin *tin, |
| 81 | fq_tin_dequeue_t dequeue_func) |
| 82 | @@ -190,12 +226,9 @@ static void fq_tin_enqueue(struct fq *fq |
| 83 | if (!flow) |
| 84 | return; |
| 85 | |
| 86 | - skb = fq_flow_dequeue(fq, flow); |
| 87 | - if (!skb) |
| 88 | + if (!fq_flow_drop(fq, flow, free_func)) |
| 89 | return; |
| 90 | |
| 91 | - free_func(fq, flow->tin, flow, skb); |
| 92 | - |
| 93 | flow->tin->overlimit++; |
| 94 | fq->overlimit++; |
| 95 | if (oom) { |