Commit 7f86066b authored by Ravikiran G. Thirumalai's avatar Ravikiran G. Thirumalai Committed by David S. Miller

[IPV6]: Convert mibstats to use kmalloc_percpu

parent c9d4b9b1
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <asm/hardirq.h> #include <asm/hardirq.h>
#include <net/ndisc.h> #include <net/ndisc.h>
#include <net/flow.h> #include <net/flow.h>
#include <net/snmp.h>
#define SIN6_LEN_RFC2133 24 #define SIN6_LEN_RFC2133 24
...@@ -105,15 +106,19 @@ struct frag_hdr { ...@@ -105,15 +106,19 @@ struct frag_hdr {
/* sysctls */ /* sysctls */
extern int sysctl_ipv6_bindv6only; extern int sysctl_ipv6_bindv6only;
extern struct ipv6_mib ipv6_statistics[NR_CPUS*2]; 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)
#define IP6_INC_STATS_USER(field) SNMP_INC_STATS_USER(ipv6_statistics, field) #define IP6_INC_STATS_USER(field) SNMP_INC_STATS_USER(ipv6_statistics, field)
extern struct icmpv6_mib icmpv6_statistics[NR_CPUS*2]; 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)
extern struct udp_mib udp_stats_in6[NR_CPUS*2]; #define ICMP6_STATS_PTR_BH(field) \
(& \
((per_cpu_ptr(icmpv6_statistics[0], smp_processor_id()))-> \
field))
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)
......
...@@ -619,6 +619,81 @@ inet6_unregister_protosw(struct inet_protosw *p) ...@@ -619,6 +619,81 @@ inet6_unregister_protosw(struct inet_protosw *p)
inet_unregister_protosw(p); inet_unregister_protosw(p);
} }
static int __init init_ipv6_mibs(void)
{
int i;
ipv6_statistics[0] = kmalloc_percpu(sizeof (struct ipv6_mib),
GFP_KERNEL);
if (!ipv6_statistics[0])
goto err_ip_mib0;
ipv6_statistics[1] = kmalloc_percpu(sizeof (struct ipv6_mib),
GFP_KERNEL);
if (!ipv6_statistics[1])
goto err_ip_mib1;
icmpv6_statistics[0] = kmalloc_percpu(sizeof (struct icmpv6_mib),
GFP_KERNEL);
if (!icmpv6_statistics[0])
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++) {
if (cpu_possible(i)) {
memset(per_cpu_ptr(ipv6_statistics[0], i), 0,
sizeof (struct ipv6_mib));
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;
err_udp_mib1:
kfree_percpu(udp_stats_in6[0]);
err_udp_mib0:
kfree_percpu(icmpv6_statistics[1]);
err_icmp_mib1:
kfree_percpu(icmpv6_statistics[0]);
err_icmp_mib0:
kfree_percpu(ipv6_statistics[1]);
err_ip_mib1:
kfree_percpu(ipv6_statistics[0]);
err_ip_mib0:
return -ENOMEM;
}
static void __exit cleanup_ipv6_mibs(void)
{
kfree_percpu(ipv6_statistics[0]);
kfree_percpu(ipv6_statistics[1]);
kfree_percpu(icmpv6_statistics[0]);
kfree_percpu(icmpv6_statistics[1]);
kfree_percpu(udp_stats_in6[0]);
kfree_percpu(udp_stats_in6[1]);
}
static int __init inet6_init(void) static int __init inet6_init(void)
{ {
struct sk_buff *dummy_skb; struct sk_buff *dummy_skb;
...@@ -669,6 +744,11 @@ static int __init inet6_init(void) ...@@ -669,6 +744,11 @@ static int __init inet6_init(void)
*/ */
(void) sock_register(&inet6_family_ops); (void) sock_register(&inet6_family_ops);
/* Initialise ipv6 mibs */
err = init_ipv6_mibs();
if (err)
goto init_mib_fail;
/* /*
* ipngwg API draft makes clear that the correct semantics * ipngwg API draft makes clear that the correct semantics
* for TCP and UDP is to consider one TCP and UDP instance * for TCP and UDP is to consider one TCP and UDP instance
...@@ -735,6 +815,8 @@ static int __init inet6_init(void) ...@@ -735,6 +815,8 @@ static int __init inet6_init(void)
#if defined(MODULE) && defined(CONFIG_SYSCTL) #if defined(MODULE) && defined(CONFIG_SYSCTL)
ipv6_sysctl_unregister(); ipv6_sysctl_unregister();
#endif #endif
cleanup_ipv6_mibs();
init_mib_fail:
return err; return err;
} }
module_init(inet6_init); module_init(inet6_init);
...@@ -765,6 +847,7 @@ static void inet6_exit(void) ...@@ -765,6 +847,7 @@ static void inet6_exit(void)
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
ipv6_sysctl_unregister(); ipv6_sysctl_unregister();
#endif #endif
cleanup_ipv6_mibs();
} }
module_exit(inet6_exit); module_exit(inet6_exit);
#endif /* MODULE */ #endif /* MODULE */
......
...@@ -65,7 +65,7 @@ ...@@ -65,7 +65,7 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
struct icmpv6_mib icmpv6_statistics[NR_CPUS*2]; DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics);
/* /*
* ICMP socket for flow control. * ICMP socket for flow control.
...@@ -377,7 +377,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, ...@@ -377,7 +377,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)
(&(icmpv6_statistics[smp_processor_id()*2].Icmp6OutDestUnreachs))[type-1]++; ICMP6_STATS_PTR_BH(Icmp6OutDestUnreachs) [type-1]++;
ICMP6_INC_STATS_BH(Icmp6OutMsgs); ICMP6_INC_STATS_BH(Icmp6OutMsgs);
out: out:
icmpv6_xmit_unlock(); icmpv6_xmit_unlock();
...@@ -539,9 +539,9 @@ static int icmpv6_rcv(struct sk_buff *skb) ...@@ -539,9 +539,9 @@ static int icmpv6_rcv(struct sk_buff *skb)
type = hdr->icmp6_type; type = hdr->icmp6_type;
if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB) if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)
(&icmpv6_statistics[smp_processor_id()*2].Icmp6InDestUnreachs)[type-ICMPV6_DEST_UNREACH]++; ICMP6_STATS_PTR_BH(Icmp6InDestUnreachs)[type-ICMPV6_DEST_UNREACH]++;
else if (type >= ICMPV6_ECHO_REQUEST && type <= NDISC_REDIRECT) else if (type >= ICMPV6_ECHO_REQUEST && type <= NDISC_REDIRECT)
(&icmpv6_statistics[smp_processor_id()*2].Icmp6InEchos)[type-ICMPV6_ECHO_REQUEST]++; ICMP6_STATS_PTR_BH(Icmp6InEchos)[type-ICMPV6_ECHO_REQUEST]++;
switch (type) { switch (type) {
case ICMPV6_ECHO_REQUEST: case ICMPV6_ECHO_REQUEST:
......
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
struct ipv6_mib ipv6_statistics[NR_CPUS*2]; DEFINE_SNMP_STAT(struct ipv6_mib, ipv6_statistics);
static struct packet_type ipv6_packet_type = static struct packet_type ipv6_packet_type =
{ {
......
...@@ -59,11 +59,11 @@ int afinet6_get_info(char *buffer, char **start, off_t offset, int length) ...@@ -59,11 +59,11 @@ int afinet6_get_info(char *buffer, char **start, off_t offset, int length)
static struct snmp6_item static struct snmp6_item
{ {
char *name; char *name;
unsigned long *ptr; void **mib;
int mibsize; int offset;
} snmp6_list[] = { } snmp6_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 , &ipv6_statistics[0].x, sizeof(struct ipv6_mib)/sizeof(unsigned long) } #define SNMP6_GEN(x) { #x , (void **)ipv6_statistics, offsetof(struct ipv6_mib, x) }
SNMP6_GEN(Ip6InReceives), SNMP6_GEN(Ip6InReceives),
SNMP6_GEN(Ip6InHdrErrors), SNMP6_GEN(Ip6InHdrErrors),
SNMP6_GEN(Ip6InTooBigErrors), SNMP6_GEN(Ip6InTooBigErrors),
...@@ -97,7 +97,7 @@ static struct snmp6_item ...@@ -97,7 +97,7 @@ static struct snmp6_item
OutRouterAdvertisements too. OutRouterAdvertisements too.
OutGroupMembQueries too. OutGroupMembQueries too.
*/ */
#define SNMP6_GEN(x) { #x , &icmpv6_statistics[0].x, sizeof(struct icmpv6_mib)/sizeof(unsigned long) } #define SNMP6_GEN(x) { #x , (void **)icmpv6_statistics, offsetof(struct icmpv6_mib, x) }
SNMP6_GEN(Icmp6InMsgs), SNMP6_GEN(Icmp6InMsgs),
SNMP6_GEN(Icmp6InErrors), SNMP6_GEN(Icmp6InErrors),
SNMP6_GEN(Icmp6InDestUnreachs), SNMP6_GEN(Icmp6InDestUnreachs),
...@@ -127,7 +127,7 @@ static struct snmp6_item ...@@ -127,7 +127,7 @@ 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 , &udp_stats_in6[0].Udp##x, sizeof(struct udp_mib)/sizeof(unsigned long) } #define SNMP6_GEN(x) { "Udp6" #x , (void **)udp_stats_in6, offsetof(struct udp_mib, Udp##x) }
SNMP6_GEN(InDatagrams), SNMP6_GEN(InDatagrams),
SNMP6_GEN(NoPorts), SNMP6_GEN(NoPorts),
SNMP6_GEN(InErrors), SNMP6_GEN(InErrors),
...@@ -135,16 +135,22 @@ static struct snmp6_item ...@@ -135,16 +135,22 @@ static struct snmp6_item
#undef SNMP6_GEN #undef SNMP6_GEN
}; };
static unsigned long fold_field(unsigned long *ptr, int size) static unsigned long
fold_field(void *mib[], int offt)
{ {
unsigned long res = 0; unsigned long res = 0;
int i; int i;
for (i=0; i<NR_CPUS; i++) { for (i = 0; i < NR_CPUS; i++) {
res += ptr[2*i*size]; if (!cpu_possible(i))
res += ptr[(2*i+1)*size]; continue;
res +=
*((unsigned long *) (((void *)per_cpu_ptr(mib[0], i)) +
offt));
res +=
*((unsigned long *) (((void *)per_cpu_ptr(mib[1], i)) +
offt));
} }
return res; return res;
} }
...@@ -155,7 +161,7 @@ int afinet6_get_snmp(char *buffer, char **start, off_t offset, int length) ...@@ -155,7 +161,7 @@ int afinet6_get_snmp(char *buffer, char **start, off_t offset, int length)
for (i=0; i<sizeof(snmp6_list)/sizeof(snmp6_list[0]); i++) for (i=0; i<sizeof(snmp6_list)/sizeof(snmp6_list[0]); i++)
len += sprintf(buffer+len, "%-32s\t%ld\n", snmp6_list[i].name, len += sprintf(buffer+len, "%-32s\t%ld\n", snmp6_list[i].name,
fold_field(snmp6_list[i].ptr, snmp6_list[i].mibsize)); fold_field(snmp6_list[i].mib, snmp6_list[i].offset));
len -= offset; len -= offset;
......
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
#include <net/checksum.h> #include <net/checksum.h>
struct udp_mib udp_stats_in6[NR_CPUS*2]; DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6);
/* XXX This is identical to tcp_ipv6.c:ipv6_rcv_saddr_equal, put /* XXX This is identical to tcp_ipv6.c:ipv6_rcv_saddr_equal, put
* XXX it somewhere common. -DaveM * XXX it somewhere common. -DaveM
......
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