提交 3f6c65d6 编写于 作者: W Wei Wang 提交者: David S. Miller

tcp: ignore rcv_rtt sample with old ts ecr value

When receiving multiple packets with the same ts ecr value, only try
to compute rcv_rtt sample with the earliest received packet.
This is because the rcv_rtt calculated by later received packets
could possibly include long idle time or other types of delay.
For example:
(1) server sends last packet of reply with TS val V1
(2) client ACKs last packet of reply with TS ecr V1
(3) long idle time passes
(4) client sends next request data packet with TS ecr V1 (again!)
At this time, the rcv_rtt computed on server with TS ecr V1 will be
inflated with the idle time and should get ignored.
Signed-off-by: NWei Wang <weiwan@google.com>
Signed-off-by: NNeal Cardwell <ncardwell@google.com>
Signed-off-by: NEric Dumazet <edumazet@google.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 66caeeb9
...@@ -350,6 +350,7 @@ struct tcp_sock { ...@@ -350,6 +350,7 @@ struct tcp_sock {
#endif #endif
/* Receiver side RTT estimation */ /* Receiver side RTT estimation */
u32 rcv_rtt_last_tsecr;
struct { struct {
u32 rtt_us; u32 rtt_us;
u32 seq; u32 seq;
......
...@@ -2563,6 +2563,7 @@ int tcp_disconnect(struct sock *sk, int flags) ...@@ -2563,6 +2563,7 @@ int tcp_disconnect(struct sock *sk, int flags)
sk->sk_shutdown = 0; sk->sk_shutdown = 0;
sock_reset_flag(sk, SOCK_DONE); sock_reset_flag(sk, SOCK_DONE);
tp->srtt_us = 0; tp->srtt_us = 0;
tp->rcv_rtt_last_tsecr = 0;
tp->write_seq += tp->max_window + 2; tp->write_seq += tp->max_window + 2;
if (tp->write_seq == 0) if (tp->write_seq == 0)
tp->write_seq = 1; tp->write_seq = 1;
......
...@@ -582,9 +582,12 @@ static inline void tcp_rcv_rtt_measure_ts(struct sock *sk, ...@@ -582,9 +582,12 @@ static inline void tcp_rcv_rtt_measure_ts(struct sock *sk,
{ {
struct tcp_sock *tp = tcp_sk(sk); struct tcp_sock *tp = tcp_sk(sk);
if (tp->rx_opt.rcv_tsecr && if (tp->rx_opt.rcv_tsecr == tp->rcv_rtt_last_tsecr)
(TCP_SKB_CB(skb)->end_seq - return;
TCP_SKB_CB(skb)->seq >= inet_csk(sk)->icsk_ack.rcv_mss)) { tp->rcv_rtt_last_tsecr = tp->rx_opt.rcv_tsecr;
if (TCP_SKB_CB(skb)->end_seq -
TCP_SKB_CB(skb)->seq >= inet_csk(sk)->icsk_ack.rcv_mss) {
u32 delta = tcp_time_stamp(tp) - tp->rx_opt.rcv_tsecr; u32 delta = tcp_time_stamp(tp) - tp->rx_opt.rcv_tsecr;
u32 delta_us; u32 delta_us;
...@@ -5475,6 +5478,11 @@ void tcp_rcv_established(struct sock *sk, struct sk_buff *skb) ...@@ -5475,6 +5478,11 @@ void tcp_rcv_established(struct sock *sk, struct sk_buff *skb)
tcp_ack(sk, skb, 0); tcp_ack(sk, skb, 0);
__kfree_skb(skb); __kfree_skb(skb);
tcp_data_snd_check(sk); tcp_data_snd_check(sk);
/* When receiving pure ack in fast path, update
* last ts ecr directly instead of calling
* tcp_rcv_rtt_measure_ts()
*/
tp->rcv_rtt_last_tsecr = tp->rx_opt.rcv_tsecr;
return; return;
} else { /* Header too small */ } else { /* Header too small */
TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS); TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册