root/net/tcp/timer.c

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

DEFINITIONS

This source file includes following definitions.
  1. delete_timer
  2. reset_timer
  3. net_timer

   1 /* timer.c */
   2 /*
   3   Copyright (C) 1992  Ross Biro
   4   
   5   This program is free software; you can redistribute it and/or modify
   6   it under the terms of the GNU General Public License as published by
   7   the Free Software Foundation; either version 1, or (at your option)
   8   any later version.
   9   
  10   This program is distributed in the hope that it will be useful,
  11   but WITHOUT ANY WARRANTY; without even the implied warranty of
  12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13   GNU General Public License for more details.
  14   
  15   You should have received a copy of the GNU General Public License
  16   along with this program; if not, write to the Free Software
  17   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  18   
  19   The Author may be reached as bir7@leland.stanford.edu or
  20   C/O Department of Mathematics; Stanford University; Stanford, CA 94305
  21   */
  22 
  23 /* $Id: timer.c,v 0.8.4.5 1992/12/12 19:25:04 bir7 Exp $ */
  24 /* $Log: timer.c,v $
  25  * Revision 0.8.4.5  1992/12/12  19:25:04  bir7
  26  * cleaned up Log messages.
  27  *
  28  * Revision 0.8.4.4  1992/12/12  01:50:49  bir7
  29  * Fixed timeouts.
  30  *
  31  * Revision 0.8.4.3  1992/12/06  23:29:59  bir7
  32  * Fixed bugs in timeout.
  33  *
  34  * Revision 0.8.4.2  1992/11/10  10:38:48  bir7
  35  * Change free_s to kfree_s and accidently changed free_skb to kfree_skb.
  36  *
  37  * Revision 0.8.4.1  1992/11/10  00:17:18  bir7
  38  * version change only.
  39  *
  40  * Revision 0.8.3.2  1992/11/10  00:14:47  bir7
  41  * Changed malloc to kmalloc and added Id and Log
  42  * */
  43 
  44 #include <linux/types.h>
  45 #include <linux/errno.h>
  46 #include <linux/socket.h>
  47 #include <netinet/in.h>
  48 #include <linux/kernel.h>
  49 #include <linux/sched.h>
  50 #include <linux/timer.h>
  51 #include <asm/system.h>
  52 #include "timer.h"
  53 #include "ip.h"
  54 #include "tcp.h"
  55 #include "sock.h"
  56 #include "arp.h"
  57 
  58 #undef TIMER_DEBUG
  59 
  60 #ifdef PRINTK
  61 #undef PRINTK
  62 #endif
  63 
  64 
  65 #ifdef TIMER_DEBUG
  66 #define PRINTK(x) printk x
  67 #else
  68 #define PRINTK(x) /**/
  69 #endif
  70 
  71 static struct timer *timer_base=NULL;
  72 unsigned long seq_offset;
  73 
  74 void
  75 delete_timer (struct timer *t)
     /* [previous][next][first][last][top][bottom][index][help] */
  76 {
  77    struct timer *tm;
  78    PRINTK (("delete_timer (t=%X)\n",t));
  79    if (timer_base == NULL || t == NULL) return;
  80    cli();
  81    if (t == timer_base) 
  82      {
  83         timer_base = t->next;
  84         if (timer_base != NULL)
  85           {
  86              timer_table[NET_TIMER].expires = timer_base->when;
  87              timer_active |= 1 << NET_TIMER;
  88           }
  89         else
  90           {
  91              timer_active &= ~(1 << NET_TIMER);
  92           }
  93         sti();
  94         return;
  95      }
  96    for (tm = timer_base;tm->next != NULL ;tm=tm->next)
  97      {
  98         if (tm->next == t)
  99           {
 100              tm->next = t->next;
 101              sti();
 102              return;
 103           }
 104      }
 105    sti();
 106 }
 107 
 108 
 109 void
 110 reset_timer (struct timer *t)
     /* [previous][next][first][last][top][bottom][index][help] */
 111 {
 112    struct timer *tm;
 113 
 114    delete_timer (t);
 115    t->when = timer_seq + t->len;
 116    PRINTK (("reset_timer (t=%X) when = %d jiffies = %d\n",t, t->when, jiffies));
 117    if (t == NULL)
 118      {
 119         printk ("*** reset timer NULL timer\n");
 120         __asm__ ("\t int $3\n"::);
 121      }
 122    /* first see if it goes at the beginning. */
 123    cli();
 124    if (timer_base == NULL) 
 125      {
 126         t->next = NULL;
 127         timer_base = t;
 128         timer_table[NET_TIMER].expires = t->when;
 129         timer_active |= 1 << NET_TIMER;
 130         sti();
 131         return;
 132      }
 133    if (before (t->when, timer_base->when))
 134      {
 135         t->next = timer_base;
 136         timer_base = t;
 137         timer_table[NET_TIMER].expires = t->when;
 138         timer_active |= 1 << NET_TIMER;
 139         sti();
 140         return;
 141      }
 142    for (tm = timer_base; ; tm=tm->next)
 143      {
 144         if (tm->next == NULL || before (t->when,tm->next->when))
 145           {
 146              t->next = tm->next;
 147              tm->next = t;
 148              sti();
 149              return;
 150           }
 151      }
 152 }
 153 
 154 void
 155 net_timer (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 156 {
 157    volatile struct sock *sk;
 158 
 159    /* now we will only be called whenever we need to do something, but
 160       we must be sure to process all of the sockets that need it. */
 161 
 162    while (timer_base != NULL && after (timer_seq+1 ,timer_base->when))
 163      {
 164         int why;
 165         sk = timer_base->sk;
 166         cli();
 167         if (sk->inuse)
 168           {
 169              sti();
 170              break;
 171           }
 172         sk->inuse = 1;
 173         sti();
 174         why = sk->timeout;
 175 
 176         PRINTK (("net_timer: found sk=%X why = %d\n",sk, why));
 177 
 178         if (sk->keepopen)
 179           {
 180              sk->time_wait.len = TCP_TIMEOUT_LEN;
 181              sk->timeout = TIME_KEEPOPEN;
 182              reset_timer (timer_base);
 183           }
 184         else
 185           {
 186              sk->timeout = 0;
 187              delete_timer(timer_base);
 188           }
 189         
 190         /* always see if we need to send an ack. */
 191         if (sk->ack_backlog)
 192           {
 193              sk->prot->read_wakeup(sk);
 194              if (!sk->dead) wake_up (sk->sleep);
 195           }
 196         
 197         /* now we need to figure out why the socket was on the timer. */
 198         switch (why)
 199           {
 200 
 201             case TIME_DONE:
 202              if (!sk->dead || sk->state != TCP_CLOSE)
 203                {
 204                   printk ("non dead socket in time_done\n");
 205                   release_sock (sk);
 206                   break;
 207                }
 208              destroy_sock (sk);
 209              break;
 210 
 211             case TIME_DESTROY: /* we've waited for a while for all
 212                                   the memory assosiated with the
 213                                   socket to be freed.  We need to
 214                                   print an error message. */
 215              PRINTK (("possible memory leak.  sk = %X\n", sk));
 216              print_sk (sk);
 217              reset_timer ((struct timer *)&sk->time_wait);
 218              sk->inuse = 0;
 219              break;
 220              
 221             case TIME_CLOSE: /* we've waited long enough, close the
 222                                 socket. */
 223              
 224              sk->state = TCP_CLOSE;
 225              delete_timer ((struct timer *)&sk->time_wait);
 226              /* kill the arp entry 
 227                 in case the hardware has changed. */
 228              arp_destroy (sk->daddr);
 229              if (!sk->dead)
 230                wake_up (sk->sleep);
 231              release_sock(sk);
 232              break;
 233              
 234             case TIME_WRITE: /* try to retransmit. */
 235              /* it could be we got here because we needed
 236                 to send an ack.  So we need to check for that. */
 237              if (sk->send_head != NULL)
 238                {
 239                  if (before (jiffies, sk->send_head->when + 2*sk->rtt))
 240                    {
 241                      sk->time_wait.len = 2*sk->rtt;
 242                      sk->timeout = TIME_WRITE;
 243                      reset_timer ((struct timer *)&sk->time_wait);
 244                      release_sock (sk);
 245                      break;
 246                    }
 247                  PRINTK (("retransmitting.\n"));
 248                  sk->prot->retransmit (sk, 0);
 249 
 250                   if (sk->retransmits > TCP_RETR1)
 251                     {
 252                       PRINTK (("timer.c TIME_WRITE time-out 1\n"));
 253                       arp_destroy (sk->daddr);
 254                       ip_route_check (sk->daddr);
 255                     }
 256 
 257                   if (sk->retransmits > TCP_RETR2)
 258                     {
 259                       PRINTK (("timer.c TIME_WRITE time-out 2\n"));
 260                        sk->err = ETIMEDOUT;
 261                        if (sk->state == TCP_FIN_WAIT1 ||
 262                            sk->state == TCP_FIN_WAIT2 ||
 263                            sk->state == TCP_LAST_ACK)
 264                          {
 265                             sk->state = TCP_TIME_WAIT;
 266                             sk->timeout = TIME_CLOSE;
 267                             sk->time_wait.len = TCP_TIMEWAIT_LEN;
 268                             reset_timer ((struct timer *)&sk->time_wait);
 269                             release_sock(sk);
 270                             break;
 271                          }
 272                        else /* sk->state == ... */
 273                          {
 274                             sk->prot->close (sk,1);
 275                             break;
 276                          }
 277                     }
 278                   release_sock (sk);
 279                   break;
 280                }
 281              release_sock (sk);
 282              break;
 283 
 284             case TIME_KEEPOPEN: /* send something to keep the
 285                                    connection open. */
 286 
 287              if (sk->prot->write_wakeup != NULL)
 288                sk->prot->write_wakeup(sk);
 289              sk->retransmits ++;
 290              if (sk->shutdown == SHUTDOWN_MASK)
 291                {
 292                  sk->prot->close (sk,1);
 293                  sk->state = TCP_CLOSE;
 294                }
 295 
 296              if (sk->retransmits > TCP_RETR1)
 297                {
 298                  PRINTK (("timer.c TIME_KEEPOPEN time-out 1\n"));
 299                  arp_destroy (sk->daddr);
 300                  ip_route_check (sk->daddr);
 301                  release_sock (sk);
 302                  break;
 303                }
 304              if (sk->retransmits > TCP_RETR2)
 305                {
 306                  PRINTK (("timer.c TIME_KEEPOPEN time-out 2\n"));
 307                   arp_destroy (sk->daddr);
 308                   sk->err = ETIMEDOUT;
 309                   if (sk->state == TCP_FIN_WAIT1 ||
 310                       sk->state == TCP_FIN_WAIT2)
 311                     {
 312                        sk->state = TCP_TIME_WAIT;
 313                        if (!sk->dead)
 314                          wake_up (sk->sleep);
 315                        release_sock(sk);
 316                     }
 317                   else /* sk->state == */
 318                     {
 319                        sk->prot->close (sk, 1);
 320                     }
 321                   break;
 322                }
 323              release_sock (sk);
 324              break;
 325              
 326             default:
 327              release_sock(sk);
 328              break;
 329           } /* switch */
 330      } /* while (timer_base != ...  */
 331 
 332    /* Now we need to reset the timer. */
 333    if (timer_base != NULL)
 334      {
 335         timer_table[NET_TIMER].expires = timer_base->when;
 336         timer_active |= 1 << NET_TIMER;
 337      }
 338 }
 339 
 340 

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