namespace cleanup
[cor.git] / net / cor / kpacket_parse.c
blob259746da7c046b7b044c0c7208a1e80591705e49
1 /**
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
18 * 02110-1301, USA.
21 #include <asm/byteorder.h>
23 #include "cor.h"
25 static void parse_ack_conn(struct cor_neighbor *nb, struct sk_buff *skb,
26 __u64 *bytes_acked)
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);
35 int setwindow = 0;
36 __u8 window = 0;
38 if ((flags & KP_ACK_CONN_FLAGS_WINDOW) != 0) {
39 setwindow = 1;
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);
50 __u32 ooo_len;
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);
58 } else {
59 BUG();
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);
78 return;
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);
85 } else {
86 set_last_act(src_in);
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))
109 return;
111 BUG_ON((snd_conn_id & (1 << 31)) != 0);
113 if (unlikely(snd_conn_id == 0))
114 return;
116 if (is_clientmode())
117 goto err;
119 if (newconn_checkpriority(nb, priority) != 0)
120 goto err;
122 cm = alloc_control_msg(nb, ACM_PRIORITY_MED);
123 if (unlikely(cm == 0))
124 goto err;
126 if (is_highlatency != 1)
127 is_highlatency = 0;
129 src_in = alloc_conn(GFP_ATOMIC, is_highlatency);
131 if (unlikely(src_in == 0))
132 goto err;
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))) {
139 src_in->isreset = 2;
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);
145 src_in = 0;
146 goto err;
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);
176 if (0) {
177 struct cor_conn *src_in;
178 err:
179 if (cm != 0) {
180 free_control_msg(cm);
183 src_in = get_conn(nb, rcv_conn_id);
184 if (src_in == 0)
185 send_reset_conn(nb, snd_conn_id, 0);
186 else
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))
199 goto err;
201 if (unlikely(src_in->is_client))
202 goto err;
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))
209 goto err_unlock;
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))
215 goto err_unlock;
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);
239 if (0) {
240 err_unlock:
241 spin_unlock_bh(&(src_in->reversedir->rcv_lock));
242 spin_unlock_bh(&(src_in->rcv_lock));
243 err:
244 if (src_in == 0)
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);
260 BUG_ON(data == 0);
262 if (unlikely(datalength == 0))
263 return;
265 conn_rcv(nb, 0, data, datalength, conn_id, seqno, rcv_delayed_lowbuf,
266 flush);
269 static void parse_reset(struct cor_neighbor *nb, struct sk_buff *skb)
271 __u32 conn_id = pull_u32(skb);
273 int send;
275 struct cor_conn *src_in = get_conn(nb, conn_id);
276 if (src_in == 0)
277 return;
279 if (src_in->is_client) {
280 spin_lock_bh(&(src_in->rcv_lock));
281 spin_lock_bh(&(src_in->reversedir->rcv_lock));
282 } else {
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));
294 } else {
295 spin_unlock_bh(&(src_in->reversedir->rcv_lock));
296 spin_unlock_bh(&(src_in->rcv_lock));
299 if (send)
300 reset_conn(src_in);
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)
308 int ack = 0;
309 int ping_rcvd = 0;
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);
315 __u8 code;
316 __be32 sessionid;
318 if (codeptr == 0)
319 return;
321 code = *codeptr;
322 if (code != KP_INIT_SESSION)
323 return;
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);
330 } else {
331 return;
335 while (1) {
336 __be32 sessionid;
337 __u64 seqno2;
339 __u32 cookie;
340 __u32 respdelay_full;
342 __u8 *codeptr = cor_pull_skb(skb, 1);
343 __u8 code;
345 if (codeptr == 0)
346 break;
348 code = *codeptr;
350 switch (code) {
351 case KP_PADDING:
352 break;
353 case KP_INIT_SESSION:
354 /* ignore if sessionid_rcv_needed is false */
355 sessionid = pull_be32(skb);
356 if (sessionid != nb->sessionid) {
357 return;
359 break;
360 case KP_PING:
361 ping_rcvd = 1;
362 pingcookie = pull_u32(skb);
363 break;
364 case KP_PONG:
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)
370 ack = 1;
371 break;
372 case KP_ACK:
373 seqno2 = pull_u48(skb);
374 kern_ack_rcvd(nb, seqno2);
375 break;
376 case KP_ACK_CONN:
377 parse_ack_conn(nb, skb, &bytes_acked);
378 ack = 1;
379 break;
380 case KP_CONNECT:
381 parse_connect(nb, skb);
382 ack = 1;
383 break;
384 case KP_CONNECT_SUCCESS:
385 parse_conn_success(nb, skb);
386 ack = 1;
387 break;
388 case KP_CONN_DATA:
389 parse_conndata(nb, skb, 0, 0);
390 break;
391 case KP_CONN_DATA_LOWBUFDELAYED:
392 parse_conndata(nb, skb, 1, 0);
393 break;
394 case KP_CONN_DATA_FLUSH:
395 parse_conndata(nb, skb, 0, 1);
396 break;
397 case KP_CONN_DATA_LOWBUFDELAYED_FLUSH:
398 parse_conndata(nb, skb, 1, 1);
399 break;
400 case KP_RESET_CONN:
401 parse_reset(nb, skb);
402 ack = 1;
403 break;
404 case KP_SET_MAX_CMSG_DELAY:
405 atomic_set(&(nb->max_remote_ack_delay_us),
406 pull_u32(skb));
407 atomic_set(&(nb->max_remote_ackconn_delay_us),
408 pull_u32(skb));
409 atomic_set(&(nb->max_remote_other_delay_us),
410 pull_u32(skb));
411 ack = 1;
412 break;
413 default:
414 BUG();
418 #ifdef COR_NBCONGWIN
419 if (bytes_acked > 0)
420 nbcongwin_data_acked(nb, bytes_acked);
421 #endif
423 if (ack)
424 send_ack(nb, seqno1);
425 if (ping_rcvd)
426 send_pong(nb, pingcookie, pkg_rcv_start);
429 static int kernel_packet_checklen(struct sk_buff *skb)
431 while (1) {
432 __u8 *codeptr = cor_pull_skb(skb, 1);
433 __u8 code;
434 __u8 *flags;
436 char *lengthptr;
437 __u32 length;
439 if (codeptr == 0)
440 break;
441 code = *codeptr;
443 switch (code) {
444 case KP_PADDING:
445 break;
446 case KP_INIT_SESSION:
447 case KP_PING:
448 if (cor_pull_skb(skb, 4) == 0)
449 return 1;
450 break;
451 case KP_PONG:
452 if (cor_pull_skb(skb, 12) == 0)
453 return 1;
454 break;
455 case KP_ACK:
456 if (cor_pull_skb(skb, 6) == 0)
457 return 1;
458 break;
459 case KP_ACK_CONN:
460 if (cor_pull_skb(skb, 4) == 0)
461 return 1;
462 flags = cor_pull_skb(skb, 1);
463 if (flags == 0)
464 return 1;
465 if (cor_pull_skb(skb, cor_ack_conn_len(*flags)) == 0)
466 return 1;
467 break;
468 case KP_CONNECT:
469 if (cor_pull_skb(skb, 20) == 0)
470 return 1;
471 break;
472 case KP_CONNECT_SUCCESS:
473 if (cor_pull_skb(skb, 5) == 0)
474 return 1;
475 break;
476 case KP_CONN_DATA:
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)
481 return 1;
482 lengthptr = cor_pull_skb(skb, 2);
483 if (lengthptr == 0)
484 return 1;
485 length = ntohs(*((__u16 *)lengthptr));
486 if (cor_pull_skb(skb, length) == 0)
487 return 1;
488 break;
489 case KP_RESET_CONN:
490 if (cor_pull_skb(skb, 4) == 0)
491 return 1;
492 break;
493 case KP_SET_MAX_CMSG_DELAY:
494 if (cor_pull_skb(skb, 12) == 0)
495 return 1;
496 break;
497 default:
498 return 1;
501 return 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"); */
513 goto discard;
516 skb->data = data;
517 skb->len = len;
519 kernel_packet2(nb, skb, seqno, pkg_rcv_start);
520 discard:
521 kfree_skb(skb);
524 MODULE_LICENSE("GPL");