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 pull_u8(skb
); /* window */
178 if (unlikely(cm
== 0))
179 send_ping_all_conns(nb
);
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
);
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
))) {
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))
209 sconn
->target
.out
.seqno_windowlimit
=
210 sconn
->target
.out
.seqno_nextsend
+
213 insert_reverse_connid(sconn
);
219 struct control_msg_out
*cm
;
221 cm
= alloc_control_msg(nb
, ACM_PRIORITY_HIGH
);
222 if (unlikely(cm
== 0))
223 send_ping_all_conns(nb
);
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
,
233 #warning todo ping conn waiting?
234 atomic_cmpxchg(&(rconn
->reversedir
->isreset
), 0, 1);
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))
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))
271 BUG_ON(rconn
->sourcetype
!= SOURCE_IN
);
272 BUG_ON(rconn
->reversedir
== 0);
274 if (unlikely(rconn
->source
.in
.nb
!= nb
))
277 parsefunc(nb
, skb
, seqno
, rconn
);
279 struct control_msg_out
*cm
;
281 cm
= alloc_control_msg(nb
, ACM_PRIORITY_MED
);
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
);
301 conn_rcv_buildskb(data
, datalength
, conn_id
, seqno
);
304 static void parse_connect(struct neighbor
*nb
, struct sk_buff
*skb
)
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))
314 rconn
= alloc_conn(GFP_KERNEL
);
316 if (unlikely(rconn
== 0))
319 if (unlikely(conn_init_out(rconn
->reversedir
, nb
)))
324 rconn
->reversedir
->target
.out
.conn_id
= conn_id
;
325 rconn
->reversedir
->target
.out
.seqno_windowlimit
=
326 rconn
->reversedir
->target
.out
.seqno_nextsend
+
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
));
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
,
366 __u8
*codeptr
= cor_pull_skb(skb
, 1);
378 cookie
= pull_u32(skb
, 0);
379 send_pong(nb
, cookie
);
382 cookie
= pull_u32(skb
, 0);
383 respdelay
= pull_u32(skb
, 1);
384 ping_resp(nb
, cookie
, respdelay
);
388 seqno2
= pull_u32(skb
, 1);
389 kern_ack_rcvd(nb
, seqno2
);
392 conn_cmd(nb
, skb
, seqno1
, code
, parse_ack_conn
,
396 case KP_ACK_CONN_OOO
:
397 conn_cmd(nb
, skb
, seqno1
, code
, parse_ack_conn_ooo
,
398 discard_ack_conn_ooo
);
402 parse_connect(nb
, skb
);
405 case KP_CONNECT_SUCCESS
:
406 conn_cmd(nb
, skb
, seqno1
, code
, parse_conn_success
,
407 discard_conn_success
);
411 parse_conndata(nb
, skb
);
414 conn_id
= pull_u32(skb
, 1);
415 conn_cmd(nb
, skb
, seqno1
, code
, parse_ping_conn
, 0);
419 conn_cmd(nb
, skb
, seqno1
, code
, parse_reset
, 0);
422 case KP_CONNID_UNKNOWN
:
423 conn_id
= pull_u32(skb
, 1);
424 conn
= get_conn_reverse(nb
, conn_id
);
426 BUG_ON(conn
->reversedir
->sourcetype
!=
428 pong_rcvd(conn
->reversedir
);
429 atomic_cmpxchg(&(conn
->isreset
), 0, 1);
435 case KP_PING_ALL_CONNS
:
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;
446 atomic_set(&(nb
->max_remote_cmsg_delay
), max_cmsg_dly
);
450 parse_set_credits(nb
, skb
);
453 case KP_SET_CONN_CREDITS
:
454 conn_cmd(nb
, skb
, seqno1
, code
, parse_set_conn_credits
,
455 discard_set_conn_credits
);
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
);
472 __u8
*codeptr
= cor_pull_skb(skb2
, 1);
486 if (cor_pull_skb(skb2
, 4) == 0)
490 if (cor_pull_skb(skb2
, 8) == 0)
494 if (cor_pull_skb(skb2
, 4) == 0)
498 if (cor_pull_skb(skb2
, 9) == 0)
501 case KP_ACK_CONN_OOO
:
502 if (cor_pull_skb(skb2
, 17) == 0)
506 if (cor_pull_skb(skb2
, 5) == 0)
509 case KP_CONNECT_SUCCESS
:
510 if (cor_pull_skb(skb2
, 9) == 0)
514 if (cor_pull_skb(skb2
, 8) == 0)
516 lengthptr
= cor_pull_skb(skb2
, 2);
519 length
= ntohs(*((__u16
*)lengthptr
));
520 if (cor_pull_skb(skb2
, length
) == 0)
525 case KP_CONNID_UNKNOWN
:
526 if (cor_pull_skb(skb2
, 4) == 0)
529 case KP_PING_ALL_CONNS
:
531 case KP_SET_MAX_CMSG_DELAY
:
532 if (cor_pull_skb(skb2
, 4) == 0)
536 if (cor_pull_skb(skb2
, 20) == 0)
539 case KP_SET_CONN_CREDITS
:
540 if (cor_pull_skb(skb2
, 8) == 0)
548 kernel_packet2(nb
, skb
, seqno
);