summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/sysctl/net.txt13
-rw-r--r--include/net/pkt_sched.h3
-rw-r--r--include/net/sch_generic.h1
-rw-r--r--net/core/sysctl_net_core.c30
-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
8 files changed, 112 insertions, 8 deletions
diff --git a/Documentation/sysctl/net.txt b/Documentation/sysctl/net.txt
index d569f2a424d5..9a0319a82470 100644
--- a/Documentation/sysctl/net.txt
+++ b/Documentation/sysctl/net.txt
@@ -50,6 +50,19 @@ The maximum number of packets that kernel can handle on a NAPI interrupt,
50it's a Per-CPU variable. 50it's a Per-CPU variable.
51Default: 64 51Default: 64
52 52
53default_qdisc
54--------------
55
56The default queuing discipline to use for network devices. This allows
57overriding the default queue discipline of pfifo_fast with an
58alternative. Since the default queuing discipline is created with the
59no additional parameters so is best suited to queuing disciplines that
60work well without configuration like stochastic fair queue (sfq),
61CoDel (codel) or fair queue CoDel (fq_codel). Don't use queuing disciplines
62like Hierarchical Token Bucket or Deficit Round Robin which require setting
63up classes and bandwidths.
64Default: pfifo_fast
65
53busy_read 66busy_read
54---------------- 67----------------
55Low latency busy poll timeout for socket reads. (needs CONFIG_NET_RX_BUSY_POLL) 68Low latency busy poll timeout for socket reads. (needs CONFIG_NET_RX_BUSY_POLL)
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
index f7c24f8fbdc5..59ec3cd15d68 100644
--- a/include/net/pkt_sched.h
+++ b/include/net/pkt_sched.h
@@ -85,6 +85,9 @@ struct Qdisc *fifo_create_dflt(struct Qdisc *sch, struct Qdisc_ops *ops,
85 85
86int register_qdisc(struct Qdisc_ops *qops); 86int register_qdisc(struct Qdisc_ops *qops);
87int unregister_qdisc(struct Qdisc_ops *qops); 87int unregister_qdisc(struct Qdisc_ops *qops);
88void qdisc_get_default(char *id, size_t len);
89int qdisc_set_default(const char *id);
90
88void qdisc_list_del(struct Qdisc *q); 91void qdisc_list_del(struct Qdisc *q);
89struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle); 92struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle);
90struct Qdisc *qdisc_lookup_class(struct net_device *dev, u32 handle); 93struct Qdisc *qdisc_lookup_class(struct net_device *dev, u32 handle);
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 76368c9d4503..2e31bf14df00 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -316,6 +316,7 @@ extern struct Qdisc noop_qdisc;
316extern struct Qdisc_ops noop_qdisc_ops; 316extern struct Qdisc_ops noop_qdisc_ops;
317extern struct Qdisc_ops pfifo_fast_ops; 317extern struct Qdisc_ops pfifo_fast_ops;
318extern struct Qdisc_ops mq_qdisc_ops; 318extern struct Qdisc_ops mq_qdisc_ops;
319extern const struct Qdisc_ops *default_qdisc_ops;
319 320
320struct Qdisc_class_common { 321struct Qdisc_class_common {
321 u32 classid; 322 u32 classid;
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index 31107abd2783..cca444190907 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -20,6 +20,7 @@
20#include <net/sock.h> 20#include <net/sock.h>
21#include <net/net_ratelimit.h> 21#include <net/net_ratelimit.h>
22#include <net/busy_poll.h> 22#include <net/busy_poll.h>
23#include <net/pkt_sched.h>
23 24
24static int zero = 0; 25static int zero = 0;
25static int one = 1; 26static int one = 1;
@@ -193,6 +194,26 @@ static int flow_limit_table_len_sysctl(struct ctl_table *table, int write,
193} 194}
194#endif /* CONFIG_NET_FLOW_LIMIT */ 195#endif /* CONFIG_NET_FLOW_LIMIT */
195 196
197#ifdef CONFIG_NET_SCHED
198static int set_default_qdisc(struct ctl_table *table, int write,
199 void __user *buffer, size_t *lenp, loff_t *ppos)
200{
201 char id[IFNAMSIZ];
202 struct ctl_table tbl = {
203 .data = id,
204 .maxlen = IFNAMSIZ,
205 };
206 int ret;
207
208 qdisc_get_default(id, IFNAMSIZ);
209
210 ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
211 if (write && ret == 0)
212 ret = qdisc_set_default(id);
213 return ret;
214}
215#endif
216
196static struct ctl_table net_core_table[] = { 217static struct ctl_table net_core_table[] = {
197#ifdef CONFIG_NET 218#ifdef CONFIG_NET
198 { 219 {
@@ -315,7 +336,14 @@ static struct ctl_table net_core_table[] = {
315 .mode = 0644, 336 .mode = 0644,
316 .proc_handler = proc_dointvec 337 .proc_handler = proc_dointvec
317 }, 338 },
318# 339#endif
340#ifdef CONFIG_NET_SCHED
341 {
342 .procname = "default_qdisc",
343 .mode = 0644,
344 .maxlen = IFNAMSIZ,
345 .proc_handler = set_default_qdisc
346 },
319#endif 347#endif
320#endif /* CONFIG_NET */ 348#endif /* CONFIG_NET */
321 { 349 {
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) {