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
44 void 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
55 void 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
66 void 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
77 void 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
88 void 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
99 void 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
112 void rose_stop_heartbeat(struct sock *sk)
113 {
114 del_timer(&sk->timer);
115 }
116
117 void rose_stop_timer(struct sock *sk)
118 {
119 del_timer(&sk->protinfo.rose->timer);
120 }
121
122 void rose_stop_idletimer(struct sock *sk)
123 {
124 del_timer(&sk->protinfo.rose->idletimer);
125 }
126
127 static 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
161 static 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
188 static 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
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.