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