Skip to content

Commit

Permalink
ipv4: Fix IPsec slowpath fragmentation problem
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Steffen Klassert authored and David S. Miller committed Jun 28, 2011
1 parent 33f99dc commit 353e5c9
Showing 1 changed file with 5 additions and 5 deletions.
10 changes: 5 additions & 5 deletions net/ipv4/ip_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -802,8 +802,6 @@ static int __ip_append_data(struct sock *sk,
skb = skb_peek_tail(queue);

exthdrlen = !skb ? rt->dst.header_len : 0;
length += exthdrlen;
transhdrlen += exthdrlen;
mtu = cork->fragsize;

hh_len = LL_RESERVED_SPACE(rt->dst.dev);
Expand Down Expand Up @@ -883,6 +881,8 @@ static int __ip_append_data(struct sock *sk,
else
alloclen = fraglen;

alloclen += exthdrlen;

/* The last fragment gets additional space at tail.
* Note, with MSG_MORE we overallocate on fragments,
* because we have no idea what fragment will be
Expand Down Expand Up @@ -923,11 +923,11 @@ static int __ip_append_data(struct sock *sk,
/*
* Find where to start putting bytes.
*/
data = skb_put(skb, fraglen);
data = skb_put(skb, fraglen + exthdrlen);
skb_set_network_header(skb, exthdrlen);
skb->transport_header = (skb->network_header +
fragheaderlen);
data += fragheaderlen;
data += fragheaderlen + exthdrlen;

if (fraggap) {
skb->csum = skb_copy_and_csum_bits(
Expand Down Expand Up @@ -1061,7 +1061,7 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork,
*/
*rtp = NULL;
cork->fragsize = inet->pmtudisc == IP_PMTUDISC_PROBE ?
rt->dst.dev->mtu : dst_mtu(rt->dst.path);
rt->dst.dev->mtu : dst_mtu(&rt->dst);
cork->dst = &rt->dst;
cork->length = 0;
cork->tx_flags = ipc->tx_flags;
Expand Down

0 comments on commit 353e5c9

Please sign in to comment.