diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2010-10-05 06:41:36 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-10-05 23:39:38 -0400 |
commit | ebc0ffae5dfb4447e0a431ffe7fe1d467c48bbb9 (patch) | |
tree | 395e50547ffccc6b73e04a44190eb4b4f2d2316b /include/net/ip_fib.h | |
parent | c2952c314b4fe61820ba8fd6c949eed636140d52 (diff) |
fib: RCU conversion of fib_lookup()
fib_lookup() converted to be called in RCU protected context, no
reference taken and released on a contended cache line (fib_clntref)
fib_table_lookup() and fib_semantic_match() get an additional parameter.
struct fib_info gets an rcu_head field, and is freed after an rcu grace
period.
Stress test :
(Sending 160.000.000 UDP frames on same neighbour,
IP route cache disabled, dual E5540 @2.53GHz,
32bit kernel, FIB_HASH) (about same results for FIB_TRIE)
Before patch :
real 1m31.199s
user 0m13.761s
sys 23m24.780s
After patch:
real 1m5.375s
user 0m14.997s
sys 15m50.115s
Before patch Profile :
13044.00 15.4% __ip_route_output_key vmlinux
8438.00 10.0% dst_destroy vmlinux
5983.00 7.1% fib_semantic_match vmlinux
5410.00 6.4% fib_rules_lookup vmlinux
4803.00 5.7% neigh_lookup vmlinux
4420.00 5.2% _raw_spin_lock vmlinux
3883.00 4.6% rt_set_nexthop vmlinux
3261.00 3.9% _raw_read_lock vmlinux
2794.00 3.3% fib_table_lookup vmlinux
2374.00 2.8% neigh_resolve_output vmlinux
2153.00 2.5% dst_alloc vmlinux
1502.00 1.8% _raw_read_lock_bh vmlinux
1484.00 1.8% kmem_cache_alloc vmlinux
1407.00 1.7% eth_header vmlinux
1406.00 1.7% ipv4_dst_destroy vmlinux
1298.00 1.5% __copy_from_user_ll vmlinux
1174.00 1.4% dev_queue_xmit vmlinux
1000.00 1.2% ip_output vmlinux
After patch Profile :
13712.00 15.8% dst_destroy vmlinux
8548.00 9.9% __ip_route_output_key vmlinux
7017.00 8.1% neigh_lookup vmlinux
4554.00 5.3% fib_semantic_match vmlinux
4067.00 4.7% _raw_read_lock vmlinux
3491.00 4.0% dst_alloc vmlinux
3186.00 3.7% neigh_resolve_output vmlinux
3103.00 3.6% fib_table_lookup vmlinux
2098.00 2.4% _raw_read_lock_bh vmlinux
2081.00 2.4% kmem_cache_alloc vmlinux
2013.00 2.3% _raw_spin_lock vmlinux
1763.00 2.0% __copy_from_user_ll vmlinux
1763.00 2.0% ip_output vmlinux
1761.00 2.0% ipv4_dst_destroy vmlinux
1631.00 1.9% eth_header vmlinux
1440.00 1.7% _raw_read_unlock_bh vmlinux
Reference results, if IP route cache is enabled :
real 0m29.718s
user 0m10.845s
sys 7m37.341s
25213.00 29.5% __ip_route_output_key vmlinux
9011.00 10.5% dst_release vmlinux
4817.00 5.6% ip_push_pending_frames vmlinux
4232.00 5.0% ip_finish_output vmlinux
3940.00 4.6% udp_sendmsg vmlinux
3730.00 4.4% __copy_from_user_ll vmlinux
3716.00 4.4% ip_route_output_flow vmlinux
2451.00 2.9% __xfrm_lookup vmlinux
2221.00 2.6% ip_append_data vmlinux
1718.00 2.0% _raw_spin_lock_bh vmlinux
1655.00 1.9% __alloc_skb vmlinux
1572.00 1.8% sock_wfree vmlinux
1345.00 1.6% kfree vmlinux
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net/ip_fib.h')
-rw-r--r-- | include/net/ip_fib.h | 17 |
1 files changed, 4 insertions, 13 deletions
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index c93f94edc610..ba3666d31766 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h | |||
@@ -86,6 +86,7 @@ struct fib_info { | |||
86 | #ifdef CONFIG_IP_ROUTE_MULTIPATH | 86 | #ifdef CONFIG_IP_ROUTE_MULTIPATH |
87 | int fib_power; | 87 | int fib_power; |
88 | #endif | 88 | #endif |
89 | struct rcu_head rcu; | ||
89 | struct fib_nh fib_nh[0]; | 90 | struct fib_nh fib_nh[0]; |
90 | #define fib_dev fib_nh[0].nh_dev | 91 | #define fib_dev fib_nh[0].nh_dev |
91 | }; | 92 | }; |
@@ -148,7 +149,7 @@ struct fib_table { | |||
148 | }; | 149 | }; |
149 | 150 | ||
150 | extern int fib_table_lookup(struct fib_table *tb, const struct flowi *flp, | 151 | extern int fib_table_lookup(struct fib_table *tb, const struct flowi *flp, |
151 | struct fib_result *res); | 152 | struct fib_result *res, int fib_flags); |
152 | extern int fib_table_insert(struct fib_table *, struct fib_config *); | 153 | extern int fib_table_insert(struct fib_table *, struct fib_config *); |
153 | extern int fib_table_delete(struct fib_table *, struct fib_config *); | 154 | extern int fib_table_delete(struct fib_table *, struct fib_config *); |
154 | extern int fib_table_dump(struct fib_table *table, struct sk_buff *skb, | 155 | extern int fib_table_dump(struct fib_table *table, struct sk_buff *skb, |
@@ -185,11 +186,11 @@ static inline int fib_lookup(struct net *net, const struct flowi *flp, | |||
185 | struct fib_table *table; | 186 | struct fib_table *table; |
186 | 187 | ||
187 | table = fib_get_table(net, RT_TABLE_LOCAL); | 188 | table = fib_get_table(net, RT_TABLE_LOCAL); |
188 | if (!fib_table_lookup(table, flp, res)) | 189 | if (!fib_table_lookup(table, flp, res, FIB_LOOKUP_NOREF)) |
189 | return 0; | 190 | return 0; |
190 | 191 | ||
191 | table = fib_get_table(net, RT_TABLE_MAIN); | 192 | table = fib_get_table(net, RT_TABLE_MAIN); |
192 | if (!fib_table_lookup(table, flp, res)) | 193 | if (!fib_table_lookup(table, flp, res, FIB_LOOKUP_NOREF)) |
193 | return 0; | 194 | return 0; |
194 | return -ENETUNREACH; | 195 | return -ENETUNREACH; |
195 | } | 196 | } |
@@ -254,16 +255,6 @@ static inline void fib_info_put(struct fib_info *fi) | |||
254 | free_fib_info(fi); | 255 | free_fib_info(fi); |
255 | } | 256 | } |
256 | 257 | ||
257 | static inline void fib_res_put(struct fib_result *res) | ||
258 | { | ||
259 | if (res->fi) | ||
260 | fib_info_put(res->fi); | ||
261 | #ifdef CONFIG_IP_MULTIPLE_TABLES | ||
262 | if (res->r) | ||
263 | fib_rule_put(res->r); | ||
264 | #endif | ||
265 | } | ||
266 | |||
267 | #ifdef CONFIG_PROC_FS | 258 | #ifdef CONFIG_PROC_FS |
268 | extern int __net_init fib_proc_init(struct net *net); | 259 | extern int __net_init fib_proc_init(struct net *net); |
269 | extern void __net_exit fib_proc_exit(struct net *net); | 260 | extern void __net_exit fib_proc_exit(struct net *net); |