Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/rose/rose_timer.c
15109 views
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 ([email protected])
8
* Copyright (C) 2002 Ralf Baechle DO1GRB ([email protected])
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/system.h>
27
#include <linux/fcntl.h>
28
#include <linux/mm.h>
29
#include <linux/interrupt.h>
30
#include <net/rose.h>
31
32
static void rose_heartbeat_expiry(unsigned long);
33
static void rose_timer_expiry(unsigned long);
34
static void rose_idletimer_expiry(unsigned long);
35
36
void rose_start_heartbeat(struct sock *sk)
37
{
38
del_timer(&sk->sk_timer);
39
40
sk->sk_timer.data = (unsigned long)sk;
41
sk->sk_timer.function = &rose_heartbeat_expiry;
42
sk->sk_timer.expires = jiffies + 5 * HZ;
43
44
add_timer(&sk->sk_timer);
45
}
46
47
void rose_start_t1timer(struct sock *sk)
48
{
49
struct rose_sock *rose = rose_sk(sk);
50
51
del_timer(&rose->timer);
52
53
rose->timer.data = (unsigned long)sk;
54
rose->timer.function = &rose_timer_expiry;
55
rose->timer.expires = jiffies + rose->t1;
56
57
add_timer(&rose->timer);
58
}
59
60
void rose_start_t2timer(struct sock *sk)
61
{
62
struct rose_sock *rose = rose_sk(sk);
63
64
del_timer(&rose->timer);
65
66
rose->timer.data = (unsigned long)sk;
67
rose->timer.function = &rose_timer_expiry;
68
rose->timer.expires = jiffies + rose->t2;
69
70
add_timer(&rose->timer);
71
}
72
73
void rose_start_t3timer(struct sock *sk)
74
{
75
struct rose_sock *rose = rose_sk(sk);
76
77
del_timer(&rose->timer);
78
79
rose->timer.data = (unsigned long)sk;
80
rose->timer.function = &rose_timer_expiry;
81
rose->timer.expires = jiffies + rose->t3;
82
83
add_timer(&rose->timer);
84
}
85
86
void rose_start_hbtimer(struct sock *sk)
87
{
88
struct rose_sock *rose = rose_sk(sk);
89
90
del_timer(&rose->timer);
91
92
rose->timer.data = (unsigned long)sk;
93
rose->timer.function = &rose_timer_expiry;
94
rose->timer.expires = jiffies + rose->hb;
95
96
add_timer(&rose->timer);
97
}
98
99
void rose_start_idletimer(struct sock *sk)
100
{
101
struct rose_sock *rose = rose_sk(sk);
102
103
del_timer(&rose->idletimer);
104
105
if (rose->idle > 0) {
106
rose->idletimer.data = (unsigned long)sk;
107
rose->idletimer.function = &rose_idletimer_expiry;
108
rose->idletimer.expires = jiffies + rose->idle;
109
110
add_timer(&rose->idletimer);
111
}
112
}
113
114
void rose_stop_heartbeat(struct sock *sk)
115
{
116
del_timer(&sk->sk_timer);
117
}
118
119
void rose_stop_timer(struct sock *sk)
120
{
121
del_timer(&rose_sk(sk)->timer);
122
}
123
124
void rose_stop_idletimer(struct sock *sk)
125
{
126
del_timer(&rose_sk(sk)->idletimer);
127
}
128
129
static void rose_heartbeat_expiry(unsigned long param)
130
{
131
struct sock *sk = (struct sock *)param;
132
struct rose_sock *rose = rose_sk(sk);
133
134
bh_lock_sock(sk);
135
switch (rose->state) {
136
case ROSE_STATE_0:
137
/* Magic here: If we listen() and a new link dies before it
138
is accepted() it isn't 'dead' so doesn't get removed. */
139
if (sock_flag(sk, SOCK_DESTROY) ||
140
(sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) {
141
bh_unlock_sock(sk);
142
rose_destroy_socket(sk);
143
return;
144
}
145
break;
146
147
case ROSE_STATE_3:
148
/*
149
* Check for the state of the receive buffer.
150
*/
151
if (atomic_read(&sk->sk_rmem_alloc) < (sk->sk_rcvbuf / 2) &&
152
(rose->condition & ROSE_COND_OWN_RX_BUSY)) {
153
rose->condition &= ~ROSE_COND_OWN_RX_BUSY;
154
rose->condition &= ~ROSE_COND_ACK_PENDING;
155
rose->vl = rose->vr;
156
rose_write_internal(sk, ROSE_RR);
157
rose_stop_timer(sk); /* HB */
158
break;
159
}
160
break;
161
}
162
163
rose_start_heartbeat(sk);
164
bh_unlock_sock(sk);
165
}
166
167
static void rose_timer_expiry(unsigned long param)
168
{
169
struct sock *sk = (struct sock *)param;
170
struct rose_sock *rose = rose_sk(sk);
171
172
bh_lock_sock(sk);
173
switch (rose->state) {
174
case ROSE_STATE_1: /* T1 */
175
case ROSE_STATE_4: /* T2 */
176
rose_write_internal(sk, ROSE_CLEAR_REQUEST);
177
rose->state = ROSE_STATE_2;
178
rose_start_t3timer(sk);
179
break;
180
181
case ROSE_STATE_2: /* T3 */
182
rose->neighbour->use--;
183
rose_disconnect(sk, ETIMEDOUT, -1, -1);
184
break;
185
186
case ROSE_STATE_3: /* HB */
187
if (rose->condition & ROSE_COND_ACK_PENDING) {
188
rose->condition &= ~ROSE_COND_ACK_PENDING;
189
rose_enquiry_response(sk);
190
}
191
break;
192
}
193
bh_unlock_sock(sk);
194
}
195
196
static void rose_idletimer_expiry(unsigned long param)
197
{
198
struct sock *sk = (struct sock *)param;
199
200
bh_lock_sock(sk);
201
rose_clear_queues(sk);
202
203
rose_write_internal(sk, ROSE_CLEAR_REQUEST);
204
rose_sk(sk)->state = ROSE_STATE_2;
205
206
rose_start_t3timer(sk);
207
208
sk->sk_state = TCP_CLOSE;
209
sk->sk_err = 0;
210
sk->sk_shutdown |= SEND_SHUTDOWN;
211
212
if (!sock_flag(sk, SOCK_DEAD)) {
213
sk->sk_state_change(sk);
214
sock_set_flag(sk, SOCK_DEAD);
215
}
216
bh_unlock_sock(sk);
217
}
218
219