aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorlucien <lucien.xin@gmail.com>2014-03-17 00:51:01 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-04-14 09:42:17 -0400
commit8e5612a299431024c3b8c136ba4cb7c523dec934 (patch)
tree365e234a8141ad09c543277819523efc26395225 /net
parent9b12db3dd5abcf63b452296f34440dbdff6c16e5 (diff)
ipv6: ip6_append_data_mtu do not handle the mtu of the second fragment properly
[ Upstream commit e367c2d03dba4c9bcafad24688fadb79dd95b218 ] In ip6_append_data_mtu(), when the xfrm mode is not tunnel(such as transport),the ipsec header need to be added in the first fragment, so the mtu will decrease to reserve space for it, then the second fragment come, the mtu should be turn back, as the commit 0c1833797a5a6ec23ea9261d979aa18078720b74 said. however, in the commit a493e60ac4bbe2e977e7129d6d8cbb0dd236be, it use *mtu = min(*mtu, ...) to change the mtu, which lead to the new mtu is alway equal with the first fragment's. and cannot turn back. when I test through ping6 -c1 -s5000 $ip (mtu=1280): ...frag (0|1232) ESP(spi=0x00002000,seq=0xb), length 1232 ...frag (1232|1216) ...frag (2448|1216) ...frag (3664|1216) ...frag (4880|164) which should be: ...frag (0|1232) ESP(spi=0x00001000,seq=0x1), length 1232 ...frag (1232|1232) ...frag (2464|1232) ...frag (3696|1232) ...frag (4928|116) so delete the min() when change back the mtu. Signed-off-by: Xin Long <lucien.xin@gmail.com> Fixes: 75a493e60ac4bb ("ipv6: ip6_append_data_mtu did not care about pmtudisc and frag_size") Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net')
-rw-r--r--net/ipv6/ip6_output.c14
1 files changed, 6 insertions, 8 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 98a262b759ae..390b05d488b8 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1108,21 +1108,19 @@ static void ip6_append_data_mtu(unsigned int *mtu,
1108 unsigned int fragheaderlen, 1108 unsigned int fragheaderlen,
1109 struct sk_buff *skb, 1109 struct sk_buff *skb,
1110 struct rt6_info *rt, 1110 struct rt6_info *rt,
1111 bool pmtuprobe) 1111 unsigned int orig_mtu)
1112{ 1112{
1113 if (!(rt->dst.flags & DST_XFRM_TUNNEL)) { 1113 if (!(rt->dst.flags & DST_XFRM_TUNNEL)) {
1114 if (skb == NULL) { 1114 if (skb == NULL) {
1115 /* first fragment, reserve header_len */ 1115 /* first fragment, reserve header_len */
1116 *mtu = *mtu - rt->dst.header_len; 1116 *mtu = orig_mtu - rt->dst.header_len;
1117 1117
1118 } else { 1118 } else {
1119 /* 1119 /*
1120 * this fragment is not first, the headers 1120 * this fragment is not first, the headers
1121 * space is regarded as data space. 1121 * space is regarded as data space.
1122 */ 1122 */
1123 *mtu = min(*mtu, pmtuprobe ? 1123 *mtu = orig_mtu;
1124 rt->dst.dev->mtu :
1125 dst_mtu(rt->dst.path));
1126 } 1124 }
1127 *maxfraglen = ((*mtu - fragheaderlen) & ~7) 1125 *maxfraglen = ((*mtu - fragheaderlen) & ~7)
1128 + fragheaderlen - sizeof(struct frag_hdr); 1126 + fragheaderlen - sizeof(struct frag_hdr);
@@ -1139,7 +1137,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
1139 struct ipv6_pinfo *np = inet6_sk(sk); 1137 struct ipv6_pinfo *np = inet6_sk(sk);
1140 struct inet_cork *cork; 1138 struct inet_cork *cork;
1141 struct sk_buff *skb, *skb_prev = NULL; 1139 struct sk_buff *skb, *skb_prev = NULL;
1142 unsigned int maxfraglen, fragheaderlen, mtu; 1140 unsigned int maxfraglen, fragheaderlen, mtu, orig_mtu;
1143 int exthdrlen; 1141 int exthdrlen;
1144 int dst_exthdrlen; 1142 int dst_exthdrlen;
1145 int hh_len; 1143 int hh_len;
@@ -1221,6 +1219,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
1221 dst_exthdrlen = 0; 1219 dst_exthdrlen = 0;
1222 mtu = cork->fragsize; 1220 mtu = cork->fragsize;
1223 } 1221 }
1222 orig_mtu = mtu;
1224 1223
1225 hh_len = LL_RESERVED_SPACE(rt->dst.dev); 1224 hh_len = LL_RESERVED_SPACE(rt->dst.dev);
1226 1225
@@ -1300,8 +1299,7 @@ alloc_new_skb:
1300 if (skb == NULL || skb_prev == NULL) 1299 if (skb == NULL || skb_prev == NULL)
1301 ip6_append_data_mtu(&mtu, &maxfraglen, 1300 ip6_append_data_mtu(&mtu, &maxfraglen,
1302 fragheaderlen, skb, rt, 1301 fragheaderlen, skb, rt,
1303 np->pmtudisc == 1302 orig_mtu);
1304 IPV6_PMTUDISC_PROBE);
1305 1303
1306 skb_prev = skb; 1304 skb_prev = skb;
1307 1305