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 40 static void rose_heartbeat_expiry(unsigned long); 41 static void rose_timer_expiry(unsigned long); 42 static void rose_idletimer_expiry(unsigned long); 43 rose_start_heartbeat(struct sock * sk)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 rose_start_t1timer(struct sock * sk)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 rose_start_t2timer(struct sock * sk)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 rose_start_t3timer(struct sock * sk)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 rose_start_hbtimer(struct sock * sk)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 rose_start_idletimer(struct sock * sk)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 rose_stop_heartbeat(struct sock * sk)112void rose_stop_heartbeat(struct sock *sk) 113 { 114 del_timer(&sk->timer); 115 } 116 rose_stop_timer(struct sock * sk)117void rose_stop_timer(struct sock *sk) 118 { 119 del_timer(&sk->protinfo.rose->timer); 120 } 121 rose_stop_idletimer(struct sock * sk)122void rose_stop_idletimer(struct sock *sk) 123 { 124 del_timer(&sk->protinfo.rose->idletimer); 125 } 126 rose_heartbeat_expiry(unsigned long param)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 rose_timer_expiry(unsigned long param)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 rose_idletimer_expiry(unsigned long param)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