Here's a patchset to enable networking mibs to use kmalloc_percpu instead
of the traditional padded NR_CPUS arrays.
Advantages:
1. Removes NR_CPUS bloat due to static definition
2. Can support node local allocation
3. Will work with modules
The changes have been split for ipv4, ipv6 and sctp. We can later do away
with the __pad and associated logic duing proc reporting (in the mibs)
if this patchset is acceptable.
This patch is 1 of 3
D: Name: ipv4mibs-2.5.50-1.patch
D: Author: Ravikiran Thirumalai
D: Description: Changes ipv4 stats to use kmalloc_percpu from the traditional
D: padded NR_CPUS arrays
include/net/icmp.h | 15 ++++++-
include/net/ip.h | 6 +-
include/net/snmp.h | 39 +++++++++++++------
include/net/tcp.h | 6 +-
include/net/udp.h | 2
net/ipv4/af_inet.c | 61 +++++++++++++++++++++++++++++
net/ipv4/icmp.c | 96 ++++++++++++++++++++++-------------------------
net/ipv4/ip_input.c | 2
net/ipv4/proc.c | 37 +++++++++---------
net/ipv4/tcp.c | 13 +++---
net/ipv4/tcp_input.c | 4 -
net/ipv4/tcp_minisocks.c | 4 -
net/ipv4/tcp_timer.c | 3 -
net/ipv4/udp.c | 2
14 files changed, 190 insertions(+), 100 deletions(-)
diff -ruN -X dontdiff linux-2.5.50/include/net/icmp.h mibstats-2.5.50/include/net/icmp.h
--- linux-2.5.50/include/net/icmp.h Thu Nov 28 04:06:18 2002
+++ mibstats-2.5.50/include/net/icmp.h Wed Dec 4 12:13:33 2002
@@ -23,6 +23,7 @@
#include <net/sock.h>
#include <net/protocol.h>
+#include <net/snmp.h>
#include <linux/ip.h>
struct icmp_err {
@@ -31,10 +32,22 @@
};
extern struct icmp_err icmp_err_convert[];
-extern struct icmp_mib icmp_statistics[NR_CPUS*2];
+DECLARE_SNMP_STAT(struct icmp_mib, icmp_statistics);
#define ICMP_INC_STATS(field) SNMP_INC_STATS(icmp_statistics, field)
#define ICMP_INC_STATS_BH(field) SNMP_INC_STATS_BH(icmp_statistics, field)
#define ICMP_INC_STATS_USER(field) SNMP_INC_STATS_USER(icmp_statistics, field)
+#define ICMP_INC_STATS_FIELD(offt) \
+ (*((unsigned long *) ((void *) \
+ per_cpu_ptr(icmp_statistics[!in_softirq()],\
+ smp_processor_id())) + offt))++;
+#define ICMP_INC_STATS_BH_FIELD(offt) \
+ (*((unsigned long *) ((void *) \
+ per_cpu_ptr(icmp_statistics[0], \
+ smp_processor_id())) + offt))++;
+#define ICMP_INC_STATS_USER_FIELD(offt) \
+ (*((unsigned long *) ((void *) \
+ per_cpu_ptr(icmp_statistics[1], \
+ smp_processor_id())) + offt))++;
extern void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info);
extern int icmp_rcv(struct sk_buff *skb);
diff -ruN -X dontdiff linux-2.5.50/include/net/ip.h mibstats-2.5.50/include/net/ip.h
--- linux-2.5.50/include/net/ip.h Thu Nov 28 04:06:15 2002
+++ mibstats-2.5.50/include/net/ip.h Wed Dec 4 12:13:33 2002
@@ -149,14 +149,16 @@
};
extern struct ipv4_config ipv4_config;
-extern struct ip_mib ip_statistics[NR_CPUS*2];
+DECLARE_SNMP_STAT(struct ip_mib, ip_statistics);
#define IP_INC_STATS(field) SNMP_INC_STATS(ip_statistics, field)
#define IP_INC_STATS_BH(field) SNMP_INC_STATS_BH(ip_statistics, field)
#define IP_INC_STATS_USER(field) SNMP_INC_STATS_USER(ip_statistics, field)
-extern struct linux_mib net_statistics[NR_CPUS*2];
+DECLARE_SNMP_STAT(struct linux_mib, net_statistics);
#define NET_INC_STATS(field) SNMP_INC_STATS(net_statistics, field)
#define NET_INC_STATS_BH(field) SNMP_INC_STATS_BH(net_statistics, field)
#define NET_INC_STATS_USER(field) SNMP_INC_STATS_USER(net_statistics, field)
+#define NET_ADD_STATS_BH(field, adnd) SNMP_ADD_STATS_BH(net_statistics, field, adnd)
+#define NET_ADD_STATS_USER(field, adnd) SNMP_ADD_STATS_USER(net_statistics, field, adnd)
extern int sysctl_local_port_range[2];
extern int sysctl_ip_default_ttl;
diff -ruN -X dontdiff linux-2.5.50/include/net/snmp.h mibstats-2.5.50/include/net/snmp.h
--- linux-2.5.50/include/net/snmp.h Thu Nov 28 04:05:57 2002
+++ mibstats-2.5.50/include/net/snmp.h Wed Dec 4 12:13:33 2002
@@ -62,7 +62,7 @@
unsigned long IpFragFails;
unsigned long IpFragCreates;
unsigned long __pad[0];
-} ____cacheline_aligned;
+};
struct ipv6_mib
{
@@ -89,7 +89,7 @@
unsigned long Ip6InMcastPkts;
unsigned long Ip6OutMcastPkts;
unsigned long __pad[0];
-} ____cacheline_aligned;
+};
struct icmp_mib
{
@@ -121,7 +121,7 @@
unsigned long IcmpOutAddrMaskReps;
unsigned long dummy;
unsigned long __pad[0];
-} ____cacheline_aligned;
+};
struct icmpv6_mib
{
@@ -159,7 +159,7 @@
unsigned long Icmp6OutGroupMembResponses;
unsigned long Icmp6OutGroupMembReductions;
unsigned long __pad[0];
-} ____cacheline_aligned;
+};
struct tcp_mib
{
@@ -178,7 +178,7 @@
unsigned long TcpInErrs;
unsigned long TcpOutRsts;
unsigned long __pad[0];
-} ____cacheline_aligned;
+};
struct udp_mib
{
@@ -187,7 +187,7 @@
unsigned long UdpInErrors;
unsigned long UdpOutDatagrams;
unsigned long __pad[0];
-} ____cacheline_aligned;
+};
/* draft-ietf-sigtran-sctp-mib-07.txt */
struct sctp_mib
@@ -216,7 +216,7 @@
unsigned long SctpValCookieLife;
unsigned long SctpMaxInitRetr;
unsigned long __pad[0];
-} ____cacheline_aligned;
+};
struct linux_mib
{
@@ -286,7 +286,7 @@
unsigned long TCPAbortFailed;
unsigned long TCPMemoryPressures;
unsigned long __pad[0];
-} ____cacheline_aligned;
+};
/*
@@ -294,8 +294,25 @@
* addl $1,memory is atomic against interrupts (but atomic_inc would be overkill because of the lock
* cycles). Wants new nonlocked_atomic_inc() primitives -AK
*/
-#define SNMP_INC_STATS(mib, field) ((mib)[2*smp_processor_id()+!in_softirq()].field++)
-#define SNMP_INC_STATS_BH(mib, field) ((mib)[2*smp_processor_id()].field++)
-#define SNMP_INC_STATS_USER(mib, field) ((mib)[2*smp_processor_id()+1].field++)
+#define DEFINE_SNMP_STAT(type, name) \
+ __typeof__(type) *name[2]
+#define DECLARE_SNMP_STAT(type, name) \
+ extern __typeof__(type) *name[2]
+
+#define SNMP_STAT_USRPTR(name) (name[0])
+#define SNMP_STAT_BHPTR(name) (name[1])
+
+#define SNMP_INC_STATS_BH(mib, field) \
+ (per_cpu_ptr(mib[0], smp_processor_id())->field++)
+#define SNMP_INC_STATS_USER(mib, field) \
+ (per_cpu_ptr(mib[1], smp_processor_id())->field++)
+#define SNMP_INC_STATS(mib, field) \
+ (per_cpu_ptr(mib[!in_softirq()], smp_processor_id())->field++)
+#define SNMP_DEC_STATS(mib, field) \
+ (per_cpu_ptr(mib[!in_softirq()], smp_processor_id())->field--)
+#define SNMP_ADD_STATS_BH(mib, field, addend) \
+ (per_cpu_ptr(mib[0], smp_processor_id())->field += addend)
+#define SNMP_ADD_STATS_USER(mib, field, addend) \
+ (per_cpu_ptr(mib[1], smp_processor_id())->field += addend)
#endif
diff -ruN -X dontdiff linux-2.5.50/include/net/tcp.h mibstats-2.5.50/include/net/tcp.h
--- linux-2.5.50/include/net/tcp.h Thu Nov 28 04:05:50 2002
+++ mibstats-2.5.50/include/net/tcp.h Wed Dec 4 12:13:33 2002
@@ -28,6 +28,7 @@
#include <linux/tcp.h>
#include <linux/slab.h>
#include <linux/cache.h>
+#include <linux/percpu.h>
#include <net/checksum.h>
#include <net/sock.h>
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
@@ -630,10 +631,11 @@
extern struct proto tcp_prot;
-extern struct tcp_mib tcp_statistics[NR_CPUS*2];
+DECLARE_SNMP_STAT(struct tcp_mib, tcp_statistics);
#define TCP_INC_STATS(field) SNMP_INC_STATS(tcp_statistics, field)
#define TCP_INC_STATS_BH(field) SNMP_INC_STATS_BH(tcp_statistics, field)
#define TCP_INC_STATS_USER(field) SNMP_INC_STATS_USER(tcp_statistics, field)
+#define TCP_DEC_STATS(field) SNMP_DEC_STATS(tcp_statistics, field)
extern void tcp_put_port(struct sock *sk);
extern void __tcp_put_port(struct sock *sk);
@@ -1399,7 +1401,7 @@
/* fall through */
default:
if (oldstate==TCP_ESTABLISHED)
- tcp_statistics[smp_processor_id()*2+!in_softirq()].TcpCurrEstab--;
+ TCP_DEC_STATS(TcpCurrEstab);
}
/* Change state AFTER socket is unhashed to avoid closed
diff -ruN -X dontdiff linux-2.5.50/include/net/udp.h mibstats-2.5.50/include/net/udp.h
--- linux-2.5.50/include/net/udp.h Thu Nov 28 04:06:17 2002
+++ mibstats-2.5.50/include/net/udp.h Wed Dec 4 12:13:33 2002
@@ -71,7 +71,7 @@
extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
extern int udp_disconnect(struct sock *sk, int flags);
-extern struct udp_mib udp_statistics[NR_CPUS*2];
+DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
#define UDP_INC_STATS(field) SNMP_INC_STATS(udp_statistics, field)
#define UDP_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_statistics, field)
#define UDP_INC_STATS_USER(field) SNMP_INC_STATS_USER(udp_statistics, field)
diff -ruN -X dontdiff linux-2.5.50/net/ipv4/af_inet.c mibstats-2.5.50/net/ipv4/af_inet.c
--- linux-2.5.50/net/ipv4/af_inet.c Thu Nov 28 04:05:50 2002
+++ mibstats-2.5.50/net/ipv4/af_inet.c Wed Dec 4 12:13:33 2002
@@ -115,7 +115,7 @@
#include <linux/mroute.h>
#endif
-struct linux_mib net_statistics[NR_CPUS * 2];
+DEFINE_SNMP_STAT(struct linux_mib, net_statistics);
#ifdef INET_REFCNT_DEBUG
atomic_t inet_sock_nr;
@@ -1055,6 +1055,59 @@
.handler = icmp_rcv,
};
+static int __init init_ipv4_mibs(void)
+{
+ int i;
+
+ net_statistics[0] =
+ kmalloc_percpu(sizeof (struct linux_mib), GFP_KERNEL);
+ net_statistics[1] =
+ kmalloc_percpu(sizeof (struct linux_mib), GFP_KERNEL);
+ ip_statistics[0] = kmalloc_percpu(sizeof (struct ip_mib), GFP_KERNEL);
+ ip_statistics[1] = kmalloc_percpu(sizeof (struct ip_mib), GFP_KERNEL);
+ icmp_statistics[0] =
+ kmalloc_percpu(sizeof (struct icmp_mib), GFP_KERNEL);
+ icmp_statistics[1] =
+ kmalloc_percpu(sizeof (struct icmp_mib), GFP_KERNEL);
+ tcp_statistics[0] = kmalloc_percpu(sizeof (struct tcp_mib), GFP_KERNEL);
+ tcp_statistics[1] = kmalloc_percpu(sizeof (struct tcp_mib), GFP_KERNEL);
+ udp_statistics[0] = kmalloc_percpu(sizeof (struct udp_mib), GFP_KERNEL);
+ udp_statistics[1] = kmalloc_percpu(sizeof (struct udp_mib), GFP_KERNEL);
+ if (!
+ (net_statistics[0]
...
read more »