aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIlpo Järvinen <ilpo.jarvinen@helsinki.fi>2007-02-22 02:01:36 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2007-04-26 01:23:03 -0400
commit30935cf4f915c3178ce63331d6ff4c82163e26af (patch)
tree481acea11d681837c87d6da0a9bc848384ce4199
parentbdaae17da81db79b9aa4dfbf43305cfeef64f6a8 (diff)
[TCP] FRTO: Comment cleanup & improvement
Moved comments out from the body of process_frto() to the head (preferred way; see Documentation/CodingStyle). Bonus: it's much easier to read in this compacted form. FRTO algorithm and implementation is described in greater detail. For interested reader, more information is available in RFC4138. 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.c49
1 files changed, 32 insertions, 17 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index fe96e176d85a..561e5d404988 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1236,22 +1236,22 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
1236 return flag; 1236 return flag;
1237} 1237}
1238 1238
1239/* F-RTO can only be used if these conditions are satisfied:
1240 * - there must be some unsent new data
1241 * - the advertised window should allow sending it
1242 */
1239int tcp_use_frto(const struct sock *sk) 1243int tcp_use_frto(const struct sock *sk)
1240{ 1244{
1241 const struct tcp_sock *tp = tcp_sk(sk); 1245 const struct tcp_sock *tp = tcp_sk(sk);
1242 1246
1243 /* F-RTO must be activated in sysctl and there must be some
1244 * unsent new data, and the advertised window should allow
1245 * sending it.
1246 */
1247 return (sysctl_tcp_frto && sk->sk_send_head && 1247 return (sysctl_tcp_frto && sk->sk_send_head &&
1248 !after(TCP_SKB_CB(sk->sk_send_head)->end_seq, 1248 !after(TCP_SKB_CB(sk->sk_send_head)->end_seq,
1249 tp->snd_una + tp->snd_wnd)); 1249 tp->snd_una + tp->snd_wnd));
1250} 1250}
1251 1251
1252/* RTO occurred, but do not yet enter loss state. Instead, transmit two new 1252/* RTO occurred, but do not yet enter Loss state. Instead, defer RTO
1253 * segments to see from the next ACKs whether any data was really missing. 1253 * recovery a bit and use heuristics in tcp_process_frto() to detect if
1254 * If the RTO was spurious, new ACKs should arrive. 1254 * the RTO was spurious.
1255 */ 1255 */
1256void tcp_enter_frto(struct sock *sk) 1256void tcp_enter_frto(struct sock *sk)
1257{ 1257{
@@ -2489,6 +2489,30 @@ static void tcp_conservative_spur_to_response(struct tcp_sock *tp)
2489 tcp_moderate_cwnd(tp); 2489 tcp_moderate_cwnd(tp);
2490} 2490}
2491 2491
2492/* F-RTO spurious RTO detection algorithm (RFC4138)
2493 *
2494 * F-RTO affects during two new ACKs following RTO. State (ACK number) is kept
2495 * in frto_counter. When ACK advances window (but not to or beyond highest
2496 * sequence sent before RTO):
2497 * On First ACK, send two new segments out.
2498 * On Second ACK, RTO was likely spurious. Do spurious response (response
2499 * algorithm is not part of the F-RTO detection algorithm
2500 * given in RFC4138 but can be selected separately).
2501 * Otherwise (basically on duplicate ACK), RTO was (likely) caused by a loss
2502 * and TCP falls back to conventional RTO recovery.
2503 *
2504 * Rationale: if the RTO was spurious, new ACKs should arrive from the
2505 * original window even after we transmit two new data segments.
2506 *
2507 * F-RTO is implemented (mainly) in four functions:
2508 * - tcp_use_frto() is used to determine if TCP is can use F-RTO
2509 * - tcp_enter_frto() prepares TCP state on RTO if F-RTO is used, it is
2510 * called when tcp_use_frto() showed green light
2511 * - tcp_process_frto() handles incoming ACKs during F-RTO algorithm
2512 * - tcp_enter_frto_loss() is called if there is not enough evidence
2513 * to prove that the RTO is indeed spurious. It transfers the control
2514 * from F-RTO to the conventional RTO recovery
2515 */
2492static void tcp_process_frto(struct sock *sk, u32 prior_snd_una) 2516static void tcp_process_frto(struct sock *sk, u32 prior_snd_una)
2493{ 2517{
2494 struct tcp_sock *tp = tcp_sk(sk); 2518 struct tcp_sock *tp = tcp_sk(sk);
@@ -2497,25 +2521,16 @@ static void tcp_process_frto(struct sock *sk, u32 prior_snd_una)
2497 2521
2498 if (tp->snd_una == prior_snd_una || 2522 if (tp->snd_una == prior_snd_una ||
2499 !before(tp->snd_una, tp->frto_highmark)) { 2523 !before(tp->snd_una, tp->frto_highmark)) {
2500 /* RTO was caused by loss, start retransmitting in
2501 * go-back-N slow start
2502 */
2503 tcp_enter_frto_loss(sk); 2524 tcp_enter_frto_loss(sk);
2504 return; 2525 return;
2505 } 2526 }
2506 2527
2507 if (tp->frto_counter == 1) { 2528 if (tp->frto_counter == 1) {
2508 /* First ACK after RTO advances the window: allow two new
2509 * segments out.
2510 */
2511 tp->snd_cwnd = tcp_packets_in_flight(tp) + 2; 2529 tp->snd_cwnd = tcp_packets_in_flight(tp) + 2;
2512 } else { 2530 } else /* frto_counter == 2 */ {
2513 tcp_conservative_spur_to_response(tp); 2531 tcp_conservative_spur_to_response(tp);
2514 } 2532 }
2515 2533
2516 /* F-RTO affects on two new ACKs following RTO.
2517 * At latest on third ACK the TCP behavior is back to normal.
2518 */
2519 tp->frto_counter = (tp->frto_counter + 1) % 3; 2534 tp->frto_counter = (tp->frto_counter + 1) % 3;
2520} 2535}
2521 2536