diff options
author | Aki M Nyrhinen <anyrhine@cs.helsinki.fi> | 2006-06-12 00:18:56 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-06-12 00:18:56 -0400 |
commit | 79320d7e14900c549c3520791a297328f53ff71e (patch) | |
tree | bd2c9cc7f2d4b7790ad1e18fb9a00aad621c0354 /net | |
parent | afec35e3fee900b3016519d0b5512064e4625b2c (diff) |
[TCP]: continued: reno sacked_out count fix
From: Aki M Nyrhinen <anyrhine@cs.helsinki.fi>
IMHO the current fix to the problem (in_flight underflow in reno)
is incorrect. it treats the symptons but ignores the problem. the
problem is timing out packets other than the head packet when we
don't have sack. i try to explain (sorry if explaining the obvious).
with sack, scanning the retransmit queue for timed out packets is
fine because we know which packets in our retransmit queue have been
acked by the receiver.
without sack, we know only how many packets in our retransmit queue the
receiver has acknowledged, but no idea which packets.
think of a "typical" slow-start overshoot case, where for example
every third packet in a window get lost because a router buffer gets
full.
with sack, we check for timeouts on those every third packet (as the
rest have been sacked). the packet counting works out and if there
is no reordering, we'll retransmit exactly the packets that were
lost.
without sack, however, we check for timeout on every packet and end up
retransmitting consecutive packets in the retransmit queue. in our
slow-start example, 2/3 of those retransmissions are unnecessary. these
unnecessary retransmissions eat the congestion window and evetually
prevent fast recovery from continuing, if enough packets were lost.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/tcp_input.c | 4 |
1 files changed, 1 insertions, 3 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 4a538bc1683d..b5521a9d3dc1 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -1649,7 +1649,7 @@ static void tcp_update_scoreboard(struct sock *sk, struct tcp_sock *tp) | |||
1649 | * Hence, we can detect timed out packets during fast | 1649 | * Hence, we can detect timed out packets during fast |
1650 | * retransmit without falling to slow start. | 1650 | * retransmit without falling to slow start. |
1651 | */ | 1651 | */ |
1652 | if (tcp_head_timedout(sk, tp)) { | 1652 | if (!IsReno(tp) && tcp_head_timedout(sk, tp)) { |
1653 | struct sk_buff *skb; | 1653 | struct sk_buff *skb; |
1654 | 1654 | ||
1655 | skb = tp->scoreboard_skb_hint ? tp->scoreboard_skb_hint | 1655 | skb = tp->scoreboard_skb_hint ? tp->scoreboard_skb_hint |
@@ -1662,8 +1662,6 @@ static void tcp_update_scoreboard(struct sock *sk, struct tcp_sock *tp) | |||
1662 | if (!(TCP_SKB_CB(skb)->sacked&TCPCB_TAGBITS)) { | 1662 | if (!(TCP_SKB_CB(skb)->sacked&TCPCB_TAGBITS)) { |
1663 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; | 1663 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; |
1664 | tp->lost_out += tcp_skb_pcount(skb); | 1664 | tp->lost_out += tcp_skb_pcount(skb); |
1665 | if (IsReno(tp)) | ||
1666 | tcp_remove_reno_sacks(sk, tp, tcp_skb_pcount(skb) + 1); | ||
1667 | 1665 | ||
1668 | /* clear xmit_retrans hint */ | 1666 | /* clear xmit_retrans hint */ |
1669 | if (tp->retransmit_skb_hint && | 1667 | if (tp->retransmit_skb_hint && |