Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 57d532a0 authored by Eric Dumazet's avatar Eric Dumazet Committed by Kaustubh Pandey
Browse files

tcp: address problems caused by EDT misshaps



When a qdisc setup including pacing FQ is dismantled and recreated,
some TCP packets are sent earlier than instructed by TCP stack.
TCP can be fooled when ACK comes back, because the following
operation can return a negative value.

    tcp_time_stamp(tp) - tp->rx_opt.rcv_tsecr;

Some paths in TCP stack were not dealing properly with this,
this patch addresses four of them.

Change-Id: Ib7208509a066a9fd8c6b83846bc69fe33a6ae617
Fixes: ab408b6dc744 ("tcp: switch tcp and sch_fq to new earliest departure time model")
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Git-Commit: 9efdda4e3abed13f0903b7b6e4d4c2102019440a
Git-repo: https://android.googlesource.com/kernel/common/


Signed-off-by: default avatarKaustubh Pandey <kapandey@codeaurora.org>
parent 502f6541
Loading
Loading
Loading
Loading
+10 −6
Original line number Diff line number Diff line
@@ -580,12 +580,14 @@ static inline void tcp_rcv_rtt_measure_ts(struct sock *sk,
		u32 delta = tcp_time_stamp(tp) - tp->rx_opt.rcv_tsecr;
		u32 delta_us;

		if (likely(delta < INT_MAX / (USEC_PER_SEC / TCP_TS_HZ))) {
			if (!delta)
				delta = 1;
			delta_us = delta * (USEC_PER_SEC / TCP_TS_HZ);
			tcp_rcv_rtt_update(tp, delta_us, 0);
		}
	}
}

/*
 * This function should be called every time data is copied to user space.
@@ -2929,9 +2931,11 @@ static bool tcp_ack_update_rtt(struct sock *sk, const int flag,
	if (seq_rtt_us < 0 && tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr &&
	    flag & FLAG_ACKED) {
		u32 delta = tcp_time_stamp(tp) - tp->rx_opt.rcv_tsecr;
		u32 delta_us = delta * (USEC_PER_SEC / TCP_TS_HZ);

		seq_rtt_us = ca_rtt_us = delta_us;
		if (likely(delta < INT_MAX / (USEC_PER_SEC / TCP_TS_HZ))) {
			seq_rtt_us = delta * (USEC_PER_SEC / TCP_TS_HZ);
			ca_rtt_us = seq_rtt_us;
		}
	}
	rs->rtt_us = ca_rtt_us; /* RTT of last (S)ACKed packet (or -1) */
	if (seq_rtt_us < 0)
+6 −4
Original line number Diff line number Diff line
@@ -40,15 +40,17 @@ static u32 tcp_clamp_rto_to_user_timeout(const struct sock *sk)
{
	struct inet_connection_sock *icsk = inet_csk(sk);
	u32 elapsed, start_ts;
	s32 remaining;

	start_ts = tcp_retransmit_stamp(sk);
	if (!icsk->icsk_user_timeout || !start_ts)
		return icsk->icsk_rto;
	elapsed = tcp_time_stamp(tcp_sk(sk)) - start_ts;
	if (elapsed >= icsk->icsk_user_timeout)
	remaining = icsk->icsk_user_timeout - elapsed;
	if (remaining <= 0)
		return 1; /* user timeout has passed; fire ASAP */
	else
		return min_t(u32, icsk->icsk_rto, msecs_to_jiffies(icsk->icsk_user_timeout - elapsed));

	return min_t(u32, icsk->icsk_rto, msecs_to_jiffies(remaining));
}

static void set_tcp_default(void)
@@ -242,7 +244,7 @@ static bool retransmits_timed_out(struct sock *sk,
				(boundary - linear_backoff_thresh) * TCP_RTO_MAX;
		timeout = jiffies_to_msecs(timeout);
	}
	return (tcp_time_stamp(tcp_sk(sk)) - start_ts) >= timeout;
	return (s32)(tcp_time_stamp(tcp_sk(sk)) - start_ts - timeout) >= 0;
}

/* A write timeout has occurred. Process the after effects. */