aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/af_inet.c
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2010-06-30 16:31:19 -0400
committerDavid S. Miller <davem@davemloft.net>2010-06-30 16:31:19 -0400
commit4ce3c183fcade7f4b30a33dae90cd774c3d9e094 (patch)
tree84d5a130da50096fdbeb7fffea596dffe2cebd80 /net/ipv4/af_inet.c
parentf3eb62d2cc7da7bea4b394dd06f6bc738aa284e7 (diff)
snmp: 64bit ipstats_mib for all arches
/proc/net/snmp and /proc/net/netstat expose SNMP counters. Width of these counters is either 32 or 64 bits, depending on the size of "unsigned long" in kernel. This means user program parsing these files must already be prepared to deal with 64bit values, regardless of user program being 32 or 64 bit. This patch introduces 64bit snmp values for IPSTAT mib, where some counters can wrap pretty fast if they are 32bit wide. # netstat -s|egrep "InOctets|OutOctets" InOctets: 244068329096 OutOctets: 244069348848 Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/af_inet.c')
-rw-r--r--net/ipv4/af_inet.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 640db9b90330..3ceb025b16f2 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1427,6 +1427,42 @@ unsigned long snmp_fold_field(void __percpu *mib[], int offt)
1427} 1427}
1428EXPORT_SYMBOL_GPL(snmp_fold_field); 1428EXPORT_SYMBOL_GPL(snmp_fold_field);
1429 1429
1430#if BITS_PER_LONG==32
1431
1432u64 snmp_fold_field64(void __percpu *mib[], int offt, size_t syncp_offset)
1433{
1434 u64 res = 0;
1435 int cpu;
1436
1437 for_each_possible_cpu(cpu) {
1438 void *bhptr, *userptr;
1439 struct u64_stats_sync *syncp;
1440 u64 v_bh, v_user;
1441 unsigned int start;
1442
1443 /* first mib used by softirq context, we must use _bh() accessors */
1444 bhptr = per_cpu_ptr(SNMP_STAT_BHPTR(mib), cpu);
1445 syncp = (struct u64_stats_sync *)(bhptr + syncp_offset);
1446 do {
1447 start = u64_stats_fetch_begin_bh(syncp);
1448 v_bh = *(((u64 *) bhptr) + offt);
1449 } while (u64_stats_fetch_retry_bh(syncp, start));
1450
1451 /* second mib used in USER context */
1452 userptr = per_cpu_ptr(SNMP_STAT_USRPTR(mib), cpu);
1453 syncp = (struct u64_stats_sync *)(userptr + syncp_offset);
1454 do {
1455 start = u64_stats_fetch_begin(syncp);
1456 v_user = *(((u64 *) userptr) + offt);
1457 } while (u64_stats_fetch_retry(syncp, start));
1458
1459 res += v_bh + v_user;
1460 }
1461 return res;
1462}
1463EXPORT_SYMBOL_GPL(snmp_fold_field64);
1464#endif
1465
1430int snmp_mib_init(void __percpu *ptr[2], size_t mibsize, size_t align) 1466int snmp_mib_init(void __percpu *ptr[2], size_t mibsize, size_t align)
1431{ 1467{
1432 BUG_ON(ptr == NULL); 1468 BUG_ON(ptr == NULL);