blob: cfdb46ab3a7f866dd77957abc2f202d673c99bd5 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* -*- linux-c -*-
2 * sysctl_net_core.c: sysctl interface to net core subsystem.
3 *
4 * Begun April 1, 1996, Mike Shaver.
5 * Added /proc/sys/net/core directory entry (empty =) ). [MS]
6 */
7
8#include <linux/mm.h>
9#include <linux/sysctl.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010#include <linux/module.h>
Arnaldo Carvalho de Melo20380732005-08-16 02:18:02 -030011#include <linux/socket.h>
Pavel Emelyanova37ae402007-10-23 21:13:53 -070012#include <linux/netdevice.h>
Ingo Molnar3fff4c42009-09-22 16:18:09 +020013#include <linux/ratelimit.h>
Tom Herbertfec5e652010-04-16 16:01:27 -070014#include <linux/vmalloc.h>
Pavel Emelyanov33eb9cf2007-12-05 01:37:34 -080015#include <linux/init.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090016#include <linux/slab.h>
Shan Wei7426a562012-04-18 18:05:46 +000017#include <linux/kmemleak.h>
Ingo Molnar3fff4c42009-09-22 16:18:09 +020018
Hannes Eder63d819c2009-02-25 10:32:14 +000019#include <net/ip.h>
Arnaldo Carvalho de Melo20380732005-08-16 02:18:02 -030020#include <net/sock.h>
David S. Millerc5c177b2011-05-27 13:41:33 -040021#include <net/net_ratelimit.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070022
bingtian.ly@taobao.comcdda8892013-01-23 20:35:28 +000023static int one = 1;
24
Tom Herbertfec5e652010-04-16 16:01:27 -070025#ifdef CONFIG_RPS
26static int rps_sock_flow_sysctl(ctl_table *table, int write,
27 void __user *buffer, size_t *lenp, loff_t *ppos)
28{
29 unsigned int orig_size, size;
30 int ret, i;
31 ctl_table tmp = {
32 .data = &size,
33 .maxlen = sizeof(size),
34 .mode = table->mode
35 };
36 struct rps_sock_flow_table *orig_sock_table, *sock_table;
37 static DEFINE_MUTEX(sock_flow_mutex);
38
39 mutex_lock(&sock_flow_mutex);
40
Eric Dumazet6e3f7fa2010-10-25 03:02:02 +000041 orig_sock_table = rcu_dereference_protected(rps_sock_flow_table,
42 lockdep_is_held(&sock_flow_mutex));
Tom Herbertfec5e652010-04-16 16:01:27 -070043 size = orig_size = orig_sock_table ? orig_sock_table->mask + 1 : 0;
44
45 ret = proc_dointvec(&tmp, write, buffer, lenp, ppos);
46
47 if (write) {
48 if (size) {
49 if (size > 1<<30) {
50 /* Enforce limit to prevent overflow */
51 mutex_unlock(&sock_flow_mutex);
52 return -EINVAL;
53 }
54 size = roundup_pow_of_two(size);
55 if (size != orig_size) {
56 sock_table =
57 vmalloc(RPS_SOCK_FLOW_TABLE_SIZE(size));
58 if (!sock_table) {
59 mutex_unlock(&sock_flow_mutex);
60 return -ENOMEM;
61 }
62
63 sock_table->mask = size - 1;
64 } else
65 sock_table = orig_sock_table;
66
67 for (i = 0; i < size; i++)
68 sock_table->ents[i] = RPS_NO_CPU;
69 } else
70 sock_table = NULL;
71
72 if (sock_table != orig_sock_table) {
73 rcu_assign_pointer(rps_sock_flow_table, sock_table);
Eric Dumazetadc93002011-11-17 03:13:26 +000074 if (sock_table)
Ingo Molnarc5905af2012-02-24 08:31:31 +010075 static_key_slow_inc(&rps_needed);
Eric Dumazetadc93002011-11-17 03:13:26 +000076 if (orig_sock_table) {
Ingo Molnarc5905af2012-02-24 08:31:31 +010077 static_key_slow_dec(&rps_needed);
Eric Dumazetadc93002011-11-17 03:13:26 +000078 synchronize_rcu();
79 vfree(orig_sock_table);
80 }
Tom Herbertfec5e652010-04-16 16:01:27 -070081 }
82 }
83
84 mutex_unlock(&sock_flow_mutex);
85
86 return ret;
87}
88#endif /* CONFIG_RPS */
89
Pavel Emelyanov33eb9cf2007-12-05 01:37:34 -080090static struct ctl_table net_core_table[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070091#ifdef CONFIG_NET
92 {
Linus Torvalds1da177e2005-04-16 15:20:36 -070093 .procname = "wmem_max",
94 .data = &sysctl_wmem_max,
95 .maxlen = sizeof(int),
96 .mode = 0644,
bingtian.ly@taobao.comcdda8892013-01-23 20:35:28 +000097 .proc_handler = proc_dointvec_minmax,
98 .extra1 = &one,
Linus Torvalds1da177e2005-04-16 15:20:36 -070099 },
100 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101 .procname = "rmem_max",
102 .data = &sysctl_rmem_max,
103 .maxlen = sizeof(int),
104 .mode = 0644,
bingtian.ly@taobao.comcdda8892013-01-23 20:35:28 +0000105 .proc_handler = proc_dointvec_minmax,
106 .extra1 = &one,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 },
108 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 .procname = "wmem_default",
110 .data = &sysctl_wmem_default,
111 .maxlen = sizeof(int),
112 .mode = 0644,
bingtian.ly@taobao.comcdda8892013-01-23 20:35:28 +0000113 .proc_handler = proc_dointvec_minmax,
114 .extra1 = &one,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 },
116 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 .procname = "rmem_default",
118 .data = &sysctl_rmem_default,
119 .maxlen = sizeof(int),
120 .mode = 0644,
bingtian.ly@taobao.comcdda8892013-01-23 20:35:28 +0000121 .proc_handler = proc_dointvec_minmax,
122 .extra1 = &one,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123 },
124 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 .procname = "dev_weight",
126 .data = &weight_p,
127 .maxlen = sizeof(int),
128 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -0800129 .proc_handler = proc_dointvec
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130 },
131 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132 .procname = "netdev_max_backlog",
133 .data = &netdev_max_backlog,
134 .maxlen = sizeof(int),
135 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -0800136 .proc_handler = proc_dointvec
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 },
Eric Dumazet0a148422011-04-20 09:27:32 +0000138#ifdef CONFIG_BPF_JIT
139 {
140 .procname = "bpf_jit_enable",
141 .data = &bpf_jit_enable,
142 .maxlen = sizeof(int),
143 .mode = 0644,
144 .proc_handler = proc_dointvec
145 },
146#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 {
Eric Dumazet3b098e22010-05-15 23:57:10 -0700148 .procname = "netdev_tstamp_prequeue",
149 .data = &netdev_tstamp_prequeue,
150 .maxlen = sizeof(int),
151 .mode = 0644,
152 .proc_handler = proc_dointvec
153 },
154 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 .procname = "message_cost",
Dave Young717115e2008-07-25 01:45:58 -0700156 .data = &net_ratelimit_state.interval,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 .maxlen = sizeof(int),
158 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -0800159 .proc_handler = proc_dointvec_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 },
161 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 .procname = "message_burst",
Dave Young717115e2008-07-25 01:45:58 -0700163 .data = &net_ratelimit_state.burst,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 .maxlen = sizeof(int),
165 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -0800166 .proc_handler = proc_dointvec,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 },
168 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 .procname = "optmem_max",
170 .data = &sysctl_optmem_max,
171 .maxlen = sizeof(int),
172 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -0800173 .proc_handler = proc_dointvec
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 },
Tom Herbertfec5e652010-04-16 16:01:27 -0700175#ifdef CONFIG_RPS
176 {
177 .procname = "rps_sock_flow_entries",
178 .maxlen = sizeof(int),
179 .mode = 0644,
180 .proc_handler = rps_sock_flow_sysctl
181 },
182#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183#endif /* CONFIG_NET */
184 {
Stephen Hemminger51b0bde2005-06-23 20:14:40 -0700185 .procname = "netdev_budget",
186 .data = &netdev_budget,
187 .maxlen = sizeof(int),
188 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -0800189 .proc_handler = proc_dointvec
Stephen Hemminger51b0bde2005-06-23 20:14:40 -0700190 },
Stephen Hemmingera2a316f2007-03-08 20:41:08 -0800191 {
Stephen Hemmingera2a316f2007-03-08 20:41:08 -0800192 .procname = "warnings",
193 .data = &net_msg_warn,
194 .maxlen = sizeof(int),
195 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -0800196 .proc_handler = proc_dointvec
Stephen Hemmingera2a316f2007-03-08 20:41:08 -0800197 },
Eric W. Biedermanf8572d82009-11-05 13:32:03 -0800198 { }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199};
Pavel Emelyanov33eb9cf2007-12-05 01:37:34 -0800200
Pavel Emelyanovd5a45022008-05-19 13:49:52 -0700201static struct ctl_table netns_core_table[] = {
202 {
Pavel Emelyanovd5a45022008-05-19 13:49:52 -0700203 .procname = "somaxconn",
204 .data = &init_net.core.sysctl_somaxconn,
205 .maxlen = sizeof(int),
206 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -0800207 .proc_handler = proc_dointvec
Pavel Emelyanovd5a45022008-05-19 13:49:52 -0700208 },
Eric W. Biedermanf8572d82009-11-05 13:32:03 -0800209 { }
Pavel Emelyanovd5a45022008-05-19 13:49:52 -0700210};
211
Pavel Emelyanov024626e2007-12-08 00:09:24 -0800212static __net_init int sysctl_core_net_init(struct net *net)
213{
Pavel Emelyanovd5a45022008-05-19 13:49:52 -0700214 struct ctl_table *tbl;
Pavel Emelyanov024626e2007-12-08 00:09:24 -0800215
Pavel Emelyanov8efa6e92008-03-31 19:41:14 -0700216 net->core.sysctl_somaxconn = SOMAXCONN;
Pavel Emelyanovb8e1f9b2007-12-08 00:12:33 -0800217
Pavel Emelyanovd5a45022008-05-19 13:49:52 -0700218 tbl = netns_core_table;
Octavian Purdila09ad9bc2009-11-25 15:14:13 -0800219 if (!net_eq(net, &init_net)) {
Pavel Emelyanovd5a45022008-05-19 13:49:52 -0700220 tbl = kmemdup(tbl, sizeof(netns_core_table), GFP_KERNEL);
Pavel Emelyanov024626e2007-12-08 00:09:24 -0800221 if (tbl == NULL)
222 goto err_dup;
223
Pavel Emelyanovd5a45022008-05-19 13:49:52 -0700224 tbl[0].data = &net->core.sysctl_somaxconn;
Eric W. Biederman464dc802012-11-16 03:02:59 +0000225
226 /* Don't export any sysctls to unprivileged users */
227 if (net->user_ns != &init_user_ns) {
228 tbl[0].procname = NULL;
229 }
Pavel Emelyanov024626e2007-12-08 00:09:24 -0800230 }
231
Eric W. Biedermanec8f23c2012-04-19 13:44:49 +0000232 net->core.sysctl_hdr = register_net_sysctl(net, "net/core", tbl);
Pavel Emelyanov8efa6e92008-03-31 19:41:14 -0700233 if (net->core.sysctl_hdr == NULL)
Pavel Emelyanov024626e2007-12-08 00:09:24 -0800234 goto err_reg;
235
236 return 0;
237
238err_reg:
Pavel Emelyanovd5a45022008-05-19 13:49:52 -0700239 if (tbl != netns_core_table)
Pavel Emelyanov024626e2007-12-08 00:09:24 -0800240 kfree(tbl);
241err_dup:
242 return -ENOMEM;
243}
244
245static __net_exit void sysctl_core_net_exit(struct net *net)
246{
247 struct ctl_table *tbl;
248
Pavel Emelyanov8efa6e92008-03-31 19:41:14 -0700249 tbl = net->core.sysctl_hdr->ctl_table_arg;
250 unregister_net_sysctl_table(net->core.sysctl_hdr);
Pavel Emelyanovd5a45022008-05-19 13:49:52 -0700251 BUG_ON(tbl == netns_core_table);
Pavel Emelyanov024626e2007-12-08 00:09:24 -0800252 kfree(tbl);
253}
254
255static __net_initdata struct pernet_operations sysctl_core_ops = {
256 .init = sysctl_core_net_init,
257 .exit = sysctl_core_net_exit,
258};
259
Pavel Emelyanov33eb9cf2007-12-05 01:37:34 -0800260static __init int sysctl_core_init(void)
261{
Eric W. Biederman43444752012-04-19 13:22:55 +0000262 register_net_sysctl(&init_net, "net/core", net_core_table);
Pavel Emelyanov024626e2007-12-08 00:09:24 -0800263 return register_pernet_subsys(&sysctl_core_ops);
Pavel Emelyanov33eb9cf2007-12-05 01:37:34 -0800264}
265
Alexey Dobriyanb27aead2008-11-25 18:00:48 -0800266fs_initcall(sysctl_core_init);