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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [uclinux/] [uClinux-2.0.x/] [net/] [netrom/] [nr_subr.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
 *      NET/ROM release 006
3
 *
4
 *      This code REQUIRES 1.2.1 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
 *      History
13
 *      NET/ROM 001     Jonathan(G4KLX) Cloned from ax25_subr.c
14
 *      NET/ROM 003     Jonathan(G4KLX) Added G8BPQ NET/ROM extensions.
15
 */
16
 
17
#include <linux/config.h>
18
#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
19
#include <linux/errno.h>
20
#include <linux/types.h>
21
#include <linux/socket.h>
22
#include <linux/in.h>
23
#include <linux/kernel.h>
24
#include <linux/sched.h>
25
#include <linux/timer.h>
26
#include <linux/string.h>
27
#include <linux/sockios.h>
28
#include <linux/net.h>
29
#include <net/ax25.h>
30
#include <linux/inet.h>
31
#include <linux/netdevice.h>
32
#include <linux/skbuff.h>
33
#include <net/sock.h>
34
#include <asm/segment.h>
35
#include <asm/system.h>
36
#include <linux/fcntl.h>
37
#include <linux/mm.h>
38
#include <linux/interrupt.h>
39
#include <net/netrom.h>
40
 
41
/*
42
 *      This routine purges all of the queues of frames.
43
 */
44
void nr_clear_queues(struct sock *sk)
45
{
46
        struct sk_buff *skb;
47
 
48
        while ((skb = skb_dequeue(&sk->write_queue)) != NULL)
49
                kfree_skb(skb, FREE_WRITE);
50
 
51
        while ((skb = skb_dequeue(&sk->protinfo.nr->ack_queue)) != NULL)
52
                kfree_skb(skb, FREE_WRITE);
53
 
54
        while ((skb = skb_dequeue(&sk->protinfo.nr->reseq_queue)) != NULL)
55
                kfree_skb(skb, FREE_READ);
56
 
57
        while ((skb = skb_dequeue(&sk->protinfo.nr->frag_queue)) != NULL)
58
                kfree_skb(skb, FREE_READ);
59
}
60
 
61
/*
62
 * This routine purges the input queue of those frames that have been
63
 * acknowledged. This replaces the boxes labelled "V(a) <- N(r)" on the
64
 * SDL diagram.
65
 */
66
void nr_frames_acked(struct sock *sk, unsigned short nr)
67
{
68
        struct sk_buff *skb;
69
 
70
        /*
71
         * Remove all the ack-ed frames from the ack queue.
72
         */
73
        if (sk->protinfo.nr->va != nr) {
74
                while (skb_peek(&sk->protinfo.nr->ack_queue) != NULL && sk->protinfo.nr->va != nr) {
75
                        skb = skb_dequeue(&sk->protinfo.nr->ack_queue);
76
                        kfree_skb(skb, FREE_WRITE);
77
                        sk->protinfo.nr->va = (sk->protinfo.nr->va + 1) % NR_MODULUS;
78
                }
79
        }
80
}
81
 
82
/*
83
 * Requeue all the un-ack-ed frames on the output queue to be picked
84
 * up by nr_kick called from the timer. This arrangement handles the
85
 * possibility of an empty output queue.
86
 */
87
void nr_requeue_frames(struct sock *sk)
88
{
89
        struct sk_buff *skb, *skb_prev = NULL;
90
 
91
        while ((skb = skb_dequeue(&sk->protinfo.nr->ack_queue)) != NULL) {
92
                if (skb_prev == NULL)
93
                        skb_queue_head(&sk->write_queue, skb);
94
                else
95
                        skb_append(skb_prev, skb);
96
                skb_prev = skb;
97
        }
98
}
99
 
100
/*
101
 *      Validate that the value of nr is between va and vs. Return true or
102
 *      false for testing.
103
 */
104
int nr_validate_nr(struct sock *sk, unsigned short nr)
105
{
106
        unsigned short vc = sk->protinfo.nr->va;
107
 
108
        while (vc != sk->protinfo.nr->vs) {
109
                if (nr == vc) return 1;
110
                vc = (vc + 1) % NR_MODULUS;
111
        }
112
 
113
        if (nr == sk->protinfo.nr->vs) return 1;
114
 
115
        return 0;
116
}
117
 
118
/*
119
 *      Check that ns is within the receive window.
120
 */
121
int nr_in_rx_window(struct sock *sk, unsigned short ns)
122
{
123
        unsigned short vc = sk->protinfo.nr->vr;
124
        unsigned short vt = (sk->protinfo.nr->vl + sk->protinfo.nr->window) % NR_MODULUS;
125
 
126
        while (vc != vt) {
127
                if (ns == vc) return 1;
128
                vc = (vc + 1) % NR_MODULUS;
129
        }
130
 
131
        return 0;
132
}
133
 
134
/*
135
 *  This routine is called when the HDLC layer internally generates a
136
 *  control frame.
137
 */
138
void nr_write_internal(struct sock *sk, int frametype)
139
{
140
        struct sk_buff *skb;
141
        unsigned char  *dptr;
142
        int len, timeout;
143
 
144
        len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + NR_NETWORK_LEN + NR_TRANSPORT_LEN;
145
 
146
        switch (frametype & 0x0F) {
147
                case NR_CONNREQ:
148
                        len += 17;
149
                        break;
150
                case NR_CONNACK:
151
                        len += (sk->protinfo.nr->bpqext) ? 2 : 1;
152
                        break;
153
                case NR_DISCREQ:
154
                case NR_DISCACK:
155
                case NR_INFOACK:
156
                        break;
157
                default:
158
                        printk(KERN_ERR "nr_write_internal: invalid frame type %d\n", frametype);
159
                        return;
160
        }
161
 
162
        if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL)
163
                return;
164
 
165
        skb->free = 1;
166
 
167
        /*
168
         *      Space for AX.25 and NET/ROM network header
169
         */
170
        skb_reserve(skb, AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + NR_NETWORK_LEN);
171
 
172
        dptr = skb_put(skb, skb_tailroom(skb));
173
 
174
        switch (frametype & 0x0F) {
175
 
176
                case NR_CONNREQ:
177
                        timeout  = sk->protinfo.nr->t1 / NR_SLOWHZ;
178
                        *dptr++  = sk->protinfo.nr->my_index;
179
                        *dptr++  = sk->protinfo.nr->my_id;
180
                        *dptr++  = 0;
181
                        *dptr++  = 0;
182
                        *dptr++  = frametype;
183
                        *dptr++  = sk->protinfo.nr->window;
184
                        memcpy(dptr, &sk->protinfo.nr->user_addr, AX25_ADDR_LEN);
185
                        dptr[6] &= ~AX25_CBIT;
186
                        dptr[6] &= ~AX25_EBIT;
187
                        dptr[6] |= AX25_SSSID_SPARE;
188
                        dptr    += AX25_ADDR_LEN;
189
                        memcpy(dptr, &sk->protinfo.nr->source_addr, AX25_ADDR_LEN);
190
                        dptr[6] &= ~AX25_CBIT;
191
                        dptr[6] &= ~AX25_EBIT;
192
                        dptr[6] |= AX25_SSSID_SPARE;
193
                        dptr    += AX25_ADDR_LEN;
194
                        *dptr++  = timeout % 256;
195
                        *dptr++  = timeout / 256;
196
                        break;
197
 
198
                case NR_CONNACK:
199
                        *dptr++ = sk->protinfo.nr->your_index;
200
                        *dptr++ = sk->protinfo.nr->your_id;
201
                        *dptr++ = sk->protinfo.nr->my_index;
202
                        *dptr++ = sk->protinfo.nr->my_id;
203
                        *dptr++ = frametype;
204
                        *dptr++ = sk->protinfo.nr->window;
205
                        if (sk->protinfo.nr->bpqext) *dptr++ = sysctl_netrom_network_ttl_initialiser;
206
                        break;
207
 
208
                case NR_DISCREQ:
209
                case NR_DISCACK:
210
                        *dptr++ = sk->protinfo.nr->your_index;
211
                        *dptr++ = sk->protinfo.nr->your_id;
212
                        *dptr++ = 0;
213
                        *dptr++ = 0;
214
                        *dptr++ = frametype;
215
                        break;
216
 
217
                case NR_INFOACK:
218
                        *dptr++ = sk->protinfo.nr->your_index;
219
                        *dptr++ = sk->protinfo.nr->your_id;
220
                        *dptr++ = 0;
221
                        *dptr++ = sk->protinfo.nr->vr;
222
                        *dptr++ = frametype;
223
                        break;
224
        }
225
 
226
        nr_transmit_buffer(sk, skb);
227
}
228
 
229
/*
230
 * This routine is called when a Connect Acknowledge with the Choke Flag
231
 * set is needed to refuse a connection.
232
 * If 'my' is set, send the "reset" using our circuit ID.
233
 */
234
void nr_transmit_dm(struct sk_buff *skb, int my)
235
{
236
        struct sk_buff *skbn;
237
        unsigned char *dptr;
238
        int len;
239
 
240
        len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + NR_NETWORK_LEN + NR_TRANSPORT_LEN + 1;
241
 
242
        if ((skbn = alloc_skb(len, GFP_ATOMIC)) == NULL)
243
                return;
244
 
245
        skbn->free = 1;
246
 
247
        skb_reserve(skbn, AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN);
248
 
249
        dptr = skb_put(skbn, NR_NETWORK_LEN + NR_TRANSPORT_LEN);
250
 
251
        memcpy(dptr, skb->data + 7, AX25_ADDR_LEN);
252
        dptr[6] &= ~AX25_CBIT;
253
        dptr[6] &= ~AX25_EBIT;
254
        dptr[6] |= AX25_SSSID_SPARE;
255
        dptr += AX25_ADDR_LEN;
256
 
257
        memcpy(dptr, skb->data + 0, AX25_ADDR_LEN);
258
        dptr[6] &= ~AX25_CBIT;
259
        dptr[6] |= AX25_EBIT;
260
        dptr[6] |= AX25_SSSID_SPARE;
261
        dptr += AX25_ADDR_LEN;
262
 
263
        *dptr++ = sysctl_netrom_network_ttl_initialiser;
264
 
265
        if (my) {
266
                *dptr++ = 0;
267
                *dptr++ = 0;
268
                *dptr++ = skb->data[15];
269
                *dptr++ = skb->data[16];
270
        } else {
271
                *dptr++ = skb->data[15];
272
                *dptr++ = skb->data[16];
273
                *dptr++ = 0;
274
                *dptr++ = 0;
275
        }
276
 
277
        *dptr++ = NR_CONNACK | NR_CHOKE_FLAG;
278
        *dptr++ = 0;
279
 
280
        if (!nr_route_frame(skbn, NULL))
281
                kfree_skb(skbn, FREE_WRITE);
282
}
283
 
284
#endif

powered by: WebSVN 2.1.0

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