aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2015-09-17 08:38:00 -0700
committerWolfgang Wiedmeyer <wolfgit@wiedmeyer.de>2016-03-18 01:51:05 +0100
commit56018a035f69fe27d7f7e0d20b402be2cd51bfcf (patch)
tree6a398da6ac76ac09b0ce05898fc9a8e603269563
parentdd720295caeb0dee1672883a72bb471053137c2f (diff)
downloadkernel_samsung_smdk4412-56018a035f69fe27d7f7e0d20b402be2cd51bfcf.zip
kernel_samsung_smdk4412-56018a035f69fe27d7f7e0d20b402be2cd51bfcf.tar.gz
kernel_samsung_smdk4412-56018a035f69fe27d7f7e0d20b402be2cd51bfcf.tar.bz2
tcp_cubic: do not set epoch_start in the future
Tracking idle time in bictcp_cwnd_event() is imprecise, as epoch_start is normally set at ACK processing time, not at send time. Doing a proper fix would need to add an additional state variable, and does not seem worth the trouble, given CUBIC bug has been there forever before Jana noticed it. Let's simply not set epoch_start in the future, otherwise bictcp_update() could overflow and CUBIC would again grow cwnd too fast. This was detected thanks to a packetdrill test Neal wrote that was flaky before applying this fix. Change-Id: I600d3a8ac0ed1d70f3ff5cc6b7341ac13178f4f3 Fixes: 30927520dbae ("tcp_cubic: better follow cubic curve after idle period") Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: Neal Cardwell <ncardwell@google.com> Signed-off-by: Yuchung Cheng <ycheng@google.com> Cc: Jana Iyengar <jri@google.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
-rw-r--r--net/ipv4/tcp_cubic.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c
index ceb6362..2cee558 100644
--- a/net/ipv4/tcp_cubic.c
+++ b/net/ipv4/tcp_cubic.c
@@ -154,14 +154,20 @@ static void bictcp_init(struct sock *sk)
static void bictcp_cwnd_event(struct sock *sk, enum tcp_ca_event event)
{
if (event == CA_EVENT_TX_START) {
- s32 delta = tcp_time_stamp - tcp_sk(sk)->lsndtime;
struct bictcp *ca = inet_csk_ca(sk);
+ u32 now = tcp_time_stamp;
+ s32 delta;
+
+ delta = now - tcp_sk(sk)->lsndtime;
/* We were application limited (idle) for a while.
* Shift epoch_start to keep cwnd growth to cubic curve.
*/
- if (ca->epoch_start && delta > 0)
+ if (ca->epoch_start && delta > 0) {
ca->epoch_start += delta;
+ if (after(ca->epoch_start, now))
+ ca->epoch_start = now;
+ }
return;
}
}