diff options
-rw-r--r-- | include/net/ipv6.h | 20 | ||||
-rw-r--r-- | net/ipv6/Makefile | 3 | ||||
-rw-r--r-- | net/ipv6/addrconf.c | 60 | ||||
-rw-r--r-- | net/ipv6/af_inet6.c | 30 | ||||
-rw-r--r-- | net/ipv6/proc.c | 125 |
5 files changed, 91 insertions, 147 deletions
diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 4408def379bf..f70afef9c3cc 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h | |||
@@ -166,14 +166,6 @@ DECLARE_SNMP_STAT(struct udp_mib, udplite_stats_in6); | |||
166 | if (is_udplite) SNMP_INC_STATS_USER(udplite_stats_in6, field); \ | 166 | if (is_udplite) SNMP_INC_STATS_USER(udplite_stats_in6, field); \ |
167 | else SNMP_INC_STATS_USER(udp_stats_in6, field); } while(0) | 167 | else SNMP_INC_STATS_USER(udp_stats_in6, field); } while(0) |
168 | 168 | ||
169 | int snmp6_register_dev(struct inet6_dev *idev); | ||
170 | int snmp6_unregister_dev(struct inet6_dev *idev); | ||
171 | int snmp6_alloc_dev(struct inet6_dev *idev); | ||
172 | int snmp6_free_dev(struct inet6_dev *idev); | ||
173 | int snmp6_mib_init(void *ptr[2], size_t mibsize, size_t mibalign); | ||
174 | void snmp6_mib_free(void *ptr[2]); | ||
175 | void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, int bytes); | ||
176 | |||
177 | struct ip6_ra_chain | 169 | struct ip6_ra_chain |
178 | { | 170 | { |
179 | struct ip6_ra_chain *next; | 171 | struct ip6_ra_chain *next; |
@@ -606,8 +598,20 @@ extern int udplite6_proc_init(void); | |||
606 | extern void udplite6_proc_exit(void); | 598 | extern void udplite6_proc_exit(void); |
607 | extern int ipv6_misc_proc_init(void); | 599 | extern int ipv6_misc_proc_init(void); |
608 | extern void ipv6_misc_proc_exit(void); | 600 | extern void ipv6_misc_proc_exit(void); |
601 | extern int snmp6_register_dev(struct inet6_dev *idev); | ||
602 | extern int snmp6_unregister_dev(struct inet6_dev *idev); | ||
609 | 603 | ||
610 | extern struct rt6_statistics rt6_stats; | 604 | extern struct rt6_statistics rt6_stats; |
605 | #else | ||
606 | static inline int snmp6_register_dev(struct inet6_dev *idev) | ||
607 | { | ||
608 | return 0; | ||
609 | } | ||
610 | |||
611 | static inline int snmp6_unregister_dev(struct inet6_dev *idev) | ||
612 | { | ||
613 | return 0; | ||
614 | } | ||
611 | #endif | 615 | #endif |
612 | 616 | ||
613 | #ifdef CONFIG_SYSCTL | 617 | #ifdef CONFIG_SYSCTL |
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index e9478688c3d3..0acf64dc5775 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile | |||
@@ -7,7 +7,7 @@ obj-$(CONFIG_IPV6) += ipv6.o | |||
7 | ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \ | 7 | ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \ |
8 | route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \ | 8 | route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \ |
9 | raw.o protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ | 9 | raw.o protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ |
10 | exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \ | 10 | exthdrs.o sysctl_net_ipv6.o datagram.o \ |
11 | ip6_flowlabel.o inet6_connection_sock.o | 11 | ip6_flowlabel.o inet6_connection_sock.o |
12 | 12 | ||
13 | ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \ | 13 | ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \ |
@@ -28,6 +28,7 @@ obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o | |||
28 | obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o | 28 | obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o |
29 | obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o | 29 | obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o |
30 | obj-$(CONFIG_NETFILTER) += netfilter/ | 30 | obj-$(CONFIG_NETFILTER) += netfilter/ |
31 | obj-$(CONFIG_PROC_FS) += proc.o | ||
31 | 32 | ||
32 | obj-$(CONFIG_IPV6_SIT) += sit.o | 33 | obj-$(CONFIG_IPV6_SIT) += sit.o |
33 | obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o | 34 | obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 33ccc95c349b..ea86bf4bfe0a 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -81,6 +81,7 @@ | |||
81 | #endif | 81 | #endif |
82 | 82 | ||
83 | #include <asm/uaccess.h> | 83 | #include <asm/uaccess.h> |
84 | #include <asm/unaligned.h> | ||
84 | 85 | ||
85 | #include <linux/proc_fs.h> | 86 | #include <linux/proc_fs.h> |
86 | #include <linux/seq_file.h> | 87 | #include <linux/seq_file.h> |
@@ -246,6 +247,37 @@ static void addrconf_mod_timer(struct inet6_ifaddr *ifp, | |||
246 | add_timer(&ifp->timer); | 247 | add_timer(&ifp->timer); |
247 | } | 248 | } |
248 | 249 | ||
250 | static int snmp6_alloc_dev(struct inet6_dev *idev) | ||
251 | { | ||
252 | int err = -ENOMEM; | ||
253 | |||
254 | if (!idev || !idev->dev) | ||
255 | return -EINVAL; | ||
256 | |||
257 | if (snmp_mib_init((void **)idev->stats.ipv6, | ||
258 | sizeof(struct ipstats_mib), | ||
259 | __alignof__(struct ipstats_mib)) < 0) | ||
260 | goto err_ip; | ||
261 | if (snmp_mib_init((void **)idev->stats.icmpv6, | ||
262 | sizeof(struct icmpv6_mib), | ||
263 | __alignof__(struct icmpv6_mib)) < 0) | ||
264 | goto err_icmp; | ||
265 | |||
266 | return 0; | ||
267 | |||
268 | err_icmp: | ||
269 | snmp_mib_free((void **)idev->stats.ipv6); | ||
270 | err_ip: | ||
271 | return err; | ||
272 | } | ||
273 | |||
274 | static int snmp6_free_dev(struct inet6_dev *idev) | ||
275 | { | ||
276 | snmp_mib_free((void **)idev->stats.icmpv6); | ||
277 | snmp_mib_free((void **)idev->stats.ipv6); | ||
278 | return 0; | ||
279 | } | ||
280 | |||
249 | /* Nobody refers to this device, we may destroy it. */ | 281 | /* Nobody refers to this device, we may destroy it. */ |
250 | 282 | ||
251 | static void in6_dev_finish_destroy_rcu(struct rcu_head *head) | 283 | static void in6_dev_finish_destroy_rcu(struct rcu_head *head) |
@@ -3438,6 +3470,34 @@ static inline size_t inet6_if_nlmsg_size(void) | |||
3438 | ); | 3470 | ); |
3439 | } | 3471 | } |
3440 | 3472 | ||
3473 | static inline void __snmp6_fill_stats(u64 *stats, void **mib, int items, | ||
3474 | int bytes) | ||
3475 | { | ||
3476 | int i; | ||
3477 | int pad = bytes - sizeof(u64) * items; | ||
3478 | BUG_ON(pad < 0); | ||
3479 | |||
3480 | /* Use put_unaligned() because stats may not be aligned for u64. */ | ||
3481 | put_unaligned(items, &stats[0]); | ||
3482 | for (i = 1; i < items; i++) | ||
3483 | put_unaligned(snmp_fold_field(mib, i), &stats[i]); | ||
3484 | |||
3485 | memset(&stats[items], 0, pad); | ||
3486 | } | ||
3487 | |||
3488 | static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, | ||
3489 | int bytes) | ||
3490 | { | ||
3491 | switch(attrtype) { | ||
3492 | case IFLA_INET6_STATS: | ||
3493 | __snmp6_fill_stats(stats, (void **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes); | ||
3494 | break; | ||
3495 | case IFLA_INET6_ICMP6STATS: | ||
3496 | __snmp6_fill_stats(stats, (void **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes); | ||
3497 | break; | ||
3498 | } | ||
3499 | } | ||
3500 | |||
3441 | static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, | 3501 | static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, |
3442 | u32 pid, u32 seq, int event, unsigned int flags) | 3502 | u32 pid, u32 seq, int event, unsigned int flags) |
3443 | { | 3503 | { |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 825d03e87ae0..18cb928c8d92 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -714,26 +714,26 @@ EXPORT_SYMBOL_GPL(ipv6_opt_accepted); | |||
714 | 714 | ||
715 | static int __init init_ipv6_mibs(void) | 715 | static int __init init_ipv6_mibs(void) |
716 | { | 716 | { |
717 | if (snmp6_mib_init((void **)ipv6_statistics, sizeof (struct ipstats_mib), | 717 | if (snmp_mib_init((void **)ipv6_statistics, sizeof (struct ipstats_mib), |
718 | __alignof__(struct ipstats_mib)) < 0) | 718 | __alignof__(struct ipstats_mib)) < 0) |
719 | goto err_ip_mib; | 719 | goto err_ip_mib; |
720 | if (snmp6_mib_init((void **)icmpv6_statistics, sizeof (struct icmpv6_mib), | 720 | if (snmp_mib_init((void **)icmpv6_statistics, sizeof (struct icmpv6_mib), |
721 | __alignof__(struct icmpv6_mib)) < 0) | 721 | __alignof__(struct icmpv6_mib)) < 0) |
722 | goto err_icmp_mib; | 722 | goto err_icmp_mib; |
723 | if (snmp6_mib_init((void **)udp_stats_in6, sizeof (struct udp_mib), | 723 | if (snmp_mib_init((void **)udp_stats_in6, sizeof (struct udp_mib), |
724 | __alignof__(struct udp_mib)) < 0) | 724 | __alignof__(struct udp_mib)) < 0) |
725 | goto err_udp_mib; | 725 | goto err_udp_mib; |
726 | if (snmp6_mib_init((void **)udplite_stats_in6, sizeof (struct udp_mib), | 726 | if (snmp_mib_init((void **)udplite_stats_in6, sizeof (struct udp_mib), |
727 | __alignof__(struct udp_mib)) < 0) | 727 | __alignof__(struct udp_mib)) < 0) |
728 | goto err_udplite_mib; | 728 | goto err_udplite_mib; |
729 | return 0; | 729 | return 0; |
730 | 730 | ||
731 | err_udplite_mib: | 731 | err_udplite_mib: |
732 | snmp6_mib_free((void **)udp_stats_in6); | 732 | snmp_mib_free((void **)udp_stats_in6); |
733 | err_udp_mib: | 733 | err_udp_mib: |
734 | snmp6_mib_free((void **)icmpv6_statistics); | 734 | snmp_mib_free((void **)icmpv6_statistics); |
735 | err_icmp_mib: | 735 | err_icmp_mib: |
736 | snmp6_mib_free((void **)ipv6_statistics); | 736 | snmp_mib_free((void **)ipv6_statistics); |
737 | err_ip_mib: | 737 | err_ip_mib: |
738 | return -ENOMEM; | 738 | return -ENOMEM; |
739 | 739 | ||
@@ -741,10 +741,10 @@ err_ip_mib: | |||
741 | 741 | ||
742 | static void cleanup_ipv6_mibs(void) | 742 | static void cleanup_ipv6_mibs(void) |
743 | { | 743 | { |
744 | snmp6_mib_free((void **)ipv6_statistics); | 744 | snmp_mib_free((void **)ipv6_statistics); |
745 | snmp6_mib_free((void **)icmpv6_statistics); | 745 | snmp_mib_free((void **)icmpv6_statistics); |
746 | snmp6_mib_free((void **)udp_stats_in6); | 746 | snmp_mib_free((void **)udp_stats_in6); |
747 | snmp6_mib_free((void **)udplite_stats_in6); | 747 | snmp_mib_free((void **)udplite_stats_in6); |
748 | } | 748 | } |
749 | 749 | ||
750 | static int __init inet6_init(void) | 750 | static int __init inet6_init(void) |
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 7a00bedb6b93..acb306a5dd56 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c | |||
@@ -23,13 +23,12 @@ | |||
23 | #include <linux/proc_fs.h> | 23 | #include <linux/proc_fs.h> |
24 | #include <linux/seq_file.h> | 24 | #include <linux/seq_file.h> |
25 | #include <linux/stddef.h> | 25 | #include <linux/stddef.h> |
26 | #include <asm/unaligned.h> | 26 | #include <net/ip.h> |
27 | #include <net/sock.h> | 27 | #include <net/sock.h> |
28 | #include <net/tcp.h> | 28 | #include <net/tcp.h> |
29 | #include <net/transp_v6.h> | 29 | #include <net/transp_v6.h> |
30 | #include <net/ipv6.h> | 30 | #include <net/ipv6.h> |
31 | 31 | ||
32 | #ifdef CONFIG_PROC_FS | ||
33 | static struct proc_dir_entry *proc_net_devsnmp6; | 32 | static struct proc_dir_entry *proc_net_devsnmp6; |
34 | 33 | ||
35 | static int fold_prot_inuse(struct proto *proto) | 34 | static int fold_prot_inuse(struct proto *proto) |
@@ -142,29 +141,14 @@ static struct snmp_mib snmp6_udplite6_list[] = { | |||
142 | SNMP_MIB_ITEM("UdpLite6OutDatagrams", UDP_MIB_OUTDATAGRAMS), | 141 | SNMP_MIB_ITEM("UdpLite6OutDatagrams", UDP_MIB_OUTDATAGRAMS), |
143 | SNMP_MIB_SENTINEL | 142 | SNMP_MIB_SENTINEL |
144 | }; | 143 | }; |
145 | #endif /* CONFIG_PROC_FS */ | ||
146 | 144 | ||
147 | static unsigned long | ||
148 | fold_field(void *mib[], int offt) | ||
149 | { | ||
150 | unsigned long res = 0; | ||
151 | int i; | ||
152 | |||
153 | for_each_possible_cpu(i) { | ||
154 | res += *(((unsigned long *)per_cpu_ptr(mib[0], i)) + offt); | ||
155 | res += *(((unsigned long *)per_cpu_ptr(mib[1], i)) + offt); | ||
156 | } | ||
157 | return res; | ||
158 | } | ||
159 | |||
160 | #ifdef CONFIG_PROC_FS | ||
161 | static inline void | 145 | static inline void |
162 | snmp6_seq_show_item(struct seq_file *seq, void **mib, struct snmp_mib *itemlist) | 146 | snmp6_seq_show_item(struct seq_file *seq, void **mib, struct snmp_mib *itemlist) |
163 | { | 147 | { |
164 | int i; | 148 | int i; |
165 | for (i=0; itemlist[i].name; i++) | 149 | for (i=0; itemlist[i].name; i++) |
166 | seq_printf(seq, "%-32s\t%lu\n", itemlist[i].name, | 150 | seq_printf(seq, "%-32s\t%lu\n", itemlist[i].name, |
167 | fold_field(mib, itemlist[i].entry)); | 151 | snmp_fold_field(mib, itemlist[i].entry)); |
168 | } | 152 | } |
169 | 153 | ||
170 | static int snmp6_seq_show(struct seq_file *seq, void *v) | 154 | static int snmp6_seq_show(struct seq_file *seq, void *v) |
@@ -209,37 +193,7 @@ static const struct file_operations snmp6_seq_fops = { | |||
209 | .llseek = seq_lseek, | 193 | .llseek = seq_lseek, |
210 | .release = single_release, | 194 | .release = single_release, |
211 | }; | 195 | }; |
212 | #endif /* CONFIG_PROC_FS */ | ||
213 | 196 | ||
214 | static inline void | ||
215 | __snmp6_fill_stats(u64 *stats, void **mib, int items, int bytes) | ||
216 | { | ||
217 | int i; | ||
218 | int pad = bytes - sizeof(u64) * items; | ||
219 | BUG_ON(pad < 0); | ||
220 | |||
221 | /* Use put_unaligned() because stats may not be aligned for u64. */ | ||
222 | put_unaligned(items, &stats[0]); | ||
223 | for (i = 1; i < items; i++) | ||
224 | put_unaligned(fold_field(mib, i), &stats[i]); | ||
225 | |||
226 | memset(&stats[items], 0, pad); | ||
227 | } | ||
228 | |||
229 | void | ||
230 | snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, int bytes) | ||
231 | { | ||
232 | switch(attrtype) { | ||
233 | case IFLA_INET6_STATS: | ||
234 | __snmp6_fill_stats(stats, (void **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes); | ||
235 | break; | ||
236 | case IFLA_INET6_ICMP6STATS: | ||
237 | __snmp6_fill_stats(stats, (void **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes); | ||
238 | break; | ||
239 | } | ||
240 | } | ||
241 | |||
242 | #ifdef CONFIG_PROC_FS | ||
243 | int snmp6_register_dev(struct inet6_dev *idev) | 197 | int snmp6_register_dev(struct inet6_dev *idev) |
244 | { | 198 | { |
245 | struct proc_dir_entry *p; | 199 | struct proc_dir_entry *p; |
@@ -304,78 +258,3 @@ void ipv6_misc_proc_exit(void) | |||
304 | proc_net_remove("snmp6"); | 258 | proc_net_remove("snmp6"); |
305 | } | 259 | } |
306 | 260 | ||
307 | #else /* CONFIG_PROC_FS */ | ||
308 | |||
309 | |||
310 | int snmp6_register_dev(struct inet6_dev *idev) | ||
311 | { | ||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | int snmp6_unregister_dev(struct inet6_dev *idev) | ||
316 | { | ||
317 | return 0; | ||
318 | } | ||
319 | |||
320 | #endif /* CONFIG_PROC_FS */ | ||
321 | |||
322 | int snmp6_alloc_dev(struct inet6_dev *idev) | ||
323 | { | ||
324 | int err = -ENOMEM; | ||
325 | |||
326 | if (!idev || !idev->dev) | ||
327 | return -EINVAL; | ||
328 | |||
329 | if (snmp6_mib_init((void **)idev->stats.ipv6, sizeof(struct ipstats_mib), | ||
330 | __alignof__(struct ipstats_mib)) < 0) | ||
331 | goto err_ip; | ||
332 | if (snmp6_mib_init((void **)idev->stats.icmpv6, sizeof(struct icmpv6_mib), | ||
333 | __alignof__(struct icmpv6_mib)) < 0) | ||
334 | goto err_icmp; | ||
335 | |||
336 | return 0; | ||
337 | |||
338 | err_icmp: | ||
339 | snmp6_mib_free((void **)idev->stats.ipv6); | ||
340 | err_ip: | ||
341 | return err; | ||
342 | } | ||
343 | |||
344 | int snmp6_free_dev(struct inet6_dev *idev) | ||
345 | { | ||
346 | snmp6_mib_free((void **)idev->stats.icmpv6); | ||
347 | snmp6_mib_free((void **)idev->stats.ipv6); | ||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | int snmp6_mib_init(void *ptr[2], size_t mibsize, size_t mibalign) | ||
352 | { | ||
353 | if (ptr == NULL) | ||
354 | return -EINVAL; | ||
355 | |||
356 | ptr[0] = __alloc_percpu(mibsize); | ||
357 | if (!ptr[0]) | ||
358 | goto err0; | ||
359 | |||
360 | ptr[1] = __alloc_percpu(mibsize); | ||
361 | if (!ptr[1]) | ||
362 | goto err1; | ||
363 | |||
364 | return 0; | ||
365 | |||
366 | err1: | ||
367 | free_percpu(ptr[0]); | ||
368 | ptr[0] = NULL; | ||
369 | err0: | ||
370 | return -ENOMEM; | ||
371 | } | ||
372 | |||
373 | void snmp6_mib_free(void *ptr[2]) | ||
374 | { | ||
375 | if (ptr == NULL) | ||
376 | return; | ||
377 | free_percpu(ptr[0]); | ||
378 | free_percpu(ptr[1]); | ||
379 | ptr[0] = ptr[1] = NULL; | ||
380 | } | ||
381 | |||