aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ip6_output.c
diff options
context:
space:
mode:
authorlucien <lucien.xin@gmail.com>2014-03-17 00:51:01 -0400
committerDavid S. Miller <davem@davemloft.net>2014-03-18 15:17:53 -0400
commite367c2d03dba4c9bcafad24688fadb79dd95b218 (patch)
treec2810ba4094340d30a3689e126caa433182d4948 /net/ipv6/ip6_output.c
parentd1958f8c2f0d6bfaa115f4dce1d5d19be5c6b090 (diff)
ipv6: ip6_append_data_mtu do not handle the mtu of the second fragment properly
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>
Diffstat (limited to 'net/ipv6/ip6_output.c')
-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 16f91a2e7888..64d6073731d3 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1101,21 +1101,19 @@ static void ip6_append_data_mtu(unsigned int *mtu,
1101 unsigned int fragheaderlen, 1101 unsigned int fragheaderlen,
1102 struct sk_buff *skb, 1102 struct sk_buff *skb,
1103 struct rt6_info *rt, 1103 struct rt6_info *rt,
1104 bool pmtuprobe) 1104 unsigned int orig_mtu)
1105{ 1105{
1106 if (!(rt->dst.flags & DST_XFRM_TUNNEL)) { 1106 if (!(rt->dst.flags & DST_XFRM_TUNNEL)) {
1107 if (skb == NULL) { 1107 if (skb == NULL) {
1108 /* first fragment, reserve header_len */ 1108 /* first fragment, reserve header_len */
1109 *mtu = *mtu - rt->dst.header_len; 1109 *mtu = orig_mtu - rt->dst.header_len;
1110 1110
1111 } else { 1111 } else {
1112 /* 1112 /*
1113 * this fragment is not first, the headers 1113 * this fragment is not first, the headers
1114 * space is regarded as data space. 1114 * space is regarded as data space.
1115 */ 1115 */
1116 *mtu = min(*mtu, pmtuprobe ? 1116 *mtu = orig_mtu;
1117 rt->dst.dev->mtu :
1118 dst_mtu(rt->dst.path));
1119 } 1117 }
1120 *maxfraglen = ((*mtu - fragheaderlen) & ~7) 1118 *maxfraglen = ((*mtu - fragheaderlen) & ~7)
1121 + fragheaderlen - sizeof(struct frag_hdr); 1119 + fragheaderlen - sizeof(struct frag_hdr);
@@ -1132,7 +1130,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
1132 struct ipv6_pinfo *np = inet6_sk(sk); 1130 struct ipv6_pinfo *np = inet6_sk(sk);
1133 struct inet_cork *cork; 1131 struct inet_cork *cork;
1134 struct sk_buff *skb, *skb_prev = NULL; 1132 struct sk_buff *skb, *skb_prev = NULL;
1135 unsigned int maxfraglen, fragheaderlen, mtu; 1133 unsigned int maxfraglen, fragheaderlen, mtu, orig_mtu;
1136 int exthdrlen; 1134 int exthdrlen;
1137 int dst_exthdrlen; 1135 int dst_exthdrlen;
1138 int hh_len; 1136 int hh_len;
@@ -1214,6 +1212,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
1214 dst_exthdrlen = 0; 1212 dst_exthdrlen = 0;
1215 mtu = cork->fragsize; 1213 mtu = cork->fragsize;
1216 } 1214 }
1215 orig_mtu = mtu;
1217 1216
1218 hh_len = LL_RESERVED_SPACE(rt->dst.dev); 1217 hh_len = LL_RESERVED_SPACE(rt->dst.dev);
1219 1218
@@ -1311,8 +1310,7 @@ alloc_new_skb:
1311 if (skb == NULL || skb_prev == NULL) 1310 if (skb == NULL || skb_prev == NULL)
1312 ip6_append_data_mtu(&mtu, &maxfraglen, 1311 ip6_append_data_mtu(&mtu, &maxfraglen,
1313 fragheaderlen, skb, rt, 1312 fragheaderlen, skb, rt,
1314 np->pmtudisc >= 1313 orig_mtu);
1315 IPV6_PMTUDISC_PROBE);
1316 1314
1317 skb_prev = skb; 1315 skb_prev = skb;
1318 1316