tcp: when rearming RTO, if RTO time is in past then fire RTO ASAP
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / net / ipv4 / tcp_input.c
index 9c6225780bd5aafdb175a762d45c704e82416582..85dd09be16182ad882b66a71e33541433dd2c2ea 100644 (file)
@@ -68,6 +68,7 @@
 #include <linux/module.h>
 #include <linux/sysctl.h>
 #include <linux/kernel.h>
+#include <linux/reciprocal_div.h>
 #include <net/dst.h>
 #include <net/tcp.h>
 #include <net/inet_common.h>
@@ -87,7 +88,7 @@ int sysctl_tcp_adv_win_scale __read_mostly = 1;
 EXPORT_SYMBOL(sysctl_tcp_adv_win_scale);
 
 /* rfc5961 challenge ack rate limiting */
-int sysctl_tcp_challenge_ack_limit = 100;
+int sysctl_tcp_challenge_ack_limit = 1000;
 
 int sysctl_tcp_stdurg __read_mostly;
 int sysctl_tcp_rfc1337 __read_mostly;
@@ -110,6 +111,7 @@ int sysctl_tcp_early_retrans __read_mostly = 3;
 #define FLAG_ORIG_SACK_ACKED   0x200 /* Never retransmitted data are (s)acked  */
 #define FLAG_SND_UNA_ADVANCED  0x400 /* Snd_una was changed (!= FLAG_DATA_ACKED) */
 #define FLAG_DSACKING_ACK      0x800 /* SACK blocks contained D-SACK info */
+#define FLAG_SET_XMIT_TIMER    0x1000 /* Set TLP or RTO timer */
 #define FLAG_SACK_RENEGING     0x2000 /* snd_una advanced to a sacked seq */
 #define FLAG_UPDATE_TS_RECENT  0x4000 /* tcp_replace_ts_recent() */
 
@@ -699,6 +701,34 @@ static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt)
        }
 }
 
+/* Set the sk_pacing_rate to allow proper sizing of TSO packets.
+ * Note: TCP stack does not yet implement pacing.
+ * FQ packet scheduler can be used to implement cheap but effective
+ * TCP pacing, to smooth the burst on large writes when packets
+ * in flight is significantly lower than cwnd (or rwin)
+ */
+static void tcp_update_pacing_rate(struct sock *sk)
+{
+       const struct tcp_sock *tp = tcp_sk(sk);
+       u64 rate;
+
+       /* set sk_pacing_rate to 200 % of current rate (mss * cwnd / srtt) */
+       rate = (u64)tp->mss_cache * 2 * (HZ << 3);
+
+       rate *= max(tp->snd_cwnd, tp->packets_out);
+
+       /* Correction for small srtt : minimum srtt being 8 (1 jiffy << 3),
+        * be conservative and assume srtt = 1 (125 us instead of 1.25 ms)
+        * We probably need usec resolution in the future.
+        * Note: This also takes care of possible srtt=0 case,
+        * when tcp_rtt_estimator() was not yet called.
+        */
+       if (tp->srtt > 8 + 2)
+               do_div(rate, tp->srtt);
+
+       sk->sk_pacing_rate = min_t(u64, rate, ~0U);
+}
+
 /* Calculate rto without backoff.  This is the second half of Van Jacobson's
  * routine referred to above.
  */
@@ -1047,7 +1077,7 @@ static bool tcp_check_dsack(struct sock *sk, const struct sk_buff *ack_skb,
        }
 
        /* D-SACK for already forgotten data... Do dumb counting. */
-       if (dup_sack && tp->undo_marker && tp->undo_retrans &&
+       if (dup_sack && tp->undo_marker && tp->undo_retrans > 0 &&
            !after(end_seq_0, prior_snd_una) &&
            after(end_seq_0, tp->undo_marker))
                tp->undo_retrans--;
@@ -1102,7 +1132,7 @@ static int tcp_match_skb_to_sack(struct sock *sk, struct sk_buff *skb,
                        unsigned int new_len = (pkt_len / mss) * mss;
                        if (!in_sack && new_len < pkt_len) {
                                new_len += mss;
-                               if (new_len > skb->len)
+                               if (new_len >= skb->len)
                                        return 0;
                        }
                        pkt_len = new_len;
@@ -1126,7 +1156,7 @@ static u8 tcp_sacktag_one(struct sock *sk,
 
        /* Account D-SACK for retransmitted packet. */
        if (dup_sack && (sacked & TCPCB_RETRANS)) {
-               if (tp->undo_marker && tp->undo_retrans &&
+               if (tp->undo_marker && tp->undo_retrans > 0 &&
                    after(end_seq, tp->undo_marker))
                        tp->undo_retrans--;
                if (sacked & TCPCB_SACKED_ACKED)
@@ -1264,7 +1294,10 @@ static bool tcp_shifted_skb(struct sock *sk, struct sk_buff *skb,
                tp->lost_cnt_hint -= tcp_skb_pcount(prev);
        }
 
-       TCP_SKB_CB(skb)->tcp_flags |= TCP_SKB_CB(prev)->tcp_flags;
+       TCP_SKB_CB(prev)->tcp_flags |= TCP_SKB_CB(skb)->tcp_flags;
+       if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)
+               TCP_SKB_CB(prev)->end_seq++;
+
        if (skb == tcp_highest_sack(sk))
                tcp_advance_highest_sack(sk, skb);
 
@@ -1819,7 +1852,7 @@ static void tcp_clear_retrans_partial(struct tcp_sock *tp)
        tp->lost_out = 0;
 
        tp->undo_marker = 0;
-       tp->undo_retrans = 0;
+       tp->undo_retrans = -1;
 }
 
 void tcp_clear_retrans(struct tcp_sock *tp)
@@ -2521,8 +2554,8 @@ static inline void tcp_end_cwnd_reduction(struct sock *sk)
        struct tcp_sock *tp = tcp_sk(sk);
 
        /* Reset cwnd to ssthresh in CWR or Recovery (unless it's undone) */
-       if (inet_csk(sk)->icsk_ca_state == TCP_CA_CWR ||
-           (tp->undo_marker && tp->snd_ssthresh < TCP_INFINITE_SSTHRESH)) {
+       if (tp->snd_ssthresh < TCP_INFINITE_SSTHRESH &&
+           (inet_csk(sk)->icsk_ca_state == TCP_CA_CWR || tp->undo_marker)) {
                tp->snd_cwnd = tp->snd_ssthresh;
                tp->snd_cwnd_stamp = tcp_time_stamp;
        }
@@ -2669,7 +2702,7 @@ static void tcp_enter_recovery(struct sock *sk, bool ece_ack)
 
        tp->prior_ssthresh = 0;
        tp->undo_marker = tp->snd_una;
-       tp->undo_retrans = tp->retrans_out;
+       tp->undo_retrans = tp->retrans_out ? : -1;
 
        if (inet_csk(sk)->icsk_ca_state < TCP_CA_CWR) {
                if (!ece_ack)
@@ -2689,13 +2722,12 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack)
        bool recovered = !before(tp->snd_una, tp->high_seq);
 
        if (tp->frto) { /* F-RTO RFC5682 sec 3.1 (sack enhanced version). */
-               if (flag & FLAG_ORIG_SACK_ACKED) {
-                       /* Step 3.b. A timeout is spurious if not all data are
-                        * lost, i.e., never-retransmitted data are (s)acked.
-                        */
-                       tcp_try_undo_loss(sk, true);
+               /* Step 3.b. A timeout is spurious if not all data are
+                * lost, i.e., never-retransmitted data are (s)acked.
+                */
+               if (tcp_try_undo_loss(sk, flag & FLAG_ORIG_SACK_ACKED))
                        return;
-               }
+
                if (after(tp->snd_nxt, tp->high_seq) &&
                    (flag & FLAG_DATA_SACKED || is_dupack)) {
                        tp->frto = 0; /* Loss was real: 2nd part of step 3.a */
@@ -2941,14 +2973,11 @@ void tcp_rearm_rto(struct sock *sk)
                /* Offset the time elapsed after installing regular RTO */
                if (icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS ||
                    icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) {
-                       struct sk_buff *skb = tcp_write_queue_head(sk);
-                       const u32 rto_time_stamp = TCP_SKB_CB(skb)->when + rto;
-                       s32 delta = (s32)(rto_time_stamp - tcp_time_stamp);
+                       s32 delta = tcp_rto_delta(sk);
                        /* delta may not be positive if the socket is locked
                         * when the retrans timer fires and is rescheduled.
                         */
-                       if (delta > 0)
-                               rto = delta;
+                       rto = max_t(int, delta, 1);
                }
                inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, rto,
                                          TCP_RTO_MAX);
@@ -2973,6 +3002,13 @@ void tcp_resume_early_retransmit(struct sock *sk)
        tcp_xmit_retransmit_queue(sk);
 }
 
+/* Try to schedule a loss probe; if that doesn't work, then schedule an RTO. */
+static void tcp_set_xmit_timer(struct sock *sk)
+{
+       if (!tcp_schedule_loss_probe(sk))
+               tcp_rearm_rto(sk);
+}
+
 /* If we get here, the whole TSO packet has not been acked. */
 static u32 tcp_tso_acked(struct sock *sk, struct sk_buff *skb)
 {
@@ -3046,10 +3082,11 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
                        if (seq_rtt < 0) {
                                seq_rtt = ca_seq_rtt;
                        }
-                       if (!(sacked & TCPCB_SACKED_ACKED))
+                       if (!(sacked & TCPCB_SACKED_ACKED)) {
                                reord = min(pkts_acked, reord);
-                       if (!after(scb->end_seq, tp->high_seq))
-                               flag |= FLAG_ORIG_SACK_ACKED;
+                               if (!after(scb->end_seq, tp->high_seq))
+                                       flag |= FLAG_ORIG_SACK_ACKED;
+                       }
                }
 
                if (sacked & TCPCB_SACKED_ACKED)
@@ -3102,7 +3139,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
                }
 
                tcp_ack_update_rtt(sk, flag, seq_rtt);
-               tcp_rearm_rto(sk);
+               flag |= FLAG_SET_XMIT_TIMER;  /* set TLP or RTO timer */
 
                if (tcp_is_reno(tp)) {
                        tcp_remove_reno_sacks(sk, pkts_acked);
@@ -3257,12 +3294,19 @@ static void tcp_send_challenge_ack(struct sock *sk)
        static u32 challenge_timestamp;
        static unsigned int challenge_count;
        u32 now = jiffies / HZ;
+       u32 count;
 
        if (now != challenge_timestamp) {
+               u32 half = (sysctl_tcp_challenge_ack_limit + 1) >> 1;
+
                challenge_timestamp = now;
-               challenge_count = 0;
+               ACCESS_ONCE(challenge_count) = half +
+                                 reciprocal_divide(prandom_u32(),
+                                       sysctl_tcp_challenge_ack_limit);
        }
-       if (++challenge_count <= sysctl_tcp_challenge_ack_limit) {
+       count = ACCESS_ONCE(challenge_count);
+       if (count > 0) {
+               ACCESS_ONCE(challenge_count) = count - 1;
                NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK);
                tcp_send_ack(sk);
        }
@@ -3314,7 +3358,7 @@ static void tcp_process_tlp_ack(struct sock *sk, u32 ack, int flag)
                        tcp_init_cwnd_reduction(sk, true);
                        tcp_set_ca_state(sk, TCP_CA_CWR);
                        tcp_end_cwnd_reduction(sk);
-                       tcp_set_ca_state(sk, TCP_CA_Open);
+                       tcp_try_keep_open(sk);
                        NET_INC_STATS_BH(sock_net(sk),
                                         LINUX_MIB_TCPLOSSPROBERECOVERY);
                }
@@ -3330,7 +3374,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
        u32 ack_seq = TCP_SKB_CB(skb)->seq;
        u32 ack = TCP_SKB_CB(skb)->ack_seq;
        bool is_dupack = false;
-       u32 prior_in_flight;
+       u32 prior_in_flight, prior_cwnd = tp->snd_cwnd, prior_rtt = tp->srtt;
        u32 prior_fackets;
        int prior_packets = tp->packets_out;
        int prior_sacked = tp->sacked_out;
@@ -3355,10 +3399,6 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
        if (after(ack, tp->snd_nxt))
                goto invalid_ack;
 
-       if (icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS ||
-           icsk->icsk_pending == ICSK_TIME_LOSS_PROBE)
-               tcp_rearm_rto(sk);
-
        if (after(ack, prior_snd_una))
                flag |= FLAG_SND_UNA_ADVANCED;
 
@@ -3415,6 +3455,12 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
 
        pkts_acked = previous_packets_out - tp->packets_out;
 
+       if (tp->tlp_high_seq)
+               tcp_process_tlp_ack(sk, ack, flag);
+       /* If needed, reset TLP/RTO timer; RACK may later override this. */
+       if (flag & FLAG_SET_XMIT_TIMER)
+               tcp_set_xmit_timer(sk);
+
        if (tcp_ack_is_dubious(sk, flag)) {
                /* Advance CWND, if state allows this. */
                if ((flag & FLAG_DATA_ACKED) && tcp_may_raise_cwnd(sk, flag))
@@ -3427,17 +3473,14 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
                        tcp_cong_avoid(sk, ack, prior_in_flight);
        }
 
-       if (tp->tlp_high_seq)
-               tcp_process_tlp_ack(sk, ack, flag);
-
        if ((flag & FLAG_FORWARD_PROGRESS) || !(flag & FLAG_NOT_DUP)) {
                struct dst_entry *dst = __sk_dst_get(sk);
                if (dst)
                        dst_confirm(dst);
        }
 
-       if (icsk->icsk_pending == ICSK_TIME_RETRANS)
-               tcp_schedule_loss_probe(sk);
+       if (tp->srtt != prior_rtt || tp->snd_cwnd != prior_cwnd)
+               tcp_update_pacing_rate(sk);
        return 1;
 
 no_queue:
@@ -3598,7 +3641,10 @@ static bool tcp_parse_aligned_timestamp(struct tcp_sock *tp, const struct tcphdr
                ++ptr;
                tp->rx_opt.rcv_tsval = ntohl(*ptr);
                ++ptr;
-               tp->rx_opt.rcv_tsecr = ntohl(*ptr) - tp->tsoffset;
+               if (*ptr)
+                       tp->rx_opt.rcv_tsecr = ntohl(*ptr) - tp->tsoffset;
+               else
+                       tp->rx_opt.rcv_tsecr = 0;
                return true;
        }
        return false;
@@ -3623,7 +3669,7 @@ static bool tcp_fast_parse_options(const struct sk_buff *skb,
        }
 
        tcp_parse_options(skb, &tp->rx_opt, 1, NULL);
-       if (tp->rx_opt.saw_tstamp)
+       if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr)
                tp->rx_opt.rcv_tsecr -= tp->tsoffset;
 
        return true;
@@ -5291,6 +5337,7 @@ void tcp_finish_connect(struct sock *sk, struct sk_buff *skb)
        struct inet_connection_sock *icsk = inet_csk(sk);
 
        tcp_set_state(sk, TCP_ESTABLISHED);
+       icsk->icsk_ack.lrcvtime = tcp_time_stamp;
 
        if (skb != NULL) {
                icsk->icsk_af_ops->sk_rx_dst_set(sk, skb);
@@ -5376,7 +5423,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
        int saved_clamp = tp->rx_opt.mss_clamp;
 
        tcp_parse_options(skb, &tp->rx_opt, 0, &foc);
-       if (tp->rx_opt.saw_tstamp)
+       if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr)
                tp->rx_opt.rcv_tsecr -= tp->tsoffset;
 
        if (th->ack) {
@@ -5491,7 +5538,6 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
                         * to stand against the temptation 8)     --ANK
                         */
                        inet_csk_schedule_ack(sk);
-                       icsk->icsk_ack.lrcvtime = tcp_time_stamp;
                        tcp_enter_quickack_mode(sk);
                        inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
                                                  TCP_DELACK_MAX, TCP_RTO_MAX);
@@ -5539,6 +5585,7 @@ discard:
                }
 
                tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1;
+               tp->copied_seq = tp->rcv_nxt;
                tp->rcv_wup = TCP_SKB_CB(skb)->seq + 1;
 
                /* RFC1323: The window in SYN & SYN/ACK segments is
@@ -5733,6 +5780,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                                } else
                                        tcp_init_metrics(sk);
 
+                               tcp_update_pacing_rate(sk);
+
                                /* Prevent spurious tcp_cwnd_restart() on
                                 * first data packet.
                                 */