OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [net/] [autotest/] [current/] [tests/] [floodpingmux.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      autotest/current/tests/floodpingmux.c
4
//
5
//      Flood pinging test, the server floods me and I flood hir.
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
// ####BSDALTCOPYRIGHTBEGIN####                                             
40
// -------------------------------------------                              
41
// Portions of this software may have been derived from FreeBSD, OpenBSD,   
42
// or other sources, and if so are covered by the appropriate copyright     
43
// and license included herein.                                             
44
// -------------------------------------------                              
45
// ####BSDALTCOPYRIGHTEND####                                               
46
//==========================================================================
47
//#####DESCRIPTIONBEGIN####
48
//
49
// Author(s):    hmt,gthomas
50
// Contributors: hmt,gthomas
51
// Date:         2000-10-23
52
// Purpose:      
53
// Description:  
54
//              
55
//
56
//####DESCRIPTIONEND####
57
//
58
//==========================================================================
59
 
60
#include <pkgconf/system.h>
61
 
62
#include <cyg/infra/testcase.h>         // testing infrastructure
63
 
64
#include <pkgconf/net.h>
65
 
66
#ifdef CYGBLD_DEVS_ETH_DEVICE_H    // Get the device config if it exists
67
#include CYGBLD_DEVS_ETH_DEVICE_H  // May provide CYGTST_DEVS_ETH_TEST_NET_REALTIME
68
#endif
69
 
70
#ifdef CYGPKG_NET_TESTS_USE_RT_TEST_HARNESS // do we use the rt test?
71
# ifdef CYGTST_DEVS_ETH_TEST_NET_REALTIME // Get the test ancilla if it exists
72
#  include CYGTST_DEVS_ETH_TEST_NET_REALTIME
73
# endif
74
#endif
75
 
76
 
77
// Fill in the blanks if necessary
78
#ifndef TNR_OFF
79
# define TNR_OFF()
80
#endif
81
#ifndef TNR_ON
82
# define TNR_ON()
83
#endif
84
#ifndef TNR_INIT
85
# define TNR_INIT()
86
#endif
87
#ifndef TNR_PRINT_ACTIVITY
88
# define TNR_PRINT_ACTIVITY()
89
#endif
90
 
91
// ------------------------------------------------------------------------
92
 
93
#include <errno.h>
94
#include <network.h>
95
 
96
#define MAX_PACKET 4096
97
 
98
#define NUMTHREADS 3
99
#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + MAX_PACKET + MAX_PACKET + 0x1000)
100
static char thread_stack[NUMTHREADS][STACK_SIZE];
101
static cyg_thread thread_data[NUMTHREADS];
102
static cyg_handle_t thread_handle[NUMTHREADS];
103
 
104
#define DO_DUMPSTATS( seq ) (0 == (0xffff & seq))
105
 
106
#ifdef CYGHWR_NET_DRIVER_ETH0
107
struct sockaddr_in host0;
108
#endif
109
#ifdef CYGHWR_NET_DRIVER_ETH1
110
struct sockaddr_in host1;
111
#endif
112
static int sock;
113
 
114
static int uniqueid[3] = { 0x1234, 0x4321, 0xdead };
115
 
116
static int ok_recv[3] = { 0,0,0 };
117
static int bogus_recv[3] = { 0,0,0 };
118
static int pings_sent[3] = { 0,0,0 };
119
 
120
// ------------------------------------------------------------------------
121
static void dumpstats(void)
122
{
123
    TNR_OFF();
124
    diag_printf( "------------------------\n" );
125
#ifdef CYGHWR_NET_DRIVER_ETH0
126
    if (eth0_up) {
127
        diag_printf("%16s: Sent %d packets, received %d OK, %d bad\n",
128
                    inet_ntoa(host0.sin_addr), pings_sent[0],
129
                    ok_recv[0], bogus_recv[0]);
130
    }
131
#endif
132
#ifdef CYGHWR_NET_DRIVER_ETH1
133
    if (eth1_up) {
134
        diag_printf("%16s: Sent %d packets, received %d OK, %d bad\n",
135
                    inet_ntoa(host1.sin_addr), pings_sent[1],
136
                    ok_recv[1], bogus_recv[1]);
137
    }
138
#endif
139
    if ( pings_sent[2] )
140
        diag_printf("Wierd!  %d unknown sends!\n", pings_sent[2] );
141
    if ( ok_recv[2] )
142
        diag_printf("Wierd!  %d unknown good recvs!\n", ok_recv[2] );
143
    if ( bogus_recv[2] )
144
        diag_printf("Wierd!  %d unknown bogus recvs!\n", bogus_recv[2] );
145
    diag_printf( "------------------------\n" );
146
    TNR_ON();
147
}
148
 
149
 
150
// ------------------------------------------------------------------------
151
// Compute INET checksum
152
int
153
inet_cksum(u_short *addr, int len)
154
{
155
    register int nleft = len;
156
    register u_short *w = addr;
157
    register u_short answer;
158
    register u_int sum = 0;
159
    u_short odd_byte = 0;
160
 
161
    /*
162
     *  Our algorithm is simple, using a 32 bit accumulator (sum),
163
     *  we add sequential 16 bit words to it, and at the end, fold
164
     *  back all the carry bits from the top 16 bits into the lower
165
     *  16 bits.
166
     */
167
    while( nleft > 1 )  {
168
        sum += *w++;
169
        nleft -= 2;
170
    }
171
 
172
    /* mop up an odd byte, if necessary */
173
    if( nleft == 1 ) {
174
        *(u_char *)(&odd_byte) = *(u_char *)w;
175
        sum += odd_byte;
176
    }
177
 
178
    /*
179
     * add back carry outs from top 16 bits to low 16 bits
180
     */
181
    sum = (sum >> 16) + (sum & 0x0000ffff); /* add hi 16 to low 16 */
182
    sum += (sum >> 16);                     /* add carry */
183
    answer = ~sum;                          /* truncate to 16 bits */
184
    return (answer);
185
}
186
 
187
// ------------------------------------------------------------------------
188
static void
189
show_icmp(unsigned char *pkt, int len, struct sockaddr_in *from)
190
{
191
    cyg_tick_count_t *tp, tv;
192
    struct ip *ip;
193
    struct icmp *icmp;
194
    int which = 2;
195
    tv = cyg_current_time();
196
#ifdef CYGHWR_NET_DRIVER_ETH0
197
    if (eth0_up && (from->sin_addr.s_addr == host0.sin_addr.s_addr) )
198
        which = 0;
199
#endif
200
#ifdef CYGHWR_NET_DRIVER_ETH1
201
    if (eth1_up && (from->sin_addr.s_addr == host1.sin_addr.s_addr) )
202
        which = 1;
203
#endif
204
 
205
    ip = (struct ip *)pkt;
206
    if ((len < sizeof(*ip)) || ip->ip_v != IPVERSION) {
207
        TNR_OFF();
208
        diag_printf("%s: Short packet or not IP! - Len: %d, Version: %d\n",
209
                    inet_ntoa(from->sin_addr), len, ip->ip_v);
210
        TNR_ON();
211
        bogus_recv[which]++;
212
        return;
213
    }
214
    icmp = (struct icmp *)(pkt + sizeof(*ip));
215
    len -= (sizeof(*ip) + 8);
216
    tp = (cyg_tick_count_t *)&icmp->icmp_data;
217
    if (icmp->icmp_type != ICMP_ECHOREPLY) {
218
        TNR_OFF();
219
        diag_printf("%s: Invalid ICMP - type: %d\n",
220
                    inet_ntoa(from->sin_addr), icmp->icmp_type);
221
        TNR_ON();
222
        bogus_recv[which]++;
223
        return;
224
    }
225
    ok_recv[which]++;
226
    if (icmp->icmp_id != uniqueid[which]) {
227
        TNR_OFF();
228
        diag_printf("%s: ICMP received for wrong id - sent: %x, recvd: %x\n",
229
                    inet_ntoa(from->sin_addr), uniqueid[which], icmp->icmp_id);
230
        TNR_ON();
231
    }
232
//    diag_printf("%d bytes from %s: ", len, inet_ntoa(from->sin_addr));
233
//    diag_printf("icmp_seq=%d", icmp->icmp_seq);
234
//    diag_printf(", time=%dms\n", (int)(tv - *tp)*10);
235
}
236
 
237
// ------------------------------------------------------------------------
238
static void
239
floodrecv(cyg_addrword_t p)
240
{
241
    unsigned char pkt[MAX_PACKET];
242
    struct sockaddr_in from;
243
    int len, fromlen;
244
 
245
    diag_printf("PING listener...\n" );
246
    for (;;) {
247
        // Wait for a response
248
        fromlen = sizeof(from);
249
        len = recvfrom(sock, pkt, sizeof(pkt), 0,
250
                       (struct sockaddr *)&from, &fromlen);
251
        if (len < 0)
252
            perror("recvfrom");
253
        else
254
            show_icmp(pkt, len, &from);
255
    }
256
}
257
 
258
// ------------------------------------------------------------------------
259
static void
260
pingsend( int seq, struct sockaddr_in *host,
261
          struct icmp *icmp, int icmp_len, int which )
262
{
263
    cyg_tick_count_t *tp;
264
    long *dp;
265
    int i;
266
    // Build ICMP packet for interface
267
    icmp->icmp_type = ICMP_ECHO;
268
    icmp->icmp_code = 0;
269
    icmp->icmp_cksum = 0;
270
    icmp->icmp_seq = seq;
271
    icmp->icmp_id = uniqueid[which];
272
    // Set up ping data
273
    tp = (cyg_tick_count_t *)&icmp->icmp_data;
274
    *tp++ = cyg_current_time();
275
    dp = (long *)tp;
276
    for (i = sizeof(*tp);  i < icmp_len;  i += sizeof(*dp))
277
        *dp++ = i;
278
 
279
    // Add checksum
280
    icmp->icmp_cksum = inet_cksum( (u_short *)icmp, icmp_len+8);
281
    // Send it off
282
    if (sendto(sock, icmp, icmp_len+8, MSG_DONTWAIT,
283
              (struct sockaddr *)host, sizeof(*host)) < 0) {
284
        perror("sendto");
285
    }
286
    pings_sent[which]++;
287
}
288
 
289
// ------------------------------------------------------------------------
290
static void
291
floodsend(cyg_addrword_t param)
292
{
293
    unsigned char pkt0[MAX_PACKET], pkt1[MAX_PACKET];
294
 
295
    struct icmp *icmp0 = (struct icmp *)pkt0;
296
    struct icmp *icmp1 = (struct icmp *)pkt1;
297
 
298
    int icmp_len = 64;
299
    int seq;
300
 
301
    for (seq = 0; 1 ; seq++) {
302
        if ( DO_DUMPSTATS( seq ) )
303
            dumpstats();
304
 
305
#ifdef CYGHWR_NET_DRIVER_ETH0
306
        if (eth0_up)
307
            pingsend( seq, &host0, icmp0, icmp_len, 0 );
308
#endif
309
#ifdef CYGHWR_NET_DRIVER_ETH1
310
        if (eth1_up)
311
            pingsend( seq, &host1, icmp1, icmp_len, 1 );
312
#endif
313
    }
314
}
315
 
316
 
317
// ------------------------------------------------------------------------
318
 
319
#include "autohost.inl"
320
 
321
static void
322
do_ping_tests(struct bootp *bp, int testtime, int filesize)
323
{
324
    char order[256];
325
    diag_printf( "INFO: telling %s to run 1 flood ping for %d seconds, %d bytes\n",
326
          inet_ntoa(bp->bp_siaddr), testtime, filesize );
327
 
328
    sprintf( order, "%s %s %d %d", "FLOOD_PING",
329
             inet_ntoa(bp->bp_yiaddr),
330
             testtime,
331
             filesize );
332
    autohost_tell( bp, order );
333
}
334
 
335
// ------------------------------------------------------------------------
336
 
337
#define TESTTIME (5 * 60) // Seconds
338
 
339
void
340
net_test(cyg_addrword_t param)
341
{
342
    struct protoent *p;
343
 
344
    diag_printf("Start Flood PING test\n");
345
    init_all_network_interfaces();
346
    diag_printf("Interfaces up:\n");
347
 
348
    if ((p = getprotobyname("icmp")) == (struct protoent *)0) {
349
        perror("getprotobyname");
350
        return;
351
    }
352
    sock = socket(AF_INET, SOCK_RAW, p->p_proto);
353
    if (sock < 0) {
354
        perror("tx socket");
355
        return;
356
    }
357
 
358
#ifdef CYGHWR_NET_DRIVER_ETH0
359
    if (eth0_up) {
360
        host0.sin_family = AF_INET;
361
        host0.sin_len = sizeof(host0);
362
        host0.sin_addr = eth0_bootp_data.bp_siaddr;
363
        host0.sin_port = 0;
364
        diag_printf("PING server %16s\n", inet_ntoa(host0.sin_addr));
365
    }
366
#endif
367
#ifdef CYGHWR_NET_DRIVER_ETH1
368
    if (eth1_up) {
369
        host1.sin_family = AF_INET;
370
        host1.sin_len = sizeof(host1);
371
        host1.sin_addr = eth1_bootp_data.bp_siaddr;
372
        host1.sin_port = 0;
373
        diag_printf("PING server %16s\n", inet_ntoa(host1.sin_addr));
374
    }
375
#endif
376
    autohost_init();
377
 
378
    TNR_INIT();
379
 
380
    // Now command the host to do ping to us...
381
#ifdef CYGHWR_NET_DRIVER_ETH0
382
    if (eth0_up) {
383
        do_ping_tests(&eth0_bootp_data, TESTTIME, 56);
384
    }
385
#endif
386
#ifdef CYGHWR_NET_DRIVER_ETH1
387
    if (eth1_up) {
388
        do_ping_tests(&eth1_bootp_data, TESTTIME, 56);
389
    }
390
#endif
391
 
392
    // And start the threads that make us ping them, and count the results
393
    cyg_thread_resume(thread_handle[1]);
394
    cyg_thread_resume(thread_handle[2]);
395
 
396
    // Let the server run for 5 minutes
397
    cyg_thread_delay(2*100); // let the stuff start up first
398
    TNR_ON();
399
    cyg_thread_delay(TESTTIME*100); // FIXME - assume cS clock.
400
 
401
    // Stop the threads that make us ping them.  Thread [2] is the pinger,
402
    // thread [1] the receiver so that might as well continue.
403
    cyg_thread_suspend(thread_handle[2]);
404
 
405
    // Additional delay 'cos host may be slower than us - and it has to
406
    // complete a transfer anyway:
407
    cyg_thread_delay(  30    *100); // FIXME - assume cS clock.
408
    TNR_OFF();
409
 
410
    autohost_end( 0
411
#ifdef CYGHWR_NET_DRIVER_ETH0
412
                  + eth0_up
413
#endif
414
#ifdef CYGHWR_NET_DRIVER_ETH1
415
                  + eth1_up
416
#endif
417
        ); // check for 2 pass messages from hosts
418
 
419
    diag_printf("After running:\n");
420
    dumpstats();
421
    TNR_OFF(); // dumpstats() turned it on again!
422
    TNR_PRINT_ACTIVITY();
423
    CYG_TEST_EXIT("Done");
424
}
425
 
426
void
427
cyg_start(void)
428
{
429
    // Create a main thread, so we can run the scheduler and have time 'pass'
430
    cyg_thread_create(10,                // Priority - just a number
431
                      net_test,          // entry
432
                      0,                 // entry parameter
433
                      "Network test",    // Name
434
                     &thread_stack[0][0], // Stack
435
                      STACK_SIZE,        // Size
436
                      &thread_handle[0], // Handle
437
                      &thread_data[0]    // Thread data structure
438
            );
439
    cyg_thread_resume(thread_handle[0]);  // Start it
440
 
441
    // Create the secondary threads
442
    cyg_thread_create(11,                // Priority - just a number
443
                      floodrecv,         // entry
444
                      0,                 // entry parameter
445
                      "Flood Ping Recv", // Name
446
                     &thread_stack[1][0], // Stack
447
                      STACK_SIZE,        // Size
448
                      &thread_handle[1], // Handle
449
                      &thread_data[1]    // Thread data structure
450
            );
451
    cyg_thread_create(12,                // Priority - just a number
452
                      floodsend,         // entry
453
                      0,                 // entry parameter
454
                      "Flood Ping Send", // Name
455
                     &thread_stack[2][0], // Stack
456
                      STACK_SIZE,        // Size
457
                      &thread_handle[2], // Handle
458
                      &thread_data[2]    // Thread data structure
459
            );
460
 
461
    cyg_scheduler_start();
462
}
463
 
464
// EOF floodpingmux.c

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.