Mercurial > ecos
comparison packages/net/tcpip/current/tests/linux_echo.c @ 147:d397fc472bcf
Merge from eCos master repository on 2001-01-05-06:43:02-GMT
| author | jlarmour |
|---|---|
| date | Fri, 05 Jan 2001 17:12:36 +0000 |
| parents | |
| children | 3902ef905c9c |
comparison
equal
deleted
inserted
replaced
| 146:bd918119cf0b | 147:d397fc472bcf |
|---|---|
| 1 //========================================================================== | |
| 2 // | |
| 3 // tests/linux_echo.c | |
| 4 // | |
| 5 // Simple TCP throughput test - echo component FOR LINUX HOST | |
| 6 // * CAUTION: host, i.e. non eCos, only * | |
| 7 // | |
| 8 //========================================================================== | |
| 9 //####COPYRIGHTBEGIN#### | |
| 10 // | |
| 11 // ------------------------------------------- | |
| 12 // The contents of this file are subject to the Red Hat eCos Public License | |
| 13 // Version 1.1 (the "License"); you may not use this file except in | |
| 14 // compliance with the License. You may obtain a copy of the License at | |
| 15 // http://www.redhat.com/ | |
| 16 // | |
| 17 // Software distributed under the License is distributed on an "AS IS" | |
| 18 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the | |
| 19 // License for the specific language governing rights and limitations under | |
| 20 // the License. | |
| 21 // | |
| 22 // The Original Code is eCos - Embedded Configurable Operating System, | |
| 23 // released September 30, 1998. | |
| 24 // | |
| 25 // The Initial Developer of the Original Code is Red Hat. | |
| 26 // Portions created by Red Hat are | |
| 27 // Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc. | |
| 28 // All Rights Reserved. | |
| 29 // ------------------------------------------- | |
| 30 // | |
| 31 //####COPYRIGHTEND#### | |
| 32 //####BSDCOPYRIGHTBEGIN#### | |
| 33 // | |
| 34 // ------------------------------------------- | |
| 35 // | |
| 36 // Portions of this software may have been derived from OpenBSD or other sources, | |
| 37 // and are covered by the appropriate copyright disclaimers included herein. | |
| 38 // | |
| 39 // ------------------------------------------- | |
| 40 // | |
| 41 //####BSDCOPYRIGHTEND#### | |
| 42 //========================================================================== | |
| 43 //#####DESCRIPTIONBEGIN#### | |
| 44 // | |
| 45 // Author(s): gthomas | |
| 46 // Contributors: gthomas | |
| 47 // Date: 2000-01-10 | |
| 48 // Purpose: | |
| 49 // Description: This is the middle part of a three part test. The idea is | |
| 50 // to test the throughput of box in a configuration like this: | |
| 51 // | |
| 52 // +------+ port +----+ port +----+ | |
| 53 // |SOURCE|=========>|ECHO|============>|SINK| | |
| 54 // +------+ 9990 +----+ 9991 +----+ | |
| 55 // | |
| 56 // | |
| 57 //####DESCRIPTIONEND#### | |
| 58 // | |
| 59 //========================================================================== | |
| 60 | |
| 61 #undef _KERNEL | |
| 62 #include <stdlib.h> | |
| 63 #include <unistd.h> | |
| 64 #include <stdio.h> | |
| 65 | |
| 66 #include <sys/param.h> | |
| 67 #include <sys/socket.h> | |
| 68 #include <sys/ioctl.h> | |
| 69 #include <sys/errno.h> | |
| 70 #include <sys/time.h> | |
| 71 | |
| 72 #include <net/if.h> | |
| 73 #include <netinet/in.h> | |
| 74 #include <netinet/ip.h> | |
| 75 #include <netinet/ip_icmp.h> | |
| 76 #include <net/route.h> | |
| 77 | |
| 78 #include <netdb.h> | |
| 79 | |
| 80 #define true 1 | |
| 81 #define false 1 | |
| 82 | |
| 83 #define TNR_ON() | |
| 84 #define TNR_OFF() | |
| 85 | |
| 86 #define diag_printf printf | |
| 87 | |
| 88 void | |
| 89 pexit(char *s) | |
| 90 { | |
| 91 perror(s); | |
| 92 exit(1); | |
| 93 } | |
| 94 | |
| 95 | |
| 96 #define SOURCE_PORT 9990 | |
| 97 #define SINK_PORT 9991 | |
| 98 | |
| 99 #define MAX_BUF 8192 | |
| 100 static unsigned char data_buf[MAX_BUF]; | |
| 101 | |
| 102 struct test_params { | |
| 103 long nbufs; | |
| 104 long bufsize; | |
| 105 long load; | |
| 106 }; | |
| 107 | |
| 108 struct test_status { | |
| 109 long ok; | |
| 110 }; | |
| 111 | |
| 112 int max( int a, int b ) { return (a>b)?a:b; } | |
| 113 int min( int a, int b ) { return (a<b)?a:b; } | |
| 114 | |
| 115 | |
| 116 int | |
| 117 do_read(int s, void *_buf, int len) | |
| 118 { | |
| 119 int total, slen, rlen; | |
| 120 unsigned char *buf = (unsigned char *)_buf; | |
| 121 total = 0; | |
| 122 rlen = len; | |
| 123 while (total < len) { | |
| 124 slen = read(s, buf, rlen); | |
| 125 if (slen != rlen) { | |
| 126 if (slen < 0) { | |
| 127 diag_printf("Error after reading %d bytes\n", total); | |
| 128 return -1; | |
| 129 } | |
| 130 rlen -= slen; | |
| 131 buf += slen; | |
| 132 } | |
| 133 total += slen; | |
| 134 } | |
| 135 return total; | |
| 136 } | |
| 137 | |
| 138 int | |
| 139 do_write(int s, void *_buf, int len) | |
| 140 { | |
| 141 int total, slen, rlen; | |
| 142 unsigned char *buf = (unsigned char *)_buf; | |
| 143 total = 0; | |
| 144 rlen = len; | |
| 145 while (total < len) { | |
| 146 slen = write(s, buf, rlen); | |
| 147 if (slen != rlen) { | |
| 148 if (slen < 0) { | |
| 149 diag_printf("Error after writing %d bytes\n", total); | |
| 150 return -1; | |
| 151 } | |
| 152 rlen -= slen; | |
| 153 buf += slen; | |
| 154 } | |
| 155 total += slen; | |
| 156 } | |
| 157 return total; | |
| 158 } | |
| 159 | |
| 160 static void | |
| 161 echo_test(void * p) | |
| 162 { | |
| 163 int s_source, s_sink, e_source, e_sink; | |
| 164 struct sockaddr_in e_source_addr, e_sink_addr, local; | |
| 165 int one = 1; | |
| 166 fd_set in_fds; | |
| 167 int i, num, len; | |
| 168 struct test_params params,nparams; | |
| 169 struct test_status status,nstatus; | |
| 170 | |
| 171 s_source = socket(AF_INET, SOCK_STREAM, 0); | |
| 172 if (s_source < 0) { | |
| 173 pexit("stream socket"); | |
| 174 } | |
| 175 memset(&local, 0, sizeof(local)); | |
| 176 local.sin_family = AF_INET; | |
| 177 // local.sin_len = sizeof(local); | |
| 178 local.sin_port = ntohs(SOURCE_PORT); | |
| 179 local.sin_addr.s_addr = INADDR_ANY; | |
| 180 if(bind(s_source, (struct sockaddr *) &local, sizeof(local)) < 0) { | |
| 181 pexit("bind /source/ error"); | |
| 182 } | |
| 183 if (setsockopt(s_source, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) { | |
| 184 pexit("setsockopt /source/ SO_REUSEADDR"); | |
| 185 } | |
| 186 listen(s_source, SOMAXCONN); | |
| 187 | |
| 188 s_sink = socket(AF_INET, SOCK_STREAM, 0); | |
| 189 if (s_sink < 0) { | |
| 190 pexit("stream socket"); | |
| 191 } | |
| 192 memset(&local, 0, sizeof(local)); | |
| 193 local.sin_family = AF_INET; | |
| 194 // local.sin_len = sizeof(local); | |
| 195 local.sin_port = ntohs(SINK_PORT); | |
| 196 local.sin_addr.s_addr = INADDR_ANY; | |
| 197 if(bind(s_sink, (struct sockaddr *) &local, sizeof(local)) < 0) { | |
| 198 pexit("bind /sink/ error"); | |
| 199 } | |
| 200 if (setsockopt(s_sink, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) { | |
| 201 pexit("setsockopt /sink/ SO_REUSEADDR"); | |
| 202 } | |
| 203 listen(s_sink, SOMAXCONN); | |
| 204 | |
| 205 e_source = 0; e_sink = 0; | |
| 206 while (true) { | |
| 207 // Wait for a connection on either of the ports | |
| 208 FD_ZERO(&in_fds); | |
| 209 FD_SET(s_source, &in_fds); | |
| 210 FD_SET(s_sink, &in_fds); | |
| 211 num = select(max(s_sink,s_source)+1, &in_fds, 0, 0, 0); | |
| 212 if (FD_ISSET(s_source, &in_fds)) { | |
| 213 len = sizeof(e_source_addr); | |
| 214 if ((e_source = accept(s_source, (struct sockaddr *)&e_source_addr, &len)) < 0) { | |
| 215 pexit("accept /source/"); | |
| 216 } | |
| 217 diag_printf("SOURCE connection from %s:%d\n", | |
| 218 inet_ntoa(e_source_addr.sin_addr), ntohs(e_source_addr.sin_port)); | |
| 219 } | |
| 220 if (FD_ISSET(s_sink, &in_fds)) { | |
| 221 len = sizeof(e_sink_addr); | |
| 222 if ((e_sink = accept(s_sink, (struct sockaddr *)&e_sink_addr, &len)) < 0) { | |
| 223 pexit("accept /sink/"); | |
| 224 } | |
| 225 diag_printf("SINK connection from %s:%d\n", | |
| 226 inet_ntoa(e_sink_addr.sin_addr), ntohs(e_sink_addr.sin_port)); | |
| 227 } | |
| 228 // Continue with test once a connection is established in both directions | |
| 229 if ((e_source != 0) && (e_sink != 0)) { | |
| 230 break; | |
| 231 } | |
| 232 } | |
| 233 | |
| 234 // Wait for "source" to tell us the testing paramters | |
| 235 if (do_read(e_source, &nparams, sizeof(nparams)) != sizeof(nparams)) { | |
| 236 pexit("Can't read initialization parameters"); | |
| 237 } | |
| 238 | |
| 239 params.nbufs = ntohl(nparams.nbufs); | |
| 240 params.bufsize = ntohl(nparams.bufsize); | |
| 241 params.load = ntohl(nparams.load); | |
| 242 | |
| 243 diag_printf("Using %d buffers of %d bytes each, %d%% background load\n", | |
| 244 params.nbufs, params.bufsize, params.load); | |
| 245 | |
| 246 // Tell the sink what the parameters are | |
| 247 if (do_write(e_sink, &nparams, sizeof(nparams)) != sizeof(nparams)) { | |
| 248 pexit("Can't write initialization parameters"); | |
| 249 } | |
| 250 | |
| 251 status.ok = 1; | |
| 252 nstatus.ok = htonl(status.ok); | |
| 253 | |
| 254 // Tell the "source" to start - we're all connected and ready to go! | |
| 255 if (do_write(e_source, &nstatus, sizeof(nstatus)) != sizeof(nstatus)) { | |
| 256 pexit("Can't send ACK to 'source' host"); | |
| 257 } | |
| 258 | |
| 259 TNR_ON(); | |
| 260 | |
| 261 // Echo the data from the source to the sink hosts | |
| 262 for (i = 0; i < params.nbufs; i++) { | |
| 263 if ((len = do_read(e_source, data_buf, params.bufsize)) != params.bufsize) { | |
| 264 TNR_OFF(); | |
| 265 diag_printf("Can't read buf #%d: ", i+1); | |
| 266 if (len < 0) { | |
| 267 perror("I/O error"); | |
| 268 } else { | |
| 269 diag_printf("short read - only %d bytes\n", len); | |
| 270 } | |
| 271 TNR_ON(); | |
| 272 } | |
| 273 if ((len = do_write(e_sink, data_buf, params.bufsize)) != params.bufsize) { | |
| 274 TNR_OFF(); | |
| 275 diag_printf("Can't write buf #%d: ", i+1); | |
| 276 if (len < 0) { | |
| 277 perror("I/O error"); | |
| 278 } else { | |
| 279 diag_printf("short write - only %d bytes\n", len); | |
| 280 } | |
| 281 TNR_ON(); | |
| 282 } | |
| 283 } | |
| 284 | |
| 285 TNR_OFF(); | |
| 286 | |
| 287 // Wait for the data to drain and the "sink" to tell us all is OK. | |
| 288 if (do_read(e_sink, &status, sizeof(status)) != sizeof(status)) { | |
| 289 pexit("Can't receive ACK from 'sink' host"); | |
| 290 } | |
| 291 | |
| 292 } | |
| 293 | |
| 294 | |
| 295 int | |
| 296 main(int argc, char *argv[]) | |
| 297 { | |
| 298 echo_test(argv[1]); | |
| 299 return 0; | |
| 300 } | |
| 301 | |
| 302 | |
| 303 // EOF | |
| 304 |
