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 /net | |
| parent | b0270e91014dabfceaf37f5b40ad51bbf21a1302 (diff) | |
| download | linux-aad88724c9d54acb1a9737cb6069d8470fa85f74.tar.bz2 | |
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>
Diffstat (limited to 'net')
| -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 | 
13 files changed, 48 insertions, 33 deletions
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:  	mutex_unlock(&dst_gc_mutex);  } -int dst_discard(struct sk_buff *skb) +int dst_discard_sk(struct sock *sk, struct sk_buff *skb)  {  	kfree_skb(skb);  	return 0;  } -EXPORT_SYMBOL(dst_discard); +EXPORT_SYMBOL(dst_discard_sk);  const u32 dst_default_metrics[RTAX_MAX + 1] = {  	/* This initializer is needed to force linker to place this variable @@ -184,7 +184,7 @@ void *dst_alloc(struct dst_ops *ops, struct net_device *dev,  	dst->xfrm = NULL;  #endif  	dst->input = dst_discard; -	dst->output = dst_discard; +	dst->output = dst_discard_sk;  	dst->error = 0;  	dst->obsolete = initial_obsolete;  	dst->header_len = 0; @@ -209,8 +209,10 @@ static void ___dst_free(struct dst_entry *dst)  	/* The first case (dev==NULL) is required, when  	   protocol module is unloaded.  	 */ -	if (dst->dev == NULL || !(dst->dev->flags&IFF_UP)) -		dst->input = dst->output = dst_discard; +	if (dst->dev == NULL || !(dst->dev->flags&IFF_UP)) { +		dst->input = dst_discard; +		dst->output = dst_discard_sk; +	}  	dst->obsolete = DST_OBSOLETE_DEAD;  } @@ -361,7 +363,8 @@ static void dst_ifdown(struct dst_entry *dst, struct net_device *dev,  		return;  	if (!unregister) { -		dst->input = dst->output = dst_discard; +		dst->input = dst_discard; +		dst->output = dst_discard_sk;  	} else {  		dst->dev = dev_net(dst->dev)->loopback_dev;  		dev_hold(dst->dev); diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index ce0cbbfe0f43..daccc4a36d80 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -752,7 +752,7 @@ static int dn_to_neigh_output(struct sk_buff *skb)  	return n->output(n, skb);  } -static int dn_output(struct sk_buff *skb) +static int dn_output(struct sock *sk, struct sk_buff *skb)  {  	struct dst_entry *dst = skb_dst(skb);  	struct dn_route *rt = (struct dn_route *)dst; @@ -838,6 +838,18 @@ drop:   * Used to catch bugs. This should never normally get   * called.   */ +static int dn_rt_bug_sk(struct sock *sk, struct sk_buff *skb) +{ +	struct dn_skb_cb *cb = DN_SKB_CB(skb); + +	net_dbg_ratelimited("dn_rt_bug: skb from:%04x to:%04x\n", +			    le16_to_cpu(cb->src), le16_to_cpu(cb->dst)); + +	kfree_skb(skb); + +	return NET_RX_DROP; +} +  static int dn_rt_bug(struct sk_buff *skb)  {  	struct dn_skb_cb *cb = DN_SKB_CB(skb); @@ -1463,7 +1475,7 @@ make_route:  	rt->n = neigh;  	rt->dst.lastuse = jiffies; -	rt->dst.output = dn_rt_bug; +	rt->dst.output = dn_rt_bug_sk;  	switch (res.type) {  	case RTN_UNICAST:  		rt->dst.input = dn_forward; diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 7ad68b860935..1cbeba5edff9 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -101,17 +101,17 @@ int __ip_local_out(struct sk_buff *skb)  		       skb_dst(skb)->dev, dst_output);  } -int ip_local_out(struct sk_buff *skb) +int ip_local_out_sk(struct sock *sk, struct sk_buff *skb)  {  	int err;  	err = __ip_local_out(skb);  	if (likely(err == 1)) -		err = dst_output(skb); +		err = dst_output_sk(sk, skb);  	return err;  } -EXPORT_SYMBOL_GPL(ip_local_out); +EXPORT_SYMBOL_GPL(ip_local_out_sk);  static inline int ip_select_ttl(struct inet_sock *inet, struct dst_entry *dst)  { @@ -226,9 +226,8 @@ static int ip_finish_output(struct sk_buff *skb)  		return ip_finish_output2(skb);  } -int ip_mc_output(struct sk_buff *skb) +int ip_mc_output(struct sock *sk, struct sk_buff *skb)  { -	struct sock *sk = skb->sk;  	struct rtable *rt = skb_rtable(skb);  	struct net_device *dev = rt->dst.dev; @@ -287,7 +286,7 @@ int ip_mc_output(struct sk_buff *skb)  			    !(IPCB(skb)->flags & IPSKB_REROUTED));  } -int ip_output(struct sk_buff *skb) +int ip_output(struct sock *sk, struct sk_buff *skb)  {  	struct net_device *dev = skb_dst(skb)->dev; diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index e77381d1df9a..484d0ce27ef7 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -670,7 +670,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,  		return;  	} -	err = iptunnel_xmit(rt, skb, fl4.saddr, fl4.daddr, protocol, +	err = iptunnel_xmit(skb->sk, rt, skb, fl4.saddr, fl4.daddr, protocol,  			    tos, ttl, df, !net_eq(tunnel->net, dev_net(dev)));  	iptunnel_xmit_stats(err, &dev->stats, dev->tstats); diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c index e0c2b1d2ea4e..bcf206c79005 100644 --- a/net/ipv4/ip_tunnel_core.c +++ b/net/ipv4/ip_tunnel_core.c @@ -46,7 +46,7 @@  #include <net/netns/generic.h>  #include <net/rtnetlink.h> -int iptunnel_xmit(struct rtable *rt, struct sk_buff *skb, +int iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,  		  __be32 src, __be32 dst, __u8 proto,  		  __u8 tos, __u8 ttl, __be16 df, bool xnet)  { @@ -76,7 +76,7 @@ int iptunnel_xmit(struct rtable *rt, struct sk_buff *skb,  	iph->ttl	=	ttl;  	__ip_select_ident(iph, &rt->dst, (skb_shinfo(skb)->gso_segs ?: 1) - 1); -	err = ip_local_out(skb); +	err = ip_local_out_sk(sk, skb);  	if (unlikely(net_xmit_eval(err)))  		pkt_len = 0;  	return pkt_len; diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 20a59c388e6e..1485aafcad59 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1129,7 +1129,7 @@ static void ipv4_link_failure(struct sk_buff *skb)  		dst_set_expires(&rt->dst, 0);  } -static int ip_rt_bug(struct sk_buff *skb) +static int ip_rt_bug(struct sock *sk, struct sk_buff *skb)  {  	pr_debug("%s: %pI4 -> %pI4, %s\n",  		 __func__, &ip_hdr(skb)->saddr, &ip_hdr(skb)->daddr, @@ -2218,7 +2218,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or  		new->__use = 1;  		new->input = dst_discard; -		new->output = dst_discard; +		new->output = dst_discard_sk;  		new->dev = ort->dst.dev;  		if (new->dev) diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index baa0f63731fd..40e701f2e1e0 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c @@ -86,7 +86,7 @@ int xfrm4_output_finish(struct sk_buff *skb)  	return xfrm_output(skb);  } -int xfrm4_output(struct sk_buff *skb) +int xfrm4_output(struct sock *sk, struct sk_buff *skb)  {  	struct dst_entry *dst = skb_dst(skb);  	struct xfrm_state *x = dst->xfrm; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 3284d61577c0..40e7581374f7 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -132,7 +132,7 @@ static int ip6_finish_output(struct sk_buff *skb)  		return ip6_finish_output2(skb);  } -int ip6_output(struct sk_buff *skb) +int ip6_output(struct sock *sk, struct sk_buff *skb)  {  	struct net_device *dev = skb_dst(skb)->dev;  	struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 5ea462eacd9f..4011617cca68 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -84,9 +84,9 @@ static void		ip6_dst_ifdown(struct dst_entry *,  static int		 ip6_dst_gc(struct dst_ops *ops);  static int		ip6_pkt_discard(struct sk_buff *skb); -static int		ip6_pkt_discard_out(struct sk_buff *skb); +static int		ip6_pkt_discard_out(struct sock *sk, struct sk_buff *skb);  static int		ip6_pkt_prohibit(struct sk_buff *skb); -static int		ip6_pkt_prohibit_out(struct sk_buff *skb); +static int		ip6_pkt_prohibit_out(struct sock *sk, struct sk_buff *skb);  static void		ip6_link_failure(struct sk_buff *skb);  static void		ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,  					   struct sk_buff *skb, u32 mtu); @@ -290,7 +290,7 @@ static const struct rt6_info ip6_blk_hole_entry_template = {  		.obsolete	= DST_OBSOLETE_FORCE_CHK,  		.error		= -EINVAL,  		.input		= dst_discard, -		.output		= dst_discard, +		.output		= dst_discard_sk,  	},  	.rt6i_flags	= (RTF_REJECT | RTF_NONEXTHOP),  	.rt6i_protocol  = RTPROT_KERNEL, @@ -1058,7 +1058,7 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori  		new->__use = 1;  		new->input = dst_discard; -		new->output = dst_discard; +		new->output = dst_discard_sk;  		if (dst_metrics_read_only(&ort->dst))  			new->_metrics = ort->dst._metrics; @@ -1577,7 +1577,7 @@ int ip6_route_add(struct fib6_config *cfg)  		switch (cfg->fc_type) {  		case RTN_BLACKHOLE:  			rt->dst.error = -EINVAL; -			rt->dst.output = dst_discard; +			rt->dst.output = dst_discard_sk;  			rt->dst.input = dst_discard;  			break;  		case RTN_PROHIBIT: @@ -2129,7 +2129,7 @@ static int ip6_pkt_discard(struct sk_buff *skb)  	return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_INNOROUTES);  } -static int ip6_pkt_discard_out(struct sk_buff *skb) +static int ip6_pkt_discard_out(struct sock *sk, struct sk_buff *skb)  {  	skb->dev = skb_dst(skb)->dev;  	return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_OUTNOROUTES); @@ -2140,7 +2140,7 @@ static int ip6_pkt_prohibit(struct sk_buff *skb)  	return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_INNOROUTES);  } -static int ip6_pkt_prohibit_out(struct sk_buff *skb) +static int ip6_pkt_prohibit_out(struct sock *sk, struct sk_buff *skb)  {  	skb->dev = skb_dst(skb)->dev;  	return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 1693c8d885f0..8da8268d65f8 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -974,8 +974,9 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,  		goto out;  	} -	err = iptunnel_xmit(rt, skb, fl4.saddr, fl4.daddr, IPPROTO_IPV6, tos, -			    ttl, df, !net_eq(tunnel->net, dev_net(dev))); +	err = iptunnel_xmit(skb->sk, rt, skb, fl4.saddr, fl4.daddr, +			    IPPROTO_IPV6, tos, ttl, df, +			    !net_eq(tunnel->net, dev_net(dev)));  	iptunnel_xmit_stats(err, &dev->stats, dev->tstats);  	return NETDEV_TX_OK; diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 6cd625e37706..19ef329bdbf8 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c @@ -163,7 +163,7 @@ static int __xfrm6_output(struct sk_buff *skb)  	return x->outer_mode->afinfo->output_finish(skb);  } -int xfrm6_output(struct sk_buff *skb) +int xfrm6_output(struct sock *sk, struct sk_buff *skb)  {  	return NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb, NULL,  		       skb_dst(skb)->dev, __xfrm6_output); diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c index a3d6951602db..ebb6e2442554 100644 --- a/net/openvswitch/vport-gre.c +++ b/net/openvswitch/vport-gre.c @@ -174,7 +174,7 @@ static int gre_tnl_send(struct vport *vport, struct sk_buff *skb)  	skb->local_df = 1; -	return iptunnel_xmit(rt, skb, fl.saddr, +	return iptunnel_xmit(skb->sk, rt, skb, fl.saddr,  			     OVS_CB(skb)->tun_key->ipv4_dst, IPPROTO_GRE,  			     OVS_CB(skb)->tun_key->ipv4_tos,  			     OVS_CB(skb)->tun_key->ipv4_ttl, df, false); diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index f02f511b7107..c08fbd11ceff 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1842,7 +1842,7 @@ purge_queue:  	xfrm_pol_put(pol);  } -static int xdst_queue_output(struct sk_buff *skb) +static int xdst_queue_output(struct sock *sk, struct sk_buff *skb)  {  	unsigned long sched_next;  	struct dst_entry *dst = skb_dst(skb);  |