Feature update for tls_bench test that will allow passing in arguments (#1466)

* Feature update for tls_bench test that will allow passing in command line arguments that enable test features.
* Fix type conversion errors.
* Fixed use of uninitialized data. Declare DH arrays as const.
This commit is contained in:
Eric Blankenhorn
2018-04-02 16:00:34 -05:00
committed by David Garske
parent b33feb9dbf
commit adb817e8d2
2 changed files with 251 additions and 157 deletions

View File

@@ -28,7 +28,7 @@ gcc -lwolfssl -lpthread -o tls_bench tls_bench.c
Or Or
#include <examples/benchmark/tls_bench.h> #include <examples/benchmark/tls_bench.h>
bench_tls(); bench_tls(args);
*/ */
@@ -41,6 +41,8 @@ bench_tls();
#include <wolfssl/wolfcrypt/settings.h> #include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/ssl.h> #include <wolfssl/ssl.h>
#include <wolfssl/test.h>
#include <examples/benchmark/tls_bench.h> #include <examples/benchmark/tls_bench.h>
/* force certificate test buffers to be included via headers */ /* force certificate test buffers to be included via headers */
@@ -57,15 +59,16 @@ bench_tls();
#include <unistd.h> #include <unistd.h>
#include <sys/time.h> #include <sys/time.h>
/* configuration parameters */ /* Defaults for configuration parameters */
#define THREAD_COUNT 2 #define THREAD_PAIRS 1 /* Thread pairs of server/client */
#define RUNTIME_SEC 2 #define MEM_BUFFER_SZ (1024*16) /* Must be large enough to handle max packet size */
#define MEM_BUFFER_SZ (1024*5)
#define MIN_DHKEY_BITS 1024 #define MIN_DHKEY_BITS 1024
#define RUNTIME_SEC 1
#define TEST_SIZE_BYTES (1024 * 1024)
#define TEST_PACKET_SIZE 1024
#define SHOW_VERBOSE 0 /* Default output is tab delimited format */
/* default output is tab delimited format. Uncomment these to show more */ static int argShowPeerInfo = 0; /* Show more info about wolfSSL configuration */
//#define SHOW_PEER_INFO
//#define SHOW_VERBOSE_OUTPUT
static const char* kTestStr = static const char* kTestStr =
"Biodiesel cupidatat marfa, cliche aute put a bird on it incididunt elit\n" "Biodiesel cupidatat marfa, cliche aute put a bird on it incididunt elit\n"
@@ -147,7 +150,7 @@ static const char* kTestStr =
#ifndef NO_DH #ifndef NO_DH
/* dh1024 p */ /* dh1024 p */
static unsigned char p[] = static const unsigned char p[] =
{ {
0xE6, 0x96, 0x9D, 0x3D, 0x49, 0x5B, 0xE3, 0x2C, 0x7C, 0xF1, 0x80, 0xC3, 0xE6, 0x96, 0x9D, 0x3D, 0x49, 0x5B, 0xE3, 0x2C, 0x7C, 0xF1, 0x80, 0xC3,
0xBD, 0xD4, 0x79, 0x8E, 0x91, 0xB7, 0x81, 0x82, 0x51, 0xBB, 0x05, 0x5E, 0xBD, 0xD4, 0x79, 0x8E, 0x91, 0xB7, 0x81, 0x82, 0x51, 0xBB, 0x05, 0x5E,
@@ -163,7 +166,7 @@ static unsigned char p[] =
}; };
/* dh1024 g */ /* dh1024 g */
static unsigned char g[] = static const unsigned char g[] =
{ {
0x02, 0x02,
}; };
@@ -194,6 +197,12 @@ typedef struct {
typedef struct { typedef struct {
const char* cipher; const char* cipher;
/* The total number of bytes to transfer per connection */
int numBytes;
/* The data payload size in the packet. Will be padded if packet size > buffer size. */
int packetSize;
/* client messages to server in memory */ /* client messages to server in memory */
memBuf_t to_server; memBuf_t to_server;
@@ -209,38 +218,9 @@ typedef struct {
int shutdown; int shutdown;
} info_t; } info_t;
#ifdef SHOW_PEER_INFO /* Global vars for argument parsing */
static void showPeer(WOLFSSL* ssl) int myoptind = 0;
{ char* myoptarg = NULL;
WOLFSSL_CIPHER* cipher;
#ifdef HAVE_ECC
const char *name;
#endif
#ifndef NO_DH
int bits;
#endif
printf("SSL version is %s\n", wolfSSL_get_version(ssl));
cipher = wolfSSL_get_current_cipher(ssl);
printf("SSL cipher suite is %s\n", wolfSSL_CIPHER_get_name(cipher));
#ifdef HAVE_ECC
if ((name = wolfSSL_get_curve_name(ssl)) != NULL)
printf("SSL curve name is %s\n", name);
#endif
#ifndef NO_DH
if ((bits = wolfSSL_GetDhKey_Sz(ssl)) > 0)
printf("SSL DH size is %d bits\n", bits);
#endif
if (wolfSSL_session_reused(ssl))
printf("SSL reused session\n");
#ifdef WOLFSSL_ALT_CERT_CHAINS
if (wolfSSL_is_peer_alt_cert_chain(ssl))
printf("Alternate cert chain used\n");
#endif
}
#endif
/* server send callback */ /* server send callback */
static int ServerSend(WOLFSSL* ssl, char* buf, int sz, void* ctx) static int ServerSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
@@ -353,12 +333,6 @@ static int ClientRecv(WOLFSSL* ssl, char* buf, int sz, void* ctx)
} }
static WC_NORETURN void err_sys(const char* msg)
{
printf("wolfSSL error: %s\n", msg);
exit(1);
}
static double gettime_secs(int reset) static double gettime_secs(int reset)
{ {
struct timeval tv; struct timeval tv;
@@ -372,13 +346,12 @@ static void* client_thread(void* args)
{ {
info_t* info = (info_t*)args; info_t* info = (info_t*)args;
unsigned char buf[MEM_BUFFER_SZ]; unsigned char buf[MEM_BUFFER_SZ];
unsigned char *writeBuf;
double start; double start;
int ret, len; int ret;
WOLFSSL_CTX* cli_ctx; WOLFSSL_CTX* cli_ctx;
WOLFSSL* cli_ssl; WOLFSSL* cli_ssl;
#ifdef SHOW_PEER_INFO
int haveShownPeerInfo = 0; int haveShownPeerInfo = 0;
#endif
/* set up client */ /* set up client */
cli_ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()); cli_ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method());
@@ -408,6 +381,16 @@ static void* client_thread(void* args)
wolfSSL_CTX_SetMinDhKey_Sz(cli_ctx, MIN_DHKEY_BITS); wolfSSL_CTX_SetMinDhKey_Sz(cli_ctx, MIN_DHKEY_BITS);
#endif #endif
/* Allocate and initialize a packet sized buffer */
writeBuf = (unsigned char*)malloc(info->packetSize);
if (writeBuf != NULL) {
strncpy((char*)writeBuf, kTestStr, info->packetSize);
*(writeBuf + info->packetSize) = '\0';
}
else {
err_sys("failed to allocate memory");
}
while (!info->shutdown) { while (!info->shutdown) {
cli_ssl = wolfSSL_new(cli_ctx); cli_ssl = wolfSSL_new(cli_ctx);
if (cli_ctx == NULL) err_sys("error creating client object"); if (cli_ctx == NULL) err_sys("error creating client object");
@@ -426,17 +409,15 @@ static void* client_thread(void* args)
} }
info->client_stats.connTime += start; info->client_stats.connTime += start;
#ifdef SHOW_PEER_INFO if ((argShowPeerInfo) && (!haveShownPeerInfo)) {
if (!haveShownPeerInfo) {
haveShownPeerInfo = 1; haveShownPeerInfo = 1;
showPeer(cli_ssl); showPeer(cli_ssl);
} }
#endif
/* write test message to server */ /* write test message to server */
len = (int)strlen(kTestStr)+1; /* include null term */ while (info->client_stats.rxTotal < info->numBytes) {
start = gettime_secs(1); start = gettime_secs(1);
ret = wolfSSL_write(cli_ssl, kTestStr, len); ret = wolfSSL_write(cli_ssl, writeBuf, info->packetSize);
info->client_stats.txTime += gettime_secs(0) - start; info->client_stats.txTime += gettime_secs(0) - start;
if (ret > 0) { if (ret > 0) {
info->client_stats.txTotal += ret; info->client_stats.txTotal += ret;
@@ -451,9 +432,10 @@ static void* client_thread(void* args)
} }
/* validate echo */ /* validate echo */
if (strncmp(kTestStr, (char*)buf, strlen(kTestStr)) != 0) { if (strncmp((char*)writeBuf, (char*)buf, info->packetSize) != 0) {
err_sys("echo check failed!\n"); err_sys("echo check failed!\n");
} }
}
info->client_stats.connCount++; info->client_stats.connCount++;
@@ -462,6 +444,7 @@ static void* client_thread(void* args)
/* clean up */ /* clean up */
wolfSSL_CTX_free(cli_ctx); wolfSSL_CTX_free(cli_ctx);
free(writeBuf);
pthread_cond_signal(&info->to_server.cond); pthread_cond_signal(&info->to_server.cond);
info->to_client.done = 1; info->to_client.done = 1;
@@ -538,6 +521,7 @@ static void* server_thread(void* args)
info->server_stats.connTime += start; info->server_stats.connTime += start;
while (info->server_stats.txTotal < info->numBytes) {
/* read msg post handshake from client */ /* read msg post handshake from client */
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
start = gettime_secs(1); start = gettime_secs(1);
@@ -555,6 +539,7 @@ static void* server_thread(void* args)
if (ret > 0) { if (ret > 0) {
info->server_stats.txTotal += ret; info->server_stats.txTotal += ret;
} }
}
info->server_stats.connCount++; info->server_stats.connCount++;
@@ -605,48 +590,148 @@ static void print_stats(stats_t* wcStat, const char* desc, const char* cipher, i
wcStat->connTime * 1000, wcStat->connTime * 1000,
wcStat->connTime * 1000 / wcStat->connCount); wcStat->connTime * 1000 / wcStat->connCount);
} }
static void Usage(void)
{
printf("tls_bench " LIBWOLFSSL_VERSION_STRING
" NOTE: All files relative to wolfSSL home dir\n");
printf("-? Help, print this usage\n");
printf("-b <num> The total <num> bytes transferred per test connection, default %d\n", TEST_SIZE_BYTES);
#ifdef DEBUG_WOLFSSL
printf("-d Enable debug messages\n");
#endif
printf("-e List Every cipher suite available\n");
printf("-i Show peer info\n");
printf("-l <str> Cipher suite list (: delimited)\n");
printf("-t <num> Time <num> (seconds) to run each test, default %d\n", RUNTIME_SEC);
printf("-p <num> The packet size <num> in bytes [1-16kB], default %d\n", TEST_PACKET_SIZE);
printf("-v Show verbose output\n");
printf("-T <num> Thread pairs of server/client, default %d\n", THREAD_PAIRS);
}
static void ShowCiphers(void)
{
char ciphers[4096];
int ret = wolfSSL_get_ciphers(ciphers, (int)sizeof(ciphers));
if (ret == WOLFSSL_SUCCESS)
printf("%s\n", ciphers);
}
#ifdef __GNUC__ #ifdef __GNUC__
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #endif
int bench_tls(void) int bench_tls(void* args)
{ {
info_t theadInfo[THREAD_COUNT]; info_t *theadInfo, *info;
info_t* info;
int i, doShutdown; int i, doShutdown;
char *cipher, *next_cipher, ciphers[4096]; char *cipher, *next_cipher, ciphers[4096];
int argc = ((func_args*)args)->argc;
char** argv = ((func_args*)args)->argv;
int ch;
#ifdef DEBUG_WOLFSSL /* Vars configured by command line arguments */
wolfSSL_Debugging_ON(); int argRuntimeSec = RUNTIME_SEC;
#endif char *argCipherList = NULL;
int argTestSizeBytes = TEST_SIZE_BYTES;
int argTestPacketSize = TEST_PACKET_SIZE;
int argThreadPairs = THREAD_PAIRS;
int argShowVerbose = SHOW_VERBOSE;
((func_args*)args)->return_code = -1; /* error state */
/* Initialize wolfSSL */ /* Initialize wolfSSL */
wolfSSL_Init(); wolfSSL_Init();
/* Run for each cipher */ /* Parse command line arguments */
wolfSSL_get_ciphers(ciphers, (int)sizeof(ciphers)); while ((ch = mygetopt(argc, argv, "?" "b:deil:p:t:vT:")) != -1) {
switch (ch) {
case '?' :
Usage();
exit(EXIT_SUCCESS);
#ifndef SHOW_VERBOSE_OUTPUT case 'b' :
printf("Side\tCipher\tTotal Bytes\tNum Conns\tRx ms\tTx ms\tRx MB/s\tTx MB/s\tConnect Total ms\tConnect Avg ms\n"); argTestSizeBytes = atoi(myoptarg);
break;
#ifdef DEBUG_WOLFSSL
case 'd' :
wolfSSL_Debugging_ON();
break;
#endif #endif
/* parse by : */ case 'e' :
ShowCiphers();
exit(EXIT_SUCCESS);
case 'i' :
argShowPeerInfo = 1;
break;
case 'l' :
argCipherList = myoptarg;
break;
case 'p' :
argTestPacketSize = atoi(myoptarg);
break;
case 't' :
argRuntimeSec = atoi(myoptarg);
break;
case 'v' :
argShowVerbose = 1;
break;
case 'T' :
argThreadPairs = atoi(myoptarg);
break;
default:
Usage();
exit(MY_EX_USAGE);
}
}
/* reset for test cases */
myoptind = 0;
if (argCipherList != NULL) {
/* Use the list from CL argument */
cipher = argCipherList;
}
else {
/* Run for each cipher */
wolfSSL_get_ciphers(ciphers, (int)sizeof(ciphers));
cipher = ciphers; cipher = ciphers;
while (cipher != NULL && cipher[0] != '\0') { }
/* Allocate test info array */
theadInfo = (info_t*)malloc(sizeof(info_t) * argThreadPairs);
if (theadInfo != NULL) {
memset(theadInfo, 0, sizeof(info_t) * argThreadPairs);
}
/* parse by : */
while ((cipher != NULL) && (cipher[0] != '\0') && (theadInfo != NULL)) {
next_cipher = strchr(cipher, ':'); next_cipher = strchr(cipher, ':');
if (next_cipher != NULL) { if (next_cipher != NULL) {
cipher[next_cipher - cipher] = '\0'; cipher[next_cipher - cipher] = '\0';
} }
#ifdef SHOW_VERBOSE_OUTPUT if (argShowVerbose) {
printf("Cipher: %s\n", cipher); printf("Cipher: %s\n", cipher);
#endif }
memset(&theadInfo, 0, sizeof(theadInfo)); for (i=0; i<argThreadPairs; i++) {
for (i=0; i<THREAD_COUNT; i++) { info = (info_t*)memset(&theadInfo[i], 0, sizeof(info_t));
info = &theadInfo[i];
info->cipher = cipher; info->cipher = cipher;
info->numBytes = argTestSizeBytes;
info->packetSize = argTestPacketSize;
pthread_mutex_init(&info->to_server.mutex, NULL); pthread_mutex_init(&info->to_server.mutex, NULL);
pthread_mutex_init(&info->to_client.mutex, NULL); pthread_mutex_init(&info->to_client.mutex, NULL);
@@ -662,10 +747,10 @@ int bench_tls(void)
} }
/* run for x time */ /* run for x time */
sleep(RUNTIME_SEC); sleep(argRuntimeSec);
/* mark threads to quit */ /* mark threads to quit */
for (i = 0; i < THREAD_COUNT; ++i) { for (i = 0; i < argThreadPairs; ++i) {
info = &theadInfo[i]; info = &theadInfo[i];
info->shutdown = 1; info->shutdown = 1;
} }
@@ -674,35 +759,36 @@ int bench_tls(void)
do { do {
doShutdown = 1; doShutdown = 1;
for (i = 0; i < THREAD_COUNT; ++i) { for (i = 0; i < argThreadPairs; ++i) {
info = &theadInfo[i]; info = &theadInfo[i];
if (!info->to_client.done || !info->to_server.done) { if (!info->to_client.done || !info->to_server.done) {
doShutdown = 0; doShutdown = 0;
sleep(1); /* Allow other threads to run */
} }
} }
} while (!doShutdown); } while (!doShutdown);
#ifdef SHOW_VERBOSE_OUTPUT if (argShowVerbose) {
printf("Shutdown complete\n"); printf("Shutdown complete\n");
/* print results */ /* print results */
for (i = 0; i < THREAD_COUNT; ++i) { for (i = 0; i < argThreadPairs; ++i) {
info = &theadInfo[i]; info = &theadInfo[i];
printf("\nThread %d\n", i); printf("\nThread %d\n", i);
print_stats(&info->server_stats, "Server", info->cipher, 1); print_stats(&info->server_stats, "Server", info->cipher, 1);
print_stats(&info->client_stats, "Server", info->cipher, 1); print_stats(&info->client_stats, "Server", info->cipher, 1);
} }
#endif }
/* print combined results for more than one thread */ /* print combined results for more than one thread */
{
stats_t cli_comb; stats_t cli_comb;
stats_t srv_comb; stats_t srv_comb;
memset(&cli_comb, 0, sizeof(cli_comb)); memset(&cli_comb, 0, sizeof(cli_comb));
memset(&srv_comb, 0, sizeof(srv_comb)); memset(&srv_comb, 0, sizeof(srv_comb));
for (i = 0; i < THREAD_COUNT; ++i) { for (i = 0; i < argThreadPairs; ++i) {
info = &theadInfo[i]; info = &theadInfo[i];
cli_comb.connCount += info->client_stats.connCount; cli_comb.connCount += info->client_stats.connCount;
@@ -724,33 +810,41 @@ int bench_tls(void)
srv_comb.txTime += info->server_stats.txTime; srv_comb.txTime += info->server_stats.txTime;
} }
#ifdef SHOW_VERBOSE_OUTPUT if (argShowVerbose) {
printf("Totals for %d Threads\n", THREAD_COUNT); printf("Totals for %d Threads\n", argThreadPairs);
#endif }
else {
printf("Side\tCipher\tTotal Bytes\tNum Conns\tRx ms\tTx ms\tRx MB/s\tTx MB/s\tConnect Total ms\tConnect Avg ms\n");
print_stats(&srv_comb, "Server", theadInfo[0].cipher, 0); print_stats(&srv_comb, "Server", theadInfo[0].cipher, 0);
print_stats(&cli_comb, "Client", theadInfo[0].cipher, 0); print_stats(&cli_comb, "Client", theadInfo[0].cipher, 0);
} }
/* target next cipher */ /* target next cipher */
cipher = (next_cipher) ? next_cipher+1 : NULL; cipher = (next_cipher != NULL) ? (next_cipher + 1) : NULL;
} }
/* Cleanup and return */ /* Cleanup the wolfSSL environment */
wolfSSL_Cleanup(); /* Cleanup the wolfSSL environment */ wolfSSL_Cleanup();
return 0; /* Return reporting a success */ /* Free theadInfo array */
free(theadInfo);
/* Return reporting a success */
return (((func_args*)args)->return_code = 0);
} }
#ifndef NO_MAIN_DRIVER #ifndef NO_MAIN_DRIVER
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
(void)argc; func_args args;
(void)argv;
bench_tls(); args.argc = argc;
args.argv = argv;
return 0; bench_tls(&args);
return(args.return_code);
} }
#endif #endif

View File

@@ -24,7 +24,7 @@
#define WOLFSSL_TLS_BENCH_H #define WOLFSSL_TLS_BENCH_H
int bench_tls(void); int bench_tls(void* args);
#endif /* WOLFSSL_TLS_BENCH_H */ #endif /* WOLFSSL_TLS_BENCH_H */