Merge branch 'upstream-fixes' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
[pandora-kernel.git] / net / ipv4 / tcp_timer.c
index 0b71380..e188095 100644 (file)
@@ -36,55 +36,14 @@ static void tcp_write_timer(unsigned long);
 static void tcp_delack_timer(unsigned long);
 static void tcp_keepalive_timer (unsigned long data);
 
-#ifdef INET_CSK_DEBUG
-const char inet_csk_timer_bug_msg[] = "inet_csk BUG: unknown timer value\n";
-EXPORT_SYMBOL(inet_csk_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 inet_csk_init_xmit_timers(struct sock *sk,
-                              void (*retransmit_handler)(unsigned long),
-                              void (*delack_handler)(unsigned long),
-                              void (*keepalive_handler)(unsigned long))
-{
-       struct inet_connection_sock *icsk = inet_csk(sk);
-
-       init_timer(&icsk->icsk_retransmit_timer);
-       init_timer(&icsk->icsk_delack_timer);
-       init_timer(&sk->sk_timer);
-
-       icsk->icsk_retransmit_timer.function = retransmit_handler;
-       icsk->icsk_delack_timer.function     = delack_handler;
-       sk->sk_timer.function                = keepalive_handler;
-
-       icsk->icsk_retransmit_timer.data = 
-               icsk->icsk_delack_timer.data =
-                       sk->sk_timer.data  = (unsigned long)sk;
-
-       icsk->icsk_pending = icsk->icsk_ack.pending = 0;
-}
-
-void inet_csk_clear_xmit_timers(struct sock *sk)
-{
-       struct inet_connection_sock *icsk = inet_csk(sk);
-
-       icsk->icsk_pending = icsk->icsk_ack.pending = icsk->icsk_ack.blocked = 0;
-
-       sk_stop_timer(sk, &icsk->icsk_retransmit_timer);
-       sk_stop_timer(sk, &icsk->icsk_delack_timer);
-       sk_stop_timer(sk, &sk->sk_timer);
-}
-
 void tcp_init_xmit_timers(struct sock *sk)
 {
        inet_csk_init_xmit_timers(sk, &tcp_write_timer, &tcp_delack_timer,
                                  &tcp_keepalive_timer);
 }
 
+EXPORT_SYMBOL(tcp_init_xmit_timers);
+
 static void tcp_write_err(struct sock *sk)
 {
        sk->sk_err = sk->sk_err_soft ? : ETIMEDOUT;
@@ -99,7 +58,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.
@@ -173,7 +132,7 @@ static int tcp_write_timeout(struct sock *sk)
                           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
+                          to make it. It is disgusting. It does not work in any
                           case. Let me to cite the same draft, which requires for
                           us to implement this:
 
@@ -274,11 +233,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;
+               icsk->icsk_probes_out = 0;
                return;
        }
 
@@ -289,7 +249,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
@@ -300,16 +260,15 @@ static void tcp_probe_timer(struct sock *sk)
        max_probes = sysctl_tcp_retries2;
 
        if (sock_flag(sk, SOCK_DEAD)) {
-               const struct inet_connection_sock *icsk = inet_csk(sk);
                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. */
@@ -360,19 +319,20 @@ static void tcp_retransmit_timer(struct sock *sk)
                goto out;
 
        if (icsk->icsk_retransmits == 0) {
-               if (tp->ca_state == TCP_CA_Disorder || tp->ca_state == TCP_CA_Recovery) {
+               if (icsk->icsk_ca_state == TCP_CA_Disorder ||
+                   icsk->icsk_ca_state == TCP_CA_Recovery) {
                        if (tp->rx_opt.sack_ok) {
-                               if (tp->ca_state == TCP_CA_Recovery)
+                               if (icsk->icsk_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)
+                               if (icsk->icsk_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) {
+               } else if (icsk->icsk_ca_state == TCP_CA_Loss) {
                        NET_INC_STATS_BH(LINUX_MIB_TCPLOSSFAILURES);
                } else {
                        NET_INC_STATS_BH(LINUX_MIB_TCPTIMEOUTS);
@@ -392,7 +352,8 @@ static void tcp_retransmit_timer(struct sock *sk)
                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));
+                                         min(icsk->icsk_rto, TCP_RESOURCE_PROBE_INTERVAL),
+                                         TCP_RTO_MAX);
                goto out;
        }
 
@@ -416,7 +377,7 @@ static void tcp_retransmit_timer(struct sock *sk)
 
 out_reset_timer:
        icsk->icsk_rto = min(icsk->icsk_rto << 1, TCP_RTO_MAX);
-       inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto);
+       inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto, TCP_RTO_MAX);
        if (icsk->icsk_retransmits > sysctl_tcp_retries1)
                __sk_dst_reset(sk);
 
@@ -470,97 +431,8 @@ out_unlock:
 
 static void tcp_synack_timer(struct sock *sk)
 {
-       struct tcp_sock *tp = tcp_sk(sk);
-       struct inet_connection_sock *icsk = inet_csk(sk);
-       struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt;
-       int max_retries = icsk->icsk_syn_retries ? : sysctl_tcp_synack_retries;
-       int thresh = max_retries;
-       unsigned long now = jiffies;
-       struct request_sock **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 ||
-                                    (inet_rsk(req)->acked && req->retrans < max_retries))
-                                   && !req->rsk_ops->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 */
-                               inet_csk_reqsk_queue_unlink(sk, req, reqp);
-                               reqsk_queue_removed(&icsk->icsk_accept_queue, req);
-                               reqsk_free(req);
-                               continue;
-                       }
-                       reqp = &req->dl_next;
-               }
-
-               i = (i+1)&(TCP_SYNQ_HSIZE-1);
-
-       } while (--budget > 0);
-
-       lopt->clock_hand = i;
-
-       if (lopt->qlen)
-               inet_csk_reset_keepalive_timer(sk, TCP_SYNQ_INTERVAL);
-}
-
-void inet_csk_delete_keepalive_timer(struct sock *sk)
-{
-       sk_stop_timer(sk, &sk->sk_timer);
-}
-
-void inet_csk_reset_keepalive_timer(struct sock *sk, unsigned long len)
-{
-       sk_reset_timer(sk, &sk->sk_timer, jiffies + len);
+       inet_csk_reqsk_queue_prune(sk, TCP_SYNQ_INTERVAL,
+                                  TCP_TIMEOUT_INIT, TCP_RTO_MAX);
 }
 
 void tcp_set_keepalive(struct sock *sk, int val)
@@ -578,6 +450,7 @@ void tcp_set_keepalive(struct sock *sk, int val)
 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;
 
@@ -619,14 +492,14 @@ static void tcp_keepalive_timer (unsigned long data)
        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 ((!tp->keepalive_probes && icsk->icsk_probes_out >= sysctl_tcp_keepalive_probes) ||
+                    (tp->keepalive_probes && icsk->icsk_probes_out >= tp->keepalive_probes)) {
                        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,
@@ -653,8 +526,3 @@ out:
        bh_unlock_sock(sk);
        sock_put(sk);
 }
-
-EXPORT_SYMBOL(inet_csk_clear_xmit_timers);
-EXPORT_SYMBOL(inet_csk_delete_keepalive_timer);
-EXPORT_SYMBOL(tcp_init_xmit_timers);
-EXPORT_SYMBOL(inet_csk_reset_keepalive_timer);