aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2010-05-10 07:31:49 -0400
committerDavid S. Miller <davem@davemloft.net>2010-05-17 20:18:52 -0400
commitab6e3feba1f1bc3b9418b854da6f481408d243de (patch)
tree18977292fa858067f7cc4d7a7df8a69dd5562a3d
parent4a94445c9a5cf5461fb41d80040033b9a8e2a85a (diff)
net: No dst refcounting in ip_queue_xmit()
TCP outgoing packets can avoid two atomic ops, and dirtying of previously higly contended cache line using new refdst infrastructure. Note 1: loopback device excluded because of !IFF_XMIT_DST_RELEASE Note 2: UDP packets dsts are built before ip_queue_xmit(). Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv4/ip_output.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 252897443ef9..9a4a6c96cb0d 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -318,10 +318,12 @@ int ip_queue_xmit(struct sk_buff *skb)
318 struct ip_options *opt = inet->opt; 318 struct ip_options *opt = inet->opt;
319 struct rtable *rt; 319 struct rtable *rt;
320 struct iphdr *iph; 320 struct iphdr *iph;
321 int res;
321 322
322 /* Skip all of this if the packet is already routed, 323 /* Skip all of this if the packet is already routed,
323 * f.e. by something like SCTP. 324 * f.e. by something like SCTP.
324 */ 325 */
326 rcu_read_lock();
325 rt = skb_rtable(skb); 327 rt = skb_rtable(skb);
326 if (rt != NULL) 328 if (rt != NULL)
327 goto packet_routed; 329 goto packet_routed;
@@ -359,7 +361,7 @@ int ip_queue_xmit(struct sk_buff *skb)
359 } 361 }
360 sk_setup_caps(sk, &rt->u.dst); 362 sk_setup_caps(sk, &rt->u.dst);
361 } 363 }
362 skb_dst_set(skb, dst_clone(&rt->u.dst)); 364 skb_dst_set_noref(skb, &rt->u.dst);
363 365
364packet_routed: 366packet_routed:
365 if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway) 367 if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway)
@@ -391,9 +393,12 @@ packet_routed:
391 skb->priority = sk->sk_priority; 393 skb->priority = sk->sk_priority;
392 skb->mark = sk->sk_mark; 394 skb->mark = sk->sk_mark;
393 395
394 return ip_local_out(skb); 396 res = ip_local_out(skb);
397 rcu_read_unlock();
398 return res;
395 399
396no_route: 400no_route:
401 rcu_read_unlock();
397 IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); 402 IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
398 kfree_skb(skb); 403 kfree_skb(skb);
399 return -EHOSTUNREACH; 404 return -EHOSTUNREACH;