Merge pull request #2863 from miyazakh/dtls_benchmark

added dtls benchmark
This commit is contained in:
David Garske
2020-03-27 12:06:06 -07:00
committed by GitHub
2 changed files with 335 additions and 13 deletions

View File

@ -105,6 +105,16 @@ bench_tls(args);
#endif
#endif
#ifdef WOLFSSL_DTLS
#ifdef BENCH_EMBEDDED
/* WOLFSSL_MAX_MTU in internal.h */
#define TEST_DTLS_PACKET_SIZE (1500)
#else
/* MAX_UDP_SIZE in interna.h */
#define TEST_DTLS_PACKET_SIZE (8092)
#endif
#endif
/* In memory transfer buffer maximum size */
/* Must be large enough to handle max TLS packet size plus max TLS header MAX_MSG_EXTRA */
#define MEM_BUFFER_SZ (TEST_PACKET_SIZE + 38 + WC_MAX_DIGEST_SIZE)
@ -275,6 +285,17 @@ typedef struct {
int showVerbose;
#ifndef NO_WOLFSSL_SERVER
int listenFd;
#endif
#ifdef WOLFSSL_DTLS
int doDTLS;
struct sockaddr_in serverAddr;
struct sockaddr_in clientAddr;
#ifdef HAVE_PTHREAD
int serverReady;
int clientOrserverOnly;
pthread_mutex_t dtls_mutex;
pthread_cond_t dtls_cond;
#endif
#endif
side_t client;
side_t server;
@ -300,6 +321,9 @@ typedef struct {
int myoptind = 0;
char* myoptarg = NULL;
#ifdef WOLFSSL_DTLS
int DoneHandShake = 0;
#endif
static double gettime_secs(int reset)
{
@ -495,6 +519,99 @@ static int SocketSend(int sockFd, char* buf, int sz)
}
return sent;
}
#ifdef WOLFSSL_DTLS
static int ReceiveFrom(WOLFSSL *ssl, int sd, char *buf, int sz)
{
int recvd;
int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
struct sockaddr peer;
socklen_t peerSz;
if (DoneHandShake) dtls_timeout = 0;
if (!wolfSSL_get_using_nonblock(ssl)) {
struct timeval timeout;
XMEMSET(&timeout, 0, sizeof(timeout));
timeout.tv_sec = dtls_timeout;
if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
sizeof(timeout)) != 0) {
printf("setsockopt rcvtimeo failed\n");
}
}
recvd = (int)recvfrom(sd, buf, sz, 0, (SOCKADDR*)&peer, &peerSz);
if (recvd < 0) {
if (errno == SOCKET_EWOULDBLOCK || errno == SOCKET_EAGAIN) {
if (wolfSSL_dtls_get_using_nonblock(ssl)) {
return WOLFSSL_CBIO_ERR_WANT_READ;
}
else {
return WOLFSSL_CBIO_ERR_TIMEOUT;
}
}
else if (errno == SOCKET_ECONNRESET) {
return WOLFSSL_CBIO_ERR_CONN_RST;
}
else if (errno == SOCKET_EINTR) {
return WOLFSSL_CBIO_ERR_ISR;
}
else if (errno == SOCKET_ECONNREFUSED) {
return WOLFSSL_CBIO_ERR_WANT_READ;
}
else {
return WOLFSSL_CBIO_ERR_GENERAL;
}
}
else {
if (recvd == 0) {
return WOLFSSL_CBIO_ERR_CONN_CLOSE;
}
}
return recvd;
}
static int SendTo(int sd, char *buf, int sz, const struct sockaddr *peer,
socklen_t peerSz)
{
int sent;
int len = sz;
sent = (int)sendto(sd, &buf[sz - len], len, 0, peer, peerSz);
if (sent < 0) {
if (errno == SOCKET_EWOULDBLOCK || errno == SOCKET_EAGAIN) {
return WOLFSSL_CBIO_ERR_WANT_WRITE;
}
else if (errno == SOCKET_ECONNRESET) {
return WOLFSSL_CBIO_ERR_CONN_RST;
}
else if (errno == SOCKET_EINTR) {
return WOLFSSL_CBIO_ERR_ISR;
}
else if (errno == SOCKET_EPIPE) {
return WOLFSSL_CBIO_ERR_CONN_CLOSE;
}
else {
return WOLFSSL_CBIO_ERR_GENERAL;
}
}
return sent;
}
static int myDoneHsCb(WOLFSSL* ssl, void* user_ctx)
{
(void) ssl;
(void) user_ctx;
DoneHandShake = 1;
return 1;
}
#endif
#ifndef NO_WOLFSSL_SERVER
static int ServerSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
@ -505,7 +622,13 @@ static int ServerSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
if (info->useLocalMem)
return ServerMemSend(info, buf, sz);
#endif
return SocketSend(info->server.sockFd, buf, sz);
#ifdef WOLFSSL_DTLS
if (info->doDTLS) {
return SendTo(info->server.sockFd, buf, sz,
(const struct sockaddr*)&info->clientAddr, sizeof(info->clientAddr));
} else
#endif
return SocketSend(info->server.sockFd, buf, sz);
}
static int ServerRecv(WOLFSSL* ssl, char* buf, int sz, void* ctx)
{
@ -515,7 +638,12 @@ static int ServerRecv(WOLFSSL* ssl, char* buf, int sz, void* ctx)
if (info->useLocalMem)
return ServerMemRecv(info, buf, sz);
#endif
return SocketRecv(info->server.sockFd, buf, sz);
#ifdef WOLFSSL_DTLS
if (info->doDTLS) {
return ReceiveFrom(ssl, info->server.sockFd, buf, sz);
} else
#endif
return SocketRecv(info->server.sockFd, buf, sz);
}
#endif /* !NO_WOLFSSL_SERVER */
@ -528,7 +656,13 @@ static int ClientSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
if (info->useLocalMem)
return ClientMemSend(info, buf, sz);
#endif
return SocketSend(info->client.sockFd, buf, sz);
#ifdef WOLFSSL_DTLS
if (info->doDTLS) {
return SendTo(info->client.sockFd, buf, sz,
(const struct sockaddr*)&info->serverAddr, sizeof(info->serverAddr));
} else
#endif
return SocketSend(info->client.sockFd, buf, sz);
}
static int ClientRecv(WOLFSSL* ssl, char* buf, int sz, void* ctx)
{
@ -538,7 +672,12 @@ static int ClientRecv(WOLFSSL* ssl, char* buf, int sz, void* ctx)
if (info->useLocalMem)
return ClientMemRecv(info, buf, sz);
#endif
return SocketRecv(info->client.sockFd, buf, sz);
#ifdef WOLFSSL_DTLS
if (info->doDTLS) {
return ReceiveFrom(ssl, info->client.sockFd, buf, sz);
} else
#endif
return SocketRecv(info->client.sockFd, buf, sz);
}
#endif /* !NO_WOLFSSL_CLIENT */
@ -548,6 +687,9 @@ static void CloseAndCleanupSocket(int* sockFd)
close(*sockFd);
*sockFd = -1;
}
#ifdef WOLFSSL_DTLS
DoneHandShake = 0;
#endif
}
#ifdef BENCH_USE_NONBLOCK
@ -589,6 +731,17 @@ static int SetupSocketAndConnect(info_t* info, const char* host,
servAddr.sin_addr.s_addr = inet_addr(host);
}
#ifdef WOLFSSL_DTLS
if (info->doDTLS) {
/* Create the SOCK_DGRAM socket type is implemented on the User
* Datagram Protocol/Internet Protocol(UDP/IP protocol).*/
if ((info->client.sockFd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
printf("ERROR: failed to create the SOCK_DGRAM socket\n");
return -1;
}
XMEMCPY(&info->serverAddr, &servAddr, sizeof(servAddr));
} else {
#endif
/* Create a socket that uses an Internet IPv4 address,
* Sets the socket to be stream based (TCP),
* 0 means choose the default protocol. */
@ -603,6 +756,9 @@ static int SetupSocketAndConnect(info_t* info, const char* host,
printf("ERROR: failed to connect\n");
return -1;
}
#ifdef WOLFSSL_DTLS
}
#endif
#ifdef BENCH_USE_NONBLOCK
if (SetSocketNonBlocking(info->client.sockFd) != 0) {
@ -631,11 +787,20 @@ static int bench_tls_client(info_t* info)
total = gettime_secs(0);
/* set up client */
#ifdef WOLFSSL_DTLS
if(info->doDTLS) {
if (tls13) return WOLFSSL_SUCCESS;
cli_ctx = wolfSSL_CTX_new(wolfDTLSv1_2_client_method());
} else
#endif
#ifdef WOLFSSL_TLS13
if (tls13)
cli_ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
#endif
if (!tls13)
#ifdef WOLFSSL_DTLS
if(!info->doDTLS)
#endif
#if !defined(WOLFSSL_TLS13)
cli_ctx = wolfSSL_CTX_new(wolfSSLv23_client_method());
#elif !defined(WOLFSSL_NO_TLS12)
@ -721,9 +886,36 @@ static int bench_tls_client(info_t* info)
goto exit;
}
#ifdef WOLFSSL_DTLS
if (info->doDTLS) {
ret = wolfSSL_dtls_set_peer(cli_ssl, &info->serverAddr,
sizeof(info->serverAddr));
if (ret != WOLFSSL_SUCCESS) {
printf("error setting dtls peer\n");
goto exit;
}
ret = wolfSSL_SetHsDoneCb(cli_ssl, myDoneHsCb, NULL);
if (ret != WOLFSSL_SUCCESS) {
printf("error handshake done callback\n");
goto exit;
}
}
#endif
wolfSSL_SetIOReadCtx(cli_ssl, info);
wolfSSL_SetIOWriteCtx(cli_ssl, info);
#if defined(HAVE_PTHREAD) && defined(WOLFSSL_DTLS)
/* synchronize with server */
if (info->doDTLS && !info->clientOrserverOnly) {
pthread_mutex_lock(&info->dtls_mutex);
if (info->serverReady != 1) {
pthread_cond_wait(&info->dtls_cond, &info->dtls_mutex);
}
/* for next loop */
info->serverReady = 0;
pthread_mutex_unlock(&info->dtls_mutex);
}
#endif
/* perform connect */
start = gettime_secs(1);
#ifndef BENCH_USE_NONBLOCK
@ -870,7 +1062,7 @@ static void* client_thread(void* args)
#ifndef NO_WOLFSSL_SERVER
static int SetupSocketAndListen(int* listenFd, word32 port)
static int SetupSocketAndListen(int* listenFd, word32 port, int doDTLS)
{
struct sockaddr_in servAddr;
#if defined(_MSC_VER) || defined(__MINGW32__)
@ -878,13 +1070,25 @@ static int SetupSocketAndListen(int* listenFd, word32 port)
#else
int optval = 1;
#endif
#ifndef WOLFSSL_DTLS
(void) doDTLS;
#endif
/* Setup server address */
XMEMSET(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(port);
servAddr.sin_addr.s_addr = INADDR_ANY;
#ifdef WOLFSSL_DTLS
if (doDTLS) {
/* Create a socket that is implemented on the User Datagram Protocol/
* Interet Protocol(UDP/IP protocol). */
if((*listenFd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
printf("ERROR: failed to create the socket\n");
return -1;
}
} else
#endif
/* Create a socket that uses an Internet IPv4 address,
* Sets the socket to be stream based (TCP),
* 0 means choose the default protocol. */
@ -906,7 +1110,9 @@ static int SetupSocketAndListen(int* listenFd, word32 port)
printf("ERROR: failed to bind\n");
return -1;
}
#ifdef WOLFSSL_DTLS
if (!doDTLS)
#endif
if (listen(*listenFd, 5) != 0) {
printf("ERROR: failed to listen\n");
return -1;
@ -926,7 +1132,28 @@ static int SocketWaitClient(info_t* info)
int connd;
struct sockaddr_in clientAddr;
socklen_t size = sizeof(clientAddr);
#ifdef WOLFSSL_DTLS
char msg[64];
if (info->doDTLS) {
#ifdef HAVE_PTHREAD
if (!info->clientOrserverOnly) {
pthread_mutex_lock(&info->dtls_mutex);
info->serverReady = 1;
pthread_cond_signal(&info->dtls_cond);
pthread_mutex_unlock(&info->dtls_mutex);
}
#endif
connd = (int)recvfrom(info->listenFd, (char *)msg, sizeof(msg),
MSG_PEEK, (struct sockaddr*)&clientAddr, &size);
if (connd < -1) {
printf("ERROR: failed to accept the connection\n");
return -1;
}
XMEMCPY(&info->clientAddr, &clientAddr, sizeof(clientAddr));
info->server.sockFd = info->listenFd;
} else {
#endif
if ((connd = accept(info->listenFd, (struct sockaddr*)&clientAddr, &size)) == -1) {
if (errno == SOCKET_EWOULDBLOCK)
return -2;
@ -934,6 +1161,9 @@ static int SocketWaitClient(info_t* info)
return -1;
}
info->server.sockFd = connd;
#ifdef WOLFSSL_DTLS
}
#endif
if (info->showVerbose) {
printf("Got client %d\n", connd);
@ -960,12 +1190,21 @@ static int bench_tls_server(info_t* info)
int total_sz;
/* set up server */
#ifdef WOLFSSL_DTLS
if(info->doDTLS) {
if(tls13) return WOLFSSL_SUCCESS;
srv_ctx = wolfSSL_CTX_new(wolfDTLSv1_2_server_method());
} else {
#endif
#ifdef WOLFSSL_TLS13
if (tls13)
srv_ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method());
#endif
if (!tls13)
srv_ctx = wolfSSL_CTX_new(wolfSSLv23_server_method());
#ifdef WOLFSSL_DTLS
}
#endif
if (srv_ctx == NULL) {
printf("error creating server ctx\n");
ret = MEMORY_E; goto exit;
@ -1059,10 +1298,19 @@ static int bench_tls_server(info_t* info)
printf("error creating server object\n");
ret = MEMORY_E; goto exit;
}
#ifdef WOLFSSL_DTLS
if (info->doDTLS) {
ret = wolfSSL_dtls_set_peer(srv_ssl, &info->clientAddr,
sizeof(info->clientAddr));
if (ret != WOLFSSL_SUCCESS) {
printf("error setting dtls peer\n");
goto exit;
}
}
#endif
wolfSSL_SetIOReadCtx(srv_ssl, info);
wolfSSL_SetIOWriteCtx(srv_ssl, info);
#ifndef NO_DH
wolfSSL_SetTmpDH(srv_ssl, p, sizeof(p), g, sizeof(g));
#endif
@ -1153,6 +1401,12 @@ static int bench_tls_server(info_t* info)
wolfSSL_free(srv_ssl);
srv_ssl = NULL;
#ifdef WOLFSSL_DTLS
if (info->doDTLS) {
SetupSocketAndListen(&info->listenFd, info->port, info->doDTLS);
}
#endif
}
exit:
@ -1182,7 +1436,11 @@ static void* server_thread(void* args)
if (!info->useLocalMem) {
/* Setup TLS server listener */
ret = SetupSocketAndListen(&info->listenFd, info->port);
#ifdef WOLFSSL_DTLS
ret = SetupSocketAndListen(&info->listenFd, info->port, info->doDTLS);
#else
ret = SetupSocketAndListen(&info->listenFd, info->port, 0);
#endif
}
if (ret == 0) {
ret = bench_tls_server(info);
@ -1252,6 +1510,9 @@ static void Usage(void)
printf("-l <str> Cipher suite list (: delimited)\n");
printf("-t <num> Time <num> (seconds) to run each test (default %d)\n", BENCH_RUNTIME_SEC);
printf("-p <num> The packet size <num> in bytes [1-16kB] (default %d)\n", TEST_PACKET_SIZE);
#ifdef WOLFSSL_DTLS
printf(" In the case of DTLS, [1-8kB] (default %d)\n", TEST_DTLS_PACKET_SIZE);
#endif
printf("-S <num> The total size <num> in bytes (default %d)\n", TEST_MAX_SIZE);
printf("-v Show verbose output\n");
#ifdef DEBUG_WOLFSSL
@ -1261,6 +1522,9 @@ static void Usage(void)
printf("-T <num> Number of threaded server/client pairs (default %d)\n", NUM_THREAD_PAIRS);
printf("-m Use local memory, not socket\n");
#endif
#ifdef WOLFSSL_DTLS
printf("-u Use DTLS\n");
#endif
}
static void ShowCiphers(void)
@ -1307,7 +1571,10 @@ int bench_tls(void* args)
int argLocalMem = 0;
int listenFd = -1;
#endif
#ifdef WOLFSSL_DTLS
int doDTLS = 0;
int option_p = 0;
#endif
if (args != NULL) {
argc = ((func_args*)args)->argc;
argv = ((func_args*)args)->argv;
@ -1318,7 +1585,7 @@ int bench_tls(void* args)
wolfSSL_Init();
/* Parse command line arguments */
while ((ch = mygetopt(argc, argv, "?" "deil:p:t:vT:sch:P:mS:")) != -1) {
while ((ch = mygetopt(argc, argv, "?" "udeil:p:t:vT:sch:P:mS:")) != -1) {
switch (ch) {
case '?' :
Usage();
@ -1365,6 +1632,9 @@ int bench_tls(void* args)
Usage();
ret = MY_EX_USAGE; goto exit;
}
#ifdef WOLFSSL_DTLS
option_p = 1;
#endif
break;
case 'S' :
@ -1390,7 +1660,17 @@ int bench_tls(void* args)
argLocalMem = 1;
#endif
break;
case 'u':
#ifdef WOLFSSL_DTLS
doDTLS = 1;
#ifdef BENCH_USE_NONBLOCK
printf("tls_bench hasn't yet supported DTLS "
"non-blocking mode.\n");
Usage();
ret = MY_EX_USAGE; goto exit;
#endif
#endif
break;
default:
Usage();
ret = MY_EX_USAGE; goto exit;
@ -1438,11 +1718,32 @@ int bench_tls(void* args)
/* Use same listen socket to avoid timing issues between client and server */
if (argServerOnly && !argLocalMem) {
/* Setup TLS server listener */
ret = SetupSocketAndListen(&listenFd, argPort);
#ifdef WOLFSSL_DTLS
ret = SetupSocketAndListen(&listenFd, argPort, doDTLS);
#else
ret = SetupSocketAndListen(&listenFd, argPort, 0);
#endif
if (ret != 0) goto exit;
}
#endif
#ifdef WOLFSSL_DTLS
if (doDTLS) {
if (argLocalMem) {
printf("tls_bench hasn't yet supported DTLS with local memory.\n");
ret = MY_EX_USAGE; goto exit;
}
if (option_p && argTestPacketSize > TEST_DTLS_PACKET_SIZE){
printf("Invalid packet size %d\n", argTestPacketSize);
Usage();
ret = MY_EX_USAGE; goto exit;
} else {
/* argTestPacketSize would be default for tcp packet */
if (argTestPacketSize >= TEST_PACKET_SIZE)
argTestPacketSize = TEST_DTLS_PACKET_SIZE;
}
}
#endif
printf("Running TLS Benchmarks...\n");
/* parse by : */
@ -1464,6 +1765,7 @@ int bench_tls(void* args)
info->port = argPort + i; /* threads must have separate ports */
info->cipher = cipher;
info->packetSize = argTestPacketSize;
info->runTimeSec = argRuntimeSec;
info->maxSize = argTestMaxSize;
info->showPeerInfo = argShowPeerInfo;
@ -1474,6 +1776,15 @@ int bench_tls(void* args)
info->client.sockFd = -1;
info->server.sockFd = -1;
#ifdef WOLFSSL_DTLS
info->doDTLS = doDTLS;
#ifdef HAVE_PTHREAD
info->serverReady = 0;
if (argServerOnly || argClientOnly) {
info->clientOrserverOnly = 1;
}
#endif
#endif
if (argClientOnly) {
#ifndef NO_WOLFSSL_CLIENT
ret = bench_tls_client(info);
@ -1489,6 +1800,10 @@ int bench_tls(void* args)
info->useLocalMem = argLocalMem;
pthread_mutex_init(&info->to_server.mutex, NULL);
pthread_mutex_init(&info->to_client.mutex, NULL);
#ifdef WOLFSSL_DTLS
pthread_mutex_init(&info->dtls_mutex, NULL);
pthread_cond_init(&info->dtls_cond, NULL);
#endif
pthread_cond_init(&info->to_server.cond, NULL);
pthread_cond_init(&info->to_client.cond, NULL);

View File

@ -498,6 +498,13 @@ static WC_INLINE int mygetopt(int argc, char** argv, const char* optstring)
char c;
char* cp;
/* Added sanity check becuase scan-build complains argv[myoptind] access
* results in a null pointer dereference. */
if (argv == NULL) {
myoptarg = NULL;
return -1;
}
if (myoptind == 0)
next = NULL; /* we're starting new/over */