diff options
| author | Eric Dumazet <edumazet@google.com> | 2014-04-15 13:47:15 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2014-04-15 13:47:15 -0400 |
| commit | aad88724c9d54acb1a9737cb6069d8470fa85f74 (patch) | |
| tree | 78cc7b925f3d05338373898f018892b8f434a948 | |
| parent | b0270e91014dabfceaf37f5b40ad51bbf21a1302 (diff) | |
ipv4: add a sock pointer to dst->output() path.
In the dst->output() path for ipv4, the code assumes the skb it has to
transmit is attached to an inet socket, specifically via
ip_mc_output() : The sk_mc_loop() test triggers a WARN_ON() when the
provider of the packet is an AF_PACKET socket.
The dst->output() method gets an additional 'struct sock *sk'
parameter. This needs a cascade of changes so that this parameter can
be propagated from vxlan to final consumer.
Fixes: 8f646c922d55 ("vxlan: keep original skb ownership")
Reported-by: lucien xin <lucien.xin@gmail.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/vxlan.c | 4 | ||||
| -rw-r--r-- | include/net/dst.h | 14 | ||||
| -rw-r--r-- | include/net/ip.h | 11 | ||||
| -rw-r--r-- | include/net/ip_tunnels.h | 2 | ||||
| -rw-r--r-- | include/net/ipv6.h | 2 | ||||
| -rw-r--r-- | include/net/xfrm.h | 6 | ||||
| -rw-r--r-- | net/core/dst.c | 15 | ||||
| -rw-r--r-- | net/decnet/dn_route.c | 16 | ||||
| -rw-r--r-- | net/ipv4/ip_output.c | 11 | ||||
| -rw-r--r-- | net/ipv4/ip_tunnel.c | 2 | ||||
| -rw-r--r-- | net/ipv4/ip_tunnel_core.c | 4 | ||||
| -rw-r--r-- | net/ipv4/route.c | 4 | ||||
| -rw-r--r-- | net/ipv4/xfrm4_output.c | 2 | ||||
| -rw-r--r-- | net/ipv6/ip6_output.c | 2 | ||||
| -rw-r--r-- | net/ipv6/route.c | 14 | ||||
| -rw-r--r-- | net/ipv6/sit.c | 5 | ||||
| -rw-r--r-- | net/ipv6/xfrm6_output.c | 2 | ||||
| -rw-r--r-- | net/openvswitch/vport-gre.c | 2 | ||||
| -rw-r--r-- | net/xfrm/xfrm_policy.c | 2 |
19 files changed, 74 insertions, 46 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index c55e316373a1..82355d5d155a 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c | |||
| @@ -1755,8 +1755,8 @@ int vxlan_xmit_skb(struct vxlan_sock *vs, | |||
| 1755 | if (err) | 1755 | if (err) |
| 1756 | return err; | 1756 | return err; |
| 1757 | 1757 | ||
| 1758 | return iptunnel_xmit(rt, skb, src, dst, IPPROTO_UDP, tos, ttl, df, | 1758 | return iptunnel_xmit(vs->sock->sk, rt, skb, src, dst, IPPROTO_UDP, |
| 1759 | false); | 1759 | tos, ttl, df, false); |
| 1760 | } | 1760 | } |
| 1761 | EXPORT_SYMBOL_GPL(vxlan_xmit_skb); | 1761 | EXPORT_SYMBOL_GPL(vxlan_xmit_skb); |
| 1762 | 1762 | ||
diff --git a/include/net/dst.h b/include/net/dst.h index 46ed958e0c6e..71c60f42be48 100644 --- a/include/net/dst.h +++ b/include/net/dst.h | |||
| @@ -45,7 +45,7 @@ struct dst_entry { | |||
| 45 | void *__pad1; | 45 | void *__pad1; |
| 46 | #endif | 46 | #endif |
| 47 | int (*input)(struct sk_buff *); | 47 | int (*input)(struct sk_buff *); |
| 48 | int (*output)(struct sk_buff *); | 48 | int (*output)(struct sock *sk, struct sk_buff *skb); |
| 49 | 49 | ||
| 50 | unsigned short flags; | 50 | unsigned short flags; |
| 51 | #define DST_HOST 0x0001 | 51 | #define DST_HOST 0x0001 |
| @@ -367,7 +367,11 @@ static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb) | |||
| 367 | return child; | 367 | return child; |
| 368 | } | 368 | } |
| 369 | 369 | ||
| 370 | int dst_discard(struct sk_buff *skb); | 370 | int dst_discard_sk(struct sock *sk, struct sk_buff *skb); |
| 371 | static inline int dst_discard(struct sk_buff *skb) | ||
| 372 | { | ||
| 373 | return dst_discard_sk(skb->sk, skb); | ||
| 374 | } | ||
| 371 | void *dst_alloc(struct dst_ops *ops, struct net_device *dev, int initial_ref, | 375 | void *dst_alloc(struct dst_ops *ops, struct net_device *dev, int initial_ref, |
| 372 | int initial_obsolete, unsigned short flags); | 376 | int initial_obsolete, unsigned short flags); |
| 373 | void __dst_free(struct dst_entry *dst); | 377 | void __dst_free(struct dst_entry *dst); |
| @@ -449,9 +453,13 @@ static inline void dst_set_expires(struct dst_entry *dst, int timeout) | |||
| 449 | } | 453 | } |
| 450 | 454 | ||
| 451 | /* Output packet to network from transport. */ | 455 | /* Output packet to network from transport. */ |
| 456 | static inline int dst_output_sk(struct sock *sk, struct sk_buff *skb) | ||
| 457 | { | ||
| 458 | return skb_dst(skb)->output(sk, skb); | ||
| 459 | } | ||
| 452 | static inline int dst_output(struct sk_buff *skb) | 460 | static inline int dst_output(struct sk_buff *skb) |
| 453 | { | 461 | { |
| 454 | return skb_dst(skb)->output(skb); | 462 | return dst_output_sk(skb->sk, skb); |
| 455 | } | 463 | } |
| 456 | 464 | ||
| 457 | /* Input packet from network to transport. */ | 465 | /* Input packet from network to transport. */ |
diff --git a/include/net/ip.h b/include/net/ip.h index 77e73d293e09..3ec2b0fb9d83 100644 --- a/include/net/ip.h +++ b/include/net/ip.h | |||
| @@ -104,13 +104,18 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, | |||
| 104 | struct net_device *orig_dev); | 104 | struct net_device *orig_dev); |
| 105 | int ip_local_deliver(struct sk_buff *skb); | 105 | int ip_local_deliver(struct sk_buff *skb); |
| 106 | int ip_mr_input(struct sk_buff *skb); | 106 | int ip_mr_input(struct sk_buff *skb); |
| 107 | int ip_output(struct sk_buff *skb); | 107 | int ip_output(struct sock *sk, struct sk_buff *skb); |
| 108 | int ip_mc_output(struct sk_buff *skb); | 108 | int ip_mc_output(struct sock *sk, struct sk_buff *skb); |
| 109 | int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)); | 109 | int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)); |
| 110 | int ip_do_nat(struct sk_buff *skb); | 110 | int ip_do_nat(struct sk_buff *skb); |
| 111 | void ip_send_check(struct iphdr *ip); | 111 | void ip_send_check(struct iphdr *ip); |
| 112 | int __ip_local_out(struct sk_buff *skb); | 112 | int __ip_local_out(struct sk_buff *skb); |
| 113 | int ip_local_out(struct sk_buff *skb); | 113 | int ip_local_out_sk(struct sock *sk, struct sk_buff *skb); |
| 114 | static inline int ip_local_out(struct sk_buff *skb) | ||
| 115 | { | ||
| 116 | return ip_local_out_sk(skb->sk, skb); | ||
| 117 | } | ||
| 118 | |||
| 114 | int ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl); | 119 | int ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl); |
| 115 | void ip_init(void); | 120 | void ip_init(void); |
| 116 | int ip_append_data(struct sock *sk, struct flowi4 *fl4, | 121 | int ip_append_data(struct sock *sk, struct flowi4 *fl4, |
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index e77c10405d51..a4daf9eb8562 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h | |||
| @@ -153,7 +153,7 @@ static inline u8 ip_tunnel_ecn_encap(u8 tos, const struct iphdr *iph, | |||
| 153 | } | 153 | } |
| 154 | 154 | ||
| 155 | int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto); | 155 | int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto); |
| 156 | int iptunnel_xmit(struct rtable *rt, struct sk_buff *skb, | 156 | int iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, |
| 157 | __be32 src, __be32 dst, __u8 proto, | 157 | __be32 src, __be32 dst, __u8 proto, |
| 158 | __u8 tos, __u8 ttl, __be16 df, bool xnet); | 158 | __u8 tos, __u8 ttl, __be16 df, bool xnet); |
| 159 | 159 | ||
diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 4f541f11ce63..d640925bc454 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h | |||
| @@ -731,7 +731,7 @@ struct dst_entry *ip6_blackhole_route(struct net *net, | |||
| 731 | * skb processing functions | 731 | * skb processing functions |
| 732 | */ | 732 | */ |
| 733 | 733 | ||
| 734 | int ip6_output(struct sk_buff *skb); | 734 | int ip6_output(struct sock *sk, struct sk_buff *skb); |
| 735 | int ip6_forward(struct sk_buff *skb); | 735 | int ip6_forward(struct sk_buff *skb); |
| 736 | int ip6_input(struct sk_buff *skb); | 736 | int ip6_input(struct sk_buff *skb); |
| 737 | int ip6_mc_input(struct sk_buff *skb); | 737 | int ip6_mc_input(struct sk_buff *skb); |
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 32682ae47b3f..116e9c7e19cb 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
| @@ -333,7 +333,7 @@ struct xfrm_state_afinfo { | |||
| 333 | const xfrm_address_t *saddr); | 333 | const xfrm_address_t *saddr); |
| 334 | int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n); | 334 | int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n); |
| 335 | int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n); | 335 | int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n); |
| 336 | int (*output)(struct sk_buff *skb); | 336 | int (*output)(struct sock *sk, struct sk_buff *skb); |
| 337 | int (*output_finish)(struct sk_buff *skb); | 337 | int (*output_finish)(struct sk_buff *skb); |
| 338 | int (*extract_input)(struct xfrm_state *x, | 338 | int (*extract_input)(struct xfrm_state *x, |
| 339 | struct sk_buff *skb); | 339 | struct sk_buff *skb); |
| @@ -1540,7 +1540,7 @@ static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi) | |||
| 1540 | 1540 | ||
| 1541 | int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb); | 1541 | int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb); |
| 1542 | int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb); | 1542 | int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb); |
| 1543 | int xfrm4_output(struct sk_buff *skb); | 1543 | int xfrm4_output(struct sock *sk, struct sk_buff *skb); |
| 1544 | int xfrm4_output_finish(struct sk_buff *skb); | 1544 | int xfrm4_output_finish(struct sk_buff *skb); |
| 1545 | int xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err); | 1545 | int xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err); |
| 1546 | int xfrm4_protocol_register(struct xfrm4_protocol *handler, unsigned char protocol); | 1546 | int xfrm4_protocol_register(struct xfrm4_protocol *handler, unsigned char protocol); |
| @@ -1565,7 +1565,7 @@ __be32 xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr); | |||
| 1565 | __be32 xfrm6_tunnel_spi_lookup(struct net *net, const xfrm_address_t *saddr); | 1565 | __be32 xfrm6_tunnel_spi_lookup(struct net *net, const xfrm_address_t *saddr); |
| 1566 | int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb); | 1566 | int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb); |
| 1567 | int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb); | 1567 | int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb); |
| 1568 | int xfrm6_output(struct sk_buff *skb); | 1568 | int xfrm6_output(struct sock *sk, struct sk_buff *skb); |
| 1569 | int xfrm6_output_finish(struct sk_buff *skb); | 1569 | int xfrm6_output_finish(struct sk_buff *skb); |
| 1570 | int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb, | 1570 | int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb, |
| 1571 | u8 **prevhdr); | 1571 | u8 **prevhdr); |
diff --git a/net/core/dst.c b/net/core/dst.c index ca4231ec7347..80d6286c8b62 100644 --- a/net/core/dst.c +++ b/net/core/dst.c | |||
| @@ -142,12 +142,12 @@ loop: | |||
| 142 | mutex_unlock(&dst_gc_mutex); | 142 | mutex_unlock(&dst_gc_mutex); |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | int dst_discard(struct sk_buff *skb) | 145 | int dst_discard_sk(struct sock *sk, struct sk_buff *skb) |
| 146 | { | 146 | { |
| 147 | kfree_skb(skb); | 147 | kfree_skb(skb); |
| 148 | return 0; | 148 | return 0; |
