root/net/ipv4/tcp_timer.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tcp_reset_xmit_timer
  2. tcp_retransmit_time
  3. tcp_retransmit
  4. tcp_write_timeout
  5. tcp_retransmit_timer

   1 /*
   2  * INET         An implementation of the TCP/IP protocol suite for the LINUX
   3  *              operating system.  INET is implemented using the  BSD Socket
   4  *              interface as the means of communication with the user level.
   5  *
   6  *              Implementation of the Transmission Control Protocol(TCP).
   7  *
   8  * Version:     @(#)tcp.c       1.0.16  05/25/93
   9  *
  10  * Authors:     Ross Biro, <bir7@leland.Stanford.Edu>
  11  *              Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  12  *              Mark Evans, <evansmp@uhura.aston.ac.uk>
  13  *              Corey Minyard <wf-rch!minyard@relay.EU.net>
  14  *              Florian La Roche, <flla@stud.uni-sb.de>
  15  *              Charles Hedrick, <hedrick@klinzhai.rutgers.edu>
  16  *              Linus Torvalds, <torvalds@cs.helsinki.fi>
  17  *              Alan Cox, <gw4pts@gw4pts.ampr.org>
  18  *              Matthew Dillon, <dillon@apollo.west.oic.com>
  19  *              Arnt Gulbrandsen, <agulbra@nvg.unit.no>
  20  *              Jorge Cwik, <jorge@laser.satlink.net>
  21  */
  22 
  23 #include <net/tcp.h>
  24 
  25 /*
  26  *      Reset the retransmission timer
  27  */
  28  
  29 void tcp_reset_xmit_timer(struct sock *sk, int why, unsigned long when)
     /* [previous][next][first][last][top][bottom][index][help] */
  30 {
  31         del_timer(&sk->retransmit_timer);
  32         sk->ip_xmit_timeout = why;
  33         if((long)when < 0)
  34         {
  35                 when=3;
  36                 printk("Error: Negative timer in xmit_timer\n");
  37         }
  38         sk->retransmit_timer.expires=jiffies+when;
  39         add_timer(&sk->retransmit_timer);
  40 }
  41 
  42 /*
  43  *      This is the normal code called for timeouts.  It does the retransmission
  44  *      and then does backoff.  tcp_do_retransmit is separated out because
  45  *      tcp_ack needs to send stuff from the retransmit queue without
  46  *      initiating a backoff.
  47  */
  48 
  49 
  50 static void tcp_retransmit_time(struct sock *sk, int all)
     /* [previous][next][first][last][top][bottom][index][help] */
  51 {
  52         tcp_do_retransmit(sk, all);
  53 
  54         /*
  55          * Increase the timeout each time we retransmit.  Note that
  56          * we do not increase the rtt estimate.  rto is initialized
  57          * from rtt, but increases here.  Jacobson (SIGCOMM 88) suggests
  58          * that doubling rto each time is the least we can get away with.
  59          * In KA9Q, Karn uses this for the first few times, and then
  60          * goes to quadratic.  netBSD doubles, but only goes up to *64,
  61          * and clamps at 1 to 64 sec afterwards.  Note that 120 sec is
  62          * defined in the protocol as the maximum possible RTT.  I guess
  63          * we'll have to use something other than TCP to talk to the
  64          * University of Mars.
  65          *
  66          * PAWS allows us longer timeouts and large windows, so once
  67          * implemented ftp to mars will work nicely. We will have to fix
  68          * the 120 second clamps though!
  69          */
  70 
  71         sk->retransmits++;
  72         sk->prot->retransmits++;
  73         sk->backoff++;
  74         sk->rto = min(sk->rto << 1, 120*HZ);
  75         tcp_reset_xmit_timer(sk, TIME_WRITE, sk->rto);
  76 }
  77 
  78 /*
  79  *      A timer event has trigger a tcp retransmit timeout. The
  80  *      socket xmit queue is ready and set up to send. Because
  81  *      the ack receive code keeps the queue straight we do
  82  *      nothing clever here.
  83  */
  84 
  85 void tcp_retransmit(struct sock *sk, int all)
     /* [previous][next][first][last][top][bottom][index][help] */
  86 {
  87         if (all) 
  88         {
  89                 tcp_retransmit_time(sk, all);
  90                 return;
  91         }
  92 
  93         sk->ssthresh = sk->cong_window >> 1; /* remember window where we lost */
  94         /* sk->ssthresh in theory can be zero.  I guess that's OK */
  95         sk->cong_count = 0;
  96 
  97         sk->cong_window = 1;
  98 
  99         /* Do the actual retransmit. */
 100         tcp_retransmit_time(sk, all);
 101 }
 102 
 103 /*
 104  *      A write timeout has occurred. Process the after effects.
 105  */
 106 
 107 static int tcp_write_timeout(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 108 {
 109         /*
 110          *      Look for a 'soft' timeout.
 111          */
 112         if ((sk->state == TCP_ESTABLISHED && sk->retransmits && !(sk->retransmits & 7))
 113                 || (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR1)) 
 114         {
 115                 /*
 116                  *      Attempt to recover if arp has changed (unlikely!) or
 117                  *      a route has shifted (not supported prior to 1.3).
 118                  */
 119                 ip_rt_advice(&sk->ip_route_cache, 0);
 120         }
 121         
 122         /*
 123          *      Have we tried to SYN too many times (repent repent 8))
 124          */
 125          
 126         if(sk->retransmits > TCP_SYN_RETRIES && sk->state==TCP_SYN_SENT)
 127         {
 128                 if(sk->err_soft)
 129                         sk->err=sk->err_soft;
 130                 else
 131                         sk->err=ETIMEDOUT;
 132                 sk->error_report(sk);
 133                 del_timer(&sk->retransmit_timer);
 134                 tcp_statistics.TcpAttemptFails++;       /* Is this right ??? - FIXME - */
 135                 tcp_set_state(sk,TCP_CLOSE);
 136                 /* Don't FIN, we got nothing back */
 137                 release_sock(sk);
 138                 return 0;
 139         }
 140         /*
 141          *      Has it gone just too far ?
 142          */
 143         if (sk->retransmits > TCP_RETR2) 
 144         {
 145                 if(sk->err_soft)
 146                         sk->err = sk->err_soft;
 147                 else
 148                         sk->err = ETIMEDOUT;
 149                 sk->error_report(sk);
 150                 del_timer(&sk->retransmit_timer);
 151                 /*
 152                  *      Time wait the socket 
 153                  */
 154                 if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2 || sk->state == TCP_CLOSING ) 
 155                 {
 156                         tcp_set_state(sk,TCP_TIME_WAIT);
 157                         tcp_reset_msl_timer (sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
 158                 }
 159                 else
 160                 {
 161                         /*
 162                          *      Clean up time.
 163                          */
 164                         tcp_set_state(sk, TCP_CLOSE);
 165                         release_sock(sk);
 166                         return 0;
 167                 }
 168         }
 169         return 1;
 170 }
 171 
 172 /*
 173  *      The TCP retransmit timer. This lacks a few small details.
 174  *
 175  *      1.      An initial rtt timeout on the probe0 should cause what we can
 176  *              of the first write queue buffer to be split and sent.
 177  *      2.      On a 'major timeout' as defined by RFC1122 we shouldn't report
 178  *              ETIMEDOUT if we know an additional 'soft' error caused this.
 179  *              tcp_err should save a 'soft error' for us.
 180  */
 181 
 182 void tcp_retransmit_timer(unsigned long data)
     /* [previous][next][first][last][top][bottom][index][help] */
 183 {
 184         struct sock *sk = (struct sock*)data;
 185         int why = sk->ip_xmit_timeout;
 186 
 187         /*
 188          *      We are reset. We will send no more retransmits.
 189          */
 190          
 191         if(sk->zapped)
 192                 return;
 193                 
 194         /* 
 195          *      Only process if socket is not in use
 196          */
 197 
 198         cli();
 199         if (sk->inuse || in_bh) 
 200         {
 201                 /* Try again in 1 second */
 202                 sk->retransmit_timer.expires = jiffies+HZ;
 203                 add_timer(&sk->retransmit_timer);
 204                 sti();
 205                 return;
 206         }
 207 
 208         sk->inuse = 1;
 209         sti();
 210 
 211 
 212         if (sk->ack_backlog && !sk->dead) 
 213                 sk->data_ready(sk,0);
 214 
 215         /* Now we need to figure out why the socket was on the timer. */
 216 
 217         switch (why) 
 218         {
 219                 /* Window probing */
 220                 case TIME_PROBE0:
 221                         tcp_send_probe0(sk);
 222                         tcp_write_timeout(sk);
 223                         break;
 224                 /* Retransmitting */
 225                 case TIME_WRITE:
 226                         /* It could be we got here because we needed to send an ack.
 227                          * So we need to check for that.
 228                          */
 229                 {
 230                         struct sk_buff *skb;
 231                         unsigned long flags;
 232 
 233                         save_flags(flags);
 234                         cli();
 235                         skb = sk->send_head;
 236                         if (!skb) 
 237                         {
 238                                 if (sk->ack_backlog)
 239                                         tcp_read_wakeup(sk);
 240                                 restore_flags(flags);
 241                         } 
 242                         else 
 243                         {
 244                                 /*
 245                                  *      Kicked by a delayed ack. Reset timer
 246                                  *      correctly now
 247                                  */
 248                                 if (jiffies < skb->when + sk->rto) 
 249                                 {
 250                                         if (sk->ack_backlog)
 251                                                 tcp_read_wakeup(sk);
 252                                         tcp_reset_xmit_timer (sk, TIME_WRITE, skb->when + sk->rto - jiffies);
 253                                         restore_flags(flags);
 254                                         break;
 255                                 }
 256                                 restore_flags(flags);
 257                                 /*
 258                                  *      Retransmission
 259                                  */
 260                                 sk->retransmits++;
 261                                 sk->prot->retransmits++;
 262                                 sk->prot->retransmit (sk, 0);
 263                                 tcp_write_timeout(sk);
 264                         }
 265                         break;
 266                 }
 267                 /* Sending Keepalives */
 268                 case TIME_KEEPOPEN:
 269                         /* 
 270                          * this reset_timer() call is a hack, this is not
 271                          * how KEEPOPEN is supposed to work.
 272                          */
 273                         tcp_reset_xmit_timer (sk, TIME_KEEPOPEN, TCP_TIMEOUT_LEN);
 274 
 275                         /* Send something to keep the connection open. */
 276                         if (sk->prot->write_wakeup)
 277                                   sk->prot->write_wakeup (sk);
 278                         sk->retransmits++;
 279                         sk->prot->retransmits++;
 280                         tcp_write_timeout(sk);
 281                         break;
 282                 default:
 283                         printk ("rexmit_timer: timer expired - reason unknown\n");
 284                         break;
 285         }
 286         release_sock(sk);
 287 }

/* [previous][next][first][last][top][bottom][index][help] */