aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteffen Klassert <steffen.klassert@secunet.com>2011-06-21 21:05:37 -0400
committerDavid S. Miller <davem@davemloft.net>2011-06-27 23:34:26 -0400
commit353e5c9abd900de3d1a40925386ffe4abf76111e (patch)
tree0aeb8a65afb48fb4011d4ee4aa243288d24c8daf
parent33f99dc7fd948bbc808a24a0989c167f8973b643 (diff)
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>
-rw-r--r--net/ipv4/ip_output.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 6b894d430e61..4a7e16b5d3f3 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -802,8 +802,6 @@ static int __ip_append_data(struct sock *sk,
802 skb = skb_peek_tail(queue); 802 skb = skb_peek_tail(queue);
803 803
804 exthdrlen = !skb ? rt->dst.header_len : 0; 804 exthdrlen = !skb ? rt->dst.header_len : 0;
805 length += exthdrlen;
806 transhdrlen += exthdrlen;
807 mtu = cork->fragsize; 805 mtu = cork->fragsize;
808 806
809 hh_len = LL_RESERVED_SPACE(rt->dst.dev); 807 hh_len = LL_RESERVED_SPACE(rt->dst.dev);
@@ -883,6 +881,8 @@ alloc_new_skb:
883 else 881 else
884 alloclen = fraglen; 882 alloclen = fraglen;
885 883
884 alloclen += exthdrlen;
885
886 /* The last fragment gets additional space at tail. 886 /* The last fragment gets additional space at tail.
887 * Note, with MSG_MORE we overallocate on fragments, 887 * Note, with MSG_MORE we overallocate on fragments,
888 * because we have no idea what fragment will be 888 * because we have no idea what fragment will be
@@ -923,11 +923,11 @@ alloc_new_skb:
923 /* 923 /*
924 * Find where to start putting bytes. 924 * Find where to start putting bytes.
925 */ 925 */
926 data = skb_put(skb, fraglen); 926 data = skb_put(skb, fraglen + exthdrlen);
927 skb_set_network_header(skb, exthdrlen); 927 skb_set_network_header(skb, exthdrlen);
928 skb->transport_header = (skb->network_header + 928 skb->transport_header = (skb->network_header +
929 fragheaderlen); 929 fragheaderlen);
930 data += fragheaderlen; 930 data += fragheaderlen + exthdrlen;
931 931
932 if (fraggap) { 932 if (fraggap) {
933 skb->csum = skb_copy_and_csum_bits( 933 skb->csum = skb_copy_and_csum_bits(
@@ -1061,7 +1061,7 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork,
1061 */ 1061 */
1062 *rtp = NULL; 1062 *rtp = NULL;
1063 cork->fragsize = inet->pmtudisc == IP_PMTUDISC_PROBE ? 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 cork->dst = &rt->dst; 1065 cork->dst = &rt->dst;
1066 cork->length = 0; 1066 cork->length = 0;
1067 cork->tx_flags = ipc->tx_flags; 1067 cork->tx_flags = ipc->tx_flags;