ping send timing, skb memory leak
[cor_2_6_31.git] / net / cor / kpacket_gen.c
blob1b57dcdbfe97ad83f1ab22083398ff6def0e264d
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 int ping = 0;
330 int pingdelay1 = 1000;
331 int pingdelay2 = 400;
333 mutex_lock(&(nb->cmsg_lock));
335 BUG_ON(list_empty(&(nb->control_msgs_out)) && (nb->length != 0));
336 BUG_ON((list_empty(&(nb->control_msgs_out)) == 0) && (nb->length == 0));
338 ping = time_before_eq(nb->last_ping_time + msecs_to_jiffies(pingdelay1),
339 jiffies);
341 while ((list_empty(&(nb->control_msgs_out)) == 0 &&
342 (nb->length >= targetmss || allmsgs)) ||
343 ping) {
344 struct sk_buff *skb;
345 int size = targetmss;
346 __u32 length;
348 if (nb->noping_cnt > 3)
349 ping = 1;
350 if (time_before_eq(nb->last_ping_time +
351 msecs_to_jiffies(pingdelay2), jiffies))
352 ping = 1;
353 nb->noping_cnt++;
355 length = nb->length + (ping != 0 ? 5 : 0);
356 if (size > length)
357 size = length;
358 mutex_unlock(&(nb->cmsg_lock));
359 skb = create_packet_kernel(nb, size, GFP_KERNEL);
360 if (skb == 0) {
361 printk(KERN_ERR "cor: send_messages: cannot allocate "
362 "skb (out of memory?)");
363 goto out;
366 if (ping) {
367 __u32 pingcookie = add_ping_req(nb);
368 int rc = add_ping(skb, pingcookie, size);
369 if (rc == 0)
370 goto err;
371 nb->noping_cnt = 0;
372 nb->last_ping_time = jiffies;
373 size -= rc;
374 ping = 0;
376 _send_messages(nb, skb, size);
378 if (0) {
379 err:
380 printk(KERN_ERR "kpacket_gen add_ping error");
381 kfree_skb(skb);
384 mutex_lock(&(nb->cmsg_lock));
386 mutex_unlock(&(nb->cmsg_lock));
388 out:
389 BUG_ON(nb->length < 0);
392 static void controlmsg_timerfunc(struct work_struct *work)
394 struct neighbor *nb = container_of(to_delayed_work(work),
395 struct neighbor, cmsg_timer);
396 __u64 jiffies = get_jiffies_64();
398 mutex_lock(&(nb->cmsg_lock));
400 if (nb->timeout > jiffies) {
401 INIT_DELAYED_WORK(&(nb->cmsg_timer), controlmsg_timerfunc);
402 schedule_delayed_work(&(nb->cmsg_timer), nb->timeout - jiffies);
403 mutex_unlock(&(nb->cmsg_lock));
404 return;
407 mutex_unlock(&(nb->cmsg_lock));
409 send_messages(nb, 1);
410 schedule_controlmsg_timerfunc(nb);
413 void schedule_controlmsg_timerfunc(struct neighbor *nb)
415 int target_delay_ms = 100;
416 int target_delay_jiffies = msecs_to_jiffies(target_delay_ms);
417 __u64 jiffies = get_jiffies_64();
418 long long delay;
420 mutex_lock(&(nb->cmsg_lock));
421 nb->timeout += target_delay_jiffies;
423 delay = nb->timeout - jiffies;
424 if (delay < 0) {
425 delay = 0;
426 nb->timeout = jiffies;
429 INIT_DELAYED_WORK(&(nb->cmsg_timer), controlmsg_timerfunc);
430 schedule_delayed_work(&(nb->cmsg_timer), delay);
431 mutex_unlock(&(nb->cmsg_lock));
434 static void add_control_msg(struct control_msg_out *msg, struct neighbor *nb)
436 BUG_ON(msg == 0);
438 mutex_lock(&(nb->cmsg_lock));
440 msg->nb = nb;
441 nb->length += msg->length;
442 list_add_tail(&(msg->lh), &(nb->control_msgs_out));
444 if (unlikely(nb->length >= mss(nb)))
445 send_messages(nb, 0);
447 mutex_unlock(&(nb->cmsg_lock));
450 void send_pong(struct control_msg_out *cm, struct neighbor *nb, __u32 cookie)
452 BUG_ON(cm->lh.next != LIST_POISON1 || cm->lh.prev != LIST_POISON2);
453 cm->type = MSGTYPE_PONG;
454 cm->msg.pong.cookie = cookie;
455 cm->msg.pong.time_enqueued = jiffies;
456 cm->length = 9;
457 add_control_msg(cm, nb);
460 void send_reset_conn(struct control_msg_out *cm, struct neighbor *nb,
461 __u32 conn_id)
463 BUG_ON(cm->lh.next != LIST_POISON1 || cm->lh.prev != LIST_POISON2);
464 cm->type = MSGTYPE_RESET_CONN;
465 cm->msg.reset.conn_id = conn_id;
466 cm->length = 5;
467 add_control_msg(cm, nb);
470 void send_ack(struct control_msg_out *cm, struct neighbor *nb, __u32 conn_id,
471 __u32 seqno)
473 BUG_ON(cm->lh.next != LIST_POISON1 || cm->lh.prev != LIST_POISON2);
474 cm->type = MSGTYPE_ACK;
475 cm->msg.ack.conn_id = conn_id;
476 cm->msg.ack.seqno = seqno;
477 cm->length = 9;
478 add_control_msg(cm, nb);
481 void send_connect_success(struct control_msg_out *cm, struct neighbor *nb,
482 __u32 rcvd_conn_id, __u32 gen_conn_id)
484 BUG_ON(cm->lh.next != LIST_POISON1 || cm->lh.prev != LIST_POISON2);
485 cm->type = MSGTYPE_CONNECT_SUCCESS;
486 cm->msg.connect_success.rcvd_conn_id = rcvd_conn_id;
487 cm->msg.connect_success.gen_conn_id = gen_conn_id;
488 cm->length = 9;
489 add_control_msg(cm, nb);
492 void send_connect_nb(struct control_msg_out *cm, struct neighbor *nb,
493 __u32 conn_id)
495 BUG_ON(cm->lh.next != LIST_POISON1 || cm->lh.prev != LIST_POISON2);
496 cm->type = MSGTYPE_CONNECT;
497 cm->msg.connect.conn_id = conn_id;
498 cm->length = 5;
499 add_control_msg(cm, nb);
502 void send_conndata(struct control_msg_out *cm, struct neighbor *nb,
503 __u32 conn_id, __u32 seqno, char *data_orig, char *data,
504 __u32 datalen)
506 BUG_ON(cm->lh.next != LIST_POISON1 || cm->lh.prev != LIST_POISON2);
507 cm->type = MSGTYPE_CONNDATA;
508 cm->msg.conn_data.conn_id = conn_id;
509 cm->msg.conn_data.seqno = seqno;
510 cm->msg.conn_data.data_orig = data_orig;
511 cm->msg.conn_data.data = data;
512 cm->msg.conn_data.datalen = datalen;
513 cm->length = 9 + datalen;
514 add_control_msg(cm, nb);