credit system
[cor_2_6_31.git] / net / cor / kpacket_parse.c
blob9b62e593879668cec898cbf61d5672bd5c89e805
1 /*
2 * Connection oriented routing
3 * Copyright (C) 2007-2010 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 ping_all_conns(struct neighbor *nb)
90 struct conn *rconn;
92 mutex_lock(&(nb->conn_list_lock));
94 if (list_empty(&(nb->snd_conn_list))) {
95 BUG_ON(nb->num_send_conns != 0);
96 goto out;
99 rconn = container_of(nb->snd_conn_list.next, struct conn,
100 target.out.nb_list);
102 BUG_ON(rconn->targettype != TARGET_OUT);
104 nb->next_ping_conn = rconn;
105 nb->ping_conns_remaining = nb->num_send_conns;
106 kref_get(&(rconn->ref));
108 out:
109 mutex_unlock(&(nb->conn_list_lock));
112 static void discard_ack_conn(struct neighbor *nb, struct sk_buff *skb)
114 pull_u32(skb, 1); /* seqno */
115 pull_u8(skb); /* window */
118 static void discard_set_conn_credits(struct neighbor *nb, struct sk_buff *skb)
120 pull_u32(skb, 1); /* credit_rate */
123 static void parse_ack_conn(struct neighbor *nb, struct sk_buff *skb,
124 __u32 kpacket_seqno, struct conn *rconn)
126 __u32 seqno = pull_u32(skb, 1);
127 __u8 window = pull_u8(skb);
129 reset_ping(rconn);
131 conn_ack_rcvd(kpacket_seqno, rconn->reversedir, seqno, window, 0, 0);
134 static void discard_ack_conn_ooo(struct neighbor *nb, struct sk_buff *skb)
136 pull_u32(skb, 1); /* seqno */
137 pull_u8(skb); /* window */
138 pull_u32(skb, 1); /* seqno_ooo */
139 pull_u32(skb, 1); /* length */
142 static void parse_ack_conn_ooo(struct neighbor *nb, struct sk_buff *skb,
143 __u32 kpacket_seqno, struct conn *rconn)
145 __u32 seqno = pull_u32(skb, 1);
146 __u8 window = pull_u8(skb);
147 __u32 seqno_ooo = pull_u32(skb, 1);
148 __u32 length = pull_u32(skb, 1);
150 reset_ping(rconn);
152 conn_ack_rcvd(kpacket_seqno, rconn->reversedir, seqno, window,
153 seqno_ooo, length);
156 static void discard_conn_success(struct neighbor *nb, struct sk_buff *skb)
158 __u32 conn_id = pull_u32(skb, 1);
159 struct control_msg_out *cm = alloc_control_msg(nb, ACM_PRIORITY_HIGH);
161 pull_u8(skb); /* window */
163 if (unlikely(cm == 0))
164 send_ping_all_conns(nb);
165 else
166 send_reset_conn(cm, conn_id);
169 static void parse_conn_success(struct neighbor *nb, struct sk_buff *skb,
170 __u32 seqno, struct conn *rconn)
172 struct conn *sconn = rconn->reversedir;
174 __u32 conn_id = pull_u32(skb, 1);
175 __u32 init_seqno = pull_u32(skb, 1);
176 __u8 window = pull_u8(skb);
178 BUG_ON(sconn == 0);
180 mutex_lock(&(sconn->rcv_lock));
182 if (unlikely(unlikely(sconn->targettype != TARGET_OUT) ||
183 unlikely(sconn->target.out.nb != nb) ||
184 unlikely(sconn->target.out.conn_id != 0 &&
185 sconn->target.out.conn_id != conn_id))) {
186 goto reset;
189 if (likely(sconn->target.out.conn_id == 0)) {
190 sconn->target.out.conn_id = conn_id;
192 if (unlikely(atomic_read(&(sconn->isreset)) != 0))
193 goto reset;
195 sconn->target.out.seqno_nextsend = init_seqno;
196 sconn->target.out.seqno_acked = init_seqno;
197 reset_seqno(sconn, init_seqno);
199 sconn->target.out.seqno_windowlimit =
200 sconn->target.out.seqno_nextsend +
201 dec_log_64_11(window);
203 insert_reverse_connid(sconn);
206 if (0) {
207 struct control_msg_out *cm;
208 reset:
209 cm = alloc_control_msg(nb, ACM_PRIORITY_HIGH);
210 if (unlikely(cm == 0))
211 send_ping_all_conns(nb);
212 else
213 send_reset_conn(cm, conn_id);
215 mutex_unlock(&(sconn->rcv_lock));
217 flush_buf(sconn);
220 static void parse_reset(struct neighbor *nb, struct sk_buff *skb, __u32 seqno,
221 struct conn *rconn)
223 atomic_cmpxchg(&(rconn->reversedir->isreset), 0, 1);
224 reset_conn(rconn);
227 static void parse_ping_conn(struct neighbor *nb, struct sk_buff *skb,
228 __u32 seqno, struct conn *rconn)
230 struct control_msg_out *cm = alloc_control_msg(nb, ACM_PRIORITY_MED);
232 if (unlikely(cm == 0))
233 return;
235 mutex_lock(&(rconn->rcv_lock));
236 send_ack_conn(cm, rconn, rconn->reversedir->target.out.conn_id,
237 rconn->source.in.next_seqno);
238 mutex_unlock(&(rconn->rcv_lock));
241 static void parse_set_conn_credits(struct neighbor *nb, struct sk_buff *skb,
242 __u32 seqno, struct conn *rconn)
244 __u32 crate_in = pull_u32(skb, 1);
245 set_conn_in_crate(rconn, crate_in);
248 static void conn_cmd(struct neighbor *nb, struct sk_buff *skb, __u32 seqno,
249 __u8 code, void (*parsefunc)(struct neighbor *nb,
250 struct sk_buff *skb, __u32 seqno, struct conn *rconn),
251 void (*readdiscardfunc)(struct neighbor *nb,
252 struct sk_buff *skb))
254 __u32 conn_id = pull_u32(skb, 1);
255 struct conn *rconn = get_conn(conn_id);
257 if (unlikely(rconn == 0))
258 goto err;
260 BUG_ON(rconn->sourcetype != SOURCE_IN);
261 BUG_ON(rconn->reversedir == 0);
263 if (unlikely(rconn->source.in.nb != nb))
264 goto err;
266 parsefunc(nb, skb, seqno, rconn);
267 if (0) {
268 struct control_msg_out *cm;
269 err:
270 cm = alloc_control_msg(nb, ACM_PRIORITY_MED);
271 if (likely(cm != 0))
272 send_connid_unknown(cm, conn_id);
274 if (readdiscardfunc != 0)
275 readdiscardfunc(nb, skb);
277 if (likely(rconn != 0))
278 kref_put(&(rconn->ref), free_conn);
281 static void parse_conndata(struct neighbor *nb, struct sk_buff *skb)
283 __u32 conn_id = pull_u32(skb, 1);
284 __u32 seqno = pull_u32(skb, 1);
285 __u16 datalength = pull_u16(skb, 1);
286 char *data = cor_pull_skb(skb, datalength);
288 BUG_ON(data == 0);
290 conn_rcv_buildskb(data, datalength, conn_id, seqno);
293 static void parse_connect(struct neighbor *nb, struct sk_buff *skb)
295 struct conn *rconn;
296 __u32 conn_id = pull_u32(skb, 1);
297 __u32 init_seqno = pull_u32(skb, 1);
298 __u8 window = pull_u8(skb);
299 struct control_msg_out *cm = alloc_control_msg(nb, ACM_PRIORITY_HIGH);
301 if (unlikely(cm == 0))
302 return;
304 rconn = alloc_conn(GFP_KERNEL);
306 if (unlikely(rconn == 0))
307 goto err;
309 mutex_lock(&(rconn->reversedir->rcv_lock));
310 if (unlikely(conn_init_out(rconn->reversedir, nb)))
311 goto err1;
313 rconn->reversedir->target.out.conn_id = conn_id;
315 rconn->reversedir->target.out.seqno_nextsend = init_seqno;
316 rconn->reversedir->target.out.seqno_acked = init_seqno;
317 reset_seqno(rconn->reversedir, init_seqno);
319 rconn->reversedir->target.out.seqno_windowlimit =
320 rconn->reversedir->target.out.seqno_nextsend +
321 dec_log_64_11(window);
322 insert_reverse_connid(rconn->reversedir);
324 send_connect_success(cm, rconn->reversedir->target.out.conn_id,
325 rconn->source.in.conn_id, rconn->source.in.next_seqno,
326 rconn);
328 mutex_unlock(&(rconn->reversedir->rcv_lock));
330 refresh_conn_credits(rconn, 0, 0);
331 refresh_conn_credits(rconn->reversedir, 0, 0);
333 if (0) {
334 err1:
335 mutex_unlock(&(rconn->rcv_lock));
336 kref_put(&(rconn->reversedir->ref), free_conn);
337 kref_put(&(rconn->ref), free_conn);
338 err:
339 send_reset_conn(cm, conn_id);
343 static void kernel_packet2(struct neighbor *nb, struct sk_buff *skb,
344 __u32 seqno1)
346 int ack = 0;
348 while (1) {
349 struct conn *conn;
350 __u32 seqno2;
352 __u32 conn_id;
354 __u32 cookie;
355 __u32 respdelay;
357 __u32 max_cmsg_dly;
359 __u8 *codeptr = cor_pull_skb(skb, 1);
360 __u8 code;
362 if (codeptr == 0)
363 break;
365 code = *codeptr;
367 switch (code) {
368 case KP_PADDING:
369 break;
370 case KP_PING:
371 cookie = pull_u32(skb, 0);
372 send_pong(nb, cookie);
373 break;
374 case KP_PONG:
375 cookie = pull_u32(skb, 0);
376 respdelay = pull_u32(skb, 1);
377 ping_resp(nb, cookie, respdelay);
378 ack = 1;
379 break;
380 case KP_ACK:
381 seqno2 = pull_u32(skb, 1);
382 kern_ack_rcvd(nb, seqno2);
383 break;
384 case KP_ACK_CONN:
385 conn_cmd(nb, skb, seqno1, code, parse_ack_conn,
386 discard_ack_conn);
387 ack = 1;
388 break;
389 case KP_ACK_CONN_OOO:
390 conn_cmd(nb, skb, seqno1, code, parse_ack_conn_ooo,
391 discard_ack_conn_ooo);
392 ack = 1;
393 break;
394 case KP_CONNECT:
395 parse_connect(nb, skb);
396 ack = 1;
397 break;
398 case KP_CONNECT_SUCCESS:
399 conn_cmd(nb, skb, seqno1, code, parse_conn_success,
400 discard_conn_success);
401 ack = 1;
402 break;
403 case KP_CONN_DATA:
404 parse_conndata(nb, skb);
405 break;
406 case KP_PING_CONN:
407 conn_id = pull_u32(skb, 1);
408 conn_cmd(nb, skb, seqno1, code, parse_ping_conn, 0);
409 ack = 1;
410 break;
411 case KP_RESET_CONN:
412 conn_cmd(nb, skb, seqno1, code, parse_reset, 0);
413 ack = 1;
414 break;
415 case KP_CONNID_UNKNOWN:
416 conn_id = pull_u32(skb, 1);
417 conn = get_conn_reverse(nb, conn_id);
418 if (conn != 0) {
419 BUG_ON(conn->reversedir->sourcetype !=
420 SOURCE_IN);
421 atomic_cmpxchg(&(conn->isreset), 0, 1);
422 reset_conn(conn);
423 kref_put(&(conn->ref), free_conn);
424 conn = 0;
426 ack = 1;
427 break;
428 case KP_PING_ALL_CONNS:
429 ping_all_conns(nb);
430 ack = 1;
431 break;
432 case KP_SET_MAX_CMSG_DELAY:
433 max_cmsg_dly = pull_u32(skb, 1);
434 if (((__u64) max_cmsg_dly) * 1000 > ((__u64)
435 (max_cmsg_dly * 1000)))
436 max_cmsg_dly = 400000000;
437 else
438 max_cmsg_dly *= 100;
439 atomic_set(&(nb->max_remote_cmsg_delay), max_cmsg_dly);
440 ack = 1;
441 break;
442 case KP_SET_CONN_CREDITS:
443 conn_cmd(nb, skb, seqno1, code, parse_set_conn_credits,
444 discard_set_conn_credits);
445 ack = 1;
446 break;
447 default:
448 BUG();
452 if (ack)
453 send_ack(nb, seqno1);
456 void kernel_packet(struct neighbor *nb, struct sk_buff *skb, __u32 seqno)
458 struct sk_buff *skb2 = skb_clone(skb, __GFP_DMA | GFP_KERNEL);
460 while (1) {
461 __u8 *codeptr = cor_pull_skb(skb2, 1);
462 __u8 code;
464 char *lengthptr;
465 __u32 length;
467 if (codeptr == 0)
468 break;
469 code = *codeptr;
471 switch (code) {
472 case KP_PADDING:
473 break;
474 case KP_PING:
475 if (cor_pull_skb(skb2, 4) == 0)
476 goto discard;
477 break;
478 case KP_PONG:
479 if (cor_pull_skb(skb2, 8) == 0)
480 goto discard;
481 break;
482 case KP_ACK:
483 if (cor_pull_skb(skb2, 4) == 0)
484 goto discard;
485 break;
486 case KP_ACK_CONN:
487 if (cor_pull_skb(skb2, 9) == 0)
488 goto discard;
489 break;
490 case KP_ACK_CONN_OOO:
491 if (cor_pull_skb(skb2, 17) == 0)
492 goto discard;
493 break;
494 case KP_CONNECT:
495 if (cor_pull_skb(skb2, 9) == 0)
496 goto discard;
497 break;
498 case KP_CONNECT_SUCCESS:
499 if (cor_pull_skb(skb2, 13) == 0)
500 goto discard;
501 break;
502 case KP_CONN_DATA:
503 if (cor_pull_skb(skb2, 8) == 0)
504 goto discard;
505 lengthptr = cor_pull_skb(skb2, 2);
506 if (lengthptr == 0)
507 goto discard;
508 length = ntohs(*((__u16 *)lengthptr));
509 if (cor_pull_skb(skb2, length) == 0)
510 goto discard;
511 break;
512 case KP_PING_CONN:
513 case KP_RESET_CONN:
514 case KP_CONNID_UNKNOWN:
515 if (cor_pull_skb(skb2, 4) == 0)
516 goto discard;
517 break;
518 case KP_PING_ALL_CONNS:
519 break;
520 case KP_SET_MAX_CMSG_DELAY:
521 if (cor_pull_skb(skb2, 4) == 0)
522 goto discard;
523 break;
524 case KP_SET_CONN_CREDITS:
525 if (cor_pull_skb(skb2, 8) == 0)
526 goto discard;
527 break;
528 default:
529 goto discard;
532 kfree_skb(skb2);
533 kernel_packet2(nb, skb, seqno);
534 kfree_skb(skb);
535 return;
536 discard:
537 kfree_skb(skb2);
538 kfree_skb(skb);
541 MODULE_LICENSE("GPL");