aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/proc.c')
-rw-r--r--net/ipv6/proc.c125
1 files changed, 2 insertions, 123 deletions
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