|
@@ -1851,19 +1851,22 @@ static inline u32 tcp_cwnd_min(const struct sock *sk)
|
|
|
}
|
|
|
|
|
|
/* Decrease cwnd each second ack. */
|
|
|
-static void tcp_cwnd_down(struct sock *sk)
|
|
|
+static void tcp_cwnd_down(struct sock *sk, int flag)
|
|
|
{
|
|
|
struct tcp_sock *tp = tcp_sk(sk);
|
|
|
int decr = tp->snd_cwnd_cnt + 1;
|
|
|
|
|
|
- tp->snd_cwnd_cnt = decr&1;
|
|
|
- decr >>= 1;
|
|
|
+ if ((flag&FLAG_FORWARD_PROGRESS) ||
|
|
|
+ (IsReno(tp) && !(flag&FLAG_NOT_DUP))) {
|
|
|
+ tp->snd_cwnd_cnt = decr&1;
|
|
|
+ decr >>= 1;
|
|
|
|
|
|
- if (decr && tp->snd_cwnd > tcp_cwnd_min(sk))
|
|
|
- tp->snd_cwnd -= decr;
|
|
|
+ if (decr && tp->snd_cwnd > tcp_cwnd_min(sk))
|
|
|
+ tp->snd_cwnd -= decr;
|
|
|
|
|
|
- tp->snd_cwnd = min(tp->snd_cwnd, tcp_packets_in_flight(tp)+1);
|
|
|
- tp->snd_cwnd_stamp = tcp_time_stamp;
|
|
|
+ tp->snd_cwnd = min(tp->snd_cwnd, tcp_packets_in_flight(tp)+1);
|
|
|
+ tp->snd_cwnd_stamp = tcp_time_stamp;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/* Nothing was retransmitted or returned timestamp is less
|
|
@@ -2060,7 +2063,7 @@ static void tcp_try_to_open(struct sock *sk, int flag)
|
|
|
}
|
|
|
tcp_moderate_cwnd(tp);
|
|
|
} else {
|
|
|
- tcp_cwnd_down(sk);
|
|
|
+ tcp_cwnd_down(sk, flag);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -2260,7 +2263,7 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
|
|
|
|
|
|
if (is_dupack || tcp_head_timedout(sk))
|
|
|
tcp_update_scoreboard(sk);
|
|
|
- tcp_cwnd_down(sk);
|
|
|
+ tcp_cwnd_down(sk, flag);
|
|
|
tcp_xmit_retransmit_queue(sk);
|
|
|
}
|
|
|
|