Commit 3cec1921 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'tunnel-shinfo'



Antoine Tenart says:

====================
net: do not modify the shared tunnel info when PMTU triggers an ICMP reply

The series fixes an issue were a shared ip_tunnel_info is modified when
PMTU triggers an ICMP reply in vxlan and geneve, making following
packets in that flow to have a wrong destination address if the flow
isn't updated. A detailled information is given in each of the two
commits.

This was tested manually with OVS and I ran the PTMU selftests with
kmemleak enabled (all OK, none was skipped).
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents aa5a5b7a 68c1a943
Loading
Loading
Loading
Loading
+20 −4
Original line number Diff line number Diff line
@@ -908,8 +908,16 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,

		info = skb_tunnel_info(skb);
		if (info) {
			info->key.u.ipv4.dst = fl4.saddr;
			info->key.u.ipv4.src = fl4.daddr;
			struct ip_tunnel_info *unclone;

			unclone = skb_tunnel_info_unclone(skb);
			if (unlikely(!unclone)) {
				dst_release(&rt->dst);
				return -ENOMEM;
			}

			unclone->key.u.ipv4.dst = fl4.saddr;
			unclone->key.u.ipv4.src = fl4.daddr;
		}

		if (!pskb_may_pull(skb, ETH_HLEN)) {
@@ -993,8 +1001,16 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
		struct ip_tunnel_info *info = skb_tunnel_info(skb);

		if (info) {
			info->key.u.ipv6.dst = fl6.saddr;
			info->key.u.ipv6.src = fl6.daddr;
			struct ip_tunnel_info *unclone;

			unclone = skb_tunnel_info_unclone(skb);
			if (unlikely(!unclone)) {
				dst_release(dst);
				return -ENOMEM;
			}

			unclone->key.u.ipv6.dst = fl6.saddr;
			unclone->key.u.ipv6.src = fl6.daddr;
		}

		if (!pskb_may_pull(skb, ETH_HLEN)) {
+14 −4
Original line number Diff line number Diff line
@@ -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);