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

Commit 986ca37e authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'tcp-in-slow-start'



Yuchung Cheng says:

====================
tcp: fixes some congestion control corner cases

This patch series fixes corner cases of TCP congestion control.
First issue is to avoid continuing slow start when cwnd reaches ssthresh.
Second issue is incorrectly processing order of congestion state and
cwnd update when entering fast recovery or undoing cwnd.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 1007f59d b20a3fa3
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -989,6 +989,11 @@ static inline unsigned int tcp_packets_in_flight(const struct tcp_sock *tp)

#define TCP_INFINITE_SSTHRESH	0x7fffffff

static inline bool tcp_in_slow_start(const struct tcp_sock *tp)
{
	return tp->snd_cwnd < tp->snd_ssthresh;
}

static inline bool tcp_in_initial_slowstart(const struct tcp_sock *tp)
{
	return tp->snd_ssthresh >= TCP_INFINITE_SSTHRESH;
@@ -1065,7 +1070,7 @@ static inline bool tcp_is_cwnd_limited(const struct sock *sk)
	const struct tcp_sock *tp = tcp_sk(sk);

	/* If in slow start, ensure cwnd grows to twice what was ACKed. */
	if (tp->snd_cwnd <= tp->snd_ssthresh)
	if (tcp_in_slow_start(tp))
		return tp->snd_cwnd < 2 * tp->max_packets_out;

	return tp->is_cwnd_limited;
+1 −1
Original line number Diff line number Diff line
@@ -146,7 +146,7 @@ static void bictcp_cong_avoid(struct sock *sk, u32 ack, u32 acked)
	if (!tcp_is_cwnd_limited(sk))
		return;

	if (tp->snd_cwnd <= tp->snd_ssthresh)
	if (tcp_in_slow_start(tp))
		tcp_slow_start(tp, acked);
	else {
		bictcp_update(ca, tp->snd_cwnd);
+1 −1
Original line number Diff line number Diff line
@@ -264,7 +264,7 @@ static void tcp_cdg_cong_avoid(struct sock *sk, u32 ack, u32 acked)
	u32 prior_snd_cwnd;
	u32 incr;

	if (tp->snd_cwnd < tp->snd_ssthresh && hystart_detect)
	if (tcp_in_slow_start(tp) && hystart_detect)
		tcp_cdg_hystart_update(sk);

	if (after(ack, ca->rtt_seq) && ca->rtt.v64) {
+2 −4
Original line number Diff line number Diff line
@@ -365,10 +365,8 @@ int tcp_set_congestion_control(struct sock *sk, const char *name)
 */
u32 tcp_slow_start(struct tcp_sock *tp, u32 acked)
{
	u32 cwnd = tp->snd_cwnd + acked;
	u32 cwnd = min(tp->snd_cwnd + acked, tp->snd_ssthresh);

	if (cwnd > tp->snd_ssthresh)
		cwnd = tp->snd_ssthresh + 1;
	acked -= cwnd - tp->snd_cwnd;
	tp->snd_cwnd = min(cwnd, tp->snd_cwnd_clamp);

@@ -413,7 +411,7 @@ void tcp_reno_cong_avoid(struct sock *sk, u32 ack, u32 acked)
		return;

	/* In "safe" area, increase. */
	if (tp->snd_cwnd <= tp->snd_ssthresh) {
	if (tcp_in_slow_start(tp)) {
		acked = tcp_slow_start(tp, acked);
		if (!acked)
			return;
+2 −2
Original line number Diff line number Diff line
@@ -320,7 +320,7 @@ static void bictcp_cong_avoid(struct sock *sk, u32 ack, u32 acked)
	if (!tcp_is_cwnd_limited(sk))
		return;

	if (tp->snd_cwnd <= tp->snd_ssthresh) {
	if (tcp_in_slow_start(tp)) {
		if (hystart && after(ack, ca->end_seq))
			bictcp_hystart_reset(sk);
		acked = tcp_slow_start(tp, acked);
@@ -439,7 +439,7 @@ static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us)
		ca->delay_min = delay;

	/* hystart triggers when cwnd is larger than some threshold */
	if (hystart && tp->snd_cwnd <= tp->snd_ssthresh &&
	if (hystart && tcp_in_slow_start(tp) &&
	    tp->snd_cwnd >= hystart_low_window)
		hystart_update(sk, delay);
}
Loading