]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/net/common/v2_0/tests/flood.c
Initial revision
[karo-tx-redboot.git] / packages / net / common / v2_0 / tests / flood.c
1 //==========================================================================
2 //
3 //      tests/flood.c
4 //
5 //      Flood PING test
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, hmt
22 // Contributors: gthomas
23 // Date:         2000-05-03
24 // Purpose:      
25 // Description:  
26 //              
27 //
28 //####DESCRIPTIONEND####
29 //
30 //==========================================================================
31
32 #include <pkgconf/system.h>
33 #include <pkgconf/net.h>
34
35 #ifdef CYGBLD_DEVS_ETH_DEVICE_H    // Get the device config if it exists
36 #include CYGBLD_DEVS_ETH_DEVICE_H  // May provide CYGTST_DEVS_ETH_TEST_NET_REALTIME
37 #endif
38
39 #ifdef CYGPKG_NET_TESTS_USE_RT_TEST_HARNESS // do we use the rt test?
40 # ifdef CYGTST_DEVS_ETH_TEST_NET_REALTIME // Get the test ancilla if it exists
41 #  include CYGTST_DEVS_ETH_TEST_NET_REALTIME
42 # endif
43 #endif
44
45
46 // Fill in the blanks if necessary
47 #ifndef TNR_OFF
48 # define TNR_OFF()
49 #endif
50 #ifndef TNR_ON
51 # define TNR_ON()
52 #endif
53 #ifndef TNR_INIT
54 # define TNR_INIT()
55 #endif
56 #ifndef TNR_PRINT_ACTIVITY
57 # define TNR_PRINT_ACTIVITY()
58 #endif
59
60
61 // FLOOD PING test code
62
63 #include <network.h>
64
65 #define MAX_PACKET 4096
66
67 #define NUMTHREADS 3
68 #define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + MAX_PACKET + MAX_PACKET + 0x1000)
69 static char thread_stack[NUMTHREADS][STACK_SIZE];
70 static cyg_thread thread_data[NUMTHREADS];
71 static cyg_handle_t thread_handle[NUMTHREADS];
72
73 #define DO_DUMPSTATS( seq ) (0 == (0xffff & seq))
74
75 #ifdef CYGHWR_NET_DRIVER_ETH0
76 struct sockaddr_in host0;
77 #endif
78 #ifdef CYGHWR_NET_DRIVER_ETH1
79 struct sockaddr_in host1;
80 #endif
81 static int sock;
82
83 static int uniqueid[3] = { 0x1234, 0x4321, 0xdead };
84
85 static int ok_recv[3] = { 0,0,0 };
86 static int bogus_recv[3] = { 0,0,0 };
87 static int pings_sent[3] = { 0,0,0 };
88
89 extern void cyg_kmem_print_stats( void );
90
91 extern void
92 cyg_test_exit(void);
93
94 void
95 pexit(char *s)
96 {
97     perror(s);
98     cyg_test_exit();
99 }
100
101 // ------------------------------------------------------------------------
102 static void dumpstats(void)
103 {
104     TNR_OFF();
105     diag_printf( "------------------------\n" );
106 #ifdef CYGHWR_NET_DRIVER_ETH0
107     if (eth0_up) {
108         diag_printf("%16s: Sent %d packets, received %d OK, %d bad\n",
109                     inet_ntoa(host0.sin_addr), pings_sent[0],
110                     ok_recv[0], bogus_recv[0]);
111     }
112 #endif
113 #ifdef CYGHWR_NET_DRIVER_ETH1
114     if (eth1_up) {
115         diag_printf("%16s: Sent %d packets, received %d OK, %d bad\n",
116                     inet_ntoa(host1.sin_addr), pings_sent[1],
117                     ok_recv[1], bogus_recv[1]);
118     }
119 #endif
120     if ( pings_sent[2] )
121         diag_printf("Wierd!  %d unknown sends!\n", pings_sent[2] );
122     if ( ok_recv[2] )
123         diag_printf("Wierd!  %d unknown good recvs!\n", ok_recv[2] );
124     if ( bogus_recv[2] )
125         diag_printf("Wierd!  %d unknown bogus recvs!\n", bogus_recv[2] );
126     cyg_kmem_print_stats();
127     diag_printf( "------------------------\n" );
128     TNR_ON();
129 }
130
131
132 // ------------------------------------------------------------------------
133 // Compute INET checksum
134 int
135 inet_cksum(u_short *addr, int len)
136 {
137     register int nleft = len;
138     register u_short *w = addr;
139     register u_short answer;
140     register u_int sum = 0;
141     u_short odd_byte = 0;
142
143     /*
144      *  Our algorithm is simple, using a 32 bit accumulator (sum),
145      *  we add sequential 16 bit words to it, and at the end, fold
146      *  back all the carry bits from the top 16 bits into the lower
147      *  16 bits.
148      */
149     while( nleft > 1 )  {
150         sum += *w++;
151         nleft -= 2;
152     }
153
154     /* mop up an odd byte, if necessary */
155     if( nleft == 1 ) {
156         *(u_char *)(&odd_byte) = *(u_char *)w;
157         sum += odd_byte;
158     }
159
160     /*
161      * add back carry outs from top 16 bits to low 16 bits
162      */
163     sum = (sum >> 16) + (sum & 0x0000ffff); /* add hi 16 to low 16 */
164     sum += (sum >> 16);                     /* add carry */
165     answer = ~sum;                          /* truncate to 16 bits */
166     return (answer);
167 }
168
169 // ------------------------------------------------------------------------
170 static void
171 show_icmp(unsigned char *pkt, int len, struct sockaddr_in *from)
172 {
173     cyg_tick_count_t *tp, tv;
174     struct ip *ip;
175     struct icmp *icmp;
176     int which = 2;
177     tv = cyg_current_time();
178 #ifdef CYGHWR_NET_DRIVER_ETH0
179     if (eth0_up && (from->sin_addr.s_addr == host0.sin_addr.s_addr) )
180         which = 0;
181 #endif
182 #ifdef CYGHWR_NET_DRIVER_ETH1
183     if (eth1_up && (from->sin_addr.s_addr == host1.sin_addr.s_addr) )
184         which = 1;
185 #endif
186
187     ip = (struct ip *)pkt;
188     if ((len < sizeof(*ip)) || ip->ip_v != IPVERSION) {
189         diag_printf("%s: Short packet or not IP! - Len: %d, Version: %d\n", 
190                     inet_ntoa(from->sin_addr), len, ip->ip_v);
191         bogus_recv[which]++;
192         return;
193     }
194     icmp = (struct icmp *)(pkt + sizeof(*ip));
195     len -= (sizeof(*ip) + 8);
196     tp = (cyg_tick_count_t *)&icmp->icmp_data;
197     if (icmp->icmp_type != ICMP_ECHOREPLY) {
198         diag_printf("%s: Invalid ICMP - type: %d\n", 
199                     inet_ntoa(from->sin_addr), icmp->icmp_type);
200         bogus_recv[which]++;
201         return;
202     }
203     ok_recv[which]++;
204     if (icmp->icmp_id != uniqueid[which]) {
205         diag_printf("%s: ICMP received for wrong id - sent: %x, recvd: %x\n", 
206                     inet_ntoa(from->sin_addr), uniqueid[which], icmp->icmp_id);
207     }
208 //    diag_printf("%d bytes from %s: ", len, inet_ntoa(from->sin_addr));
209 //    diag_printf("icmp_seq=%d", icmp->icmp_seq);
210 //    diag_printf(", time=%dms\n", (int)(tv - *tp)*10);
211 }
212
213 // ------------------------------------------------------------------------
214 static void
215 floodrecv(cyg_addrword_t p)
216 {
217     unsigned char pkt[MAX_PACKET];
218     struct sockaddr_in from;
219     int len, fromlen;
220
221     diag_printf("PING listener...\n" );
222     for (;;) {
223         // Wait for a response
224         fromlen = sizeof(from);
225         len = recvfrom(sock, pkt, sizeof(pkt), 0,
226                        (struct sockaddr *)&from, &fromlen);
227         if (len < 0)
228             perror("recvfrom");
229         else
230             show_icmp(pkt, len, &from);
231     }
232 }
233
234 // ------------------------------------------------------------------------
235 static void
236 pingsend( int seq, struct sockaddr_in *host,
237           struct icmp *icmp, int icmp_len, int which )
238 {
239     cyg_tick_count_t *tp;
240     long *dp;
241     int i;
242     // Build ICMP packet for interface
243     icmp->icmp_type = ICMP_ECHO;
244     icmp->icmp_code = 0;
245     icmp->icmp_cksum = 0;
246     icmp->icmp_seq = seq;
247     icmp->icmp_id = uniqueid[which];
248     // Set up ping data
249     tp = (cyg_tick_count_t *)&icmp->icmp_data;
250     *tp++ = cyg_current_time();
251     dp = (long *)tp;
252     for (i = sizeof(*tp);  i < icmp_len;  i += sizeof(*dp))
253         *dp++ = i;
254
255     // Add checksum
256     icmp->icmp_cksum = inet_cksum( (u_short *)icmp, icmp_len+8);
257     // Send it off
258     if (sendto(sock, icmp, icmp_len+8, MSG_DONTWAIT,
259               (struct sockaddr *)host, sizeof(*host)) < 0) {
260         perror("sendto");
261     }
262     pings_sent[which]++;
263 }
264
265 // ------------------------------------------------------------------------
266 static void
267 floodsend(cyg_addrword_t param)
268 {
269 #ifdef CYGHWR_NET_DRIVER_ETH0
270     unsigned char pkt0[MAX_PACKET];
271     struct icmp *icmp0 = (struct icmp *)pkt0;
272 #endif
273 #ifdef CYGHWR_NET_DRIVER_ETH1
274     unsigned char pkt1[MAX_PACKET];
275     struct icmp *icmp1 = (struct icmp *)pkt1;
276 #endif
277
278     int icmp_len = 64;
279     int seq;
280
281     for (seq = 0; 1 ; seq++) {
282         if ( DO_DUMPSTATS( seq ) )
283             dumpstats();
284
285 #ifdef CYGHWR_NET_DRIVER_ETH0
286         if (eth0_up)
287             pingsend( seq, &host0, icmp0, icmp_len, 0 );
288 #endif
289 #ifdef CYGHWR_NET_DRIVER_ETH1
290         if (eth1_up)
291             pingsend( seq, &host1, icmp1, icmp_len, 1 );
292 #endif
293     }
294 }
295
296
297 // ------------------------------------------------------------------------
298 void
299 net_test(cyg_addrword_t param)
300 {
301     struct protoent *p;
302
303     diag_printf("Start Flood PING test\n");
304     init_all_network_interfaces();
305     diag_printf("Interfaces up:\n");
306     cyg_kmem_print_stats();
307
308     TNR_INIT();
309
310     if ((p = getprotobyname("icmp")) == (struct protoent *)0) {
311         perror("getprotobyname");
312         return;
313     }
314     sock = socket(AF_INET, SOCK_RAW, p->p_proto);
315     if (sock < 0) {
316         perror("tx socket");
317         return;
318     }
319
320 #ifdef CYGHWR_NET_DRIVER_ETH0
321     if (eth0_up) {
322         host0.sin_family = AF_INET;
323         host0.sin_len = sizeof(host0);
324         host0.sin_addr = eth0_bootp_data.bp_siaddr;
325         host0.sin_port = 0;
326         diag_printf("PING server %16s\n", inet_ntoa(host0.sin_addr));
327     }
328 #endif
329 #ifdef CYGHWR_NET_DRIVER_ETH1
330     if (eth1_up) {
331         host1.sin_family = AF_INET;
332         host1.sin_len = sizeof(host1);
333         host1.sin_addr = eth1_bootp_data.bp_siaddr;
334         host1.sin_port = 0;
335         diag_printf("PING server %16s\n", inet_ntoa(host1.sin_addr));
336     }
337 #endif
338
339     cyg_thread_resume(thread_handle[1]);
340     cyg_thread_resume(thread_handle[2]);
341
342     cyg_thread_delay( 100 ); // let the other threads start and print
343
344     TNR_ON();                // then enable the test
345
346     cyg_thread_delay( 12000 ); // run for a couple of minutes
347
348     TNR_OFF();
349
350     diag_printf("After running:\n");
351     dumpstats();
352     TNR_PRINT_ACTIVITY();
353     cyg_test_exit();
354 }
355
356 // ------------------------------------------------------------------------
357 void
358 cyg_start(void)
359 {
360     // Create a main thread, so we can run the scheduler and have time 'pass'
361     cyg_thread_create(10,                // Priority - just a number
362                       net_test,          // entry
363                       0,                 // entry parameter
364                       "Network test",    // Name
365                      &thread_stack[0][0], // Stack
366                       STACK_SIZE,        // Size
367                       &thread_handle[0], // Handle
368                       &thread_data[0]    // Thread data structure
369             );
370     cyg_thread_resume(thread_handle[0]);  // Start it
371
372     // Create the secondary threads
373     cyg_thread_create(11,                // Priority - just a number
374                       floodrecv,         // entry
375                       0,                 // entry parameter
376                       "Flood Ping Recv", // Name
377                      &thread_stack[1][0], // Stack
378                       STACK_SIZE,        // Size
379                       &thread_handle[1], // Handle
380                       &thread_data[1]    // Thread data structure
381             );
382     cyg_thread_create(12,                // Priority - just a number
383                       floodsend,         // entry
384                       0,                 // entry parameter
385                       "Flood Ping Send", // Name
386                      &thread_stack[2][0], // Stack
387                       STACK_SIZE,        // Size
388                       &thread_handle[2], // Handle
389                       &thread_data[2]    // Thread data structure
390             );
391
392
393     cyg_scheduler_start();
394 }
395
396 // EOF flood.c
397