diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2010-12-20 16:18:16 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-12-20 16:18:16 -0500 |
commit | aa3e219997e4b949be4199660936099ded0b401f (patch) | |
tree | e463d695dbf0e92f7fd2c6b3132bbb9c38493829 | |
parent | 914e5cea14b2e4651cdb0707e0936b43246deda0 (diff) |
net_sched: sch_sfq: fix allot handling
When deploying SFQ/IFB here at work, I found the allot management was
pretty wrong in sfq, even changing allot from short to int...
We should init allot for each new flow, not using a previous value found
in slot.
Before patch, I saw bursts of several packets per flow, apparently
denying the default "quantum 1514" limit I had on my SFQ class.
class sfq 11:1 parent 11:
(dropped 0, overlimits 0 requeues 0)
backlog 0b 7p requeues 0
allot 11546
class sfq 11:46 parent 11:
(dropped 0, overlimits 0 requeues 0)
backlog 0b 1p requeues 0
allot -23873
class sfq 11:78 parent 11:
(dropped 0, overlimits 0 requeues 0)
backlog 0b 5p requeues 0
allot 11393
After patch, better fairness among each flow, allot limit being
respected, allot is positive :
class sfq 11:e parent 11:
(dropped 0, overlimits 0 requeues 86)
backlog 0b 3p requeues 86
allot 596
class sfq 11:94 parent 11:
(dropped 0, overlimits 0 requeues 0)
backlog 0b 3p requeues 0
allot 1468
class sfq 11:a4 parent 11:
(dropped 0, overlimits 0 requeues 0)
backlog 0b 4p requeues 0
allot 650
class sfq 11:bb parent 11:
(dropped 0, overlimits 0 requeues 0)
backlog 0b 3p requeues 0
allot 596
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/sched/sch_sfq.c | 20 |
1 files changed, 8 insertions, 12 deletions
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 3cf478d012dd..7150705f1d0b 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c | |||
@@ -270,7 +270,6 @@ static unsigned int sfq_drop(struct Qdisc *sch) | |||
270 | /* It is difficult to believe, but ALL THE SLOTS HAVE LENGTH 1. */ | 270 | /* It is difficult to believe, but ALL THE SLOTS HAVE LENGTH 1. */ |
271 | d = q->next[q->tail]; | 271 | d = q->next[q->tail]; |
272 | q->next[q->tail] = q->next[d]; | 272 | q->next[q->tail] = q->next[d]; |
273 | q->allot[q->next[d]] += q->quantum; | ||
274 | skb = q->qs[d].prev; | 273 | skb = q->qs[d].prev; |
275 | len = qdisc_pkt_len(skb); | 274 | len = qdisc_pkt_len(skb); |
276 | __skb_unlink(skb, &q->qs[d]); | 275 | __skb_unlink(skb, &q->qs[d]); |
@@ -321,14 +320,13 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
321 | sfq_inc(q, x); | 320 | sfq_inc(q, x); |
322 | if (q->qs[x].qlen == 1) { /* The flow is new */ | 321 | if (q->qs[x].qlen == 1) { /* The flow is new */ |
323 | if (q->tail == SFQ_DEPTH) { /* It is the first flow */ | 322 | if (q->tail == SFQ_DEPTH) { /* It is the first flow */ |
324 | q->tail = x; | ||
325 | q->next[x] = x; | 323 | q->next[x] = x; |
326 | q->allot[x] = q->quantum; | ||
327 | } else { | 324 | } else { |
328 | q->next[x] = q->next[q->tail]; | 325 | q->next[x] = q->next[q->tail]; |
329 | q->next[q->tail] = x; | 326 | q->next[q->tail] = x; |
330 | q->tail = x; | ||
331 | } | 327 | } |
328 | q->tail = x; | ||
329 | q->allot[x] = q->quantum; | ||
332 | } | 330 | } |
333 | if (++sch->q.qlen <= q->limit) { | 331 | if (++sch->q.qlen <= q->limit) { |
334 | sch->bstats.bytes += qdisc_pkt_len(skb); | 332 | sch->bstats.bytes += qdisc_pkt_len(skb); |
@@ -359,13 +357,13 @@ sfq_dequeue(struct Qdisc *sch) | |||
359 | { | 357 | { |
360 | struct sfq_sched_data *q = qdisc_priv(sch); | 358 | struct sfq_sched_data *q = qdisc_priv(sch); |
361 | struct sk_buff *skb; | 359 | struct sk_buff *skb; |
362 | sfq_index a, old_a; | 360 | sfq_index a, next_a; |
363 | 361 | ||
364 | /* No active slots */ | 362 | /* No active slots */ |
365 | if (q->tail == SFQ_DEPTH) | 363 | if (q->tail == SFQ_DEPTH) |
366 | return NULL; | 364 | return NULL; |
367 | 365 | ||
368 | a = old_a = q->next[q->tail]; | 366 | a = q->next[q->tail]; |
369 | 367 | ||
370 | /* Grab packet */ | 368 | /* Grab packet */ |
371 | skb = __skb_dequeue(&q->qs[a]); | 369 | skb = __skb_dequeue(&q->qs[a]); |
@@ -376,17 +374,15 @@ sfq_dequeue(struct Qdisc *sch) | |||
376 | /* Is the slot empty? */ | 374 | /* Is the slot empty? */ |
377 | if (q->qs[a].qlen == 0) { | 375 | if (q->qs[a].qlen == 0) { |
378 | q->ht[q->hash[a]] = SFQ_DEPTH; | 376 | q->ht[q->hash[a]] = SFQ_DEPTH; |
379 | a = q->next[a]; | 377 | next_a = q->next[a]; |
380 | if (a == old_a) { | 378 | if (a == next_a) { |
381 | q->tail = SFQ_DEPTH; | 379 | q->tail = SFQ_DEPTH; |
382 | return skb; | 380 | return skb; |
383 | } | 381 | } |
384 | q->next[q->tail] = a; | 382 | q->next[q->tail] = next_a; |
385 | q->allot[a] += q->quantum; | ||
386 | } else if ((q->allot[a] -= qdisc_pkt_len(skb)) <= 0) { | 383 | } else if ((q->allot[a] -= qdisc_pkt_len(skb)) <= 0) { |
387 | q->tail = a; | ||
388 | a = q->next[a]; | ||
389 | q->allot[a] += q->quantum; | 384 | q->allot[a] += q->quantum; |
385 | q->tail = a; | ||
390 | } | 386 | } |
391 | return skb; | 387 | return skb; |
392 | } | 388 | } |