aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/tcp_input.c27
1 files changed, 23 insertions, 4 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 3f26599ddc88..ca46eb9151f8 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1248,20 +1248,39 @@ static int tcp_match_skb_to_sack(struct sock *sk, struct sk_buff *skb,
1248{ 1248{
1249 int in_sack, err; 1249 int in_sack, err;
1250 unsigned int pkt_len; 1250 unsigned int pkt_len;
1251 unsigned int mss;
1251 1252
1252 in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) && 1253 in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) &&
1253 !before(end_seq, TCP_SKB_CB(skb)->end_seq); 1254 !before(end_seq, TCP_SKB_CB(skb)->end_seq);
1254 1255
1255 if (tcp_skb_pcount(skb) > 1 && !in_sack && 1256 if (tcp_skb_pcount(skb) > 1 && !in_sack &&
1256 after(TCP_SKB_CB(skb)->end_seq, start_seq)) { 1257 after(TCP_SKB_CB(skb)->end_seq, start_seq)) {
1257 1258 mss = tcp_skb_mss(skb);
1258 in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq); 1259 in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq);
1259 1260
1260 if (!in_sack) 1261 if (!in_sack) {
1261 pkt_len = start_seq - TCP_SKB_CB(skb)->seq; 1262 pkt_len = start_seq - TCP_SKB_CB(skb)->seq;
1262 else 1263 if (pkt_len < mss)
1264 pkt_len = mss;
1265 } else {
1263 pkt_len = end_seq - TCP_SKB_CB(skb)->seq; 1266 pkt_len = end_seq - TCP_SKB_CB(skb)->seq;
1264 err = tcp_fragment(sk, skb, pkt_len, skb_shinfo(skb)->gso_size); 1267 if (pkt_len < mss)
1268 return -EINVAL;
1269 }
1270
1271 /* Round if necessary so that SACKs cover only full MSSes
1272 * and/or the remaining small portion (if present)
1273 */
1274 if (pkt_len > mss) {
1275 unsigned int new_len = (pkt_len / mss) * mss;
1276 if (!in_sack && new_len < pkt_len) {
1277 new_len += mss;
1278 if (new_len > skb->len)
1279 return 0;
1280 }
1281 pkt_len = new_len;
1282 }
1283 err = tcp_fragment(sk, skb, pkt_len, mss);
1265 if (err < 0) 1284 if (err < 0)
1266 return err; 1285 return err;
1267 } 1286 }