conn rcv_lock converted to spinlock, struct cor_sock created, kernel_packet skb_clone...
[cor_2_6_31.git] / net / cor / kpacket_parse.c
blobf6247f2e46e4476e4b66cf15e63f483ef8b1595e
1 /**
2 * Connection oriented routing
3 * Copyright (C) 2007-2011 Michael Blizek
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA.
21 #include <asm/byteorder.h>
23 #include "cor.h"
25 /*static __u64 pull_u64(struct sk_buff *skb, int convbo)
27 char *ptr = cor_pull_skb(skb, 8);
29 __u64 ret = 0;
31 BUG_ON(0 == ptr);
33 ((char *)&ret)[0] = ptr[0];
34 ((char *)&ret)[1] = ptr[1];
35 ((char *)&ret)[2] = ptr[2];
36 ((char *)&ret)[3] = ptr[3];
37 ((char *)&ret)[4] = ptr[4];
38 ((char *)&ret)[5] = ptr[5];
39 ((char *)&ret)[6] = ptr[6];
40 ((char *)&ret)[7] = ptr[7];
42 if (convbo)
43 return be64_to_cpu(ret);
44 return ret;
45 }*/
47 static __u32 pull_u32(struct sk_buff *skb, int convbo)
49 char *ptr = cor_pull_skb(skb, 4);
51 __u32 ret = 0;
53 BUG_ON(0 == ptr);
55 ((char *)&ret)[0] = ptr[0];
56 ((char *)&ret)[1] = ptr[1];
57 ((char *)&ret)[2] = ptr[2];
58 ((char *)&ret)[3] = ptr[3];
60 if (convbo)
61 return be32_to_cpu(ret);
62 return ret;
65 static __u16 pull_u16(struct sk_buff *skb, int convbo)
67 char *ptr = cor_pull_skb(skb, 2);
69 __u16 ret = 0;
71 BUG_ON(0 == ptr);
73 ((char *)&ret)[0] = ptr[0];
74 ((char *)&ret)[1] = ptr[1];
76 if (convbo)
77 return be16_to_cpu(ret);
78 return ret;
81 static __u8 pull_u8(struct sk_buff *skb)
83 char *ptr = cor_pull_skb(skb, 1);
84 BUG_ON(0 == ptr);
85 return *ptr;
88 static void parse_ack_conn(struct neighbor *nb, struct sk_buff *skb)
90 __u32 conn_id = pull_u32(skb, 1);
91 __u8 flags = pull_u8(skb);
93 struct conn *src_in = get_conn(conn_id);
95 if ((flags & KP_ACK_CONN_FLAGS_SEQNO) != 0) {
96 __u32 seqno = pull_u32(skb, 1);
97 int setwindow = 0;
98 __u8 window = 0;
100 if ((flags & KP_ACK_CONN_FLAGS_WINDOW) != 0) {
101 setwindow = 1;
102 window = pull_u8(skb);
105 if (likely(src_in != 0))
106 conn_ack_rcvd(nb, conn_id, src_in->reversedir, seqno,
107 setwindow, window);
110 if (ooolen(flags) != 0) {
111 __u32 seqno_ooo = pull_u32(skb, 1);
112 __u32 ooo_len;
114 if (ooolen(flags) == 1) {
115 ooo_len = pull_u8(skb);
116 } else if (ooolen(flags) == 2) {
117 ooo_len = pull_u16(skb, 1);
118 } else if (ooolen(flags) == 4) {
119 ooo_len = pull_u32(skb, 1);
120 } else {
121 BUG();
124 if (likely(src_in != 0))
125 conn_ack_ooo_rcvd(nb, conn_id, src_in->reversedir,
126 seqno_ooo, ooo_len);
129 if (flags & KP_ACK_CONN_FLAGS_CREDITS) {
130 __u16 value = pull_u16(skb, 1);
132 __u8 seqno = value >> 10;
133 __u16 decaytime = value & 1023;
135 BUG_ON(seqno >= 64);
136 BUG_ON(decaytime >= 1024);
138 if (likely(src_in != 0))
139 set_conn_in_decaytime(nb, conn_id, src_in, seqno,
140 decaytime);
143 if (unlikely(src_in == 0)) {
144 send_connid_unknown(nb, conn_id);
145 return;
148 spin_lock_bh(&(src_in->rcv_lock));
150 if (unlikely(is_conn_in(src_in, nb, conn_id) == 0)) {
151 send_connid_unknown(nb, conn_id);
152 } else {
153 set_last_act(src_in);
156 spin_unlock_bh(&(src_in->rcv_lock));
158 kref_put(&(src_in->ref), free_conn);
161 static void parse_connect(struct neighbor *nb, struct sk_buff *skb)
163 struct conn *src_in;
164 __u32 conn_id = pull_u32(skb, 1);
165 __u32 init_seqno = pull_u32(skb, 1);
166 __u8 window = pull_u8(skb);
167 __u16 credits = pull_u16(skb, 1);
168 __u8 credits_seqno = credits >> 10;
169 __u16 decaytime = credits & 1023;
170 struct control_msg_out *cm = alloc_control_msg(nb, ACM_PRIORITY_MED);
171 __u32 gen_conn_id;
172 __u32 gen_seqno;
174 if (unlikely(cm == 0))
175 goto err;
177 src_in = alloc_conn(GFP_ATOMIC);
179 if (unlikely(src_in == 0))
180 goto err;
182 src_in->is_client = 1;
184 spin_lock_bh(&(src_in->rcv_lock));
185 spin_lock_bh(&(src_in->reversedir->rcv_lock));
186 if (unlikely(conn_init_out(src_in->reversedir, nb))) {
187 spin_unlock_bh(&(src_in->reversedir->rcv_lock));
188 spin_unlock_bh(&(src_in->rcv_lock));
189 kref_put(&(src_in->reversedir->ref), free_conn);
190 kref_put(&(src_in->ref), free_conn);
191 goto err;
194 gen_conn_id = src_in->source.in.conn_id;
195 gen_seqno = src_in->source.in.next_seqno;
197 src_in->reversedir->target.out.conn_id = conn_id;
199 src_in->reversedir->target.out.seqno_nextsend = init_seqno;
200 src_in->reversedir->target.out.seqno_acked = init_seqno;
201 reset_seqno(src_in->reversedir, init_seqno);
203 src_in->reversedir->target.out.seqno_windowlimit =
204 src_in->reversedir->target.out.seqno_nextsend +
205 dec_log_64_11(window);
206 insert_reverse_connid(src_in->reversedir);
207 spin_unlock_bh(&(src_in->reversedir->rcv_lock));
208 spin_unlock_bh(&(src_in->rcv_lock));
210 BUG_ON(credits_seqno >= 64);
211 BUG_ON(decaytime >= 1024);
212 set_conn_in_decaytime(nb, gen_conn_id, src_in, credits_seqno,
213 decaytime);
215 send_connect_success(cm, conn_id, gen_conn_id, gen_seqno, src_in);
217 if (0) {
218 err:
219 if (cm != 0) {
220 free_control_msg(cm);
222 send_reset_conn(nb, conn_id, 0, 0);
226 static void parse_conn_success(struct neighbor *nb, struct sk_buff *skb)
228 __u32 conn_id1 = pull_u32(skb, 1);
229 __u32 conn_id2 = pull_u32(skb, 1);
230 __u32 init_seqno = pull_u32(skb, 1);
231 __u8 window = pull_u8(skb);
232 __u16 credits = pull_u16(skb, 1);
234 __u8 credits_seqno = credits >> 10;
235 __u16 decaytime = credits & 1023;
237 int set = 0;
239 struct conn *src_in = get_conn(conn_id1);
241 if (unlikely(src_in == 0))
242 goto err;
244 if (unlikely(src_in->is_client != 0))
245 goto err;
248 spin_lock_bh(&(src_in->reversedir->rcv_lock));
249 spin_lock_bh(&(src_in->rcv_lock));
251 if (unlikely(is_conn_in(src_in, nb, conn_id1) == 0))
252 goto err_unlock;
254 if (unlikely(unlikely(src_in->reversedir->targettype != TARGET_OUT) ||
255 unlikely(src_in->reversedir->target.out.nb != nb) ||
256 unlikely(src_in->reversedir->target.out.conn_id != 0 &&
257 src_in->reversedir->target.out.conn_id != conn_id2)))
258 goto err_unlock;
260 if (unlikely(src_in->reversedir->isreset != 0))
261 goto err_unlock;
263 set_last_act(src_in);
265 if (likely(src_in->reversedir->target.out.conn_id == 0)) {
266 src_in->reversedir->target.out.conn_id = conn_id2;
267 src_in->reversedir->target.out.seqno_nextsend = init_seqno;
268 src_in->reversedir->target.out.seqno_acked = init_seqno;
269 src_in->reversedir->target.out.decaytime_send_allowed = 1;
270 reset_seqno(src_in->reversedir, init_seqno);
272 src_in->reversedir->target.out.seqno_windowlimit =
273 src_in->reversedir->target.out.seqno_nextsend +
274 dec_log_64_11(window);
276 insert_reverse_connid(src_in->reversedir);
278 set = 1;
281 spin_unlock_bh(&(src_in->reversedir->rcv_lock));
282 spin_unlock_bh(&(src_in->rcv_lock));
284 BUG_ON(credits_seqno >= 64);
285 BUG_ON(decaytime >= 1024);
286 if (set)
287 set_conn_in_decaytime(nb, conn_id1, src_in, credits_seqno,
288 decaytime);
290 flush_buf(src_in->reversedir);
292 if (0) {
293 err_unlock:
294 spin_unlock_bh(&(src_in->reversedir->rcv_lock));
295 spin_unlock_bh(&(src_in->rcv_lock));
296 err:
297 send_reset_conn(nb, conn_id2, conn_id1, 0);
300 if (likely(src_in != 0))
301 kref_put(&(src_in->ref), free_conn);
304 static void parse_conndata(struct neighbor *nb, struct sk_buff *skb)
306 __u32 conn_id = pull_u32(skb, 1);
307 __u32 seqno = pull_u32(skb, 1);
308 __u16 datalength = pull_u16(skb, 1);
309 char *data = cor_pull_skb(skb, datalength);
311 BUG_ON(data == 0);
313 conn_rcv_buildskb(nb, data, datalength, conn_id, seqno);
316 static void parse_reset(struct neighbor *nb, struct sk_buff *skb)
318 __u32 conn_id = pull_u32(skb, 1);
320 int send;
322 struct conn *src_in = get_conn(conn_id);
323 if (src_in == 0)
324 return;
326 if (src_in->is_client) {
327 spin_lock_bh(&(src_in->rcv_lock));
328 spin_lock_bh(&(src_in->reversedir->rcv_lock));
329 } else {
330 spin_lock_bh(&(src_in->reversedir->rcv_lock));
331 spin_lock_bh(&(src_in->rcv_lock));
334 send = unlikely(is_conn_in(src_in, nb, conn_id));
335 if (send && src_in->reversedir->isreset == 0)
336 src_in->reversedir->isreset = 1;
338 if (src_in->is_client) {
339 spin_unlock_bh(&(src_in->rcv_lock));
340 spin_unlock_bh(&(src_in->reversedir->rcv_lock));
341 } else {
342 spin_unlock_bh(&(src_in->reversedir->rcv_lock));
343 spin_unlock_bh(&(src_in->rcv_lock));
346 if (send)
347 reset_conn(src_in);
349 kref_put(&(src_in->ref), free_conn);
352 static void parse_connid_unknown(struct neighbor *nb, struct sk_buff *skb)
354 __u32 conn_id = pull_u32(skb, 1);
355 struct conn *trgt_out = get_conn_reverse(nb, conn_id);
356 if (trgt_out == 0)
357 return;
359 spin_lock_bh(&(trgt_out->rcv_lock));
361 if (unlikely(trgt_out->targettype != TARGET_OUT))
362 goto err;
363 if (unlikely((trgt_out->target.out.nb != nb)))
364 goto err;
365 if (unlikely((trgt_out->target.out.conn_id != conn_id)))
366 goto err;
368 if (trgt_out->isreset == 0)
369 trgt_out->isreset = 1;
371 spin_unlock_bh(&(trgt_out->rcv_lock));
373 reset_conn(trgt_out);
375 if (0) {
376 err:
377 spin_unlock_bh(&(trgt_out->rcv_lock));
379 kref_put(&(trgt_out->ref), free_conn);
382 static void kernel_packet2(struct neighbor *nb, struct sk_buff *skb,
383 __u32 seqno1)
385 int ack = 0;
387 while (1) {
388 __u32 seqno2;
390 __u32 cookie;
391 __u32 respdelay;
393 __u32 max_cmsg_dly;
395 __u8 *codeptr = cor_pull_skb(skb, 1);
396 __u8 code;
398 if (codeptr == 0)
399 break;
401 code = *codeptr;
403 switch (code) {
404 case KP_PADDING:
405 break;
406 case KP_PING:
407 cookie = pull_u32(skb, 0);
408 send_pong(nb, cookie);
409 break;
410 case KP_PONG:
411 cookie = pull_u32(skb, 0);
412 respdelay = pull_u32(skb, 1);
413 ping_resp(nb, cookie, respdelay);
414 ack = 1;
415 break;
416 case KP_ACK:
417 seqno2 = pull_u32(skb, 1);
418 kern_ack_rcvd(nb, seqno2);
419 break;
420 case KP_ACK_CONN:
421 parse_ack_conn(nb, skb);
422 ack = 1;
423 break;
424 case KP_CONNECT:
425 parse_connect(nb, skb);
426 ack = 1;
427 break;
428 case KP_CONNECT_SUCCESS:
429 parse_conn_success(nb, skb);
430 ack = 1;
431 break;
432 case KP_CONN_DATA:
433 parse_conndata(nb, skb);
434 break;
435 case KP_RESET_CONN:
436 parse_reset(nb, skb);
437 ack = 1;
438 break;
439 case KP_CONNID_UNKNOWN:
440 parse_connid_unknown(nb, skb);
441 ack = 1;
442 break;
443 case KP_SET_MAX_CMSG_DELAY:
444 max_cmsg_dly = pull_u32(skb, 1);
445 if (((__u64) max_cmsg_dly) * 1000 > ((__u64)
446 (max_cmsg_dly * 1000)))
447 max_cmsg_dly = 400000000;
448 else
449 max_cmsg_dly *= 100;
450 atomic_set(&(nb->max_remote_cmsg_delay), max_cmsg_dly);
451 ack = 1;
452 break;
453 default:
454 BUG();
458 if (ack)
459 send_ack(nb, seqno1);
462 void kernel_packet(struct neighbor *nb, struct sk_buff *skb, __u32 seqno)
464 unsigned char *data = skb->data;
465 unsigned int len = skb->len;
467 while (1) {
468 __u8 *codeptr = cor_pull_skb(skb, 1);
469 __u8 code;
470 __u8 *flags;
472 char *lengthptr;
473 __u32 length;
475 if (codeptr == 0)
476 break;
477 code = *codeptr;
479 switch (code) {
480 case KP_PADDING:
481 break;
482 case KP_PING:
483 if (cor_pull_skb(skb, 4) == 0)
484 goto discard;
485 break;
486 case KP_PONG:
487 if (cor_pull_skb(skb, 8) == 0)
488 goto discard;
489 break;
490 case KP_ACK:
491 if (cor_pull_skb(skb, 4) == 0)
492 goto discard;
493 break;
494 case KP_ACK_CONN:
495 if (cor_pull_skb(skb, 4) == 0)
496 goto discard;
497 flags = cor_pull_skb(skb, 1);
498 if (flags == 0)
499 goto discard;
500 if (cor_pull_skb(skb, ack_conn_len(*flags)) == 0)
501 goto discard;
502 break;
503 case KP_CONNECT:
504 if (cor_pull_skb(skb, 11) == 0)
505 goto discard;
506 break;
507 case KP_CONNECT_SUCCESS:
508 if (cor_pull_skb(skb, 15) == 0)
509 goto discard;
510 break;
511 case KP_CONN_DATA:
512 if (cor_pull_skb(skb, 8) == 0)
513 goto discard;
514 lengthptr = cor_pull_skb(skb, 2);
515 if (lengthptr == 0)
516 goto discard;
517 length = ntohs(*((__u16 *)lengthptr));
518 if (cor_pull_skb(skb, length) == 0)
519 goto discard;
520 break;
521 case KP_RESET_CONN:
522 case KP_CONNID_UNKNOWN:
523 if (cor_pull_skb(skb, 4) == 0)
524 goto discard;
525 break;
526 case KP_SET_MAX_CMSG_DELAY:
527 if (cor_pull_skb(skb, 4) == 0)
528 goto discard;
529 break;
530 default:
531 goto discard;
535 skb->data = data;
536 skb->len = len;
538 kernel_packet2(nb, skb, seqno);
539 discard:
540 kfree_skb(skb);
543 MODULE_LICENSE("GPL");