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

