kernel message sending bugfixes, connection specific timeouts
[cor_2_6_31.git] / net / cor / kpacket_gen.c
blob6a2e63b686bc5f553e8dc6fffe99f3c28ccf7a21
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, int pongsonly)
286 int length = 0;
287 int retransmit = 0;
289 mutex_lock(&(nb->cmsg_lock));
290 while (!list_empty(&(nb->ucontrol_msgs_out)) || (!pongsonly &&
291 !list_empty(&(nb->control_msgs_out)))) {
292 int rc;
294 int urgent = !list_empty(&(nb->ucontrol_msgs_out));
296 struct control_msg_out *cm;
297 int retrans = 0;
299 if (urgent)
300 cm = container_of(nb->ucontrol_msgs_out.next,
301 struct control_msg_out, lh);
302 else
303 cm = container_of(nb->control_msgs_out.next,
304 struct control_msg_out, lh);
306 list_del(&(cm->lh));
307 if (urgent)
308 nb->ucmlength -= cm->length;
309 else
310 nb->cmlength -= cm->length;
311 if (cm->type != MSGTYPE_ACK || cm->msg.ack.conn_id != 0)
312 retrans = 1;
313 mutex_unlock(&(nb->cmsg_lock));
314 rc = add_message(skb, cm, spaceleft - length);
315 mutex_lock(&(nb->cmsg_lock));
317 if (rc == 0) {
318 if (urgent) {
319 list_add(&(cm->lh), &(nb->ucontrol_msgs_out));
320 nb->ucmlength += cm->length;
321 } else {
322 list_add(&(cm->lh), &(nb->control_msgs_out));
323 nb->cmlength += cm->length;
325 break;
328 length += rc;
330 if (retrans)
331 retransmit = 1;
334 mutex_unlock(&(nb->cmsg_lock));
336 padding(skb, spaceleft - length);
337 send_packet(skb, nb, retransmit);
340 static void send_messages(struct neighbor *nb, int allmsgs)
342 int targetmss = mss(nb);
343 int pingok;
344 int ping = 0;
346 int pingdelay1 = 1000;
347 int pingdelay2 = 400;
349 int nbstate = get_neigh_state(nb);
351 mutex_lock(&(nb->cmsg_lock));
353 BUG_ON(list_empty(&(nb->control_msgs_out)) && (nb->cmlength != 0));
354 BUG_ON((list_empty(&(nb->control_msgs_out)) == 0) &&
355 (nb->cmlength == 0));
356 BUG_ON(list_empty(&(nb->ucontrol_msgs_out)) && (nb->ucmlength != 0));
357 BUG_ON((list_empty(&(nb->ucontrol_msgs_out)) == 0) &&
358 (nb->ucmlength == 0));
360 pingok = time_to_send_ping(nb);
362 if (pingok)
363 ping = time_after_eq(jiffies, nb->last_ping_time +
364 msecs_to_jiffies(pingdelay1));
366 while ((((nbstate == NEIGHBOR_STATE_ACTIVE &&
367 !list_empty(&(nb->control_msgs_out))) ||
368 !list_empty(&(nb->ucontrol_msgs_out))
369 ) && ( (nbstate == NEIGHBOR_STATE_ACTIVE ?
370 nb->cmlength : 0) + nb->ucmlength >= targetmss ||
371 allmsgs)) || (pingok && ping)) {
372 struct sk_buff *skb;
373 int size = targetmss;
374 __u32 length;
376 if (pingok && nb->noping_cnt > 3)
377 ping = 1;
378 if (pingok && time_before_eq(nb->last_ping_time +
379 msecs_to_jiffies(pingdelay2), jiffies))
380 ping = 1;
381 nb->noping_cnt++;
383 length = nb->ucmlength + (ping != 0 ? 5 : 0) + (likely(
384 nbstate == NEIGHBOR_STATE_ACTIVE) ?
385 nb->cmlength : 0);
386 if (size > length)
387 size = length;
388 mutex_unlock(&(nb->cmsg_lock));
389 skb = create_packet_kernel(nb, size, GFP_KERNEL);
390 if (skb == 0) {
391 printk(KERN_ERR "cor: send_messages: cannot allocate "
392 "skb (out of memory?)");
393 goto out;
396 if (ping) {
397 __u32 pingcookie = add_ping_req(nb);
398 int rc = add_ping(skb, pingcookie, size);
399 if (rc == 0)
400 goto err;
401 nb->noping_cnt = 0;
402 nb->last_ping_time = jiffies;
403 size -= rc;
404 ping = 0;
406 _send_messages(nb, skb, size, nbstate != NEIGHBOR_STATE_ACTIVE);
408 if (0) {
409 err:
410 printk(KERN_ERR "kpacket_gen add_ping error");
411 kfree_skb(skb);
414 mutex_lock(&(nb->cmsg_lock));
416 mutex_unlock(&(nb->cmsg_lock));
418 out:
419 BUG_ON(nb->cmlength < 0);
422 static void controlmsg_timerfunc(struct work_struct *work)
424 struct neighbor *nb = container_of(to_delayed_work(work),
425 struct neighbor, cmsg_timer);
426 __u64 jiffies = get_jiffies_64();
428 mutex_lock(&(nb->cmsg_lock));
430 if (nb->timeout > jiffies) {
431 INIT_DELAYED_WORK(&(nb->cmsg_timer), controlmsg_timerfunc);
432 schedule_delayed_work(&(nb->cmsg_timer), nb->timeout - jiffies);
433 mutex_unlock(&(nb->cmsg_lock));
434 return;
437 mutex_unlock(&(nb->cmsg_lock));
439 send_messages(nb, 1);
440 schedule_controlmsg_timerfunc(nb);
441 kref_put(&(nb->ref), neighbor_free);
444 void schedule_controlmsg_timerfunc(struct neighbor *nb)
446 int target_delay_ms = 100;
447 int target_delay_jiffies = msecs_to_jiffies(target_delay_ms);
448 __u64 jiffies = get_jiffies_64();
449 long long delay;
451 int state = get_neigh_state(nb);
453 if (state == NEIGHBOR_STATE_KILLED)
454 return;
456 mutex_lock(&(nb->cmsg_lock));
457 nb->timeout += target_delay_jiffies;
459 delay = nb->timeout - jiffies;
460 if (delay < 0) {
461 delay = 0;
462 nb->timeout = jiffies;
465 INIT_DELAYED_WORK(&(nb->cmsg_timer), controlmsg_timerfunc);
466 schedule_delayed_work(&(nb->cmsg_timer), delay);
467 mutex_unlock(&(nb->cmsg_lock));
468 kref_get(&(nb->ref));
471 static void add_control_msg(struct control_msg_out *msg, struct neighbor *nb)
473 int nbstate = get_neigh_state(nb);
475 BUG_ON(msg == 0);
476 BUG_ON(msg->lh.next != LIST_POISON1 || msg->lh.prev != LIST_POISON2);
478 mutex_lock(&(nb->cmsg_lock));
480 msg->nb = nb;
481 if (unlikely(msg->type == MSGTYPE_PONG || (msg->type == MSGTYPE_ACK &&
482 unlikely(msg->msg.ack.conn_id == 0)))) {
483 nb->ucmlength += msg->length;
484 list_add_tail(&(msg->lh), &(nb->ucontrol_msgs_out));
485 } else {
486 nb->cmlength += msg->length;
487 list_add_tail(&(msg->lh), &(nb->control_msgs_out));
490 if (unlikely((nbstate == NEIGHBOR_STATE_ACTIVE ? nb->cmlength : 0) +
491 nb->ucmlength >= mss(nb)))
492 send_messages(nb, 0);
494 mutex_unlock(&(nb->cmsg_lock));
497 void send_pong(struct control_msg_out *cm, struct neighbor *nb, __u32 cookie)
499 cm->type = MSGTYPE_PONG;
500 cm->msg.pong.cookie = cookie;
501 cm->msg.pong.time_enqueued = jiffies;
502 cm->length = 9;
503 add_control_msg(cm, nb);
506 void send_reset_conn(struct control_msg_out *cm, struct neighbor *nb,
507 __u32 conn_id)
509 cm->type = MSGTYPE_RESET_CONN;
510 cm->msg.reset.conn_id = conn_id;
511 cm->length = 5;
512 add_control_msg(cm, nb);
515 void send_ack(struct control_msg_out *cm, struct neighbor *nb, __u32 conn_id,
516 __u32 seqno)
518 cm->type = MSGTYPE_ACK;
519 cm->msg.ack.conn_id = conn_id;
520 cm->msg.ack.seqno = seqno;
521 cm->length = 9;
522 add_control_msg(cm, nb);
525 void send_connect_success(struct control_msg_out *cm, struct neighbor *nb,
526 __u32 rcvd_conn_id, __u32 gen_conn_id)
528 cm->type = MSGTYPE_CONNECT_SUCCESS;
529 cm->msg.connect_success.rcvd_conn_id = rcvd_conn_id;
530 cm->msg.connect_success.gen_conn_id = gen_conn_id;
531 cm->length = 9;
532 add_control_msg(cm, nb);
535 void send_connect_nb(struct control_msg_out *cm, struct neighbor *nb,
536 __u32 conn_id)
538 cm->type = MSGTYPE_CONNECT;
539 cm->msg.connect.conn_id = conn_id;
540 cm->length = 5;
541 add_control_msg(cm, nb);
544 void send_conndata(struct control_msg_out *cm, struct neighbor *nb,
545 __u32 conn_id, __u32 seqno, char *data_orig, char *data,
546 __u32 datalen)
548 cm->type = MSGTYPE_CONNDATA;
549 cm->msg.conn_data.conn_id = conn_id;
550 cm->msg.conn_data.seqno = seqno;
551 cm->msg.conn_data.data_orig = data_orig;
552 cm->msg.conn_data.data = data;
553 cm->msg.conn_data.datalen = datalen;
554 cm->length = 11 + datalen;
555 add_control_msg(cm, nb);