free the conn objects of both directions at the same time
[cor_2_6_31.git] / net / cor / kpacket_gen.c
blob6a88c00f38402419292104cf54ce409ec63df879
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_ACK 1
27 #define MSGTYPE_CONNECT 2
28 #define MSGTYPE_CONNECT_SUCCESS 3
29 #define MSGTYPE_CONNECT_FAILED_TEMP 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 __u8 type;
41 union{
42 struct{
43 __u32 conn_id;
44 __u32 seqno;
45 }ack;
47 struct{
48 __u32 conn_id;
49 }connect;
51 struct{
52 __u32 rcvd_conn_id;
53 __u32 gen_conn_id;
54 }connect_success;
56 struct{
57 __u32 conn_id;
58 }connect_failed;
60 struct{
61 __u32 conn_id;
62 }reset;
64 struct{
65 __u32 conn_id;
66 }reset_bw;
68 struct conn_data{
69 __u32 conn_id;
70 __u32 seqno;
71 char *data_orig;
72 char *data;
73 __u32 datalen;
74 }conn_data;
75 }msg;
78 struct control_msg_out *alloc_control_msg(void)
80 return kmalloc(sizeof(struct control_msg_out), GFP_KERNEL);
83 void free_control_msg(struct control_msg_out *cm)
85 kfree(cm);
88 static int add_ack(struct sk_buff *skb, struct control_msg_out *cm,
89 int spaceleft)
91 char *dst;
93 if (spaceleft < 9)
94 return 0;
96 dst = skb_put(skb, 9);
97 BUG_ON(0 == dst);
99 dst[0] = KP_ACK;
100 put_u32(dst + 1, cm->msg.ack.conn_id, 1);
101 put_u32(dst + 5, cm->msg.ack.seqno, 1);
103 return 9;
106 static int add_connect(struct sk_buff *skb, struct control_msg_out *cm,
107 int spaceleft)
109 char *dst;
111 if (spaceleft < 5)
112 return 0;
114 dst = skb_put(skb, 5);
115 BUG_ON(0 == dst);
117 dst[0] = KP_CONNECT;
118 put_u32(dst + 1, cm->msg.connect.conn_id, 1);
120 return 5;
123 static int add_connect_success(struct sk_buff *skb, struct control_msg_out *cm,
124 int spaceleft)
126 char *dst;
128 if (spaceleft < 9)
129 return 0;
131 dst = skb_put(skb, 9);
132 BUG_ON(0 == dst);
134 dst[0] = KP_CONNECT_SUCCESS;
135 put_u32(dst + 1, cm->msg.connect_success.rcvd_conn_id, 1);
136 put_u32(dst + 5, cm->msg.connect_success.rcvd_conn_id, 1);
138 return 9;
141 static int add_connect_failed_temp(struct sk_buff *skb,
142 struct control_msg_out *cm, int spaceleft)
144 char *dst;
146 if (spaceleft < 5)
147 return 0;
149 dst = skb_put(skb, 5);
150 BUG_ON(0 == dst);
152 dst[0] = KP_CONNECT_FAILED_TEMP;
153 put_u32(dst + 1, cm->msg.connect_failed.conn_id, 1);
155 return 5;
158 static int add_reset_conn(struct sk_buff *skb, struct control_msg_out *cm,
159 int spaceleft)
161 char *dst;
163 if (spaceleft < 5)
164 return 0;
166 dst = skb_put(skb, 5);
167 BUG_ON(0 == dst);
169 dst[0] = KP_RESET_CONN;
170 put_u32(dst + 1, cm->msg.reset.conn_id, 1);
172 return 5;
175 static int add_conndata(struct sk_buff *skb, struct control_msg_out *cm,
176 int spaceleft)
178 char *dst;
180 int totallen = cm->msg.conn_data.datalen + 5;
181 int putlen = min(totallen, spaceleft);
183 if (spaceleft < 25 && totallen > 25)
184 return 0;
186 dst = skb_put(skb, putlen);
187 BUG_ON(0 == dst);
189 dst[0] = KP_RESET_CONN;
190 put_u32(dst + 1, cm->msg.conn_data.conn_id, 1);
191 put_u32(dst + 5, cm->msg.conn_data.seqno, 1);
193 memcpy(dst + 9, cm->msg.conn_data.data, putlen - 9);
194 cm->msg.conn_data.datalen -= (putlen - 9);
196 if (cm->msg.conn_data.datalen == 0) {
197 kfree(cm->msg.conn_data.data_orig);
198 free_control_msg(cm);
199 } else {
200 send_conndata(cm, cm->nb, cm->msg.conn_data.conn_id,
201 cm->msg.conn_data.seqno,
202 cm->msg.conn_data.data_orig,
203 cm->msg.conn_data.data,
204 cm->msg.conn_data.datalen);
207 return putlen;
211 static int add_message(struct sk_buff *skb, struct control_msg_out *cm,
212 int spaceleft)
214 int free = 1;
215 int rc;
216 switch (cm->type) {
217 case MSGTYPE_ACK:
218 rc = add_ack(skb, cm, spaceleft);
219 break;
220 case MSGTYPE_CONNECT:
221 rc = add_connect(skb, cm, spaceleft);
222 break;
223 case MSGTYPE_CONNECT_SUCCESS:
224 rc = add_connect_success(skb, cm, spaceleft);
225 break;
226 case MSGTYPE_CONNECT_FAILED_TEMP:
227 rc = add_connect_failed_temp(skb, cm, spaceleft);
228 break;
229 case MSGTYPE_RESET_CONN:
230 rc = add_reset_conn(skb, cm, spaceleft);
231 break;
232 case MSGTYPE_CONNDATA:
233 free = 0;
234 rc = add_conndata(skb, cm, spaceleft);
235 break;
236 default:
237 BUG();
239 if (free)
240 free_control_msg(cm);
241 return rc;
245 static void padding(struct sk_buff *skb, int length)
247 char *dst = skb_put(skb, length);
248 BUG_ON(0 == dst);
249 memset(dst, KP_PADDING, length);
252 static void _send_messages(struct neighbor *nb, struct sk_buff *skb,
253 int spaceleft)
255 int length = 0;
257 while (!list_empty((struct list_head *) &(nb->control_msgs_out))) {
258 int rc;
260 struct control_msg_out *cm = (struct control_msg_out *)
261 nb->control_msgs_out.next;
262 list_del((struct list_head *) cm);
264 rc = add_message(skb, cm, spaceleft - length);
265 if (0 == rc)
266 goto send_packet;
267 length += rc;
270 send_packet:
271 nb->length -= length;
273 padding(skb, spaceleft - length);
274 send_packet(skb, nb);
277 static void send_messages(struct neighbor *nb, int allmsgs)
279 int targetmss = mss(nb);
281 while (nb->length >= targetmss || (allmsgs &&
282 likely(list_empty(&(nb->control_msgs_out)) == 0))) {
283 struct sk_buff *skb;
284 int size = targetmss;
285 if (size > nb->length)
286 size = nb->length;
287 skb = create_packet_kernel(nb, size, GFP_KERNEL);
288 if (skb == 0) {
289 printk(KERN_ERR "cor: send_messages: cannot allocate "
290 "skb (out of memory?)");
291 break;
293 _send_messages(nb, skb, size);
297 static void controlmsg_timerfunc(struct work_struct *work)
299 struct neighbor *nb = container_of(to_delayed_work(work),
300 struct neighbor, cmsg_timer);
301 __u64 jiffies = get_jiffies_64();
303 mutex_lock(&(nb->cmsg_lock));
305 if (nb->timeout > jiffies) {
306 INIT_DELAYED_WORK(&(nb->cmsg_timer), controlmsg_timerfunc);
307 schedule_delayed_work(&(nb->cmsg_timer), nb->timeout - jiffies);
308 goto out;
311 send_messages(nb, 1);
313 out:
314 mutex_unlock(&(nb->cmsg_lock));
317 void schedule_controlmsg_timerfunc(struct neighbor *nb)
319 int target_delay_ms = 100;
320 int target_delay_jiffies = msecs_to_jiffies(target_delay_ms);
321 __u64 jiffies = get_jiffies_64();
322 int delay;
324 nb->timeout += target_delay_jiffies;
326 delay = nb->timeout - jiffies;
327 if (delay < 0)
328 delay = 0;
330 INIT_DELAYED_WORK(&(nb->cmsg_timer), controlmsg_timerfunc);
331 schedule_delayed_work(&(nb->cmsg_timer), delay);
334 static void add_control_msg(struct control_msg_out *msg, __u32 length,
335 struct neighbor *nb)
337 BUG_ON(msg == 0);
339 mutex_lock(&(nb->cmsg_lock));
341 msg->nb = nb;
342 nb->length += length;
343 list_add_tail((struct list_head *) msg,
344 (struct list_head *) &(nb->control_msgs_out));
346 if (unlikely(nb->length >= mss(nb)))
347 send_messages(nb, 0);
349 mutex_unlock(&(nb->cmsg_lock));
352 void send_reset_conn(struct control_msg_out *cm, struct neighbor *nb,
353 __u32 conn_id)
355 cm->type = MSGTYPE_RESET_CONN;
356 cm->msg.reset.conn_id = conn_id;
357 add_control_msg(cm, 5, nb);
360 void send_ack(struct control_msg_out *cm, struct neighbor *nb, __u32 conn_id,
361 __u32 seqno)
363 cm->type = MSGTYPE_ACK;
364 cm->msg.ack.conn_id = conn_id;
365 cm->msg.ack.seqno = seqno;
366 add_control_msg(cm, 9, nb);
369 void send_connect_failed_temp(struct control_msg_out *cm, struct neighbor *nb,
370 __u32 conn_id)
372 cm->type = MSGTYPE_CONNECT_FAILED_TEMP;
373 cm->msg.connect_failed.conn_id = conn_id;
374 add_control_msg(cm, 5, nb);
377 void send_connect_success(struct control_msg_out *cm, struct conn *rconn)
379 BUG_ON(rconn == 0);
380 cm->type = MSGTYPE_CONNECT_SUCCESS;
381 cm->msg.connect_success.rcvd_conn_id =
382 rconn->reversedir->target.out.conn_id;
383 cm->msg.connect_success.gen_conn_id = rconn->source.in.conn_id;
384 add_control_msg(cm, 9, rconn->target.out.nb);
387 void send_connect_nb(struct control_msg_out *cm, struct conn *rconn)
389 BUG_ON(rconn == 0);
390 BUG_ON(rconn->reversedir == 0);
391 BUG_ON(rconn->reversedir->sourcetype != SOURCE_IN);
392 cm->type = MSGTYPE_CONNECT;
393 cm->msg.connect.conn_id = rconn->reversedir->source.in.conn_id;
394 add_control_msg(cm, 5, rconn->target.out.nb);
397 void send_conndata(struct control_msg_out *cm, struct neighbor *nb,
398 __u32 conn_id, __u32 seqno, char *data_orig, char *data,
399 __u32 datalen)
401 cm->type = MSGTYPE_CONNDATA;
402 cm->msg.conn_data.conn_id = conn_id;
403 cm->msg.conn_data.seqno = seqno;
404 cm->msg.conn_data.data_orig = data_orig;
405 cm->msg.conn_data.data = data;
406 cm->msg.conn_data.datalen = datalen;
407 add_control_msg(cm, 9 + datalen, nb);