Skip to content

Commit 6da7c8f

Browse files
shemmingerdavem330
authored andcommitted
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 <[email protected]> Acked-by: Eric Dumazet <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 7d7628f commit 6da7c8f

File tree

8 files changed

+112
-8
lines changed

8 files changed

+112
-8
lines changed

Documentation/sysctl/net.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,19 @@ The maximum number of packets that kernel can handle on a NAPI interrupt,
5050
it's a Per-CPU variable.
5151
Default: 64
5252

53+
default_qdisc
54+
--------------
55+
56+
The default queuing discipline to use for network devices. This allows
57+
overriding the default queue discipline of pfifo_fast with an
58+
alternative. Since the default queuing discipline is created with the
59+
no additional parameters so is best suited to queuing disciplines that
60+
work well without configuration like stochastic fair queue (sfq),
61+
CoDel (codel) or fair queue CoDel (fq_codel). Don't use queuing disciplines
62+
like Hierarchical Token Bucket or Deficit Round Robin which require setting
63+
up classes and bandwidths.
64+
Default: pfifo_fast
65+
5366
busy_read
5467
----------------
5568
Low latency busy poll timeout for socket reads. (needs CONFIG_NET_RX_BUSY_POLL)

include/net/pkt_sched.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ struct Qdisc *fifo_create_dflt(struct Qdisc *sch, struct Qdisc_ops *ops,
8585

8686
int register_qdisc(struct Qdisc_ops *qops);
8787
int unregister_qdisc(struct Qdisc_ops *qops);
88+
void qdisc_get_default(char *id, size_t len);
89+
int qdisc_set_default(const char *id);
90+
8891
void qdisc_list_del(struct Qdisc *q);
8992
struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle);
9093
struct Qdisc *qdisc_lookup_class(struct net_device *dev, u32 handle);

include/net/sch_generic.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ extern struct Qdisc noop_qdisc;
316316
extern struct Qdisc_ops noop_qdisc_ops;
317317
extern struct Qdisc_ops pfifo_fast_ops;
318318
extern struct Qdisc_ops mq_qdisc_ops;
319+
extern const struct Qdisc_ops *default_qdisc_ops;
319320

320321
struct Qdisc_class_common {
321322
u32 classid;

net/core/sysctl_net_core.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <net/sock.h>
2121
#include <net/net_ratelimit.h>
2222
#include <net/busy_poll.h>
23+
#include <net/pkt_sched.h>
2324

2425
static int zero = 0;
2526
static int one = 1;
@@ -193,6 +194,26 @@ static int flow_limit_table_len_sysctl(struct ctl_table *table, int write,
193194
}
194195
#endif /* CONFIG_NET_FLOW_LIMIT */
195196

197+
#ifdef CONFIG_NET_SCHED
198+
static 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+
196217
static struct ctl_table net_core_table[] = {
197218
#ifdef CONFIG_NET
198219
{
@@ -315,7 +336,14 @@ static struct ctl_table net_core_table[] = {
315336
.mode = 0644,
316337
.proc_handler = proc_dointvec
317338
},
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+
},
319347
#endif
320348
#endif /* CONFIG_NET */
321349
{

net/sched/sch_api.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,11 @@ static DEFINE_RWLOCK(qdisc_mod_lock);
131131
************************************************/
132132

133133

134+
/* Qdisc to use by default */
135+
136+
const struct Qdisc_ops *default_qdisc_ops = &pfifo_fast_ops;
137+
EXPORT_SYMBOL(default_qdisc_ops);
138+
134139
/* The list of all installed queueing disciplines. */
135140

136141
static struct Qdisc_ops *qdisc_base;
@@ -200,6 +205,58 @@ int unregister_qdisc(struct Qdisc_ops *qops)
200205
}
201206
EXPORT_SYMBOL(unregister_qdisc);
202207

208+
/* Get default qdisc if not otherwise specified */
209+
void 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+
216+
static 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 */
232+
int 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+
203260
/* We know handle. Find qdisc among all qdisc's attached to device
204261
(root qdisc, all its children, children of children etc.)
205262
*/
@@ -1854,6 +1911,7 @@ static int __init pktsched_init(void)
18541911
return err;
18551912
}
18561913

1914+
register_qdisc(&pfifo_fast_ops);
18571915
register_qdisc(&pfifo_qdisc_ops);
18581916
register_qdisc(&bfifo_qdisc_ops);
18591917
register_qdisc(&pfifo_head_drop_qdisc_ops);

net/sched/sch_generic.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,6 @@ struct Qdisc_ops pfifo_fast_ops __read_mostly = {
530530
.dump = pfifo_fast_dump,
531531
.owner = THIS_MODULE,
532532
};
533-
EXPORT_SYMBOL(pfifo_fast_ops);
534533

535534
static struct lock_class_key qdisc_tx_busylock;
536535

@@ -583,6 +582,9 @@ struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,
583582
{
584583
struct Qdisc *sch;
585584

585+
if (!try_module_get(ops->owner))
586+
goto errout;
587+
586588
sch = qdisc_alloc(dev_queue, ops);
587589
if (IS_ERR(sch))
588590
goto errout;
@@ -686,7 +688,7 @@ static void attach_one_default_qdisc(struct net_device *dev,
686688

687689
if (dev->tx_queue_len) {
688690
qdisc = qdisc_create_dflt(dev_queue,
689-
&pfifo_fast_ops, TC_H_ROOT);
691+
default_qdisc_ops, TC_H_ROOT);
690692
if (!qdisc) {
691693
netdev_info(dev, "activation failed\n");
692694
return;
@@ -739,9 +741,8 @@ void dev_activate(struct net_device *dev)
739741
int need_watchdog;
740742

741743
/* No queueing discipline is attached to device;
742-
create default one i.e. pfifo_fast for devices,
743-
which need queueing and noqueue_qdisc for
744-
virtual interfaces
744+
* create default one for devices, which need queueing
745+
* and noqueue_qdisc for virtual interfaces
745746
*/
746747

747748
if (dev->qdisc == &noop_qdisc)

net/sched/sch_mq.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ static int mq_init(struct Qdisc *sch, struct nlattr *opt)
5757

5858
for (ntx = 0; ntx < dev->num_tx_queues; ntx++) {
5959
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,
6161
TC_H_MAKE(TC_H_MAJ(sch->handle),
6262
TC_H_MIN(ntx + 1)));
6363
if (qdisc == NULL)

net/sched/sch_mqprio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt)
124124

125125
for (i = 0; i < dev->num_tx_queues; i++) {
126126
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,
128128
TC_H_MAKE(TC_H_MAJ(sch->handle),
129129
TC_H_MIN(i + 1)));
130130
if (qdisc == NULL) {

0 commit comments

Comments
 (0)