aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r--net/ipv4/tcp_input.c39
1 files changed, 39 insertions, 0 deletions
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 */
3576static 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. */
3573static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) 3606static 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
3702invalid_ack: 3741invalid_ack: