Merge tag 'linux-can-next-for-4.4-20150917' of git://git.kernel.org/pub/scm/linux...
[cascardo/linux.git] / net / ipv4 / tcp_output.c
index b1c218d..d0ad355 100644 (file)
@@ -137,12 +137,12 @@ static __u16 tcp_advertise_mss(struct sock *sk)
 }
 
 /* RFC2861. Reset CWND after idle period longer RTO to "restart window".
- * This is the first part of cwnd validation mechanism. */
-static void tcp_cwnd_restart(struct sock *sk, const struct dst_entry *dst)
+ * This is the first part of cwnd validation mechanism.
+ */
+void tcp_cwnd_restart(struct sock *sk, s32 delta)
 {
        struct tcp_sock *tp = tcp_sk(sk);
-       s32 delta = tcp_time_stamp - tp->lsndtime;
-       u32 restart_cwnd = tcp_init_cwnd(tp, dst);
+       u32 restart_cwnd = tcp_init_cwnd(tp, __sk_dst_get(sk));
        u32 cwnd = tp->snd_cwnd;
 
        tcp_ca_event(sk, CA_EVENT_CWND_RESTART);
@@ -163,20 +163,17 @@ static void tcp_event_data_sent(struct tcp_sock *tp,
 {
        struct inet_connection_sock *icsk = inet_csk(sk);
        const u32 now = tcp_time_stamp;
-       const struct dst_entry *dst = __sk_dst_get(sk);
 
-       if (sysctl_tcp_slow_start_after_idle &&
-           (!tp->packets_out && (s32)(now - tp->lsndtime) > icsk->icsk_rto))
-               tcp_cwnd_restart(sk, __sk_dst_get(sk));
+       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 ((u32)(now - icsk->icsk_ack.lrcvtime) < icsk->icsk_ack.ato &&
-           (!dst || !dst_metric(dst, RTAX_QUICKACK)))
-                       icsk->icsk_ack.pingpong = 1;
+       if ((u32)(now - icsk->icsk_ack.lrcvtime) < icsk->icsk_ack.ato)
+               icsk->icsk_ack.pingpong = 1;
 }
 
 /* Account for an ACK we sent. */
@@ -946,9 +943,6 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
                                                           &md5);
        tcp_header_size = tcp_options_size + sizeof(struct tcphdr);
 
-       if (tcp_packets_in_flight(tp) == 0)
-               tcp_ca_event(sk, CA_EVENT_TX_START);
-
        /* if no packet is in qdisc/device queue, then allow XPS to select
         * another queue. We can be called from tcp_tsq_handler()
         * which holds one reference to sk_wmem_alloc.
@@ -1776,7 +1770,7 @@ static bool tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb,
        if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)
                goto send_now;
 
-       if (!((1 << icsk->icsk_ca_state) & (TCPF_CA_Open | TCPF_CA_CWR)))
+       if (icsk->icsk_ca_state >= TCP_CA_Recovery)
                goto send_now;
 
        /* Avoid bursty behavior by allowing defer
@@ -2151,7 +2145,7 @@ repair:
                tcp_cwnd_validate(sk, is_cwnd_limited);
                return false;
        }
-       return (push_one == 2) || (!tp->packets_out && tcp_send_head(sk));
+       return !tp->packets_out && tcp_send_head(sk);
 }
 
 bool tcp_schedule_loss_probe(struct sock *sk)
@@ -2228,7 +2222,7 @@ static bool skb_still_in_host_queue(const struct sock *sk,
        return false;
 }
 
-/* When probe timeout (PTO) fires, send a new segment if one exists, else
+/* When probe timeout (PTO) fires, try send a new segment if possible, else
  * retransmit the last segment.
  */
 void tcp_send_loss_probe(struct sock *sk)
@@ -2237,11 +2231,19 @@ void tcp_send_loss_probe(struct sock *sk)
        struct sk_buff *skb;
        int pcount;
        int mss = tcp_current_mss(sk);
-       int err = -1;
 
-       if (tcp_send_head(sk)) {
-               err = tcp_write_xmit(sk, mss, TCP_NAGLE_OFF, 2, GFP_ATOMIC);
-               goto rearm_timer;
+       skb = tcp_send_head(sk);
+       if (skb) {
+               if (tcp_snd_wnd_test(tp, skb, mss)) {
+                       pcount = tp->packets_out;
+                       tcp_write_xmit(sk, mss, TCP_NAGLE_OFF, 2, GFP_ATOMIC);
+                       if (tp->packets_out > pcount)
+                               goto probe_sent;
+                       goto rearm_timer;
+               }
+               skb = tcp_write_queue_prev(sk, skb);
+       } else {
+               skb = tcp_write_queue_tail(sk);
        }
 
        /* At most one outstanding TLP retransmission. */
@@ -2249,7 +2251,6 @@ void tcp_send_loss_probe(struct sock *sk)
                goto rearm_timer;
 
        /* Retransmit last segment. */
-       skb = tcp_write_queue_tail(sk);
        if (WARN_ON(!skb))
                goto rearm_timer;
 
@@ -2264,26 +2265,24 @@ void tcp_send_loss_probe(struct sock *sk)
                if (unlikely(tcp_fragment(sk, skb, (pcount - 1) * mss, mss,
                                          GFP_ATOMIC)))
                        goto rearm_timer;
-               skb = tcp_write_queue_tail(sk);
+               skb = tcp_write_queue_next(sk, skb);
        }
 
        if (WARN_ON(!skb || !tcp_skb_pcount(skb)))
                goto rearm_timer;
 
-       err = __tcp_retransmit_skb(sk, skb);
+       if (__tcp_retransmit_skb(sk, skb))
+               goto rearm_timer;
 
        /* Record snd_nxt for loss detection. */
-       if (likely(!err))
-               tp->tlp_high_seq = tp->snd_nxt;
+       tp->tlp_high_seq = tp->snd_nxt;
 
+probe_sent:
+       NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPLOSSPROBES);
+       /* Reset s.t. tcp_rearm_rto will restart timer from now */
+       inet_csk(sk)->icsk_pending = 0;
 rearm_timer:
-       inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
-                                 inet_csk(sk)->icsk_rto,
-                                 TCP_RTO_MAX);
-
-       if (likely(!err))
-               NET_INC_STATS_BH(sock_net(sk),
-                                LINUX_MIB_TCPLOSSPROBES);
+       tcp_rearm_rto(sk);
 }
 
 /* Push out any pending frames which were held back due to
@@ -2988,6 +2987,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
        rcu_read_lock();
        md5 = tcp_rsk(req)->af_specific->req_md5_lookup(sk, req_to_sk(req));
 #endif
+       skb_set_hash(skb, tcp_rsk(req)->txhash, PKT_HASH_TYPE_L4);
        tcp_header_size = tcp_synack_options(sk, req, mss, skb, &opts, md5,
                                             foc) + sizeof(*th);
 
@@ -3506,6 +3506,7 @@ int tcp_rtx_synack(struct sock *sk, struct request_sock *req)
        struct flowi fl;
        int res;
 
+       tcp_rsk(req)->txhash = net_tx_rndhash();
        res = af_ops->send_synack(sk, NULL, &fl, req, 0, NULL);
        if (!res) {
                TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS);