aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2010-10-08 02:37:34 -0400
committerDavid S. Miller <davem@davemloft.net>2010-10-11 16:06:53 -0400
commitfc66f95c68b6d4535a0ea2ea15d5cf626e310956 (patch)
treeac3a7f08ad741a67ff683bf93e5669ddcae95ed7 /net/bridge
parent0ed8ddf4045fcfcac36bad753dc4046118c603ec (diff)
net dst: use a percpu_counter to track entries
struct dst_ops tracks number of allocated dst in an atomic_t field, subject to high cache line contention in stress workload. Switch to a percpu_counter, to reduce number of time we need to dirty a central location. Place it on a separate cache line to avoid dirtying read only fields. Stress test : (Sending 160.000.000 UDP frames, IP route cache disabled, dual E5540 @2.53GHz, 32bit kernel, FIB_TRIE, SLUB/NUMA) Before: real 0m51.179s user 0m15.329s sys 10m15.942s After: real 0m45.570s user 0m15.525s sys 9m56.669s With a small reordering of struct neighbour fields, subject of a following patch, (to separate refcnt from other read mostly fields) real 0m41.841s user 0m15.261s sys 8m45.949s Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_netfilter.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 77f7b5fda45a..7f9ce9600ef3 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -106,7 +106,6 @@ static struct dst_ops fake_dst_ops = {
106 .family = AF_INET, 106 .family = AF_INET,
107 .protocol = cpu_to_be16(ETH_P_IP), 107 .protocol = cpu_to_be16(ETH_P_IP),
108 .update_pmtu = fake_update_pmtu, 108 .update_pmtu = fake_update_pmtu,
109 .entries = ATOMIC_INIT(0),
110}; 109};
111 110
112/* 111/*
@@ -1003,15 +1002,22 @@ int __init br_netfilter_init(void)
1003{ 1002{
1004 int ret; 1003 int ret;
1005 1004
1006 ret = nf_register_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops)); 1005 ret = dst_entries_init(&fake_dst_ops);
1007 if (ret < 0) 1006 if (ret < 0)
1008 return ret; 1007 return ret;
1008
1009 ret = nf_register_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
1010 if (ret < 0) {
1011 dst_entries_destroy(&fake_dst_ops);
1012 return ret;
1013 }
1009#ifdef CONFIG_SYSCTL 1014#ifdef CONFIG_SYSCTL
1010 brnf_sysctl_header = register_sysctl_paths(brnf_path, brnf_table); 1015 brnf_sysctl_header = register_sysctl_paths(brnf_path, brnf_table);
1011 if (brnf_sysctl_header == NULL) { 1016 if (brnf_sysctl_header == NULL) {
1012 printk(KERN_WARNING 1017 printk(KERN_WARNING
1013 "br_netfilter: can't register to sysctl.\n"); 1018 "br_netfilter: can't register to sysctl.\n");
1014 nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops)); 1019 nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
1020 dst_entries_destroy(&fake_dst_ops);
1015 return -ENOMEM; 1021 return -ENOMEM;
1016 } 1022 }
1017#endif 1023#endif
@@ -1025,4 +1031,5 @@ void br_netfilter_fini(void)
1025#ifdef CONFIG_SYSCTL 1031#ifdef CONFIG_SYSCTL
1026 unregister_sysctl_table(brnf_sysctl_header); 1032 unregister_sysctl_table(brnf_sysctl_header);
1027#endif 1033#endif
1034 dst_entries_destroy(&fake_dst_ops);
1028} 1035}