tcp: account all retransmit failures
[deliverable/linux.git] / net / ipv4 / tcp_output.c
index ec335fabd5cc12daba8addf5de86adc90abbd561..92fde8d1aa821c38b59ba467fe386eb3306c2dfe 100644 (file)
@@ -160,6 +160,7 @@ 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))
@@ -170,8 +171,9 @@ static void tcp_event_data_sent(struct tcp_sock *tp,
        /* 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)
-               icsk->icsk_ack.pingpong = 1;
+       if ((u32)(now - icsk->icsk_ack.lrcvtime) < icsk->icsk_ack.ato &&
+           (!dst || !dst_metric(dst, RTAX_QUICKACK)))
+                       icsk->icsk_ack.pingpong = 1;
 }
 
 /* Account for an ACK we sent. */
@@ -181,6 +183,21 @@ static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts)
        inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);
 }
 
+
+u32 tcp_default_init_rwnd(u32 mss)
+{
+       /* Initial receive window should be twice of TCP_INIT_CWND to
+        * enable proper sending of new unsent data during fast recovery
+        * (RFC 3517, Section 4, NextSeg() rule (2)). Further place a
+        * limit when mss is larger than 1460.
+        */
+       u32 init_rwnd = TCP_INIT_CWND * 2;
+
+       if (mss > 1460)
+               init_rwnd = max((1460 * init_rwnd) / mss, 2U);
+       return init_rwnd;
+}
+
 /* Determine a window scaling and initial window to offer.
  * Based on the assumption that the given amount of space
  * will be offered. Store the results in the tp structure.
@@ -230,22 +247,10 @@ void tcp_select_initial_window(int __space, __u32 mss,
                }
        }
 
-       /* Set initial window to a value enough for senders starting with
-        * initial congestion window of TCP_DEFAULT_INIT_RCVWND. Place
-        * a limit on the initial window when mss is larger than 1460.
-        */
        if (mss > (1 << *rcv_wscale)) {
-               int init_cwnd = TCP_DEFAULT_INIT_RCVWND;
-               if (mss > 1460)
-                       init_cwnd =
-                       max_t(u32, (1460 * TCP_DEFAULT_INIT_RCVWND) / mss, 2);
-               /* when initializing use the value from init_rcv_wnd
-                * rather than the default from above
-                */
-               if (init_rcv_wnd)
-                       *rcv_wnd = min(*rcv_wnd, init_rcv_wnd * mss);
-               else
-                       *rcv_wnd = min(*rcv_wnd, init_cwnd * mss);
+               if (!init_rcv_wnd) /* Use default unless specified otherwise */
+                       init_rcv_wnd = tcp_default_init_rwnd(mss);
+               *rcv_wnd = min(*rcv_wnd, init_rcv_wnd * mss);
        }
 
        /* Set the clamp no higher than max representable value */
@@ -2402,6 +2407,8 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
                 * see tcp_input.c tcp_sacktag_write_queue().
                 */
                TCP_SKB_CB(skb)->ack_seq = tp->snd_nxt;
+       } else {
+               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPRETRANSFAIL);
        }
        return err;
 }
@@ -2523,10 +2530,9 @@ begin_fwd:
                if (sacked & (TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS))
                        continue;
 
-               if (tcp_retransmit_skb(sk, skb)) {
-                       NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPRETRANSFAIL);
+               if (tcp_retransmit_skb(sk, skb))
                        return;
-               }
+
                NET_INC_STATS_BH(sock_net(sk), mib_idx);
 
                if (tcp_in_cwnd_reduction(sk))
This page took 0.026303 seconds and 5 git commands to generate.