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