Skip to content

handshake: test SSL_CTX pool #27

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ handshake [-t] [-s] <certsdir> <threadcount>
-P - use ossl_lib_ctx pool (can be combined with -s. If sharing is enabled, ssl_ctx
is shared within single thread)
-o - set ossl_lib_ctx pool size (use only with -P)
-l - use ssl_ctx pool
certsdir - Directory where the test can locate servercert.pem and serverkey.pem
threadcount - Number of concurrent threads to run in test

Expand Down
2 changes: 1 addition & 1 deletion source/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ clean:
CPPFLAGS += -I$(TARGET_OSSL_INCLUDE_PATH) -I.
# For second include path, i.e. out of tree build of OpenSSL uncomment this:
# CPPFLAGS += -I$(TARGET_OSSL_INCLUDE_PATH2)
CFLAGS += -pthread -O3
CFLAGS += -pthread -O3 -Wall
LDFLAGS += -L$(TARGET_OSSL_LIBRARY_PATH) -L.
# For setting RUNPATH on built executables uncomment this:
# LDFLAGS += -Wl,-rpath,$(TARGET_OSSL_LIBRARY_PATH)
Expand Down
171 changes: 139 additions & 32 deletions source/handshake.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,35 @@

int err = 0;

typedef enum {
INIT_LIB_CTX,
INIT_LIB_AND_SSL_CTX,
} init_ctx;

struct ctx {
OSSL_LIB_CTX *libctx;
SSL_CTX *sctx;
SSL_CTX *cctx;
};

static SSL_CTX *sctx = NULL, *cctx = NULL;
static int share_ctx = 1;
static char *cert = NULL;
static char *privkey = NULL;
static OSSL_LIB_CTX **libctx_pool = NULL;
static struct ctx **ctx_pool = NULL;


OSSL_TIME *times;

static int threadcount;
size_t num_calls;
static long ossl_lib_ctx_pool_size = 16;
static long pool_size = 16;

typedef enum {
TC_SSL_CTX,
TC_OSSL_LIB_CTX_PER_THREAD,
TC_OSSL_LIB_CTX_POOL,
TC_SSL_CTX_POOL,
} test_case_t;

static void do_handshake(size_t num)
Expand Down Expand Up @@ -149,15 +161,15 @@ static void do_handshake_ossl_lib_ctx_pool(size_t num)
int ret = 1;
size_t i;
OSSL_TIME start, end;
OSSL_LIB_CTX *libctx = NULL;
SSL_CTX *lsctx = NULL;
SSL_CTX *lcctx = NULL;
struct ctx *ctx = NULL;

start = ossl_time_now();

libctx = libctx_pool[num % ossl_lib_ctx_pool_size];
ctx = ctx_pool[num % pool_size];
if (share_ctx == 1) {
if (!perflib_create_ossl_lib_ctx_pair(libctx,
if (!perflib_create_ossl_lib_ctx_pair(ctx->libctx,
TLS_server_method(),
TLS_client_method(),
0, 0, &lsctx, &lcctx, cert,
Expand All @@ -170,7 +182,7 @@ static void do_handshake_ossl_lib_ctx_pool(size_t num)

for (i = 0; i < num_calls / threadcount; ++i) {
if (share_ctx == 0) {
if (!perflib_create_ossl_lib_ctx_pair(libctx,
if (!perflib_create_ossl_lib_ctx_pair(ctx->libctx,
TLS_server_method(),
TLS_client_method(),
0, 0, &lsctx, &lcctx, cert,
Expand Down Expand Up @@ -206,37 +218,101 @@ static void do_handshake_ossl_lib_ctx_pool(size_t num)
err = 1;
}

static int init_ossl_lib_ctx_pool()
static void do_handshake_ssl_ctx_pool(size_t num)
{
libctx_pool = OPENSSL_malloc(ossl_lib_ctx_pool_size * sizeof(*libctx_pool));
if (libctx_pool == NULL)
return 1;
SSL *clientssl = NULL, *serverssl = NULL;
int ret = 1;
size_t i;
OSSL_TIME start, end;
struct ctx *ssl_ctx = NULL;

for (int i = 0; i < ossl_lib_ctx_pool_size; ++i) {
libctx_pool[i] = OSSL_LIB_CTX_new();
if (libctx_pool[i] == NULL) {
fprintf(stderr, "%s:%d: Failed to create ossl lib context\n", __FILE__, __LINE__);
return 0;
}
start = ossl_time_now();

ssl_ctx = ctx_pool[num % pool_size];
for (i = 0; i < num_calls / threadcount; ++i) {
ret = perflib_create_ssl_objects(ssl_ctx->sctx, ssl_ctx->cctx, &serverssl, &clientssl,
NULL, NULL);
ret &= perflib_create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE);
perflib_shutdown_ssl_connection(serverssl, clientssl);
serverssl = clientssl = NULL;
}

return 1;
end = ossl_time_now();
times[num] = ossl_time_subtract(end, start);

if (!ret)
err = 1;
}

static void free_ossl_lib_ctx_pool()
static void free_ctx_pool()
{
for (int i = 0; i < ossl_lib_ctx_pool_size; ++i) {
OSSL_LIB_CTX_free(libctx_pool[i]);
if (ctx_pool == NULL)
return;
for (int i = 0; i < pool_size; ++i) {
if (ctx_pool[i]) {
OSSL_LIB_CTX_free(ctx_pool[i]->libctx);
SSL_CTX_free(ctx_pool[i]->sctx);
SSL_CTX_free(ctx_pool[i]->cctx);
OPENSSL_free(ctx_pool[i]);
}
}
OPENSSL_free(ctx_pool);
ctx_pool = NULL;
}

static int init_ctx_pool(init_ctx init_ctx)
{
ctx_pool = OPENSSL_zalloc(pool_size * sizeof(*ctx_pool));
if (ctx_pool == NULL) {
fprintf(stderr, "%s:%d: Failed to allocate ssl ctx pool\n", __FILE__, __LINE__);
return 0;
}

for (int i = 0; i < pool_size; ++i) {
SSL_CTX *lsctx = NULL, *lcctx = NULL;
struct ctx *ctx = NULL;
OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();

if (libctx == NULL) {
fprintf(stderr, "%s:%d: Failed to create ossl lib context\n", __FILE__, __LINE__);
return 0;
}

OPENSSL_free(libctx_pool);
if (init_ctx == INIT_LIB_AND_SSL_CTX) {
if (!perflib_create_ossl_lib_ctx_pair(libctx,
TLS_server_method(),
TLS_client_method(),
0, 0, &lsctx, &lcctx, cert,
privkey)) {
fprintf(stderr, "%s:%d: Failed to create SSL_CTX pair\n", __FILE__, __LINE__);
OSSL_LIB_CTX_free(libctx);
return 0;
}
}

ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx == NULL) {
OSSL_LIB_CTX_free(libctx);
SSL_CTX_free(lsctx);
SSL_CTX_free(lcctx);
return 0;
}

ctx->libctx = libctx;
ctx->sctx = lsctx;
ctx->cctx = lcctx;
ctx_pool[i] = ctx;
}

return 1;
}

static int test_ossl_lib_ctx_pool(size_t threadcount, OSSL_TIME *duration)
{
int ret = 0;

ret = init_ossl_lib_ctx_pool();
ret = init_ctx_pool(INIT_LIB_CTX);
if (!ret)
goto err;

Expand All @@ -245,18 +321,37 @@ static int test_ossl_lib_ctx_pool(size_t threadcount, OSSL_TIME *duration)
printf("Failed to run the test\n");

err:
free_ossl_lib_ctx_pool();
free_ctx_pool();

return ret;
}

static int test_ssl_ctx_pool(size_t threadcount, OSSL_TIME *duration)
{
int ret = 0;

ret = init_ctx_pool(INIT_LIB_AND_SSL_CTX);
if (!ret)
goto err;

ret = perflib_run_multi_thread_test(do_handshake_ssl_ctx_pool, threadcount, duration);
if (!ret)
printf("Failed to run the test\n");

err:
free_ctx_pool();

return ret;
}

void usage(const char *progname)
{
printf("Usage: %s [-t] [-s] [-p] [-P] [-o] certsdir threadcount\n", progname);
printf("Usage: %s [options] certsdir threadcount\n", progname);
printf("-t - terse output\n");
printf("-s - disable context sharing\n");
printf("-p - use ossl_lib_ctx per thread\n");
printf("-P - use ossl_lib_ctx pool\n");
printf("-l - use ssl ctx pool\n");
printf("-o - set ossl_lib_ctx pool size\n");
}

Expand All @@ -269,11 +364,11 @@ int main(int argc, char * const argv[])
int i;
int terse = 0;
int opt;
int p_flag = 0, P_flag = 0;
int p_flag = 0, P_flag = 0, l_flag = 0;
char *endptr = NULL;
test_case_t test_case = TC_SSL_CTX;

while ((opt = getopt(argc, argv, "tspPo:")) != -1) {
while ((opt = getopt(argc, argv, "tspPo:l")) != -1) {
switch (opt) {
case 't':
terse = 1;
Expand All @@ -291,8 +386,8 @@ int main(int argc, char * const argv[])
break;
case 'o':
errno = 0;
ossl_lib_ctx_pool_size = strtol(optarg, &endptr, 0);
if (errno == ERANGE && ossl_lib_ctx_pool_size == ULONG_MAX) {
pool_size = strtol(optarg, &endptr, 0);
if (errno == ERANGE && pool_size == ULONG_MAX) {
perror("Overflow occurred");
usage(basename(argv[0]));
return EXIT_FAILURE;
Expand All @@ -302,21 +397,25 @@ int main(int argc, char * const argv[])
usage(basename(argv[0]));
return EXIT_FAILURE;
}
if (ossl_lib_ctx_pool_size < 1) {
if (pool_size < 1) {
fprintf(stderr, "Pool size must be a > 0\n");
usage(basename(argv[0]));
return EXIT_FAILURE;
}
break;
case 'l':
l_flag = 1;
test_case = TC_SSL_CTX_POOL;
break;
default:
usage(basename(argv[0]));
return EXIT_FAILURE;
}
}

if ((p_flag + P_flag) > 1) {
fprintf(stderr,
"Error: -p and -P mutually exclusive. Choose only one.\n\n");
if ((p_flag + P_flag + l_flag) > 1) {
fprintf(stderr, "Error: -p, -P, and -l are mutually exclusive."
" Choose only one.\n\n");
usage(basename(argv[0]));
return EXIT_FAILURE;
}
Expand Down Expand Up @@ -386,6 +485,14 @@ int main(int argc, char * const argv[])
}
break;
}
case TC_SSL_CTX_POOL: {
int ret = test_ssl_ctx_pool(threadcount, &duration);
if (!ret) {
printf("Failed to run the test\n");
goto err;
}
break;
}
default:
fprintf(stderr, "Invalid test case\n");
goto err;
Expand Down