Commit cb319625 authored by Hideaki Yoshifuji's avatar Hideaki Yoshifuji

[IPV6]: SNMP6 clean-up.

parent ea1499aa
...@@ -106,6 +106,7 @@ struct frag_hdr { ...@@ -106,6 +106,7 @@ struct frag_hdr {
/* sysctls */ /* sysctls */
extern int sysctl_ipv6_bindv6only; extern int sysctl_ipv6_bindv6only;
/* MIBs */
DECLARE_SNMP_STAT(struct ipv6_mib, ipv6_statistics); DECLARE_SNMP_STAT(struct ipv6_mib, ipv6_statistics);
#define IP6_INC_STATS(field) SNMP_INC_STATS(ipv6_statistics, field) #define IP6_INC_STATS(field) SNMP_INC_STATS(ipv6_statistics, field)
#define IP6_INC_STATS_BH(field) SNMP_INC_STATS_BH(ipv6_statistics, field) #define IP6_INC_STATS_BH(field) SNMP_INC_STATS_BH(ipv6_statistics, field)
...@@ -114,16 +115,17 @@ DECLARE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics); ...@@ -114,16 +115,17 @@ DECLARE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics);
#define ICMP6_INC_STATS(field) SNMP_INC_STATS(icmpv6_statistics, field) #define ICMP6_INC_STATS(field) SNMP_INC_STATS(icmpv6_statistics, field)
#define ICMP6_INC_STATS_BH(field) SNMP_INC_STATS_BH(icmpv6_statistics, field) #define ICMP6_INC_STATS_BH(field) SNMP_INC_STATS_BH(icmpv6_statistics, field)
#define ICMP6_INC_STATS_USER(field) SNMP_INC_STATS_USER(icmpv6_statistics, field) #define ICMP6_INC_STATS_USER(field) SNMP_INC_STATS_USER(icmpv6_statistics, field)
#define ICMP6_STATS_PTR_BH(field) \ #define ICMP6_INC_STATS_OFFSET_BH(field, offset) \
(& \ SNMP_INC_STATS_OFFSET_BH(icmpv6_statistics, field, offset)
((per_cpu_ptr(icmpv6_statistics[0], smp_processor_id()))-> \
field))
DECLARE_SNMP_STAT(struct udp_mib, udp_stats_in6); DECLARE_SNMP_STAT(struct udp_mib, udp_stats_in6);
#define UDP6_INC_STATS(field) SNMP_INC_STATS(udp_stats_in6, field) #define UDP6_INC_STATS(field) SNMP_INC_STATS(udp_stats_in6, field)
#define UDP6_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_stats_in6, field) #define UDP6_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_stats_in6, field)
#define UDP6_INC_STATS_USER(field) SNMP_INC_STATS_USER(udp_stats_in6, field) #define UDP6_INC_STATS_USER(field) SNMP_INC_STATS_USER(udp_stats_in6, field)
extern atomic_t inet6_sock_nr; extern atomic_t inet6_sock_nr;
int snmp6_mib_init(void *ptr[2], size_t mibsize);
void snmp6_mib_free(void *ptr[2]);
struct ip6_ra_chain struct ip6_ra_chain
{ {
struct ip6_ra_chain *next; struct ip6_ra_chain *next;
......
...@@ -304,6 +304,8 @@ struct linux_mib ...@@ -304,6 +304,8 @@ struct linux_mib
#define SNMP_INC_STATS_BH(mib, field) \ #define SNMP_INC_STATS_BH(mib, field) \
(per_cpu_ptr(mib[0], smp_processor_id())->field++) (per_cpu_ptr(mib[0], smp_processor_id())->field++)
#define SNMP_INC_STATS_OFFSET_BH(mib, field, offset) \
((*((&per_cpu_ptr(mib[0], smp_processor_id())->field) + (offset)))++)
#define SNMP_INC_STATS_USER(mib, field) \ #define SNMP_INC_STATS_USER(mib, field) \
(per_cpu_ptr(mib[1], smp_processor_id())->field++) (per_cpu_ptr(mib[1], smp_processor_id())->field++)
#define SNMP_INC_STATS(mib, field) \ #define SNMP_INC_STATS(mib, field) \
......
...@@ -631,79 +631,72 @@ inet6_unregister_protosw(struct inet_protosw *p) ...@@ -631,79 +631,72 @@ inet6_unregister_protosw(struct inet_protosw *p)
inet_unregister_protosw(p); inet_unregister_protosw(p);
} }
static int __init init_ipv6_mibs(void) int
snmp6_mib_init(void *ptr[2], size_t mibsize)
{ {
int i; int i;
ipv6_statistics[0] = kmalloc_percpu(sizeof (struct ipv6_mib), if (ptr == NULL)
GFP_KERNEL); return -EINVAL;
if (!ipv6_statistics[0])
goto err_ip_mib0; ptr[0] = kmalloc_percpu(mibsize, GFP_KERNEL);
ipv6_statistics[1] = kmalloc_percpu(sizeof (struct ipv6_mib), if (!ptr[0])
GFP_KERNEL); goto err0;
if (!ipv6_statistics[1])
goto err_ip_mib1; ptr[1] = kmalloc_percpu(mibsize, GFP_KERNEL);
if (!ptr[1])
icmpv6_statistics[0] = kmalloc_percpu(sizeof (struct icmpv6_mib), goto err1;
GFP_KERNEL);
if (!icmpv6_statistics[0]) /* Zero percpu version of the mibs */
goto err_icmp_mib0;
icmpv6_statistics[1] = kmalloc_percpu(sizeof (struct icmpv6_mib),
GFP_KERNEL);
if (!icmpv6_statistics[1])
goto err_icmp_mib1;
udp_stats_in6[0] = kmalloc_percpu(sizeof (struct udp_mib),
GFP_KERNEL);
if (!udp_stats_in6[0])
goto err_udp_mib0;
udp_stats_in6[1] = kmalloc_percpu(sizeof (struct udp_mib),
GFP_KERNEL);
if (!udp_stats_in6[1])
goto err_udp_mib1;
/* Zero all percpu versions of the mibs */
for (i = 0; i < NR_CPUS; i++) { for (i = 0; i < NR_CPUS; i++) {
if (cpu_possible(i)) { if (cpu_possible(i)) {
memset(per_cpu_ptr(ipv6_statistics[0], i), 0, memset(per_cpu_ptr(ptr[0], i), 0, mibsize);
sizeof (struct ipv6_mib)); memset(per_cpu_ptr(ptr[1], i), 0, mibsize);
memset(per_cpu_ptr(ipv6_statistics[1], i), 0,
sizeof (struct ipv6_mib));
memset(per_cpu_ptr(icmpv6_statistics[0], i), 0,
sizeof (struct icmpv6_mib));
memset(per_cpu_ptr(icmpv6_statistics[1], i), 0,
sizeof (struct icmpv6_mib));
memset(per_cpu_ptr(udp_stats_in6[0], i), 0,
sizeof (struct udp_mib));
memset(per_cpu_ptr(udp_stats_in6[1], i), 0,
sizeof (struct udp_mib));
} }
} }
return 0; return 0;
err_udp_mib1: err1:
kfree_percpu(udp_stats_in6[0]); kfree_percpu(ptr[0]);
err_udp_mib0: ptr[0] = NULL;
kfree_percpu(icmpv6_statistics[1]); err0:
err_icmp_mib1: return -ENOMEM;
kfree_percpu(icmpv6_statistics[0]); }
err_icmp_mib0:
kfree_percpu(ipv6_statistics[1]); void
err_ip_mib1: snmp6_mib_free(void *ptr[2])
kfree_percpu(ipv6_statistics[0]); {
err_ip_mib0: if (ptr == NULL)
return;
kfree_percpu(ptr[0]);
kfree_percpu(ptr[1]);
ptr[0] = ptr[1] = NULL;
}
static int __init init_ipv6_mibs(void)
{
if (snmp6_mib_init((void **)ipv6_statistics, sizeof (struct ipv6_mib)) < 0)
goto err_ip_mib;
if (snmp6_mib_init((void **)icmpv6_statistics, sizeof (struct icmpv6_mib)) < 0)
goto err_icmp_mib;
if (snmp6_mib_init((void **)udp_stats_in6, sizeof (struct udp_mib)) < 0)
goto err_udp_mib;
return 0;
err_udp_mib:
snmp6_mib_free((void **)icmpv6_statistics);
err_icmp_mib:
snmp6_mib_free((void **)ipv6_statistics);
err_ip_mib:
return -ENOMEM; return -ENOMEM;
} }
static void cleanup_ipv6_mibs(void) static void cleanup_ipv6_mibs(void)
{ {
kfree_percpu(ipv6_statistics[0]); snmp6_mib_free((void **)ipv6_statistics);
kfree_percpu(ipv6_statistics[1]); snmp6_mib_free((void **)icmpv6_statistics);
kfree_percpu(icmpv6_statistics[0]); snmp6_mib_free((void **)udp_stats_in6);
kfree_percpu(icmpv6_statistics[1]);
kfree_percpu(udp_stats_in6[0]);
kfree_percpu(udp_stats_in6[1]);
} }
extern int ipv6_misc_proc_init(void); extern int ipv6_misc_proc_init(void);
......
...@@ -354,7 +354,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, ...@@ -354,7 +354,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, len, NULL, -1, ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, len, NULL, -1,
MSG_DONTWAIT); MSG_DONTWAIT);
if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB) if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)
ICMP6_STATS_PTR_BH(Icmp6OutDestUnreachs) [type-ICMPV6_DEST_UNREACH]++; ICMP6_INC_STATS_OFFSET_BH(Icmp6OutDestUnreachs, type-ICMPV6_DEST_UNREACH);
ICMP6_INC_STATS_BH(Icmp6OutMsgs); ICMP6_INC_STATS_BH(Icmp6OutMsgs);
out: out:
icmpv6_xmit_unlock(); icmpv6_xmit_unlock();
...@@ -517,9 +517,9 @@ static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) ...@@ -517,9 +517,9 @@ static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
type = hdr->icmp6_type; type = hdr->icmp6_type;
if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB) if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)
ICMP6_STATS_PTR_BH(Icmp6InDestUnreachs)[type-ICMPV6_DEST_UNREACH]++; ICMP6_INC_STATS_OFFSET_BH(Icmp6InDestUnreachs, type-ICMPV6_DEST_UNREACH);
else if (type >= ICMPV6_ECHO_REQUEST && type <= NDISC_REDIRECT) else if (type >= ICMPV6_ECHO_REQUEST && type <= NDISC_REDIRECT)
ICMP6_STATS_PTR_BH(Icmp6InEchos)[type-ICMPV6_ECHO_REQUEST]++; ICMP6_INC_STATS_OFFSET_BH(Icmp6InEchos, type-ICMPV6_ECHO_REQUEST);
switch (type) { switch (type) {
case ICMPV6_ECHO_REQUEST: case ICMPV6_ECHO_REQUEST:
......
...@@ -10,12 +10,14 @@ ...@@ -10,12 +10,14 @@
* Version: $Id: proc.c,v 1.17 2002/02/01 22:01:04 davem Exp $ * Version: $Id: proc.c,v 1.17 2002/02/01 22:01:04 davem Exp $
* *
* Authors: David S. Miller (davem@caip.rutgers.edu) * Authors: David S. Miller (davem@caip.rutgers.edu)
* YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version * as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
#include <linux/config.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/socket.h> #include <linux/socket.h>
#include <linux/net.h> #include <linux/net.h>
...@@ -53,14 +55,16 @@ static int sockstat6_seq_show(struct seq_file *seq, void *v) ...@@ -53,14 +55,16 @@ static int sockstat6_seq_show(struct seq_file *seq, void *v)
} }
static struct snmp6_item struct snmp6_item
{ {
char *name; char *name;
void **mib;
int offset; int offset;
} snmp6_list[] = { };
#define SNMP6_SENTINEL { .name = NULL, .offset = 0 }
static struct snmp6_item snmp6_ipv6_list[] = {
/* ipv6 mib according to draft-ietf-ipngwg-ipv6-mib-04 */ /* ipv6 mib according to draft-ietf-ipngwg-ipv6-mib-04 */
#define SNMP6_GEN(x) { #x , (void **)ipv6_statistics, offsetof(struct ipv6_mib, x) } #define SNMP6_GEN(x) { .name = #x , .offset = offsetof(struct ipv6_mib, x) }
SNMP6_GEN(Ip6InReceives), SNMP6_GEN(Ip6InReceives),
SNMP6_GEN(Ip6InHdrErrors), SNMP6_GEN(Ip6InHdrErrors),
SNMP6_GEN(Ip6InTooBigErrors), SNMP6_GEN(Ip6InTooBigErrors),
...@@ -84,6 +88,10 @@ static struct snmp6_item ...@@ -84,6 +88,10 @@ static struct snmp6_item
SNMP6_GEN(Ip6InMcastPkts), SNMP6_GEN(Ip6InMcastPkts),
SNMP6_GEN(Ip6OutMcastPkts), SNMP6_GEN(Ip6OutMcastPkts),
#undef SNMP6_GEN #undef SNMP6_GEN
SNMP6_SENTINEL
};
static struct snmp6_item snmp6_icmp6_list[] = {
/* icmpv6 mib according to draft-ietf-ipngwg-ipv6-icmp-mib-02 /* icmpv6 mib according to draft-ietf-ipngwg-ipv6-icmp-mib-02
Exceptions: {In|Out}AdminProhibs are removed, because I see Exceptions: {In|Out}AdminProhibs are removed, because I see
...@@ -94,7 +102,7 @@ static struct snmp6_item ...@@ -94,7 +102,7 @@ static struct snmp6_item
OutRouterAdvertisements too. OutRouterAdvertisements too.
OutGroupMembQueries too. OutGroupMembQueries too.
*/ */
#define SNMP6_GEN(x) { #x , (void **)icmpv6_statistics, offsetof(struct icmpv6_mib, x) } #define SNMP6_GEN(x) { .name = #x , .offset = offsetof(struct icmpv6_mib, x) }
SNMP6_GEN(Icmp6InMsgs), SNMP6_GEN(Icmp6InMsgs),
SNMP6_GEN(Icmp6InErrors), SNMP6_GEN(Icmp6InErrors),
SNMP6_GEN(Icmp6InDestUnreachs), SNMP6_GEN(Icmp6InDestUnreachs),
...@@ -124,12 +132,17 @@ static struct snmp6_item ...@@ -124,12 +132,17 @@ static struct snmp6_item
SNMP6_GEN(Icmp6OutGroupMembResponses), SNMP6_GEN(Icmp6OutGroupMembResponses),
SNMP6_GEN(Icmp6OutGroupMembReductions), SNMP6_GEN(Icmp6OutGroupMembReductions),
#undef SNMP6_GEN #undef SNMP6_GEN
#define SNMP6_GEN(x) { "Udp6" #x , (void **)udp_stats_in6, offsetof(struct udp_mib, Udp##x) } SNMP6_SENTINEL
};
static struct snmp6_item snmp6_udp6_list[] = {
#define SNMP6_GEN(x) { .name = "Udp6" #x , .offset = offsetof(struct udp_mib, Udp##x) }
SNMP6_GEN(InDatagrams), SNMP6_GEN(InDatagrams),
SNMP6_GEN(NoPorts), SNMP6_GEN(NoPorts),
SNMP6_GEN(InErrors), SNMP6_GEN(InErrors),
SNMP6_GEN(OutDatagrams) SNMP6_GEN(OutDatagrams),
#undef SNMP6_GEN #undef SNMP6_GEN
SNMP6_SENTINEL
}; };
static unsigned long static unsigned long
...@@ -151,18 +164,23 @@ fold_field(void *mib[], int offt) ...@@ -151,18 +164,23 @@ fold_field(void *mib[], int offt)
return res; return res;
} }
static int snmp6_seq_show(struct seq_file *seq, void *v) static inline void
snmp6_seq_show_item(struct seq_file *seq, void **mib, struct snmp6_item *itemlist)
{ {
int i; int i;
for (i=0; itemlist[i].name; i++)
seq_printf(seq, "%-32s\t%lu\n", itemlist[i].name,
fold_field(mib, itemlist[i].offset));
}
for (i=0; i<sizeof(snmp6_list)/sizeof(snmp6_list[0]); i++) static int snmp6_seq_show(struct seq_file *seq, void *v)
seq_printf(seq, "%-32s\t%lu\n", snmp6_list[i].name, {
fold_field(snmp6_list[i].mib, snmp6_list[i].offset)); snmp6_seq_show_item(seq, (void **)ipv6_statistics, snmp6_ipv6_list);
snmp6_seq_show_item(seq, (void **)icmpv6_statistics, snmp6_icmp6_list);
snmp6_seq_show_item(seq, (void **)udp_stats_in6, snmp6_udp6_list);
return 0; return 0;
} }
static int sockstat6_seq_open(struct inode *inode, struct file *file) static int sockstat6_seq_open(struct inode *inode, struct file *file)
{ {
return single_open(file, sockstat6_seq_show, NULL); return single_open(file, sockstat6_seq_show, NULL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment