1 /*
2 * NET An implementation of the IEEE 802.2 LLC protocol for the
3 * LINUX operating system. LLC is implemented as a set of
4 * state machines and callbacks for higher networking layers.
5 *
6 * llc_sendpdu(), llc_sendipdu(), resend() + queue handling code
7 *
8 * Written by Tim Alpaerts, Tim_Alpaerts@toyota-motor-europe.com
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 *
15 * Changes
16 * Alan Cox : Chainsawed into Linux format, style
17 * Added llc_ to function names
18 */
19
20 #include <linux/types.h>
21 #include <linux/kernel.h>
22 #include <linux/slab.h>
23 #include <linux/netdevice.h>
24 #include <linux/skbuff.h>
25 #include <net/p8022.h>
26 #include <linux/stat.h>
27 #include <asm/byteorder.h>
28 #include <net/llc_frame.h>
29 #include <net/llc.h>
30
31 static unsigned char cntl_byte_encode[] =
32 {
33 0x00, /* I_CMD */
34 0x01, /* RR_CMD */
35 0x05, /* RNR_CMD */
36 0x09, /* REJ_CMD */
37 0x43, /* DISC_CMD */
38 0x7F, /* SABME_CMD */
39 0x00, /* I_RSP */
40 0x01, /* RR_RSP */
41 0x05, /* RNR_RSP */
42 0x09, /* REJ_RSP */
43 0x63, /* UA_RSP */
44 0x0F, /* DM_RSP */
45 0x87, /* FRMR_RSP */
46 0xFF, /* BAD_FRAME */
47 0x03, /* UI_CMD */
48 0xBF, /* XID_CMD */
49 0xE3, /* TEST_CMD */
50 0xBF, /* XID_RSP */
51 0xE3 /* TEST_RSP */
52 };
53
54 static unsigned char fr_length_encode[] =
55 {
56 0x04, /* I_CMD */
57 0x04, /* RR_CMD */
58 0x04, /* RNR_CMD */
59 0x04, /* REJ_CMD */
60 0x03, /* DISC_CMD */
61 0x03, /* SABME_CMD */
62 0x04, /* I_RSP */
63 0x04, /* RR_RSP */
64 0x04, /* RNR_RSP */
65 0x04, /* REJ_RSP */
66 0x03, /* UA_RSP */
67 0x03, /* DM_RSP */
68 0x03, /* FRMR_RSP */
69 0x00, /* BAD_FRAME */
70 0x03, /* UI_CMD */
71 0x03, /* XID_CMD */
72 0x03, /* TEST_CMD */
73 0x03, /* XID_RSP */
74 0x03 /* TEST_RSP */
75 };
76
77 static unsigned char cr_bit_encode[] = {
78 0x00, /* I_CMD */
79 0x00, /* RR_CMD */
80 0x00, /* RNR_CMD */
81 0x00, /* REJ_CMD */
82 0x00, /* DISC_CMD */
83 0x00, /* SABME_CMD */
84 0x01, /* I_RSP */
85 0x01, /* RR_RSP */
86 0x01, /* RNR_RSP */
87 0x01, /* REJ_RSP */
88 0x01, /* UA_RSP */
89 0x01, /* DM_RSP */
90 0x01, /* FRMR_RSP */
91 0x00, /* BAD_FRAME */
92 0x00, /* UI_CMD */
93 0x00, /* XID_CMD */
94 0x00, /* TEST_CMD */
95 0x01, /* XID_RSP */
96 0x01 /* TEST_RSP */
97 };
98
99 /*
100 * Sendpdu() constructs an output frame in a new skb and
101 * gives it to the MAC layer for transmission.
102 * This function is not used to send I pdus.
103 * No queues are updated here, nothing is saved for retransmission.
104 *
105 * Parameter pf controls both the poll/final bit and dsap
106 * fields in the output pdu.
107 * The dsap trick was needed to implement XID_CMD send with
108 * zero dsap field as described in doc 6.6 item 1 of enum.
109 */
110
llc_sendpdu(llcptr lp,char type,char pf,int data_len,char * pdu_data)111 void llc_sendpdu(llcptr lp, char type, char pf, int data_len, char *pdu_data)
112 {
113 frameptr fr; /* ptr to output pdu buffer */
114 unsigned short int fl; /* frame length == 802.3 "length" value */
115 struct sk_buff *skb;
116
117 fl = data_len + fr_length_encode[(int)type];
118 skb = alloc_skb(16 + fl, GFP_ATOMIC);
119 if (skb != NULL)
120 {
121 skb->dev = lp->dev;
122 skb_reserve(skb, 16);
123 fr = (frameptr) skb_put(skb, fl);
124 memset(fr, 0, fl);
125 /*
126 * Construct 802.2 header
127 */
128 if (pf & 0x02)
129 fr->pdu_hdr.dsap = 0;
130 else
131 fr->pdu_hdr.dsap = lp->remote_sap;
132 fr->pdu_hdr.ssap = lp->local_sap + cr_bit_encode[(int)type];
133 fr->pdu_cntl.byte1 = cntl_byte_encode[(int)type];
134 /*
135 * Fill in pflag and seq nbrs:
136 */
137 if (IS_SFRAME(fr))
138 {
139 /* case S-frames */
140 if (pf & 0x01)
141 fr->i_hdr.i_pflag = 1;
142 fr->i_hdr.nr = lp->vr;
143 }
144 else
145 {
146 /* case U frames */
147 if (pf & 0x01)
148 fr->u_hdr.u_pflag = 1;
149 }
150
151 if (data_len > 0)
152 { /* append data if any */
153 if (IS_UFRAME(fr))
154 {
155 memcpy(fr->u_hdr.u_info, pdu_data, data_len);
156 }
157 else
158 {
159 memcpy(fr->i_hdr.is_info, pdu_data, data_len);
160 }
161 }
162 lp->dev->hard_header(skb, lp->dev, ETH_P_802_3,
163 lp->remote_mac, NULL, fl);
164 skb->dev=lp->dev;
165 dev_queue_xmit(skb);
166 }
167 else
168 printk(KERN_DEBUG "cl2llc: skb_alloc() in llc_sendpdu() failed\n");
169 }
170
llc_xid_request(llcptr lp,char opt,int ll,char * data)171 void llc_xid_request(llcptr lp, char opt, int ll, char * data)
172 {
173 llc_sendpdu(lp, XID_CMD, opt, ll, data);
174 }
175
llc_test_request(llcptr lp,int ll,char * data)176 void llc_test_request(llcptr lp, int ll, char * data)
177 {
178 llc_sendpdu(lp, TEST_CMD, 0, ll, data);
179 }
180
llc_unit_data_request(llcptr lp,int ll,char * data)181 void llc_unit_data_request(llcptr lp, int ll, char * data)
182 {
183 llc_sendpdu(lp, UI_CMD, 0, ll, data);
184 }
185
186
187 /*
188 * llc_sendipdu() Completes an I pdu in an existing skb and gives it
189 * to the MAC layer for transmission.
190 * Parameter "type" must be either I_CMD or I_RSP.
191 * The skb is not freed after xmit, it is kept in case a retransmission
192 * is requested. If needed it can be picked up again from the rtq.
193 */
194
llc_sendipdu(llcptr lp,char type,char pf,struct sk_buff * skb)195 void llc_sendipdu(llcptr lp, char type, char pf, struct sk_buff *skb)
196 {
197 frameptr fr; /* ptr to output pdu buffer */
198 struct sk_buff *tmp;
199
200 fr = (frameptr) skb->data;
201
202 fr->pdu_hdr.dsap = lp->remote_sap;
203 fr->pdu_hdr.ssap = lp->local_sap + cr_bit_encode[(int)type];
204 fr->pdu_cntl.byte1 = cntl_byte_encode[(int)type];
205
206 if (pf)
207 fr->i_hdr.i_pflag = 1; /* p/f and seq numbers */
208 fr->i_hdr.nr = lp->vr;
209 fr->i_hdr.ns = lp->vs;
210 lp->vs++;
211 if (lp->vs > 127)
212 lp->vs = 0;
213 lp->dev->hard_header(skb, lp->dev, ETH_P_802_3,
214 lp->remote_mac, NULL, skb->len);
215 ADD_TO_RTQ(skb); /* add skb to the retransmit queue */
216 tmp=skb_clone(skb, GFP_ATOMIC);
217 if(tmp!=NULL)
218 {
219 tmp->dev=lp->dev;
220 dev_queue_xmit(tmp);
221 }
222 }
223
224
225 /*
226 * Resend_ipdu() will resend the pdus in the retransmit queue (rtq)
227 * the return value is the number of pdus resend.
228 * ack_nr is N(R) of 1st pdu to resent.
229 * Type is I_CMD or I_RSP for 1st pdu resent.
230 * p is p/f flag 0 or 1 for 1st pdu resent.
231 * All subsequent pdus will be sent as I_CMDs with p/f set to 0
232 */
233
llc_resend_ipdu(llcptr lp,unsigned char ack_nr,unsigned char type,char p)234 int llc_resend_ipdu(llcptr lp, unsigned char ack_nr, unsigned char type, char p)
235 {
236 struct sk_buff *skb,*tmp;
237 int resend_count;
238 frameptr fr;
239 unsigned long flags;
240
241
242 resend_count = 0;
243
244 save_flags(flags);
245 cli();
246
247 skb = skb_peek(&lp->rtq);
248
249 while(skb && skb != (struct sk_buff *)&lp->rtq)
250 {
251 fr = (frameptr) (skb->data + lp->dev->hard_header_len);
252 if (resend_count == 0)
253 {
254 /*
255 * Resending 1st pdu:
256 */
257
258 if (p)
259 fr->i_hdr.i_pflag = 1;
260 else
261 fr->i_hdr.i_pflag = 0;
262
263 if (type == I_CMD)
264 fr->pdu_hdr.ssap = fr->pdu_hdr.ssap & 0xfe;
265 else
266 fr->pdu_hdr.ssap = fr->pdu_hdr.ssap | 0x01;
267 }
268 else
269 {
270 /*
271 * Resending pdu 2...n
272 */
273
274 fr->pdu_hdr.ssap = fr->pdu_hdr.ssap & 0xfe;
275 fr->i_hdr.i_pflag = 0;
276 }
277 fr->i_hdr.nr = lp->vr;
278 fr->i_hdr.ns = lp->vs;
279 lp->vs++;
280 if (lp->vs > 127)
281 lp->vs = 0;
282 tmp=skb_clone(skb, GFP_ATOMIC);
283 if(tmp!=NULL)
284 {
285 tmp->dev = lp->dev;
286 dev_queue_xmit(tmp);
287 }
288 resend_count++;
289 skb = skb->next;
290 }
291 restore_flags(flags);
292 return resend_count;
293 }
294
295 /* ************** internal queue management code ****************** */
296
297
298 /*
299 * Remove one skb from the front of the awaiting transmit queue
300 * (this is the skb longest on the queue) and return a pointer to
301 * that skb.
302 */
303
llc_pull_from_atq(llcptr lp)304 struct sk_buff *llc_pull_from_atq(llcptr lp)
305 {
306 return skb_dequeue(&lp->atq);
307 }
308
309 /*
310 * Free_acknowledged_skbs(), remove from retransmit queue (rtq)
311 * and free all skbs with an N(S) chronologicaly before 'pdu_ack'.
312 * The return value is the number of pdus acknowledged.
313 */
314
llc_free_acknowledged_skbs(llcptr lp,unsigned char pdu_ack)315 int llc_free_acknowledged_skbs(llcptr lp, unsigned char pdu_ack)
316 {
317 struct sk_buff *pp;
318 frameptr fr;
319 int ack_count;
320 unsigned char ack; /* N(S) of most recently ack'ed pdu */
321 unsigned char ns_save;
322 unsigned long flags;
323
324 if (pdu_ack > 0)
325 ack = pdu_ack -1;
326 else
327 ack = 127;
328
329 ack_count = 0;
330
331 save_flags(flags);
332 cli();
333
334 pp = skb_dequeue(&lp->rtq);
335 while (pp != NULL)
336 {
337 /*
338 * Locate skb with N(S) == ack
339 */
340
341 /*
342 * BUG: FIXME - use skb->h.*
343 */
344 fr = (frameptr) (pp->data + lp->dev->hard_header_len);
345 ns_save = fr->i_hdr.ns;
346
347 kfree_skb(pp);
348 ack_count++;
349
350 if (ns_save == ack)
351 break;
352 pp = skb_dequeue(&lp->rtq);
353 }
354 restore_flags(flags);
355 return ack_count;
356 }
357
358