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
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 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)
96 atomic_set(&(rconn
->source
.in
.pong_awaiting
), 0);
97 nb
->pong_conns_expected
--;
99 mutex_unlock(&(nb
->conn_list_lock
));
103 static void ping_all_conns(struct neighbor
*nb
)
107 mutex_lock(&(nb
->conn_list_lock
));
109 if (list_empty(&(nb
->snd_conn_list
))) {
110 BUG_ON(nb
->num_send_conns
!= 0);
114 rconn
= container_of(nb
->snd_conn_list
.next
, struct conn
,
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
));
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
);
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);
167 conn_ack_rcvd(kpacket_seqno
, rconn
->reversedir
, seqno
, window
,
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 if (unlikely(cm
== 0))
177 send_ping_all_conns(nb
);
179 send_reset_conn(cm
, conn_id
);
182 static void parse_conn_success(struct neighbor
*nb
, struct sk_buff
*skb
,
183 __u32 seqno
, struct conn
*rconn
)
185 struct conn
*sconn
= rconn
->reversedir
;
187 __u32 conn_id
= pull_u32(skb
, 1);
191 mutex_lock(&(sconn
->rcv_lock
));
193 if (unlikely(unlikely(sconn
->targettype
!= TARGET_OUT
) ||
194 unlikely(sconn
->target
.out
.nb
!= nb
) ||
195 unlikely(sconn
->target
.out
.conn_id
!= 0 &&
196 sconn
->target
.out
.conn_id
!= conn_id
))) {
200 if (likely(sconn
->target
.out
.conn_id
== 0)) {
201 sconn
->target
.out
.conn_id
= conn_id
;
203 if (unlikely(atomic_read(&(sconn
->isreset
)) != 0))
206 insert_reverse_connid(sconn
);
212 struct control_msg_out
*cm
;
214 cm
= alloc_control_msg(nb
, ACM_PRIORITY_HIGH
);
215 if (unlikely(cm
== 0))
216 send_ping_all_conns(nb
);
218 send_reset_conn(cm
, conn_id
);
220 mutex_unlock(&(sconn
->rcv_lock
));
223 static void parse_reset(struct neighbor
*nb
, struct sk_buff
*skb
, __u32 seqno
,
226 #warning todo ping conn waiting?
227 atomic_cmpxchg(&(rconn
->reversedir
->isreset
), 0, 1);
231 static void parse_ping_conn(struct neighbor
*nb
, struct sk_buff
*skb
,
232 __u32 seqno
, struct conn
*rconn
)
234 struct control_msg_out
*cm
= alloc_control_msg(nb
, ACM_PRIORITY_MED
);
236 if (unlikely(cm
== 0))
239 mutex_lock(&(rconn
->rcv_lock
));
240 #warning todo set window
241 send_ack_conn(cm
, rconn
->reversedir
->target
.out
.conn_id
,
242 rconn
->source
.in
.next_seqno
, enc_window(65536));
243 mutex_unlock(&(rconn
->rcv_lock
));
246 static void parse_set_conn_credits(struct neighbor
*nb
, struct sk_buff
*skb
,
247 __u32 seqno
, struct conn
*rconn
)
249 __u32 crate_in
= pull_u32(skb
, 1);
250 set_conn_in_crate(rconn
, crate_in
);
253 static void conn_cmd(struct neighbor
*nb
, struct sk_buff
*skb
, __u32 seqno
,
254 __u8 code
, void (*parsefunc
)(struct neighbor
*nb
,
255 struct sk_buff
*skb
, __u32 seqno
, struct conn
*rconn
),
256 void (*readdiscardfunc
)(struct neighbor
*nb
,
257 struct sk_buff
*skb
))
259 __u32 conn_id
= pull_u32(skb
, 1);
260 struct conn
*rconn
= get_conn(conn_id
);
262 if (unlikely(rconn
== 0))
265 BUG_ON(rconn
->sourcetype
!= SOURCE_IN
);
266 BUG_ON(rconn
->reversedir
== 0);
268 if (unlikely(rconn
->source
.in
.nb
!= nb
))
271 parsefunc(nb
, skb
, seqno
, rconn
);
273 struct control_msg_out
*cm
;
275 cm
= alloc_control_msg(nb
, ACM_PRIORITY_MED
);
277 send_connid_unknown(cm
, conn_id
);
279 if (readdiscardfunc
!= 0)
280 readdiscardfunc(nb
, skb
);
282 if (likely(rconn
!= 0))
283 kref_put(&(rconn
->ref
), free_conn
);
286 static void parse_conndata(struct neighbor
*nb
, struct sk_buff
*skb
)
288 __u32 conn_id
= pull_u32(skb
, 1);
289 __u32 seqno
= pull_u32(skb
, 1);
290 __u16 datalength
= pull_u16(skb
, 1);
291 char *data
= cor_pull_skb(skb
, datalength
);
295 conn_rcv_buildskb(data
, datalength
, conn_id
, seqno
);
298 static void parse_connect(struct neighbor
*nb
, struct sk_buff
*skb
)
301 __u32 conn_id
= pull_u32(skb
, 1);
302 struct control_msg_out
*cm
= alloc_control_msg(nb
, ACM_PRIORITY_HIGH
);
304 if (unlikely(cm
== 0))
307 rconn
= alloc_conn(GFP_KERNEL
);
309 if (unlikely(rconn
== 0))
312 if (unlikely(conn_init_out(rconn
->reversedir
, nb
)))
315 rconn
->reversedir
->target
.out
.conn_id
= conn_id
;
316 insert_reverse_connid(rconn
->reversedir
);
318 send_connect_success(cm
, rconn
->reversedir
->target
.out
.conn_id
,
319 rconn
->source
.in
.conn_id
);
323 send_reset_conn(cm
, conn_id
);
327 static void parse_set_credits(struct neighbor
*nb
, struct sk_buff
*skb
)
329 __u64 credits
= pull_u64(skb
, 1);
330 __s32 creditrate_initial
= pull_u32(skb
, 1);
331 __u32 creditrate_earning
= pull_u32(skb
, 1);
332 __u32 creditrate_spending
= pull_u32(skb
, 1);
334 set_credits(nb
, credits
, creditrate_initial
, creditrate_earning
,
335 creditrate_spending
);
338 #warning todo set window on connect/connect_success
339 static void kernel_packet2(struct neighbor
*nb
, struct sk_buff
*skb
,
355 __u8
*codeptr
= cor_pull_skb(skb
, 1);
367 cookie
= pull_u32(skb
, 0);
368 send_pong(nb
, cookie
);
371 cookie
= pull_u32(skb
, 0);
372 respdelay
= pull_u32(skb
, 1);
373 ping_resp(nb
, cookie
, respdelay
);
377 seqno2
= pull_u32(skb
, 1);
378 kern_ack_rcvd(nb
, seqno2
);
381 conn_cmd(nb
, skb
, seqno1
, code
, parse_ack_conn
,
385 case KP_ACK_CONN_OOO
:
386 conn_cmd(nb
, skb
, seqno1
, code
, parse_ack_conn_ooo
,
387 discard_ack_conn_ooo
);
391 parse_connect(nb
, skb
);
394 case KP_CONNECT_SUCCESS
:
395 conn_cmd(nb
, skb
, seqno1
, code
, parse_conn_success
,
396 discard_conn_success
);
400 parse_conndata(nb
, skb
);
403 conn_id
= pull_u32(skb
, 1);
404 conn_cmd(nb
, skb
, seqno1
, code
, parse_ping_conn
, 0);
408 conn_cmd(nb
, skb
, seqno1
, code
, parse_reset
, 0);
411 case KP_CONNID_UNKNOWN
:
412 conn_id
= pull_u32(skb
, 1);
413 conn
= get_conn_reverse(nb
, conn_id
);
415 BUG_ON(conn
->reversedir
->sourcetype
!=
417 pong_rcvd(conn
->reversedir
);
418 atomic_cmpxchg(&(conn
->isreset
), 0, 1);
424 case KP_PING_ALL_CONNS
:
428 case KP_SET_MAX_CMSG_DELAY
:
429 max_cmsg_dly
= pull_u32(skb
, 1);
430 if (((__u64
) max_cmsg_dly
) * 1000 > ((__u64
)
431 (max_cmsg_dly
* 1000)))
432 max_cmsg_dly
= 400000000;
435 atomic_set(&(nb
->max_remote_cmsg_delay
), max_cmsg_dly
);
439 parse_set_credits(nb
, skb
);
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
, 4) == 0)
498 case KP_CONNECT_SUCCESS
:
499 if (cor_pull_skb(skb2
, 8) == 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)
525 if (cor_pull_skb(skb2
, 20) == 0)
528 case KP_SET_CONN_CREDITS
:
529 if (cor_pull_skb(skb2
, 8) == 0)
537 kernel_packet2(nb
, skb
, seqno
);