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 50typedef 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 58static int opta = 0; 59static int optc = 0; 60static struct hostent *host; 61 62int 63benchmark_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*/ 79int 80benchmark_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 101int 102benchmark_initrun() 103{ 104 (void) setfdlimit(3 * lm_optB * lm_optT + 10); 105 106 return (0); 107} 108 109int 110benchmark_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 186int 187benchmark_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 227int 228benchmark(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 290int 291benchmark_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} 306