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
21 #include <asm/byteorder.h>
25 /*static __u64 pull_u64(struct sk_buff *skb, int convbo)
27 char *ptr = cor_pull_skb(skb, 8);
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];
43 return be64_to_cpu(ret);
47 static __u32
pull_u32(struct sk_buff
*skb
, int convbo
)
49 char *ptr
= cor_pull_skb(skb
, 4);
55 ((char *)&ret
)[0] = ptr
[0];
56 ((char *)&ret
)[1] = ptr
[1];
57 ((char *)&ret
)[2] = ptr
[2];
58 ((char *)&ret
)[3] = ptr
[3];
61 return be32_to_cpu(ret
);
65 static __u16
pull_u16(struct sk_buff
*skb
, int convbo
)
67 char *ptr
= cor_pull_skb(skb
, 2);
73 ((char *)&ret
)[0] = ptr
[0];
74 ((char *)&ret
)[1] = ptr
[1];
77 return be16_to_cpu(ret
);
81 static __u8
pull_u8(struct sk_buff
*skb
)
83 char *ptr
= cor_pull_skb(skb
, 1);
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);
100 if ((flags
& KP_ACK_CONN_FLAGS_WINDOW
) != 0) {
102 window
= pull_u8(skb
);
105 if (likely(src_in
!= 0))
106 conn_ack_rcvd(nb
, conn_id
, src_in
->reversedir
, seqno
,
110 if (ooolen(flags
) != 0) {
111 __u32 seqno_ooo
= pull_u32(skb
, 1);
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);
124 if (likely(src_in
!= 0))
125 conn_ack_ooo_rcvd(nb
, conn_id
, src_in
->reversedir
,
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;
136 BUG_ON(decaytime
>= 1024);
138 if (likely(src_in
!= 0))
139 set_conn_in_decaytime(nb
, conn_id
, src_in
, seqno
,
143 if (unlikely(src_in
== 0)) {
144 send_connid_unknown(nb
, conn_id
);
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
);
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
)
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
);
174 if (unlikely(cm
== 0))
177 src_in
= alloc_conn(GFP_ATOMIC
);
179 if (unlikely(src_in
== 0))
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
);
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
,
215 send_connect_success(cm
, conn_id
, gen_conn_id
, gen_seqno
, src_in
);
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;
239 struct conn
*src_in
= get_conn(conn_id1
);
241 if (unlikely(src_in
== 0))
244 if (unlikely(src_in
->is_client
!= 0))
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))
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
)))
260 if (unlikely(src_in
->reversedir
->isreset
!= 0))
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
);
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);
287 set_conn_in_decaytime(nb
, conn_id1
, src_in
, credits_seqno
,
290 flush_buf(src_in
->reversedir
);
294 spin_unlock_bh(&(src_in
->reversedir
->rcv_lock
));
295 spin_unlock_bh(&(src_in
->rcv_lock
));
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
);
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);
322 struct conn
*src_in
= get_conn(conn_id
);
326 if (src_in
->is_client
) {
327 spin_lock_bh(&(src_in
->rcv_lock
));
328 spin_lock_bh(&(src_in
->reversedir
->rcv_lock
));
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
));
342 spin_unlock_bh(&(src_in
->reversedir
->rcv_lock
));
343 spin_unlock_bh(&(src_in
->rcv_lock
));
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
);
359 spin_lock_bh(&(trgt_out
->rcv_lock
));
361 if (unlikely(trgt_out
->targettype
!= TARGET_OUT
))
363 if (unlikely((trgt_out
->target
.out
.nb
!= nb
)))
365 if (unlikely((trgt_out
->target
.out
.conn_id
!= conn_id
)))
368 if (trgt_out
->isreset
== 0)
369 trgt_out
->isreset
= 1;
371 spin_unlock_bh(&(trgt_out
->rcv_lock
));
373 reset_conn(trgt_out
);
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
,
395 __u8
*codeptr
= cor_pull_skb(skb
, 1);
407 cookie
= pull_u32(skb
, 0);
408 send_pong(nb
, cookie
);
411 cookie
= pull_u32(skb
, 0);
412 respdelay
= pull_u32(skb
, 1);
413 ping_resp(nb
, cookie
, respdelay
);
417 seqno2
= pull_u32(skb
, 1);
418 kern_ack_rcvd(nb
, seqno2
);
421 parse_ack_conn(nb
, skb
);
425 parse_connect(nb
, skb
);
428 case KP_CONNECT_SUCCESS
:
429 parse_conn_success(nb
, skb
);
433 parse_conndata(nb
, skb
);
436 parse_reset(nb
, skb
);
439 case KP_CONNID_UNKNOWN
:
440 parse_connid_unknown(nb
, skb
);
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;
450 atomic_set(&(nb
->max_remote_cmsg_delay
), max_cmsg_dly
);
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
;
468 __u8
*codeptr
= cor_pull_skb(skb
, 1);
483 if (cor_pull_skb(skb
, 4) == 0)
487 if (cor_pull_skb(skb
, 8) == 0)
491 if (cor_pull_skb(skb
, 4) == 0)
495 if (cor_pull_skb(skb
, 4) == 0)
497 flags
= cor_pull_skb(skb
, 1);
500 if (cor_pull_skb(skb
, ack_conn_len(*flags
)) == 0)
504 if (cor_pull_skb(skb
, 11) == 0)
507 case KP_CONNECT_SUCCESS
:
508 if (cor_pull_skb(skb
, 15) == 0)
512 if (cor_pull_skb(skb
, 8) == 0)
514 lengthptr
= cor_pull_skb(skb
, 2);
517 length
= ntohs(*((__u16
*)lengthptr
));
518 if (cor_pull_skb(skb
, length
) == 0)
522 case KP_CONNID_UNKNOWN
:
523 if (cor_pull_skb(skb
, 4) == 0)
526 case KP_SET_MAX_CMSG_DELAY
:
527 if (cor_pull_skb(skb
, 4) == 0)
538 kernel_packet2(nb
, skb
, seqno
);
543 MODULE_LICENSE("GPL");