| From a6d95c5a628a09be129f25d5663a7e9db8261f51 Mon Sep 17 00:00:00 2001 |
| From: Jiri Bohac <jbohac@suse.cz> |
| Date: Wed, 26 Jan 2022 16:00:18 +0100 |
| Subject: Revert "xfrm: xfrm_state_mtu should return at least 1280 for ipv6" |
| |
| From: Jiri Bohac <jbohac@suse.cz> |
| |
| commit a6d95c5a628a09be129f25d5663a7e9db8261f51 upstream. |
| |
| This reverts commit b515d2637276a3810d6595e10ab02c13bfd0b63a. |
| |
| Commit b515d2637276a3810d6595e10ab02c13bfd0b63a ("xfrm: xfrm_state_mtu |
| should return at least 1280 for ipv6") in v5.14 breaks the TCP MSS |
| calculation in ipsec transport mode, resulting complete stalls of TCP |
| connections. This happens when the (P)MTU is 1280 or slighly larger. |
| |
| The desired formula for the MSS is: |
| MSS = (MTU - ESP_overhead) - IP header - TCP header |
| |
| However, the above commit clamps the (MTU - ESP_overhead) to a |
| minimum of 1280, turning the formula into |
| MSS = max(MTU - ESP overhead, 1280) - IP header - TCP header |
| |
| With the (P)MTU near 1280, the calculated MSS is too large and the |
| resulting TCP packets never make it to the destination because they |
| are over the actual PMTU. |
| |
| The above commit also causes suboptimal double fragmentation in |
| xfrm tunnel mode, as described in |
| https://lore.kernel.org/netdev/20210429202529.codhwpc7w6kbudug@dwarf.suse.cz/ |
| |
| The original problem the above commit was trying to fix is now fixed |
| by commit 6596a0229541270fb8d38d989f91b78838e5e9da ("xfrm: fix MTU |
| regression"). |
| |
| Signed-off-by: Jiri Bohac <jbohac@suse.cz> |
| Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| include/net/xfrm.h | 1 - |
| net/ipv4/esp4.c | 2 +- |
| net/ipv6/esp6.c | 2 +- |
| net/xfrm/xfrm_state.c | 14 ++------------ |
| 4 files changed, 4 insertions(+), 15 deletions(-) |
| |
| --- a/include/net/xfrm.h |
| +++ b/include/net/xfrm.h |
| @@ -1543,7 +1543,6 @@ void xfrm_sad_getinfo(struct net *net, s |
| void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si); |
| u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq); |
| int xfrm_init_replay(struct xfrm_state *x); |
| -u32 __xfrm_state_mtu(struct xfrm_state *x, int mtu); |
| u32 xfrm_state_mtu(struct xfrm_state *x, int mtu); |
| int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload); |
| int xfrm_init_state(struct xfrm_state *x); |
| --- a/net/ipv4/esp4.c |
| +++ b/net/ipv4/esp4.c |
| @@ -499,7 +499,7 @@ static int esp_output(struct xfrm_state |
| struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb); |
| u32 padto; |
| |
| - padto = min(x->tfcpad, __xfrm_state_mtu(x, dst->child_mtu_cached)); |
| + padto = min(x->tfcpad, xfrm_state_mtu(x, dst->child_mtu_cached)); |
| if (skb->len < padto) |
| esp.tfclen = padto - skb->len; |
| } |
| --- a/net/ipv6/esp6.c |
| +++ b/net/ipv6/esp6.c |
| @@ -440,7 +440,7 @@ static int esp6_output(struct xfrm_state |
| struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb); |
| u32 padto; |
| |
| - padto = min(x->tfcpad, __xfrm_state_mtu(x, dst->child_mtu_cached)); |
| + padto = min(x->tfcpad, xfrm_state_mtu(x, dst->child_mtu_cached)); |
| if (skb->len < padto) |
| esp.tfclen = padto - skb->len; |
| } |
| --- a/net/xfrm/xfrm_state.c |
| +++ b/net/xfrm/xfrm_state.c |
| @@ -2440,7 +2440,7 @@ void xfrm_state_delete_tunnel(struct xfr |
| } |
| EXPORT_SYMBOL(xfrm_state_delete_tunnel); |
| |
| -u32 __xfrm_state_mtu(struct xfrm_state *x, int mtu) |
| +u32 xfrm_state_mtu(struct xfrm_state *x, int mtu) |
| { |
| const struct xfrm_type *type = READ_ONCE(x->type); |
| struct crypto_aead *aead; |
| @@ -2471,17 +2471,7 @@ u32 __xfrm_state_mtu(struct xfrm_state * |
| return ((mtu - x->props.header_len - crypto_aead_authsize(aead) - |
| net_adj) & ~(blksize - 1)) + net_adj - 2; |
| } |
| -EXPORT_SYMBOL_GPL(__xfrm_state_mtu); |
| - |
| -u32 xfrm_state_mtu(struct xfrm_state *x, int mtu) |
| -{ |
| - mtu = __xfrm_state_mtu(x, mtu); |
| - |
| - if (x->props.family == AF_INET6 && mtu < IPV6_MIN_MTU) |
| - return IPV6_MIN_MTU; |
| - |
| - return mtu; |
| -} |
| +EXPORT_SYMBOL_GPL(xfrm_state_mtu); |
| |
| int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload) |
| { |