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

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