Skip to content

Commit e774e6a

Browse files
ArtisticFantasygregkh
authored andcommitted
ipvs: fix PMTU for GUE/GRE tunnel ICMP errors
[ Upstream commit 6b335af ] When an ICMP Fragmentation Needed error is received for a tunneled IPVS connection, ip_vs_in_icmp() recomputes the MTU that the original packet can use by subtracting the tunnel overhead from the reported next-hop MTU. The current code always subtracts sizeof(struct iphdr), which is only the IPIP overhead. For GUE and GRE tunnels, ipvs_udp_decap() and ipvs_gre_decap() already compute the additional tunnel header length, but that value is scoped to the decapsulation block and is lost before the ICMP_FRAG_NEEDED handling. As a result, the ICMP error sent back to the client advertises an MTU that is too large, so PMTUD can fail to converge for GUE/GRE-tunneled real servers. With a reported next-hop MTU of 1400, a GUE tunnel currently returns 1380 to the client. The correct value is 1368: 1400 - sizeof(struct iphdr) - sizeof(struct udphdr) - sizeof(struct guehdr) Hoist the tunnel header length into the main ip_vs_in_icmp() scope and subtract sizeof(struct iphdr) + ulen in the Fragmentation Needed path. The IPIP path keeps ulen as 0, so its existing 1400 - 20 = 1380 result is unchanged. Fixes: 508f744 ("ipvs: strip udp tunnel headers from icmp errors") Cc: stable@vger.kernel.org Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn> Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn> Reported-by: Ao Wang <wangao@seu.edu.cn> Reported-by: Xuewei Feng <fengxw06@126.com> Reported-by: Qi Li <qli01@tsinghua.edu.cn> Reported-by: Ke Xu <xuke@tsinghua.edu.cn> Assisted-by: Claude-Code:GLM-5.2 Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn> Acked-by: Julian Anastasov <ja@ssi.bg> Signed-off-by: Florian Westphal <fw@strlen.de> Stable-dep-of: 3f7a535 ("ipvs: ensure inner headers in ICMP errors are in headroom") Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 5848e91 commit e774e6a

1 file changed

Lines changed: 3 additions & 3 deletions

File tree

net/netfilter/ipvs/ip_vs_core.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1594,6 +1594,7 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
15941594
bool tunnel, new_cp = false;
15951595
union nf_inet_addr *raddr;
15961596
char *outer_proto = "IPIP";
1597+
int ulen = 0;
15971598

15981599
*related = 1;
15991600

@@ -1658,7 +1659,6 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
16581659
/* Error for our tunnel must arrive at LOCAL_IN */
16591660
(skb_rtable(skb)->rt_flags & RTCF_LOCAL)) {
16601661
__u8 iproto;
1661-
int ulen;
16621662

16631663
/* Non-first fragment has no UDP/GRE header */
16641664
if (unlikely(cih->frag_off & htons(IP_OFFSET)))
@@ -1763,8 +1763,8 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
17631763
if (dest_dst)
17641764
mtu = dst_mtu(dest_dst->dst_cache);
17651765
}
1766-
if (mtu > 68 + sizeof(struct iphdr))
1767-
mtu -= sizeof(struct iphdr);
1766+
if (mtu > 68 + sizeof(struct iphdr) + ulen)
1767+
mtu -= sizeof(struct iphdr) + ulen;
17681768
info = htonl(mtu);
17691769
}
17701770
/* Strip outer IP, ICMP and IPIP/UDP/GRE, go to IP header of

0 commit comments

Comments
 (0)