mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00
net/sched: Make cake_enqueue return NET_XMIT_CN when past buffer_limit
The following setup can trigger a WARNING in htb_activate due to
the condition: !cl->leaf.q->q.qlen
tc qdisc del dev lo root
tc qdisc add dev lo root handle 1: htb default 1
tc class add dev lo parent 1: classid 1:1 \
htb rate 64bit
tc qdisc add dev lo parent 1:1 handle f: \
cake memlimit 1b
ping -I lo -f -c1 -s64 -W0.001 127.0.0.1
This is because the low memlimit leads to a low buffer_limit, which
causes packet dropping. However, cake_enqueue still returns
NET_XMIT_SUCCESS, causing htb_enqueue to call htb_activate with an
empty child qdisc. We should return NET_XMIT_CN when packets are
dropped from the same tin and flow.
I do not believe return value of NET_XMIT_CN is necessary for packet
drops in the case of ack filtering, as that is meant to optimize
performance, not to signal congestion.
Fixes: 046f6fd5da
("sched: Add Common Applications Kept Enhanced (cake) qdisc")
Signed-off-by: William Liu <will@willsroot.io>
Reviewed-by: Savino Dicanosa <savy@syst3mfailure.io>
Acked-by: Toke Høiland-Jørgensen <toke@toke.dk>
Reviewed-by: Jamal Hadi Salim <jhs@mojatatu.com>
Link: https://patch.msgid.link/20250819033601.579821-1-will@willsroot.io
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
e318cd6714
commit
15de71d06a
@ -1750,7 +1750,7 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
|
|||||||
ktime_t now = ktime_get();
|
ktime_t now = ktime_get();
|
||||||
struct cake_tin_data *b;
|
struct cake_tin_data *b;
|
||||||
struct cake_flow *flow;
|
struct cake_flow *flow;
|
||||||
u32 idx;
|
u32 idx, tin;
|
||||||
|
|
||||||
/* choose flow to insert into */
|
/* choose flow to insert into */
|
||||||
idx = cake_classify(sch, &b, skb, q->flow_mode, &ret);
|
idx = cake_classify(sch, &b, skb, q->flow_mode, &ret);
|
||||||
@ -1760,6 +1760,7 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
|
|||||||
__qdisc_drop(skb, to_free);
|
__qdisc_drop(skb, to_free);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
tin = (u32)(b - q->tins);
|
||||||
idx--;
|
idx--;
|
||||||
flow = &b->flows[idx];
|
flow = &b->flows[idx];
|
||||||
|
|
||||||
@ -1927,13 +1928,22 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
|
|||||||
q->buffer_max_used = q->buffer_used;
|
q->buffer_max_used = q->buffer_used;
|
||||||
|
|
||||||
if (q->buffer_used > q->buffer_limit) {
|
if (q->buffer_used > q->buffer_limit) {
|
||||||
|
bool same_flow = false;
|
||||||
u32 dropped = 0;
|
u32 dropped = 0;
|
||||||
|
u32 drop_id;
|
||||||
|
|
||||||
while (q->buffer_used > q->buffer_limit) {
|
while (q->buffer_used > q->buffer_limit) {
|
||||||
dropped++;
|
dropped++;
|
||||||
cake_drop(sch, to_free);
|
drop_id = cake_drop(sch, to_free);
|
||||||
|
|
||||||
|
if ((drop_id >> 16) == tin &&
|
||||||
|
(drop_id & 0xFFFF) == idx)
|
||||||
|
same_flow = true;
|
||||||
}
|
}
|
||||||
b->drop_overlimit += dropped;
|
b->drop_overlimit += dropped;
|
||||||
|
|
||||||
|
if (same_flow)
|
||||||
|
return NET_XMIT_CN;
|
||||||
}
|
}
|
||||||
return NET_XMIT_SUCCESS;
|
return NET_XMIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user