window limits
[cor_2_6_31.git] / net / cor / kpacket_parse.c
blob9f3721b009fb43a8d501e24f4c33e3c818f666e9
1 /*
2 * Connection oriented routing
3 * Copyright (C) 2007-2008 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;
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 pong_rcvd(struct conn *rconn)
90 struct neighbor *nb = rconn->source.in.nb;
91 if (atomic_read(&(rconn->source.in.pong_awaiting)) != 0) {
92 mutex_lock(&(nb->conn_list_lock));
93 if (atomic_read(&(rconn->source.in.pong_awaiting)) == 0)
94 goto unlock;
96 atomic_set(&(rconn->source.in.pong_awaiting), 0);
97 nb->pong_conns_expected--;
98 unlock:
99 mutex_unlock(&(nb->conn_list_lock));
103 static void ping_all_conns(struct neighbor *nb)
105 struct conn *rconn;
107 mutex_lock(&(nb->conn_list_lock));
109 if (list_empty(&(nb->snd_conn_list))) {
110 BUG_ON(nb->num_send_conns != 0);
111 goto out;
114 rconn = container_of(nb->snd_conn_list.next, struct conn,
115 target.out.nb_list);
117 BUG_ON(rconn->targettype != TARGET_OUT);
119 nb->next_ping_conn = rconn;
120 nb->ping_conns_remaining = nb->num_send_conns;
121 kref_get(&(rconn->ref));
123 out:
124 mutex_unlock(&(nb->conn_list_lock));
127 static void discard_ack_conn(struct neighbor *nb, struct sk_buff *skb)
129 pull_u32(skb, 1); /* seqno */
130 pull_u8(skb); /* window */
133 static void discard_set_conn_credits(struct neighbor *nb, struct sk_buff *skb)
135 pull_u32(skb, 1); /* credit_rate */
138 static void parse_ack_conn(struct neighbor *nb, struct sk_buff *skb,
139 __u32 kpacket_seqno, struct conn *rconn)
141 __u32 seqno = pull_u32(skb, 1);
142 __u8 window = pull_u8(skb);
144 pong_rcvd(rconn);
146 conn_ack_rcvd(kpacket_seqno, rconn->reversedir, seqno, window, 0, 0);
149 static void discard_ack_conn_ooo(struct neighbor *nb, struct sk_buff *skb)
151 pull_u32(skb, 1); /* seqno */
152 pull_u8(skb); /* window */
153 pull_u32(skb, 1); /* seqno_ooo */
154 pull_u32(skb, 1); /* length */
157 static void parse_ack_conn_ooo(struct neighbor *nb, struct sk_buff *skb,
158 __u32 kpacket_seqno, struct conn *rconn)
160 __u32 seqno = pull_u32(skb, 1);
161 __u8 window = pull_u8(skb);
162 __u32 seqno_ooo = pull_u32(skb, 1);
163 __u32 length = pull_u32(skb, 1);
165 pong_rcvd(rconn);
167 conn_ack_rcvd(kpacket_seqno, rconn->reversedir, seqno, window,
168 seqno_ooo, length);
171 static void discard_conn_success(struct neighbor *nb, struct sk_buff *skb)
173 __u32 conn_id = pull_u32(skb, 1);
174 struct control_msg_out *cm = alloc_control_msg(nb, ACM_PRIORITY_HIGH);
176 pull_u8(skb); /* window */
178 if (unlikely(cm == 0))
179 send_ping_all_conns(nb);
180 else
181 send_reset_conn(cm, conn_id);
184 static void parse_conn_success(struct neighbor *nb, struct sk_buff *skb,
185 __u32 seqno, struct conn *rconn)
187 struct conn *sconn = rconn->reversedir;
189 __u32 conn_id = pull_u32(skb, 1);
190 __u8 window = pull_u8(skb);
192 BUG_ON(sconn == 0);
194 mutex_lock(&(sconn->rcv_lock));
196 if (unlikely(unlikely(sconn->targettype != TARGET_OUT) ||
197 unlikely(sconn->target.out.nb != nb) ||
198 unlikely(sconn->target.out.conn_id != 0 &&
199 sconn->target.out.conn_id != conn_id))) {
200 goto reset;
203 if (likely(sconn->target.out.conn_id == 0)) {
204 sconn->target.out.conn_id = conn_id;
206 if (unlikely(atomic_read(&(sconn->isreset)) != 0))
207 goto reset;
209 sconn->target.out.seqno_windowlimit =
210 sconn->target.out.seqno_nextsend +
211 dec_window(window);
213 insert_reverse_connid(sconn);
216 flush_out(sconn);
218 if (0) {
219 struct control_msg_out *cm;
220 reset:
221 cm = alloc_control_msg(nb, ACM_PRIORITY_HIGH);
222 if (unlikely(cm == 0))
223 send_ping_all_conns(nb);
224 else
225 send_reset_conn(cm, conn_id);
227 mutex_unlock(&(sconn->rcv_lock));
230 static void parse_reset(struct neighbor *nb, struct sk_buff *skb, __u32 seqno,
231 struct conn *rconn)
233 #warning todo ping conn waiting?
234 atomic_cmpxchg(&(rconn->reversedir->isreset), 0, 1);
235 reset_conn(rconn);
238 static void parse_ping_conn(struct neighbor *nb, struct sk_buff *skb,
239 __u32 seqno, struct conn *rconn)
241 struct control_msg_out *cm = alloc_control_msg(nb, ACM_PRIORITY_MED);
243 if (unlikely(cm == 0))
244 return;
246 mutex_lock(&(rconn->rcv_lock));
247 send_ack_conn(cm, rconn, rconn->reversedir->target.out.conn_id,
248 rconn->source.in.next_seqno);
249 mutex_unlock(&(rconn->rcv_lock));
252 static void parse_set_conn_credits(struct neighbor *nb, struct sk_buff *skb,
253 __u32 seqno, struct conn *rconn)
255 __u32 crate_in = pull_u32(skb, 1);
256 set_conn_in_crate(rconn, crate_in);
259 static void conn_cmd(struct neighbor *nb, struct sk_buff *skb, __u32 seqno,
260 __u8 code, void (*parsefunc)(struct neighbor *nb,
261 struct sk_buff *skb, __u32 seqno, struct conn *rconn),
262 void (*readdiscardfunc)(struct neighbor *nb,
263 struct sk_buff *skb))
265 __u32 conn_id = pull_u32(skb, 1);
266 struct conn *rconn = get_conn(conn_id);
268 if (unlikely(rconn == 0))
269 goto err;
271 BUG_ON(rconn->sourcetype != SOURCE_IN);
272 BUG_ON(rconn->reversedir == 0);
274 if (unlikely(rconn->source.in.nb != nb))
275 goto err;
277 parsefunc(nb, skb, seqno, rconn);
278 if (0) {
279 struct control_msg_out *cm;
280 err:
281 cm = alloc_control_msg(nb, ACM_PRIORITY_MED);
282 if (likely(cm != 0))
283 send_connid_unknown(cm, conn_id);
285 if (readdiscardfunc != 0)
286 readdiscardfunc(nb, skb);
288 if (likely(rconn != 0))
289 kref_put(&(rconn->ref), free_conn);
292 static void parse_conndata(struct neighbor *nb, struct sk_buff *skb)
294 __u32 conn_id = pull_u32(skb, 1);
295 __u32 seqno = pull_u32(skb, 1);
296 __u16 datalength = pull_u16(skb, 1);
297 char *data = cor_pull_skb(skb, datalength);
299 BUG_ON(data == 0);
301 conn_rcv_buildskb(data, datalength, conn_id, seqno);
304 static void parse_connect(struct neighbor *nb, struct sk_buff *skb)
306 struct conn *rconn;
307 __u32 conn_id = pull_u32(skb, 1);
308 __u8 window = pull_u8(skb);
309 struct control_msg_out *cm = alloc_control_msg(nb, ACM_PRIORITY_HIGH);
311 if (unlikely(cm == 0))
312 return;
314 rconn = alloc_conn(GFP_KERNEL);
316 if (unlikely(rconn == 0))
317 goto err;
319 if (unlikely(conn_init_out(rconn->reversedir, nb)))
320 goto err;
322 #warning kref???
324 rconn->reversedir->target.out.conn_id = conn_id;
325 rconn->reversedir->target.out.seqno_windowlimit =
326 rconn->reversedir->target.out.seqno_nextsend +
327 dec_window(window);
328 insert_reverse_connid(rconn->reversedir);
330 send_connect_success(cm, rconn->reversedir->target.out.conn_id,
331 rconn->source.in.conn_id, get_window(rconn));
333 if (0) {
334 err:
335 send_reset_conn(cm, conn_id);
339 static void parse_set_credits(struct neighbor *nb, struct sk_buff *skb)
341 __u64 credits = pull_u64(skb, 1);
342 __s32 creditrate_initial = pull_u32(skb, 1);
343 __u32 creditrate_earning = pull_u32(skb, 1);
344 __u32 creditrate_spending = pull_u32(skb, 1);
346 set_credits(nb, credits, creditrate_initial, creditrate_earning,
347 creditrate_spending);
350 static void kernel_packet2(struct neighbor *nb, struct sk_buff *skb,
351 __u32 seqno1)
353 int ack = 0;
355 while (1) {
356 struct conn *conn;
357 __u32 seqno2;
359 __u32 conn_id;
361 __u32 cookie;
362 __u32 respdelay;
364 __u32 max_cmsg_dly;
366 __u8 *codeptr = cor_pull_skb(skb, 1);
367 __u8 code;
369 if (codeptr == 0)
370 break;
372 code = *codeptr;
374 switch (code) {
375 case KP_PADDING:
376 break;
377 case KP_PING:
378 cookie = pull_u32(skb, 0);
379 send_pong(nb, cookie);
380 break;
381 case KP_PONG:
382 cookie = pull_u32(skb, 0);
383 respdelay = pull_u32(skb, 1);
384 ping_resp(nb, cookie, respdelay);
385 ack = 1;
386 break;
387 case KP_ACK:
388 seqno2 = pull_u32(skb, 1);
389 kern_ack_rcvd(nb, seqno2);
390 break;
391 case KP_ACK_CONN:
392 conn_cmd(nb, skb, seqno1, code, parse_ack_conn,
393 discard_ack_conn);
394 ack = 1;
395 break;
396 case KP_ACK_CONN_OOO:
397 conn_cmd(nb, skb, seqno1, code, parse_ack_conn_ooo,
398 discard_ack_conn_ooo);
399 ack = 1;
400 break;
401 case KP_CONNECT:
402 parse_connect(nb, skb);
403 ack = 1;
404 break;
405 case KP_CONNECT_SUCCESS:
406 conn_cmd(nb, skb, seqno1, code, parse_conn_success,
407 discard_conn_success);
408 ack = 1;
409 break;
410 case KP_CONN_DATA:
411 parse_conndata(nb, skb);
412 break;
413 case KP_PING_CONN:
414 conn_id = pull_u32(skb, 1);
415 conn_cmd(nb, skb, seqno1, code, parse_ping_conn, 0);
416 ack = 1;
417 break;
418 case KP_RESET_CONN:
419 conn_cmd(nb, skb, seqno1, code, parse_reset, 0);
420 ack = 1;
421 break;
422 case KP_CONNID_UNKNOWN:
423 conn_id = pull_u32(skb, 1);
424 conn = get_conn_reverse(nb, conn_id);
425 if (conn != 0) {
426 BUG_ON(conn->reversedir->sourcetype !=
427 SOURCE_IN);
428 pong_rcvd(conn->reversedir);
429 atomic_cmpxchg(&(conn->isreset), 0, 1);
430 reset_conn(conn);
431 conn = 0;
433 ack = 1;
434 break;
435 case KP_PING_ALL_CONNS:
436 ping_all_conns(nb);
437 ack = 1;
438 break;
439 case KP_SET_MAX_CMSG_DELAY:
440 max_cmsg_dly = pull_u32(skb, 1);
441 if (((__u64) max_cmsg_dly) * 1000 > ((__u64)
442 (max_cmsg_dly * 1000)))
443 max_cmsg_dly = 400000000;
444 else
445 max_cmsg_dly *= 100;
446 atomic_set(&(nb->max_remote_cmsg_delay), max_cmsg_dly);
447 ack = 1;
448 break;
449 case KP_SET_CREDITS:
450 parse_set_credits(nb, skb);
451 ack = 1;
452 break;
453 case KP_SET_CONN_CREDITS:
454 conn_cmd(nb, skb, seqno1, code, parse_set_conn_credits,
455 discard_set_conn_credits);
456 ack = 1;
457 break;
458 default:
459 BUG();
463 if (ack)
464 send_ack(nb, seqno1);
467 void kernel_packet(struct neighbor *nb, struct sk_buff *skb, __u32 seqno)
469 struct sk_buff *skb2 = skb_clone(skb, __GFP_DMA | GFP_KERNEL);
471 while (1) {
472 __u8 *codeptr = cor_pull_skb(skb2, 1);
473 __u8 code;
475 char *lengthptr;
476 __u32 length;
478 if (codeptr == 0)
479 break;
480 code = *codeptr;
482 switch (code) {
483 case KP_PADDING:
484 break;
485 case KP_PING:
486 if (cor_pull_skb(skb2, 4) == 0)
487 goto discard;
488 break;
489 case KP_PONG:
490 if (cor_pull_skb(skb2, 8) == 0)
491 goto discard;
492 break;
493 case KP_ACK:
494 if (cor_pull_skb(skb2, 4) == 0)
495 goto discard;
496 break;
497 case KP_ACK_CONN:
498 if (cor_pull_skb(skb2, 9) == 0)
499 goto discard;
500 break;
501 case KP_ACK_CONN_OOO:
502 if (cor_pull_skb(skb2, 17) == 0)
503 goto discard;
504 break;
505 case KP_CONNECT:
506 if (cor_pull_skb(skb2, 5) == 0)
507 goto discard;
508 break;
509 case KP_CONNECT_SUCCESS:
510 if (cor_pull_skb(skb2, 9) == 0)
511 goto discard;
512 break;
513 case KP_CONN_DATA:
514 if (cor_pull_skb(skb2, 8) == 0)
515 goto discard;
516 lengthptr = cor_pull_skb(skb2, 2);
517 if (lengthptr == 0)
518 goto discard;
519 length = ntohs(*((__u16 *)lengthptr));
520 if (cor_pull_skb(skb2, length) == 0)
521 goto discard;
522 break;
523 case KP_PING_CONN:
524 case KP_RESET_CONN:
525 case KP_CONNID_UNKNOWN:
526 if (cor_pull_skb(skb2, 4) == 0)
527 goto discard;
528 break;
529 case KP_PING_ALL_CONNS:
530 break;
531 case KP_SET_MAX_CMSG_DELAY:
532 if (cor_pull_skb(skb2, 4) == 0)
533 goto discard;
534 break;
535 case KP_SET_CREDITS:
536 if (cor_pull_skb(skb2, 20) == 0)
537 goto discard;
538 break;
539 case KP_SET_CONN_CREDITS:
540 if (cor_pull_skb(skb2, 8) == 0)
541 goto discard;
542 break;
543 default:
544 goto discard;
547 kfree_skb(skb2);
548 kernel_packet2(nb, skb, seqno);
549 kfree_skb(skb);
550 return;
551 discard:
552 kfree_skb(skb2);
553 kfree_skb(skb);