aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/addrconf.c
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2011-05-18 21:14:23 -0400
committerDavid S. Miller <davem@davemloft.net>2011-05-19 16:21:22 -0400
commitbe281e554e2a4cf2478df7a8b8926c89454bccfa (patch)
tree7e80e5eb0aa76efcdb39a06413ff9e0ae73de35a /net/ipv6/addrconf.c
parent75e308c894c4a5e47c005b8e821ae5f539ad2ef3 (diff)
ipv6: reduce per device ICMP mib sizes
ipv6 has per device ICMP SNMP counters, taking too much space because they use percpu storage. needed size per device is : (512+4)*sizeof(long)*number_of_possible_cpus*2 On a 32bit kernel, 16 possible cpus, this wastes more than 64kbytes of memory per ipv6 enabled network device, taken in vmalloc pool. Since ICMP messages are rare, just use shared counters (atomic_long_t) Per network space ICMP counters are still using percpu memory, we might also convert them to shared counters in a future patch. Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> CC: Denys Fedoryshchenko <denys@visp.net.lb> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r--net/ipv6/addrconf.c24
1 files changed, 12 insertions, 12 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index f2f9b2e3cfe9..3cfbbf3387a0 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -289,19 +289,19 @@ static int snmp6_alloc_dev(struct inet6_dev *idev)
289 sizeof(struct ipstats_mib), 289 sizeof(struct ipstats_mib),
290 __alignof__(struct ipstats_mib)) < 0) 290 __alignof__(struct ipstats_mib)) < 0)
291 goto err_ip; 291 goto err_ip;
292 if (snmp_mib_init((void __percpu **)idev->stats.icmpv6, 292 idev->stats.icmpv6dev = kzalloc(sizeof(struct icmpv6_mib_device),
293 sizeof(struct icmpv6_mib), 293 GFP_KERNEL);
294 __alignof__(struct icmpv6_mib)) < 0) 294 if (!idev->stats.icmpv6dev)
295 goto err_icmp; 295 goto err_icmp;
296 if (snmp_mib_init((void __percpu **)idev->stats.icmpv6msg, 296 idev->stats.icmpv6msgdev = kzalloc(sizeof(struct icmpv6msg_mib_device),
297 sizeof(struct icmpv6msg_mib), 297 GFP_KERNEL);
298 __alignof__(struct icmpv6msg_mib)) < 0) 298 if (!idev->stats.icmpv6msgdev)
299 goto err_icmpmsg; 299 goto err_icmpmsg;
300 300
301 return 0; 301 return 0;
302 302
303err_icmpmsg: 303err_icmpmsg:
304 snmp_mib_free((void __percpu **)idev->stats.icmpv6); 304 kfree(idev->stats.icmpv6dev);
305err_icmp: 305err_icmp:
306 snmp_mib_free((void __percpu **)idev->stats.ipv6); 306 snmp_mib_free((void __percpu **)idev->stats.ipv6);
307err_ip: 307err_ip:
@@ -310,8 +310,8 @@ err_ip:
310 310
311static void snmp6_free_dev(struct inet6_dev *idev) 311static void snmp6_free_dev(struct inet6_dev *idev)
312{ 312{
313 snmp_mib_free((void __percpu **)idev->stats.icmpv6msg); 313 kfree(idev->stats.icmpv6msgdev);
314 snmp_mib_free((void __percpu **)idev->stats.icmpv6); 314 kfree(idev->stats.icmpv6dev);
315 snmp_mib_free((void __percpu **)idev->stats.ipv6); 315 snmp_mib_free((void __percpu **)idev->stats.ipv6);
316} 316}
317 317
@@ -3838,7 +3838,7 @@ static inline size_t inet6_if_nlmsg_size(void)
3838 + nla_total_size(inet6_ifla6_size()); /* IFLA_PROTINFO */ 3838 + nla_total_size(inet6_ifla6_size()); /* IFLA_PROTINFO */
3839} 3839}
3840 3840
3841static inline void __snmp6_fill_stats(u64 *stats, void __percpu **mib, 3841static inline void __snmp6_fill_statsdev(u64 *stats, atomic_long_t *mib,
3842 int items, int bytes) 3842 int items, int bytes)
3843{ 3843{
3844 int i; 3844 int i;
@@ -3848,7 +3848,7 @@ static inline void __snmp6_fill_stats(u64 *stats, void __percpu **mib,
3848 /* Use put_unaligned() because stats may not be aligned for u64. */ 3848 /* Use put_unaligned() because stats may not be aligned for u64. */
3849 put_unaligned(items, &stats[0]); 3849 put_unaligned(items, &stats[0]);
3850 for (i = 1; i < items; i++) 3850 for (i = 1; i < items; i++)
3851 put_unaligned(snmp_fold_field(mib, i), &stats[i]); 3851 put_unaligned(atomic_long_read(&mib[i]), &stats[i]);
3852 3852
3853 memset(&stats[items], 0, pad); 3853 memset(&stats[items], 0, pad);
3854} 3854}
@@ -3877,7 +3877,7 @@ static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype,
3877 IPSTATS_MIB_MAX, bytes, offsetof(struct ipstats_mib, syncp)); 3877 IPSTATS_MIB_MAX, bytes, offsetof(struct ipstats_mib, syncp));
3878 break; 3878 break;
3879 case IFLA_INET6_ICMP6STATS: 3879 case IFLA_INET6_ICMP6STATS:
3880 __snmp6_fill_stats(stats, (void __percpu **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes); 3880 __snmp6_fill_statsdev(stats, idev->stats.icmpv6dev->mibs, ICMP6_MIB_MAX, bytes);
3881 break; 3881 break;
3882 } 3882 }
3883} 3883}