Skip to content

Commit

Permalink
net: No dst refcounting in ip_queue_xmit()
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Eric Dumazet authored and David S. Miller committed May 18, 2010
1 parent 4a94445 commit ab6e3fe
Showing 1 changed file with 7 additions and 2 deletions.
9 changes: 7 additions & 2 deletions net/ipv4/ip_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,10 +318,12 @@ int ip_queue_xmit(struct sk_buff *skb)
struct ip_options *opt = inet->opt;
struct rtable *rt;
struct iphdr *iph;
int res;

/* Skip all of this if the packet is already routed,
* f.e. by something like SCTP.
*/
rcu_read_lock();
rt = skb_rtable(skb);
if (rt != NULL)
goto packet_routed;
Expand Down Expand Up @@ -359,7 +361,7 @@ int ip_queue_xmit(struct sk_buff *skb)
}
sk_setup_caps(sk, &rt->u.dst);
}
skb_dst_set(skb, dst_clone(&rt->u.dst));
skb_dst_set_noref(skb, &rt->u.dst);

packet_routed:
if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway)
Expand Down Expand Up @@ -391,9 +393,12 @@ int ip_queue_xmit(struct sk_buff *skb)
skb->priority = sk->sk_priority;
skb->mark = sk->sk_mark;

return ip_local_out(skb);
res = ip_local_out(skb);
rcu_read_unlock();
return res;

no_route:
rcu_read_unlock();
IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
kfree_skb(skb);
return -EHOSTUNREACH;
Expand Down

0 comments on commit ab6e3fe

Please sign in to comment.