Merge remote-tracking branch 'sound/for-next'
[linux] / net / ipv4 / tcp_output.c
index 730bc44..96bdb8e 100644 (file)
@@ -165,13 +165,16 @@ static void tcp_event_data_sent(struct tcp_sock *tp,
        if (tcp_packets_in_flight(tp) == 0)
                tcp_ca_event(sk, CA_EVENT_TX_START);
 
-       tp->lsndtime = now;
-
-       /* If it is a reply for ato after last received
-        * packet, enter pingpong mode.
+       /* If this is the first data packet sent in response to the
+        * previous received data,
+        * and it is a reply for ato after last received packet,
+        * increase pingpong count.
         */
-       if ((u32)(now - icsk->icsk_ack.lrcvtime) < icsk->icsk_ack.ato)
-               icsk->icsk_ack.pingpong = 1;
+       if (before(tp->lsndtime, icsk->icsk_ack.lrcvtime) &&
+           (u32)(now - icsk->icsk_ack.lrcvtime) < icsk->icsk_ack.ato)
+               inet_csk_inc_pingpong_cnt(sk);
+
+       tp->lsndtime = now;
 }
 
 /* Account for an ACK we sent. */
@@ -980,7 +983,6 @@ static void tcp_update_skb_after_send(struct sock *sk, struct sk_buff *skb,
 {
        struct tcp_sock *tp = tcp_sk(sk);
 
-       skb->skb_mstamp_ns = tp->tcp_wstamp_ns;
        if (sk->sk_pacing_status != SK_PACING_NONE) {
                unsigned long rate = sk->sk_pacing_rate;
 
@@ -1028,7 +1030,9 @@ static int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb,
 
        BUG_ON(!skb || !tcp_skb_pcount(skb));
        tp = tcp_sk(sk);
-
+       prior_wstamp = tp->tcp_wstamp_ns;
+       tp->tcp_wstamp_ns = max(tp->tcp_wstamp_ns, tp->tcp_clock_cache);
+       skb->skb_mstamp_ns = tp->tcp_wstamp_ns;
        if (clone_it) {
                TCP_SKB_CB(skb)->tx.in_flight = TCP_SKB_CB(skb)->end_seq
                        - tp->snd_una;
@@ -1045,11 +1049,6 @@ static int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb,
                        return -ENOBUFS;
        }
 
-       prior_wstamp = tp->tcp_wstamp_ns;
-       tp->tcp_wstamp_ns = max(tp->tcp_wstamp_ns, tp->tcp_clock_cache);
-
-       skb->skb_mstamp_ns = tp->tcp_wstamp_ns;
-
        inet = inet_sk(sk);
        tcb = TCP_SKB_CB(skb);
        memset(&opts, 0, sizeof(opts));
@@ -2937,12 +2936,16 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs)
                err = tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC);
        }
 
+       /* To avoid taking spuriously low RTT samples based on a timestamp
+        * for a transmit that never happened, always mark EVER_RETRANS
+        */
+       TCP_SKB_CB(skb)->sacked |= TCPCB_EVER_RETRANS;
+
        if (BPF_SOCK_OPS_TEST_FLAG(tp, BPF_SOCK_OPS_RETRANS_CB_FLAG))
                tcp_call_bpf_3arg(sk, BPF_SOCK_OPS_RETRANS_CB,
                                  TCP_SKB_CB(skb)->seq, segs, err);
 
        if (likely(!err)) {
-               TCP_SKB_CB(skb)->sacked |= TCPCB_EVER_RETRANS;
                trace_tcp_retransmit_skb(sk, skb);
        } else if (err != -EBUSY) {
                NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPRETRANSFAIL, segs);
@@ -2963,13 +2966,12 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs)
 #endif
                TCP_SKB_CB(skb)->sacked |= TCPCB_RETRANS;
                tp->retrans_out += tcp_skb_pcount(skb);
-
-               /* Save stamp of the first retransmit. */
-               if (!tp->retrans_stamp)
-                       tp->retrans_stamp = tcp_skb_timestamp(skb);
-
        }
 
+       /* Save stamp of the first (attempted) retransmit. */
+       if (!tp->retrans_stamp)
+               tp->retrans_stamp = tcp_skb_timestamp(skb);
+
        if (tp->undo_retrans < 0)
                tp->undo_retrans = 0;
        tp->undo_retrans += tcp_skb_pcount(skb);
@@ -3456,6 +3458,7 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn)
                        skb_trim(syn_data, copied);
                        space = copied;
                }
+               skb_zcopy_set(syn_data, fo->uarg, NULL);
        }
        /* No more data pending in inet_wait_for_connect() */
        if (space == fo->size)
@@ -3569,7 +3572,7 @@ void tcp_send_delayed_ack(struct sock *sk)
                const struct tcp_sock *tp = tcp_sk(sk);
                int max_ato = HZ / 2;
 
-               if (icsk->icsk_ack.pingpong ||
+               if (inet_csk_in_pingpong_mode(sk) ||
                    (icsk->icsk_ack.pending & ICSK_ACK_PUSHED))
                        max_ato = TCP_DELACK_MAX;
 
@@ -3750,7 +3753,7 @@ void tcp_send_probe0(struct sock *sk)
        struct inet_connection_sock *icsk = inet_csk(sk);
        struct tcp_sock *tp = tcp_sk(sk);
        struct net *net = sock_net(sk);
-       unsigned long probe_max;
+       unsigned long timeout;
        int err;
 
        err = tcp_write_wakeup(sk, LINUX_MIB_TCPWINPROBE);
@@ -3762,26 +3765,18 @@ void tcp_send_probe0(struct sock *sk)
                return;
        }
 
+       icsk->icsk_probes_out++;
        if (err <= 0) {
                if (icsk->icsk_backoff < net->ipv4.sysctl_tcp_retries2)
                        icsk->icsk_backoff++;
-               icsk->icsk_probes_out++;
-               probe_max = TCP_RTO_MAX;
+               timeout = tcp_probe0_when(sk, TCP_RTO_MAX);
        } else {
                /* If packet was not sent due to local congestion,
-                * do not backoff and do not remember icsk_probes_out.
-                * Let local senders to fight for local resources.
-                *
-                * Use accumulated backoff yet.
+                * Let senders fight for local resources conservatively.
                 */
-               if (!icsk->icsk_probes_out)
-                       icsk->icsk_probes_out = 1;
-               probe_max = TCP_RESOURCE_PROBE_INTERVAL;
-       }
-       tcp_reset_xmit_timer(sk, ICSK_TIME_PROBE0,
-                            tcp_probe0_when(sk, probe_max),
-                            TCP_RTO_MAX,
-                            NULL);
+               timeout = TCP_RESOURCE_PROBE_INTERVAL;
+       }
+       tcp_reset_xmit_timer(sk, ICSK_TIME_PROBE0, timeout, TCP_RTO_MAX, NULL);
 }
 
 int tcp_rtx_synack(const struct sock *sk, struct request_sock *req)