diff options
author | Ilpo Järvinen <ilpo.jarvinen@helsinki.fi> | 2007-02-22 02:01:36 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-04-26 01:23:03 -0400 |
commit | 30935cf4f915c3178ce63331d6ff4c82163e26af (patch) | |
tree | 481acea11d681837c87d6da0a9bc848384ce4199 | |
parent | bdaae17da81db79b9aa4dfbf43305cfeef64f6a8 (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.c | 49 |
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 | */ | ||
1239 | int tcp_use_frto(const struct sock *sk) | 1243 | int 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 | */ |
1256 | void tcp_enter_frto(struct sock *sk) | 1256 | void 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 | */ | ||
2492 | static void tcp_process_frto(struct sock *sk, u32 prior_snd_una) | 2516 | static 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 | ||