Merge tag 'v3.10.76' into update
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / net / ipv4 / tcp_input.c
index 9c6225780bd5aafdb175a762d45c704e82416582..ab151653c0502a8d20fb071b7028095d88d5717b 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;
@@ -98,6 +99,7 @@ int sysctl_tcp_thin_dupack __read_mostly;
 
 int sysctl_tcp_moderate_rcvbuf __read_mostly = 1;
 int sysctl_tcp_early_retrans __read_mostly = 3;
+int sysctl_tcp_default_init_rwnd __read_mostly = TCP_DEFAULT_INIT_RCVWND;
 
 #define FLAG_DATA              0x01 /* Incoming frame contained data.          */
 #define FLAG_WIN_UPDATE                0x02 /* Incoming ACK was a window update.       */
@@ -351,14 +353,14 @@ static void tcp_grow_window(struct sock *sk, const struct sk_buff *skb)
 static void tcp_fixup_rcvbuf(struct sock *sk)
 {
        u32 mss = tcp_sk(sk)->advmss;
-       u32 icwnd = TCP_DEFAULT_INIT_RCVWND;
+       u32 icwnd = sysctl_tcp_default_init_rwnd;
        int rcvmem;
 
        /* Limit to 10 segments if mss <= 1460,
         * or 14600/mss segments, with a minimum of two segments.
         */
        if (mss > 1460)
-               icwnd = max_t(u32, (1460 * TCP_DEFAULT_INIT_RCVWND) / mss, 2);
+               icwnd = max_t(u32, (1460 * icwnd) / mss, 2);
 
        rcvmem = SKB_TRUESIZE(mss + MAX_TCP_HEADER);
        while (tcp_win_from_space(rcvmem) < mss)
@@ -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)
@@ -1837,6 +1870,7 @@ void tcp_clear_retrans(struct tcp_sock *tp)
 void tcp_enter_loss(struct sock *sk, int how)
 {
        const struct inet_connection_sock *icsk = inet_csk(sk);
+       struct inet_connection_sock *icsk1 = inet_csk(sk);
        struct tcp_sock *tp = tcp_sk(sk);
        struct sk_buff *skb;
        bool new_recovery = false;
@@ -1850,7 +1884,40 @@ void tcp_enter_loss(struct sock *sk, int how)
                tp->snd_ssthresh = icsk->icsk_ca_ops->ssthresh(sk);
                tcp_ca_event(sk, CA_EVENT_LOSS);
        }
+       if (icsk->icsk_MMSRB == 1)
+       {
+               #ifdef CONFIG_MTK_NET_LOGGING 
+           printk("[mtk_net][mmspb] tcp_enter_loss snd_cwnd=%u, snd_cwnd_cnt=%u\n", tp->snd_cwnd, tp->snd_cwnd_cnt);
+        #endif
+            if (tp->mss_cache != 0)
+                tp->snd_cwnd = (tp->rcv_wnd / tp->mss_cache);
+            else
+            {
+                tp->snd_cwnd = (tp->rcv_wnd / tp->advmss);
+            }
+               
+            if (tp->snd_ssthresh > 16)
+            {
+                tp->snd_cwnd = tp->snd_ssthresh / 2;//set snd_cwnd is half of default snd_ssthresh
+            }
+            else
+            {
+                tp->snd_cwnd = tp->snd_ssthresh / 2 + 4;
+            }
+            #ifdef CONFIG_MTK_NET_LOGGING 
+            printk("[mtk_net][mmspb] tcp_enter_loss update snd_cwnd=%u\n", tp->snd_cwnd);
+            #endif
+            icsk1->icsk_MMSRB = 0;
+            #ifdef CONFIG_MTK_NET_LOGGING 
+            printk("[mtk_net][mmspb] tcp_enter_loss set icsk_MMSRB=0\n");
+            #endif
+       }
+        else
+        {
        tp->snd_cwnd       = 1;
+        }      
+  
+       //tp->snd_cwnd     = 1;
        tp->snd_cwnd_cnt   = 0;
        tp->snd_cwnd_stamp = tcp_time_stamp;
 
@@ -1913,7 +1980,7 @@ static bool tcp_check_sack_reneging(struct sock *sk, int flag)
                icsk->icsk_retransmits++;
                tcp_retransmit_skb(sk, tcp_write_queue_head(sk));
                inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
-                                         icsk->icsk_rto, TCP_RTO_MAX);
+                                         icsk->icsk_rto, sysctl_tcp_rto_max);
                return true;
        }
        return false;
@@ -1962,7 +2029,7 @@ static bool tcp_pause_early_retransmit(struct sock *sk, int flag)
                return false;
 
        inet_csk_reset_xmit_timer(sk, ICSK_TIME_EARLY_RETRANS, delay,
-                                 TCP_RTO_MAX);
+                                 sysctl_tcp_rto_max);
        return true;
 }
 
@@ -2669,7 +2736,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 +2756,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 */
@@ -2951,7 +3017,7 @@ void tcp_rearm_rto(struct sock *sk)
                                rto = delta;
                }
                inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, rto,
-                                         TCP_RTO_MAX);
+                                         sysctl_tcp_rto_max);
        }
 }
 
@@ -3046,10 +3112,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)
@@ -3180,8 +3247,8 @@ static void tcp_ack_probe(struct sock *sk)
                 */
        } else {
                inet_csk_reset_xmit_timer(sk, ICSK_TIME_PROBE0,
-                                         min(icsk->icsk_rto << icsk->icsk_backoff, TCP_RTO_MAX),
-                                         TCP_RTO_MAX);
+                                         min_t(unsigned int, icsk->icsk_rto << icsk->icsk_backoff, sysctl_tcp_rto_max),
+                                         sysctl_tcp_rto_max);
        }
 }
 
@@ -3257,12 +3324,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 +3388,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 +3404,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;
@@ -3438,6 +3512,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
 
        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 +3674,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 +3702,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;
@@ -5376,7 +5455,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) {
@@ -5494,7 +5573,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
                        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);
+                                                 TCP_DELACK_MAX, sysctl_tcp_rto_max);
 
 discard:
                        __kfree_skb(skb);
@@ -5733,6 +5812,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.
                                 */