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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [net/] [netrom/] [nr_out.c] - Blame information for rev 1765

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_out.c
14
 *      NET/ROM 003     Jonathan(G4KLX) Added NET/ROM fragmentation.
15
 *                      Darryl(G7LED)   Fixed NAK, to give out correct reponse.
16
 */
17
 
18
#include <linux/config.h>
19
#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
20
#include <linux/errno.h>
21
#include <linux/types.h>
22
#include <linux/socket.h>
23
#include <linux/in.h>
24
#include <linux/kernel.h>
25
#include <linux/sched.h>
26
#include <linux/timer.h>
27
#include <linux/string.h>
28
#include <linux/sockios.h>
29
#include <linux/net.h>
30
#include <net/ax25.h>
31
#include <linux/inet.h>
32
#include <linux/netdevice.h>
33
#include <linux/skbuff.h>
34
#include <net/sock.h>
35
#include <asm/segment.h>
36
#include <asm/system.h>
37
#include <linux/fcntl.h>
38
#include <linux/mm.h>
39
#include <linux/interrupt.h>
40
#include <net/netrom.h>
41
 
42
/*
43
 *      This is where all NET/ROM frames pass, except for IP-over-NET/ROM which
44
 *      cannot be fragmented in this manner.
45
 */
46
void nr_output(struct sock *sk, struct sk_buff *skb)
47
{
48
        struct sk_buff *skbn;
49
        unsigned char transport[NR_TRANSPORT_LEN];
50
        int err, frontlen, len;
51
 
52
        if (skb->len - NR_TRANSPORT_LEN > NR_MAX_PACKET_SIZE) {
53
                /* Save a copy of the Transport Header */
54
                memcpy(transport, skb->data, NR_TRANSPORT_LEN);
55
                skb_pull(skb, NR_TRANSPORT_LEN);
56
 
57
                frontlen = skb_headroom(skb);
58
 
59
                while (skb->len > 0) {
60
                        if ((skbn = sock_alloc_send_skb(sk, frontlen + NR_MAX_PACKET_SIZE, 0, 0, &err)) == NULL)
61
                                return;
62
 
63
                        skbn->sk   = sk;
64
                        skbn->free = 1;
65
 
66
                        skb_reserve(skbn, frontlen);
67
 
68
                        len = (NR_MAX_PACKET_SIZE > skb->len) ? skb->len : NR_MAX_PACKET_SIZE;
69
 
70
                        /* Copy the user data */
71
                        memcpy(skb_put(skbn, len), skb->data, len);
72
                        skb_pull(skb, len);
73
 
74
                        /* Duplicate the Transport Header */
75
                        skb_push(skbn, NR_TRANSPORT_LEN);
76
                        memcpy(skbn->data, transport, NR_TRANSPORT_LEN);
77
 
78
                        if (skb->len > 0)
79
                                skbn->data[4] |= NR_MORE_FLAG;
80
 
81
                        skb_queue_tail(&sk->write_queue, skbn); /* Throw it on the queue */
82
                }
83
 
84
                kfree_skb(skb, FREE_WRITE);
85
        } else {
86
                skb_queue_tail(&sk->write_queue, skb);          /* Throw it on the queue */
87
        }
88
 
89
        if (sk->protinfo.nr->state == NR_STATE_3)
90
                nr_kick(sk);
91
}
92
 
93
/*
94
 *      This procedure is passed a buffer descriptor for an iframe. It builds
95
 *      the rest of the control part of the frame and then writes it out.
96
 */
97
static void nr_send_iframe(struct sock *sk, struct sk_buff *skb)
98
{
99
        if (skb == NULL)
100
                return;
101
 
102
        skb->data[2] = sk->protinfo.nr->vs;
103
        skb->data[3] = sk->protinfo.nr->vr;
104
 
105
        if (sk->protinfo.nr->condition & NR_COND_OWN_RX_BUSY)
106
                skb->data[4] |= NR_CHOKE_FLAG;
107
 
108
        nr_transmit_buffer(sk, skb);
109
}
110
 
111
void nr_send_nak_frame(struct sock *sk)
112
{
113
        struct sk_buff *skb, *skbn;
114
 
115
        if ((skb = skb_peek(&sk->protinfo.nr->ack_queue)) == NULL)
116
                return;
117
 
118
        if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL)
119
                return;
120
 
121
        skbn->data[2] = sk->protinfo.nr->va;
122
        skbn->data[3] = sk->protinfo.nr->vr;
123
 
124
        if (sk->protinfo.nr->condition & NR_COND_OWN_RX_BUSY)
125
                skbn->data[4] |= NR_CHOKE_FLAG;
126
 
127
        nr_transmit_buffer(sk, skbn);
128
 
129
        sk->protinfo.nr->condition &= ~NR_COND_ACK_PENDING;
130
        sk->protinfo.nr->vl         = sk->protinfo.nr->vr;
131
        sk->protinfo.nr->t1timer    = 0;
132
}
133
 
134
void nr_kick(struct sock *sk)
135
{
136
        struct sk_buff *skb, *skbn;
137
        unsigned short start, end;
138
 
139
        del_timer(&sk->timer);
140
 
141
        start = (skb_peek(&sk->protinfo.nr->ack_queue) == NULL) ? sk->protinfo.nr->va : sk->protinfo.nr->vs;
142
        end   = (sk->protinfo.nr->va + sk->protinfo.nr->window) % NR_MODULUS;
143
 
144
        if (!(sk->protinfo.nr->condition & NR_COND_PEER_RX_BUSY) &&
145
            start != end                                         &&
146
            skb_peek(&sk->write_queue) != NULL) {
147
 
148
                sk->protinfo.nr->vs = start;
149
 
150
                /*
151
                 * Transmit data until either we're out of data to send or
152
                 * the window is full.
153
                 */
154
 
155
                /*
156
                 * Dequeue the frame and copy it.
157
                 */
158
                skb  = skb_dequeue(&sk->write_queue);
159
 
160
                do {
161
                        if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
162
                                skb_queue_head(&sk->write_queue, skb);
163
                                break;
164
                        }
165
 
166
                        skbn->sk = sk;
167
                        atomic_add(skbn->truesize, &sk->wmem_alloc);
168
 
169
                        /*
170
                         * Transmit the frame copy.
171
                         */
172
                        nr_send_iframe(sk, skbn);
173
 
174
                        sk->protinfo.nr->vs = (sk->protinfo.nr->vs + 1) % NR_MODULUS;
175
 
176
                        /*
177
                         * Requeue the original data frame.
178
                         */
179
                        skb_queue_tail(&sk->protinfo.nr->ack_queue, skb);
180
 
181
                } while (sk->protinfo.nr->vs != end && (skb = skb_dequeue(&sk->write_queue)) != NULL);
182
 
183
                sk->protinfo.nr->vl         = sk->protinfo.nr->vr;
184
                sk->protinfo.nr->condition &= ~NR_COND_ACK_PENDING;
185
 
186
                if (sk->protinfo.nr->t1timer == 0)
187
                        sk->protinfo.nr->t1timer = sk->protinfo.nr->t1;
188
        }
189
 
190
        nr_set_timer(sk);
191
}
192
 
193
void nr_transmit_buffer(struct sock *sk, struct sk_buff *skb)
194
{
195
        unsigned char *dptr;
196
 
197
        /*
198
         *      Add the protocol byte and network header.
199
         */
200
        dptr = skb_push(skb, NR_NETWORK_LEN);
201
 
202
        memcpy(dptr, &sk->protinfo.nr->source_addr, AX25_ADDR_LEN);
203
        dptr[6] &= ~AX25_CBIT;
204
        dptr[6] &= ~AX25_EBIT;
205
        dptr[6] |= AX25_SSSID_SPARE;
206
        dptr += AX25_ADDR_LEN;
207
 
208
        memcpy(dptr, &sk->protinfo.nr->dest_addr, AX25_ADDR_LEN);
209
        dptr[6] &= ~AX25_CBIT;
210
        dptr[6] |= AX25_EBIT;
211
        dptr[6] |= AX25_SSSID_SPARE;
212
        dptr += AX25_ADDR_LEN;
213
 
214
        *dptr++ = sysctl_netrom_network_ttl_initialiser;
215
 
216
        if (!nr_route_frame(skb, NULL))
217
                kfree_skb(skb, FREE_WRITE);
218
}
219
 
220
/*
221
 * The following routines are taken from page 170 of the 7th ARRL Computer
222
 * Networking Conference paper, as is the whole state machine.
223
 */
224
 
225
void nr_establish_data_link(struct sock *sk)
226
{
227
        sk->protinfo.nr->condition = 0x00;
228
        sk->protinfo.nr->n2count   = 0;
229
 
230
        nr_write_internal(sk, NR_CONNREQ);
231
 
232
        sk->protinfo.nr->t2timer = 0;
233
        sk->protinfo.nr->t1timer = sk->protinfo.nr->t1;
234
}
235
 
236
/*
237
 * Never send a NAK when we are CHOKEd.
238
 */
239
void nr_enquiry_response(struct sock *sk)
240
{
241
        int frametype = NR_INFOACK;
242
 
243
        if (sk->protinfo.nr->condition & NR_COND_OWN_RX_BUSY) {
244
                frametype |= NR_CHOKE_FLAG;
245
        } else {
246
                if (skb_peek(&sk->protinfo.nr->reseq_queue) != NULL)
247
                        frametype |= NR_NAK_FLAG;
248
        }
249
 
250
        nr_write_internal(sk, frametype);
251
 
252
        sk->protinfo.nr->vl         = sk->protinfo.nr->vr;
253
        sk->protinfo.nr->condition &= ~NR_COND_ACK_PENDING;
254
}
255
 
256
void nr_check_iframes_acked(struct sock *sk, unsigned short nr)
257
{
258
        if (sk->protinfo.nr->vs == nr) {
259
                nr_frames_acked(sk, nr);
260
                sk->protinfo.nr->t1timer = 0;
261
                sk->protinfo.nr->n2count = 0;
262
        } else {
263
                if (sk->protinfo.nr->va != nr) {
264
                        nr_frames_acked(sk, nr);
265
                        sk->protinfo.nr->t1timer = sk->protinfo.nr->t1;
266
                }
267
        }
268
}
269
 
270
#endif

powered by: WebSVN 2.1.0

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