diff options
Diffstat (limited to 'drivers/net/vxlan.c')
| -rw-r--r-- | drivers/net/vxlan.c | 20 | 
1 files changed, 16 insertions, 4 deletions
| diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 666dd201c3d5..02a14f1b938a 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2725,12 +2725,17 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,  			goto tx_error;  		} else if (err) {  			if (info) { +				struct ip_tunnel_info *unclone;  				struct in_addr src, dst; +				unclone = skb_tunnel_info_unclone(skb); +				if (unlikely(!unclone)) +					goto tx_error; +  				src = remote_ip.sin.sin_addr;  				dst = local_ip.sin.sin_addr; -				info->key.u.ipv4.src = src.s_addr; -				info->key.u.ipv4.dst = dst.s_addr; +				unclone->key.u.ipv4.src = src.s_addr; +				unclone->key.u.ipv4.dst = dst.s_addr;  			}  			vxlan_encap_bypass(skb, vxlan, vxlan, vni, false);  			dst_release(ndst); @@ -2781,12 +2786,17 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,  			goto tx_error;  		} else if (err) {  			if (info) { +				struct ip_tunnel_info *unclone;  				struct in6_addr src, dst; +				unclone = skb_tunnel_info_unclone(skb); +				if (unlikely(!unclone)) +					goto tx_error; +  				src = remote_ip.sin6.sin6_addr;  				dst = local_ip.sin6.sin6_addr; -				info->key.u.ipv6.src = src; -				info->key.u.ipv6.dst = dst; +				unclone->key.u.ipv6.src = src; +				unclone->key.u.ipv6.dst = dst;  			}  			vxlan_encap_bypass(skb, vxlan, vxlan, vni, false); @@ -3484,6 +3494,7 @@ static struct socket *vxlan_create_sock(struct net *net, bool ipv6,  	if (err < 0)  		return ERR_PTR(err); +	udp_allow_gso(sock->sk);  	return sock;  } @@ -3703,6 +3714,7 @@ static int vxlan_config_validate(struct net *src_net, struct vxlan_config *conf,  #if IS_ENABLED(CONFIG_IPV6)  		if (use_ipv6) {  			struct inet6_dev *idev = __in6_dev_get(lowerdev); +  			if (idev && idev->cnf.disable_ipv6) {  				NL_SET_ERR_MSG(extack,  					       "IPv6 support disabled by administrator"); | 
