aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/tcp_input.c')
-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 69d8c38ccd39..ca9590f4f520 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
@@ -2059,7 +2078,7 @@ static void tcp_update_scoreboard(struct sock *sk)
2059 if (!tcp_skb_timedout(sk, skb)) 2078 if (!tcp_skb_timedout(sk, skb))
2060 break; 2079 break;
2061 2080
2062 if (!(TCP_SKB_CB(skb)->sacked&TCPCB_TAGBITS)) { 2081 if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_SACKED_ACKED|TCPCB_LOST))) {
2063 TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; 2082 TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
2064 tp->lost_out += tcp_skb_pcount(skb); 2083 tp->lost_out += tcp_skb_pcount(skb);
2065 tcp_verify_retransmit_hint(tp, skb); 2084 tcp_verify_retransmit_hint(tp, skb);