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
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 ping_all_conns(struct neighbor
*nb
)
92 mutex_lock(&(nb
->conn_list_lock
));
94 if (list_empty(&(nb
->snd_conn_list
))) {
95 BUG_ON(nb
->num_send_conns
!= 0);
99 rconn
= container_of(nb
->snd_conn_list
.next
, struct conn
,
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
));
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
);
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);
152 conn_ack_rcvd(kpacket_seqno
, rconn
->reversedir
, seqno
, window
,
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
);
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
);
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
))) {
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))
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
);
207 struct control_msg_out
*cm
;
209 cm
= alloc_control_msg(nb
, ACM_PRIORITY_HIGH
);
210 if (unlikely(cm
== 0))
211 send_ping_all_conns(nb
);
213 send_reset_conn(cm
, conn_id
);
215 mutex_unlock(&(sconn
->rcv_lock
));
220 static void parse_reset(struct neighbor
*nb
, struct sk_buff
*skb
, __u32 seqno
,
223 atomic_cmpxchg(&(rconn
->reversedir
->isreset
), 0, 1);
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))
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))
260 BUG_ON(rconn
->sourcetype
!= SOURCE_IN
);
261 BUG_ON(rconn
->reversedir
== 0);
263 if (unlikely(rconn
->source
.in
.nb
!= nb
))
266 parsefunc(nb
, skb
, seqno
, rconn
);
268 struct control_msg_out
*cm
;
270 cm
= alloc_control_msg(nb
, ACM_PRIORITY_MED
);
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
);
290 conn_rcv_buildskb(data
, datalength
, conn_id
, seqno
);
293 static void parse_connect(struct neighbor
*nb
, struct sk_buff
*skb
)
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))
304 rconn
= alloc_conn(GFP_KERNEL
);
306 if (unlikely(rconn
== 0))
309 mutex_lock(&(rconn
->reversedir
->rcv_lock
));
310 if (unlikely(conn_init_out(rconn
->reversedir
, nb
)))
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
,
328 mutex_unlock(&(rconn
->reversedir
->rcv_lock
));
330 refresh_conn_credits(rconn
, 0, 0);
331 refresh_conn_credits(rconn
->reversedir
, 0, 0);
335 mutex_unlock(&(rconn
->rcv_lock
));
336 kref_put(&(rconn
->reversedir
->ref
), free_conn
);
337 kref_put(&(rconn
->ref
), free_conn
);
339 send_reset_conn(cm
, conn_id
);
343 static void kernel_packet2(struct neighbor
*nb
, struct sk_buff
*skb
,
359 __u8
*codeptr
= cor_pull_skb(skb
, 1);
371 cookie
= pull_u32(skb
, 0);
372 send_pong(nb
, cookie
);
375 cookie
= pull_u32(skb
, 0);
376 respdelay
= pull_u32(skb
, 1);
377 ping_resp(nb
, cookie
, respdelay
);
381 seqno2
= pull_u32(skb
, 1);
382 kern_ack_rcvd(nb
, seqno2
);
385 conn_cmd(nb
, skb
, seqno1
, code
, parse_ack_conn
,
389 case KP_ACK_CONN_OOO
:
390 conn_cmd(nb
, skb
, seqno1
, code
, parse_ack_conn_ooo
,
391 discard_ack_conn_ooo
);
395 parse_connect(nb
, skb
);
398 case KP_CONNECT_SUCCESS
:
399 conn_cmd(nb
, skb
, seqno1
, code
, parse_conn_success
,
400 discard_conn_success
);
404 parse_conndata(nb
, skb
);
407 conn_id
= pull_u32(skb
, 1);
408 conn_cmd(nb
, skb
, seqno1
, code
, parse_ping_conn
, 0);
412 conn_cmd(nb
, skb
, seqno1
, code
, parse_reset
, 0);
415 case KP_CONNID_UNKNOWN
:
416 conn_id
= pull_u32(skb
, 1);
417 conn
= get_conn_reverse(nb
, conn_id
);
419 BUG_ON(conn
->reversedir
->sourcetype
!=
421 atomic_cmpxchg(&(conn
->isreset
), 0, 1);
423 kref_put(&(conn
->ref
), free_conn
);
428 case KP_PING_ALL_CONNS
:
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;
439 atomic_set(&(nb
->max_remote_cmsg_delay
), max_cmsg_dly
);
442 case KP_SET_CONN_CREDITS
:
443 conn_cmd(nb
, skb
, seqno1
, code
, parse_set_conn_credits
,
444 discard_set_conn_credits
);
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
);
461 __u8
*codeptr
= cor_pull_skb(skb2
, 1);
475 if (cor_pull_skb(skb2
, 4) == 0)
479 if (cor_pull_skb(skb2
, 8) == 0)
483 if (cor_pull_skb(skb2
, 4) == 0)
487 if (cor_pull_skb(skb2
, 9) == 0)
490 case KP_ACK_CONN_OOO
:
491 if (cor_pull_skb(skb2
, 17) == 0)
495 if (cor_pull_skb(skb2
, 9) == 0)
498 case KP_CONNECT_SUCCESS
:
499 if (cor_pull_skb(skb2
, 13) == 0)
503 if (cor_pull_skb(skb2
, 8) == 0)
505 lengthptr
= cor_pull_skb(skb2
, 2);
508 length
= ntohs(*((__u16
*)lengthptr
));
509 if (cor_pull_skb(skb2
, length
) == 0)
514 case KP_CONNID_UNKNOWN
:
515 if (cor_pull_skb(skb2
, 4) == 0)
518 case KP_PING_ALL_CONNS
:
520 case KP_SET_MAX_CMSG_DELAY
:
521 if (cor_pull_skb(skb2
, 4) == 0)
524 case KP_SET_CONN_CREDITS
:
525 if (cor_pull_skb(skb2
, 8) == 0)
533 kernel_packet2(nb
, skb
, seqno
);
541 MODULE_LICENSE("GPL");