gre: fix netns vs proto registration ordering
[safe/jmp/linux-2.6] / net / ipv4 / tcp_timer.c
index 799ebe0..de7d1bf 100644 (file)
@@ -5,8 +5,6 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp_timer.c,v 1.88 2002/02/01 22:01:04 davem Exp $
- *
  * Authors:    Ross Biro
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *             Mark Evans, <evansmp@uhura.aston.ac.uk>
 #include <linux/module.h>
 #include <net/tcp.h>
 
-int sysctl_tcp_syn_retries = TCP_SYN_RETRIES; 
-int sysctl_tcp_synack_retries = TCP_SYNACK_RETRIES; 
-int sysctl_tcp_keepalive_time = TCP_KEEPALIVE_TIME;
-int sysctl_tcp_keepalive_probes = TCP_KEEPALIVE_PROBES;
-int sysctl_tcp_keepalive_intvl = TCP_KEEPALIVE_INTVL;
-int sysctl_tcp_retries1 = TCP_RETR1;
-int sysctl_tcp_retries2 = TCP_RETR2;
-int sysctl_tcp_orphan_retries;
+int sysctl_tcp_syn_retries __read_mostly = TCP_SYN_RETRIES;
+int sysctl_tcp_synack_retries __read_mostly = TCP_SYNACK_RETRIES;
+int sysctl_tcp_keepalive_time __read_mostly = TCP_KEEPALIVE_TIME;
+int sysctl_tcp_keepalive_probes __read_mostly = TCP_KEEPALIVE_PROBES;
+int sysctl_tcp_keepalive_intvl __read_mostly = TCP_KEEPALIVE_INTVL;
+int sysctl_tcp_retries1 __read_mostly = TCP_RETR1;
+int sysctl_tcp_retries2 __read_mostly = TCP_RETR2;
+int sysctl_tcp_orphan_retries __read_mostly;
 
 static void tcp_write_timer(unsigned long);
 static void tcp_delack_timer(unsigned long);
 static void tcp_keepalive_timer (unsigned long data);
 
-#ifdef TCP_DEBUG
-const char tcp_timer_bug_msg[] = KERN_DEBUG "tcpbug: unknown timer value\n";
-EXPORT_SYMBOL(tcp_timer_bug_msg);
-#endif
-
-/*
- * Using different timers for retransmit, delayed acks and probes
- * We may wish use just one timer maintaining a list of expire jiffies 
- * to optimize.
- */
-
 void tcp_init_xmit_timers(struct sock *sk)
 {
-       struct tcp_sock *tp = tcp_sk(sk);
-
-       init_timer(&tp->retransmit_timer);
-       tp->retransmit_timer.function=&tcp_write_timer;
-       tp->retransmit_timer.data = (unsigned long) sk;
-       tp->pending = 0;
-
-       init_timer(&tp->delack_timer);
-       tp->delack_timer.function=&tcp_delack_timer;
-       tp->delack_timer.data = (unsigned long) sk;
-       tp->ack.pending = 0;
-
-       init_timer(&sk->sk_timer);
-       sk->sk_timer.function   = &tcp_keepalive_timer;
-       sk->sk_timer.data       = (unsigned long)sk;
+       inet_csk_init_xmit_timers(sk, &tcp_write_timer, &tcp_delack_timer,
+                                 &tcp_keepalive_timer);
 }
 
-void tcp_clear_xmit_timers(struct sock *sk)
-{
-       struct tcp_sock *tp = tcp_sk(sk);
-
-       tp->pending = 0;
-       sk_stop_timer(sk, &tp->retransmit_timer);
-
-       tp->ack.pending = 0;
-       tp->ack.blocked = 0;
-       sk_stop_timer(sk, &tp->delack_timer);
-
-       sk_stop_timer(sk, &sk->sk_timer);
-}
+EXPORT_SYMBOL(tcp_init_xmit_timers);
 
 static void tcp_write_err(struct sock *sk)
 {
@@ -86,7 +48,7 @@ static void tcp_write_err(struct sock *sk)
        sk->sk_error_report(sk);
 
        tcp_done(sk);
-       NET_INC_STATS_BH(LINUX_MIB_TCPABORTONTIMEOUT);
+       NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONTIMEOUT);
 }
 
 /* Do not allow orphaned sockets to eat all our resources.
@@ -94,7 +56,7 @@ static void tcp_write_err(struct sock *sk)
  * to prevent DoS attacks. It is called when a retransmission timeout
  * or zero probe timeout occurs on orphaned socket.
  *
- * Criterium is still not confirmed experimentally and may change.
+ * Criteria is still not confirmed experimentally and may change.
  * We kill the socket, if:
  * 1. If number of orphaned sockets exceeds an administratively configured
  *    limit.
@@ -103,9 +65,9 @@ static void tcp_write_err(struct sock *sk)
 static int tcp_out_of_resources(struct sock *sk, int do_reset)
 {
        struct tcp_sock *tp = tcp_sk(sk);
-       int orphans = atomic_read(&tcp_orphan_count);
+       int orphans = percpu_counter_read_positive(&tcp_orphan_count);
 
-       /* If peer does not open window for long time, or did not transmit 
+       /* If peer does not open window for long time, or did not transmit
         * anything for long time, penalize it. */
        if ((s32)(tcp_time_stamp - tp->lsndtime) > 2*TCP_RTO_MAX || !do_reset)
                orphans <<= 1;
@@ -114,9 +76,7 @@ static int tcp_out_of_resources(struct sock *sk, int do_reset)
        if (sk->sk_err_soft)
                orphans <<= 1;
 
-       if (orphans >= sysctl_tcp_max_orphans ||
-           (sk->sk_wmem_queued > SOCK_MIN_SNDBUF &&
-            atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2])) {
+       if (tcp_too_many_orphans(sk, orphans)) {
                if (net_ratelimit())
                        printk(KERN_INFO "Out of socket memory\n");
 
@@ -129,7 +89,7 @@ static int tcp_out_of_resources(struct sock *sk, int do_reset)
                if (do_reset)
                        tcp_send_active_reset(sk, GFP_ATOMIC);
                tcp_done(sk);
-               NET_INC_STATS_BH(LINUX_MIB_TCPABORTONMEMORY);
+               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONMEMORY);
                return 1;
        }
        return 0;
@@ -152,53 +112,88 @@ static int tcp_orphan_retries(struct sock *sk, int alive)
        return retries;
 }
 
+static void tcp_mtu_probing(struct inet_connection_sock *icsk, struct sock *sk)
+{
+       /* Black hole detection */
+       if (sysctl_tcp_mtu_probing) {
+               if (!icsk->icsk_mtup.enabled) {
+                       icsk->icsk_mtup.enabled = 1;
+                       tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
+               } else {
+                       struct tcp_sock *tp = tcp_sk(sk);
+                       int mss;
+
+                       mss = tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_low) >> 1;
+                       mss = min(sysctl_tcp_base_mss, mss);
+                       mss = max(mss, 68 - tp->tcp_header_len);
+                       icsk->icsk_mtup.search_low = tcp_mss_to_mtu(sk, mss);
+                       tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
+               }
+       }
+}
+
+/* This function calculates a "timeout" which is equivalent to the timeout of a
+ * TCP connection after "boundary" unsucessful, exponentially backed-off
+ * retransmissions with an initial RTO of TCP_RTO_MIN.
+ */
+static bool retransmits_timed_out(struct sock *sk,
+                                 unsigned int boundary)
+{
+       unsigned int timeout, linear_backoff_thresh;
+       unsigned int start_ts;
+
+       if (!inet_csk(sk)->icsk_retransmits)
+               return false;
+
+       if (unlikely(!tcp_sk(sk)->retrans_stamp))
+               start_ts = TCP_SKB_CB(tcp_write_queue_head(sk))->when;
+       else
+               start_ts = tcp_sk(sk)->retrans_stamp;
+
+       linear_backoff_thresh = ilog2(TCP_RTO_MAX/TCP_RTO_MIN);
+
+       if (boundary <= linear_backoff_thresh)
+               timeout = ((2 << boundary) - 1) * TCP_RTO_MIN;
+       else
+               timeout = ((2 << linear_backoff_thresh) - 1) * TCP_RTO_MIN +
+                         (boundary - linear_backoff_thresh) * TCP_RTO_MAX;
+
+       return (tcp_time_stamp - start_ts) >= timeout;
+}
+
 /* A write timeout has occurred. Process the after effects. */
 static int tcp_write_timeout(struct sock *sk)
 {
-       struct tcp_sock *tp = tcp_sk(sk);
+       struct inet_connection_sock *icsk = inet_csk(sk);
        int retry_until;
+       bool do_reset;
 
        if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) {
-               if (tp->retransmits)
-                       dst_negative_advice(&sk->sk_dst_cache);
-               retry_until = tp->syn_retries ? : sysctl_tcp_syn_retries;
+               if (icsk->icsk_retransmits)
+                       dst_negative_advice(&sk->sk_dst_cache, sk);
+               retry_until = icsk->icsk_syn_retries ? : sysctl_tcp_syn_retries;
        } else {
-               if (tp->retransmits >= sysctl_tcp_retries1) {
-                       /* NOTE. draft-ietf-tcpimpl-pmtud-01.txt requires pmtu black
-                          hole detection. :-(
-
-                          It is place to make it. It is not made. I do not want
-                          to make it. It is disguisting. It does not work in any
-                          case. Let me to cite the same draft, which requires for
-                          us to implement this:
-
-   "The one security concern raised by this memo is that ICMP black holes
-   are often caused by over-zealous security administrators who block
-   all ICMP messages.  It is vitally important that those who design and
-   deploy security systems understand the impact of strict filtering on
-   upper-layer protocols.  The safest web site in the world is worthless
-   if most TCP implementations cannot transfer data from it.  It would
-   be far nicer to have all of the black holes fixed rather than fixing
-   all of the TCP implementations."
-
-                           Golden words :-).
-                  */
-
-                       dst_negative_advice(&sk->sk_dst_cache);
+               if (retransmits_timed_out(sk, sysctl_tcp_retries1)) {
+                       /* Black hole detection */
+                       tcp_mtu_probing(icsk, sk);
+
+                       dst_negative_advice(&sk->sk_dst_cache, sk);
                }
 
                retry_until = sysctl_tcp_retries2;
                if (sock_flag(sk, SOCK_DEAD)) {
-                       int alive = (tp->rto < TCP_RTO_MAX);
+                       const int alive = (icsk->icsk_rto < TCP_RTO_MAX);
+
                        retry_until = tcp_orphan_retries(sk, alive);
+                       do_reset = alive ||
+                                  !retransmits_timed_out(sk, retry_until);
 
-                       if (tcp_out_of_resources(sk, alive || tp->retransmits < retry_until))
+                       if (tcp_out_of_resources(sk, do_reset))
                                return 1;
                }
        }
 
-       if (tp->retransmits >= retry_until) {
+       if (retransmits_timed_out(sk, retry_until)) {
                /* Has it gone just too far? */
                tcp_write_err(sk);
                return 1;
@@ -208,60 +203,60 @@ static int tcp_write_timeout(struct sock *sk)
 
 static void tcp_delack_timer(unsigned long data)
 {
-       struct sock *sk = (struct sock*)data;
+       struct sock *sk = (struct sock *)data;
        struct tcp_sock *tp = tcp_sk(sk);
+       struct inet_connection_sock *icsk = inet_csk(sk);
 
        bh_lock_sock(sk);
        if (sock_owned_by_user(sk)) {
                /* Try again later. */
-               tp->ack.blocked = 1;
-               NET_INC_STATS_BH(LINUX_MIB_DELAYEDACKLOCKED);
-               sk_reset_timer(sk, &tp->delack_timer, jiffies + TCP_DELACK_MIN);
+               icsk->icsk_ack.blocked = 1;
+               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_DELAYEDACKLOCKED);
+               sk_reset_timer(sk, &icsk->icsk_delack_timer, jiffies + TCP_DELACK_MIN);
                goto out_unlock;
        }
 
-       sk_stream_mem_reclaim(sk);
+       sk_mem_reclaim_partial(sk);
 
-       if (sk->sk_state == TCP_CLOSE || !(tp->ack.pending & TCP_ACK_TIMER))
+       if (sk->sk_state == TCP_CLOSE || !(icsk->icsk_ack.pending & ICSK_ACK_TIMER))
                goto out;
 
-       if (time_after(tp->ack.timeout, jiffies)) {
-               sk_reset_timer(sk, &tp->delack_timer, tp->ack.timeout);
+       if (time_after(icsk->icsk_ack.timeout, jiffies)) {
+               sk_reset_timer(sk, &icsk->icsk_delack_timer, icsk->icsk_ack.timeout);
                goto out;
        }
-       tp->ack.pending &= ~TCP_ACK_TIMER;
+       icsk->icsk_ack.pending &= ~ICSK_ACK_TIMER;
 
-       if (skb_queue_len(&tp->ucopy.prequeue)) {
+       if (!skb_queue_empty(&tp->ucopy.prequeue)) {
                struct sk_buff *skb;
 
-               NET_ADD_STATS_BH(LINUX_MIB_TCPSCHEDULERFAILED, 
-                                skb_queue_len(&tp->ucopy.prequeue));
+               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSCHEDULERFAILED);
 
                while ((skb = __skb_dequeue(&tp->ucopy.prequeue)) != NULL)
-                       sk->sk_backlog_rcv(sk, skb);
+                       sk_backlog_rcv(sk, skb);
 
                tp->ucopy.memory = 0;
        }
 
-       if (tcp_ack_scheduled(tp)) {
-               if (!tp->ack.pingpong) {
+       if (inet_csk_ack_scheduled(sk)) {
+               if (!icsk->icsk_ack.pingpong) {
                        /* Delayed ACK missed: inflate ATO. */
-                       tp->ack.ato = min(tp->ack.ato << 1, tp->rto);
+                       icsk->icsk_ack.ato = min(icsk->icsk_ack.ato << 1, icsk->icsk_rto);
                } else {
                        /* Delayed ACK missed: leave pingpong mode and
                         * deflate ATO.
                         */
-                       tp->ack.pingpong = 0;
-                       tp->ack.ato = TCP_ATO_MIN;
+                       icsk->icsk_ack.pingpong = 0;
+                       icsk->icsk_ack.ato      = TCP_ATO_MIN;
                }
                tcp_send_ack(sk);
-               NET_INC_STATS_BH(LINUX_MIB_DELAYEDACKS);
+               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_DELAYEDACKS);
        }
        TCP_CHECK_TIMER(sk);
 
 out:
        if (tcp_memory_pressure)
-               sk_stream_mem_reclaim(sk);
+               sk_mem_reclaim(sk);
 out_unlock:
        bh_unlock_sock(sk);
        sock_put(sk);
@@ -269,11 +264,12 @@ out_unlock:
 
 static void tcp_probe_timer(struct sock *sk)
 {
+       struct inet_connection_sock *icsk = inet_csk(sk);
        struct tcp_sock *tp = tcp_sk(sk);
        int max_probes;
 
-       if (tp->packets_out || !sk->sk_send_head) {
-               tp->probes_out = 0;
+       if (tp->packets_out || !tcp_send_head(sk)) {
+               icsk->icsk_probes_out = 0;
                return;
        }
 
@@ -284,7 +280,7 @@ static void tcp_probe_timer(struct sock *sk)
         * FIXME: We ought not to do it, Solaris 2.5 actually has fixing
         * this behaviour in Solaris down as a bug fix. [AC]
         *
-        * Let me to explain. probes_out is zeroed by incoming ACKs
+        * Let me to explain. icsk_probes_out is zeroed by incoming ACKs
         * even if they advertise zero window. Hence, connection is killed only
         * if we received no ACKs for normal connection timeout. It is not killed
         * only because window stays zero for some time, window may be zero
@@ -295,15 +291,15 @@ static void tcp_probe_timer(struct sock *sk)
        max_probes = sysctl_tcp_retries2;
 
        if (sock_flag(sk, SOCK_DEAD)) {
-               int alive = ((tp->rto<<tp->backoff) < TCP_RTO_MAX);
+               const int alive = ((icsk->icsk_rto << icsk->icsk_backoff) < TCP_RTO_MAX);
+
                max_probes = tcp_orphan_retries(sk, alive);
 
-               if (tcp_out_of_resources(sk, alive || tp->probes_out <= max_probes))
+               if (tcp_out_of_resources(sk, alive || icsk->icsk_probes_out <= max_probes))
                        return;
        }
 
-       if (tp->probes_out > max_probes) {
+       if (icsk->icsk_probes_out > max_probes) {
                tcp_write_err(sk);
        } else {
                /* Only send another probe if we didn't close things up. */
@@ -315,14 +311,15 @@ static void tcp_probe_timer(struct sock *sk)
  *     The TCP retransmit timer.
  */
 
-static void tcp_retransmit_timer(struct sock *sk)
+void tcp_retransmit_timer(struct sock *sk)
 {
        struct tcp_sock *tp = tcp_sk(sk);
+       struct inet_connection_sock *icsk = inet_csk(sk);
 
        if (!tp->packets_out)
                goto out;
 
-       BUG_TRAP(!skb_queue_empty(&sk->sk_write_queue));
+       WARN_ON(tcp_write_queue_empty(sk));
 
        if (!tp->snd_wnd && !sock_flag(sk, SOCK_DEAD) &&
            !((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV))) {
@@ -332,19 +329,27 @@ static void tcp_retransmit_timer(struct sock *sk)
                 * we cannot allow such beasts to hang infinitely.
                 */
 #ifdef TCP_DEBUG
-               if (net_ratelimit()) {
-                       struct inet_sock *inet = inet_sk(sk);
-                       printk(KERN_DEBUG "TCP: Treason uncloaked! Peer %u.%u.%u.%u:%u/%u shrinks window %u:%u. Repaired.\n",
-                              NIPQUAD(inet->daddr), htons(inet->dport),
-                              inet->num, tp->snd_una, tp->snd_nxt);
+               struct inet_sock *inet = inet_sk(sk);
+               if (sk->sk_family == AF_INET) {
+                       LIMIT_NETDEBUG(KERN_DEBUG "TCP: Peer %pI4:%u/%u unexpectedly shrunk window %u:%u (repaired)\n",
+                              &inet->inet_daddr, ntohs(inet->inet_dport),
+                              inet->inet_num, tp->snd_una, tp->snd_nxt);
                }
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+               else if (sk->sk_family == AF_INET6) {
+                       struct ipv6_pinfo *np = inet6_sk(sk);
+                       LIMIT_NETDEBUG(KERN_DEBUG "TCP: Peer %pI6:%u/%u unexpectedly shrunk window %u:%u (repaired)\n",
+                              &np->daddr, ntohs(inet->inet_dport),
+                              inet->inet_num, tp->snd_una, tp->snd_nxt);
+               }
+#endif
 #endif
                if (tcp_time_stamp - tp->rcv_tstamp > TCP_RTO_MAX) {
                        tcp_write_err(sk);
                        goto out;
                }
                tcp_enter_loss(sk, 0);
-               tcp_retransmit_skb(sk, skb_peek(&sk->sk_write_queue));
+               tcp_retransmit_skb(sk, tcp_write_queue_head(sk));
                __sk_dst_reset(sk);
                goto out_reset_timer;
        }
@@ -352,24 +357,25 @@ static void tcp_retransmit_timer(struct sock *sk)
        if (tcp_write_timeout(sk))
                goto out;
 
-       if (tp->retransmits == 0) {
-               if (tp->ca_state == TCP_CA_Disorder || tp->ca_state == TCP_CA_Recovery) {
-                       if (tp->rx_opt.sack_ok) {
-                               if (tp->ca_state == TCP_CA_Recovery)
-                                       NET_INC_STATS_BH(LINUX_MIB_TCPSACKRECOVERYFAIL);
-                               else
-                                       NET_INC_STATS_BH(LINUX_MIB_TCPSACKFAILURES);
-                       } else {
-                               if (tp->ca_state == TCP_CA_Recovery)
-                                       NET_INC_STATS_BH(LINUX_MIB_TCPRENORECOVERYFAIL);
-                               else
-                                       NET_INC_STATS_BH(LINUX_MIB_TCPRENOFAILURES);
-                       }
-               } else if (tp->ca_state == TCP_CA_Loss) {
-                       NET_INC_STATS_BH(LINUX_MIB_TCPLOSSFAILURES);
+       if (icsk->icsk_retransmits == 0) {
+               int mib_idx;
+
+               if (icsk->icsk_ca_state == TCP_CA_Disorder) {
+                       if (tcp_is_sack(tp))
+                               mib_idx = LINUX_MIB_TCPSACKFAILURES;
+                       else
+                               mib_idx = LINUX_MIB_TCPRENOFAILURES;
+               } else if (icsk->icsk_ca_state == TCP_CA_Recovery) {
+                       if (tcp_is_sack(tp))
+                               mib_idx = LINUX_MIB_TCPSACKRECOVERYFAIL;
+                       else
+                               mib_idx = LINUX_MIB_TCPRENORECOVERYFAIL;
+               } else if (icsk->icsk_ca_state == TCP_CA_Loss) {
+                       mib_idx = LINUX_MIB_TCPLOSSFAILURES;
                } else {
-                       NET_INC_STATS_BH(LINUX_MIB_TCPTIMEOUTS);
+                       mib_idx = LINUX_MIB_TCPTIMEOUTS;
                }
+               NET_INC_STATS_BH(sock_net(sk), mib_idx);
        }
 
        if (tcp_use_frto(sk)) {
@@ -378,14 +384,15 @@ static void tcp_retransmit_timer(struct sock *sk)
                tcp_enter_loss(sk, 0);
        }
 
-       if (tcp_retransmit_skb(sk, skb_peek(&sk->sk_write_queue)) > 0) {
+       if (tcp_retransmit_skb(sk, tcp_write_queue_head(sk)) > 0) {
                /* Retransmission failed because of local congestion,
                 * do not backoff.
                 */
-               if (!tp->retransmits)
-                       tp->retransmits=1;
-               tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS,
-                                    min(tp->rto, TCP_RESOURCE_PROBE_INTERVAL));
+               if (!icsk->icsk_retransmits)
+                       icsk->icsk_retransmits = 1;
+               inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
+                                         min(icsk->icsk_rto, TCP_RESOURCE_PROBE_INTERVAL),
+                                         TCP_RTO_MAX);
                goto out;
        }
 
@@ -404,13 +411,13 @@ static void tcp_retransmit_timer(struct sock *sk)
         * implemented ftp to mars will work nicely. We will have to fix
         * the 120 second clamps though!
         */
-       tp->backoff++;
-       tp->retransmits++;
+       icsk->icsk_backoff++;
+       icsk->icsk_retransmits++;
 
 out_reset_timer:
-       tp->rto = min(tp->rto << 1, TCP_RTO_MAX);
-       tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
-       if (tp->retransmits > sysctl_tcp_retries1)
+       icsk->icsk_rto = min(icsk->icsk_rto << 1, TCP_RTO_MAX);
+       inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto, TCP_RTO_MAX);
+       if (retransmits_timed_out(sk, sysctl_tcp_retries1 + 1))
                __sk_dst_reset(sk);
 
 out:;
@@ -418,40 +425,40 @@ out:;
 
 static void tcp_write_timer(unsigned long data)
 {
-       struct sock *sk = (struct sock*)data;
-       struct tcp_sock *tp = tcp_sk(sk);
+       struct sock *sk = (struct sock *)data;
+       struct inet_connection_sock *icsk = inet_csk(sk);
        int event;
 
        bh_lock_sock(sk);
        if (sock_owned_by_user(sk)) {
                /* Try again later */
-               sk_reset_timer(sk, &tp->retransmit_timer, jiffies + (HZ / 20));
+               sk_reset_timer(sk, &icsk->icsk_retransmit_timer, jiffies + (HZ / 20));
                goto out_unlock;
        }
 
-       if (sk->sk_state == TCP_CLOSE || !tp->pending)
+       if (sk->sk_state == TCP_CLOSE || !icsk->icsk_pending)
                goto out;
 
-       if (time_after(tp->timeout, jiffies)) {
-               sk_reset_timer(sk, &tp->retransmit_timer, tp->timeout);
+       if (time_after(icsk->icsk_timeout, jiffies)) {
+               sk_reset_timer(sk, &icsk->icsk_retransmit_timer, icsk->icsk_timeout);
                goto out;
        }
 
-       event = tp->pending;
-       tp->pending = 0;
+       event = icsk->icsk_pending;
+       icsk->icsk_pending = 0;
 
        switch (event) {
-       case TCP_TIME_RETRANS:
+       case ICSK_TIME_RETRANS:
                tcp_retransmit_timer(sk);
                break;
-       case TCP_TIME_PROBE0:
+       case ICSK_TIME_PROBE0:
                tcp_probe_timer(sk);
                break;
        }
        TCP_CHECK_TIMER(sk);
 
 out:
-       sk_stream_mem_reclaim(sk);
+       sk_mem_reclaim(sk);
 out_unlock:
        bh_unlock_sock(sk);
        sock_put(sk);
@@ -463,101 +470,15 @@ out_unlock:
 
 static void tcp_synack_timer(struct sock *sk)
 {
-       struct tcp_sock *tp = tcp_sk(sk);
-       struct tcp_listen_opt *lopt = tp->listen_opt;
-       int max_retries = tp->syn_retries ? : sysctl_tcp_synack_retries;
-       int thresh = max_retries;
-       unsigned long now = jiffies;
-       struct open_request **reqp, *req;
-       int i, budget;
-
-       if (lopt == NULL || lopt->qlen == 0)
-               return;
-
-       /* Normally all the openreqs are young and become mature
-        * (i.e. converted to established socket) for first timeout.
-        * If synack was not acknowledged for 3 seconds, it means
-        * one of the following things: synack was lost, ack was lost,
-        * rtt is high or nobody planned to ack (i.e. synflood).
-        * When server is a bit loaded, queue is populated with old
-        * open requests, reducing effective size of queue.
-        * When server is well loaded, queue size reduces to zero
-        * after several minutes of work. It is not synflood,
-        * it is normal operation. The solution is pruning
-        * too old entries overriding normal timeout, when
-        * situation becomes dangerous.
-        *
-        * Essentially, we reserve half of room for young
-        * embrions; and abort old ones without pity, if old
-        * ones are about to clog our table.
-        */
-       if (lopt->qlen>>(lopt->max_qlen_log-1)) {
-               int young = (lopt->qlen_young<<1);
-
-               while (thresh > 2) {
-                       if (lopt->qlen < young)
-                               break;
-                       thresh--;
-                       young <<= 1;
-               }
-       }
-
-       if (tp->defer_accept)
-               max_retries = tp->defer_accept;
-
-       budget = 2*(TCP_SYNQ_HSIZE/(TCP_TIMEOUT_INIT/TCP_SYNQ_INTERVAL));
-       i = lopt->clock_hand;
-
-       do {
-               reqp=&lopt->syn_table[i];
-               while ((req = *reqp) != NULL) {
-                       if (time_after_eq(now, req->expires)) {
-                               if ((req->retrans < thresh ||
-                                    (req->acked && req->retrans < max_retries))
-                                   && !req->class->rtx_syn_ack(sk, req, NULL)) {
-                                       unsigned long timeo;
-
-                                       if (req->retrans++ == 0)
-                                               lopt->qlen_young--;
-                                       timeo = min((TCP_TIMEOUT_INIT << req->retrans),
-                                                   TCP_RTO_MAX);
-                                       req->expires = now + timeo;
-                                       reqp = &req->dl_next;
-                                       continue;
-                               }
-
-                               /* Drop this request */
-                               write_lock(&tp->syn_wait_lock);
-                               *reqp = req->dl_next;
-                               write_unlock(&tp->syn_wait_lock);
-                               lopt->qlen--;
-                               if (req->retrans == 0)
-                                       lopt->qlen_young--;
-                               tcp_openreq_free(req);
-                               continue;
-                       }
-                       reqp = &req->dl_next;
-               }
-
-               i = (i+1)&(TCP_SYNQ_HSIZE-1);
-
-       } while (--budget > 0);
-
-       lopt->clock_hand = i;
-
-       if (lopt->qlen)
-               tcp_reset_keepalive_timer(sk, TCP_SYNQ_INTERVAL);
-}
-
-void tcp_delete_keepalive_timer (struct sock *sk)
-{
-       sk_stop_timer(sk, &sk->sk_timer);
+       inet_csk_reqsk_queue_prune(sk, TCP_SYNQ_INTERVAL,
+                                  TCP_TIMEOUT_INIT, TCP_RTO_MAX);
 }
 
-void tcp_reset_keepalive_timer (struct sock *sk, unsigned long len)
+void tcp_syn_ack_timeout(struct sock *sk, struct request_sock *req)
 {
-       sk_reset_timer(sk, &sk->sk_timer, jiffies + len);
+       NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPTIMEOUTS);
 }
+EXPORT_SYMBOL(tcp_syn_ack_timeout);
 
 void tcp_set_keepalive(struct sock *sk, int val)
 {
@@ -565,23 +486,24 @@ void tcp_set_keepalive(struct sock *sk, int val)
                return;
 
        if (val && !sock_flag(sk, SOCK_KEEPOPEN))
-               tcp_reset_keepalive_timer(sk, keepalive_time_when(tcp_sk(sk)));
+               inet_csk_reset_keepalive_timer(sk, keepalive_time_when(tcp_sk(sk)));
        else if (!val)
-               tcp_delete_keepalive_timer(sk);
+               inet_csk_delete_keepalive_timer(sk);
 }
 
 
 static void tcp_keepalive_timer (unsigned long data)
 {
        struct sock *sk = (struct sock *) data;
+       struct inet_connection_sock *icsk = inet_csk(sk);
        struct tcp_sock *tp = tcp_sk(sk);
        __u32 elapsed;
 
        /* Only process if socket is not in use. */
        bh_lock_sock(sk);
        if (sock_owned_by_user(sk)) {
-               /* Try again later. */ 
-               tcp_reset_keepalive_timer (sk, HZ/20);
+               /* Try again later. */
+               inet_csk_reset_keepalive_timer (sk, HZ/20);
                goto out;
        }
 
@@ -592,7 +514,7 @@ static void tcp_keepalive_timer (unsigned long data)
 
        if (sk->sk_state == TCP_FIN_WAIT2 && sock_flag(sk, SOCK_DEAD)) {
                if (tp->linger2 >= 0) {
-                       int tmo = tcp_fin_time(tp) - TCP_TIMEWAIT_LEN;
+                       const int tmo = tcp_fin_time(sk) - TCP_TIMEWAIT_LEN;
 
                        if (tmo > 0) {
                                tcp_time_wait(sk, TCP_FIN_WAIT2, tmo);
@@ -609,20 +531,19 @@ static void tcp_keepalive_timer (unsigned long data)
        elapsed = keepalive_time_when(tp);
 
        /* It is alive without keepalive 8) */
-       if (tp->packets_out || sk->sk_send_head)
+       if (tp->packets_out || tcp_send_head(sk))
                goto resched;
 
        elapsed = tcp_time_stamp - tp->rcv_tstamp;
 
        if (elapsed >= keepalive_time_when(tp)) {
-               if ((!tp->keepalive_probes && tp->probes_out >= sysctl_tcp_keepalive_probes) ||
-                    (tp->keepalive_probes && tp->probes_out >= tp->keepalive_probes)) {
+               if (icsk->icsk_probes_out >= keepalive_probes(tp)) {
                        tcp_send_active_reset(sk, GFP_ATOMIC);
                        tcp_write_err(sk);
                        goto out;
                }
                if (tcp_write_wakeup(sk) <= 0) {
-                       tp->probes_out++;
+                       icsk->icsk_probes_out++;
                        elapsed = keepalive_intvl_when(tp);
                } else {
                        /* If keepalive was lost due to local congestion,
@@ -636,21 +557,16 @@ static void tcp_keepalive_timer (unsigned long data)
        }
 
        TCP_CHECK_TIMER(sk);
-       sk_stream_mem_reclaim(sk);
+       sk_mem_reclaim(sk);
 
 resched:
-       tcp_reset_keepalive_timer (sk, elapsed);
+       inet_csk_reset_keepalive_timer (sk, elapsed);
        goto out;
 
-death: 
+death:
        tcp_done(sk);
 
 out:
        bh_unlock_sock(sk);
        sock_put(sk);
 }
-
-EXPORT_SYMBOL(tcp_clear_xmit_timers);
-EXPORT_SYMBOL(tcp_delete_keepalive_timer);
-EXPORT_SYMBOL(tcp_init_xmit_timers);
-EXPORT_SYMBOL(tcp_reset_keepalive_timer);