• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/net/core/
1/* -*- 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>
10#include <linux/module.h>
11#include <linux/socket.h>
12#include <linux/netdevice.h>
13#include <linux/ratelimit.h>
14#include <linux/vmalloc.h>
15#include <linux/init.h>
16#include <linux/slab.h>
17
18#include <net/ip.h>
19#include <net/sock.h>
20
21#ifdef CONFIG_RPS
22static int rps_sock_flow_sysctl(ctl_table *table, int write,
23				void __user *buffer, size_t *lenp, loff_t *ppos)
24{
25	unsigned int orig_size, size;
26	int ret, i;
27	ctl_table tmp = {
28		.data = &size,
29		.maxlen = sizeof(size),
30		.mode = table->mode
31	};
32	struct rps_sock_flow_table *orig_sock_table, *sock_table;
33	static DEFINE_MUTEX(sock_flow_mutex);
34
35	mutex_lock(&sock_flow_mutex);
36
37	orig_sock_table = rps_sock_flow_table;
38	size = orig_size = orig_sock_table ? orig_sock_table->mask + 1 : 0;
39
40	ret = proc_dointvec(&tmp, write, buffer, lenp, ppos);
41
42	if (write) {
43		if (size) {
44			if (size > 1<<30) {
45				/* Enforce limit to prevent overflow */
46				mutex_unlock(&sock_flow_mutex);
47				return -EINVAL;
48			}
49			size = roundup_pow_of_two(size);
50			if (size != orig_size) {
51				sock_table =
52				    vmalloc(RPS_SOCK_FLOW_TABLE_SIZE(size));
53				if (!sock_table) {
54					mutex_unlock(&sock_flow_mutex);
55					return -ENOMEM;
56				}
57
58				sock_table->mask = size - 1;
59			} else
60				sock_table = orig_sock_table;
61
62			for (i = 0; i < size; i++)
63				sock_table->ents[i] = RPS_NO_CPU;
64		} else
65			sock_table = NULL;
66
67		if (sock_table != orig_sock_table) {
68			rcu_assign_pointer(rps_sock_flow_table, sock_table);
69			synchronize_rcu();
70			vfree(orig_sock_table);
71		}
72	}
73
74	mutex_unlock(&sock_flow_mutex);
75
76	return ret;
77}
78#endif /* CONFIG_RPS */
79
80static struct ctl_table net_core_table[] = {
81#ifdef CONFIG_NET
82	{
83		.procname	= "wmem_max",
84		.data		= &sysctl_wmem_max,
85		.maxlen		= sizeof(int),
86		.mode		= 0644,
87		.proc_handler	= proc_dointvec
88	},
89	{
90		.procname	= "rmem_max",
91		.data		= &sysctl_rmem_max,
92		.maxlen		= sizeof(int),
93		.mode		= 0644,
94		.proc_handler	= proc_dointvec
95	},
96	{
97		.procname	= "wmem_default",
98		.data		= &sysctl_wmem_default,
99		.maxlen		= sizeof(int),
100		.mode		= 0644,
101		.proc_handler	= proc_dointvec
102	},
103	{
104		.procname	= "rmem_default",
105		.data		= &sysctl_rmem_default,
106		.maxlen		= sizeof(int),
107		.mode		= 0644,
108		.proc_handler	= proc_dointvec
109	},
110	{
111		.procname	= "dev_weight",
112		.data		= &weight_p,
113		.maxlen		= sizeof(int),
114		.mode		= 0644,
115		.proc_handler	= proc_dointvec
116	},
117	{
118		.procname	= "netdev_max_backlog",
119		.data		= &netdev_max_backlog,
120		.maxlen		= sizeof(int),
121		.mode		= 0644,
122		.proc_handler	= proc_dointvec
123	},
124	{
125		.procname	= "netdev_tstamp_prequeue",
126		.data		= &netdev_tstamp_prequeue,
127		.maxlen		= sizeof(int),
128		.mode		= 0644,
129		.proc_handler	= proc_dointvec
130	},
131	{
132		.procname	= "message_cost",
133		.data		= &net_ratelimit_state.interval,
134		.maxlen		= sizeof(int),
135		.mode		= 0644,
136		.proc_handler	= proc_dointvec_jiffies,
137	},
138	{
139		.procname	= "message_burst",
140		.data		= &net_ratelimit_state.burst,
141		.maxlen		= sizeof(int),
142		.mode		= 0644,
143		.proc_handler	= proc_dointvec,
144	},
145	{
146		.procname	= "optmem_max",
147		.data		= &sysctl_optmem_max,
148		.maxlen		= sizeof(int),
149		.mode		= 0644,
150		.proc_handler	= proc_dointvec
151	},
152#ifdef CONFIG_RPS
153	{
154		.procname	= "rps_sock_flow_entries",
155		.maxlen		= sizeof(int),
156		.mode		= 0644,
157		.proc_handler	= rps_sock_flow_sysctl
158	},
159#endif
160#endif /* CONFIG_NET */
161	{
162		.procname	= "netdev_budget",
163		.data		= &netdev_budget,
164		.maxlen		= sizeof(int),
165		.mode		= 0644,
166		.proc_handler	= proc_dointvec
167	},
168	{
169		.procname	= "warnings",
170		.data		= &net_msg_warn,
171		.maxlen		= sizeof(int),
172		.mode		= 0644,
173		.proc_handler	= proc_dointvec
174	},
175	{ }
176};
177
178static struct ctl_table netns_core_table[] = {
179	{
180		.procname	= "somaxconn",
181		.data		= &init_net.core.sysctl_somaxconn,
182		.maxlen		= sizeof(int),
183		.mode		= 0644,
184		.proc_handler	= proc_dointvec
185	},
186	{ }
187};
188
189__net_initdata struct ctl_path net_core_path[] = {
190	{ .procname = "net", },
191	{ .procname = "core", },
192	{ },
193};
194
195static __net_init int sysctl_core_net_init(struct net *net)
196{
197	struct ctl_table *tbl;
198
199	net->core.sysctl_somaxconn = SOMAXCONN;
200
201	tbl = netns_core_table;
202	if (!net_eq(net, &init_net)) {
203		tbl = kmemdup(tbl, sizeof(netns_core_table), GFP_KERNEL);
204		if (tbl == NULL)
205			goto err_dup;
206
207		tbl[0].data = &net->core.sysctl_somaxconn;
208	}
209
210	net->core.sysctl_hdr = register_net_sysctl_table(net,
211			net_core_path, tbl);
212	if (net->core.sysctl_hdr == NULL)
213		goto err_reg;
214
215	return 0;
216
217err_reg:
218	if (tbl != netns_core_table)
219		kfree(tbl);
220err_dup:
221	return -ENOMEM;
222}
223
224static __net_exit void sysctl_core_net_exit(struct net *net)
225{
226	struct ctl_table *tbl;
227
228	tbl = net->core.sysctl_hdr->ctl_table_arg;
229	unregister_net_sysctl_table(net->core.sysctl_hdr);
230	BUG_ON(tbl == netns_core_table);
231	kfree(tbl);
232}
233
234static __net_initdata struct pernet_operations sysctl_core_ops = {
235	.init = sysctl_core_net_init,
236	.exit = sysctl_core_net_exit,
237};
238
239static __init int sysctl_core_init(void)
240{
241	static struct ctl_table empty[1];
242
243	register_sysctl_paths(net_core_path, empty);
244	register_net_sysctl_rotable(net_core_path, net_core_table);
245	return register_pernet_subsys(&sysctl_core_ops);
246}
247
248fs_initcall(sysctl_core_init);
249