aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrishna Kumar <krkumar2@in.ibm.com>2009-08-18 17:55:59 -0400
committerDavid S. Miller <davem@davemloft.net>2009-08-29 03:19:21 -0400
commitfd3ae5e8fc5e947a9f151e80a65763a24b6368a9 (patch)
tree2842160866656f5573aea96fc90893ad0f0d3a23
parent31ce8c71a3bdab12debb5899b1f6dac13e54c71d (diff)
Speed-up pfifo_fast lookup using a private bitmap
Maintain a per-qdisc bitmap for pfifo_fast giving availability of skbs for each band. This allows faster lookup for a skb when there are no high priority skbs. Also, it helps in (rare) cases when there are no skbs on the list, where an immediate lookup is faster than iterating through the three bands. Signed-off-by: Krishna Kumar <krkumar2@in.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/sched/sch_generic.c70
1 files changed, 48 insertions, 22 deletions
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 693df7ae33d8..6f7aebd14072 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -406,18 +406,38 @@ static const u8 prio2band[TC_PRIO_MAX+1] =
406 406
407#define PFIFO_FAST_BANDS 3 407#define PFIFO_FAST_BANDS 3
408 408
409static inline struct sk_buff_head *prio2list(struct sk_buff *skb, 409/*
410 struct Qdisc *qdisc) 410 * Private data for a pfifo_fast scheduler containing:
411 * - queues for the three band
412 * - bitmap indicating which of the bands contain skbs
413 */
414struct pfifo_fast_priv {
415 u32 bitmap;
416 struct sk_buff_head q[PFIFO_FAST_BANDS];
417};
418
419/*
420 * Convert a bitmap to the first band number where an skb is queued, where:
421 * bitmap=0 means there are no skbs on any band.
422 * bitmap=1 means there is an skb on band 0.
423 * bitmap=7 means there are skbs on all 3 bands, etc.
424 */
425static const int bitmap2band[] = {-1, 0, 1, 0, 2, 0, 1, 0};
426
427static inline struct sk_buff_head *band2list(struct pfifo_fast_priv *priv,
428 int band)
411{ 429{
412 struct sk_buff_head *list = qdisc_priv(qdisc); 430 return priv->q + band;
413 return list + prio2band[skb->priority & TC_PRIO_MAX];
414} 431}
415 432
416static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc) 433static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc)
417{ 434{
418 struct sk_buff_head *list = prio2list(skb, qdisc); 435 int band = prio2band[skb->priority & TC_PRIO_MAX];
436 struct pfifo_fast_priv *priv = qdisc_priv(qdisc);
437 struct sk_buff_head *list = band2list(priv, band);
419 438
420 if (skb_queue_len(list) < qdisc_dev(qdisc)->tx_queue_len) { 439 if (skb_queue_len(list) < qdisc_dev(qdisc)->tx_queue_len) {
440 priv->bitmap |= (1 << band);
421 qdisc->q.qlen++; 441 qdisc->q.qlen++;
422 return __qdisc_enqueue_tail(skb, qdisc, list); 442 return __qdisc_enqueue_tail(skb, qdisc, list);
423 } 443 }
@@ -427,14 +447,18 @@ static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc)
427 447
428static struct sk_buff *pfifo_fast_dequeue(struct Qdisc* qdisc) 448static struct sk_buff *pfifo_fast_dequeue(struct Qdisc* qdisc)
429{ 449{
430 int prio; 450 struct pfifo_fast_priv *priv = qdisc_priv(qdisc);
431 struct sk_buff_head *list = qdisc_priv(qdisc); 451 int band = bitmap2band[priv->bitmap];
432 452
433 for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) { 453 if (likely(band >= 0)) {
434 if (!skb_queue_empty(list + prio)) { 454 struct sk_buff_head *list = band2list(priv, band);
435 qdisc->q.qlen--; 455 struct sk_buff *skb = __qdisc_dequeue_head(qdisc, list);
436 return __qdisc_dequeue_head(qdisc, list + prio); 456
437 } 457 qdisc->q.qlen--;
458 if (skb_queue_empty(list))
459 priv->bitmap &= ~(1 << band);
460
461 return skb;
438 } 462 }
439 463
440 return NULL; 464 return NULL;
@@ -442,12 +466,13 @@ static struct sk_buff *pfifo_fast_dequeue(struct Qdisc* qdisc)
442 466
443static struct sk_buff *pfifo_fast_peek(struct Qdisc* qdisc) 467static struct sk_buff *pfifo_fast_peek(struct Qdisc* qdisc)
444{ 468{
445 int prio; 469 struct pfifo_fast_priv *priv = qdisc_priv(qdisc);
446 struct sk_buff_head *list = qdisc_priv(qdisc); 470 int band = bitmap2band[priv->bitmap];
471
472 if (band >= 0) {
473 struct sk_buff_head *list = band2list(priv, band);
447 474
448 for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) { 475 return skb_peek(list);
449 if (!skb_queue_empty(list + prio))
450 return skb_peek(list + prio);
451 } 476 }
452 477
453 return NULL; 478 return NULL;
@@ -456,11 +481,12 @@ static struct sk_buff *pfifo_fast_peek(struct Qdisc* qdisc)
456static void pfifo_fast_reset(struct Qdisc* qdisc) 481static void pfifo_fast_reset(struct Qdisc* qdisc)
457{ 482{
458 int prio; 483 int prio;
459 struct sk_buff_head *list = qdisc_priv(qdisc); 484 struct pfifo_fast_priv *priv = qdisc_priv(qdisc);
460 485
461 for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) 486 for (prio = 0; prio < PFIFO_FAST_BANDS; prio++)
462 __qdisc_reset_queue(qdisc, list + prio); 487 __qdisc_reset_queue(qdisc, band2list(priv, prio));
463 488
489 priv->bitmap = 0;
464 qdisc->qstats.backlog = 0; 490 qdisc->qstats.backlog = 0;
465 qdisc->q.qlen = 0; 491 qdisc->q.qlen = 0;
466} 492}
@@ -480,17 +506,17 @@ nla_put_failure:
480static int pfifo_fast_init(struct Qdisc *qdisc, struct nlattr *opt) 506static int pfifo_fast_init(struct Qdisc *qdisc, struct nlattr *opt)
481{ 507{
482 int prio; 508 int prio;
483 struct sk_buff_head *list = qdisc_priv(qdisc); 509 struct pfifo_fast_priv *priv = qdisc_priv(qdisc);
484 510
485 for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) 511 for (prio = 0; prio < PFIFO_FAST_BANDS; prio++)
486 skb_queue_head_init(list + prio); 512 skb_queue_head_init(band2list(priv, prio));
487 513
488 return 0; 514 return 0;
489} 515}
490 516
491static struct Qdisc_ops pfifo_fast_ops __read_mostly = { 517static struct Qdisc_ops pfifo_fast_ops __read_mostly = {
492 .id = "pfifo_fast", 518 .id = "pfifo_fast",
493 .priv_size = PFIFO_FAST_BANDS * sizeof(struct sk_buff_head), 519 .priv_size = sizeof(struct pfifo_fast_priv),
494 .enqueue = pfifo_fast_enqueue, 520 .enqueue = pfifo_fast_enqueue,
495 .dequeue = pfifo_fast_dequeue, 521 .dequeue = pfifo_fast_dequeue,
496 .peek = pfifo_fast_peek, 522 .peek = pfifo_fast_peek,