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  * benchmark to measure time to close a local tcp connection
     33  */
     34 
     35 #include <sys/types.h>
     36 #include <sys/socket.h>
     37 #include <netinet/in.h>
     38 #include <netinet/tcp.h>
     39 #include <arpa/inet.h>
     40 #include <netdb.h>
     41 #include <string.h>
     42 #include <unistd.h>
     43 #include <stdlib.h>
     44 #include <stdio.h>
     45 #include <fcntl.h>
     46 #include <errno.h>
     47 
     48 #include "libmicro.h"
     49 
     50 #define	FIRSTPORT		12345
     51 
     52 typedef struct {
     53 	int			*ts_lsns;
     54 	int			*ts_accs;
     55 	int			*ts_cons;
     56 	struct sockaddr_in	*ts_adds;
     57 } tsd_t;
     58 
     59 int
     60 benchmark_init()
     61 {
     62 	lm_tsdsize = sizeof (tsd_t);
     63 
     64 	lm_defB = 256;
     65 
     66 	(void) sprintf(lm_usage,
     67 	    "notes: measures close() on local TCP connections");
     68 
     69 	return (0);
     70 }
     71 
     72 int
     73 benchmark_initrun()
     74 {
     75 	(void) setfdlimit(3 * lm_optB * lm_optT + 10);
     76 
     77 	return (0);
     78 }
     79 
     80 int
     81 benchmark_initworker(void *tsd)
     82 {
     83 	tsd_t			*ts = (tsd_t *)tsd;
     84 	int			i, j;
     85 	int			opt = 1;
     86 	struct hostent	*host;
     87 	int			errors = 0;
     88 
     89 	ts->ts_lsns = (int *)malloc(lm_optB * sizeof (int));
     90 	if (ts->ts_lsns == NULL) {
     91 		errors ++;
     92 	}
     93 	ts->ts_accs = (int *)malloc(lm_optB * sizeof (int));
     94 	if (ts->ts_accs == NULL) {
     95 		errors ++;
     96 	}
     97 	ts->ts_cons = (int *)malloc(lm_optB * sizeof (int));
     98 	if (ts->ts_cons == NULL) {
     99 		errors ++;
    100 	}
    101 	ts->ts_adds = (struct sockaddr_in *)malloc(lm_optB *
    102 	    sizeof (struct sockaddr_in));
    103 	if (ts->ts_adds == NULL) {
    104 		errors ++;
    105 	}
    106 
    107 	j = FIRSTPORT;
    108 	for (i = 0; i < lm_optB; i++) {
    109 		ts->ts_lsns[i] = socket(AF_INET, SOCK_STREAM, 0);
    110 		if (ts->ts_lsns[i] == -1) {
    111 			perror("socket");
    112 			errors ++;
    113 		}
    114 
    115 		if (setsockopt(ts->ts_lsns[i], SOL_SOCKET, SO_REUSEADDR,
    116 		    &opt, sizeof (int)) == -1) {
    117 			perror("setsockopt");
    118 			errors ++;
    119 		}
    120 
    121 		if ((host = gethostbyname("localhost")) == NULL) {
    122 			errors ++;
    123 		}
    124 
    125 		for (;;) {
    126 			(void) memset(&ts->ts_adds[i], 0,
    127 			    sizeof (struct sockaddr_in));
    128 			ts->ts_adds[i].sin_family = AF_INET;
    129 			ts->ts_adds[i].sin_port = htons(j++);
    130 			(void) memcpy(&ts->ts_adds[i].sin_addr.s_addr,
    131 			    host->h_addr_list[0], sizeof (struct in_addr));
    132 
    133 			if (bind(ts->ts_lsns[i],
    134 			    (struct sockaddr *)&ts->ts_adds[i],
    135 			    sizeof (struct sockaddr_in)) == 0) {
    136 				break;
    137 			}
    138 
    139 			if (errno != EADDRINUSE) {
    140 				perror("bind");
    141 				errors ++;
    142 			}
    143 		}
    144 
    145 		if (listen(ts->ts_lsns[i], 5) == -1) {
    146 			perror("listen");
    147 			errors ++;
    148 		}
    149 
    150 	}
    151 	return (errors);
    152 }
    153 
    154 int
    155 benchmark_initbatch(void *tsd)
    156 {
    157 	tsd_t			*ts = (tsd_t *)tsd;
    158 	int			i;
    159 	int			result;
    160 	struct sockaddr_in	addr;
    161 	socklen_t		size;
    162 	int			errors = 0;
    163 
    164 	for (i = 0; i < lm_optB; i++) {
    165 		ts->ts_cons[i] = socket(AF_INET, SOCK_STREAM, 0);
    166 		if (ts->ts_cons[i] == -1) {
    167 			perror("socket");
    168 			errors ++;
    169 			continue;
    170 		}
    171 
    172 		if (fcntl(ts->ts_cons[i], F_SETFL, O_NDELAY) == -1) {
    173 			perror("fcnt");
    174 			errors ++;
    175 			continue;
    176 		}
    177 
    178 		result = connect(ts->ts_cons[i],
    179 		    (struct sockaddr *)&ts->ts_adds[i],
    180 		    sizeof (struct sockaddr_in));
    181 
    182 		if ((result == -1) && (errno != EINPROGRESS)) {
    183 			perror("connect");
    184 			errors ++;
    185 			continue;
    186 		}
    187 
    188 		size = sizeof (struct sockaddr);
    189 		result = accept(ts->ts_lsns[i], (struct sockaddr *)&addr,
    190 		    &size);
    191 		if (result == -1) {
    192 			perror("accept");
    193 			errors ++;
    194 			continue;
    195 		}
    196 		ts->ts_accs[i] = result;
    197 	}
    198 
    199 	return (errors);
    200 }
    201 
    202 int
    203 benchmark(void *tsd, result_t *res)
    204 {
    205 	tsd_t			*ts = (tsd_t *)tsd;
    206 	int			i;
    207 
    208 	for (i = 0; i < lm_optB; i++) {
    209 		if (close(ts->ts_accs[i]) == -1) {
    210 			res->re_errors ++;
    211 		}
    212 	}
    213 	res->re_count = i;
    214 
    215 	return (0);
    216 }
    217 
    218 int
    219 benchmark_finibatch(void *tsd)
    220 {
    221 	tsd_t			*ts = (tsd_t *)tsd;
    222 	int			i;
    223 
    224 	for (i = 0; i < lm_optB; i++) {
    225 		(void) close(ts->ts_cons[i]);
    226 	}
    227 
    228 	return (0);
    229 }
    230 
    231 int
    232 benchmark_finiworker(void *tsd)
    233 {
    234 	tsd_t			*ts = (tsd_t *)tsd;
    235 	int			i;
    236 
    237 	for (i = 0; i < lm_optB; i++) {
    238 		(void) close(ts->ts_lsns[i]);
    239 	}
    240 	return (0);
    241 }
    242