Commit 30935cf4 authored by Ilpo Järvinen's avatar Ilpo Järvinen Committed by David S. Miller

[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: default avatarIlpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent bdaae17d
...@@ -1236,22 +1236,22 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ ...@@ -1236,22 +1236,22 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
return flag; return flag;
} }
/* F-RTO can only be used if these conditions are satisfied:
* - there must be some unsent new data
* - the advertised window should allow sending it
*/
int tcp_use_frto(const struct sock *sk) int tcp_use_frto(const struct sock *sk)
{ {
const struct tcp_sock *tp = tcp_sk(sk); const struct tcp_sock *tp = tcp_sk(sk);
/* F-RTO must be activated in sysctl and there must be some
* unsent new data, and the advertised window should allow
* sending it.
*/
return (sysctl_tcp_frto && sk->sk_send_head && return (sysctl_tcp_frto && sk->sk_send_head &&
!after(TCP_SKB_CB(sk->sk_send_head)->end_seq, !after(TCP_SKB_CB(sk->sk_send_head)->end_seq,
tp->snd_una + tp->snd_wnd)); tp->snd_una + tp->snd_wnd));
} }
/* RTO occurred, but do not yet enter loss state. Instead, transmit two new /* RTO occurred, but do not yet enter Loss state. Instead, defer RTO
* segments to see from the next ACKs whether any data was really missing. * recovery a bit and use heuristics in tcp_process_frto() to detect if
* If the RTO was spurious, new ACKs should arrive. * the RTO was spurious.
*/ */
void tcp_enter_frto(struct sock *sk) void tcp_enter_frto(struct sock *sk)
{ {
...@@ -2489,6 +2489,30 @@ static void tcp_conservative_spur_to_response(struct tcp_sock *tp) ...@@ -2489,6 +2489,30 @@ static void tcp_conservative_spur_to_response(struct tcp_sock *tp)
tcp_moderate_cwnd(tp); tcp_moderate_cwnd(tp);
} }
/* F-RTO spurious RTO detection algorithm (RFC4138)
*
* F-RTO affects during two new ACKs following RTO. State (ACK number) is kept
* in frto_counter. When ACK advances window (but not to or beyond highest
* sequence sent before RTO):
* On First ACK, send two new segments out.
* On Second ACK, RTO was likely spurious. Do spurious response (response
* algorithm is not part of the F-RTO detection algorithm
* given in RFC4138 but can be selected separately).
* Otherwise (basically on duplicate ACK), RTO was (likely) caused by a loss
* and TCP falls back to conventional RTO recovery.
*
* Rationale: if the RTO was spurious, new ACKs should arrive from the
* original window even after we transmit two new data segments.
*
* F-RTO is implemented (mainly) in four functions:
* - tcp_use_frto() is used to determine if TCP is can use F-RTO
* - tcp_enter_frto() prepares TCP state on RTO if F-RTO is used, it is
* called when tcp_use_frto() showed green light
* - tcp_process_frto() handles incoming ACKs during F-RTO algorithm
* - tcp_enter_frto_loss() is called if there is not enough evidence
* to prove that the RTO is indeed spurious. It transfers the control
* from F-RTO to the conventional RTO recovery
*/
static void tcp_process_frto(struct sock *sk, u32 prior_snd_una) static void tcp_process_frto(struct sock *sk, u32 prior_snd_una)
{ {
struct tcp_sock *tp = tcp_sk(sk); struct tcp_sock *tp = tcp_sk(sk);
...@@ -2497,25 +2521,16 @@ static void tcp_process_frto(struct sock *sk, u32 prior_snd_una) ...@@ -2497,25 +2521,16 @@ static void tcp_process_frto(struct sock *sk, u32 prior_snd_una)
if (tp->snd_una == prior_snd_una || if (tp->snd_una == prior_snd_una ||
!before(tp->snd_una, tp->frto_highmark)) { !before(tp->snd_una, tp->frto_highmark)) {
/* RTO was caused by loss, start retransmitting in
* go-back-N slow start
*/
tcp_enter_frto_loss(sk); tcp_enter_frto_loss(sk);
return; return;
} }
if (tp->frto_counter == 1) { if (tp->frto_counter == 1) {
/* First ACK after RTO advances the window: allow two new
* segments out.
*/
tp->snd_cwnd = tcp_packets_in_flight(tp) + 2; tp->snd_cwnd = tcp_packets_in_flight(tp) + 2;
} else { } else /* frto_counter == 2 */ {
tcp_conservative_spur_to_response(tp); tcp_conservative_spur_to_response(tp);
} }
/* F-RTO affects on two new ACKs following RTO.
* At latest on third ACK the TCP behavior is back to normal.
*/
tp->frto_counter = (tp->frto_counter + 1) % 3; tp->frto_counter = (tp->frto_counter + 1) % 3;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment