aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv4/tcp_input.c25
1 files changed, 22 insertions, 3 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 69d8c38ccd39..4d72781a49be 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1330,12 +1330,15 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
1330 cached_fack_count = 0; 1330 cached_fack_count = 0;
1331 } 1331 }
1332 1332
1333 for (i=0; i<num_sacks; i++, sp++) { 1333 for (i = 0; i < num_sacks; i++) {
1334 struct sk_buff *skb; 1334 struct sk_buff *skb;
1335 __u32 start_seq = ntohl(sp->start_seq); 1335 __u32 start_seq = ntohl(sp->start_seq);
1336 __u32 end_seq = ntohl(sp->end_seq); 1336 __u32 end_seq = ntohl(sp->end_seq);
1337 int fack_count; 1337 int fack_count;
1338 int dup_sack = (found_dup_sack && (i == first_sack_index)); 1338 int dup_sack = (found_dup_sack && (i == first_sack_index));
1339 int next_dup = (found_dup_sack && (i+1 == first_sack_index));
1340
1341 sp++;
1339 1342
1340 if (!tcp_is_sackblock_valid(tp, dup_sack, start_seq, end_seq)) { 1343 if (!tcp_is_sackblock_valid(tp, dup_sack, start_seq, end_seq)) {
1341 if (dup_sack) { 1344 if (dup_sack) {
@@ -1361,7 +1364,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
1361 flag |= FLAG_DATA_LOST; 1364 flag |= FLAG_DATA_LOST;
1362 1365
1363 tcp_for_write_queue_from(skb, sk) { 1366 tcp_for_write_queue_from(skb, sk) {
1364 int in_sack; 1367 int in_sack = 0;
1365 u8 sacked; 1368 u8 sacked;
1366 1369
1367 if (skb == tcp_send_head(sk)) 1370 if (skb == tcp_send_head(sk))
@@ -1380,7 +1383,23 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
1380 if (!before(TCP_SKB_CB(skb)->seq, end_seq)) 1383 if (!before(TCP_SKB_CB(skb)->seq, end_seq))
1381 break; 1384 break;
1382 1385
1383 in_sack = tcp_match_skb_to_sack(sk, skb, start_seq, end_seq); 1386 dup_sack = (found_dup_sack && (i == first_sack_index));
1387
1388 /* Due to sorting DSACK may reside within this SACK block! */
1389 if (next_dup) {
1390 u32 dup_start = ntohl(sp->start_seq);
1391 u32 dup_end = ntohl(sp->end_seq);
1392
1393 if (before(TCP_SKB_CB(skb)->seq, dup_end)) {
1394 in_sack = tcp_match_skb_to_sack(sk, skb, dup_start, dup_end);
1395 if (in_sack > 0)
1396 dup_sack = 1;
1397 }
1398 }
1399
1400 /* DSACK info lost if out-of-mem, try SACK still */
1401 if (in_sack <= 0)
1402 in_sack = tcp_match_skb_to_sack(sk, skb, start_seq, end_seq);
1384 if (in_sack < 0) 1403 if (in_sack < 0)
1385 break; 1404 break;
1386 1405