fq_codel updates the configured quantum without adjusting deficits for flows that are already active. Those flows can continue to carry credit calculated under the old quantum. This can be observed by making a flow active, changing the quantum, and then dequeuing with the old deficit still present. Clamp active flow deficits to the new quantum when fq_codel's quantum changes so the new setting takes effect without waiting for stale credit to drain. Assisted-by: Codex:gpt-5.5-cyber-preview Signed-off-by: Samuel Moelius --- net/sched/sch_fq_codel.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c index 24db54684e8a..64e86ce3f34b 100644 --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c @@ -350,6 +350,19 @@ static void fq_codel_reset(struct Qdisc *sch) q->memory_usage = 0; } +static void fq_codel_clamp_active_deficits(struct fq_codel_sched_data *q, + u32 quantum) +{ + struct fq_codel_flow *flow; + + list_for_each_entry(flow, &q->new_flows, flowchain) + if (READ_ONCE(flow->deficit) > quantum) + WRITE_ONCE(flow->deficit, quantum); + list_for_each_entry(flow, &q->old_flows, flowchain) + if (READ_ONCE(flow->deficit) > quantum) + WRITE_ONCE(flow->deficit, quantum); +} + static const struct nla_policy fq_codel_policy[TCA_FQ_CODEL_MAX + 1] = { [TCA_FQ_CODEL_TARGET] = { .type = NLA_U32 }, [TCA_FQ_CODEL_LIMIT] = { .type = NLA_U32 }, @@ -430,8 +443,10 @@ static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt, WRITE_ONCE(q->cparams.ecn, !!nla_get_u32(tb[TCA_FQ_CODEL_ECN])); - if (quantum) + if (quantum) { + fq_codel_clamp_active_deficits(q, quantum); WRITE_ONCE(q->quantum, quantum); + } if (tb[TCA_FQ_CODEL_DROP_BATCH_SIZE]) WRITE_ONCE(q->drop_batch_size, -- 2.43.0