diff options
-rw-r--r-- | net/ipv4/tcp_input.c | 42 |
1 files changed, 27 insertions, 15 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 8fe754be8076..0feb10935be1 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -104,6 +104,7 @@ int sysctl_tcp_abc __read_mostly; | |||
104 | #define FLAG_ONLY_ORIG_SACKED 0x200 /* SACKs only non-rexmit sent before RTO */ | 104 | #define FLAG_ONLY_ORIG_SACKED 0x200 /* SACKs only non-rexmit sent before RTO */ |
105 | #define FLAG_SND_UNA_ADVANCED 0x400 /* Snd_una was changed (!= FLAG_DATA_ACKED) */ | 105 | #define FLAG_SND_UNA_ADVANCED 0x400 /* Snd_una was changed (!= FLAG_DATA_ACKED) */ |
106 | #define FLAG_DSACKING_ACK 0x800 /* SACK blocks contained DSACK info */ | 106 | #define FLAG_DSACKING_ACK 0x800 /* SACK blocks contained DSACK info */ |
107 | #define FLAG_NONHEAD_RETRANS_ACKED 0x1000 /* Non-head rexmitted data was ACKed */ | ||
107 | 108 | ||
108 | #define FLAG_ACKED (FLAG_DATA_ACKED|FLAG_SYN_ACKED) | 109 | #define FLAG_ACKED (FLAG_DATA_ACKED|FLAG_SYN_ACKED) |
109 | #define FLAG_NOT_DUP (FLAG_DATA|FLAG_WIN_UPDATE|FLAG_ACKED) | 110 | #define FLAG_NOT_DUP (FLAG_DATA|FLAG_WIN_UPDATE|FLAG_ACKED) |
@@ -1594,6 +1595,8 @@ void tcp_enter_frto(struct sock *sk) | |||
1594 | tp->undo_retrans = 0; | 1595 | tp->undo_retrans = 0; |
1595 | 1596 | ||
1596 | skb = tcp_write_queue_head(sk); | 1597 | skb = tcp_write_queue_head(sk); |
1598 | if (TCP_SKB_CB(skb)->sacked & TCPCB_RETRANS) | ||
1599 | tp->undo_marker = 0; | ||
1597 | if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS) { | 1600 | if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS) { |
1598 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS; | 1601 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS; |
1599 | tp->retrans_out -= tcp_skb_pcount(skb); | 1602 | tp->retrans_out -= tcp_skb_pcount(skb); |
@@ -1643,6 +1646,8 @@ static void tcp_enter_frto_loss(struct sock *sk, int allowed_segments, int flag) | |||
1643 | /* ...enter this if branch just for the first segment */ | 1646 | /* ...enter this if branch just for the first segment */ |
1644 | flag |= FLAG_DATA_ACKED; | 1647 | flag |= FLAG_DATA_ACKED; |
1645 | } else { | 1648 | } else { |
1649 | if (TCP_SKB_CB(skb)->sacked & TCPCB_RETRANS) | ||
1650 | tp->undo_marker = 0; | ||
1646 | TCP_SKB_CB(skb)->sacked &= ~(TCPCB_LOST|TCPCB_SACKED_RETRANS); | 1651 | TCP_SKB_CB(skb)->sacked &= ~(TCPCB_LOST|TCPCB_SACKED_RETRANS); |
1647 | } | 1652 | } |
1648 | 1653 | ||
@@ -1658,7 +1663,6 @@ static void tcp_enter_frto_loss(struct sock *sk, int allowed_segments, int flag) | |||
1658 | tp->snd_cwnd = tcp_packets_in_flight(tp) + allowed_segments; | 1663 | tp->snd_cwnd = tcp_packets_in_flight(tp) + allowed_segments; |
1659 | tp->snd_cwnd_cnt = 0; | 1664 | tp->snd_cwnd_cnt = 0; |
1660 | tp->snd_cwnd_stamp = tcp_time_stamp; | 1665 | tp->snd_cwnd_stamp = tcp_time_stamp; |
1661 | tp->undo_marker = 0; | ||
1662 | tp->frto_counter = 0; | 1666 | tp->frto_counter = 0; |
1663 | 1667 | ||
1664 | tp->reordering = min_t(unsigned int, tp->reordering, | 1668 | tp->reordering = min_t(unsigned int, tp->reordering, |
@@ -2584,20 +2588,6 @@ static int tcp_clean_rtx_queue(struct sock *sk, s32 *seq_rtt_p) | |||
2584 | end_seq = scb->end_seq; | 2588 | end_seq = scb->end_seq; |
2585 | } | 2589 | } |
2586 | 2590 | ||
2587 | /* Initial outgoing SYN's get put onto the write_queue | ||
2588 | * just like anything else we transmit. It is not | ||
2589 | * true data, and if we misinform our callers that | ||
2590 | * this ACK acks real data, we will erroneously exit | ||
2591 | * connection startup slow start one packet too | ||
2592 | * quickly. This is severely frowned upon behavior. | ||
2593 | */ | ||
2594 | if (!(scb->flags & TCPCB_FLAG_SYN)) { | ||
2595 | flag |= FLAG_DATA_ACKED; | ||
2596 | } else { | ||
2597 | flag |= FLAG_SYN_ACKED; | ||
2598 | tp->retrans_stamp = 0; | ||
2599 | } | ||
2600 | |||
2601 | /* MTU probing checks */ | 2591 | /* MTU probing checks */ |
2602 | if (fully_acked && icsk->icsk_mtup.probe_size && | 2592 | if (fully_acked && icsk->icsk_mtup.probe_size && |
2603 | !after(tp->mtu_probe.probe_seq_end, scb->end_seq)) { | 2593 | !after(tp->mtu_probe.probe_seq_end, scb->end_seq)) { |
@@ -2610,6 +2600,9 @@ static int tcp_clean_rtx_queue(struct sock *sk, s32 *seq_rtt_p) | |||
2610 | tp->retrans_out -= packets_acked; | 2600 | tp->retrans_out -= packets_acked; |
2611 | flag |= FLAG_RETRANS_DATA_ACKED; | 2601 | flag |= FLAG_RETRANS_DATA_ACKED; |
2612 | seq_rtt = -1; | 2602 | seq_rtt = -1; |
2603 | if ((flag & FLAG_DATA_ACKED) || | ||
2604 | (packets_acked > 1)) | ||
2605 | flag |= FLAG_NONHEAD_RETRANS_ACKED; | ||
2613 | } else if (seq_rtt < 0) { | 2606 | } else if (seq_rtt < 0) { |
2614 | seq_rtt = now - scb->when; | 2607 | seq_rtt = now - scb->when; |
2615 | if (fully_acked) | 2608 | if (fully_acked) |
@@ -2631,6 +2624,20 @@ static int tcp_clean_rtx_queue(struct sock *sk, s32 *seq_rtt_p) | |||
2631 | } | 2624 | } |
2632 | tp->packets_out -= packets_acked; | 2625 | tp->packets_out -= packets_acked; |
2633 | 2626 | ||
2627 | /* Initial outgoing SYN's get put onto the write_queue | ||
2628 | * just like anything else we transmit. It is not | ||
2629 | * true data, and if we misinform our callers that | ||
2630 | * this ACK acks real data, we will erroneously exit | ||
2631 | * connection startup slow start one packet too | ||
2632 | * quickly. This is severely frowned upon behavior. | ||
2633 | */ | ||
2634 | if (!(scb->flags & TCPCB_FLAG_SYN)) { | ||
2635 | flag |= FLAG_DATA_ACKED; | ||
2636 | } else { | ||
2637 | flag |= FLAG_SYN_ACKED; | ||
2638 | tp->retrans_stamp = 0; | ||
2639 | } | ||
2640 | |||
2634 | if (!fully_acked) | 2641 | if (!fully_acked) |
2635 | break; | 2642 | break; |
2636 | 2643 | ||
@@ -2852,6 +2859,10 @@ static int tcp_process_frto(struct sock *sk, int flag) | |||
2852 | if (flag&FLAG_DATA_ACKED) | 2859 | if (flag&FLAG_DATA_ACKED) |
2853 | inet_csk(sk)->icsk_retransmits = 0; | 2860 | inet_csk(sk)->icsk_retransmits = 0; |
2854 | 2861 | ||
2862 | if ((flag & FLAG_NONHEAD_RETRANS_ACKED) || | ||
2863 | ((tp->frto_counter >= 2) && (flag & FLAG_RETRANS_DATA_ACKED))) | ||
2864 | tp->undo_marker = 0; | ||
2865 | |||
2855 | if (!before(tp->snd_una, tp->frto_highmark)) { | 2866 | if (!before(tp->snd_una, tp->frto_highmark)) { |
2856 | tcp_enter_frto_loss(sk, (tp->frto_counter == 1 ? 2 : 3), flag); | 2867 | tcp_enter_frto_loss(sk, (tp->frto_counter == 1 ? 2 : 3), flag); |
2857 | return 1; | 2868 | return 1; |
@@ -2916,6 +2927,7 @@ static int tcp_process_frto(struct sock *sk, int flag) | |||
2916 | break; | 2927 | break; |
2917 | } | 2928 | } |
2918 | tp->frto_counter = 0; | 2929 | tp->frto_counter = 0; |
2930 | tp->undo_marker = 0; | ||
2919 | } | 2931 | } |
2920 | return 0; | 2932 | return 0; |
2921 | } | 2933 | } |