Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

stephen hemminger and committed by
David S. Miller
6da7c8fc 7d7628f3

+112 -8
+13
Documentation/sysctl/net.txt
··· 50 50 it's a Per-CPU variable. 51 51 Default: 64 52 52 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 + 53 66 busy_read 54 67 ---------------- 55 68 Low latency busy poll timeout for socket reads. (needs CONFIG_NET_RX_BUSY_POLL)
+3
include/net/pkt_sched.h
··· 85 85 86 86 int register_qdisc(struct Qdisc_ops *qops); 87 87 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 + 88 91 void qdisc_list_del(struct Qdisc *q); 89 92 struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle); 90 93 struct Qdisc *qdisc_lookup_class(struct net_device *dev, u32 handle);
+1
include/net/sch_generic.h
··· 316 316 extern struct Qdisc_ops noop_qdisc_ops; 317 317 extern struct Qdisc_ops pfifo_fast_ops; 318 318 extern struct Qdisc_ops mq_qdisc_ops; 319 + extern const struct Qdisc_ops *default_qdisc_ops; 319 320 320 321 struct Qdisc_class_common { 321 322 u32 classid;
+29 -1
net/core/sysctl_net_core.c
··· 20 20 #include <net/sock.h> 21 21 #include <net/net_ratelimit.h> 22 22 #include <net/busy_poll.h> 23 + #include <net/pkt_sched.h> 23 24 24 25 static int zero = 0; 25 26 static int one = 1; ··· 194 193 } 195 194 #endif /* CONFIG_NET_FLOW_LIMIT */ 196 195 196 + #ifdef CONFIG_NET_SCHED 197 + static int set_default_qdisc(struct ctl_table *table, int write, 198 + void __user *buffer, size_t *lenp, loff_t *ppos) 199 + { 200 + char id[IFNAMSIZ]; 201 + struct ctl_table tbl = { 202 + .data = id, 203 + .maxlen = IFNAMSIZ, 204 + }; 205 + int ret; 206 + 207 + qdisc_get_default(id, IFNAMSIZ); 208 + 209 + ret = proc_dostring(&tbl, write, buffer, lenp, ppos); 210 + if (write && ret == 0) 211 + ret = qdisc_set_default(id); 212 + return ret; 213 + } 214 + #endif 215 + 197 216 static struct ctl_table net_core_table[] = { 198 217 #ifdef CONFIG_NET 199 218 { ··· 336 315 .mode = 0644, 337 316 .proc_handler = proc_dointvec 338 317 }, 339 - # 318 + #endif 319 + #ifdef CONFIG_NET_SCHED 320 + { 321 + .procname = "default_qdisc", 322 + .mode = 0644, 323 + .maxlen = IFNAMSIZ, 324 + .proc_handler = set_default_qdisc 325 + }, 340 326 #endif 341 327 #endif /* CONFIG_NET */ 342 328 {
+58
net/sched/sch_api.c
··· 131 131 ************************************************/ 132 132 133 133 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 + 134 139 /* The list of all installed queueing disciplines. */ 135 140 136 141 static struct Qdisc_ops *qdisc_base; ··· 204 199 return err; 205 200 } 206 201 EXPORT_SYMBOL(unregister_qdisc); 202 + 203 + /* Get default qdisc if not otherwise specified */ 204 + void qdisc_get_default(char *name, size_t len) 205 + { 206 + read_lock(&qdisc_mod_lock); 207 + strlcpy(name, default_qdisc_ops->id, len); 208 + read_unlock(&qdisc_mod_lock); 209 + } 210 + 211 + static struct Qdisc_ops *qdisc_lookup_default(const char *name) 212 + { 213 + struct Qdisc_ops *q = NULL; 214 + 215 + for (q = qdisc_base; q; q = q->next) { 216 + if (!strcmp(name, q->id)) { 217 + if (!try_module_get(q->owner)) 218 + q = NULL; 219 + break; 220 + } 221 + } 222 + 223 + return q; 224 + } 225 + 226 + /* Set new default qdisc to use */ 227 + int qdisc_set_default(const char *name) 228 + { 229 + const struct Qdisc_ops *ops; 230 + 231 + if (!capable(CAP_NET_ADMIN)) 232 + return -EPERM; 233 + 234 + write_lock(&qdisc_mod_lock); 235 + ops = qdisc_lookup_default(name); 236 + if (!ops) { 237 + /* Not found, drop lock and try to load module */ 238 + write_unlock(&qdisc_mod_lock); 239 + request_module("sch_%s", name); 240 + write_lock(&qdisc_mod_lock); 241 + 242 + ops = qdisc_lookup_default(name); 243 + } 244 + 245 + if (ops) { 246 + /* Set new default */ 247 + module_put(default_qdisc_ops->owner); 248 + default_qdisc_ops = ops; 249 + } 250 + write_unlock(&qdisc_mod_lock); 251 + 252 + return ops ? 0 : -ENOENT; 253 + } 207 254 208 255 /* We know handle. Find qdisc among all qdisc's attached to device 209 256 (root qdisc, all its children, children of children etc.) ··· 1911 1854 return err; 1912 1855 } 1913 1856 1857 + register_qdisc(&pfifo_fast_ops); 1914 1858 register_qdisc(&pfifo_qdisc_ops); 1915 1859 register_qdisc(&bfifo_qdisc_ops); 1916 1860 register_qdisc(&pfifo_head_drop_qdisc_ops);
+6 -5
net/sched/sch_generic.c
··· 530 530 .dump = pfifo_fast_dump, 531 531 .owner = THIS_MODULE, 532 532 }; 533 - EXPORT_SYMBOL(pfifo_fast_ops); 534 533 535 534 static struct lock_class_key qdisc_tx_busylock; 536 535 ··· 581 582 struct Qdisc_ops *ops, unsigned int parentid) 582 583 { 583 584 struct Qdisc *sch; 585 + 586 + if (!try_module_get(ops->owner)) 587 + goto errout; 584 588 585 589 sch = qdisc_alloc(dev_queue, ops); 586 590 if (IS_ERR(sch)) ··· 688 686 689 687 if (dev->tx_queue_len) { 690 688 qdisc = qdisc_create_dflt(dev_queue, 691 - &pfifo_fast_ops, TC_H_ROOT); 689 + default_qdisc_ops, TC_H_ROOT); 692 690 if (!qdisc) { 693 691 netdev_info(dev, "activation failed\n"); 694 692 return; ··· 741 739 int need_watchdog; 742 740 743 741 /* No queueing discipline is attached to device; 744 - create default one i.e. pfifo_fast for devices, 745 - which need queueing and noqueue_qdisc for 746 - virtual interfaces 742 + * create default one for devices, which need queueing 743 + * and noqueue_qdisc for virtual interfaces 747 744 */ 748 745 749 746 if (dev->qdisc == &noop_qdisc)
+1 -1
net/sched/sch_mq.c
··· 57 57 58 58 for (ntx = 0; ntx < dev->num_tx_queues; ntx++) { 59 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 61 TC_H_MAKE(TC_H_MAJ(sch->handle), 62 62 TC_H_MIN(ntx + 1))); 63 63 if (qdisc == NULL)
+1 -1
net/sched/sch_mqprio.c
··· 124 124 125 125 for (i = 0; i < dev->num_tx_queues; i++) { 126 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 128 TC_H_MAKE(TC_H_MAJ(sch->handle), 129 129 TC_H_MIN(i + 1))); 130 130 if (qdisc == NULL) {