diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/tcp_input.c | 24 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 3 |
2 files changed, 21 insertions, 6 deletions
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. |