|
|
@@ -1,56 +1,56 @@ |
|
|
|
/* |
|
|
|
* Copyright (C) 2000-2007 Hewlett-Packard Company |
|
|
|
* Copyright (C) 2007 Ted Bullock <tbullock@comlore.com> |
|
|
|
* |
|
|
|
* |
|
|
|
* This file is part of httperf, a web server performance measurment tool. |
|
|
|
* |
|
|
|
* |
|
|
|
* This program is free software; you can redistribute it and/or modify it |
|
|
|
* under the terms of the GNU General Public License as published by the Free |
|
|
|
* Software Foundation; either version 2 of the License, or (at your option) |
|
|
|
* any later version. |
|
|
|
* |
|
|
|
* |
|
|
|
* In addition, as a special exception, the copyright holders give permission |
|
|
|
* to link the code of this work with the OpenSSL project's "OpenSSL" library |
|
|
|
* (or with modified versions of it that use the same license as the "OpenSSL" |
|
|
|
* (or with modified versions of it that use the same license as the "OpenSSL" |
|
|
|
* library), and distribute linked combinations including the two. You must |
|
|
|
* obey the GNU General Public License in all respects for all of the code |
|
|
|
* used other than "OpenSSL". If you modify this file, you may extend this |
|
|
|
* exception to your version of the file, but you are not obligated to do so. |
|
|
|
* If you do not wish to do so, delete this exception statement from your |
|
|
|
* version. |
|
|
|
* |
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT |
|
|
|
* |
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT |
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
|
|
|
* more details. |
|
|
|
* |
|
|
|
* |
|
|
|
* You should have received a copy of the GNU General Public License along |
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc., 51 |
|
|
|
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|
|
|
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|
|
|
*/ |
|
|
|
|
|
|
|
/* |
|
|
|
* Fundamentals: |
|
|
|
* |
|
|
|
* |
|
|
|
* There are three subsystems to httperf: |
|
|
|
* |
|
|
|
* |
|
|
|
* 1) The load generator which determines what URI is fetched next. |
|
|
|
* |
|
|
|
* |
|
|
|
* 2) The core engine that handles the mechanics of issuing a request. |
|
|
|
* |
|
|
|
* |
|
|
|
* 3) The instrumentation infrastructure that measures various aspects of the |
|
|
|
* transaction(s). |
|
|
|
* |
|
|
|
* Since there is considerable potential variation in all three, it seems like |
|
|
|
* |
|
|
|
* Since there is considerable potential variation in all three, it seems like |
|
|
|
* an event-based approach might be ideal in tying the three together. |
|
|
|
* Ideally, it should be possible to write a new load generator without |
|
|
|
* modifications to the other subsystems. Similarly, it should be possible to |
|
|
|
* add instrumentation without requiring changes to the load generator or http |
|
|
|
* modifications to the other subsystems. Similarly, it should be possible to |
|
|
|
* add instrumentation without requiring changes to the load generator or http |
|
|
|
* engine. |
|
|
|
* |
|
|
|
* |
|
|
|
* Axioms: - The only point at which the client will fall back is if the |
|
|
|
* client itself is overloaded. There is no point trying to fix up this |
|
|
|
* case---simply declare defeat and abort the test. |
|
|
|
* case---simply declare defeat and abort the test. |
|
|
|
*/ |
|
|
|
#include "config.h" |
|
|
|
|
|
|
@@ -144,6 +144,7 @@ static struct option longopts[] = { |
|
|
|
#ifdef HAVE_SSL |
|
|
|
{"ssl", no_argument, ¶m.use_ssl, 1}, |
|
|
|
{"ssl-ciphers", required_argument, (int *) ¶m.ssl_cipher_list, 0}, |
|
|
|
{"ssl-groups", required_argument, (int *) ¶m.ssl_groups, 0}, |
|
|
|
{"tls-server-name", required_argument, (int *) ¶m.tls_server_name, 0}, |
|
|
|
{"ssl-no-reuse", no_argument, ¶m.ssl_reuse, 0}, |
|
|
|
{"ssl-certificate", required_argument, (int *) ¶m.ssl_cert, 0}, |
|
|
@@ -186,6 +187,7 @@ usage(void) |
|
|
|
"\t[--ssl-certificate file] [--ssl-key file]\n" |
|
|
|
"\t[--ssl-ca-file file] [--ssl-ca-path path]\n" |
|
|
|
"\t[--ssl-verify [yes|no]] [--ssl-protocol S]\n" |
|
|
|
"\t[--ssl-groups L]\n" |
|
|
|
#endif |
|
|
|
"\t[--think-timeout X] [--timeout X] [--verbose] [--version]\n" |
|
|
|
"\t[--wlog y|n,file] [--wsess N,N,X] [--wsesslog N,X,file]\n" |
|
|
@@ -220,7 +222,7 @@ perf_sample(struct Timer *t, Any_Type regarg) |
|
|
|
event_signal(EV_PERF_SAMPLE, 0, callarg); |
|
|
|
|
|
|
|
/* |
|
|
|
* prepare for next sample interval: |
|
|
|
* prepare for next sample interval: |
|
|
|
*/ |
|
|
|
perf_sample_start = timer_now(); |
|
|
|
if (timer_schedule(perf_sample, regarg, RATE_INTERVAL) == NULL) |
|
|
@@ -261,7 +263,7 @@ main(int argc, char **argv) |
|
|
|
/* |
|
|
|
* This works around a bug in earlier versions of FreeBSD that cause |
|
|
|
* non-finite IEEE arithmetic to cause SIGFPE instead of the |
|
|
|
* non-finite arithmetic as defined by IEEE. |
|
|
|
* non-finite arithmetic as defined by IEEE. |
|
|
|
*/ |
|
|
|
fpsetmask(0); |
|
|
|
#endif |
|
|
@@ -279,7 +281,7 @@ main(int argc, char **argv) |
|
|
|
param.num_conns = 1; |
|
|
|
/* |
|
|
|
* These should be set to the minimum of 2*bandwidth*delay and the |
|
|
|
* maximum request/reply size for single-call connections. |
|
|
|
* maximum request/reply size for single-call connections. |
|
|
|
*/ |
|
|
|
param.send_buffer_size = 4096; |
|
|
|
param.recv_buffer_size = 16384; |
|
|
@@ -291,7 +293,7 @@ main(int argc, char **argv) |
|
|
|
#endif |
|
|
|
|
|
|
|
/* |
|
|
|
* get program name: |
|
|
|
* get program name: |
|
|
|
*/ |
|
|
|
prog_name = strrchr(argv[0], '/'); |
|
|
|
if (prog_name) |
|
|
@@ -300,7 +302,7 @@ main(int argc, char **argv) |
|
|
|
prog_name = argv[0]; |
|
|
|
|
|
|
|
/* |
|
|
|
* process command line options: |
|
|
|
* process command line options: |
|
|
|
*/ |
|
|
|
while ((ch = |
|
|
|
getopt_long(argc, argv, "d:hvVn", longopts, &longindex)) >= 0) { |
|
|
@@ -428,7 +430,7 @@ main(int argc, char **argv) |
|
|
|
param.rate.mean_iat = |
|
|
|
1 / param.rate.rate_param; |
|
|
|
param.rate.dist = DETERMINISTIC; |
|
|
|
} else if (flag == ¶m.rate.mean_iat) { /* --period |
|
|
|
} else if (flag == ¶m.rate.mean_iat) { /* --period |
|
|
|
*/ |
|
|
|
param.rate.dist = DETERMINISTIC; |
|
|
|
if (!isdigit(*optarg)) |
|
|
@@ -457,7 +459,7 @@ main(int argc, char **argv) |
|
|
|
|
|
|
|
/* |
|
|
|
* remaining params depend on selected |
|
|
|
* distribution: |
|
|
|
* distribution: |
|
|
|
*/ |
|
|
|
errno = 0; |
|
|
|
switch (param.rate.dist) { |
|
|
@@ -647,6 +649,8 @@ main(int argc, char **argv) |
|
|
|
#ifdef HAVE_SSL |
|
|
|
else if (flag == ¶m.ssl_cipher_list) |
|
|
|
param.ssl_cipher_list = optarg; |
|
|
|
else if (flag == ¶m.ssl_groups) |
|
|
|
param.ssl_groups = optarg; |
|
|
|
else if (flag == ¶m.ssl_cert) |
|
|
|
param.ssl_cert = optarg; |
|
|
|
else if (flag == ¶m.ssl_key) |
|
|
@@ -877,18 +881,18 @@ main(int argc, char **argv) |
|
|
|
optarg = end + 1; |
|
|
|
|
|
|
|
/* |
|
|
|
* simulate parsing of string |
|
|
|
* simulate parsing of string |
|
|
|
*/ |
|
|
|
param.wsesslog.file = optarg; |
|
|
|
if ((end = strchr(optarg, ',')) == NULL) |
|
|
|
/* |
|
|
|
* must be last param, position end at |
|
|
|
* final \0 |
|
|
|
* must be last param, position end at |
|
|
|
* final \0 |
|
|
|
*/ |
|
|
|
end = optarg + strlen(optarg); |
|
|
|
else |
|
|
|
/* |
|
|
|
* terminate end of string |
|
|
|
* terminate end of string |
|
|
|
*/ |
|
|
|
*end++ = '\0'; |
|
|
|
optarg = end; |
|
|
@@ -996,7 +1000,7 @@ main(int argc, char **argv) |
|
|
|
* Invalid or ambiguous option name or extraneous |
|
|
|
* parameter. getopt_long () already issued an |
|
|
|
* explanation to the user, so all we do is call it |
|
|
|
* quites. |
|
|
|
* quites. |
|
|
|
*/ |
|
|
|
exit(1); |
|
|
|
|
|
|
@@ -1034,7 +1038,7 @@ main(int argc, char **argv) |
|
|
|
switch (param.ssl_protocol) |
|
|
|
{ |
|
|
|
/* 0/auto for highest available */ |
|
|
|
case 0: |
|
|
|
case 0: |
|
|
|
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) |
|
|
|
ssl_ctx = SSL_CTX_new (TLS_client_method ()); break; |
|
|
|
#else |
|
|
@@ -1043,7 +1047,7 @@ main(int argc, char **argv) |
|
|
|
|
|
|
|
#ifndef OPENSSL_NO_SSL2 |
|
|
|
/* 2/SSLv2 */ |
|
|
|
case 2: |
|
|
|
case 2: |
|
|
|
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) |
|
|
|
ssl_ctx = SSL_CTX_new (TLS_client_method ()); |
|
|
|
#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) |
|
|
@@ -1058,7 +1062,7 @@ main(int argc, char **argv) |
|
|
|
|
|
|
|
#ifndef OPENSSL_NO_SSL3 |
|
|
|
/* 3/SSLv3 */ |
|
|
|
case 3: |
|
|
|
case 3: |
|
|
|
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) |
|
|
|
ssl_ctx = SSL_CTX_new (TLS_client_method ()); |
|
|
|
SSL_CTX_set_min_proto_version(ssl_ctx, SSL3_VERSION); |
|
|
@@ -1069,9 +1073,9 @@ main(int argc, char **argv) |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
/* 4/TLSv1.0 */ |
|
|
|
case 4: |
|
|
|
case 4: |
|
|
|
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) |
|
|
|
ssl_ctx = SSL_CTX_new (TLS_client_method ()); |
|
|
|
ssl_ctx = SSL_CTX_new (TLS_client_method ()); |
|
|
|
SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_VERSION); |
|
|
|
SSL_CTX_set_max_proto_version(ssl_ctx, TLS1_VERSION); |
|
|
|
break; |
|
|
@@ -1114,7 +1118,7 @@ main(int argc, char **argv) |
|
|
|
#endif |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!ssl_ctx) { |
|
|
|
ERR_print_errors_fp(stderr); |
|
|
|
exit(-1); |
|
|
@@ -1122,7 +1126,7 @@ main(int argc, char **argv) |
|
|
|
|
|
|
|
memset(buf, 0, sizeof(buf)); |
|
|
|
RAND_seed(buf, sizeof(buf)); |
|
|
|
|
|
|
|
|
|
|
|
/* set server certificate verification */ |
|
|
|
if (param.ssl_verify == 1) |
|
|
|
SSL_CTX_set_verify (ssl_ctx, SSL_VERIFY_PEER, NULL); |
|
|
@@ -1175,7 +1179,7 @@ main(int argc, char **argv) |
|
|
|
"SSL certificate and key failed consistency check\n"); |
|
|
|
exit (1); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
if (param.port < 0) |
|
|
@@ -1199,7 +1203,7 @@ main(int argc, char **argv) |
|
|
|
gen[num_gen++] = &misc; |
|
|
|
|
|
|
|
/* |
|
|
|
* echo command invocation for logging purposes: |
|
|
|
* echo command invocation for logging purposes: |
|
|
|
*/ |
|
|
|
printf("%s", prog_name); |
|
|
|
if (verbose) |
|
|
@@ -1265,7 +1269,7 @@ main(int argc, char **argv) |
|
|
|
case DETERMINISTIC: |
|
|
|
/* |
|
|
|
* for backwards compatibility, continue to use |
|
|
|
* --rate: |
|
|
|
* --rate: |
|
|
|
*/ |
|
|
|
printf(" --rate=%g", param.rate.rate_param); |
|
|
|
break; |
|
|
@@ -1310,6 +1314,8 @@ main(int argc, char **argv) |
|
|
|
printf(" --ssl-ciphers=%s", param.ssl_cipher_list); |
|
|
|
if (param.tls_server_name) |
|
|
|
printf(" --tls-server-name=%s", param.tls_server_name); |
|
|
|
if (param.ssl_groups) |
|
|
|
printf(" --ssl-groups=%s", param.ssl_groups); |
|
|
|
if (!param.ssl_reuse) |
|
|
|
printf(" --ssl-no-reuse"); |
|
|
|
if (param.ssl_cert) printf (" --ssl-cert=%s", param.ssl_cert); |
|
|
@@ -1345,7 +1351,7 @@ main(int argc, char **argv) |
|
|
|
if (param.wsesslog.num_sessions) { |
|
|
|
/* |
|
|
|
* This overrides any --wsess, --num-conns, --num-calls, |
|
|
|
* --burst-length and any uri generator |
|
|
|
* --burst-length and any uri generator |
|
|
|
*/ |
|
|
|
printf(" --wsesslog=%u,%.3f,%s", param.wsesslog.num_sessions, |
|
|
|
param.wsesslog.think_time, param.wsesslog.file); |
|
|
@@ -1390,12 +1396,12 @@ main(int argc, char **argv) |
|
|
|
|
|
|
|
/* |
|
|
|
* Update `now'. This is to keep things accurate even when some of |
|
|
|
* the initialization routines take a long time to execute. |
|
|
|
* the initialization routines take a long time to execute. |
|
|
|
*/ |
|
|
|
timer_now_forced(); |
|
|
|
|
|
|
|
/* |
|
|
|
* ensure that clients sample rates at different times: |
|
|
|
* ensure that clients sample rates at different times: |
|
|
|
*/ |
|
|
|
t = (param.client.id + 1.0) * RATE_INTERVAL / param.client.num_clients; |
|
|
|
arg.l = 0; |
|
|
|