diff options
| -rw-r--r-- | net/ipv4/tcp_input.c | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index e990d562f5e3..cc935c8a6aae 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
| @@ -1296,7 +1296,7 @@ void tcp_enter_frto(struct sock *sk) | |||
| 1296 | * which indicates that we should follow the traditional RTO recovery, | 1296 | * which indicates that we should follow the traditional RTO recovery, |
| 1297 | * i.e. mark everything lost and do go-back-N retransmission. | 1297 | * i.e. mark everything lost and do go-back-N retransmission. |
| 1298 | */ | 1298 | */ |
| 1299 | static void tcp_enter_frto_loss(struct sock *sk) | 1299 | static void tcp_enter_frto_loss(struct sock *sk, int allowed_segments) |
| 1300 | { | 1300 | { |
| 1301 | struct tcp_sock *tp = tcp_sk(sk); | 1301 | struct tcp_sock *tp = tcp_sk(sk); |
| 1302 | struct sk_buff *skb; | 1302 | struct sk_buff *skb; |
| @@ -1326,7 +1326,7 @@ static void tcp_enter_frto_loss(struct sock *sk) | |||
| 1326 | } | 1326 | } |
| 1327 | tcp_sync_left_out(tp); | 1327 | tcp_sync_left_out(tp); |
| 1328 | 1328 | ||
| 1329 | tp->snd_cwnd = tp->frto_counter + tcp_packets_in_flight(tp)+1; | 1329 | tp->snd_cwnd = tcp_packets_in_flight(tp) + allowed_segments; |
| 1330 | tp->snd_cwnd_cnt = 0; | 1330 | tp->snd_cwnd_cnt = 0; |
| 1331 | tp->snd_cwnd_stamp = tcp_time_stamp; | 1331 | tp->snd_cwnd_stamp = tcp_time_stamp; |
| 1332 | tp->undo_marker = 0; | 1332 | tp->undo_marker = 0; |
| @@ -2527,6 +2527,11 @@ static void tcp_process_frto(struct sock *sk, u32 prior_snd_una, int flag) | |||
| 2527 | if (flag&FLAG_DATA_ACKED) | 2527 | if (flag&FLAG_DATA_ACKED) |
| 2528 | inet_csk(sk)->icsk_retransmits = 0; | 2528 | inet_csk(sk)->icsk_retransmits = 0; |
| 2529 | 2529 | ||
| 2530 | if (!before(tp->snd_una, tp->frto_highmark)) { | ||
| 2531 | tcp_enter_frto_loss(sk, tp->frto_counter + 1); | ||
| 2532 | return; | ||
| 2533 | } | ||
| 2534 | |||
| 2530 | /* RFC4138 shortcoming in step 2; should also have case c): ACK isn't | 2535 | /* RFC4138 shortcoming in step 2; should also have case c): ACK isn't |
| 2531 | * duplicate nor advances window, e.g., opposite dir data, winupdate | 2536 | * duplicate nor advances window, e.g., opposite dir data, winupdate |
| 2532 | */ | 2537 | */ |
| @@ -2534,9 +2539,8 @@ static void tcp_process_frto(struct sock *sk, u32 prior_snd_una, int flag) | |||
| 2534 | !(flag&FLAG_FORWARD_PROGRESS)) | 2539 | !(flag&FLAG_FORWARD_PROGRESS)) |
| 2535 | return; | 2540 | return; |
| 2536 | 2541 | ||
| 2537 | if (tp->snd_una == prior_snd_una || | 2542 | if (!(flag&FLAG_DATA_ACKED)) { |
| 2538 | !before(tp->snd_una, tp->frto_highmark)) { | 2543 | tcp_enter_frto_loss(sk, (tp->frto_counter == 1 ? 0 : 3)); |
| 2539 | tcp_enter_frto_loss(sk); | ||
| 2540 | return; | 2544 | return; |
| 2541 | } | 2545 | } |
| 2542 | 2546 | ||
