]> git.itanic.dy.fi Git - linux-stable/commitdiff
Revert "xfrm: xfrm_state_mtu should return at least 1280 for ipv6"
authorJiri Bohac <jbohac@suse.cz>
Wed, 26 Jan 2022 15:00:18 +0000 (16:00 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 8 Mar 2022 18:07:50 +0000 (19:07 +0100)
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
net/ipv4/esp4.c
net/ipv6/esp6.c
net/xfrm/xfrm_state.c

index 8ce63850d6d01c67d5ae338688cb660a0a3a80a9..614f19bbad74f90873b4b413e6d153d81a109fa3 100644 (file)
@@ -1543,7 +1543,6 @@ void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si);
 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);
index 86c836fa21459d3446d7b6d0acf9069b4f43da37..00210e55b4cd1526b15e8dbf4e2c6b2bf0ae46e1 100644 (file)
@@ -499,7 +499,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
                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;
        }
index 12570a73def80b3ff227b75bd0af332f91fab165..7a739f16d82b2e325b34efe62da3a00a0f4e2f41 100644 (file)
@@ -440,7 +440,7 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
                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;
        }
index c6b2c99b501b9dffe4b186b5a52e9f86710d5cf7..1423e2b7cb42a54e2ebbcadaa2c38a81e2b9be5e 100644 (file)
@@ -2440,7 +2440,7 @@ void xfrm_state_delete_tunnel(struct xfrm_state *x)
 }
 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 *x, int mtu)
        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)
 {