aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ip_output.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-01-06 20:22:09 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-06 20:22:09 -0500
commit9753dfe19a85e7e45a34a56f4cb2048bb4f50e27 (patch)
treec017a1b4a70b8447c71b01d8b320e071546b5c9d /net/ipv4/ip_output.c
parentedf7c8148ec40c0fd27c0ef3f688defcc65e3913 (diff)
parent9f42f126154786e6e76df513004800c8c633f020 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1958 commits) net: pack skb_shared_info more efficiently net_sched: red: split red_parms into parms and vars net_sched: sfq: extend limits cnic: Improve error recovery on bnx2x devices cnic: Re-init dev->stats_addr after chip reset net_sched: Bug in netem reordering bna: fix sparse warnings/errors bna: make ethtool_ops and strings const xgmac: cleanups net: make ethtool_ops const vmxnet3" make ethtool ops const xen-netback: make ops structs const virtio_net: Pass gfp flags when allocating rx buffers. ixgbe: FCoE: Add support for ndo_get_fcoe_hbainfo() call netdev: FCoE: Add new ndo_get_fcoe_hbainfo() call igb: reset PHY after recovering from PHY power down igb: add basic runtime PM support igb: Add support for byte queue limits. e1000: cleanup CE4100 MDIO registers access e1000: unmap ce4100_gbe_mdio_base_virt in e1000_remove ...
Diffstat (limited to 'net/ipv4/ip_output.c')
-rw-r--r--net/ipv4/ip_output.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 0bc95f3977d2..ff302bde8890 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -206,7 +206,7 @@ static inline int ip_finish_output2(struct sk_buff *skb)
206 } 206 }
207 207
208 rcu_read_lock(); 208 rcu_read_lock();
209 neigh = dst_get_neighbour(dst); 209 neigh = dst_get_neighbour_noref(dst);
210 if (neigh) { 210 if (neigh) {
211 int res = neigh_output(neigh, skb); 211 int res = neigh_output(neigh, skb);
212 212
@@ -319,6 +319,20 @@ int ip_output(struct sk_buff *skb)
319 !(IPCB(skb)->flags & IPSKB_REROUTED)); 319 !(IPCB(skb)->flags & IPSKB_REROUTED));
320} 320}
321 321
322/*
323 * copy saddr and daddr, possibly using 64bit load/stores
324 * Equivalent to :
325 * iph->saddr = fl4->saddr;
326 * iph->daddr = fl4->daddr;
327 */
328static void ip_copy_addrs(struct iphdr *iph, const struct flowi4 *fl4)
329{
330 BUILD_BUG_ON(offsetof(typeof(*fl4), daddr) !=
331 offsetof(typeof(*fl4), saddr) + sizeof(fl4->saddr));
332 memcpy(&iph->saddr, &fl4->saddr,
333 sizeof(fl4->saddr) + sizeof(fl4->daddr));
334}
335
322int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl) 336int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl)
323{ 337{
324 struct sock *sk = skb->sk; 338 struct sock *sk = skb->sk;
@@ -381,8 +395,8 @@ packet_routed:
381 iph->frag_off = 0; 395 iph->frag_off = 0;
382 iph->ttl = ip_select_ttl(inet, &rt->dst); 396 iph->ttl = ip_select_ttl(inet, &rt->dst);
383 iph->protocol = sk->sk_protocol; 397 iph->protocol = sk->sk_protocol;
384 iph->saddr = fl4->saddr; 398 ip_copy_addrs(iph, fl4);
385 iph->daddr = fl4->daddr; 399
386 /* Transport layer set skb->h.foo itself. */ 400 /* Transport layer set skb->h.foo itself. */
387 401
388 if (inet_opt && inet_opt->opt.optlen) { 402 if (inet_opt && inet_opt->opt.optlen) {
@@ -1337,8 +1351,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk,
1337 ip_select_ident(iph, &rt->dst, sk); 1351 ip_select_ident(iph, &rt->dst, sk);
1338 iph->ttl = ttl; 1352 iph->ttl = ttl;
1339 iph->protocol = sk->sk_protocol; 1353 iph->protocol = sk->sk_protocol;
1340 iph->saddr = fl4->saddr; 1354 ip_copy_addrs(iph, fl4);
1341 iph->daddr = fl4->daddr;
1342 1355
1343 if (opt) { 1356 if (opt) {
1344 iph->ihl += opt->optlen>>2; 1357 iph->ihl += opt->optlen>>2;