linux-old/net/rose/rose_timer.c
<<
>>
Prefs
   1/*
   2 *      ROSE release 003
   3 *
   4 *      This code REQUIRES 2.1.15 or higher/ NET3.038
   5 *
   6 *      This module:
   7 *              This module is free software; you can redistribute it and/or
   8 *              modify it under the terms of the GNU General Public License
   9 *              as published by the Free Software Foundation; either version
  10 *              2 of the License, or (at your option) any later version.
  11 *
  12 *      History
  13 *      ROSE 001        Jonathan(G4KLX) Cloned from nr_timer.c
  14 *      ROSE 003        Jonathan(G4KLX) New timer architecture.
  15 *                                      Implemented idle timer.
  16 */
  17
  18#include <linux/errno.h>
  19#include <linux/types.h>
  20#include <linux/socket.h>
  21#include <linux/in.h>
  22#include <linux/kernel.h>
  23#include <linux/sched.h>
  24#include <linux/timer.h>
  25#include <linux/string.h>
  26#include <linux/sockios.h>
  27#include <linux/net.h>
  28#include <net/ax25.h>
  29#include <linux/inet.h>
  30#include <linux/netdevice.h>
  31#include <linux/skbuff.h>
  32#include <net/sock.h>
  33#include <asm/segment.h>
  34#include <asm/system.h>
  35#include <linux/fcntl.h>
  36#include <linux/mm.h>
  37#include <linux/interrupt.h>
  38#include <net/rose.h>
  39
  40static void rose_heartbeat_expiry(unsigned long);
  41static void rose_timer_expiry(unsigned long);
  42static void rose_idletimer_expiry(unsigned long);
  43
  44void rose_start_heartbeat(struct sock *sk)
  45{
  46        del_timer(&sk->timer);
  47
  48        sk->timer.data     = (unsigned long)sk;
  49        sk->timer.function = &rose_heartbeat_expiry;
  50        sk->timer.expires  = jiffies + 5 * HZ;
  51
  52        add_timer(&sk->timer);
  53}
  54
  55void rose_start_t1timer(struct sock *sk)
  56{
  57        del_timer(&sk->protinfo.rose->timer);
  58
  59        sk->protinfo.rose->timer.data     = (unsigned long)sk;
  60        sk->protinfo.rose->timer.function = &rose_timer_expiry;
  61        sk->protinfo.rose->timer.expires  = jiffies + sk->protinfo.rose->t1;
  62
  63        add_timer(&sk->protinfo.rose->timer);
  64}
  65
  66void rose_start_t2timer(struct sock *sk)
  67{
  68        del_timer(&sk->protinfo.rose->timer);
  69
  70        sk->protinfo.rose->timer.data     = (unsigned long)sk;
  71        sk->protinfo.rose->timer.function = &rose_timer_expiry;
  72        sk->protinfo.rose->timer.expires  = jiffies + sk->protinfo.rose->t2;
  73
  74        add_timer(&sk->protinfo.rose->timer);
  75}
  76
  77void rose_start_t3timer(struct sock *sk)
  78{
  79        del_timer(&sk->protinfo.rose->timer);
  80
  81        sk->protinfo.rose->timer.data     = (unsigned long)sk;
  82        sk->protinfo.rose->timer.function = &rose_timer_expiry;
  83        sk->protinfo.rose->timer.expires  = jiffies + sk->protinfo.rose->t3;
  84
  85        add_timer(&sk->protinfo.rose->timer);
  86}
  87
  88void rose_start_hbtimer(struct sock *sk)
  89{
  90        del_timer(&sk->protinfo.rose->timer);
  91
  92        sk->protinfo.rose->timer.data     = (unsigned long)sk;
  93        sk->protinfo.rose->timer.function = &rose_timer_expiry;
  94        sk->protinfo.rose->timer.expires  = jiffies + sk->protinfo.rose->hb;
  95
  96        add_timer(&sk->protinfo.rose->timer);
  97}
  98
  99void rose_start_idletimer(struct sock *sk)
 100{
 101        del_timer(&sk->protinfo.rose->idletimer);
 102
 103        if (sk->protinfo.rose->idle > 0) {
 104                sk->protinfo.rose->idletimer.data     = (unsigned long)sk;
 105                sk->protinfo.rose->idletimer.function = &rose_idletimer_expiry;
 106                sk->protinfo.rose->idletimer.expires  = jiffies + sk->protinfo.rose->idle;
 107
 108                add_timer(&sk->protinfo.rose->idletimer);
 109        }
 110}
 111
 112void rose_stop_heartbeat(struct sock *sk)
 113{
 114        del_timer(&sk->timer);
 115}
 116
 117void rose_stop_timer(struct sock *sk)
 118{
 119        del_timer(&sk->protinfo.rose->timer);
 120}
 121
 122void rose_stop_idletimer(struct sock *sk)
 123{
 124        del_timer(&sk->protinfo.rose->idletimer);
 125}
 126
 127static void rose_heartbeat_expiry(unsigned long param)
 128{
 129        struct sock *sk = (struct sock *)param;
 130
 131        switch (sk->protinfo.rose->state) {
 132
 133                case ROSE_STATE_0:
 134                        /* Magic here: If we listen() and a new link dies before it
 135                           is accepted() it isn't 'dead' so doesn't get removed. */
 136                        if (sk->destroy || (sk->state == TCP_LISTEN && sk->dead)) {
 137                                rose_destroy_socket(sk);
 138                                return;
 139                        }
 140                        break;
 141
 142                case ROSE_STATE_3:
 143                        /*
 144                         * Check for the state of the receive buffer.
 145                         */
 146                        if (atomic_read(&sk->rmem_alloc) < (sk->rcvbuf / 2) &&
 147                            (sk->protinfo.rose->condition & ROSE_COND_OWN_RX_BUSY)) {
 148                                sk->protinfo.rose->condition &= ~ROSE_COND_OWN_RX_BUSY;
 149                                sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING;
 150                                sk->protinfo.rose->vl         = sk->protinfo.rose->vr;
 151                                rose_write_internal(sk, ROSE_RR);
 152                                rose_stop_timer(sk);    /* HB */
 153                                break;
 154                        }
 155                        break;
 156        }
 157
 158        rose_start_heartbeat(sk);
 159}
 160
 161static void rose_timer_expiry(unsigned long param)
 162{
 163        struct sock *sk = (struct sock *)param;
 164
 165        switch (sk->protinfo.rose->state) {
 166
 167                case ROSE_STATE_1:      /* T1 */
 168                case ROSE_STATE_4:      /* T2 */
 169                        rose_write_internal(sk, ROSE_CLEAR_REQUEST);
 170                        sk->protinfo.rose->state = ROSE_STATE_2;
 171                        rose_start_t3timer(sk);
 172                        break;
 173
 174                case ROSE_STATE_2:      /* T3 */
 175                        sk->protinfo.rose->neighbour->use--;
 176                        rose_disconnect(sk, ETIMEDOUT, -1, -1);
 177                        break;
 178
 179                case ROSE_STATE_3:      /* HB */
 180                        if (sk->protinfo.rose->condition & ROSE_COND_ACK_PENDING) {
 181                                sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING;
 182                                rose_enquiry_response(sk);
 183                        }
 184                        break;
 185        }
 186}
 187
 188static void rose_idletimer_expiry(unsigned long param)
 189{
 190        struct sock *sk = (struct sock *)param;
 191
 192        rose_clear_queues(sk);
 193
 194        rose_write_internal(sk, ROSE_CLEAR_REQUEST);
 195        sk->protinfo.rose->state = ROSE_STATE_2;
 196
 197        rose_start_t3timer(sk);
 198
 199        sk->state     = TCP_CLOSE;
 200        sk->err       = 0;
 201        sk->shutdown |= SEND_SHUTDOWN;  
 202
 203        if (!sk->dead)
 204                sk->state_change(sk);
 205
 206        sk->dead = 1;
 207}
 208
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.