aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/ipv6.h20
-rw-r--r--net/ipv6/Makefile3
-rw-r--r--net/ipv6/addrconf.c60
-rw-r--r--net/ipv6/af_inet6.c30
-rw-r--r--net/ipv6/proc.c125
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
169int snmp6_register_dev(struct inet6_dev *idev);
170int snmp6_unregister_dev(struct inet6_dev *idev);
171int snmp6_alloc_dev(struct inet6_dev *idev);
172int snmp6_free_dev(struct inet6_dev *idev);
173int snmp6_mib_init(void *ptr[2], size_t mibsize, size_t mibalign);
174void snmp6_mib_free(void *ptr[2]);
175void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, int bytes);
176
177struct ip6_ra_chain 169struct 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);
606extern void udplite6_proc_exit(void); 598extern void udplite6_proc_exit(void);
607extern int ipv6_misc_proc_init(void); 599extern int ipv6_misc_proc_init(void);
608extern void ipv6_misc_proc_exit(void); 600extern void ipv6_misc_proc_exit(void);
601extern int snmp6_register_dev(struct inet6_dev *idev);
602extern int snmp6_unregister_dev(struct inet6_dev *idev);
609 603
610extern struct rt6_statistics rt6_stats; 604extern struct rt6_statistics rt6_stats;
605#else
606static inline int snmp6_register_dev(struct inet6_dev *idev)
607{
608 return 0;
609}
610
611static 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
7ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \ 7ipv6-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
13ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \ 13ipv6-$(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
28obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o 28obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o
29obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o 29obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o
30obj-$(CONFIG_NETFILTER) += netfilter/ 30obj-$(CONFIG_NETFILTER) += netfilter/
31obj-$(CONFIG_PROC_FS) += proc.o
31 32
32obj-$(CONFIG_IPV6_SIT) += sit.o 33obj-$(CONFIG_IPV6_SIT) += sit.o
33obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o 34obj-$(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
250static 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
268err_icmp:
269 snmp_mib_free((void **)idev->stats.ipv6);
270err_ip:
271 return err;
272}
273
274static 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
251static void in6_dev_finish_destroy_rcu(struct rcu_head *head) 283static 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
3473static 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
3488static 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
3441static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, 3501static 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
715static int __init init_ipv6_mibs(void) 715static 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
731err_udplite_mib: 731err_udplite_mib:
732 snmp6_mib_free((void **)udp_stats_in6); 732 snmp_mib_free((void **)udp_stats_in6);
733err_udp_mib: 733err_udp_mib:
734 snmp6_mib_free((void **)icmpv6_statistics); 734 snmp_mib_free((void **)icmpv6_statistics);
735err_icmp_mib: 735err_icmp_mib:
736 snmp6_mib_free((void **)ipv6_statistics); 736 snmp_mib_free((void **)ipv6_statistics);
737err_ip_mib: 737err_ip_mib:
738 return -ENOMEM; 738 return -ENOMEM;
739 739
@@ -741,10 +741,10 @@ err_ip_mib:
741 741
742static void cleanup_ipv6_mibs(void) 742static 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
750static int __init inet6_init(void) 750static 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
33static struct proc_dir_entry *proc_net_devsnmp6; 32static struct proc_dir_entry *proc_net_devsnmp6;
34 33
35static int fold_prot_inuse(struct proto *proto) 34static 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
147static unsigned long
148fold_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
161static inline void 145static inline void
162snmp6_seq_show_item(struct seq_file *seq, void **mib, struct snmp_mib *itemlist) 146snmp6_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
170static int snmp6_seq_show(struct seq_file *seq, void *v) 154static 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
214static 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
229void
230snmp6_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
243int snmp6_register_dev(struct inet6_dev *idev) 197int 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
310int snmp6_register_dev(struct inet6_dev *idev)
311{
312 return 0;
313}
314
315int snmp6_unregister_dev(struct inet6_dev *idev)
316{
317 return 0;
318}
319
320#endif /* CONFIG_PROC_FS */
321
322int 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
338err_icmp:
339 snmp6_mib_free((void **)idev->stats.ipv6);
340err_ip:
341 return err;
342}
343
344int 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
351int 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
366err1:
367 free_percpu(ptr[0]);
368 ptr[0] = NULL;
369err0:
370 return -ENOMEM;
371}
372
373void 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