Home | History | Annotate | Download | only in libmicro
      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 }
    306