Commit 2ed0edf9 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

tcp: cubic: fix overflow error in bictcp_update()

commit 17a6e9f1 ("tcp_cubic: fix clock dependency") added an
overflow error in bictcp_update() in following code :

/* change the unit from HZ to bictcp_HZ */
t = ((tcp_time_stamp + msecs_to_jiffies(ca->delay_min>>3) -
      ca->epoch_start) << BICTCP_HZ) / HZ;

Because msecs_to_jiffies() being unsigned long, compiler does
implicit type promotion.

We really want to constrain (tcp_time_stamp - ca->epoch_start)
to a signed 32bit value, or else 't' has unexpected high values.

This bugs triggers an increase of retransmit rates ~24 days after
boot [1], as the high order bit of tcp_time_stamp flips.

[1] for hosts with HZ=1000

Big thanks to Van Jacobson for spotting this problem.
Diagnosed-by: default avatarVan Jacobson <vanj@google.com>
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Cc: Neal Cardwell <ncardwell@google.com>
Cc: Yuchung Cheng <ycheng@google.com>
Cc: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: default avatarNeal Cardwell <ncardwell@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 248ba8ec
...@@ -206,8 +206,8 @@ static u32 cubic_root(u64 a) ...@@ -206,8 +206,8 @@ static u32 cubic_root(u64 a)
*/ */
static inline void bictcp_update(struct bictcp *ca, u32 cwnd) static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
{ {
u64 offs; u32 delta, bic_target, max_cnt;
u32 delta, t, bic_target, max_cnt; u64 offs, t;
ca->ack_cnt++; /* count the number of ACKs */ ca->ack_cnt++; /* count the number of ACKs */
...@@ -250,9 +250,11 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd) ...@@ -250,9 +250,11 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
* if the cwnd < 1 million packets !!! * if the cwnd < 1 million packets !!!
*/ */
t = (s32)(tcp_time_stamp - ca->epoch_start);
t += msecs_to_jiffies(ca->delay_min >> 3);
/* change the unit from HZ to bictcp_HZ */ /* change the unit from HZ to bictcp_HZ */
t = ((tcp_time_stamp + msecs_to_jiffies(ca->delay_min>>3) t <<= BICTCP_HZ;
- ca->epoch_start) << BICTCP_HZ) / HZ; do_div(t, HZ);
if (t < ca->bic_K) /* t - K */ if (t < ca->bic_K) /* t - K */
offs = ca->bic_K - t; offs = ca->bic_K - t;
......
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