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
21 #include <asm/byteorder.h>
25 /* not sent over the network - internal meaning only */
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
36 struct control_msg_out
{
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
)
88 static int add_ack(struct sk_buff
*skb
, struct control_msg_out
*cm
,
96 dst
= skb_put(skb
, 9);
100 put_u32(dst
+ 1, cm
->msg
.ack
.conn_id
, 1);
101 put_u32(dst
+ 5, cm
->msg
.ack
.seqno
, 1);
106 static int add_connect(struct sk_buff
*skb
, struct control_msg_out
*cm
,
114 dst
= skb_put(skb
, 5);
118 put_u32(dst
+ 1, cm
->msg
.connect
.conn_id
, 1);
123 static int add_connect_success(struct sk_buff
*skb
, struct control_msg_out
*cm
,
131 dst
= skb_put(skb
, 9);
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);
141 static int add_connect_failed_temp(struct sk_buff
*skb
,
142 struct control_msg_out
*cm
, int spaceleft
)
149 dst
= skb_put(skb
, 5);
152 dst
[0] = KP_CONNECT_FAILED_TEMP
;
153 put_u32(dst
+ 1, cm
->msg
.connect_failed
.conn_id
, 1);
158 static int add_reset_conn(struct sk_buff
*skb
, struct control_msg_out
*cm
,
166 dst
= skb_put(skb
, 5);
169 dst
[0] = KP_RESET_CONN
;
170 put_u32(dst
+ 1, cm
->msg
.reset
.conn_id
, 1);
175 static int add_conndata(struct sk_buff
*skb
, struct control_msg_out
*cm
,
180 int totallen
= cm
->msg
.conn_data
.datalen
+ 5;
181 int putlen
= min(totallen
, spaceleft
);
183 if (spaceleft
< 25 && totallen
> 25)
186 dst
= skb_put(skb
, putlen
);
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
);
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
);
211 static int add_message(struct sk_buff
*skb
, struct control_msg_out
*cm
,
218 rc
= add_ack(skb
, cm
, spaceleft
);
220 case MSGTYPE_CONNECT
:
221 rc
= add_connect(skb
, cm
, spaceleft
);
223 case MSGTYPE_CONNECT_SUCCESS
:
224 rc
= add_connect_success(skb
, cm
, spaceleft
);
226 case MSGTYPE_CONNECT_FAILED_TEMP
:
227 rc
= add_connect_failed_temp(skb
, cm
, spaceleft
);
229 case MSGTYPE_RESET_CONN
:
230 rc
= add_reset_conn(skb
, cm
, spaceleft
);
232 case MSGTYPE_CONNDATA
:
234 rc
= add_conndata(skb
, cm
, spaceleft
);
240 free_control_msg(cm
);
245 static void padding(struct sk_buff
*skb
, int length
)
247 char *dst
= skb_put(skb
, length
);
249 memset(dst
, KP_PADDING
, length
);
252 static void _send_messages(struct neighbor
*nb
, struct sk_buff
*skb
,
257 while (!list_empty((struct list_head
*) &(nb
->control_msgs_out
))) {
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
);
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))) {
284 int size
= targetmss
;
285 if (size
> nb
->length
)
287 skb
= create_packet_kernel(nb
, size
, GFP_KERNEL
);
289 printk(KERN_ERR
"cor: send_messages: cannot allocate "
290 "skb (out of memory?)");
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
);
311 send_messages(nb
, 1);
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();
324 nb
->timeout
+= target_delay_jiffies
;
326 delay
= nb
->timeout
- jiffies
;
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
,
339 mutex_lock(&(nb
->cmsg_lock
));
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
,
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
,
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
,
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
)
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
)
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
,
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
);