Skip to content

Commit

Permalink
geneve: do not modify the shared tunnel info when PMTU triggers an IC…
Browse files Browse the repository at this point in the history
…MP reply

[ Upstream commit 68c1a94 ]

When the interface is part of a bridge or an Open vSwitch port and a
packet exceed a PMTU estimate, an ICMP reply is sent to the sender. When
using the external mode (collect metadata) the source and destination
addresses are reversed, so that Open vSwitch can match the packet
against an existing (reverse) flow.

But inverting the source and destination addresses in the shared
ip_tunnel_info will make following packets of the flow to use a wrong
destination address (packets will be tunnelled to itself), if the flow
isn't updated. Which happens with Open vSwitch, until the flow times
out.

Fixes this by uncloning the skb's ip_tunnel_info before inverting its
source and destination addresses, so that the modification will only be
made for the PTMU packet, not the following ones.

Fixes: c1a800e ("geneve: Support for PMTU discovery on directly bridged links")
Tested-by: Eelco Chaudron <echaudro@redhat.com>
Reviewed-by: Eelco Chaudron <echaudro@redhat.com>
Signed-off-by: Antoine Tenart <atenart@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
atenart authored and gregkh committed Apr 14, 2021
1 parent f3bc188 commit 985c9bb
Showing 1 changed file with 20 additions and 4 deletions.
24 changes: 20 additions & 4 deletions drivers/net/geneve.c
Original file line number Diff line number Diff line change
Expand Up @@ -907,8 +907,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)) {
Expand Down Expand Up @@ -992,8 +1000,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)) {
Expand Down

0 comments on commit 985c9bb

Please sign in to comment.