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