linux/net/netrom/nr_timer.c
<<
>>
Prefs
   1/*
   2 * This program is free software; you can redistribute it and/or modify
   3 * it under the terms of the GNU General Public License as published by
   4 * the Free Software Foundation; either version 2 of the License, or
   5 * (at your option) any later version.
   6 *
   7 * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
   8 * Copyright (C) 2002 Ralf Baechle DO1GRB (ralf@gnu.org)
   9 */
  10#include <linux/errno.h>
  11#include <linux/types.h>
  12#include <linux/socket.h>
  13#include <linux/in.h>
  14#include <linux/kernel.h>
  15#include <linux/jiffies.h>
  16#include <linux/timer.h>
  17#include <linux/string.h>
  18#include <linux/sockios.h>
  19#include <linux/net.h>
  20#include <net/ax25.h>
  21#include <linux/inet.h>
  22#include <linux/netdevice.h>
  23#include <linux/skbuff.h>
  24#include <net/sock.h>
  25#include <net/tcp_states.h>
  26#include <asm/uaccess.h>
  27#include <linux/fcntl.h>
  28#include <linux/mm.h>
  29#include <linux/interrupt.h>
  30#include <net/netrom.h>
  31
  32static void nr_heartbeat_expiry(unsigned long);
  33static void nr_t1timer_expiry(unsigned long);
  34static void nr_t2timer_expiry(unsigned long);
  35static void nr_t4timer_expiry(unsigned long);
  36static void nr_idletimer_expiry(unsigned long);
  37
  38void nr_init_timers(struct sock *sk)
  39{
  40        struct nr_sock *nr = nr_sk(sk);
  41
  42        setup_timer(&nr->t1timer, nr_t1timer_expiry, (unsigned long)sk);
  43        setup_timer(&nr->t2timer, nr_t2timer_expiry, (unsigned long)sk);
  44        setup_timer(&nr->t4timer, nr_t4timer_expiry, (unsigned long)sk);
  45        setup_timer(&nr->idletimer, nr_idletimer_expiry, (unsigned long)sk);
  46
  47        /* initialized by sock_init_data */
  48        sk->sk_timer.data     = (unsigned long)sk;
  49        sk->sk_timer.function = &nr_heartbeat_expiry;
  50}
  51
  52void nr_start_t1timer(struct sock *sk)
  53{
  54        struct nr_sock *nr = nr_sk(sk);
  55
  56        mod_timer(&nr->t1timer, jiffies + nr->t1);
  57}
  58
  59void nr_start_t2timer(struct sock *sk)
  60{
  61        struct nr_sock *nr = nr_sk(sk);
  62
  63        mod_timer(&nr->t2timer, jiffies + nr->t2);
  64}
  65
  66void nr_start_t4timer(struct sock *sk)
  67{
  68        struct nr_sock *nr = nr_sk(sk);
  69
  70        mod_timer(&nr->t4timer, jiffies + nr->t4);
  71}
  72
  73void nr_start_idletimer(struct sock *sk)
  74{
  75        struct nr_sock *nr = nr_sk(sk);
  76
  77        if (nr->idle > 0)
  78                mod_timer(&nr->idletimer, jiffies + nr->idle);
  79}
  80
  81void nr_start_heartbeat(struct sock *sk)
  82{
  83        mod_timer(&sk->sk_timer, jiffies + 5 * HZ);
  84}
  85
  86void nr_stop_t1timer(struct sock *sk)
  87{
  88        del_timer(&nr_sk(sk)->t1timer);
  89}
  90
  91void nr_stop_t2timer(struct sock *sk)
  92{
  93        del_timer(&nr_sk(sk)->t2timer);
  94}
  95
  96void nr_stop_t4timer(struct sock *sk)
  97{
  98        del_timer(&nr_sk(sk)->t4timer);
  99}
 100
 101void nr_stop_idletimer(struct sock *sk)
 102{
 103        del_timer(&nr_sk(sk)->idletimer);
 104}
 105
 106void nr_stop_heartbeat(struct sock *sk)
 107{
 108        del_timer(&sk->sk_timer);
 109}
 110
 111int nr_t1timer_running(struct sock *sk)
 112{
 113        return timer_pending(&nr_sk(sk)->t1timer);
 114}
 115
 116static void nr_heartbeat_expiry(unsigned long param)
 117{
 118        struct sock *sk = (struct sock *)param;
 119        struct nr_sock *nr = nr_sk(sk);
 120
 121        bh_lock_sock(sk);
 122        switch (nr->state) {
 123        case NR_STATE_0:
 124                /* Magic here: If we listen() and a new link dies before it
 125                   is accepted() it isn't 'dead' so doesn't get removed. */
 126                if (sock_flag(sk, SOCK_DESTROY) ||
 127                    (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) {
 128                        sock_hold(sk);
 129                        bh_unlock_sock(sk);
 130                        nr_destroy_socket(sk);
 131                        sock_put(sk);
 132                        return;
 133                }
 134                break;
 135
 136        case NR_STATE_3:
 137                /*
 138                 * Check for the state of the receive buffer.
 139                 */
 140                if (atomic_read(&sk->sk_rmem_alloc) < (sk->sk_rcvbuf / 2) &&
 141                    (nr->condition & NR_COND_OWN_RX_BUSY)) {
 142                        nr->condition &= ~NR_COND_OWN_RX_BUSY;
 143                        nr->condition &= ~NR_COND_ACK_PENDING;
 144                        nr->vl         = nr->vr;
 145                        nr_write_internal(sk, NR_INFOACK);
 146                        break;
 147                }
 148                break;
 149        }
 150
 151        nr_start_heartbeat(sk);
 152        bh_unlock_sock(sk);
 153}
 154
 155static void nr_t2timer_expiry(unsigned long param)
 156{
 157        struct sock *sk = (struct sock *)param;
 158        struct nr_sock *nr = nr_sk(sk);
 159
 160        bh_lock_sock(sk);
 161        if (nr->condition & NR_COND_ACK_PENDING) {
 162                nr->condition &= ~NR_COND_ACK_PENDING;
 163                nr_enquiry_response(sk);
 164        }
 165        bh_unlock_sock(sk);
 166}
 167
 168static void nr_t4timer_expiry(unsigned long param)
 169{
 170        struct sock *sk = (struct sock *)param;
 171
 172        bh_lock_sock(sk);
 173        nr_sk(sk)->condition &= ~NR_COND_PEER_RX_BUSY;
 174        bh_unlock_sock(sk);
 175}
 176
 177static void nr_idletimer_expiry(unsigned long param)
 178{
 179        struct sock *sk = (struct sock *)param;
 180        struct nr_sock *nr = nr_sk(sk);
 181
 182        bh_lock_sock(sk);
 183
 184        nr_clear_queues(sk);
 185
 186        nr->n2count = 0;
 187        nr_write_internal(sk, NR_DISCREQ);
 188        nr->state = NR_STATE_2;
 189
 190        nr_start_t1timer(sk);
 191        nr_stop_t2timer(sk);
 192        nr_stop_t4timer(sk);
 193
 194        sk->sk_state     = TCP_CLOSE;
 195        sk->sk_err       = 0;
 196        sk->sk_shutdown |= SEND_SHUTDOWN;
 197
 198        if (!sock_flag(sk, SOCK_DEAD)) {
 199                sk->sk_state_change(sk);
 200                sock_set_flag(sk, SOCK_DEAD);
 201        }
 202        bh_unlock_sock(sk);
 203}
 204
 205static void nr_t1timer_expiry(unsigned long param)
 206{
 207        struct sock *sk = (struct sock *)param;
 208        struct nr_sock *nr = nr_sk(sk);
 209
 210        bh_lock_sock(sk);
 211        switch (nr->state) {
 212        case NR_STATE_1:
 213                if (nr->n2count == nr->n2) {
 214                        nr_disconnect(sk, ETIMEDOUT);
 215                        bh_unlock_sock(sk);
 216                        return;
 217                } else {
 218                        nr->n2count++;
 219                        nr_write_internal(sk, NR_CONNREQ);
 220                }
 221                break;
 222
 223        case NR_STATE_2:
 224                if (nr->n2count == nr->n2) {
 225                        nr_disconnect(sk, ETIMEDOUT);
 226                        bh_unlock_sock(sk);
 227                        return;
 228                } else {
 229                        nr->n2count++;
 230                        nr_write_internal(sk, NR_DISCREQ);
 231                }
 232                break;
 233
 234        case NR_STATE_3:
 235                if (nr->n2count == nr->n2) {
 236                        nr_disconnect(sk, ETIMEDOUT);
 237                        bh_unlock_sock(sk);
 238                        return;
 239                } else {
 240                        nr->n2count++;
 241                        nr_requeue_frames(sk);
 242                }
 243                break;
 244        }
 245
 246        nr_start_t1timer(sk);
 247        bh_unlock_sock(sk);
 248}
 249
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.