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 for bind... keep in mind tcp hash chain effects
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
52typedef struct {
53	int 			*ts_lsns;
54	struct sockaddr_in 	*ts_adds;
55} tsd_t;
56
57static int optz = -0;
58
59int
60benchmark_init()
61{
62	lm_tsdsize = sizeof (tsd_t);
63
64	lm_defB = 256;
65	(void) sprintf(lm_optstr, "z");
66
67	(void) sprintf(lm_usage,
68	    "		[-z bind to port 0 rather than seq. number\n"
69	    "notes: measures bind() on TCP");
70
71	return (0);
72}
73
74int
75benchmark_initrun()
76{
77	(void) setfdlimit(lm_optB * lm_optT + 10);
78
79	return (0);
80}
81
82/*ARGSUSED*/
83int
84benchmark_optswitch(int opt, char *optarg)
85{
86	switch (opt) {
87	case 'z':
88		optz = 1;
89		break;
90	default:
91		return (-1);
92	}
93	return (0);
94}
95
96int
97benchmark_initbatch(void *tsd)
98{
99	tsd_t 			*ts = (tsd_t *)tsd;
100	int			i, j;
101	int			opt = 1;
102	struct hostent		*host;
103	int			errors = 0;
104
105	ts->ts_lsns = (int *)malloc(lm_optB * sizeof (int));
106	if (ts->ts_lsns == NULL)
107		errors ++;
108
109	ts->ts_adds = (struct sockaddr_in *)malloc(lm_optB *
110	    sizeof (struct sockaddr_in));
111	if (ts->ts_adds == NULL)
112		errors ++;
113
114	j = FIRSTPORT;
115	for (i = 0; i < lm_optB; i++) {
116		if ((ts->ts_lsns[i] = socket(PF_INET, SOCK_STREAM, 0)) == -1)
117			errors ++;
118
119		if (setsockopt(ts->ts_lsns[i], SOL_SOCKET, SO_REUSEADDR,
120		    &opt, sizeof (int)) == -1)
121			errors ++;
122
123		if ((host = gethostbyname("localhost")) == NULL)
124			errors ++;
125
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 = (optz ? 0 : 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	return (errors);
134}
135
136int
137benchmark(void *tsd, result_t *res)
138{
139	tsd_t			*ts = (tsd_t *)tsd;
140	int			i;
141
142	for (i = 0; i < lm_optB; i++) {
143		if ((bind(ts->ts_lsns[i],
144		    (struct sockaddr *)&ts->ts_adds[i],
145		    sizeof (struct sockaddr_in)) != 0) &&
146		    (errno != EADDRINUSE))
147			res->re_errors ++;
148	}
149	res->re_count = i;
150
151	return (0);
152}
153
154int
155benchmark_finibatch(void *tsd)
156{
157	tsd_t			*ts = (tsd_t *)tsd;
158	int			i;
159
160	for (i = 0; i < lm_optB; i++)
161		(void) close(ts->ts_lsns[i]);
162	return (0);
163}
164