comparison packages/net/common/current/tests/ping_lo_test.c @ 208:e0c0827131d1 ecos

Merge from eCos master repository on 2002-05-20-20:11:54-BST
author jlarmour
date Mon, 20 May 2002 22:19:26 +0000
parents
children db3e0a2fda2f
comparison
equal deleted inserted replaced
207:74c807ddde34 208:e0c0827131d1
1 //==========================================================================
2 //
3 // tests/ping_lo_test.c
4 //
5 // Simple test of PING (ICMP) and networking support
6 //
7 //==========================================================================
8 //####BSDCOPYRIGHTBEGIN####
9 //
10 // -------------------------------------------
11 //
12 // Portions of this software may have been derived from OpenBSD or other sources,
13 // and are covered by the appropriate copyright disclaimers included herein.
14 //
15 // -------------------------------------------
16 //
17 //####BSDCOPYRIGHTEND####
18 //==========================================================================
19 //#####DESCRIPTIONBEGIN####
20 //
21 // Author(s): gthomas, sorin@netappi.com
22 // Contributors: gthomas, sorin@netappi.com
23 // Date: 2000-01-10
24 // Purpose:
25 // Description:
26 //
27 //
28 //####DESCRIPTIONEND####
29 //
30 //==========================================================================
31
32 // PING test code
33
34 #include <network.h>
35
36 #include <cyg/infra/testcase.h>
37
38 #ifndef CYGPKG_LIBC_STDIO
39 #define perror(s) diag_printf(#s ": %s\n", strerror(errno))
40 #endif
41
42 #define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x1000)
43 static char stack[STACK_SIZE];
44 static cyg_thread thread_data;
45 static cyg_handle_t thread_handle;
46
47 #define NUM_PINGS 16
48 #define MAX_PACKET 4096
49 static unsigned char pkt1[MAX_PACKET], pkt2[MAX_PACKET];
50
51 #define UNIQUEID 0x1234
52
53 void
54 pexit(char *s)
55 {
56 CYG_TEST_FAIL_FINISH( s );
57 }
58
59 // Compute INET checksum
60 int
61 inet_cksum(u_short *addr, int len)
62 {
63 register int nleft = len;
64 register u_short *w = addr;
65 register u_short answer;
66 register u_int sum = 0;
67 u_short odd_byte = 0;
68
69 /*
70 * Our algorithm is simple, using a 32 bit accumulator (sum),
71 * we add sequential 16 bit words to it, and at the end, fold
72 * back all the carry bits from the top 16 bits into the lower
73 * 16 bits.
74 */
75 while( nleft > 1 ) {
76 sum += *w++;
77 nleft -= 2;
78 }
79
80 /* mop up an odd byte, if necessary */
81 if( nleft == 1 ) {
82 *(u_char *)(&odd_byte) = *(u_char *)w;
83 sum += odd_byte;
84 }
85
86 /*
87 * add back carry outs from top 16 bits to low 16 bits
88 */
89 sum = (sum >> 16) + (sum & 0x0000ffff); /* add hi 16 to low 16 */
90 sum += (sum >> 16); /* add carry */
91 answer = ~sum; /* truncate to 16 bits */
92 return (answer);
93 }
94
95 static int
96 show_icmp(unsigned char *pkt, int len,
97 struct sockaddr_in *from, struct sockaddr_in *to)
98 {
99 cyg_tick_count_t *tp, tv;
100 struct ip *ip;
101 struct icmp *icmp;
102 tv = cyg_current_time();
103 ip = (struct ip *)pkt;
104 if ((len < sizeof(*ip)) || ip->ip_v != IPVERSION) {
105 diag_printf("%s: Short packet or not IP! - Len: %d, Version: %d\n",
106 inet_ntoa(from->sin_addr), len, ip->ip_v);
107 return 0;
108 }
109 icmp = (struct icmp *)(pkt + sizeof(*ip));
110 len -= (sizeof(*ip) + 8);
111 tp = (cyg_tick_count_t *)&icmp->icmp_data;
112 if (icmp->icmp_type != ICMP_ECHOREPLY) {
113 diag_printf("%s: Invalid ICMP - type: %d\n",
114 inet_ntoa(from->sin_addr), icmp->icmp_type);
115 return 0;
116 }
117 if (icmp->icmp_id != UNIQUEID) {
118 diag_printf("%s: ICMP received for wrong id - sent: %x, recvd: %x\n",
119 inet_ntoa(from->sin_addr), UNIQUEID, icmp->icmp_id);
120 }
121 diag_printf("%d bytes from %s: ", len, inet_ntoa(from->sin_addr));
122 diag_printf("icmp_seq=%d", icmp->icmp_seq);
123 diag_printf(", time=%dms\n", (int)(tv - *tp)*10);
124 return (from->sin_addr.s_addr == to->sin_addr.s_addr);
125 }
126
127 static void
128 ping_host(int s, struct sockaddr_in *host)
129 {
130 struct icmp *icmp = (struct icmp *)pkt1;
131 int icmp_len = 64;
132 int seq, ok_recv, bogus_recv;
133 cyg_tick_count_t *tp;
134 long *dp;
135 struct sockaddr_in from;
136 int i, len, fromlen;
137
138 ok_recv = 0;
139 bogus_recv = 0;
140 diag_printf("PING server %s\n", inet_ntoa(host->sin_addr));
141 for (seq = 0; seq < NUM_PINGS; seq++) {
142 // Build ICMP packet
143 icmp->icmp_type = ICMP_ECHO;
144 icmp->icmp_code = 0;
145 icmp->icmp_cksum = 0;
146 icmp->icmp_seq = seq;
147 icmp->icmp_id = 0x1234;
148 // Set up ping data
149 tp = (cyg_tick_count_t *)&icmp->icmp_data;
150 *tp++ = cyg_current_time();
151 dp = (long *)tp;
152 for (i = sizeof(*tp); i < icmp_len; i += sizeof(*dp)) {
153 *dp++ = i;
154 }
155 // Add checksum
156 icmp->icmp_cksum = inet_cksum( (u_short *)icmp, icmp_len+8);
157 // Send it off
158 if (sendto(s, icmp, icmp_len+8, 0, (struct sockaddr *)host, sizeof(*host)) < 0) {
159 perror("sendto");
160 continue;
161 }
162 // Wait for a response
163 fromlen = sizeof(from);
164 len = recvfrom(s, pkt2, sizeof(pkt2), 0, (struct sockaddr *)&from, &fromlen);
165 if (len < 0) {
166 perror("recvfrom");
167 } else {
168 if (show_icmp(pkt2, len, &from, host)) {
169 ok_recv++;
170 } else {
171 bogus_recv++;
172 }
173 }
174 }
175 diag_printf("Sent %d packets, received %d OK, %d bad\n", NUM_PINGS, ok_recv, bogus_recv);
176 }
177
178 static void
179 ping_test_loopback( int lo )
180 {
181 struct protoent *p;
182 struct timeval tv;
183 struct sockaddr_in host;
184 int s;
185
186 if ((p = getprotobyname("icmp")) == (struct protoent *)0) {
187 perror("getprotobyname");
188 return;
189 }
190 s = socket(AF_INET, SOCK_RAW, p->p_proto);
191 if (s < 0) {
192 perror("socket");
193 return;
194 }
195 tv.tv_sec = 1;
196 tv.tv_usec = 0;
197 setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
198 // Set up host address
199 host.sin_family = AF_INET;
200 host.sin_len = sizeof(host);
201 host.sin_addr.s_addr = htonl(INADDR_LOOPBACK + (0x100 * lo));
202 host.sin_port = 0;
203 ping_host(s, &host);
204 // Now try a bogus host
205 host.sin_addr.s_addr = htonl(ntohl(host.sin_addr.s_addr) + 32);
206 ping_host(s, &host);
207 }
208
209 void
210 net_test(cyg_addrword_t p)
211 {
212 int i;
213 diag_printf("Start PING test\n");
214 init_all_network_interfaces();
215 #if NLOOP > 0
216 for ( i = 0; i < NLOOP; i++ )
217 ping_test_loopback( i );
218 for ( i = 0; i < NLOOP; i++ )
219 ping_test_loopback( i );
220 CYG_TEST_PASS_FINISH( "Done pinging loopback" );
221 #endif
222 CYG_TEST_NA( "No loopback devs" );
223 }
224
225 void
226 cyg_start(void)
227 {
228 CYG_TEST_INIT();
229
230 // Create a main thread, so we can run the scheduler and have time 'pass'
231 cyg_thread_create(CYGPKG_NET_THREAD_PRIORITY-4,// Priority - just a number
232 net_test, // entry
233 0, // entry parameter
234 "Loopback ping test", // Name
235 &stack[0], // Stack
236 STACK_SIZE, // Size
237 &thread_handle, // Handle
238 &thread_data // Thread data structure
239 );
240 cyg_thread_resume(thread_handle); // Start it
241 cyg_scheduler_start();
242 }