1
/* SCTP kernel reference Implementation
2
* (C) Copyright IBM Corp. 2001, 2003
3
* Copyright (C) 1999 Cisco and Motorola
5
* This file is part of the SCTP Linux kernel reference implementation.
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2, or (at your option)
12
* This program is distributed in the hope that it
13
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
15
* ************************
16
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
* See the GNU General Public License for more details.
19
* You should have received a copy of the GNU General Public License
20
* along with GNU CC; see the file COPYING. If not, write to
21
* the Free Software Foundation, 59 Temple Place - Suite 330,
22
* Boston, MA 02111-1307, USA.
24
* Please send any bug reports or fixes you make to one of the following
27
* La Monte H.P. Yarroll <piggy@acm.org>
28
* Karl Knutson <karl@athena.chicago.il.us>
29
* Sridhar Samudrala <samudrala@us.ibm.com>
31
* Any bugs reported given to us we will try to fix... any fixes shared will
32
* be incorporated into the next SCTP release.
36
/* ft_frame_lostpacket.c
37
* This is the Functional Test for the ability to handle a lost
38
* packet during data transmission for the SCTP kernel reference
39
* implementation state machine.
41
* It walks the state machine through a modified complete data
42
* exchange where we set up a link, send one data message
43
* successfully, send another data message and have it get lost, time
44
* out and retransmit the second message, and then tear down the link
47
* La Monte H.P. Yarroll <piggy@acm.org>
48
* Karl Knutson <karl@athena.chicago.il.us>
50
* We use functions which approximate the user level API defined in
51
* draft-stewart-sctpsocket-sigtran-01.txt. */
53
#include <linux/types.h>
54
#include <linux/list.h> /* For struct list_head */
55
#include <linux/socket.h>
57
#include <linux/time.h> /* For struct timeval */
59
#include <linux/wait.h> /* For wait_queue_head_t */
60
#include <linux/skbuff.h>
61
#include <linux/errno.h>
62
#include <net/sctp/sctp.h>
63
#include <net/sctp/sm.h>
68
main(int argc, char *argv[])
72
struct sctp_endpoint *ep1;
73
struct sctp_association *asoc1;
74
struct sctp_transport *tran1;
75
struct sctp_endpoint *ep2;
76
struct sctp_association *asoc2;
77
struct sctp_transport *tran2;
79
struct sockaddr_in loop;
81
struct sctp_cmsghdr cmsghdr;
84
struct msghdr inmessage;
86
uint8_t *messages[] = {
94
"The test frame has a bug!", /* We should NEVER see this... */
100
/* Do all that random stuff needed to make a sensible
105
/* Create the two endpoints which will talk to each other. */
106
sk1 = sctp_socket(PF_INET, SOCK_SEQPACKET);
107
sk2 = sctp_socket(PF_INET, SOCK_SEQPACKET);
109
loop.sin_family = AF_INET;
110
loop.sin_addr.s_addr = SCTP_IP_LOOPBACK;
112
/* Bind these sockets to the test ports. */
113
loop.sin_port = htons(SCTP_TESTPORT_1);
114
error = test_bind(sk1, (struct sockaddr *)&loop, sizeof(loop));
115
if (error != 0) { DUMP_CORE; }
117
loop.sin_port = htons(SCTP_TESTPORT_2);
118
error = test_bind(sk2, (struct sockaddr *)&loop, sizeof(loop));
119
if (error != 0) { DUMP_CORE; }
121
/* Mark sk2 as being able to accept new associations. */
122
if (0 != sctp_seqpacket_listen(sk2, 1)) {
126
/* Build up a msghdr structure we can use for all sending. */
127
outmsg.msg_name = &loop;
128
outmsg.msg_namelen = sizeof(loop);
129
outmsg.msg_iov = &out_iov;
130
outmsg.msg_iovlen = 1;
131
outmsg.msg_control = NULL;
132
outmsg.msg_controllen = 0;
133
outmsg.msg_flags = 0;
135
/* Send the first message. This will create the association. */
136
outmsg.msg_iov->iov_base = messages[0];
137
outmsg.msg_iov->iov_len = strlen(messages[0]) + 1;
138
bytes_sent = sctp_sendmsg(NULL, sk1, &outmsg, strlen(messages[0])+1);
139
if (bytes_sent != strlen(messages[0]) + 1) { DUMP_CORE; }
141
error = test_run_network();
142
if (error != 0) { DUMP_CORE; }
144
/* Extract all those nice internal structures we like to muck
147
ep1 = sctp_sk(sk1)->ep;
148
asoc1 = test_ep_first_asoc(ep1);
149
tran1 = (struct sctp_transport *)asoc1->peer.transport_addr_list.next;
150
ep2 = sctp_sk(sk2)->ep;
151
asoc2 = test_ep_first_asoc(ep2);
152
tran2 = (struct sctp_transport *)asoc1->peer.transport_addr_list.next;
154
/* DO NOT PASS THIS LINE WITHOUT SEEING COOKIE ACK AND THE
158
/* NOW initialize inmessage with enough space for DATA... */
159
memset(&inmessage, 0, sizeof(inmessage));
160
big_buffer = kmalloc(REALLY_BIG, GFP_KERNEL);
161
iov.iov_base = big_buffer;
162
iov.iov_len = REALLY_BIG;
163
inmessage.msg_iov = &iov;
164
inmessage.msg_iovlen = 1;
165
/* or a control message. */
166
inmessage.msg_control = &cmsghdr;
167
inmessage.msg_controllen = sizeof(struct sctp_cmsghdr);
169
/* Get the communication up message from sk2. */
170
error = sctp_recvmsg(NULL, sk2, &inmessage, REALLY_BIG,
171
/* noblock */ 1, /* flags */ 0,
173
if (error < 0) {DUMP_CORE;}
175
test_frame_check_notification(&inmessage,
177
sizeof(struct sctp_assoc_change),
181
/* Restore the altered values for the next call... */
182
iov.iov_base = big_buffer;
183
iov.iov_len = REALLY_BIG;
184
inmessage.msg_iov = &iov;
185
inmessage.msg_iovlen = 1;
186
inmessage.msg_control = &cmsghdr;
187
inmessage.msg_controllen = sizeof(struct sctp_cmsghdr);
189
/* Get the communication up message from sk1. */
190
error = sctp_recvmsg(NULL, sk1, &inmessage, REALLY_BIG,
191
/* noblock */ 1, /* flags */ 0,
194
printk("recvmsg: Something went wrong, error: %d\n", error);
197
test_frame_check_notification(&inmessage,
199
sizeof(struct sctp_assoc_change),
204
/* Get the first message which was sent. */
205
iov.iov_base = big_buffer;
206
iov.iov_len = REALLY_BIG;
207
inmessage.msg_iov = &iov;
208
inmessage.msg_iovlen = 1;
209
inmessage.msg_control = &cmsghdr;
210
inmessage.msg_controllen = sizeof(struct sctp_cmsghdr);
211
error = sctp_recvmsg(NULL, sk2, &inmessage, REALLY_BIG,
212
/* noblock */ 1, /* flags */ 0,
214
if (error < 0) { DUMP_CORE; }
216
test_frame_check_message(&inmessage,
218
sizeof(struct sctp_cmsghdr),
222
sizeof(struct sctp_sndrcvinfo),
223
strlen(messages[0]) + 1,
227
/* Send another message. (And lose it! Mwahahaha!) */
228
outmsg.msg_iov->iov_base = messages[1];
229
outmsg.msg_iov->iov_len = strlen(messages[1]) + 1;
230
bytes_sent = sctp_sendmsg(NULL, sk1, &outmsg, strlen(messages[1])+1);
231
if (bytes_sent != strlen(messages[1]) + 1) { DUMP_CORE; }
233
test_kill_next_packet(SCTP_CID_DATA);
234
error = test_run_network();
235
if (error != 0) { DUMP_CORE; }
237
/* Confirm that we did NOT get the message. */
239
/* Restore the altered values for the message receive attempt. */
240
iov.iov_base = big_buffer;
241
iov.iov_len = REALLY_BIG;
242
inmessage.msg_iov = &iov;
243
inmessage.msg_iovlen = 1;
244
inmessage.msg_control = &cmsghdr;
245
inmessage.msg_controllen = sizeof(struct sctp_cmsghdr);
247
error = sctp_recvmsg(NULL, sk2, &inmessage, REALLY_BIG,
248
/* noblock */ 1, /* flags */ 0,
251
if (-EAGAIN != error) {
255
/* Make the timeout happen. */
256
jiffies += asoc1->peer.primary_path->rto + 1;
257
test_run_timeout(); /* Internet fast-forward */
259
/* Rerun the network. */
261
error = test_run_network();
262
if (error != 0) { DUMP_CORE; }
264
/* Confirm that we get the retransmitted message. */
266
iov.iov_base = big_buffer;
267
iov.iov_len = REALLY_BIG;
268
inmessage.msg_iov = &iov;
269
inmessage.msg_iovlen = 1;
270
inmessage.msg_control = &cmsghdr;
271
inmessage.msg_controllen = sizeof(struct sctp_cmsghdr);
273
error = sctp_recvmsg(NULL, sk2, &inmessage, REALLY_BIG,
274
/* noblock */ 1, /* flags */ 0,
276
if (error < 0) { DUMP_CORE; }
277
test_frame_check_message(&inmessage,
279
sizeof(struct sctp_cmsghdr),
283
sizeof(struct sctp_sndrcvinfo),
284
strlen(messages[1]) + 1,
288
/* Check to see that nothing can be read from sk1. */
289
iov.iov_len = REALLY_BIG;
290
iov.iov_base = big_buffer;
291
inmessage.msg_iov = &iov;
292
inmessage.msg_iovlen = 1;
293
inmessage.msg_control = &cmsghdr;
294
inmessage.msg_controllen = sizeof(struct sctp_cmsghdr);
295
error = sctp_recvmsg(NULL, sk1, &inmessage, REALLY_BIG,
296
/* noblock */ 1, /* flags */ 0,
298
if (error != -EAGAIN) { DUMP_CORE; }
300
/* Send another packet because we need a sack. Yeah, this
301
* will be fixed one day...
303
outmsg.msg_iov->iov_base = messages[2];
304
outmsg.msg_iov->iov_len = strlen(messages[2]) + 1;
305
bytes_sent = sctp_sendmsg(NULL, sk1, &outmsg, strlen(messages[2])+1);
306
if (bytes_sent != strlen(messages[2]) + 1) { DUMP_CORE; }
307
error = test_run_network();
308
if (error != 0) { DUMP_CORE; }
309
inmessage.msg_control = &cmsghdr;
310
inmessage.msg_controllen = sizeof(struct sctp_cmsghdr);
311
error = sctp_recvmsg(NULL, sk2, &inmessage, REALLY_BIG,
312
/* noblock */ 1, /* flags */ 0,
314
if (error < 0) { DUMP_CORE; }
315
test_frame_check_message(&inmessage,
317
sizeof(struct sctp_cmsghdr),
321
sizeof(struct sctp_sndrcvinfo),
322
strlen(messages[2]) + 1,
326
/* 2nd round: network down for 2 consecutive RTO. See if
327
* DATA goes through in the 3rd retran attempt.
330
/* Lose the first transmission */
331
test_frame_send_message(sk1, (struct sockaddr *)&loop, messages[3]);
332
test_kill_next_packet(SCTP_CID_DATA);
333
if ( test_run_network() ) {
337
/* We should NOT see the packet. */
338
test_frame_get_message(sk2, NULL);
340
/* Force the RTO and see the retransmission. */
341
jiffies += asoc1->peer.primary_path->rto + 1;
343
test_for_chunk(SCTP_CID_DATA, 0);
345
/* Lose the retransmission. */
346
test_kill_next_packet(SCTP_CID_DATA);
347
if ( test_run_network() ) {
351
/* We should NOT see the packet. */
352
test_frame_get_message(sk2, NULL);
354
/* Force the RTO again and see that it goes through. */
355
jiffies += asoc1->peer.primary_path->rto + 1;
356
if ( test_run_network() ) {
360
/* We should now see the packet. */
361
test_frame_get_message(sk2, messages[3]);
363
/* Force the SACK. */
364
jiffies += asoc1->timeouts[SCTP_EVENT_TIMEOUT_SACK] + 1;
365
if ( test_run_network() ) {
368
/* Test for delayed SHUTDOWN_ACK: let sk2 close the link first,
369
* in the meantime, sk1 still has a backlogged packet to send.
370
* Not until sk1 clears its sendQ, can it generate SHUTDOWN-ACK.
373
test_frame_send_message(sk1, (struct sockaddr *)&loop, messages[4]) ;
375
if ( test_run_network() ) {
379
test_frame_get_message(sk2, messages[4]) ;
383
/* Force out SACK. */
384
jiffies += asoc1->timeouts[SCTP_EVENT_TIMEOUT_SACK] + 1;
385
if ( test_run_network() ) {
389
test_frame_get_event(sk1, SCTP_ASSOC_CHANGE, SCTP_SHUTDOWN_COMP);
393
printk("\n\n%s passed\n\n\n", argv[0]);
396
/* Indicate successful completion. */