ping reqs
[cor_2_6_31.git] / net / cor / kpacket_gen.c
blob6418c56a050c98a55815fe1f09b9360ec5071452
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_PING 1
27 #define MSGTYPE_PONG 2
28 #define MSGTYPE_ACK 3
29 #define MSGTYPE_CONNECT 4
30 #define MSGTYPE_CONNECT_SUCCESS 5
31 #define MSGTYPE_RESET_CONN 6
32 #define MSGTYPE_CONNDATA 7
35 * lh must be first
37 struct control_msg_out{
38 struct list_head lh;
39 struct neighbor *nb;
41 __u32 length;
43 __u8 type;
44 union{
45 struct{
46 __u32 cookie;
47 }ping;
49 struct{
50 __u32 cookie;
51 unsigned long time_enqueued; /* jiffies */
52 }pong;
54 struct{
55 __u32 conn_id;
56 __u32 seqno;
57 }ack;
59 struct{
60 __u32 conn_id;
61 }connect;
63 struct{
64 __u32 rcvd_conn_id;
65 __u32 gen_conn_id;
66 }connect_success;
68 struct{
69 __u32 conn_id;
70 }reset;
72 struct{
73 __u32 conn_id;
74 }reset_bw;
76 struct conn_data{
77 __u32 conn_id;
78 __u32 seqno;
79 char *data_orig;
80 char *data;
81 __u32 datalen;
82 }conn_data;
83 }msg;
86 struct control_msg_out *alloc_control_msg(void)
88 return kmalloc(sizeof(struct control_msg_out), GFP_KERNEL);
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, struct control_msg_out *cm,
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, cm->msg.ping.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_ACK;
143 put_u32(dst + 1, cm->msg.pong.cookie, 0);
144 put_u32(dst + 5, jiffies_to_msecs(jiffies - cm->msg.pong.time_enqueued,
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_PING:
252 rc = add_ping(skb, cm, spaceleft);
253 break;
254 case MSGTYPE_PONG:
255 rc = add_pong(skb, cm, spaceleft);
256 break;
257 case MSGTYPE_CONNECT:
258 rc = add_connect(skb, cm, spaceleft);
259 break;
260 case MSGTYPE_CONNECT_SUCCESS:
261 rc = add_connect_success(skb, cm, spaceleft);
262 break;
263 case MSGTYPE_RESET_CONN:
264 rc = add_reset_conn(skb, cm, spaceleft);
265 break;
266 case MSGTYPE_CONNDATA:
267 free = 0;
268 rc = add_conndata(skb, cm, spaceleft);
269 break;
270 default:
271 BUG();
273 if (free && rc != 0)
274 free_control_msg(cm);
275 return rc;
279 static void padding(struct sk_buff *skb, int length)
281 char *dst = skb_put(skb, length);
282 BUG_ON(0 == dst);
283 memset(dst, KP_PADDING, length);
286 static void _send_messages(struct neighbor *nb, struct sk_buff *skb,
287 int spaceleft)
289 int length = 0;
290 int retransmit = 0;
292 mutex_lock(&(nb->cmsg_lock));
293 while (!list_empty((struct list_head *) &(nb->control_msgs_out))) {
294 int rc;
296 struct control_msg_out *cm = (struct control_msg_out *)
297 nb->control_msgs_out.next;
298 list_del((struct list_head *) cm);
299 mutex_unlock(&(nb->cmsg_lock));
300 rc = add_message(skb, cm, spaceleft - length);
301 mutex_lock(&(nb->cmsg_lock));
303 if (rc == 0)
304 break;
306 length += cm->length;
307 nb->length -= cm->length;
309 if (cm->type != MSGTYPE_ACK || cm->msg.ack.conn_id != 0)
310 retransmit = 1;
313 mutex_unlock(&(nb->cmsg_lock));
315 padding(skb, spaceleft - length);
316 send_packet(skb, nb, retransmit);
319 static void send_messages(struct neighbor *nb, int allmsgs)
321 int targetmss = mss(nb);
323 mutex_lock(&(nb->cmsg_lock));
325 BUG_ON(list_empty(&(nb->control_msgs_out)) && (nb->length != 0));
326 BUG_ON((list_empty(&(nb->control_msgs_out)) == 0) && (nb->length == 0));
328 while (likely(list_empty(&(nb->control_msgs_out)) == 0) &&
329 (nb->length >= targetmss || allmsgs)) {
330 struct sk_buff *skb;
331 int size = targetmss;
332 if (size > nb->length)
333 size = nb->length;
334 mutex_unlock(&(nb->cmsg_lock));
335 skb = create_packet_kernel(nb, size, GFP_KERNEL);
336 if (skb == 0) {
337 printk(KERN_ERR "cor: send_messages: cannot allocate "
338 "skb (out of memory?)");
339 goto out;
341 _send_messages(nb, skb, size);
342 mutex_lock(&(nb->cmsg_lock));
344 mutex_unlock(&(nb->cmsg_lock));
346 out:
347 BUG_ON(nb->length < 0);
350 static void controlmsg_timerfunc(struct work_struct *work)
352 struct neighbor *nb = container_of(to_delayed_work(work),
353 struct neighbor, cmsg_timer);
354 __u64 jiffies = get_jiffies_64();
356 mutex_lock(&(nb->cmsg_lock));
358 if (nb->timeout > jiffies) {
359 INIT_DELAYED_WORK(&(nb->cmsg_timer), controlmsg_timerfunc);
360 schedule_delayed_work(&(nb->cmsg_timer), nb->timeout - jiffies);
361 mutex_unlock(&(nb->cmsg_lock));
362 return;
365 mutex_unlock(&(nb->cmsg_lock));
367 send_messages(nb, 1);
368 schedule_controlmsg_timerfunc(nb);
371 void schedule_controlmsg_timerfunc(struct neighbor *nb)
373 int target_delay_ms = 100;
374 int target_delay_jiffies = msecs_to_jiffies(target_delay_ms);
375 __u64 jiffies = get_jiffies_64();
376 long long delay;
378 mutex_lock(&(nb->cmsg_lock));
379 nb->timeout += target_delay_jiffies;
381 delay = nb->timeout - jiffies;
382 if (delay < 0) {
383 delay = 0;
384 nb->timeout = jiffies;
387 INIT_DELAYED_WORK(&(nb->cmsg_timer), controlmsg_timerfunc);
388 schedule_delayed_work(&(nb->cmsg_timer), delay);
389 mutex_unlock(&(nb->cmsg_lock));
392 static void add_control_msg(struct control_msg_out *msg, struct neighbor *nb)
394 BUG_ON(msg == 0);
396 printk(KERN_ERR "add_msg %d", msg->type);
398 mutex_lock(&(nb->cmsg_lock));
400 msg->nb = nb;
401 nb->length += msg->length;
402 list_add_tail((struct list_head *) msg,
403 (struct list_head *) &(nb->control_msgs_out));
405 if (unlikely(nb->length >= mss(nb)))
406 send_messages(nb, 0);
408 mutex_unlock(&(nb->cmsg_lock));
411 void send_pong(struct control_msg_out *cm, struct neighbor *nb, __u32 cookie)
413 cm->type = MSGTYPE_PONG;
414 cm->msg.pong.cookie = cookie;
415 cm->msg.pong.time_enqueued = jiffies;
416 cm->length = 9;
417 add_control_msg(cm, nb);
420 void send_reset_conn(struct control_msg_out *cm, struct neighbor *nb,
421 __u32 conn_id)
423 cm->type = MSGTYPE_RESET_CONN;
424 cm->msg.reset.conn_id = conn_id;
425 cm->length = 5;
426 add_control_msg(cm, nb);
429 void send_ack(struct control_msg_out *cm, struct neighbor *nb, __u32 conn_id,
430 __u32 seqno)
432 cm->type = MSGTYPE_ACK;
433 cm->msg.ack.conn_id = conn_id;
434 cm->msg.ack.seqno = seqno;
435 cm->length = 9;
436 add_control_msg(cm, nb);
439 void send_connect_success(struct control_msg_out *cm, struct neighbor *nb,
440 __u32 rcvd_conn_id, __u32 gen_conn_id)
442 cm->type = MSGTYPE_CONNECT_SUCCESS;
443 cm->msg.connect_success.rcvd_conn_id = rcvd_conn_id;
444 cm->msg.connect_success.gen_conn_id = gen_conn_id;
445 cm->length = 9;
446 add_control_msg(cm, nb);
449 void send_connect_nb(struct control_msg_out *cm, struct neighbor *nb,
450 __u32 conn_id)
452 cm->type = MSGTYPE_CONNECT;
453 cm->msg.connect.conn_id = conn_id;
454 cm->length = 5;
455 add_control_msg(cm, nb);
458 void send_conndata(struct control_msg_out *cm, struct neighbor *nb,
459 __u32 conn_id, __u32 seqno, char *data_orig, char *data,
460 __u32 datalen)
462 cm->type = MSGTYPE_CONNDATA;
463 cm->msg.conn_data.conn_id = conn_id;
464 cm->msg.conn_data.seqno = seqno;
465 cm->msg.conn_data.data_orig = data_orig;
466 cm->msg.conn_data.data = data;
467 cm->msg.conn_data.datalen = datalen;
468 cm->length = 9 + datalen;
469 add_control_msg(cm, nb);