Skip to content

Commit 68c1a94

Browse files
atenartdavem330
authored andcommitted
geneve: do not modify the shared tunnel info when PMTU triggers an ICMP reply
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 <[email protected]> Reviewed-by: Eelco Chaudron <[email protected]> Signed-off-by: Antoine Tenart <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 30a93d2 commit 68c1a94

File tree

1 file changed

+20
-4
lines changed

1 file changed

+20
-4
lines changed

drivers/net/geneve.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -908,8 +908,16 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
908908

909909
info = skb_tunnel_info(skb);
910910
if (info) {
911-
info->key.u.ipv4.dst = fl4.saddr;
912-
info->key.u.ipv4.src = fl4.daddr;
911+
struct ip_tunnel_info *unclone;
912+
913+
unclone = skb_tunnel_info_unclone(skb);
914+
if (unlikely(!unclone)) {
915+
dst_release(&rt->dst);
916+
return -ENOMEM;
917+
}
918+
919+
unclone->key.u.ipv4.dst = fl4.saddr;
920+
unclone->key.u.ipv4.src = fl4.daddr;
913921
}
914922

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

9951003
if (info) {
996-
info->key.u.ipv6.dst = fl6.saddr;
997-
info->key.u.ipv6.src = fl6.daddr;
1004+
struct ip_tunnel_info *unclone;
1005+
1006+
unclone = skb_tunnel_info_unclone(skb);
1007+
if (unlikely(!unclone)) {
1008+
dst_release(dst);
1009+
return -ENOMEM;
1010+
}
1011+
1012+
unclone->key.u.ipv6.dst = fl6.saddr;
1013+
unclone->key.u.ipv6.src = fl6.daddr;
9981014
}
9991015

10001016
if (!pskb_may_pull(skb, ETH_HLEN)) {

0 commit comments

Comments
 (0)