aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/sch_generic.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-09-06 04:58:51 -0400
committerDavid S. Miller <davem@davemloft.net>2009-09-06 05:07:05 -0400
commit6ec1c69a8f6492fd25722f4762721921da074c12 (patch)
treea78323d1f7f84acbe08c25d7300b935ae4bb7c62 /net/sched/sch_generic.c
parent589983cd21f4a2e4ed74a958805a90fa676845c5 (diff)
net_sched: add classful multiqueue dummy scheduler
This patch adds a classful dummy scheduler which can be used as root qdisc for multiqueue devices and exposes each device queue as a child class. This allows to address queues individually and graft them similar to regular classes. Additionally it presents an accumulated view of the statistics of all real root qdiscs in the dummy root. Two new callbacks are added to the qdisc_ops and qdisc_class_ops: - cl_ops->select_queue selects the tx queue number for new child classes. - qdisc_ops->attach() overrides root qdisc device grafting to attach non-shared qdiscs to the queues. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched/sch_generic.c')
-rw-r--r--net/sched/sch_generic.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index e7c47ceb0098..4ae6aa562f2b 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -514,7 +514,7 @@ static int pfifo_fast_init(struct Qdisc *qdisc, struct nlattr *opt)
514 return 0; 514 return 0;
515} 515}
516 516
517static struct Qdisc_ops pfifo_fast_ops __read_mostly = { 517struct Qdisc_ops pfifo_fast_ops __read_mostly = {
518 .id = "pfifo_fast", 518 .id = "pfifo_fast",
519 .priv_size = sizeof(struct pfifo_fast_priv), 519 .priv_size = sizeof(struct pfifo_fast_priv),
520 .enqueue = pfifo_fast_enqueue, 520 .enqueue = pfifo_fast_enqueue,
@@ -670,6 +670,26 @@ static void attach_one_default_qdisc(struct net_device *dev,
670 dev_queue->qdisc_sleeping = qdisc; 670 dev_queue->qdisc_sleeping = qdisc;
671} 671}
672 672
673static void attach_default_qdiscs(struct net_device *dev)
674{
675 struct netdev_queue *txq;
676 struct Qdisc *qdisc;
677
678 txq = netdev_get_tx_queue(dev, 0);
679
680 if (!netif_is_multiqueue(dev) || dev->tx_queue_len == 0) {
681 netdev_for_each_tx_queue(dev, attach_one_default_qdisc, NULL);
682 dev->qdisc = txq->qdisc_sleeping;
683 atomic_inc(&dev->qdisc->refcnt);
684 } else {
685 qdisc = qdisc_create_dflt(dev, txq, &mq_qdisc_ops, TC_H_ROOT);
686 if (qdisc) {
687 qdisc->ops->attach(qdisc);
688 dev->qdisc = qdisc;
689 }
690 }
691}
692
673static void transition_one_qdisc(struct net_device *dev, 693static void transition_one_qdisc(struct net_device *dev,
674 struct netdev_queue *dev_queue, 694 struct netdev_queue *dev_queue,
675 void *_need_watchdog) 695 void *_need_watchdog)
@@ -689,7 +709,6 @@ static void transition_one_qdisc(struct net_device *dev,
689 709
690void dev_activate(struct net_device *dev) 710void dev_activate(struct net_device *dev)
691{ 711{
692 struct netdev_queue *txq;
693 int need_watchdog; 712 int need_watchdog;
694 713
695 /* No queueing discipline is attached to device; 714 /* No queueing discipline is attached to device;
@@ -698,13 +717,8 @@ void dev_activate(struct net_device *dev)
698 virtual interfaces 717 virtual interfaces
699 */ 718 */
700 719
701 if (dev->qdisc == &noop_qdisc) { 720 if (dev->qdisc == &noop_qdisc)
702 netdev_for_each_tx_queue(dev, attach_one_default_qdisc, NULL); 721 attach_default_qdiscs(dev);
703
704 txq = netdev_get_tx_queue(dev, 0);
705 dev->qdisc = txq->qdisc_sleeping;
706 atomic_inc(&dev->qdisc->refcnt);
707 }
708 722
709 if (!netif_carrier_ok(dev)) 723 if (!netif_carrier_ok(dev))
710 /* Delay activation until next carrier-on event */ 724 /* Delay activation until next carrier-on event */