Skip to content

Commit

Permalink
qdisc: allow setting default queuing discipline
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
shemminger authored and davem330 committed Aug 31, 2013
1 parent 7d7628f commit 6da7c8f
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 8 deletions.
13 changes: 13 additions & 0 deletions Documentation/sysctl/net.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,19 @@ The maximum number of packets that kernel can handle on a NAPI interrupt,
it's a Per-CPU variable.
Default: 64

default_qdisc
--------------

The default queuing discipline to use for network devices. This allows
overriding the default queue discipline of pfifo_fast with an
alternative. Since the default queuing discipline is created with the
no additional parameters so is best suited to queuing disciplines that
work well without configuration like stochastic fair queue (sfq),
CoDel (codel) or fair queue CoDel (fq_codel). Don't use queuing disciplines
like Hierarchical Token Bucket or Deficit Round Robin which require setting
up classes and bandwidths.
Default: pfifo_fast

busy_read
----------------
Low latency busy poll timeout for socket reads. (needs CONFIG_NET_RX_BUSY_POLL)
Expand Down
3 changes: 3 additions & 0 deletions include/net/pkt_sched.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ struct Qdisc *fifo_create_dflt(struct Qdisc *sch, struct Qdisc_ops *ops,

int register_qdisc(struct Qdisc_ops *qops);
int unregister_qdisc(struct Qdisc_ops *qops);
void qdisc_get_default(char *id, size_t len);
int qdisc_set_default(const char *id);

void qdisc_list_del(struct Qdisc *q);
struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle);
struct Qdisc *qdisc_lookup_class(struct net_device *dev, u32 handle);
Expand Down
1 change: 1 addition & 0 deletions include/net/sch_generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ extern struct Qdisc noop_qdisc;
extern struct Qdisc_ops noop_qdisc_ops;
extern struct Qdisc_ops pfifo_fast_ops;
extern struct Qdisc_ops mq_qdisc_ops;
extern const struct Qdisc_ops *default_qdisc_ops;

struct Qdisc_class_common {
u32 classid;
Expand Down
30 changes: 29 additions & 1 deletion net/core/sysctl_net_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <net/sock.h>
#include <net/net_ratelimit.h>
#include <net/busy_poll.h>
#include <net/pkt_sched.h>

static int zero = 0;
static int one = 1;
Expand Down Expand Up @@ -193,6 +194,26 @@ static int flow_limit_table_len_sysctl(struct ctl_table *table, int write,
}
#endif /* CONFIG_NET_FLOW_LIMIT */

#ifdef CONFIG_NET_SCHED
static int set_default_qdisc(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
char id[IFNAMSIZ];
struct ctl_table tbl = {
.data = id,
.maxlen = IFNAMSIZ,
};
int ret;

qdisc_get_default(id, IFNAMSIZ);

ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
if (write && ret == 0)
ret = qdisc_set_default(id);
return ret;
}
#endif

static struct ctl_table net_core_table[] = {
#ifdef CONFIG_NET
{
Expand Down Expand Up @@ -315,7 +336,14 @@ static struct ctl_table net_core_table[] = {
.mode = 0644,
.proc_handler = proc_dointvec
},
#
#endif
#ifdef CONFIG_NET_SCHED
{
.procname = "default_qdisc",
.mode = 0644,
.maxlen = IFNAMSIZ,
.proc_handler = set_default_qdisc
},
#endif
#endif /* CONFIG_NET */
{
Expand Down
58 changes: 58 additions & 0 deletions net/sched/sch_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ static DEFINE_RWLOCK(qdisc_mod_lock);
************************************************/


/* Qdisc to use by default */

const struct Qdisc_ops *default_qdisc_ops = &pfifo_fast_ops;
EXPORT_SYMBOL(default_qdisc_ops);

/* The list of all installed queueing disciplines. */

static struct Qdisc_ops *qdisc_base;
Expand Down Expand Up @@ -200,6 +205,58 @@ int unregister_qdisc(struct Qdisc_ops *qops)
}
EXPORT_SYMBOL(unregister_qdisc);

/* Get default qdisc if not otherwise specified */
void qdisc_get_default(char *name, size_t len)
{
read_lock(&qdisc_mod_lock);
strlcpy(name, default_qdisc_ops->id, len);
read_unlock(&qdisc_mod_lock);
}

static struct Qdisc_ops *qdisc_lookup_default(const char *name)
{
struct Qdisc_ops *q = NULL;

for (q = qdisc_base; q; q = q->next) {
if (!strcmp(name, q->id)) {
if (!try_module_get(q->owner))
q = NULL;
break;
}
}

return q;
}

/* Set new default qdisc to use */
int qdisc_set_default(const char *name)
{
const struct Qdisc_ops *ops;

if (!capable(CAP_NET_ADMIN))
return -EPERM;

write_lock(&qdisc_mod_lock);
ops = qdisc_lookup_default(name);
if (!ops) {
/* Not found, drop lock and try to load module */
write_unlock(&qdisc_mod_lock);
request_module("sch_%s", name);
write_lock(&qdisc_mod_lock);

ops = qdisc_lookup_default(name);
}

if (ops) {
/* Set new default */
module_put(default_qdisc_ops->owner);
default_qdisc_ops = ops;
}
write_unlock(&qdisc_mod_lock);

return ops ? 0 : -ENOENT;
}

/* We know handle. Find qdisc among all qdisc's attached to device
(root qdisc, all its children, children of children etc.)
*/
Expand Down Expand Up @@ -1854,6 +1911,7 @@ static int __init pktsched_init(void)
return err;
}

register_qdisc(&pfifo_fast_ops);
register_qdisc(&pfifo_qdisc_ops);
register_qdisc(&bfifo_qdisc_ops);
register_qdisc(&pfifo_head_drop_qdisc_ops);
Expand Down
11 changes: 6 additions & 5 deletions net/sched/sch_generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,6 @@ struct Qdisc_ops pfifo_fast_ops __read_mostly = {
.dump = pfifo_fast_dump,
.owner = THIS_MODULE,
};
EXPORT_SYMBOL(pfifo_fast_ops);

static struct lock_class_key qdisc_tx_busylock;

Expand Down Expand Up @@ -583,6 +582,9 @@ struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,
{
struct Qdisc *sch;

if (!try_module_get(ops->owner))
goto errout;

sch = qdisc_alloc(dev_queue, ops);
if (IS_ERR(sch))
goto errout;
Expand Down Expand Up @@ -686,7 +688,7 @@ static void attach_one_default_qdisc(struct net_device *dev,

if (dev->tx_queue_len) {
qdisc = qdisc_create_dflt(dev_queue,
&pfifo_fast_ops, TC_H_ROOT);
default_qdisc_ops, TC_H_ROOT);
if (!qdisc) {
netdev_info(dev, "activation failed\n");
return;
Expand Down Expand Up @@ -739,9 +741,8 @@ void dev_activate(struct net_device *dev)
int need_watchdog;

/* No queueing discipline is attached to device;
create default one i.e. pfifo_fast for devices,
which need queueing and noqueue_qdisc for
virtual interfaces
* create default one for devices, which need queueing
* and noqueue_qdisc for virtual interfaces
*/

if (dev->qdisc == &noop_qdisc)
Expand Down
2 changes: 1 addition & 1 deletion net/sched/sch_mq.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ static int mq_init(struct Qdisc *sch, struct nlattr *opt)

for (ntx = 0; ntx < dev->num_tx_queues; ntx++) {
dev_queue = netdev_get_tx_queue(dev, ntx);
qdisc = qdisc_create_dflt(dev_queue, &pfifo_fast_ops,
qdisc = qdisc_create_dflt(dev_queue, default_qdisc_ops,
TC_H_MAKE(TC_H_MAJ(sch->handle),
TC_H_MIN(ntx + 1)));
if (qdisc == NULL)
Expand Down
2 changes: 1 addition & 1 deletion net/sched/sch_mqprio.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt)

for (i = 0; i < dev->num_tx_queues; i++) {
dev_queue = netdev_get_tx_queue(dev, i);
qdisc = qdisc_create_dflt(dev_queue, &pfifo_fast_ops,
qdisc = qdisc_create_dflt(dev_queue, default_qdisc_ops,
TC_H_MAKE(TC_H_MAJ(sch->handle),
TC_H_MIN(i + 1)));
if (qdisc == NULL) {
Expand Down

0 comments on commit 6da7c8f

Please sign in to comment.