diff options
author | Ilpo Järvinen <ilpo.jarvinen@helsinki.fi> | 2007-03-02 16:34:19 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-04-26 01:23:26 -0400 |
commit | e317f6f69cb95527799d308a9421b7dc1252989a (patch) | |
tree | 141ff608a450f1d768383f300cc204db5904b20c /net/ipv4/tcp_input.c | |
parent | e01f9d7793be82e6c252efbd52c399d3eb65abe4 (diff) |
[TCP]: FRTO undo response falls back to ratehalving one if ECEd
Undoing ssthresh is disabled in fastretrans_alert whenever
FLAG_ECE is set by clearing prior_ssthresh. The clearing does
not protect FRTO because FRTO operates before fastretrans_alert.
Moving the clearing of prior_ssthresh earlier seems to be a
suboptimal solution to the FRTO case because then FLAG_ECE will
cause a second ssthresh reduction in try_to_open (the first
occurred when FRTO was entered). So instead, FRTO falls back
immediately to the rate halving response, which switches TCP to
CA_CWR state preventing the latter reduction of ssthresh.
If the first ECE arrived before the ACK after which FRTO is able
to decide RTO as spurious, prior_ssthresh is already cleared.
Thus no undoing for ssthresh occurs. Besides, FLAG_ECE should be
set also in the following ACKs resulting in rate halving response
that sees TCP is already in CA_CWR, which again prevents an extra
ssthresh reduction on that round-trip.
If the first ECE arrived before RTO, ssthresh has already been
adapted and prior_ssthresh remains cleared on entry because TCP
is in CA_CWR (the same applies also to a case where FRTO is
entered more than once and ECE comes in the middle).
High_seq must not be touched after tcp_enter_cwr because CWR
round-trip calculation depends on it.
I believe that after this patch, FRTO should be ECN-safe and
even able to take advantage of synergy benefits.
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r-- | net/ipv4/tcp_input.c | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index cb715eadf8f5..d894bbcc1d24 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -2587,14 +2587,15 @@ static void tcp_conservative_spur_to_response(struct tcp_sock *tp) | |||
2587 | */ | 2587 | */ |
2588 | static void tcp_ratehalving_spur_to_response(struct sock *sk) | 2588 | static void tcp_ratehalving_spur_to_response(struct sock *sk) |
2589 | { | 2589 | { |
2590 | struct tcp_sock *tp = tcp_sk(sk); | ||
2591 | tcp_enter_cwr(sk, 0); | 2590 | tcp_enter_cwr(sk, 0); |
2592 | tp->high_seq = tp->frto_highmark; /* Smoother w/o this? - ij */ | ||
2593 | } | 2591 | } |
2594 | 2592 | ||
2595 | static void tcp_undo_spur_to_response(struct sock *sk) | 2593 | static void tcp_undo_spur_to_response(struct sock *sk, int flag) |
2596 | { | 2594 | { |
2597 | tcp_undo_cwr(sk, 1); | 2595 | if (flag&FLAG_ECE) |
2596 | tcp_ratehalving_spur_to_response(sk); | ||
2597 | else | ||
2598 | tcp_undo_cwr(sk, 1); | ||
2598 | } | 2599 | } |
2599 | 2600 | ||
2600 | /* F-RTO spurious RTO detection algorithm (RFC4138) | 2601 | /* F-RTO spurious RTO detection algorithm (RFC4138) |
@@ -2681,7 +2682,7 @@ static int tcp_process_frto(struct sock *sk, u32 prior_snd_una, int flag) | |||
2681 | } else /* frto_counter == 2 */ { | 2682 | } else /* frto_counter == 2 */ { |
2682 | switch (sysctl_tcp_frto_response) { | 2683 | switch (sysctl_tcp_frto_response) { |
2683 | case 2: | 2684 | case 2: |
2684 | tcp_undo_spur_to_response(sk); | 2685 | tcp_undo_spur_to_response(sk, flag); |
2685 | break; | 2686 | break; |
2686 | case 1: | 2687 | case 1: |
2687 | tcp_conservative_spur_to_response(tp); | 2688 | tcp_conservative_spur_to_response(tp); |