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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [net/] [common/] [current/] [tests/] [ping_test.c] - Blame information for rev 857

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      tests/ping_test.c
4
//
5
//      Simple test of PING (ICMP) and networking support
6
//
7
//==========================================================================
8
// ####BSDALTCOPYRIGHTBEGIN####                                             
9
// -------------------------------------------                              
10
// Portions of this software may have been derived from FreeBSD, OpenBSD,   
11
// or other sources, and if so are covered by the appropriate copyright     
12
// and license included herein.                                             
13
// -------------------------------------------                              
14
// ####BSDALTCOPYRIGHTEND####                                               
15
//==========================================================================
16
//#####DESCRIPTIONBEGIN####
17
//
18
// Author(s):    gthomas
19
// Contributors: gthomas, andrew.lunn@ascom.ch
20
// Date:         2000-01-10
21
// Purpose:      
22
// Description:  
23
//              
24
//
25
//####DESCRIPTIONEND####
26
//
27
//==========================================================================
28
 
29
// PING test code
30
 
31
#include <network.h>
32
#ifdef CYGPKG_NET_INET6
33
#include <netinet/ip6.h>
34
#include <netinet/icmp6.h>
35
#endif
36
 
37
#include <pkgconf/system.h>
38
#include <pkgconf/net.h>
39
 
40
#include <cyg/infra/testcase.h>
41
 
42
#ifdef CYGBLD_DEVS_ETH_DEVICE_H    // Get the device config if it exists
43
#include CYGBLD_DEVS_ETH_DEVICE_H  // May provide CYGTST_DEVS_ETH_TEST_NET_REALTIME
44
#endif
45
 
46
#ifdef CYGPKG_NET_TESTS_USE_RT_TEST_HARNESS // do we use the rt test?
47
# ifdef CYGTST_DEVS_ETH_TEST_NET_REALTIME // Get the test ancilla if it exists
48
#  include CYGTST_DEVS_ETH_TEST_NET_REALTIME
49
# endif
50
#endif
51
 
52
// Fill in the blanks if necessary
53
#ifndef TNR_OFF
54
# define TNR_OFF()
55
#endif
56
#ifndef TNR_ON
57
# define TNR_ON()
58
#endif
59
#ifndef TNR_INIT
60
# define TNR_INIT()
61
#endif
62
#ifndef TNR_PRINT_ACTIVITY
63
# define TNR_PRINT_ACTIVITY()
64
#endif
65
 
66
 
67
 
68
#ifndef CYGPKG_LIBC_STDIO
69
#define perror(s) diag_printf(#s ": %s\n", strerror(errno))
70
#endif
71
 
72
#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x1000)
73
static char stack[STACK_SIZE];
74
static cyg_thread thread_data;
75
static cyg_handle_t thread_handle;
76
 
77
#define NUM_PINGS 16
78
#define MAX_PACKET 4096
79
#define MIN_PACKET   64
80
#define MAX_SEND   4000
81
 
82
#define PACKET_ADD  ((MAX_SEND - MIN_PACKET)/NUM_PINGS)
83
#define nPACKET_ADD  1 
84
 
85
static unsigned char pkt1[MAX_PACKET], pkt2[MAX_PACKET];
86
 
87
#define UNIQUEID 0x1234
88
 
89
void
90
pexit(char *s)
91
{
92
    CYG_TEST_FAIL_FINISH(s);
93
}
94
 
95
// Compute INET checksum
96
int
97
inet_cksum(u_short *addr, int len)
98
{
99
    register int nleft = len;
100
    register u_short *w = addr;
101
    register u_short answer;
102
    register u_int sum = 0;
103
    u_short odd_byte = 0;
104
 
105
    /*
106
     *  Our algorithm is simple, using a 32 bit accumulator (sum),
107
     *  we add sequential 16 bit words to it, and at the end, fold
108
     *  back all the carry bits from the top 16 bits into the lower
109
     *  16 bits.
110
     */
111
    while( nleft > 1 )  {
112
        sum += *w++;
113
        nleft -= 2;
114
    }
115
 
116
    /* mop up an odd byte, if necessary */
117
    if( nleft == 1 ) {
118
        *(u_char *)(&odd_byte) = *(u_char *)w;
119
        sum += odd_byte;
120
    }
121
 
122
    /*
123
     * add back carry outs from top 16 bits to low 16 bits
124
     */
125
    sum = (sum >> 16) + (sum & 0x0000ffff); /* add hi 16 to low 16 */
126
    sum += (sum >> 16);                     /* add carry */
127
    answer = ~sum;                          /* truncate to 16 bits */
128
    return (answer);
129
}
130
 
131
static int
132
show_icmp(unsigned char *pkt, int len,
133
          struct sockaddr_in *from, struct sockaddr_in *to)
134
{
135
    cyg_tick_count_t *tp, tv;
136
    struct ip *ip;
137
    struct icmp *icmp;
138
    tv = cyg_current_time();
139
    ip = (struct ip *)pkt;
140
    if ((len < sizeof(*ip)) || ip->ip_v != IPVERSION) {
141
        diag_printf("%s: Short packet or not IP! - Len: %d, Version: %d\n",
142
                    inet_ntoa(from->sin_addr), len, ip->ip_v);
143
        return 0;
144
    }
145
    icmp = (struct icmp *)(pkt + sizeof(*ip));
146
    len -= (sizeof(*ip) + 8);
147
    tp = (cyg_tick_count_t *)&icmp->icmp_data;
148
    if (icmp->icmp_type != ICMP_ECHOREPLY) {
149
        diag_printf("%s: Invalid ICMP - type: %d\n",
150
                    inet_ntoa(from->sin_addr), icmp->icmp_type);
151
        return 0;
152
    }
153
    if (icmp->icmp_id != UNIQUEID) {
154
        diag_printf("%s: ICMP received for wrong id - sent: %x, recvd: %x\n",
155
                    inet_ntoa(from->sin_addr), UNIQUEID, icmp->icmp_id);
156
    }
157
    diag_printf("%d bytes from %s: ", len, inet_ntoa(from->sin_addr));
158
    diag_printf("icmp_seq=%d", icmp->icmp_seq);
159
    diag_printf(", time=%dms\n", (int)(tv - *tp)*10);
160
    return (from->sin_addr.s_addr == to->sin_addr.s_addr);
161
}
162
 
163
static void
164
ping_host(int s, struct sockaddr_in *host)
165
{
166
    struct icmp *icmp = (struct icmp *)pkt1;
167
    int icmp_len = MIN_PACKET;
168
    int seq, ok_recv, bogus_recv;
169
    cyg_tick_count_t *tp;
170
    long *dp;
171
    struct sockaddr_in from;
172
    int i, len;
173
    socklen_t fromlen;
174
 
175
    ok_recv = 0;
176
    bogus_recv = 0;
177
    diag_printf("PING server %s\n", inet_ntoa(host->sin_addr));
178
    for (seq = 0;  seq < NUM_PINGS;  seq++, icmp_len += PACKET_ADD ) {
179
        TNR_ON();
180
        // Build ICMP packet
181
        icmp->icmp_type = ICMP_ECHO;
182
        icmp->icmp_code = 0;
183
        icmp->icmp_cksum = 0;
184
        icmp->icmp_seq = seq;
185
        icmp->icmp_id = 0x1234;
186
        // Set up ping data
187
        tp = (cyg_tick_count_t *)&icmp->icmp_data;
188
        *tp++ = cyg_current_time();
189
        dp = (long *)tp;
190
        for (i = sizeof(*tp);  i < icmp_len;  i += sizeof(*dp)) {
191
            *dp++ = i;
192
        }
193
        // Add checksum
194
        icmp->icmp_cksum = inet_cksum( (u_short *)icmp, icmp_len+8);
195
        // Send it off
196
        if (sendto(s, icmp, icmp_len+8, 0, (struct sockaddr *)host, sizeof(*host)) < 0) {
197
            TNR_OFF();
198
            perror("sendto");
199
            continue;
200
        }
201
        // Wait for a response
202
        fromlen = sizeof(from);
203
        len = recvfrom(s, pkt2, sizeof(pkt2), 0, (struct sockaddr *)&from, &fromlen);
204
        TNR_OFF();
205
        if (len < 0) {
206
            perror("recvfrom");
207
            icmp_len = MIN_PACKET - PACKET_ADD; // just in case - long routes
208
        } else {
209
            if (show_icmp(pkt2, len, &from, host)) {
210
                ok_recv++;
211
            } else {
212
                bogus_recv++;
213
            }
214
        }
215
    }
216
    TNR_OFF();
217
    diag_printf("Sent %d packets, received %d OK, %d bad\n", NUM_PINGS, ok_recv, bogus_recv);
218
}
219
 
220
#ifdef CYGPKG_NET_INET6
221
static int
222
show6_icmp(unsigned char *pkt, int len,
223
          const struct sockaddr_in6 *from, const struct sockaddr_in6 *to)
224
{
225
    cyg_tick_count_t *tp, tv;
226
    struct icmp6_hdr *icmp;
227
    char fromnamebuf[128];
228
    char tonamebuf[128];
229
    int error;
230
 
231
    error = getnameinfo((struct sockaddr *)from,sizeof(*from),
232
                        fromnamebuf, sizeof(fromnamebuf),
233
                        NULL, 0,
234
                        NI_NUMERICHOST);
235
    if (error) {
236
      perror ("getnameinfo(from)");
237
      return 0;
238
    }
239
 
240
    error = getnameinfo((struct sockaddr *)to,sizeof(*to),
241
                        tonamebuf, sizeof(tonamebuf),
242
                        NULL, 0,
243
                        NI_NUMERICHOST);
244
    if (error) {
245
      perror ("getnameinfo(to)");
246
      return 0;
247
    }
248
 
249
    tv = cyg_current_time();
250
    icmp = (struct icmp6_hdr *)pkt;
251
    tp = (cyg_tick_count_t *)&icmp->icmp6_data8[4];
252
 
253
    if (icmp->icmp6_type != ICMP6_ECHO_REPLY) {
254
        return 0;
255
    }
256
    if (icmp->icmp6_id != UNIQUEID) {
257
        diag_printf("%s: ICMP received for wrong id - sent: %x, recvd: %x\n",
258
                    fromnamebuf, UNIQUEID, icmp->icmp6_id);
259
    }
260
    diag_printf("%d bytes from %s: ", len, fromnamebuf);
261
    diag_printf("icmp_seq=%d", icmp->icmp6_seq);
262
    diag_printf(", time=%dms\n", (int)(tv - *tp)*10);
263
    return (!memcmp(&from->sin6_addr, &to->sin6_addr,sizeof(from->sin6_addr)));
264
}
265
 
266
static void
267
ping6_host(int s, const struct sockaddr_in6 *host)
268
{
269
    struct icmp6_hdr *icmp = (struct icmp6_hdr *)pkt1;
270
    int icmp_len = 64;
271
    int seq, ok_recv, bogus_recv;
272
    cyg_tick_count_t *tp;
273
    long *dp;
274
    struct sockaddr_in6 from;
275
    int i, len, fromlen;
276
    char namebuf[128];
277
    int error;
278
    int echo_responce;
279
 
280
    ok_recv = 0;
281
    bogus_recv = 0;
282
    error = getnameinfo((struct sockaddr *)host,sizeof(*host),
283
                        namebuf, sizeof(namebuf),
284
                        NULL, 0,
285
                        NI_NUMERICHOST);
286
    if (error) {
287
      perror ("getnameinfo");
288
    } else {
289
      diag_printf("PING6 server %s\n", namebuf);
290
    }
291
    for (seq = 0;  seq < NUM_PINGS;  seq++) {
292
        // Build ICMP packet
293
        icmp->icmp6_type = ICMP6_ECHO_REQUEST;
294
        icmp->icmp6_code = 0;
295
        icmp->icmp6_cksum = 0;
296
        icmp->icmp6_seq = seq;
297
        icmp->icmp6_id = UNIQUEID;
298
 
299
        // Set up ping data
300
        tp = (cyg_tick_count_t *)&icmp->icmp6_data8[4];
301
        *tp++ = cyg_current_time();
302
        dp = (long *)tp;
303
        for (i = sizeof(*tp);  i < icmp_len;  i += sizeof(*dp)) {
304
            *dp++ = i;
305
        }
306
        // Add checksum
307
        icmp->icmp6_cksum = inet_cksum( (u_short *)icmp, icmp_len+8);
308
        // Send it off
309
        if (sendto(s, icmp, icmp_len+8, 0, (struct sockaddr *)host,
310
                   sizeof(*host)) < 0) {
311
            perror("sendto");
312
            continue;
313
        }
314
        // Wait for a response. We get our own ECHO_REQUEST and the responce
315
        echo_responce = 0;
316
        while (!echo_responce) {
317
          fromlen = sizeof(from);
318
          len = recvfrom(s, pkt2, sizeof(pkt2), 0, (struct sockaddr *)&from,
319
                         &fromlen);
320
          if (len < 0) {
321
            perror("recvfrom");
322
            echo_responce=1;
323
          } else {
324
            if (show6_icmp(pkt2, len, &from, host)) {
325
              ok_recv++;
326
              echo_responce=1;
327
            }
328
          }
329
        }
330
    }
331
    diag_printf("Sent %d packets, received %d OK, %d bad\n", NUM_PINGS,
332
                ok_recv, bogus_recv);
333
}
334
 
335
static void
336
ping6_test( struct sockaddr_in6 *host)
337
{
338
    struct protoent *p;
339
    struct timeval tv;
340
    struct sockaddr_in6 addr;
341
    int s;
342
 
343
    if ((p = getprotobyname("ipv6-icmp")) == (struct protoent *)0) {
344
        perror("getprotobyname");
345
        return;
346
    }
347
    s = socket(AF_INET6, SOCK_RAW, p->p_proto);
348
    if (s < 0) {
349
        perror("socket");
350
        return;
351
    }
352
    tv.tv_sec = 1;
353
    tv.tv_usec = 0;
354
    setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
355
 
356
    ping6_host(s, host);
357
 
358
    // Now try a bogus host
359
    memcpy(&addr,host,sizeof(addr));
360
    addr.sin6_addr.s6_addr[15] = addr.sin6_addr.s6_addr[15] + 32;
361
    ping6_host(s, &addr);
362
}
363
#endif
364
 
365
#ifdef CYGPKG_PROFILE_GPROF
366
#include <cyg/profile/profile.h>
367
 
368
extern char _stext, _etext;  // Defined by the linker
369
 
370
static void
371
start_profile(void)
372
{
373
    // This starts up the system-wide profiling, gathering
374
    // profile information on all of the code, with a 16 byte
375
    // "bucket" size, at a rate of 100us/profile hit.
376
    // Note: a bucket size of 16 will give pretty good function
377
    //       resolution.  Much smaller and the buffer becomes
378
    //       much too large for very little gain.
379
    // Note: a timer period of 100us is also a reasonable
380
    //       compromise.  Any smaller and the overhead of 
381
    //       handling the timter (profile) interrupt could
382
    //       swamp the system.  A fast processor might get
383
    //       by with a smaller value, but a slow one could
384
    //       even be swamped by this value.  If the value is
385
    //       too large, the usefulness of the profile is reduced.
386
    profile_on(&_stext, &_etext, 16, 100);
387
}
388
#endif
389
 
390
static void
391
ping_test(struct bootp *bp)
392
{
393
    struct protoent *p;
394
    struct timeval tv;
395
    struct sockaddr_in host;
396
    int s;
397
 
398
    if ((p = getprotobyname("icmp")) == (struct protoent *)0) {
399
        pexit("getprotobyname");
400
        return;
401
    }
402
    s = socket(AF_INET, SOCK_RAW, p->p_proto);
403
    if (s < 0) {
404
        pexit("socket");
405
        return;
406
    }
407
    tv.tv_sec = 1;
408
    tv.tv_usec = 0;
409
    setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
410
    // Set up host address
411
    host.sin_family = AF_INET;
412
    host.sin_len = sizeof(host);
413
    host.sin_addr = bp->bp_siaddr;
414
    host.sin_port = 0;
415
    ping_host(s, &host);
416
    // Now try a bogus host
417
    host.sin_addr.s_addr = htonl(ntohl(host.sin_addr.s_addr) + 32);
418
    ping_host(s, &host);
419
}
420
 
421
void
422
net_test(cyg_addrword_t p)
423
{
424
#ifdef CYGPKG_NET_INET6
425
    struct sockaddr_in6 ipv6router;
426
#endif
427
 
428
    diag_printf("Start PING test\n");
429
    TNR_INIT();
430
    init_all_network_interfaces();
431
#ifdef CYGPKG_PROFILE_GPROF
432
    start_profile();
433
#endif
434
#ifdef CYGHWR_NET_DRIVER_ETH0
435
    if (eth0_up) {
436
        ping_test(&eth0_bootp_data);
437
    }
438
#endif
439
#ifdef CYGHWR_NET_DRIVER_ETH1
440
    if (eth1_up) {
441
        ping_test(&eth1_bootp_data);
442
    }
443
#endif
444
#ifdef CYGPKG_NET_INET6
445
    if (cyg_net_get_ipv6_advrouter(&ipv6router)) {
446
      ping6_test(&ipv6router);
447
    } else {
448
      CYG_TEST_FAIL("No router advertisement recieved");
449
    }
450
#endif
451
    TNR_PRINT_ACTIVITY();
452
    CYG_TEST_PASS_FINISH("Ping test OK");
453
}
454
 
455
void
456
cyg_start(void)
457
{
458
    // Create a main thread, so we can run the scheduler and have time 'pass'
459
    cyg_thread_create(10,                // Priority - just a number
460
                      net_test,          // entry
461
                      0,                 // entry parameter
462
                      "Network test",    // Name
463
                      &stack[0],         // Stack
464
                      STACK_SIZE,        // Size
465
                      &thread_handle,    // Handle
466
                      &thread_data       // Thread data structure
467
            );
468
    cyg_thread_resume(thread_handle);  // Start it
469
    cyg_scheduler_start();
470
}

powered by: WebSVN 2.1.0

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