diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-11-01 15:09:33 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-11-01 15:09:33 -0400 |
commit | 54866f032307063776b4eff7eadb131d47f9f9b4 (patch) | |
tree | 5fb7b5f886b43fbe115e81c14570c40c44956b53 /net/ipv4/tcp_input.c | |
parent | b4d367fb20ed19be4a53fa88b407248aeb8bd461 (diff) | |
parent | 49259d34c52df6be482fefca946debe28ba9a2f6 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6:
[IRDA] IRNET: Fix build when TCGETS2 is defined.
[NET]: docbook fixes for netif_ functions
[NET]: Hide the net_ns kmem cache
[NET]: Mark the setup_net as __net_init
[NET]: Hide the dead code in the net_namespace.c
[NET]: Relax the reference counting of init_net_ns
[NETNS]: Make the init/exit hooks checks outside the loop
[NET]: Forget the zero_it argument of sk_alloc()
[NET]: Remove bogus zero_it argument from sk_alloc
[NET]: Make the sk_clone() lighter
[NET]: Move some core sock setup into sk_prot_alloc
[NET]: Auto-zero the allocated sock object
[NET]: Cleanup the allocation/freeing of the sock object
[NET]: Move the get_net() from sock_copy()
[NET]: Move the sock_copy() from the header
[TCP]: Another TAGBITS -> SACKED_ACKED|LOST conversion
[TCP]: Process DSACKs that reside within a SACK block
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r-- | net/ipv4/tcp_input.c | 27 |
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); |