ping reqs part 2, kpacket_gen access shortly after free fix
[cor_2_6_31.git] / net / cor / kpacket_gen.c
blobee720eef0686119f49ea3f9500c0b06066af1ddf
1 /*
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
18 * 02110-1301, USA.
21 #include <asm/byteorder.h>
23 #include "cor.h"
25 /* not sent over the network - internal meaning only */
26 #define MSGTYPE_PONG 1
27 #define MSGTYPE_ACK 2
28 #define MSGTYPE_CONNECT 3
29 #define MSGTYPE_CONNECT_SUCCESS 4
30 #define MSGTYPE_RESET_CONN 5
31 #define MSGTYPE_CONNDATA 6
34 * lh must be first
36 struct control_msg_out{
37 struct list_head lh;
38 struct neighbor *nb;
40 __u32 length;
42 __u8 type;
43 union{
44 struct{
45 __u32 cookie;
46 unsigned long time_enqueued; /* jiffies */
47 }pong;
49 struct{
50 __u32 conn_id;
51 __u32 seqno;
52 }ack;
54 struct{
55 __u32 conn_id;
56 }connect;
58 struct{
59 __u32 rcvd_conn_id;
60 __u32 gen_conn_id;
61 }connect_success;
63 struct{
64 __u32 conn_id;
65 }reset;
67 struct{
68 __u32 conn_id;
69 }reset_bw;
71 struct conn_data{
72 __u32 conn_id;
73 __u32 seqno;
74 char *data_orig;
75 char *data;
76 __u32 datalen;
77 }conn_data;
78 }msg;
81 struct control_msg_out *alloc_control_msg(void)
83 struct control_msg_out *cm = kmalloc(sizeof(struct control_msg_out), GFP_KERNEL);
84 if (unlikely(cm == 0))
85 return 0;
86 cm->lh.next = LIST_POISON1;
87 cm->lh.prev = LIST_POISON2;
88 return cm;
91 void free_control_msg(struct control_msg_out *cm)
93 kfree(cm);
96 static int add_ack(struct sk_buff *skb, struct control_msg_out *cm,
97 int spaceleft)
99 char *dst;
101 if (spaceleft < 9)
102 return 0;
104 dst = skb_put(skb, 9);
105 BUG_ON(0 == dst);
107 dst[0] = KP_ACK;
108 put_u32(dst + 1, cm->msg.ack.conn_id, 1);
109 put_u32(dst + 5, cm->msg.ack.seqno, 1);
111 return 9;
114 static int add_ping(struct sk_buff *skb, __u32 cookie,
115 int spaceleft)
117 char *dst;
119 if (spaceleft < 5)
120 return 0;
122 dst = skb_put(skb, 5);
123 BUG_ON(0 == dst);
125 dst[0] = KP_PING;
126 put_u32(dst + 1, cookie, 0);
128 return 5;
131 static int add_pong(struct sk_buff *skb, struct control_msg_out *cm,
132 int spaceleft)
134 char *dst;
136 if (spaceleft < 9)
137 return 0;
139 dst = skb_put(skb, 9);
140 BUG_ON(0 == dst);
142 dst[0] = KP_PONG;
143 put_u32(dst + 1, cm->msg.pong.cookie, 0);
144 put_u32(dst + 5, 1000 * jiffies_to_msecs(jiffies -
145 cm->msg.pong.time_enqueued), 1);
147 return 9;
150 static int add_connect(struct sk_buff *skb, struct control_msg_out *cm,
151 int spaceleft)
153 char *dst;
155 if (spaceleft < 5)
156 return 0;
158 dst = skb_put(skb, 5);
159 BUG_ON(0 == dst);
161 dst[0] = KP_CONNECT;
162 put_u32(dst + 1, cm->msg.connect.conn_id, 1);
164 return 5;
167 static int add_connect_success(struct sk_buff *skb, struct control_msg_out *cm,
168 int spaceleft)
170 char *dst;
172 if (spaceleft < 9)
173 return 0;
175 dst = skb_put(skb, 9);
176 BUG_ON(0 == dst);
178 dst[0] = KP_CONNECT_SUCCESS;
179 put_u32(dst + 1, cm->msg.connect_success.rcvd_conn_id, 1);
180 put_u32(dst + 5, cm->msg.connect_success.gen_conn_id, 1);
182 return 9;
185 static int add_reset_conn(struct sk_buff *skb, struct control_msg_out *cm,
186 int spaceleft)
188 char *dst;
190 if (spaceleft < 5)
191 return 0;
193 dst = skb_put(skb, 5);
194 BUG_ON(0 == dst);
196 dst[0] = KP_RESET_CONN;
197 put_u32(dst + 1, cm->msg.reset.conn_id, 1);
199 return 5;
202 static int add_conndata(struct sk_buff *skb, struct control_msg_out *cm,
203 int spaceleft)
205 char *dst;
207 int totallen = cm->msg.conn_data.datalen + 11;
208 int putlen = min(totallen, spaceleft);
209 int dataputlen = putlen - 11;
211 if (dataputlen < 1 || (spaceleft < 25 && spaceleft < totallen))
212 return 0;
214 dst = skb_put(skb, putlen);
215 BUG_ON(0 == dst);
217 dst[0] = KP_CONN_DATA;
218 put_u32(dst + 1, cm->msg.conn_data.conn_id, 1);
219 put_u32(dst + 5, cm->msg.conn_data.seqno, 1);
220 put_u16(dst + 9, dataputlen, 1);
222 memcpy(dst + 11, cm->msg.conn_data.data, dataputlen);
224 cm->msg.conn_data.datalen -= dataputlen;
225 cm->msg.conn_data.data += dataputlen;
227 if (cm->msg.conn_data.datalen == 0) {
228 kfree(cm->msg.conn_data.data_orig);
229 free_control_msg(cm);
230 } else {
231 send_conndata(cm, cm->nb, cm->msg.conn_data.conn_id,
232 cm->msg.conn_data.seqno,
233 cm->msg.conn_data.data_orig,
234 cm->msg.conn_data.data,
235 cm->msg.conn_data.datalen);
238 return putlen;
242 static int add_message(struct sk_buff *skb, struct control_msg_out *cm,
243 int spaceleft)
245 int free = 1;
246 int rc;
247 switch (cm->type) {
248 case MSGTYPE_ACK:
249 rc = add_ack(skb, cm, spaceleft);
250 break;
251 case MSGTYPE_PONG:
252 rc = add_pong(skb, cm, spaceleft);
253 break;
254 case MSGTYPE_CONNECT:
255 rc = add_connect(skb, cm, spaceleft);
256 break;
257 case MSGTYPE_CONNECT_SUCCESS:
258 rc = add_connect_success(skb, cm, spaceleft);
259 break;
260 case MSGTYPE_RESET_CONN:
261 rc = add_reset_conn(skb, cm, spaceleft);
262 break;
263 case MSGTYPE_CONNDATA:
264 free = 0;
265 rc = add_conndata(skb, cm, spaceleft);
266 break;
267 default:
268 BUG();
270 if (free && rc != 0)
271 free_control_msg(cm);
272 return rc;
276 static void padding(struct sk_buff *skb, int length)
278 char *dst = skb_put(skb, length);
279 BUG_ON(0 == dst);
280 memset(dst, KP_PADDING, length);
283 static void _send_messages(struct neighbor *nb, struct sk_buff *skb,
284 int spaceleft)
286 int length = 0;
287 int retransmit = 0;
289 mutex_lock(&(nb->cmsg_lock));
290 while (!list_empty(&(nb->control_msgs_out))) {
291 int rc;
293 struct control_msg_out *cm = container_of(
294 nb->control_msgs_out.next,
295 struct control_msg_out, lh);
296 int retrans = 0;
297 list_del(&(cm->lh));
298 nb->length -= cm->length;
299 if (cm->type != MSGTYPE_ACK || cm->msg.ack.conn_id != 0)
300 retrans = 1;
301 mutex_unlock(&(nb->cmsg_lock));
302 rc = add_message(skb, cm, spaceleft - length);
303 mutex_lock(&(nb->cmsg_lock));
305 if (rc == 0) {
306 list_add(&(cm->lh), &(nb->control_msgs_out));
307 nb->length += cm->length;
308 break;
311 length += rc;
313 if (retrans)
314 retransmit = 1;
319 mutex_unlock(&(nb->cmsg_lock));
321 padding(skb, spaceleft - length);
322 send_packet(skb, nb, retransmit);
325 static void send_messages(struct neighbor *nb, int allmsgs)
327 int targetmss = mss(nb);
328 __u32 pingcookie;
330 mutex_lock(&(nb->cmsg_lock));
332 BUG_ON(list_empty(&(nb->control_msgs_out)) && (nb->length != 0));
333 BUG_ON((list_empty(&(nb->control_msgs_out)) == 0) && (nb->length == 0));
335 while (likely(list_empty(&(nb->control_msgs_out)) == 0) &&
336 (nb->length >= targetmss || allmsgs)) {
337 pingcookie = add_ping_req(nb);
339 struct sk_buff *skb;
340 int size = targetmss;
341 __u32 length = nb->length + (pingcookie != 0 ? 5 : 0);
342 if (size > length)
343 size = length;
344 mutex_unlock(&(nb->cmsg_lock));
345 skb = create_packet_kernel(nb, size, GFP_KERNEL);
346 if (skb == 0) {
347 printk(KERN_ERR "cor: send_messages: cannot allocate "
348 "skb (out of memory?)");
349 goto out;
352 if (pingcookie != 0) {
353 int rc = add_ping(skb, pingcookie, size);
354 if (rc == 0)
355 goto err;
356 size -= rc;
359 _send_messages(nb, skb, size);
361 if (0) {
362 err:
363 printk(KERN_ERR "kpacket_gen add_ping error");
364 kfree_skb(skb);
367 mutex_lock(&(nb->cmsg_lock));
369 mutex_unlock(&(nb->cmsg_lock));
371 out:
372 BUG_ON(nb->length < 0);
375 static void controlmsg_timerfunc(struct work_struct *work)
377 struct neighbor *nb = container_of(to_delayed_work(work),
378 struct neighbor, cmsg_timer);
379 __u64 jiffies = get_jiffies_64();
381 mutex_lock(&(nb->cmsg_lock));
383 if (nb->timeout > jiffies) {
384 INIT_DELAYED_WORK(&(nb->cmsg_timer), controlmsg_timerfunc);
385 schedule_delayed_work(&(nb->cmsg_timer), nb->timeout - jiffies);
386 mutex_unlock(&(nb->cmsg_lock));
387 return;
390 mutex_unlock(&(nb->cmsg_lock));
392 send_messages(nb, 1);
393 schedule_controlmsg_timerfunc(nb);
396 void schedule_controlmsg_timerfunc(struct neighbor *nb)
398 int target_delay_ms = 100;
399 int target_delay_jiffies = msecs_to_jiffies(target_delay_ms);
400 __u64 jiffies = get_jiffies_64();
401 long long delay;
403 mutex_lock(&(nb->cmsg_lock));
404 nb->timeout += target_delay_jiffies;
406 delay = nb->timeout - jiffies;
407 if (delay < 0) {
408 delay = 0;
409 nb->timeout = jiffies;
412 INIT_DELAYED_WORK(&(nb->cmsg_timer), controlmsg_timerfunc);
413 schedule_delayed_work(&(nb->cmsg_timer), delay);
414 mutex_unlock(&(nb->cmsg_lock));
417 static void add_control_msg(struct control_msg_out *msg, struct neighbor *nb)
419 BUG_ON(msg == 0);
421 printk(KERN_ERR "add_msg %d", msg->type);
423 mutex_lock(&(nb->cmsg_lock));
425 msg->nb = nb;
426 nb->length += msg->length;
427 list_add_tail(&(msg->lh), &(nb->control_msgs_out));
429 if (unlikely(nb->length >= mss(nb)))
430 send_messages(nb, 0);
432 mutex_unlock(&(nb->cmsg_lock));
435 void send_pong(struct control_msg_out *cm, struct neighbor *nb, __u32 cookie)
437 BUG_ON(cm->lh.next != LIST_POISON1 || cm->lh.prev != LIST_POISON2);
438 cm->type = MSGTYPE_PONG;
439 cm->msg.pong.cookie = cookie;
440 cm->msg.pong.time_enqueued = jiffies;
441 cm->length = 9;
442 add_control_msg(cm, nb);
445 void send_reset_conn(struct control_msg_out *cm, struct neighbor *nb,
446 __u32 conn_id)
448 BUG_ON(cm->lh.next != LIST_POISON1 || cm->lh.prev != LIST_POISON2);
449 cm->type = MSGTYPE_RESET_CONN;
450 cm->msg.reset.conn_id = conn_id;
451 cm->length = 5;
452 add_control_msg(cm, nb);
455 void send_ack(struct control_msg_out *cm, struct neighbor *nb, __u32 conn_id,
456 __u32 seqno)
458 BUG_ON(cm->lh.next != LIST_POISON1 || cm->lh.prev != LIST_POISON2);
459 cm->type = MSGTYPE_ACK;
460 cm->msg.ack.conn_id = conn_id;
461 cm->msg.ack.seqno = seqno;
462 cm->length = 9;
463 add_control_msg(cm, nb);
466 void send_connect_success(struct control_msg_out *cm, struct neighbor *nb,
467 __u32 rcvd_conn_id, __u32 gen_conn_id)
469 BUG_ON(cm->lh.next != LIST_POISON1 || cm->lh.prev != LIST_POISON2);
470 cm->type = MSGTYPE_CONNECT_SUCCESS;
471 cm->msg.connect_success.rcvd_conn_id = rcvd_conn_id;
472 cm->msg.connect_success.gen_conn_id = gen_conn_id;
473 cm->length = 9;
474 add_control_msg(cm, nb);
477 void send_connect_nb(struct control_msg_out *cm, struct neighbor *nb,
478 __u32 conn_id)
480 BUG_ON(cm->lh.next != LIST_POISON1 || cm->lh.prev != LIST_POISON2);
481 cm->type = MSGTYPE_CONNECT;
482 cm->msg.connect.conn_id = conn_id;
483 cm->length = 5;
484 add_control_msg(cm, nb);
487 void send_conndata(struct control_msg_out *cm, struct neighbor *nb,
488 __u32 conn_id, __u32 seqno, char *data_orig, char *data,
489 __u32 datalen)
491 BUG_ON(cm->lh.next != LIST_POISON1 || cm->lh.prev != LIST_POISON2);
492 cm->type = MSGTYPE_CONNDATA;
493 cm->msg.conn_data.conn_id = conn_id;
494 cm->msg.conn_data.seqno = seqno;
495 cm->msg.conn_data.data_orig = data_orig;
496 cm->msg.conn_data.data = data;
497 cm->msg.conn_data.datalen = datalen;
498 cm->length = 9 + datalen;
499 add_control_msg(cm, nb);