diff options
author | Ilpo Järvinen <ilpo.jarvinen@helsinki.fi> | 2007-02-22 02:13:47 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-04-26 01:23:14 -0400 |
commit | 66e93e45c09affa407750cc06398492e8b897848 (patch) | |
tree | bcf65f7c29a3bd27eb386198560463f3eece7d41 /net | |
parent | d1a54c6a0a3f9c2c4ef71982d89b8571bd9eaa51 (diff) |
[TCP] FRTO: Fake cwnd for ssthresh callback
TCP without FRTO would be in Loss state with small cwnd. FRTO,
however, leaves cwnd (typically) to a larger value which causes
ssthresh to become too large in case RTO is triggered again
compared to what conventional recovery would do. Because
consecutive RTOs result in only a single ssthresh reduction,
RTO+cumulative ACK+RTO pattern is required to trigger this
event.
A large comment is included for congestion control module writers
trying to figure out what CA_EVENT_FRTO handler should do because
there exists a remote possibility of incompatibility between
FRTO and module defined ssthresh functions.
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/tcp_input.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 3ef7e9e07964..055721d8495e 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -1289,7 +1289,31 @@ void tcp_enter_frto(struct sock *sk) | |||
1289 | ((icsk->icsk_ca_state == TCP_CA_Loss || tp->frto_counter) && | 1289 | ((icsk->icsk_ca_state == TCP_CA_Loss || tp->frto_counter) && |
1290 | !icsk->icsk_retransmits)) { | 1290 | !icsk->icsk_retransmits)) { |
1291 | tp->prior_ssthresh = tcp_current_ssthresh(sk); | 1291 | tp->prior_ssthresh = tcp_current_ssthresh(sk); |
1292 | tp->snd_ssthresh = icsk->icsk_ca_ops->ssthresh(sk); | 1292 | /* Our state is too optimistic in ssthresh() call because cwnd |
1293 | * is not reduced until tcp_enter_frto_loss() when previous FRTO | ||
1294 | * recovery has not yet completed. Pattern would be this: RTO, | ||
1295 | * Cumulative ACK, RTO (2xRTO for the same segment does not end | ||
1296 | * up here twice). | ||
1297 | * RFC4138 should be more specific on what to do, even though | ||
1298 | * RTO is quite unlikely to occur after the first Cumulative ACK | ||
1299 | * due to back-off and complexity of triggering events ... | ||
1300 | */ | ||
1301 | if (tp->frto_counter) { | ||
1302 | u32 stored_cwnd; | ||
1303 | stored_cwnd = tp->snd_cwnd; | ||
1304 | tp->snd_cwnd = 2; | ||
1305 | tp->snd_ssthresh = icsk->icsk_ca_ops->ssthresh(sk); | ||
1306 | tp->snd_cwnd = stored_cwnd; | ||
1307 | } else { | ||
1308 | tp->snd_ssthresh = icsk->icsk_ca_ops->ssthresh(sk); | ||
1309 | } | ||
1310 | /* ... in theory, cong.control module could do "any tricks" in | ||
1311 | * ssthresh(), which means that ca_state, lost bits and lost_out | ||
1312 | * counter would have to be faked before the call occurs. We | ||
1313 | * consider that too expensive, unlikely and hacky, so modules | ||
1314 | * using these in ssthresh() must deal these incompatibility | ||
1315 | * issues if they receives CA_EVENT_FRTO and frto_counter != 0 | ||
1316 | */ | ||
1293 | tcp_ca_event(sk, CA_EVENT_FRTO); | 1317 | tcp_ca_event(sk, CA_EVENT_FRTO); |
1294 | } | 1318 | } |
1295 | 1319 | ||