diff options
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r-- | net/ipv4/tcp_input.c | 29 |
1 files changed, 15 insertions, 14 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 923e0e568bfa..ad1482dd215e 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -2476,15 +2476,14 @@ static bool tcp_try_undo_loss(struct sock *sk, bool frto_undo) | |||
2476 | return false; | 2476 | return false; |
2477 | } | 2477 | } |
2478 | 2478 | ||
2479 | /* The cwnd reduction in CWR and Recovery use the PRR algorithm | 2479 | /* The cwnd reduction in CWR and Recovery uses the PRR algorithm in RFC 6937. |
2480 | * https://datatracker.ietf.org/doc/draft-ietf-tcpm-proportional-rate-reduction/ | ||
2481 | * It computes the number of packets to send (sndcnt) based on packets newly | 2480 | * It computes the number of packets to send (sndcnt) based on packets newly |
2482 | * delivered: | 2481 | * delivered: |
2483 | * 1) If the packets in flight is larger than ssthresh, PRR spreads the | 2482 | * 1) If the packets in flight is larger than ssthresh, PRR spreads the |
2484 | * cwnd reductions across a full RTT. | 2483 | * cwnd reductions across a full RTT. |
2485 | * 2) If packets in flight is lower than ssthresh (such as due to excess | 2484 | * 2) Otherwise PRR uses packet conservation to send as much as delivered. |
2486 | * losses and/or application stalls), do not perform any further cwnd | 2485 | * But when the retransmits are acked without further losses, PRR |
2487 | * reductions, but instead slow start up to ssthresh. | 2486 | * slow starts cwnd up to ssthresh to speed up the recovery. |
2488 | */ | 2487 | */ |
2489 | static void tcp_init_cwnd_reduction(struct sock *sk) | 2488 | static void tcp_init_cwnd_reduction(struct sock *sk) |
2490 | { | 2489 | { |
@@ -2501,7 +2500,7 @@ static void tcp_init_cwnd_reduction(struct sock *sk) | |||
2501 | } | 2500 | } |
2502 | 2501 | ||
2503 | static void tcp_cwnd_reduction(struct sock *sk, const int prior_unsacked, | 2502 | static void tcp_cwnd_reduction(struct sock *sk, const int prior_unsacked, |
2504 | int fast_rexmit) | 2503 | int fast_rexmit, int flag) |
2505 | { | 2504 | { |
2506 | struct tcp_sock *tp = tcp_sk(sk); | 2505 | struct tcp_sock *tp = tcp_sk(sk); |
2507 | int sndcnt = 0; | 2506 | int sndcnt = 0; |
@@ -2510,16 +2509,18 @@ static void tcp_cwnd_reduction(struct sock *sk, const int prior_unsacked, | |||
2510 | (tp->packets_out - tp->sacked_out); | 2509 | (tp->packets_out - tp->sacked_out); |
2511 | 2510 | ||
2512 | tp->prr_delivered += newly_acked_sacked; | 2511 | tp->prr_delivered += newly_acked_sacked; |
2513 | if (tcp_packets_in_flight(tp) > tp->snd_ssthresh) { | 2512 | if (delta < 0) { |
2514 | u64 dividend = (u64)tp->snd_ssthresh * tp->prr_delivered + | 2513 | u64 dividend = (u64)tp->snd_ssthresh * tp->prr_delivered + |
2515 | tp->prior_cwnd - 1; | 2514 | tp->prior_cwnd - 1; |
2516 | sndcnt = div_u64(dividend, tp->prior_cwnd) - tp->prr_out; | 2515 | sndcnt = div_u64(dividend, tp->prior_cwnd) - tp->prr_out; |
2517 | } else { | 2516 | } else if ((flag & FLAG_RETRANS_DATA_ACKED) && |
2517 | !(flag & FLAG_LOST_RETRANS)) { | ||
2518 | sndcnt = min_t(int, delta, | 2518 | sndcnt = min_t(int, delta, |
2519 | max_t(int, tp->prr_delivered - tp->prr_out, | 2519 | max_t(int, tp->prr_delivered - tp->prr_out, |
2520 | newly_acked_sacked) + 1); | 2520 | newly_acked_sacked) + 1); |
2521 | } else { | ||
2522 | sndcnt = min(delta, newly_acked_sacked); | ||
2521 | } | 2523 | } |
2522 | |||
2523 | sndcnt = max(sndcnt, (fast_rexmit ? 1 : 0)); | 2524 | sndcnt = max(sndcnt, (fast_rexmit ? 1 : 0)); |
2524 | tp->snd_cwnd = tcp_packets_in_flight(tp) + sndcnt; | 2525 | tp->snd_cwnd = tcp_packets_in_flight(tp) + sndcnt; |
2525 | } | 2526 | } |
@@ -2580,7 +2581,7 @@ static void tcp_try_to_open(struct sock *sk, int flag, const int prior_unsacked) | |||
2580 | if (inet_csk(sk)->icsk_ca_state != TCP_CA_CWR) { | 2581 | if (inet_csk(sk)->icsk_ca_state != TCP_CA_CWR) { |
2581 | tcp_try_keep_open(sk); | 2582 | tcp_try_keep_open(sk); |
2582 | } else { | 2583 | } else { |
2583 | tcp_cwnd_reduction(sk, prior_unsacked, 0); | 2584 | tcp_cwnd_reduction(sk, prior_unsacked, 0, flag); |
2584 | } | 2585 | } |
2585 | } | 2586 | } |
2586 | 2587 | ||
@@ -2737,7 +2738,7 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack) | |||
2737 | 2738 | ||
2738 | /* Undo during fast recovery after partial ACK. */ | 2739 | /* Undo during fast recovery after partial ACK. */ |
2739 | static bool tcp_try_undo_partial(struct sock *sk, const int acked, | 2740 | static bool tcp_try_undo_partial(struct sock *sk, const int acked, |
2740 | const int prior_unsacked) | 2741 | const int prior_unsacked, int flag) |
2741 | { | 2742 | { |
2742 | struct tcp_sock *tp = tcp_sk(sk); | 2743 | struct tcp_sock *tp = tcp_sk(sk); |
2743 | 2744 | ||
@@ -2753,7 +2754,7 @@ static bool tcp_try_undo_partial(struct sock *sk, const int acked, | |||
2753 | * mark more packets lost or retransmit more. | 2754 | * mark more packets lost or retransmit more. |
2754 | */ | 2755 | */ |
2755 | if (tp->retrans_out) { | 2756 | if (tp->retrans_out) { |
2756 | tcp_cwnd_reduction(sk, prior_unsacked, 0); | 2757 | tcp_cwnd_reduction(sk, prior_unsacked, 0, flag); |
2757 | return true; | 2758 | return true; |
2758 | } | 2759 | } |
2759 | 2760 | ||
@@ -2840,7 +2841,7 @@ static void tcp_fastretrans_alert(struct sock *sk, const int acked, | |||
2840 | if (tcp_is_reno(tp) && is_dupack) | 2841 | if (tcp_is_reno(tp) && is_dupack) |
2841 | tcp_add_reno_sack(sk); | 2842 | tcp_add_reno_sack(sk); |
2842 | } else { | 2843 | } else { |
2843 | if (tcp_try_undo_partial(sk, acked, prior_unsacked)) | 2844 | if (tcp_try_undo_partial(sk, acked, prior_unsacked, flag)) |
2844 | return; | 2845 | return; |
2845 | /* Partial ACK arrived. Force fast retransmit. */ | 2846 | /* Partial ACK arrived. Force fast retransmit. */ |
2846 | do_lost = tcp_is_reno(tp) || | 2847 | do_lost = tcp_is_reno(tp) || |
@@ -2891,7 +2892,7 @@ static void tcp_fastretrans_alert(struct sock *sk, const int acked, | |||
2891 | 2892 | ||
2892 | if (do_lost) | 2893 | if (do_lost) |
2893 | tcp_update_scoreboard(sk, fast_rexmit); | 2894 | tcp_update_scoreboard(sk, fast_rexmit); |
2894 | tcp_cwnd_reduction(sk, prior_unsacked, fast_rexmit); | 2895 | tcp_cwnd_reduction(sk, prior_unsacked, fast_rexmit, flag); |
2895 | tcp_xmit_retransmit_queue(sk); | 2896 | tcp_xmit_retransmit_queue(sk); |
2896 | } | 2897 | } |
2897 | 2898 | ||