Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ipv4: Fix IPsec slowpath fragmentation problem

ip_append_data() builds packets based on the mtu from dst_mtu(rt->dst.path).
On IPsec the effective mtu is lower because we need to add the protocol
headers and trailers later when we do the IPsec transformations. So after
the IPsec transformations the packet might be too big, which leads to a
slowpath fragmentation then. This patch fixes this by building the packets
based on the lower IPsec mtu from dst_mtu(&rt->dst) and adapts the exthdr
handling to this.

Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Steffen Klassert and committed by
David S. Miller
353e5c9a 33f99dc7

+5 -5
+5 -5
net/ipv4/ip_output.c
··· 802 802 skb = skb_peek_tail(queue); 803 803 804 804 exthdrlen = !skb ? rt->dst.header_len : 0; 805 - length += exthdrlen; 806 - transhdrlen += exthdrlen; 807 805 mtu = cork->fragsize; 808 806 809 807 hh_len = LL_RESERVED_SPACE(rt->dst.dev); ··· 881 883 else 882 884 alloclen = fraglen; 883 885 886 + alloclen += exthdrlen; 887 + 884 888 /* The last fragment gets additional space at tail. 885 889 * Note, with MSG_MORE we overallocate on fragments, 886 890 * because we have no idea what fragment will be ··· 923 923 /* 924 924 * Find where to start putting bytes. 925 925 */ 926 - data = skb_put(skb, fraglen); 926 + data = skb_put(skb, fraglen + exthdrlen); 927 927 skb_set_network_header(skb, exthdrlen); 928 928 skb->transport_header = (skb->network_header + 929 929 fragheaderlen); 930 - data += fragheaderlen; 930 + data += fragheaderlen + exthdrlen; 931 931 932 932 if (fraggap) { 933 933 skb->csum = skb_copy_and_csum_bits( ··· 1061 1061 */ 1062 1062 *rtp = NULL; 1063 1063 cork->fragsize = inet->pmtudisc == IP_PMTUDISC_PROBE ? 1064 - rt->dst.dev->mtu : dst_mtu(rt->dst.path); 1064 + rt->dst.dev->mtu : dst_mtu(&rt->dst); 1065 1065 cork->dst = &rt->dst; 1066 1066 cork->length = 0; 1067 1067 cork->tx_flags = ipc->tx_flags;