Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net_sched: gred: actually perform idling in WRED mode

gred_dequeue() and gred_drop() do not seem to get called when the
queue is empty, meaning that we never start idling while in WRED
mode. And since qidlestart is not stored by gred_store_wred_set(),
we would never stop idling while in WRED mode if we ever started.
This messes up the average queue size calculation that influences
packet marking/dropping behavior.

Now, we start WRED mode idling as we are removing the last packet
from the queue. Also we now actually stop WRED mode idling when we
are enqueuing a packet.

Cc: Bruce Osler <brosler@cisco.com>
Signed-off-by: David Ward <david.ward@ll.mit.edu>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

David Ward and committed by
David S. Miller
ba1bf474 1fe37b10

+15 -11
+15 -11
net/sched/sch_gred.c
··· 136 136 struct gred_sched_data *q) 137 137 { 138 138 table->wred_set.qavg = q->vars.qavg; 139 + table->wred_set.qidlestart = q->vars.qidlestart; 139 140 } 140 141 141 142 static inline int gred_use_ecn(struct gred_sched *t) ··· 260 259 } else { 261 260 q->backlog -= qdisc_pkt_len(skb); 262 261 263 - if (!q->backlog && !gred_wred_mode(t)) 264 - red_start_of_idle_period(&q->vars); 262 + if (gred_wred_mode(t)) { 263 + if (!sch->qstats.backlog) 264 + red_start_of_idle_period(&t->wred_set); 265 + } else { 266 + if (!q->backlog) 267 + red_start_of_idle_period(&q->vars); 268 + } 265 269 } 266 270 267 271 return skb; 268 272 } 269 - 270 - if (gred_wred_mode(t) && !red_is_idling(&t->wred_set)) 271 - red_start_of_idle_period(&t->wred_set); 272 273 273 274 return NULL; 274 275 } ··· 293 290 q->backlog -= len; 294 291 q->stats.other++; 295 292 296 - if (!q->backlog && !gred_wred_mode(t)) 297 - red_start_of_idle_period(&q->vars); 293 + if (gred_wred_mode(t)) { 294 + if (!sch->qstats.backlog) 295 + red_start_of_idle_period(&t->wred_set); 296 + } else { 297 + if (!q->backlog) 298 + red_start_of_idle_period(&q->vars); 299 + } 298 300 } 299 301 300 302 qdisc_drop(skb, sch); 301 303 return len; 302 304 } 303 305 304 - if (gred_wred_mode(t) && !red_is_idling(&t->wred_set)) 305 - red_start_of_idle_period(&t->wred_set); 306 - 307 306 return 0; 308 - 309 307 } 310 308 311 309 static void gred_reset(struct Qdisc *sch)