Skip to content

Commit 3f6c65d

Browse files
tracywwnjdavem330
authored andcommitted
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: Wei Wang <weiwan@google.com> Signed-off-by: Neal Cardwell <ncardwell@google.com> Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 66caeeb commit 3f6c65d

File tree

3 files changed

+13
-3
lines changed

3 files changed

+13
-3
lines changed

include/linux/tcp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ struct tcp_sock {
350350
#endif
351351

352352
/* Receiver side RTT estimation */
353+
u32 rcv_rtt_last_tsecr;
353354
struct {
354355
u32 rtt_us;
355356
u32 seq;

net/ipv4/tcp.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2563,6 +2563,7 @@ int tcp_disconnect(struct sock *sk, int flags)
25632563
sk->sk_shutdown = 0;
25642564
sock_reset_flag(sk, SOCK_DONE);
25652565
tp->srtt_us = 0;
2566+
tp->rcv_rtt_last_tsecr = 0;
25662567
tp->write_seq += tp->max_window + 2;
25672568
if (tp->write_seq == 0)
25682569
tp->write_seq = 1;

net/ipv4/tcp_input.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -582,9 +582,12 @@ static inline void tcp_rcv_rtt_measure_ts(struct sock *sk,
582582
{
583583
struct tcp_sock *tp = tcp_sk(sk);
584584

585-
if (tp->rx_opt.rcv_tsecr &&
586-
(TCP_SKB_CB(skb)->end_seq -
587-
TCP_SKB_CB(skb)->seq >= inet_csk(sk)->icsk_ack.rcv_mss)) {
585+
if (tp->rx_opt.rcv_tsecr == tp->rcv_rtt_last_tsecr)
586+
return;
587+
tp->rcv_rtt_last_tsecr = tp->rx_opt.rcv_tsecr;
588+
589+
if (TCP_SKB_CB(skb)->end_seq -
590+
TCP_SKB_CB(skb)->seq >= inet_csk(sk)->icsk_ack.rcv_mss) {
588591
u32 delta = tcp_time_stamp(tp) - tp->rx_opt.rcv_tsecr;
589592
u32 delta_us;
590593

@@ -5475,6 +5478,11 @@ void tcp_rcv_established(struct sock *sk, struct sk_buff *skb)
54755478
tcp_ack(sk, skb, 0);
54765479
__kfree_skb(skb);
54775480
tcp_data_snd_check(sk);
5481+
/* When receiving pure ack in fast path, update
5482+
* last ts ecr directly instead of calling
5483+
* tcp_rcv_rtt_measure_ts()
5484+
*/
5485+
tp->rcv_rtt_last_tsecr = tp->rx_opt.rcv_tsecr;
54785486
return;
54795487
} else { /* Header too small */
54805488
TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS);

0 commit comments

Comments
 (0)