diff options
| -rw-r--r-- | include/net/tcp.h | 2 | ||||
| -rw-r--r-- | net/ipv4/tcp_input.c | 24 | ||||
| -rw-r--r-- | net/ipv4/tcp_output.c | 3 |
3 files changed, 23 insertions, 6 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h index 7de4ea3a04d9..4fd3eb2f8ec2 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
| @@ -752,6 +752,8 @@ static inline unsigned int tcp_packets_in_flight(const struct tcp_sock *tp) | |||
| 752 | return tp->packets_out - tcp_left_out(tp) + tp->retrans_out; | 752 | return tp->packets_out - tcp_left_out(tp) + tp->retrans_out; |
| 753 | } | 753 | } |
| 754 | 754 | ||
| 755 | extern int tcp_limit_reno_sacked(struct tcp_sock *tp); | ||
| 756 | |||
| 755 | /* If cwnd > ssthresh, we may raise ssthresh to be half-way to cwnd. | 757 | /* If cwnd > ssthresh, we may raise ssthresh to be half-way to cwnd. |
| 756 | * The exception is rate halving phase, when cwnd is decreasing towards | 758 | * The exception is rate halving phase, when cwnd is decreasing towards |
| 757 | * ssthresh. | 759 | * ssthresh. |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 7d0958785bfb..b4812c3cbbcf 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
| @@ -1625,13 +1625,11 @@ out: | |||
| 1625 | return flag; | 1625 | return flag; |
| 1626 | } | 1626 | } |
| 1627 | 1627 | ||
| 1628 | /* If we receive more dupacks than we expected counting segments | 1628 | /* Limits sacked_out so that sum with lost_out isn't ever larger than |
| 1629 | * in assumption of absent reordering, interpret this as reordering. | 1629 | * packets_out. Returns zero if sacked_out adjustement wasn't necessary. |
| 1630 | * The only another reason could be bug in receiver TCP. | ||
| 1631 | */ | 1630 | */ |
| 1632 | static void tcp_check_reno_reordering(struct sock *sk, const int addend) | 1631 | int tcp_limit_reno_sacked(struct tcp_sock *tp) |
| 1633 | { | 1632 | { |
| 1634 | struct tcp_sock *tp = tcp_sk(sk); | ||
| 1635 | u32 holes; | 1633 | u32 holes; |
| 1636 | 1634 | ||
| 1637 | holes = max(tp->lost_out, 1U); | 1635 | holes = max(tp->lost_out, 1U); |
| @@ -1639,8 +1637,20 @@ static void tcp_check_reno_reordering(struct sock *sk, const int addend) | |||
| 1639 | 1637 | ||
| 1640 | if ((tp->sacked_out + holes) > tp->packets_out) { | 1638 | if ((tp->sacked_out + holes) > tp->packets_out) { |
| 1641 | tp->sacked_out = tp->packets_out - holes; | 1639 | tp->sacked_out = tp->packets_out - holes; |
| 1642 | tcp_update_reordering(sk, tp->packets_out + addend, 0); | 1640 | return 1; |
| 1643 | } | 1641 | } |
| 1642 | return 0; | ||
| 1643 | } | ||
| 1644 | |||
| 1645 | /* If we receive more dupacks than we expected counting segments | ||
| 1646 | * in assumption of absent reordering, interpret this as reordering. | ||
| 1647 | * The only another reason could be bug in receiver TCP. | ||
| 1648 | */ | ||
| 1649 | static void tcp_check_reno_reordering(struct sock *sk, const int addend) | ||
| 1650 | { | ||
| 1651 | struct tcp_sock *tp = tcp_sk(sk); | ||
| 1652 | if (tcp_limit_reno_sacked(tp)) | ||
| 1653 | tcp_update_reordering(sk, tp->packets_out + addend, 0); | ||
| 1644 | } | 1654 | } |
| 1645 | 1655 | ||
| 1646 | /* Emulate SACKs for SACKless connection: account for a new dupack. */ | 1656 | /* Emulate SACKs for SACKless connection: account for a new dupack. */ |
| @@ -2600,6 +2610,8 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, int flag) | |||
| 2600 | case TCP_CA_Loss: | 2610 | case TCP_CA_Loss: |
| 2601 | if (flag & FLAG_DATA_ACKED) | 2611 | if (flag & FLAG_DATA_ACKED) |
| 2602 | icsk->icsk_retransmits = 0; | 2612 | icsk->icsk_retransmits = 0; |
| 2613 | if (tcp_is_reno(tp) && flag & FLAG_SND_UNA_ADVANCED) | ||
| 2614 | tcp_reset_reno_sack(tp); | ||
| 2603 | if (!tcp_try_undo_loss(sk)) { | 2615 | if (!tcp_try_undo_loss(sk)) { |
| 2604 | tcp_moderate_cwnd(tp); | 2616 | tcp_moderate_cwnd(tp); |
| 2605 | tcp_xmit_retransmit_queue(sk); | 2617 | tcp_xmit_retransmit_queue(sk); |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 72b9350006fe..d29ef79c00ca 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
| @@ -1808,6 +1808,9 @@ void tcp_simple_retransmit(struct sock *sk) | |||
| 1808 | if (!lost) | 1808 | if (!lost) |
| 1809 | return; | 1809 | return; |
| 1810 | 1810 | ||
| 1811 | if (tcp_is_reno(tp)) | ||
| 1812 | tcp_limit_reno_sacked(tp); | ||
| 1813 | |||
| 1811 | tcp_verify_left_out(tp); | 1814 | tcp_verify_left_out(tp); |
| 1812 | 1815 | ||
| 1813 | /* Don't muck with the congestion window here. | 1816 | /* Don't muck with the congestion window here. |
