OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [net/] [rose/] [rose_in.c] - Blame information for rev 199

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
 *      ROSE release 003
3
 *
4
 *      This code REQUIRES 2.1.0 or higher/ NET3.029
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
 *      Most of this code is based on the SDL diagrams published in the 7th
13
 *      ARRL Computer Networking Conference papers. The diagrams have mistakes
14
 *      in them, but are mostly correct. Before you modify the code could you
15
 *      read the SDL diagrams as the code is not obvious and probably very
16
 *      easy to break;
17
 *
18
 *      History
19
 *      ROSE 001        Jonathan(G4KLX) Cloned from nr_in.c
20
 */
21
 
22
#include <linux/config.h>
23
#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE)
24
#include <linux/errno.h>
25
#include <linux/types.h>
26
#include <linux/socket.h>
27
#include <linux/in.h>
28
#include <linux/kernel.h>
29
#include <linux/sched.h>
30
#include <linux/timer.h>
31
#include <linux/string.h>
32
#include <linux/sockios.h>
33
#include <linux/net.h>
34
#include <net/ax25.h>
35
#include <linux/inet.h>
36
#include <linux/netdevice.h>
37
#include <linux/skbuff.h>
38
#include <net/sock.h>
39
#include <net/ip.h>                     /* For ip_rcv */
40
#include <asm/segment.h>
41
#include <asm/system.h>
42
#include <linux/fcntl.h>
43
#include <linux/mm.h>
44
#include <linux/interrupt.h>
45
#include <net/rose.h>
46
 
47
static int rose_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more)
48
{
49
        struct sk_buff *skbo, *skbn = skb;
50
 
51
        if (more) {
52
                sk->protinfo.rose->fraglen += skb->len;
53
                skb_queue_tail(&sk->protinfo.rose->frag_queue, skb);
54
                return 0;
55
        }
56
 
57
        if (!more && sk->protinfo.rose->fraglen > 0) {   /* End of fragment */
58
                sk->protinfo.rose->fraglen += skb->len;
59
                skb_queue_tail(&sk->protinfo.rose->frag_queue, skb);
60
 
61
                if ((skbn = alloc_skb(sk->protinfo.rose->fraglen, GFP_ATOMIC)) == NULL)
62
                        return 1;
63
 
64
                skbn->free = 1;
65
                skbn->arp  = 1;
66
                skbn->sk   = sk;
67
                skbn->h.raw = skbn->data;
68
 
69
                skbo = skb_dequeue(&sk->protinfo.rose->frag_queue);
70
                memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
71
                kfree_skb(skbo, FREE_READ);
72
 
73
                while ((skbo = skb_dequeue(&sk->protinfo.rose->frag_queue)) != NULL) {
74
                        skb_pull(skbo, ROSE_MIN_LEN);
75
                        memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
76
                        kfree_skb(skbo, FREE_READ);
77
                }
78
 
79
                sk->protinfo.rose->fraglen = 0;
80
        }
81
 
82
        /* printk("FBB : lg=%ld\n", skbn->len); */
83
        return sock_queue_rcv_skb(sk, skbn);
84
}
85
 
86
/*
87
 * State machine for state 1, Awaiting Call Accepted State.
88
 * The handling of the timer(s) is in file rose_timer.c.
89
 * Handling of state 0 and connection release is in af_rose.c.
90
 */
91
static int rose_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype)
92
{
93
        int len;
94
 
95
        switch (frametype) {
96
 
97
                case ROSE_CALL_ACCEPTED:
98
                        sk->protinfo.rose->condition = 0x00;
99
                        sk->protinfo.rose->timer     = 0;
100
                        sk->protinfo.rose->vs        = 0;
101
                        sk->protinfo.rose->va        = 0;
102
                        sk->protinfo.rose->vr        = 0;
103
                        sk->protinfo.rose->vl        = 0;
104
                        sk->protinfo.rose->state     = ROSE_STATE_3;
105
                        sk->state                    = TCP_ESTABLISHED;
106
                        if (!sk->dead)
107
                                sk->state_change(sk);
108
                        break;
109
 
110
                case ROSE_CLEAR_REQUEST:
111
                        rose_clear_queues(sk);
112
                        rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION);
113
                        sk->protinfo.rose->neighbour->use--;
114
                        sk->protinfo.rose->cause      = skb->data[3];
115
                        sk->protinfo.rose->diagnostic = skb->data[4];
116
                        sk->protinfo.rose->state = ROSE_STATE_0;
117
                        sk->state                = TCP_CLOSE;
118
                        sk->err                  = ECONNREFUSED;
119
                        sk->shutdown            |= SEND_SHUTDOWN;
120
                        if (!sk->dead)
121
                                sk->state_change(sk);
122
                        sk->dead                 = 1;
123
                        len = 5;        /* Minimum size of the frame data */
124
                        if (skb->len > len) {
125
                                /* Address block */
126
                                len += 1;
127
                                len += (((skb->data[5] >> 4) & 0x0F) + 1) / 2;
128
                                len += (((skb->data[5] >> 0) & 0x0F) + 1) / 2;
129
 
130
                                if (skb->len > len) {
131
                                        /* Facilities */
132
                                        rose_parse_facilities(skb->data + len, &sk->protinfo.rose->facilities);
133
                                }
134
                        }
135
                        break;
136
 
137
                default:
138
                        break;
139
        }
140
 
141
        return 0;
142
}
143
 
144
/*
145
 * State machine for state 2, Awaiting Clear Confirmation State.
146
 * The handling of the timer(s) is in file rose_timer.c
147
 * Handling of state 0 and connection release is in af_rose.c.
148
 */
149
static int rose_state2_machine(struct sock *sk, struct sk_buff *skb, int frametype)
150
{
151
        int len;
152
 
153
        switch (frametype) {
154
 
155
                case ROSE_CLEAR_REQUEST:
156
                        rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION);
157
                        sk->protinfo.rose->cause      = skb->data[3];
158
                        sk->protinfo.rose->diagnostic = skb->data[4];
159
                        len = 5;
160
                        if (skb->len > len) {
161
                                /* Address block */
162
                                len += 1;
163
                                len += (((skb->data[5] >> 4) & 0x0F) + 1) / 2;
164
                                len += (((skb->data[5] >> 0) & 0x0F) + 1) / 2;
165
 
166
                                if (skb->len > len) {
167
                                        /* Facilities */
168
                                        rose_parse_facilities(skb->data + len, &sk->protinfo.rose->facilities);
169
                                }
170
                        }
171
                        /* fall in next case ... */
172
                case ROSE_CLEAR_CONFIRMATION:
173
                        rose_clear_queues(sk);
174
                        sk->protinfo.rose->neighbour->use--;
175
                        sk->protinfo.rose->state = ROSE_STATE_0;
176
                        sk->state                = TCP_CLOSE;
177
                        sk->err                  = 0;
178
                        sk->shutdown            |= SEND_SHUTDOWN;
179
                        if (!sk->dead)
180
                                sk->state_change(sk);
181
                        sk->dead                 = 1;
182
                        break;
183
 
184
                default:
185
                        break;
186
        }
187
 
188
        return 0;
189
}
190
 
191
/*
192
 * State machine for state 3, Connected State.
193
 * The handling of the timer(s) is in file rose_timer.c
194
 * Handling of state 0 and connection release is in af_rose.c.
195
 */
196
static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype, int ns, int nr, int q, int d, int m)
197
{
198
        int queued = 0;
199
        int len;
200
 
201
        switch (frametype) {
202
 
203
                case ROSE_RESET_REQUEST:
204
                        rose_write_internal(sk, ROSE_RESET_CONFIRMATION);
205
                        sk->protinfo.rose->condition = 0x00;
206
                        sk->protinfo.rose->timer     = 0;
207
                        sk->protinfo.rose->vs        = 0;
208
                        sk->protinfo.rose->vr        = 0;
209
                        sk->protinfo.rose->va        = 0;
210
                        sk->protinfo.rose->vl        = 0;
211
                        break;
212
 
213
                case ROSE_CLEAR_REQUEST:
214
                        rose_clear_queues(sk);
215
                        rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION);
216
                        sk->protinfo.rose->neighbour->use--;
217
                        sk->protinfo.rose->cause      = skb->data[3];
218
                        sk->protinfo.rose->diagnostic = skb->data[4];
219
                        sk->protinfo.rose->state = ROSE_STATE_0;
220
                        sk->state                = TCP_CLOSE;
221
                        sk->err                  = 0;
222
                        sk->shutdown            |= SEND_SHUTDOWN;
223
                        if (!sk->dead)
224
                                sk->state_change(sk);
225
                        sk->dead                 = 1;
226
                        len = 5;
227
                        if (skb->len > len) {
228
                                /* Address block */
229
                                len += 1;
230
                                len += (((skb->data[5] >> 4) & 0x0F) + 1) / 2;
231
                                len += (((skb->data[5] >> 0) & 0x0F) + 1) / 2;
232
 
233
                                if (skb->len > len) {
234
                                        /* Facilities */
235
                                        rose_parse_facilities(skb->data + len, &sk->protinfo.rose->facilities);
236
                                }
237
                        }
238
                        break;
239
 
240
                case ROSE_RR:
241
                case ROSE_RNR:
242
                        if (!rose_validate_nr(sk, nr)) {
243
                                rose_clear_queues(sk);
244
                                rose_write_internal(sk, ROSE_RESET_REQUEST);
245
                                sk->protinfo.rose->condition = 0x00;
246
                                sk->protinfo.rose->vs        = 0;
247
                                sk->protinfo.rose->vr        = 0;
248
                                sk->protinfo.rose->va        = 0;
249
                                sk->protinfo.rose->vl        = 0;
250
                                sk->protinfo.rose->state     = ROSE_STATE_4;
251
                                sk->protinfo.rose->timer     = sk->protinfo.rose->t2;
252
                        } else {
253
                                rose_frames_acked(sk, nr);
254
                                /* F6FBB : only set the flag ! */
255
                                if (frametype == ROSE_RNR)
256
                                        sk->protinfo.rose->condition |= ROSE_COND_PEER_RX_BUSY;
257
                                else {
258
                                        sk->protinfo.rose->condition &= ~ROSE_COND_PEER_RX_BUSY;
259
                                }
260
                        }
261
                        break;
262
 
263
                case ROSE_DATA: /* XXX */
264
                        sk->protinfo.rose->condition &= ~ROSE_COND_PEER_RX_BUSY;
265
                        if (!rose_validate_nr(sk, nr)) {
266
                                rose_clear_queues(sk);
267
                                rose_write_internal(sk, ROSE_RESET_REQUEST);
268
                                sk->protinfo.rose->condition = 0x00;
269
                                sk->protinfo.rose->vs        = 0;
270
                                sk->protinfo.rose->vr        = 0;
271
                                sk->protinfo.rose->va        = 0;
272
                                sk->protinfo.rose->vl        = 0;
273
                                sk->protinfo.rose->state     = ROSE_STATE_4;
274
                                sk->protinfo.rose->timer     = sk->protinfo.rose->t2;
275
                                break;
276
                        }
277
                        rose_frames_acked(sk, nr);
278
                        if (ns == sk->protinfo.rose->vr) {
279
                                if (rose_queue_rx_frame(sk, skb, m) == 0) {
280
                                        sk->protinfo.rose->vr = (sk->protinfo.rose->vr + 1) % ROSE_MODULUS;
281
                                        queued = 1;
282
                                } else {
283
                                        /* should never happen ! */
284
                                        rose_clear_queues(sk);
285
                                        rose_write_internal(sk, ROSE_RESET_REQUEST);
286
                                        sk->protinfo.rose->condition = 0x00;
287
                                        sk->protinfo.rose->vs        = 0;
288
                                        sk->protinfo.rose->vr        = 0;
289
                                        sk->protinfo.rose->va        = 0;
290
                                        sk->protinfo.rose->vl        = 0;
291
                                        sk->protinfo.rose->state     = ROSE_STATE_4;
292
                                        sk->protinfo.rose->timer     = sk->protinfo.rose->t2;
293
                                        break;
294
                                }
295
                                /* F6FBB : check if room enough for a full window */
296
                                if (sk->rmem_alloc > (sk->rcvbuf - ROSE_MAX_WINDOW_LEN)) {
297
                                        sk->protinfo.rose->condition |= ROSE_COND_OWN_RX_BUSY;
298
                                }
299
                        }
300
                        /*
301
                         * If the window is full, ack the frame, else start the
302
                         * acknowledge hold back timer.
303
                         */
304
                        if (((sk->protinfo.rose->vl + sysctl_rose_window_size) % ROSE_MODULUS) == sk->protinfo.rose->vr) {
305
                                sk->protinfo.rose->condition &= ~ROSE_COND_ACK_PENDING;
306
                                sk->protinfo.rose->timer      = 0;
307
                                rose_enquiry_response(sk);
308
                        } else {
309
                                sk->protinfo.rose->condition |= ROSE_COND_ACK_PENDING;
310
                                sk->protinfo.rose->timer      = sk->protinfo.rose->hb;
311
                        }
312
                        break;
313
 
314
                default:
315
                        printk(KERN_WARNING "rose: unknown %02X in state 3\n", frametype);
316
                        break;
317
        }
318
 
319
        return queued;
320
}
321
 
322
/*
323
 * State machine for state 4, Awaiting Reset Confirmation State.
324
 * The handling of the timer(s) is in file rose_timer.c
325
 * Handling of state 0 and connection release is in af_rose.c.
326
 */
327
static int rose_state4_machine(struct sock *sk, struct sk_buff *skb, int frametype)
328
{
329
        int len;
330
 
331
        switch (frametype) {
332
 
333
                case ROSE_RESET_REQUEST:
334
                        rose_write_internal(sk, ROSE_RESET_CONFIRMATION);
335
                case ROSE_RESET_CONFIRMATION:
336
                        sk->protinfo.rose->timer     = 0;
337
                        sk->protinfo.rose->condition = 0x00;
338
                        sk->protinfo.rose->va        = 0;
339
                        sk->protinfo.rose->vr        = 0;
340
                        sk->protinfo.rose->vs        = 0;
341
                        sk->protinfo.rose->vl        = 0;
342
                        sk->protinfo.rose->state     = ROSE_STATE_3;
343
                        break;
344
 
345
                case ROSE_CLEAR_REQUEST:
346
                        rose_clear_queues(sk);
347
                        rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION);
348
                        sk->protinfo.rose->neighbour->use--;
349
                        sk->protinfo.rose->cause      = skb->data[3];
350
                        sk->protinfo.rose->diagnostic = skb->data[4];
351
                        sk->protinfo.rose->timer = 0;
352
                        sk->protinfo.rose->state = ROSE_STATE_0;
353
                        sk->state                = TCP_CLOSE;
354
                        sk->err                  = 0;
355
                        sk->shutdown            |= SEND_SHUTDOWN;
356
                        if (!sk->dead)
357
                                sk->state_change(sk);
358
                        sk->dead                 = 1;
359
                        len = 5;
360
                        if (skb->len > len) {
361
                                /* Address block */
362
                                len += 1;
363
                                len += (((skb->data[5] >> 4) & 0x0F) + 1) / 2;
364
                                len += (((skb->data[5] >> 0) & 0x0F) + 1) / 2;
365
 
366
                                if (skb->len > len) {
367
                                        /* Facilities */
368
                                        rose_parse_facilities(skb->data + len, &sk->protinfo.rose->facilities);
369
                                }
370
                        }
371
                        break;
372
 
373
                default:
374
                        break;
375
        }
376
 
377
        return 0;
378
}
379
 
380
/*
381
 * State machine for state 5, Awaiting Call Acceptance State.
382
 * The handling of the timer(s) is in file rose_timer.c
383
 * Handling of state 0 and connection release is in af_rose.c.
384
 */
385
static int rose_state5_machine(struct sock *sk, struct sk_buff *skb, int frametype)
386
{
387
        int len;
388
 
389
        switch (frametype) {
390
 
391
                case ROSE_CLEAR_REQUEST:
392
                        rose_clear_queues(sk);
393
                        rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION);
394
                        sk->protinfo.rose->neighbour->use--;
395
                        sk->protinfo.rose->cause      = skb->data[3];
396
                        sk->protinfo.rose->diagnostic = skb->data[4];
397
                        sk->protinfo.rose->state = ROSE_STATE_0;
398
                        sk->state                = TCP_CLOSE;
399
                        sk->err                  = 0;
400
                        sk->shutdown            |= SEND_SHUTDOWN;
401
                        if (!sk->dead)
402
                                sk->state_change(sk);
403
                        sk->dead                 = 1;
404
                        len = 5;
405
                        if (skb->len > len) {
406
                                /* Address block */
407
                                len += 1;
408
                                len += (((skb->data[5] >> 4) & 0x0F) + 1) / 2;
409
                                len += (((skb->data[5] >> 0) & 0x0F) + 1) / 2;
410
 
411
                                if (skb->len > len) {
412
                                        /* Facilities */
413
                                        rose_parse_facilities(skb->data + len, &sk->protinfo.rose->facilities);
414
                                }
415
                        }
416
                        break;
417
        }
418
 
419
        return 0;
420
}
421
 
422
/* Higher level upcall for a LAPB frame */
423
int rose_process_rx_frame(struct sock *sk, struct sk_buff *skb)
424
{
425
        int queued = 0, frametype, ns, nr, q, d, m;
426
 
427
        if (sk->protinfo.rose->state == ROSE_STATE_0)
428
                return 0;
429
 
430
        del_timer(&sk->timer);
431
 
432
        frametype = rose_decode(skb, &ns, &nr, &q, &d, &m);
433
 
434
        switch (sk->protinfo.rose->state) {
435
                case ROSE_STATE_1:
436
                        queued = rose_state1_machine(sk, skb, frametype);
437
                        break;
438
                case ROSE_STATE_2:
439
                        queued = rose_state2_machine(sk, skb, frametype);
440
                        break;
441
                case ROSE_STATE_3:
442
                        queued = rose_state3_machine(sk, skb, frametype, ns, nr, q, d, m);
443
                        break;
444
                case ROSE_STATE_4:
445
                        queued = rose_state4_machine(sk, skb, frametype);
446
                        break;
447
                case ROSE_STATE_5:
448
                        queued = rose_state5_machine(sk, skb, frametype);
449
                        break;
450
        }
451
 
452
        rose_set_timer(sk);
453
 
454
        return queued;
455
}
456
 
457
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.