building larger TSO frames.
        Default: 3
 
-tcp_tw_reuse - BOOLEAN
-       Allow to reuse TIME-WAIT sockets for new connections when it is
-       safe from protocol viewpoint. Default value is 0.
+tcp_tw_reuse - INTEGER
+       Enable reuse of TIME-WAIT sockets for new connections when it is
+       safe from protocol viewpoint.
+       0 - disable
+       1 - global enable
+       2 - enable for loopback traffic only
        It should not be changed without advice/request of technical
        experts.
+       Default: 2
 
 tcp_window_scaling - BOOLEAN
        Enable window scaling as defined in RFC1323.
 
 
 static int zero;
 static int one = 1;
+static int two = 2;
 static int four = 4;
 static int thousand = 1000;
 static int gso_max_segs = GSO_MAX_SEGS;
                .data           = &init_net.ipv4.sysctl_tcp_tw_reuse,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &two,
        },
        {
                .procname       = "tcp_max_tw_buckets",
 
 
 int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
 {
+       const struct inet_timewait_sock *tw = inet_twsk(sktw);
        const struct tcp_timewait_sock *tcptw = tcp_twsk(sktw);
        struct tcp_sock *tp = tcp_sk(sk);
+       int reuse = sock_net(sk)->ipv4.sysctl_tcp_tw_reuse;
+
+       if (reuse == 2) {
+               /* Still does not detect *everything* that goes through
+                * lo, since we require a loopback src or dst address
+                * or direct binding to 'lo' interface.
+                */
+               bool loopback = false;
+               if (tw->tw_bound_dev_if == LOOPBACK_IFINDEX)
+                       loopback = true;
+#if IS_ENABLED(CONFIG_IPV6)
+               if (tw->tw_family == AF_INET6) {
+                       if (ipv6_addr_loopback(&tw->tw_v6_daddr) ||
+                           (ipv6_addr_v4mapped(&tw->tw_v6_daddr) &&
+                            (tw->tw_v6_daddr.s6_addr[12] == 127)) ||
+                           ipv6_addr_loopback(&tw->tw_v6_rcv_saddr) ||
+                           (ipv6_addr_v4mapped(&tw->tw_v6_rcv_saddr) &&
+                            (tw->tw_v6_rcv_saddr.s6_addr[12] == 127)))
+                               loopback = true;
+               } else
+#endif
+               {
+                       if (ipv4_is_loopback(tw->tw_daddr) ||
+                           ipv4_is_loopback(tw->tw_rcv_saddr))
+                               loopback = true;
+               }
+               if (!loopback)
+                       reuse = 0;
+       }
 
        /* With PAWS, it is safe from the viewpoint
           of data integrity. Even without PAWS it is safe provided sequence
           and use initial timestamp retrieved from peer table.
         */
        if (tcptw->tw_ts_recent_stamp &&
-           (!twp || (sock_net(sk)->ipv4.sysctl_tcp_tw_reuse &&
-                            get_seconds() - tcptw->tw_ts_recent_stamp > 1))) {
+           (!twp || (reuse && get_seconds() - tcptw->tw_ts_recent_stamp > 1))) {
                tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2;
                if (tp->write_seq == 0)
                        tp->write_seq = 1;
        net->ipv4.sysctl_tcp_orphan_retries = 0;
        net->ipv4.sysctl_tcp_fin_timeout = TCP_FIN_TIMEOUT;
        net->ipv4.sysctl_tcp_notsent_lowat = UINT_MAX;
-       net->ipv4.sysctl_tcp_tw_reuse = 0;
+       net->ipv4.sysctl_tcp_tw_reuse = 2;
 
        cnt = tcp_hashinfo.ehash_mask + 1;
        net->ipv4.tcp_death_row.sysctl_max_tw_buckets = (cnt + 1) / 2;