aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIlpo Järvinen <ilpo.jarvinen@helsinki.fi>2007-02-22 02:11:57 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2007-04-26 01:23:13 -0400
commitd1a54c6a0a3f9c2c4ef71982d89b8571bd9eaa51 (patch)
tree4edf68266db30b59cccd10194911bbfd5d123e38
parent46d0de4ed92650b95f27acae09914996bbe624e7 (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.c35
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 */
1316static void tcp_enter_frto_loss(struct sock *sk, int allowed_segments) 1316static 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