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