This source file includes following definitions.
- nr_output
- nr_send_iframe
- nr_send_nak_frame
- nr_kick
- nr_transmit_buffer
- nr_nr_error_recovery
- nr_establish_data_link
- nr_enquiry_response
- nr_check_iframes_acked
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <linux/config.h>
20 #ifdef CONFIG_NETROM
21 #include <linux/errno.h>
22 #include <linux/types.h>
23 #include <linux/socket.h>
24 #include <linux/in.h>
25 #include <linux/kernel.h>
26 #include <linux/sched.h>
27 #include <linux/timer.h>
28 #include <linux/string.h>
29 #include <linux/sockios.h>
30 #include <linux/net.h>
31 #include <net/ax25.h>
32 #include <linux/inet.h>
33 #include <linux/netdevice.h>
34 #include <linux/skbuff.h>
35 #include <net/sock.h>
36 #include <asm/segment.h>
37 #include <asm/system.h>
38 #include <linux/fcntl.h>
39 #include <linux/mm.h>
40 #include <linux/interrupt.h>
41 #include <net/netrom.h>
42
43 int nr_output(struct sock *sk, struct sk_buff *skb)
44 {
45 skb_queue_tail(&sk->write_queue, skb);
46
47 if (sk->nr->state == NR_STATE_3)
48 nr_kick(sk);
49
50 return 0;
51 }
52
53
54
55
56
57 static void nr_send_iframe(struct sock *sk, struct sk_buff *skb)
58 {
59 unsigned char *dptr;
60
61 if (skb == NULL)
62 return;
63
64 dptr = skb->data + 34;
65
66 *dptr++ = sk->nr->vs;
67 *dptr++ = sk->nr->vr;
68
69 nr_transmit_buffer(sk, skb);
70 }
71
72 void nr_send_nak_frame(struct sock *sk)
73 {
74 struct sk_buff *skb, *skbn;
75
76 if ((skb = skb_peek(&sk->nr->ack_queue)) == NULL)
77 return;
78
79 if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL)
80 return;
81
82 nr_send_iframe(sk, skbn);
83
84 sk->nr->condition &= ~ACK_PENDING_CONDITION;
85 sk->nr->vl = sk->nr->vr;
86 sk->nr->t1timer = 0;
87 }
88
89 void nr_kick(struct sock *sk)
90 {
91 struct sk_buff *skb, *skbn;
92 int last = 1;
93 unsigned short start, end, next;
94
95 del_timer(&sk->timer);
96
97 start = (skb_peek(&sk->nr->ack_queue) == NULL) ? sk->nr->va : sk->nr->vs;
98 end = (sk->nr->va + sk->window) % NR_MODULUS;
99
100 if (!(sk->nr->condition & PEER_RX_BUSY_CONDITION) &&
101 start != end &&
102 skb_peek(&sk->write_queue) != NULL) {
103
104 sk->nr->vs = start;
105
106
107
108
109
110 do {
111
112
113
114 skb = skb_dequeue(&sk->write_queue);
115
116 if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
117 skb_queue_head(&sk->write_queue, skb);
118 return;
119 }
120
121 next = (sk->nr->vs + 1) % NR_MODULUS;
122 last = (next == end);
123
124
125
126
127 nr_send_iframe(sk, skbn);
128
129 sk->nr->vs = next;
130
131
132
133
134 skb_queue_tail(&sk->nr->ack_queue, skb);
135
136 } while (!last && skb_peek(&sk->write_queue) != NULL);
137
138 sk->nr->vl = sk->nr->vr;
139 sk->nr->condition &= ~ACK_PENDING_CONDITION;
140
141 if (sk->nr->t1timer == 0) {
142 sk->nr->t1timer = sk->nr->t1 = nr_calculate_t1(sk);
143 }
144 }
145
146 nr_set_timer(sk);
147 }
148
149 void nr_transmit_buffer(struct sock *sk, struct sk_buff *skb)
150 {
151 unsigned char *dptr;
152
153 dptr = skb->data + 16;
154
155 *dptr++ = AX25_P_NETROM;
156
157 memcpy(dptr, &sk->nr->source_addr, sizeof(ax25_address));
158 dptr[6] &= ~LAPB_C;
159 dptr[6] &= ~LAPB_E;
160 dptr[6] |= SSID_SPARE;
161 dptr += 7;
162
163 memcpy(dptr, &sk->nr->dest_addr, sizeof(ax25_address));
164 dptr[6] &= ~LAPB_C;
165 dptr[6] |= LAPB_E;
166 dptr[6] |= SSID_SPARE;
167 dptr += 7;
168
169 *dptr++ = nr_default.ttl;
170
171 skb->arp = 1;
172
173 if (!nr_route_frame(skb, NULL)) {
174 kfree_skb(skb, FREE_WRITE);
175
176 sk->state = TCP_CLOSE;
177 sk->err = ENETUNREACH;
178 if (!sk->dead)
179 sk->state_change(sk);
180 sk->dead = 1;
181 }
182 }
183
184
185
186
187
188
189 void nr_nr_error_recovery(struct sock *sk)
190 {
191 nr_establish_data_link(sk);
192 }
193
194 void nr_establish_data_link(struct sock *sk)
195 {
196 sk->nr->condition = 0x00;
197 sk->nr->n2count = 0;
198
199 nr_write_internal(sk, NR_CONNREQ);
200
201 sk->nr->t2timer = 0;
202 sk->nr->t1timer = sk->nr->t1 = nr_calculate_t1(sk);
203 }
204
205
206
207
208 void nr_enquiry_response(struct sock *sk)
209 {
210 int frametype = NR_INFOACK;
211
212 if (sk->nr->condition & OWN_RX_BUSY_CONDITION) {
213 frametype += NR_CHOKE_FLAG;
214 } else {
215 if (skb_peek(&sk->nr->reseq_queue) != NULL) {
216 frametype += NR_NAK_FLAG;
217 }
218 }
219
220 nr_write_internal(sk, frametype);
221
222 sk->nr->vl = sk->nr->vr;
223 sk->nr->condition &= ~ACK_PENDING_CONDITION;
224 }
225
226 void nr_check_iframes_acked(struct sock *sk, unsigned short nr)
227 {
228 if (sk->nr->vs == nr) {
229 nr_frames_acked(sk, nr);
230 nr_requeue_frames(sk);
231 nr_calculate_rtt(sk);
232 sk->nr->t1timer = 0;
233 sk->nr->n2count = 0;
234 } else {
235 if (sk->nr->va != nr) {
236 nr_frames_acked(sk, nr);
237 nr_requeue_frames(sk);
238 sk->nr->t1timer = sk->nr->t1 = nr_calculate_t1(sk);
239 }
240 }
241 }
242
243 #endif