]> git.saurik.com Git - apple/xnu.git/blob - tools/tests/libMicro/connection.c
xnu-3248.60.10.tar.gz
[apple/xnu.git] / tools / tests / libMicro / connection.c
1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms
5 * of the Common Development and Distribution License
6 * (the "License"). You may not use this file except
7 * in compliance with the License.
8 *
9 * You can obtain a copy of the license at
10 * src/OPENSOLARIS.LICENSE
11 * or http://www.opensolaris.org/os/licensing.
12 * See the License for the specific language governing
13 * permissions and limitations under the License.
14 *
15 * When distributing Covered Code, include this CDDL
16 * HEADER in each file and include the License file at
17 * usr/src/OPENSOLARIS.LICENSE. If applicable,
18 * add the following below this CDDL HEADER, with the
19 * fields enclosed by brackets "[]" replaced with your
20 * own identifying information: Portions Copyright [yyyy]
21 * [name of copyright owner]
22 *
23 * CDDL HEADER END
24 */
25
26 /*
27 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
29 */
30
31
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <netinet/in.h>
35 #include <netinet/tcp.h>
36 #include <arpa/inet.h>
37 #include <netdb.h>
38 #include <string.h>
39 #include <unistd.h>
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <fcntl.h>
43 #include <errno.h>
44 #include <sys/poll.h>
45
46 #include "libmicro.h"
47
48 #define FIRSTPORT 12345
49
50 typedef struct {
51 int ts_once;
52 int *ts_lsns;
53 int *ts_accs;
54 int *ts_cons;
55 struct sockaddr_in *ts_adds;
56 } tsd_t;
57
58 static int opta = 0;
59 static int optc = 0;
60 static struct hostent *host;
61
62 int
63 benchmark_init()
64 {
65 lm_defB = 256;
66 lm_tsdsize = sizeof (tsd_t);
67
68 (void) sprintf(lm_optstr, "ac");
69
70 (void) sprintf(lm_usage,
71 " [-a] (measure accept() only)\n"
72 " [-c] (measure connect() only)\n"
73 "notes: measures connect()/accept()\n");
74
75 return (0);
76 }
77
78 /*ARGSUSED*/
79 int
80 benchmark_optswitch(int opt, char *optarg)
81 {
82 switch (opt) {
83 case 'a':
84 opta = 1;
85 break;
86 case 'c':
87 optc = 1;
88 break;
89 default:
90 return (-1);
91 }
92
93 if (opta && optc) {
94 (void) printf("warning: -a overrides -c\n");
95 optc = 0;
96 }
97
98 return (0);
99 }
100
101 int
102 benchmark_initrun()
103 {
104 (void) setfdlimit(3 * lm_optB * lm_optT + 10);
105
106 return (0);
107 }
108
109 int
110 benchmark_initbatch_once(void *tsd)
111 {
112 tsd_t *ts = (tsd_t *)tsd;
113 int i, j;
114
115 int errors = 0;
116
117 ts->ts_lsns = (int *)malloc(lm_optB * sizeof (int));
118 if (ts->ts_lsns == NULL) {
119 errors ++;
120 }
121 ts->ts_accs = (int *)malloc(lm_optB * sizeof (int));
122 if (ts->ts_accs == NULL) {
123 errors ++;
124 }
125 ts->ts_cons = (int *)malloc(lm_optB * sizeof (int));
126 if (ts->ts_cons == NULL) {
127 errors ++;
128 }
129 ts->ts_adds =
130 (struct sockaddr_in *)malloc(lm_optB *
131 sizeof (struct sockaddr_in));
132 if (ts->ts_accs == NULL) {
133 errors ++;
134 }
135
136 j = FIRSTPORT;
137 for (i = 0; i < lm_optB; i++) {
138 ts->ts_lsns[i] = socket(AF_INET, SOCK_STREAM, 0);
139 if (ts->ts_lsns[i] == -1) {
140 perror("socket");
141 errors ++;
142 }
143
144 /*
145 * make accept socket non-blocking so in case of errors
146 * we don't hang
147 */
148
149 if (fcntl(ts->ts_lsns[i], F_SETFL, O_NDELAY) == -1) {
150 perror("fcntl");
151 errors ++;
152 }
153
154
155 if ((host = gethostbyname("localhost")) == NULL) {
156 errors ++;
157 }
158
159 for (;;) {
160 (void) memset(&ts->ts_adds[i], 0,
161 sizeof (struct sockaddr_in));
162 ts->ts_adds[i].sin_family = AF_INET;
163 ts->ts_adds[i].sin_port = htons(j++);
164 (void) memcpy(&ts->ts_adds[i].sin_addr.s_addr,
165 host->h_addr_list[0], sizeof (struct in_addr));
166
167 if (bind(ts->ts_lsns[i],
168 (struct sockaddr *)&ts->ts_adds[i],
169 sizeof (struct sockaddr_in)) == 0) {
170 break;
171 }
172
173 if (errno != EADDRINUSE) {
174 errors ++;
175 }
176 }
177
178 if (listen(ts->ts_lsns[i], 5) == -1) {
179 perror("listen");
180 errors ++;
181 }
182 }
183 return (errors);
184 }
185
186 int
187 benchmark_initbatch(void *tsd)
188 {
189 tsd_t *ts = (tsd_t *)tsd;
190 int i;
191 int errors = 0;
192 int result;
193
194 if (ts->ts_once++ == 0) {
195 if (errors += benchmark_initbatch_once(tsd) == -1) {
196 return (-1);
197 }
198 }
199
200
201 for (i = 0; i < lm_optB; i++) {
202 ts->ts_cons[i] = socket(AF_INET, SOCK_STREAM, 0);
203 if (ts->ts_cons[i] == -1) {
204 perror("init:socket");
205 errors ++;
206 }
207
208 if (fcntl(ts->ts_cons[i], F_SETFL, O_NDELAY) == -1) {
209 perror("init:fcntl");
210 errors ++;
211 }
212
213 if (opta) {
214 result = connect(ts->ts_cons[i],
215 (struct sockaddr *)&ts->ts_adds[i],
216 sizeof (struct sockaddr_in));
217 if ((result == -1) && (errno != EINPROGRESS)) {
218 perror("init:connect");
219 errors ++;
220 }
221 }
222 }
223
224 return (errors);
225 }
226
227 int
228 benchmark(void *tsd, result_t *res)
229
230
231
232 {
233 tsd_t *ts = (tsd_t *)tsd;
234 int i;
235 int result;
236 struct sockaddr_in addr;
237 socklen_t size;
238
239 for (i = 0; i < lm_optB; i++) {
240 if (!opta) {
241 again:
242 result = connect(ts->ts_cons[i],
243 (struct sockaddr *)&ts->ts_adds[i],
244 sizeof (struct sockaddr_in));
245 if (result != 0 && errno != EISCONN) {
246 if (errno == EINPROGRESS) {
247 struct pollfd pollfd;
248 if (optc)
249 continue;
250 pollfd.fd = ts->ts_cons[i];
251 pollfd.events = POLLOUT;
252 if (poll(&pollfd, 1, -1) == 1)
253 goto again;
254 }
255
256 res->re_errors ++;
257 perror("benchmark:connect");
258 continue;
259 }
260 }
261
262 if (!optc) {
263 size = sizeof (struct sockaddr);
264 for (;;) {
265 struct pollfd pollfd;
266 result = accept(ts->ts_lsns[i],
267 (struct sockaddr *)&addr, &size);
268 if (result > 0 || (result == -1 &&
269 errno != EAGAIN))
270 break;
271 pollfd.fd = ts->ts_lsns[i];
272 pollfd.events = POLLIN;
273 if (poll(&pollfd, 1, -1) != 1)
274 break;
275 }
276
277 ts->ts_accs[i] = result;
278 if (result == -1) {
279 res->re_errors ++;
280 perror("benchmark:accept");
281 continue;
282 }
283 }
284 }
285 res->re_count = i;
286
287 return (0);
288 }
289
290 int
291 benchmark_finibatch(void *tsd)
292 {
293 tsd_t *ts = (tsd_t *)tsd;
294 int i;
295
296 for (i = 0; i < lm_optB; i++) {
297
298 if (!optc) {
299 (void) close(ts->ts_accs[i]);
300 }
301 (void) close(ts->ts_cons[i]);
302 }
303
304 return (0);
305 }