aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched
diff options
context:
space:
mode:
authorstephen hemminger <stephen@networkplumber.org>2013-08-27 19:19:08 -0400
committerDavid S. Miller <davem@davemloft.net>2013-08-31 00:32:32 -0400
commit6da7c8fcbcbdb50ec68c61b40d554c74850fdb91 (patch)
tree587e811df17b158e2c83ca3333d2a6c4c21797ef /net/sched
parent7d7628f3719e85e41d3948759ef969707036033d (diff)
qdisc: allow setting default queuing discipline
By default, the pfifo_fast queue discipline has been used by default for all devices. But we have better choices now. This patch allow setting the default queueing discipline with sysctl. This allows easy use of better queueing disciplines on all devices without having to use tc qdisc scripts. It is intended to allow an easy path for distributions to make fq_codel or sfq the default qdisc. This patch also makes pfifo_fast more of a first class qdisc, since it is now possible to manually override the default and explicitly use pfifo_fast. The behavior for systems who do not use the sysctl is unchanged, they still get pfifo_fast Also removes leftover random # in sysctl net core. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Acked-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched')
-rw-r--r--net/sched/sch_api.c58
-rw-r--r--net/sched/sch_generic.c11
-rw-r--r--net/sched/sch_mq.c2
-rw-r--r--net/sched/sch_mqprio.c2
4 files changed, 66 insertions, 7 deletions
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 51b968d3febb..812e57900591 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -131,6 +131,11 @@ static DEFINE_RWLOCK(qdisc_mod_lock);
131 ************************************************/ 131 ************************************************/
132 132
133 133
134/* Qdisc to use by default */
135
136const struct Qdisc_ops *default_qdisc_ops = &pfifo_fast_ops;
137EXPORT_SYMBOL(default_qdisc_ops);
138
134/* The list of all installed queueing disciplines. */ 139/* The list of all installed queueing disciplines. */
135 140
136static struct Qdisc_ops *qdisc_base; 141static struct Qdisc_ops *qdisc_base;
@@ -200,6 +205,58 @@ int unregister_qdisc(struct Qdisc_ops *qops)
200} 205}
201EXPORT_SYMBOL(unregister_qdisc); 206EXPORT_SYMBOL(unregister_qdisc);
202 207
208/* Get default qdisc if not otherwise specified */
209void qdisc_get_default(char *name, size_t len)
210{
211 read_lock(&qdisc_mod_lock);
212 strlcpy(name, default_qdisc_ops->id, len);
213 read_unlock(&qdisc_mod_lock);
214}
215
216static struct Qdisc_ops *qdisc_lookup_default(const char *name)
217{
218 struct Qdisc_ops *q = NULL;
219
220 for (q = qdisc_base; q; q = q->next) {
221 if (!strcmp(name, q->id)) {
222 if (!try_module_get(q->owner))
223 q = NULL;
224 break;
225 }
226 }
227
228 return q;
229}
230
231/* Set new default qdisc to use */
232int qdisc_set_default(const char *name)
233{
234 const struct Qdisc_ops *ops;
235
236 if (!capable(CAP_NET_ADMIN))
237 return -EPERM;
238
239 write_lock(&qdisc_mod_lock);
240 ops = qdisc_lookup_default(name);
241 if (!ops) {
242 /* Not found, drop lock and try to load module */
243 write_unlock(&qdisc_mod_lock);
244 request_module("sch_%s", name);
245 write_lock(&qdisc_mod_lock);
246
247 ops = qdisc_lookup_default(name);
248 }
249
250 if (ops) {
251 /* Set new default */
252 module_put(default_qdisc_ops->owner);
253 default_qdisc_ops = ops;
254 }
255 write_unlock(&qdisc_mod_lock);
256
257 return ops ? 0 : -ENOENT;
258}
259
203/* We know handle. Find qdisc among all qdisc's attached to device 260/* We know handle. Find qdisc among all qdisc's attached to device
204 (root qdisc, all its children, children of children etc.) 261 (root qdisc, all its children, children of children etc.)
205 */ 262 */
@@ -1854,6 +1911,7 @@ static int __init pktsched_init(void)
1854 return err; 1911 return err;
1855 } 1912 }
1856 1913
1914 register_qdisc(&pfifo_fast_ops);
1857 register_qdisc(&pfifo_qdisc_ops); 1915 register_qdisc(&pfifo_qdisc_ops);
1858 register_qdisc(&bfifo_qdisc_ops); 1916 register_qdisc(&bfifo_qdisc_ops);
1859 register_qdisc(&pfifo_head_drop_qdisc_ops); 1917 register_qdisc(&pfifo_head_drop_qdisc_ops);
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 48be3d5c0d92..5078e0c5db8d 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -530,7 +530,6 @@ struct Qdisc_ops pfifo_fast_ops __read_mostly = {
530 .dump = pfifo_fast_dump, 530 .dump = pfifo_fast_dump,
531 .owner = THIS_MODULE, 531 .owner = THIS_MODULE,
532}; 532};
533EXPORT_SYMBOL(pfifo_fast_ops);
534 533
535static struct lock_class_key qdisc_tx_busylock; 534static struct lock_class_key qdisc_tx_busylock;
536 535
@@ -583,6 +582,9 @@ struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,
583{ 582{
584 struct Qdisc *sch; 583 struct Qdisc *sch;
585 584
585 if (!try_module_get(ops->owner))
586 goto errout;
587
586 sch = qdisc_alloc(dev_queue, ops); 588 sch = qdisc_alloc(dev_queue, ops);
587 if (IS_ERR(sch)) 589 if (IS_ERR(sch))
588 goto errout; 590 goto errout;
@@ -686,7 +688,7 @@ static void attach_one_default_qdisc(struct net_device *dev,
686 688
687 if (dev->tx_queue_len) { 689 if (dev->tx_queue_len) {
688 qdisc = qdisc_create_dflt(dev_queue, 690 qdisc = qdisc_create_dflt(dev_queue,
689 &pfifo_fast_ops, TC_H_ROOT); 691 default_qdisc_ops, TC_H_ROOT);
690 if (!qdisc) { 692 if (!qdisc) {
691 netdev_info(dev, "activation failed\n"); 693 netdev_info(dev, "activation failed\n");
692 return; 694 return;
@@ -739,9 +741,8 @@ void dev_activate(struct net_device *dev)
739 int need_watchdog; 741 int need_watchdog;
740 742
741 /* No queueing discipline is attached to device; 743 /* No queueing discipline is attached to device;
742 create default one i.e. pfifo_fast for devices, 744 * create default one for devices, which need queueing
743 which need queueing and noqueue_qdisc for 745 * and noqueue_qdisc for virtual interfaces
744 virtual interfaces
745 */ 746 */
746 747
747 if (dev->qdisc == &noop_qdisc) 748 if (dev->qdisc == &noop_qdisc)
diff --git a/net/sched/sch_mq.c b/net/sched/sch_mq.c
index 5da78a19ac9a..2e56185736d6 100644
--- a/net/sched/sch_mq.c
+++ b/net/sched/sch_mq.c
@@ -57,7 +57,7 @@ static int mq_init(struct Qdisc *sch, struct nlattr *opt)
57 57
58 for (ntx = 0; ntx < dev->num_tx_queues; ntx++) { 58 for (ntx = 0; ntx < dev->num_tx_queues; ntx++) {
59 dev_queue = netdev_get_tx_queue(dev, ntx); 59 dev_queue = netdev_get_tx_queue(dev, ntx);
60 qdisc = qdisc_create_dflt(dev_queue, &pfifo_fast_ops, 60 qdisc = qdisc_create_dflt(dev_queue, default_qdisc_ops,
61 TC_H_MAKE(TC_H_MAJ(sch->handle), 61 TC_H_MAKE(TC_H_MAJ(sch->handle),
62 TC_H_MIN(ntx + 1))); 62 TC_H_MIN(ntx + 1)));
63 if (qdisc == NULL) 63 if (qdisc == NULL)
diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c
index accec33c454c..d44c868cb537 100644
--- a/net/sched/sch_mqprio.c
+++ b/net/sched/sch_mqprio.c
@@ -124,7 +124,7 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt)
124 124
125 for (i = 0; i < dev->num_tx_queues; i++) { 125 for (i = 0; i < dev->num_tx_queues; i++) {
126 dev_queue = netdev_get_tx_queue(dev, i); 126 dev_queue = netdev_get_tx_queue(dev, i);
127 qdisc = qdisc_create_dflt(dev_queue, &pfifo_fast_ops, 127 qdisc = qdisc_create_dflt(dev_queue, default_qdisc_ops,
128 TC_H_MAKE(TC_H_MAJ(sch->handle), 128 TC_H_MAKE(TC_H_MAJ(sch->handle),
129 TC_H_MIN(i + 1))); 129 TC_H_MIN(i + 1)));
130 if (qdisc == NULL) { 130 if (qdisc == NULL) {