2 * Connection oriented routing
3 * Copyright (C) 2007-2012 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 void parse_ack_conn(struct cor_neighbor
*nb
, struct sk_buff
*skb
,
28 __u32 conn_id
= pull_u32(skb
);
29 __u8 flags
= pull_u8(skb
);
31 struct cor_conn
*src_in
= get_conn(nb
, conn_id
);
33 if ((flags
& KP_ACK_CONN_FLAGS_SEQNO
) != 0) {
34 __u64 seqno
= pull_u48(skb
);
38 if ((flags
& KP_ACK_CONN_FLAGS_WINDOW
) != 0) {
40 window
= pull_u8(skb
);
43 if (likely(src_in
!= 0))
44 conn_ack_rcvd(nb
, conn_id
, src_in
->reversedir
, seqno
,
45 setwindow
, window
, bytes_acked
);
48 if (cor_ooolen(flags
) != 0) {
49 __u64 seqno_ooo
= pull_u48(skb
);
52 if (cor_ooolen(flags
) == 1) {
53 ooo_len
= pull_u8(skb
);
54 } else if (cor_ooolen(flags
) == 2) {
55 ooo_len
= pull_u16(skb
);
56 } else if (cor_ooolen(flags
) == 4) {
57 ooo_len
= pull_u32(skb
);
62 if (likely(src_in
!= 0))
63 conn_ack_ooo_rcvd(nb
, conn_id
, src_in
->reversedir
,
64 seqno_ooo
, ooo_len
, bytes_acked
);
67 if (flags
& KP_ACK_CONN_FLAGS_PRIORITY
) {
68 __u8 priority_seqno
= pull_u8(skb
);
69 __u8 priority
= pull_u8(skb
);
71 if (likely(src_in
!= 0))
72 set_conn_in_priority(nb
, conn_id
, src_in
,
73 priority_seqno
, priority
);
76 if (unlikely(src_in
== 0)) {
77 send_reset_conn(nb
, conn_id
^ (conn_id
& (1 << 31)), 0);
81 spin_lock_bh(&(src_in
->rcv_lock
));
83 if (unlikely(is_conn_in(src_in
, nb
, conn_id
) == 0)) {
84 send_reset_conn(nb
, conn_id
^ (conn_id
& (1 << 31)), 0);
89 spin_unlock_bh(&(src_in
->rcv_lock
));
91 kref_put(&(src_in
->ref
), free_conn
);
94 static void parse_connect(struct cor_neighbor
*nb
, struct sk_buff
*skb
)
96 struct cor_conn
*src_in
;
97 __u32 rcv_conn_id
= pull_u32(skb
);
98 __u32 snd_conn_id
= (rcv_conn_id
& ~(1 << 31));
99 __u64 rcv_seqno
= pull_u48(skb
);
100 __u64 snd_seqno
= pull_u48(skb
);
101 __u8 window
= pull_u8(skb
);
102 __u8 priority_seqno
= pull_u8(skb
);
103 __u8 priority
= pull_u8(skb
);
104 __u8 is_highlatency
= pull_u8(skb
);
105 struct control_msg_out
*cm
= 0;
107 /* do not send reset - doing so would only corrupt things further */
108 if (unlikely((rcv_conn_id
& (1 << 31)) == 0))
111 BUG_ON((snd_conn_id
& (1 << 31)) != 0);
113 if (unlikely(snd_conn_id
== 0))
119 if (newconn_checkpriority(nb
, priority
) != 0)
122 cm
= alloc_control_msg(nb
, ACM_PRIORITY_MED
);
123 if (unlikely(cm
== 0))
126 if (is_highlatency
!= 1)
129 src_in
= alloc_conn(GFP_ATOMIC
, is_highlatency
);
131 if (unlikely(src_in
== 0))
134 src_in
->is_client
= 1;
136 spin_lock_bh(&(src_in
->rcv_lock
));
137 spin_lock_bh(&(src_in
->reversedir
->rcv_lock
));
138 if (unlikely(conn_init_out(src_in
->reversedir
, nb
, rcv_conn_id
, 1))) {
140 src_in
->reversedir
->isreset
= 2;
141 spin_unlock_bh(&(src_in
->reversedir
->rcv_lock
));
142 spin_unlock_bh(&(src_in
->rcv_lock
));
143 kref_put(&(src_in
->reversedir
->ref
), free_conn
);
144 kref_put(&(src_in
->ref
), free_conn
);
149 src_in
->source
.in
.established
= 1;
150 src_in
->reversedir
->target
.out
.established
= 1;
152 src_in
->source
.in
.next_seqno
= rcv_seqno
;
153 src_in
->source
.in
.window_seqnolimit
= rcv_seqno
;
154 src_in
->source
.in
.window_seqnolimit_remote
= rcv_seqno
;
156 update_windowlimit(src_in
);
158 src_in
->reversedir
->target
.out
.conn_id
= snd_conn_id
;
160 src_in
->reversedir
->target
.out
.seqno_nextsend
= snd_seqno
;
161 src_in
->reversedir
->target
.out
.seqno_acked
= snd_seqno
;
162 reset_seqno(src_in
->reversedir
, snd_seqno
);
164 src_in
->reversedir
->target
.out
.seqno_windowlimit
=
165 src_in
->reversedir
->target
.out
.seqno_nextsend
+
166 dec_log_64_7(window
);
168 spin_unlock_bh(&(src_in
->reversedir
->rcv_lock
));
169 spin_unlock_bh(&(src_in
->rcv_lock
));
171 src_in
->source
.in
.priority_seqno
= priority_seqno
;
172 set_conn_in_priority(nb
, rcv_conn_id
, src_in
, priority_seqno
, priority
);
174 send_connect_success(cm
, snd_conn_id
, src_in
);
177 struct cor_conn
*src_in
;
180 free_control_msg(cm
);
183 src_in
= get_conn(nb
, rcv_conn_id
);
185 send_reset_conn(nb
, snd_conn_id
, 0);
187 kref_put(&(src_in
->ref
), free_conn
);
191 static void parse_conn_success(struct cor_neighbor
*nb
, struct sk_buff
*skb
)
193 __u32 rcv_conn_id
= pull_u32(skb
);
194 __u8 window
= pull_u8(skb
);
196 struct cor_conn
*src_in
= get_conn(nb
, rcv_conn_id
);
198 if (unlikely(src_in
== 0))
201 if (unlikely(src_in
->is_client
))
205 spin_lock_bh(&(src_in
->reversedir
->rcv_lock
));
206 spin_lock_bh(&(src_in
->rcv_lock
));
208 if (unlikely(is_conn_in(src_in
, nb
, rcv_conn_id
) == 0))
211 BUG_ON(src_in
->reversedir
->targettype
!= TARGET_OUT
);
212 BUG_ON(src_in
->reversedir
->target
.out
.nb
!= nb
);
214 if (unlikely(src_in
->reversedir
->isreset
!= 0))
217 set_last_act(src_in
);
219 src_in
->source
.in
.established
= 1;
221 if (likely(src_in
->reversedir
->target
.out
.established
== 0)) {
222 src_in
->reversedir
->target
.out
.established
= 1;
223 src_in
->reversedir
->target
.out
.priority_send_allowed
= 1;
225 src_in
->reversedir
->target
.out
.seqno_windowlimit
=
226 src_in
->reversedir
->target
.out
.seqno_nextsend
+
227 dec_log_64_7(window
);
231 spin_unlock_bh(&(src_in
->rcv_lock
));
233 flush_buf(src_in
->reversedir
);
235 spin_unlock_bh(&(src_in
->reversedir
->rcv_lock
));
237 wake_sender(src_in
->reversedir
);
241 spin_unlock_bh(&(src_in
->reversedir
->rcv_lock
));
242 spin_unlock_bh(&(src_in
->rcv_lock
));
245 send_reset_conn(nb
, rcv_conn_id
^ (1 << 31), 0);
248 if (likely(src_in
!= 0))
249 kref_put(&(src_in
->ref
), free_conn
);
252 static void parse_conndata(struct cor_neighbor
*nb
, struct sk_buff
*skb
,
253 int rcv_delayed_lowbuf
, __u8 flush
)
255 __u32 conn_id
= pull_u32(skb
);
256 __u64 seqno
= pull_u48(skb
);
257 __u16 datalength
= pull_u16(skb
);
258 char *data
= cor_pull_skb(skb
, datalength
);
262 if (unlikely(datalength
== 0))
265 conn_rcv(nb
, 0, data
, datalength
, conn_id
, seqno
, rcv_delayed_lowbuf
,
269 static void parse_reset(struct cor_neighbor
*nb
, struct sk_buff
*skb
)
271 __u32 conn_id
= pull_u32(skb
);
275 struct cor_conn
*src_in
= get_conn(nb
, conn_id
);
279 if (src_in
->is_client
) {
280 spin_lock_bh(&(src_in
->rcv_lock
));
281 spin_lock_bh(&(src_in
->reversedir
->rcv_lock
));
283 spin_lock_bh(&(src_in
->reversedir
->rcv_lock
));
284 spin_lock_bh(&(src_in
->rcv_lock
));
287 send
= unlikely(is_conn_in(src_in
, nb
, conn_id
));
288 if (send
&& src_in
->reversedir
->isreset
== 0)
289 src_in
->reversedir
->isreset
= 1;
291 if (src_in
->is_client
) {
292 spin_unlock_bh(&(src_in
->rcv_lock
));
293 spin_unlock_bh(&(src_in
->reversedir
->rcv_lock
));
295 spin_unlock_bh(&(src_in
->reversedir
->rcv_lock
));
296 spin_unlock_bh(&(src_in
->rcv_lock
));
302 kref_put(&(src_in
->ref
), free_conn
);
305 static void kernel_packet2(struct cor_neighbor
*nb
, struct sk_buff
*skb
,
306 __u64 seqno1
, ktime_t pkg_rcv_start
)
310 __u32 pingcookie
= 0;
311 __u64 bytes_acked
= 0;
313 if (unlikely(atomic_read(&(nb
->sessionid_rcv_needed
)) != 0)) {
314 __u8
*codeptr
= cor_pull_skb(skb
, 1);
322 if (code
!= KP_INIT_SESSION
)
325 sessionid
= pull_be32(skb
);
326 if (sessionid
== nb
->sessionid
) {
327 atomic_set(&(nb
->sessionid_rcv_needed
), 0);
328 announce_send_stop(nb
->dev
, nb
->mac
,
329 ANNOUNCE_TYPE_UNICAST
);
340 __u32 respdelay_full
;
342 __u8
*codeptr
= cor_pull_skb(skb
, 1);
353 case KP_INIT_SESSION
:
354 /* ignore if sessionid_rcv_needed is false */
355 sessionid
= pull_be32(skb
);
356 if (sessionid
!= nb
->sessionid
) {
362 pingcookie
= pull_u32(skb
);
365 cookie
= pull_u32(skb
);
366 respdelay_full
= pull_u32(skb
);
367 pull_u32(skb
); /* respdelay_netonly */
368 ping_resp(nb
, cookie
, respdelay_full
);
369 if (get_neigh_state(nb
) == NEIGHBOR_STATE_ACTIVE
)
373 seqno2
= pull_u48(skb
);
374 kern_ack_rcvd(nb
, seqno2
);
377 parse_ack_conn(nb
, skb
, &bytes_acked
);
381 parse_connect(nb
, skb
);
384 case KP_CONNECT_SUCCESS
:
385 parse_conn_success(nb
, skb
);
389 parse_conndata(nb
, skb
, 0, 0);
391 case KP_CONN_DATA_LOWBUFDELAYED
:
392 parse_conndata(nb
, skb
, 1, 0);
394 case KP_CONN_DATA_FLUSH
:
395 parse_conndata(nb
, skb
, 0, 1);
397 case KP_CONN_DATA_LOWBUFDELAYED_FLUSH
:
398 parse_conndata(nb
, skb
, 1, 1);
401 parse_reset(nb
, skb
);
404 case KP_SET_MAX_CMSG_DELAY
:
405 atomic_set(&(nb
->max_remote_ack_delay_us
),
407 atomic_set(&(nb
->max_remote_ackconn_delay_us
),
409 atomic_set(&(nb
->max_remote_other_delay_us
),
420 nbcongwin_data_acked(nb
, bytes_acked
);
424 send_ack(nb
, seqno1
);
426 send_pong(nb
, pingcookie
, pkg_rcv_start
);
429 static int kernel_packet_checklen(struct sk_buff
*skb
)
432 __u8
*codeptr
= cor_pull_skb(skb
, 1);
446 case KP_INIT_SESSION
:
448 if (cor_pull_skb(skb
, 4) == 0)
452 if (cor_pull_skb(skb
, 12) == 0)
456 if (cor_pull_skb(skb
, 6) == 0)
460 if (cor_pull_skb(skb
, 4) == 0)
462 flags
= cor_pull_skb(skb
, 1);
465 if (cor_pull_skb(skb
, cor_ack_conn_len(*flags
)) == 0)
469 if (cor_pull_skb(skb
, 20) == 0)
472 case KP_CONNECT_SUCCESS
:
473 if (cor_pull_skb(skb
, 5) == 0)
477 case KP_CONN_DATA_LOWBUFDELAYED
:
478 case KP_CONN_DATA_FLUSH
:
479 case KP_CONN_DATA_LOWBUFDELAYED_FLUSH
:
480 if (cor_pull_skb(skb
, 10) == 0)
482 lengthptr
= cor_pull_skb(skb
, 2);
485 length
= ntohs(*((__u16
*)lengthptr
));
486 if (cor_pull_skb(skb
, length
) == 0)
490 if (cor_pull_skb(skb
, 4) == 0)
493 case KP_SET_MAX_CMSG_DELAY
:
494 if (cor_pull_skb(skb
, 12) == 0)
504 void kernel_packet(struct cor_neighbor
*nb
, struct sk_buff
*skb
, __u64 seqno
)
506 unsigned char *data
= skb
->data
;
507 unsigned int len
= skb
->len
;
509 ktime_t pkg_rcv_start
= ktime_get();
511 if (unlikely(kernel_packet_checklen(skb
) != 0)) {
512 /* printk(KERN_ERR "kpacket discard"); */
519 kernel_packet2(nb
, skb
, seqno
, pkg_rcv_start
);
524 MODULE_LICENSE("GPL");