aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/fib_semantics.c
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2010-10-05 06:41:36 -0400
committerDavid S. Miller <davem@davemloft.net>2010-10-05 23:39:38 -0400
commitebc0ffae5dfb4447e0a431ffe7fe1d467c48bbb9 (patch)
tree395e50547ffccc6b73e04a44190eb4b4f2d2316b /net/ipv4/fib_semantics.c
parentc2952c314b4fe61820ba8fd6c949eed636140d52 (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 'net/ipv4/fib_semantics.c')
-rw-r--r--net/ipv4/fib_semantics.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index ba52f399a898..0f80dfc2f7fb 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -148,6 +148,13 @@ static const struct
148 148
149/* Release a nexthop info record */ 149/* Release a nexthop info record */
150 150
151static void free_fib_info_rcu(struct rcu_head *head)
152{
153 struct fib_info *fi = container_of(head, struct fib_info, rcu);
154
155 kfree(fi);
156}
157
151void free_fib_info(struct fib_info *fi) 158void free_fib_info(struct fib_info *fi)
152{ 159{
153 if (fi->fib_dead == 0) { 160 if (fi->fib_dead == 0) {
@@ -161,7 +168,7 @@ void free_fib_info(struct fib_info *fi)
161 } endfor_nexthops(fi); 168 } endfor_nexthops(fi);
162 fib_info_cnt--; 169 fib_info_cnt--;
163 release_net(fi->fib_net); 170 release_net(fi->fib_net);
164 kfree(fi); 171 call_rcu(&fi->rcu, free_fib_info_rcu);
165} 172}
166 173
167void fib_release_info(struct fib_info *fi) 174void fib_release_info(struct fib_info *fi)
@@ -553,6 +560,7 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi,
553 nh->nh_scope = RT_SCOPE_LINK; 560 nh->nh_scope = RT_SCOPE_LINK;
554 return 0; 561 return 0;
555 } 562 }
563 rcu_read_lock();
556 { 564 {
557 struct flowi fl = { 565 struct flowi fl = {
558 .nl_u = { 566 .nl_u = {
@@ -568,8 +576,10 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi,
568 if (fl.fl4_scope < RT_SCOPE_LINK) 576 if (fl.fl4_scope < RT_SCOPE_LINK)
569 fl.fl4_scope = RT_SCOPE_LINK; 577 fl.fl4_scope = RT_SCOPE_LINK;
570 err = fib_lookup(net, &fl, &res); 578 err = fib_lookup(net, &fl, &res);
571 if (err) 579 if (err) {
580 rcu_read_unlock();
572 return err; 581 return err;
582 }
573 } 583 }
574 err = -EINVAL; 584 err = -EINVAL;
575 if (res.type != RTN_UNICAST && res.type != RTN_LOCAL) 585 if (res.type != RTN_UNICAST && res.type != RTN_LOCAL)
@@ -585,7 +595,7 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi,
585 goto out; 595 goto out;
586 err = 0; 596 err = 0;
587out: 597out:
588 fib_res_put(&res); 598 rcu_read_unlock();
589 return err; 599 return err;
590 } else { 600 } else {
591 struct in_device *in_dev; 601 struct in_device *in_dev;
@@ -879,7 +889,7 @@ failure:
879 889
880/* Note! fib_semantic_match intentionally uses RCU list functions. */ 890/* Note! fib_semantic_match intentionally uses RCU list functions. */
881int fib_semantic_match(struct list_head *head, const struct flowi *flp, 891int fib_semantic_match(struct list_head *head, const struct flowi *flp,
882 struct fib_result *res, int prefixlen) 892 struct fib_result *res, int prefixlen, int fib_flags)
883{ 893{
884 struct fib_alias *fa; 894 struct fib_alias *fa;
885 int nh_sel = 0; 895 int nh_sel = 0;
@@ -943,7 +953,8 @@ out_fill_res:
943 res->type = fa->fa_type; 953 res->type = fa->fa_type;
944 res->scope = fa->fa_scope; 954 res->scope = fa->fa_scope;
945 res->fi = fa->fa_info; 955 res->fi = fa->fa_info;
946 atomic_inc(&res->fi->fib_clntref); 956 if (!(fib_flags & FIB_LOOKUP_NOREF))
957 atomic_inc(&res->fi->fib_clntref);
947 return 0; 958 return 0;
948} 959}
949 960