aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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,