~ubuntu-branches/ubuntu/utopic/lksctp-tools/utopic-proposed

« back to all changes in this revision

Viewing changes to test/ft_frame_lostpacket.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Biebl
  • Date: 2006-10-19 20:23:28 UTC
  • mfrom: (2.1.6 edgy)
  • Revision ID: james.westby@ubuntu.com-20061019202328-ts63rxlpp07yl2nc
Tags: 1.0.6.dfsg-4
Update maintainer email address to biebl@debian.org. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* SCTP kernel reference Implementation
 
2
 * (C) Copyright IBM Corp. 2001, 2003
 
3
 * Copyright (C) 1999 Cisco and Motorola
 
4
 *
 
5
 * This file is part of the SCTP Linux kernel reference implementation.
 
6
 *
 
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)
 
10
 * any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it
 
13
 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
 
14
 
 
15
 *                 ************************
 
16
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
17
 * See the GNU General Public License for more details.
 
18
 *
 
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.
 
23
 *
 
24
 * Please send any bug reports or fixes you make to one of the following
 
25
 * email addresses:
 
26
 *
 
27
 * La Monte H.P. Yarroll <piggy@acm.org>
 
28
 * Karl Knutson <karl@athena.chicago.il.us>
 
29
 * Sridhar Samudrala <samudrala@us.ibm.com>
 
30
 *
 
31
 * Any bugs reported given to us we will try to fix... any fixes shared will
 
32
 * be incorporated into the next SCTP release.
 
33
 *  
 
34
 */
 
35
 
 
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. 
 
40
 *
 
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
 
45
 * cleanly.
 
46
 *
 
47
 * La Monte H.P. Yarroll <piggy@acm.org>
 
48
 * Karl Knutson <karl@athena.chicago.il.us>
 
49
 *
 
50
 * We use functions which approximate the user level API defined in
 
51
 * draft-stewart-sctpsocket-sigtran-01.txt.  */
 
52
 
 
53
#include <linux/types.h>
 
54
#include <linux/list.h> /* For struct list_head */
 
55
#include <linux/socket.h>
 
56
#include <linux/ip.h>
 
57
#include <linux/time.h> /* For struct timeval */
 
58
#include <net/sock.h>
 
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>
 
64
#include <errno.h>
 
65
#include <funtest.h>
 
66
 
 
67
int
 
68
main(int argc, char *argv[])
 
69
{
 
70
        struct sock *sk1;
 
71
        struct sock *sk2;
 
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;
 
78
 
 
79
        struct sockaddr_in loop;
 
80
        struct msghdr outmsg;
 
81
        struct sctp_cmsghdr cmsghdr;
 
82
        struct iovec iov;
 
83
        struct iovec out_iov;
 
84
        struct msghdr inmessage;
 
85
        uint8_t *big_buffer;
 
86
        uint8_t *messages[] = {
 
87
                "associate",
 
88
                "strike1",
 
89
                "strike2",
 
90
                "strike3",
 
91
                "strikeout",
 
92
                "steal",
 
93
                "home run",
 
94
                "The test frame has a bug!", /* We should NEVER see this... */
 
95
        };
 
96
        int error = 0;
 
97
        int bytes_sent;
 
98
        int addr_len; 
 
99
 
 
100
        /* Do all that random stuff needed to make a sensible
 
101
         * universe.
 
102
         */
 
103
        sctp_init();
 
104
 
 
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);
 
108
        
 
109
        loop.sin_family = AF_INET;
 
110
        loop.sin_addr.s_addr = SCTP_IP_LOOPBACK;
 
111
        
 
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; }
 
116
        
 
117
        loop.sin_port = htons(SCTP_TESTPORT_2);
 
118
        error = test_bind(sk2, (struct sockaddr *)&loop, sizeof(loop));
 
119
        if (error != 0) { DUMP_CORE; }
 
120
        
 
121
        /* Mark sk2 as being able to accept new associations. */
 
122
        if (0 != sctp_seqpacket_listen(sk2, 1)) {
 
123
                DUMP_CORE;
 
124
        }
 
125
 
 
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;
 
134
        
 
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; }
 
140
        
 
141
        error = test_run_network();
 
142
        if (error != 0) { DUMP_CORE; }
 
143
 
 
144
        /* Extract all those nice internal structures we like to muck
 
145
         * with...
 
146
         */
 
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;
 
153
 
 
154
        /* DO NOT PASS THIS LINE WITHOUT SEEING COOKIE ACK AND THE
 
155
         * FIRST SACK!!!!
 
156
         */
 
157
 
 
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);
 
168
 
 
169
        /* Get the communication up message from sk2.  */
 
170
        error = sctp_recvmsg(NULL, sk2, &inmessage, REALLY_BIG,
 
171
                             /* noblock */ 1, /* flags */ 0,
 
172
                             &addr_len);
 
173
        if (error < 0) {DUMP_CORE;}
 
174
 
 
175
        test_frame_check_notification(&inmessage,
 
176
                                      REALLY_BIG,
 
177
                                      sizeof(struct sctp_assoc_change),
 
178
                                      SCTP_ASSOC_CHANGE,
 
179
                                      SCTP_COMM_UP);
 
180
 
 
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);
 
188
 
 
189
        /* Get the communication up message from sk1.  */
 
190
        error = sctp_recvmsg(NULL, sk1, &inmessage, REALLY_BIG,
 
191
                             /* noblock */ 1, /* flags */ 0,
 
192
                             &addr_len);
 
193
        if (error < 0) {
 
194
                printk("recvmsg:  Something went wrong, error: %d\n", error);
 
195
                DUMP_CORE;
 
196
        }
 
197
        test_frame_check_notification(&inmessage,
 
198
                                      REALLY_BIG,
 
199
                                      sizeof(struct sctp_assoc_change),
 
200
                                      SCTP_ASSOC_CHANGE,
 
201
                                      SCTP_COMM_UP);
 
202
 
 
203
 
 
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,
 
213
                             &addr_len);
 
214
        if (error < 0) { DUMP_CORE; }
 
215
 
 
216
        test_frame_check_message(&inmessage,
 
217
                           /* orig */
 
218
                           sizeof(struct sctp_cmsghdr),
 
219
                           REALLY_BIG,
 
220
                           big_buffer,
 
221
                           /* expected */
 
222
                           sizeof(struct sctp_sndrcvinfo),
 
223
                           strlen(messages[0]) + 1,
 
224
                           messages[0],
 
225
                           SCTP_SNDRCV);
 
226
 
 
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; }
 
232
 
 
233
        test_kill_next_packet(SCTP_CID_DATA);
 
234
        error = test_run_network();
 
235
        if (error != 0) { DUMP_CORE; }
 
236
 
 
237
        /* Confirm that we did NOT get the message.  */
 
238
 
 
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);
 
246
 
 
247
        error = sctp_recvmsg(NULL, sk2, &inmessage, REALLY_BIG,
 
248
                             /* noblock */ 1, /* flags */ 0,
 
249
                             &addr_len);
 
250
 
 
251
        if (-EAGAIN != error) {
 
252
                DUMP_CORE;
 
253
        }
 
254
 
 
255
        /* Make the timeout happen.  */
 
256
        jiffies += asoc1->peer.primary_path->rto + 1;
 
257
        test_run_timeout(); /* Internet fast-forward */
 
258
 
 
259
        /* Rerun the network.  */
 
260
 
 
261
        error = test_run_network();
 
262
        if (error != 0) { DUMP_CORE; }
 
263
 
 
264
        /* Confirm that we get the retransmitted message.  */
 
265
 
 
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);
 
272
 
 
273
        error = sctp_recvmsg(NULL, sk2, &inmessage, REALLY_BIG,
 
274
                             /* noblock */ 1, /* flags */ 0,
 
275
                             &addr_len);
 
276
        if (error < 0) { DUMP_CORE; }
 
277
        test_frame_check_message(&inmessage,
 
278
                           /* orig */
 
279
                           sizeof(struct sctp_cmsghdr),
 
280
                           REALLY_BIG,
 
281
                           big_buffer,
 
282
                           /* expected */
 
283
                           sizeof(struct sctp_sndrcvinfo),
 
284
                           strlen(messages[1]) + 1,
 
285
                           messages[1],
 
286
                           SCTP_SNDRCV);
 
287
 
 
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,
 
297
                             &addr_len);
 
298
        if (error != -EAGAIN) { DUMP_CORE; }
 
299
        
 
300
        /* Send another packet because we need a sack.  Yeah, this
 
301
         * will be fixed one day...
 
302
         */
 
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,
 
313
                             &addr_len);
 
314
        if (error < 0) { DUMP_CORE; }
 
315
        test_frame_check_message(&inmessage,
 
316
                           /* orig */
 
317
                           sizeof(struct sctp_cmsghdr),
 
318
                           REALLY_BIG,
 
319
                           big_buffer,
 
320
                           /* expected */
 
321
                           sizeof(struct sctp_sndrcvinfo),
 
322
                           strlen(messages[2]) + 1,
 
323
                           messages[2],
 
324
                           SCTP_SNDRCV);
 
325
 
 
326
        /* 2nd round: network down for 2 consecutive RTO.  See if
 
327
         * DATA goes through in the 3rd retran attempt.
 
328
         */
 
329
 
 
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() ) {
 
334
                DUMP_CORE;
 
335
        } 
 
336
 
 
337
        /* We should NOT see the packet. */
 
338
        test_frame_get_message(sk2, NULL);
 
339
 
 
340
        /* Force the RTO and see the retransmission.  */
 
341
        jiffies += asoc1->peer.primary_path->rto + 1;
 
342
        test_run_timeout();
 
343
        test_for_chunk(SCTP_CID_DATA, 0);
 
344
 
 
345
        /* Lose the retransmission.  */
 
346
        test_kill_next_packet(SCTP_CID_DATA);
 
347
        if ( test_run_network() ) {
 
348
                DUMP_CORE;
 
349
        } 
 
350
 
 
351
        /* We should NOT see the packet.  */
 
352
        test_frame_get_message(sk2, NULL);
 
353
 
 
354
        /* Force the RTO again and see that it goes through.  */
 
355
        jiffies += asoc1->peer.primary_path->rto + 1;
 
356
        if ( test_run_network() ) {
 
357
                DUMP_CORE;
 
358
        } 
 
359
 
 
360
        /* We should now see the packet. */
 
361
        test_frame_get_message(sk2, messages[3]);
 
362
 
 
363
        /* Force the SACK.  */
 
364
        jiffies += asoc1->timeouts[SCTP_EVENT_TIMEOUT_SACK] + 1;
 
365
        if ( test_run_network() ) {
 
366
                DUMP_CORE;
 
367
        } 
 
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.
 
371
         */
 
372
 
 
373
        test_frame_send_message(sk1, (struct sockaddr *)&loop, messages[4]) ;
 
374
 
 
375
        if ( test_run_network() ) {
 
376
                DUMP_CORE;
 
377
        }
 
378
 
 
379
        test_frame_get_message(sk2, messages[4]) ;
 
380
 
 
381
        sctp_close(sk2, 0);
 
382
 
 
383
        /* Force out SACK.  */
 
384
        jiffies += asoc1->timeouts[SCTP_EVENT_TIMEOUT_SACK] + 1;
 
385
        if ( test_run_network() ) {
 
386
                DUMP_CORE
 
387
        }
 
388
        
 
389
        test_frame_get_event(sk1, SCTP_ASSOC_CHANGE, SCTP_SHUTDOWN_COMP);
 
390
        sctp_close(sk1, 0);
 
391
 
 
392
        if (0 == error) {
 
393
                printk("\n\n%s passed\n\n\n", argv[0]);
 
394
        }
 
395
 
 
396
        /* Indicate successful completion.  */
 
397
        exit(0);
 
398
} /* main() */