diff options
author | Ilpo Järvinen <ilpo.jarvinen@helsinki.fi> | 2007-02-22 02:11:57 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-04-26 01:23:13 -0400 |
commit | d1a54c6a0a3f9c2c4ef71982d89b8571bd9eaa51 (patch) | |
tree | 4edf68266db30b59cccd10194911bbfd5d123e38 | |
parent | 46d0de4ed92650b95f27acae09914996bbe624e7 (diff) |
[TCP] FRTO: Reverse RETRANS bit clearing logic
Previously RETRANS bits were cleared on the entry to FRTO. We
postpone that into tcp_enter_frto_loss, which is really the
place were the clearing should be done anyway. This allows
simplification of the logic from a clearing loop to the head skb
clearing only.
Besides, the other changes made in the previous patches to
tcp_use_frto made it impossible for the non-SACKed FRTO to be
entered if other than the head has been rexmitted.
With SACK-enhanced FRTO (and Appendix B), however, there can be
a number retransmissions in flight when RTO expires (same thing
could happen before this patchset also with non-SACK FRTO). To
not introduce any jumpiness into the packet counting during FRTO,
instead of clearing RETRANS bits from skbs during entry, do it
later on.
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv4/tcp_input.c | 35 |
1 files changed, 23 insertions, 12 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index a283fc12186e..3ef7e9e07964 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -1268,7 +1268,11 @@ int tcp_use_frto(struct sock *sk) | |||
1268 | 1268 | ||
1269 | /* RTO occurred, but do not yet enter Loss state. Instead, defer RTO | 1269 | /* RTO occurred, but do not yet enter Loss state. Instead, defer RTO |
1270 | * recovery a bit and use heuristics in tcp_process_frto() to detect if | 1270 | * recovery a bit and use heuristics in tcp_process_frto() to detect if |
1271 | * the RTO was spurious. | 1271 | * the RTO was spurious. Only clear SACKED_RETRANS of the head here to |
1272 | * keep retrans_out counting accurate (with SACK F-RTO, other than head | ||
1273 | * may still have that bit set); TCPCB_LOST and remaining SACKED_RETRANS | ||
1274 | * bits are handled if the Loss state is really to be entered (in | ||
1275 | * tcp_enter_frto_loss). | ||
1272 | * | 1276 | * |
1273 | * Do like tcp_enter_loss() would; when RTO expires the second time it | 1277 | * Do like tcp_enter_loss() would; when RTO expires the second time it |
1274 | * does: | 1278 | * does: |
@@ -1289,17 +1293,13 @@ void tcp_enter_frto(struct sock *sk) | |||
1289 | tcp_ca_event(sk, CA_EVENT_FRTO); | 1293 | tcp_ca_event(sk, CA_EVENT_FRTO); |
1290 | } | 1294 | } |
1291 | 1295 | ||
1292 | /* Have to clear retransmission markers here to keep the bookkeeping | ||
1293 | * in shape, even though we are not yet in Loss state. | ||
1294 | * If something was really lost, it is eventually caught up | ||
1295 | * in tcp_enter_frto_loss. | ||
1296 | */ | ||
1297 | tp->retrans_out = 0; | ||
1298 | tp->undo_marker = tp->snd_una; | 1296 | tp->undo_marker = tp->snd_una; |
1299 | tp->undo_retrans = 0; | 1297 | tp->undo_retrans = 0; |
1300 | 1298 | ||
1301 | sk_stream_for_retrans_queue(skb, sk) { | 1299 | skb = skb_peek(&sk->sk_write_queue); |
1300 | if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS) { | ||
1302 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS; | 1301 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS; |
1302 | tp->retrans_out -= tcp_skb_pcount(skb); | ||
1303 | } | 1303 | } |
1304 | tcp_sync_left_out(tp); | 1304 | tcp_sync_left_out(tp); |
1305 | 1305 | ||
@@ -1313,7 +1313,7 @@ void tcp_enter_frto(struct sock *sk) | |||
1313 | * which indicates that we should follow the traditional RTO recovery, | 1313 | * which indicates that we should follow the traditional RTO recovery, |
1314 | * i.e. mark everything lost and do go-back-N retransmission. | 1314 | * i.e. mark everything lost and do go-back-N retransmission. |
1315 | */ | 1315 | */ |
1316 | static void tcp_enter_frto_loss(struct sock *sk, int allowed_segments) | 1316 | static void tcp_enter_frto_loss(struct sock *sk, int allowed_segments, int flag) |
1317 | { | 1317 | { |
1318 | struct tcp_sock *tp = tcp_sk(sk); | 1318 | struct tcp_sock *tp = tcp_sk(sk); |
1319 | struct sk_buff *skb; | 1319 | struct sk_buff *skb; |
@@ -1322,10 +1322,21 @@ static void tcp_enter_frto_loss(struct sock *sk, int allowed_segments) | |||
1322 | tp->sacked_out = 0; | 1322 | tp->sacked_out = 0; |
1323 | tp->lost_out = 0; | 1323 | tp->lost_out = 0; |
1324 | tp->fackets_out = 0; | 1324 | tp->fackets_out = 0; |
1325 | tp->retrans_out = 0; | ||
1325 | 1326 | ||
1326 | sk_stream_for_retrans_queue(skb, sk) { | 1327 | sk_stream_for_retrans_queue(skb, sk) { |
1327 | cnt += tcp_skb_pcount(skb); | 1328 | cnt += tcp_skb_pcount(skb); |
1328 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST; | 1329 | /* |
1330 | * Count the retransmission made on RTO correctly (only when | ||
1331 | * waiting for the first ACK and did not get it)... | ||
1332 | */ | ||
1333 | if ((tp->frto_counter == 1) && !(flag&FLAG_DATA_ACKED)) { | ||
1334 | tp->retrans_out += tcp_skb_pcount(skb); | ||
1335 | /* ...enter this if branch just for the first segment */ | ||
1336 | flag |= FLAG_DATA_ACKED; | ||
1337 | } else { | ||
1338 | TCP_SKB_CB(skb)->sacked &= ~(TCPCB_LOST|TCPCB_SACKED_RETRANS); | ||
1339 | } | ||
1329 | if (!(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED)) { | 1340 | if (!(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED)) { |
1330 | 1341 | ||
1331 | /* Do not mark those segments lost that were | 1342 | /* Do not mark those segments lost that were |
@@ -2550,7 +2561,7 @@ static int tcp_process_frto(struct sock *sk, u32 prior_snd_una, int flag) | |||
2550 | inet_csk(sk)->icsk_retransmits = 0; | 2561 | inet_csk(sk)->icsk_retransmits = 0; |
2551 | 2562 | ||
2552 | if (!before(tp->snd_una, tp->frto_highmark)) { | 2563 | if (!before(tp->snd_una, tp->frto_highmark)) { |
2553 | tcp_enter_frto_loss(sk, tp->frto_counter + 1); | 2564 | tcp_enter_frto_loss(sk, tp->frto_counter + 1, flag); |
2554 | return 1; | 2565 | return 1; |
2555 | } | 2566 | } |
2556 | 2567 | ||
@@ -2562,7 +2573,7 @@ static int tcp_process_frto(struct sock *sk, u32 prior_snd_una, int flag) | |||
2562 | return 1; | 2573 | return 1; |
2563 | 2574 | ||
2564 | if (!(flag&FLAG_DATA_ACKED)) { | 2575 | if (!(flag&FLAG_DATA_ACKED)) { |
2565 | tcp_enter_frto_loss(sk, (tp->frto_counter == 1 ? 0 : 3)); | 2576 | tcp_enter_frto_loss(sk, (tp->frto_counter == 1 ? 0 : 3), flag); |
2566 | return 1; | 2577 | return 1; |
2567 | } | 2578 | } |
2568 | 2579 | ||