diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/proc.c | 1 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 39 | ||||
-rw-r--r-- | net/ipv4/tcp_minisocks.c | 1 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 9 | ||||
-rw-r--r-- | net/ipv4/tcp_timer.c | 2 |
5 files changed, 52 insertions, 0 deletions
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 4c35911d935f..b6f2ea174898 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c | |||
@@ -225,6 +225,7 @@ static const struct snmp_mib snmp4_net_list[] = { | |||
225 | SNMP_MIB_ITEM("TCPSlowStartRetrans", LINUX_MIB_TCPSLOWSTARTRETRANS), | 225 | SNMP_MIB_ITEM("TCPSlowStartRetrans", LINUX_MIB_TCPSLOWSTARTRETRANS), |
226 | SNMP_MIB_ITEM("TCPTimeouts", LINUX_MIB_TCPTIMEOUTS), | 226 | SNMP_MIB_ITEM("TCPTimeouts", LINUX_MIB_TCPTIMEOUTS), |
227 | SNMP_MIB_ITEM("TCPLossProbes", LINUX_MIB_TCPLOSSPROBES), | 227 | SNMP_MIB_ITEM("TCPLossProbes", LINUX_MIB_TCPLOSSPROBES), |
228 | SNMP_MIB_ITEM("TCPLossProbeRecovery", LINUX_MIB_TCPLOSSPROBERECOVERY), | ||
228 | SNMP_MIB_ITEM("TCPRenoRecoveryFail", LINUX_MIB_TCPRENORECOVERYFAIL), | 229 | SNMP_MIB_ITEM("TCPRenoRecoveryFail", LINUX_MIB_TCPRENORECOVERYFAIL), |
229 | SNMP_MIB_ITEM("TCPSackRecoveryFail", LINUX_MIB_TCPSACKRECOVERYFAIL), | 230 | SNMP_MIB_ITEM("TCPSackRecoveryFail", LINUX_MIB_TCPSACKRECOVERYFAIL), |
230 | SNMP_MIB_ITEM("TCPSchedulerFailed", LINUX_MIB_TCPSCHEDULERFAILED), | 231 | SNMP_MIB_ITEM("TCPSchedulerFailed", LINUX_MIB_TCPSCHEDULERFAILED), |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index b794f89ac1f2..836d74dd0187 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -2682,6 +2682,7 @@ static void tcp_init_cwnd_reduction(struct sock *sk, const bool set_ssthresh) | |||
2682 | struct tcp_sock *tp = tcp_sk(sk); | 2682 | struct tcp_sock *tp = tcp_sk(sk); |
2683 | 2683 | ||
2684 | tp->high_seq = tp->snd_nxt; | 2684 | tp->high_seq = tp->snd_nxt; |
2685 | tp->tlp_high_seq = 0; | ||
2685 | tp->snd_cwnd_cnt = 0; | 2686 | tp->snd_cwnd_cnt = 0; |
2686 | tp->prior_cwnd = tp->snd_cwnd; | 2687 | tp->prior_cwnd = tp->snd_cwnd; |
2687 | tp->prr_delivered = 0; | 2688 | tp->prr_delivered = 0; |
@@ -3569,6 +3570,38 @@ static void tcp_send_challenge_ack(struct sock *sk) | |||
3569 | } | 3570 | } |
3570 | } | 3571 | } |
3571 | 3572 | ||
3573 | /* This routine deals with acks during a TLP episode. | ||
3574 | * Ref: loss detection algorithm in draft-dukkipati-tcpm-tcp-loss-probe. | ||
3575 | */ | ||
3576 | static void tcp_process_tlp_ack(struct sock *sk, u32 ack, int flag) | ||
3577 | { | ||
3578 | struct tcp_sock *tp = tcp_sk(sk); | ||
3579 | bool is_tlp_dupack = (ack == tp->tlp_high_seq) && | ||
3580 | !(flag & (FLAG_SND_UNA_ADVANCED | | ||
3581 | FLAG_NOT_DUP | FLAG_DATA_SACKED)); | ||
3582 | |||
3583 | /* Mark the end of TLP episode on receiving TLP dupack or when | ||
3584 | * ack is after tlp_high_seq. | ||
3585 | */ | ||
3586 | if (is_tlp_dupack) { | ||
3587 | tp->tlp_high_seq = 0; | ||
3588 | return; | ||
3589 | } | ||
3590 | |||
3591 | if (after(ack, tp->tlp_high_seq)) { | ||
3592 | tp->tlp_high_seq = 0; | ||
3593 | /* Don't reduce cwnd if DSACK arrives for TLP retrans. */ | ||
3594 | if (!(flag & FLAG_DSACKING_ACK)) { | ||
3595 | tcp_init_cwnd_reduction(sk, true); | ||
3596 | tcp_set_ca_state(sk, TCP_CA_CWR); | ||
3597 | tcp_end_cwnd_reduction(sk); | ||
3598 | tcp_set_ca_state(sk, TCP_CA_Open); | ||
3599 | NET_INC_STATS_BH(sock_net(sk), | ||
3600 | LINUX_MIB_TCPLOSSPROBERECOVERY); | ||
3601 | } | ||
3602 | } | ||
3603 | } | ||
3604 | |||
3572 | /* This routine deals with incoming acks, but not outgoing ones. */ | 3605 | /* This routine deals with incoming acks, but not outgoing ones. */ |
3573 | static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) | 3606 | static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) |
3574 | { | 3607 | { |
@@ -3676,6 +3709,9 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) | |||
3676 | tcp_cong_avoid(sk, ack, prior_in_flight); | 3709 | tcp_cong_avoid(sk, ack, prior_in_flight); |
3677 | } | 3710 | } |
3678 | 3711 | ||
3712 | if (tp->tlp_high_seq) | ||
3713 | tcp_process_tlp_ack(sk, ack, flag); | ||
3714 | |||
3679 | if ((flag & FLAG_FORWARD_PROGRESS) || !(flag & FLAG_NOT_DUP)) { | 3715 | if ((flag & FLAG_FORWARD_PROGRESS) || !(flag & FLAG_NOT_DUP)) { |
3680 | struct dst_entry *dst = __sk_dst_get(sk); | 3716 | struct dst_entry *dst = __sk_dst_get(sk); |
3681 | if (dst) | 3717 | if (dst) |
@@ -3697,6 +3733,9 @@ no_queue: | |||
3697 | */ | 3733 | */ |
3698 | if (tcp_send_head(sk)) | 3734 | if (tcp_send_head(sk)) |
3699 | tcp_ack_probe(sk); | 3735 | tcp_ack_probe(sk); |
3736 | |||
3737 | if (tp->tlp_high_seq) | ||
3738 | tcp_process_tlp_ack(sk, ack, flag); | ||
3700 | return 1; | 3739 | return 1; |
3701 | 3740 | ||
3702 | invalid_ack: | 3741 | invalid_ack: |
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index b83a49cc3816..4bdb09fca401 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
@@ -440,6 +440,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, | |||
440 | newtp->fackets_out = 0; | 440 | newtp->fackets_out = 0; |
441 | newtp->snd_ssthresh = TCP_INFINITE_SSTHRESH; | 441 | newtp->snd_ssthresh = TCP_INFINITE_SSTHRESH; |
442 | tcp_enable_early_retrans(newtp); | 442 | tcp_enable_early_retrans(newtp); |
443 | newtp->tlp_high_seq = 0; | ||
443 | 444 | ||
444 | /* So many TCP implementations out there (incorrectly) count the | 445 | /* So many TCP implementations out there (incorrectly) count the |
445 | * initial SYN frame in their delayed-ACK and congestion control | 446 | * initial SYN frame in their delayed-ACK and congestion control |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index beb63dbc85f5..8e7742f0b5d2 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -2132,6 +2132,7 @@ bool tcp_schedule_loss_probe(struct sock *sk) | |||
2132 | */ | 2132 | */ |
2133 | void tcp_send_loss_probe(struct sock *sk) | 2133 | void tcp_send_loss_probe(struct sock *sk) |
2134 | { | 2134 | { |
2135 | struct tcp_sock *tp = tcp_sk(sk); | ||
2135 | struct sk_buff *skb; | 2136 | struct sk_buff *skb; |
2136 | int pcount; | 2137 | int pcount; |
2137 | int mss = tcp_current_mss(sk); | 2138 | int mss = tcp_current_mss(sk); |
@@ -2142,6 +2143,10 @@ void tcp_send_loss_probe(struct sock *sk) | |||
2142 | goto rearm_timer; | 2143 | goto rearm_timer; |
2143 | } | 2144 | } |
2144 | 2145 | ||
2146 | /* At most one outstanding TLP retransmission. */ | ||
2147 | if (tp->tlp_high_seq) | ||
2148 | goto rearm_timer; | ||
2149 | |||
2145 | /* Retransmit last segment. */ | 2150 | /* Retransmit last segment. */ |
2146 | skb = tcp_write_queue_tail(sk); | 2151 | skb = tcp_write_queue_tail(sk); |
2147 | if (WARN_ON(!skb)) | 2152 | if (WARN_ON(!skb)) |
@@ -2164,6 +2169,10 @@ void tcp_send_loss_probe(struct sock *sk) | |||
2164 | if (skb->len > 0) | 2169 | if (skb->len > 0) |
2165 | err = __tcp_retransmit_skb(sk, skb); | 2170 | err = __tcp_retransmit_skb(sk, skb); |
2166 | 2171 | ||
2172 | /* Record snd_nxt for loss detection. */ | ||
2173 | if (likely(!err)) | ||
2174 | tp->tlp_high_seq = tp->snd_nxt; | ||
2175 | |||
2167 | rearm_timer: | 2176 | rearm_timer: |
2168 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, | 2177 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, |
2169 | inet_csk(sk)->icsk_rto, | 2178 | inet_csk(sk)->icsk_rto, |
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index ecd61d54147f..eeccf795e917 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c | |||
@@ -356,6 +356,8 @@ void tcp_retransmit_timer(struct sock *sk) | |||
356 | 356 | ||
357 | WARN_ON(tcp_write_queue_empty(sk)); | 357 | WARN_ON(tcp_write_queue_empty(sk)); |
358 | 358 | ||
359 | tp->tlp_high_seq = 0; | ||
360 | |||
359 | if (!tp->snd_wnd && !sock_flag(sk, SOCK_DEAD) && | 361 | if (!tp->snd_wnd && !sock_flag(sk, SOCK_DEAD) && |
360 | !((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV))) { | 362 | !((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV))) { |
361 | /* Receiver dastardly shrinks window. Our retransmits | 363 | /* Receiver dastardly shrinks window. Our retransmits |