summaryrefslogtreecommitdiffstats
path: root/src/crypto/isa-l/isa-l_crypto/examples/saturation_test
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:54:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:54:28 +0000
commite6918187568dbd01842d8d1d2c808ce16a894239 (patch)
tree64f88b554b444a49f656b6c656111a145cbbaa28 /src/crypto/isa-l/isa-l_crypto/examples/saturation_test
parentInitial commit. (diff)
downloadceph-e6918187568dbd01842d8d1d2c808ce16a894239.tar.xz
ceph-e6918187568dbd01842d8d1d2c808ce16a894239.zip
Adding upstream version 18.2.2.upstream/18.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/crypto/isa-l/isa-l_crypto/examples/saturation_test')
-rw-r--r--src/crypto/isa-l/isa-l_crypto/examples/saturation_test/Makefile27
-rw-r--r--src/crypto/isa-l/isa-l_crypto/examples/saturation_test/README.txt25
-rw-r--r--src/crypto/isa-l/isa-l_crypto/examples/saturation_test/aes_thread.c380
-rw-r--r--src/crypto/isa-l/isa-l_crypto/examples/saturation_test/isal_multithread_perf.c206
-rw-r--r--src/crypto/isa-l/isa-l_crypto/examples/saturation_test/isal_multithread_perf.h52
-rw-r--r--src/crypto/isa-l/isa-l_crypto/examples/saturation_test/md5_thread.c213
-rw-r--r--src/crypto/isa-l/isa-l_crypto/examples/saturation_test/sha1_thread.c20
-rw-r--r--src/crypto/isa-l/isa-l_crypto/examples/saturation_test/sha256_thread.c20
-rw-r--r--src/crypto/isa-l/isa-l_crypto/examples/saturation_test/sha512_thread.c20
9 files changed, 963 insertions, 0 deletions
diff --git a/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/Makefile b/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/Makefile
new file mode 100644
index 000000000..41e9e29f2
--- /dev/null
+++ b/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/Makefile
@@ -0,0 +1,27 @@
+
+INCLUDE = /usr/include
+CFLAGS = -O2 -I$(INCLUDE)
+LDLIBS = -lisal_crypto -lcrypto -lpthread
+test = isal_multithread_perf
+
+source += isal_multithread_perf.c
+source += md5_thread.c \
+ sha1_thread.c \
+ sha256_thread.c \
+ sha512_thread.c \
+ aes_thread.c
+
+ODIR = bin
+objects = $(addprefix $(ODIR)/, $(patsubst %.c, %.o, $(source)))
+
+$(test): $(objects)
+ gcc $? $(LDLIBS) -o $@
+
+$(ODIR): ; mkdir -p $(ODIR)
+$(objects): | $(ODIR)
+$(ODIR)/%.o: %.c
+ gcc -c $(CFLAGS) $< -o $@
+
+clean:
+ @echo Cleaning up
+ @rm -fr $(ODIR) $(test)
diff --git a/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/README.txt b/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/README.txt
new file mode 100644
index 000000000..60335f76c
--- /dev/null
+++ b/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/README.txt
@@ -0,0 +1,25 @@
+/*
+ * Saturation Test
+ * Written by Xiaodong Liu <xiaodong.liu@intel.com>
+ */
+
+This tool is used to judge the saturation performance of ISA-L's multi-buffer hash and other algorithms.
+It can be used to give a comparision between multi-buffer hash and OpenSSL's single buffer hash.
+
+Compilation:
+(Make sure isa-l_crypto library is already installed. Other libs requried are openssl and pthread.)
+make
+
+Usage: ./isal_multithread_perf -n num_threads
+ -v verbose output
+ -t time to run(secs)
+ -n number of algorithm threads
+ -l len of each buffer(KB)
+ -a memory copy before algorithm -- 1 do(default); 0 not do
+ -b memory copy after algorithm -- 1 do(default); 0 not do
+ -m method of algorithm: md5 md5_mb sha1 sha1_mb sha256 sha256_mb
+ sha512 sha512_mb cbc_128_dec cbc_192_dec cbc_256_dec xts_128_enc
+ xts_256_enc gcm_128_enc gcm_256_enc
+
+Example:
+./isal_multithread_perf -m md5 -n 10
diff --git a/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/aes_thread.c b/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/aes_thread.c
new file mode 100644
index 000000000..366fc9bcf
--- /dev/null
+++ b/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/aes_thread.c
@@ -0,0 +1,380 @@
+
+#include <pthread.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "isal_multithread_perf.h"
+
+struct aes_context {
+ int const bits;
+ int (*const preproc)(struct aes_context * pCtx);
+ void (*const processor)(struct aes_context * pCtx, char *plaintext,
+ char *ciphertext, uint64_t len);
+ void (*const postproc)(struct aes_context * pCtx);
+};
+
+#define rounds_buf 2 /* first one is plain text, second is cipher text */
+
+static uint64_t aes_thread_func(int32_t id, struct aes_context *pCtx)
+{
+ uint32_t i = 0, j = 0;
+ char *aes_buf[rounds_buf] = { NULL }; /* aes buf is used to do checksum compute */
+ char *carry_buf[rounds_buf] = { NULL }; /* carry buf is used to do memory movement */
+ uint64_t round = -1;
+ struct timeval start_tv, stop_tv;
+ long long secs = run_secs;
+
+ printfv("Thread %i is started\n", id);
+ /* memory allocate */
+ for (j = 0; j < rounds_buf; j++) {
+ carry_buf[j] = (char *)calloc((size_t)buflen, 1);
+ if (carry_buf[j] == NULL) {
+ printf("calloc failed test aborted\n");
+ goto out;
+ }
+
+ aes_buf[j] = (char *)calloc((size_t)buflen, 1);
+ if (aes_buf[j] == NULL) {
+ printf("calloc failed test aborted\n");
+ goto out;
+ }
+
+ /* Create the random data */
+ for (i = 0; i < buflen; i += 1024) {
+ carry_buf[j][i] = i % 256;
+ aes_buf[j][i] = i % 256;
+ }
+ }
+
+ if (pCtx->preproc(pCtx)) {
+ printf("preproc failed test aborted\n");
+ goto out;
+ }
+
+ /* Thread sync */
+ pthread_mutex_lock(&count_lock);
+ count++;
+ if (count == num_threads) {
+ pthread_cond_broadcast(&count_cond);
+ } else {
+ pthread_cond_wait(&count_cond, &count_lock);
+ }
+ pthread_mutex_unlock(&count_lock);
+
+ printfv("Thread %i is ready\n", id);
+ /* hash func starts to run */
+ round = 0;
+ gettimeofday(&start_tv, 0);
+ gettimeofday(&stop_tv, 0);
+ while (secs > (stop_tv.tv_sec - start_tv.tv_sec)) {
+ /* Pre mem-operation */
+ if (prememcpy)
+ memcpy(aes_buf[0], carry_buf[0], buflen);
+
+ /* Calculate checksum */
+ pCtx->processor(pCtx, aes_buf[0], aes_buf[1], buflen);
+
+ /* Post mem-operation */
+ if (postmemcpy)
+ memcpy(carry_buf[1], aes_buf[1], buflen);
+
+ round++;
+
+ gettimeofday(&stop_tv, 0);
+ }
+ printfv("thread %2i, aes_func rounds %ld\n", id, round);
+
+ out:
+ pCtx->postproc(pCtx);
+
+ for (j = 0; j < rounds_buf; j++) {
+ free(carry_buf[j]);
+ free(aes_buf[j]);
+ }
+
+ return round;
+}
+
+/*
+ * facilities for AES-CBC
+ */
+static unsigned char const ic[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
+ 0x0e, 0x0f
+};
+
+void mk_rand_data(uint8_t * data, uint32_t size)
+{
+ unsigned int i;
+ for (i = 0; i < size; i++) {
+ *data++ = rand();
+ }
+}
+
+/* thread functions for cbc dec */
+struct cbc_context {
+ struct aes_context base;
+ uint8_t *iv;
+ uint8_t key[CBC_256_BITS];
+ struct cbc_key_data *key_data;
+};
+
+static int cbc_dec_pre(struct aes_context *p)
+{
+ struct cbc_context *pCtx = (struct cbc_context *)p;
+ int ret;
+
+ ret = posix_memalign((void **)&pCtx->iv, 16, (CBC_IV_DATA_LEN));
+ ret |= posix_memalign((void **)&pCtx->key_data, 16, (sizeof(*pCtx->key_data)));
+
+ if ((0 != ret) || (NULL == pCtx->iv) || (NULL == pCtx->key_data))
+ return 1;
+
+ mk_rand_data(pCtx->key, sizeof(pCtx->key));
+ memcpy(pCtx->iv, ic, CBC_IV_DATA_LEN);
+ aes_cbc_precomp(pCtx->key, pCtx->base.bits, pCtx->key_data);
+
+ return 0;
+}
+
+static void cbc_dec_post(struct aes_context *p)
+{
+ struct cbc_context *pCtx = (struct cbc_context *)p;
+
+ free(pCtx->iv);
+ free(pCtx->key_data);
+
+ return;
+}
+
+static void cbc_dec_proc(struct aes_context *p, char *plaintext, char *ciphertext,
+ uint64_t len)
+{
+ struct cbc_context *pCtx = (struct cbc_context *)p;
+
+ if (pCtx->base.bits == 128)
+ aes_cbc_dec_128(ciphertext, pCtx->iv, pCtx->key_data->dec_keys, plaintext,
+ len);
+ else if (pCtx->base.bits == 192)
+ aes_cbc_dec_192(ciphertext, pCtx->iv, pCtx->key_data->dec_keys, plaintext,
+ len);
+ else if (pCtx->base.bits == 256)
+ aes_cbc_dec_256(ciphertext, pCtx->iv, pCtx->key_data->dec_keys, plaintext,
+ len);
+ else {
+ printf("unsupported cbc encryption bits %d\n", pCtx->base.bits);
+ exit(1);
+ }
+
+ return;
+}
+
+void *cbc_128_dec_func(void *arg)
+{
+ int32_t id = *((int *)arg);
+ uint64_t round = -1;
+
+ struct cbc_context ctx =
+ { {128, cbc_dec_pre, cbc_dec_proc, cbc_dec_post}, NULL, {0}, NULL };
+
+ round = aes_thread_func(id, &ctx.base);
+
+ pthread_exit((void *)round);
+}
+
+void *cbc_192_dec_func(void *arg)
+{
+ int32_t id = *((int *)arg);
+ uint64_t round = -1;
+
+ struct cbc_context ctx =
+ { {192, cbc_dec_pre, cbc_dec_proc, cbc_dec_post}, NULL, {0}, NULL };
+
+ round = aes_thread_func(id, &ctx.base);
+
+ pthread_exit((void *)round);
+}
+
+void *cbc_256_dec_func(void *arg)
+{
+ int32_t id = *((int *)arg);
+ uint64_t round = -1;
+
+ struct cbc_context ctx =
+ { {256, cbc_dec_pre, cbc_dec_proc, cbc_dec_post}, NULL, {0}, NULL };
+
+ round = aes_thread_func(id, &ctx.base);
+
+ pthread_exit((void *)round);
+}
+
+/*
+ * thread functions for xts enc
+ */
+struct xts_content {
+ struct aes_context base;
+ unsigned char key1[16 * 2];
+ unsigned char key2[16 * 2];
+ unsigned char tinit[16];
+};
+
+static int xts_enc_pre(struct aes_context *p)
+{
+ struct xts_content *pCtx = (struct xts_content *)p;
+
+ mk_rand_data(pCtx->key1, pCtx->base.bits / 8);
+ mk_rand_data(pCtx->key2, pCtx->base.bits / 8);
+ mk_rand_data(pCtx->tinit, sizeof(pCtx->tinit));
+
+ return 0;
+}
+
+static void xts_enc_post(struct aes_context *p)
+{
+ return;
+}
+
+static void xts_enc_proc(struct aes_context *p, char *plaintext, char *ciphertext,
+ uint64_t len)
+{
+ struct xts_content *pCtx = (struct xts_content *)p;
+
+ if (pCtx->base.bits == 128)
+ XTS_AES_128_enc(pCtx->key2, pCtx->key1, pCtx->tinit, len, plaintext,
+ ciphertext);
+ else if (pCtx->base.bits == 256)
+ XTS_AES_256_enc(pCtx->key2, pCtx->key1, pCtx->tinit, len, plaintext,
+ ciphertext);
+ else {
+ printf("unsupported xts encryption bits %d\n", pCtx->base.bits);
+ exit(1);
+ }
+
+ return;
+}
+
+void *xts_128_enc_func(void *arg)
+{
+ int32_t id = *((int *)arg);
+ uint64_t round = -1;
+
+ struct xts_content ctx =
+ { {128, xts_enc_pre, xts_enc_proc, xts_enc_post}, {0}, {0}, {0} };
+
+ round = aes_thread_func(id, &ctx.base);
+
+ pthread_exit((void *)round);
+}
+
+void *xts_256_enc_func(void *arg)
+{
+ int32_t id = *((int *)arg);
+ uint64_t round = -1;
+
+ struct xts_content ctx =
+ { {256, xts_enc_pre, xts_enc_proc, xts_enc_post}, {0}, {0}, {0} };
+
+ round = aes_thread_func(id, &ctx.base);
+
+ pthread_exit((void *)round);
+}
+
+/*
+ * thread functions for gcm enc
+ */
+struct gcm_context {
+ struct aes_context base;
+ uint8_t *key;
+ unsigned char *iv;
+ unsigned char *aad;
+ unsigned char *gcm_tag;
+ struct gcm_key_data gkey;
+ struct gcm_context_data gctx;
+};
+
+static int gcm_enc_pre(struct aes_context *p)
+{
+ uint8_t const IVend[] = GCM_IV_END_MARK;
+
+ struct gcm_context *pCtx = (struct gcm_context *)p;
+
+ pCtx->key = malloc(pCtx->base.bits / 8);
+ pCtx->iv = malloc(GCM_IV_LEN);
+ pCtx->gcm_tag = malloc(MAX_TAG_LEN);
+ pCtx->aad = malloc(AAD_LENGTH);
+
+ mk_rand_data(pCtx->aad, AAD_LENGTH);
+
+ mk_rand_data(pCtx->iv, GCM_IV_LEN);
+ memcpy(&pCtx->iv[GCM_IV_END_START], IVend, sizeof(IVend));
+
+ mk_rand_data(pCtx->key, pCtx->base.bits / 8);
+ if (pCtx->base.bits == 128)
+ aes_gcm_pre_128(pCtx->key, &pCtx->gkey);
+ else
+ aes_gcm_pre_256(pCtx->key, &pCtx->gkey);
+
+ return 0;
+}
+
+static void gcm_enc_post(struct aes_context *p)
+{
+ struct gcm_context *pCtx = (struct gcm_context *)p;
+
+ free(pCtx->key);
+ free(pCtx->iv);
+ free(pCtx->gcm_tag);
+ free(pCtx->aad);
+
+ return;
+}
+
+static void gcm_enc_proc(struct aes_context *p, char *plaintext, char *ciphertext,
+ uint64_t len)
+{
+ struct gcm_context *pCtx = (struct gcm_context *)p;
+
+ if (pCtx->base.bits == 128)
+ aes_gcm_enc_128(&pCtx->gkey, &pCtx->gctx, ciphertext, plaintext, len, pCtx->iv,
+ pCtx->aad, AAD_LENGTH, pCtx->gcm_tag, MAX_TAG_LEN);
+ else if (pCtx->base.bits == 256)
+ aes_gcm_enc_256(&pCtx->gkey, &pCtx->gctx, ciphertext, plaintext, len, pCtx->iv,
+ pCtx->aad, AAD_LENGTH, pCtx->gcm_tag, MAX_TAG_LEN);
+ else {
+ printf("unsupported gcm encryption bits %d\n", pCtx->base.bits);
+ exit(1);
+ }
+
+ return;
+}
+
+void *gcm_128_enc_func(void *arg)
+{
+ int32_t id = *((int *)arg);
+ uint64_t round = -1;
+
+ struct gcm_context ctx =
+ { {128, gcm_enc_pre, gcm_enc_proc, gcm_enc_post}, NULL, NULL, NULL, NULL, {0} };
+
+ round = aes_thread_func(id, &ctx.base);
+
+ pthread_exit((void *)round);
+}
+
+void *gcm_256_enc_func(void *arg)
+{
+ int32_t id = *((int *)arg);
+ uint64_t round = -1;
+
+ struct gcm_context ctx =
+ { {256, gcm_enc_pre, gcm_enc_proc, gcm_enc_post}, NULL, NULL, NULL, NULL, {0} };
+
+ round = aes_thread_func(id, &ctx.base);
+
+ pthread_exit((void *)round);
+}
diff --git a/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/isal_multithread_perf.c b/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/isal_multithread_perf.c
new file mode 100644
index 000000000..1263fea29
--- /dev/null
+++ b/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/isal_multithread_perf.c
@@ -0,0 +1,206 @@
+/**
+ * @file isal_multithread_perf.c
+ * @brief It is used to verify high speed algorithm saturation issue
+ * @details
+ * usage: taskset -c <cpu_index1,cpu_index2,...> isal_multithread_perf -m <algorithm name> -n <thread num>
+ * eg: taskset -c 0-9,20-29 ./isal_multithread_perf -m md5_mb -n 10
+ */
+
+#include <pthread.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#include "isal_multithread_perf.h"
+
+alg_method algs[] = {
+ {"md5", md5_ossl_func, MD5_MAX_LANES}
+ ,
+ {"md5_mb", md5_mb_func, MD5_MAX_LANES}
+ ,
+ {"sha1", sha1_ossl_func, SHA1_MAX_LANES}
+ ,
+ {"sha1_mb", sha1_mb_func, SHA1_MAX_LANES}
+ ,
+ {"sha256", sha256_ossl_func, SHA256_MAX_LANES}
+ ,
+ {"sha256_mb", sha256_mb_func, SHA256_MAX_LANES}
+ ,
+ {"sha512", sha512_ossl_func, SHA512_MAX_LANES}
+ ,
+ {"sha512_mb", sha512_mb_func, SHA512_MAX_LANES}
+ ,
+ {"cbc_128_dec", cbc_128_dec_func, 1}
+ ,
+ {"cbc_192_dec", cbc_192_dec_func, 1}
+ ,
+ {"cbc_256_dec", cbc_256_dec_func, 1}
+ ,
+ {"xts_128_enc", xts_128_enc_func, 1}
+ ,
+ {"xts_256_enc", xts_256_enc_func, 1}
+ ,
+ {"gcm_128_enc", gcm_128_enc_func, 1}
+ ,
+ {"gcm_256_enc", gcm_256_enc_func, 1}
+ ,
+
+ {NULL, NULL}
+};
+
+/* Global parameters*/
+long long run_secs = 10;
+uint32_t num_threads = 2;
+uint32_t buflen = 32 * 1024;
+uint32_t prememcpy = 0;
+uint32_t postmemcpy = 0;
+char *method = "md5_mb";
+
+/* Global thread sync */
+pthread_mutex_t count_lock = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t count_cond = PTHREAD_COND_INITIALIZER;
+volatile uint32_t count = 0;
+
+int verbose = 0;
+
+void usage(char *appname)
+{
+ int i = 0;
+ printf("Usage: %s -n num_threads\n", appname);
+ printf("\t-v verbose output\n"
+ "\t-t time to run(secs)\n"
+ "\t-n number of algorithm threads\n"
+ "\t-l len of each buffer(KB)\n"
+ "\t-a memory copy before algorithm -- 1 do(default); 0 not do\n"
+ "\t-b memory copy after algorithm -- 1 do(default); 0 not do\n"
+ "\t-m method of algorithm:");
+ for (i = 0; algs[i].name != NULL; i++)
+ printf(" %s", algs[i].name);
+ printf("\n");
+
+}
+
+void notice(char *appname, alg_method * alg_choose_p)
+{
+ int i = 0;
+ printf("%s starts to run\n", appname);
+ printf("\tverbose output is %d\n"
+ "\truntime is %lld(secs)\n"
+ "\tnumber of algorithm threads is %d\n"
+ "\tlen of each buffer(KB) is %d\n"
+ "\tmemory copy before algorithm is %d\n"
+ "\tmemory copy after algorithm is %d\n"
+ "\tmethod of algorithm is %s\n", verbose, run_secs, num_threads, buflen / 1024,
+ prememcpy, postmemcpy, alg_choose_p->name);
+}
+
+int main(int argc, char **argv)
+{
+ int i = 0;
+ int opt;
+ char *optstring = "t:n:m:l:a:b:v";
+ int32_t *id = NULL, ret = 0;
+ alg_method alg_choose;
+ pthread_t *clients = NULL;
+ uint64_t count = 0, sum = 0;
+ uint32_t rounds_buf;
+
+ while ((opt = getopt(argc, argv, optstring)) != -1) {
+ switch (opt) {
+ case 't':
+ run_secs = atol(optarg);
+ if (run_secs <= 0) {
+ usage(argv[0]);
+ exit(-1);
+ }
+ break;
+ case 'n':
+ num_threads = atoi(optarg);
+ if (num_threads <= 0) {
+ usage(argv[0]);
+ exit(-1);
+ }
+ break;
+ case 'm':
+ method = optarg;
+ break;
+ case 'l':
+ buflen = atoi(optarg) * 1024;
+ if (buflen <= 0) {
+ usage(argv[0]);
+ exit(-1);
+ }
+ break;
+ case 'a':
+ prememcpy = atoi(optarg);
+ if (prememcpy != 0 && prememcpy != 1) {
+ usage(argv[0]);
+ exit(-1);
+ }
+ break;
+ case 'b':
+ postmemcpy = atoi(optarg);
+ if (postmemcpy != 0 && postmemcpy != 1) {
+ usage(argv[0]);
+ exit(-1);
+ }
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ default:
+ usage(argv[0]);
+ exit(0);
+ }
+ }
+
+ /* Check method str and set algorithm_func */
+ for (i = 0; algs[i].name != NULL; i++) {
+ if (!strcmp(method, algs[i].name)) {
+ alg_choose = algs[i];
+ break;
+ }
+ }
+ if (algs[i].name == NULL) {
+ usage(argv[0]);
+ exit(-1);
+ }
+
+ notice(argv[0], &alg_choose);
+ rounds_buf = alg_choose.rounds_nbuf;
+
+ clients = (pthread_t *) calloc(num_threads + 1, sizeof(pthread_t));
+ id = (int32_t *) calloc(num_threads + 1, sizeof(int32_t));
+
+ printf("Start %i threads, use %s function\n", num_threads, alg_choose.name);
+
+ for (i = 0; i < num_threads; i++) {
+ id[i] = i;
+
+ ret =
+ pthread_create(&clients[i], NULL, alg_choose.thread_func, (void *)&id[i]);
+
+ if (ret != 0) {
+ printf("Failed to create thread %i: %s", i, strerror(ret));
+ exit(-1);
+ }
+ printfv("Thread %i is created\n", i);
+ }
+
+ for (i = 0; i < num_threads; i++) {
+ pthread_join(clients[i], (void *)&count);
+ sum += count;
+ }
+ double loop_unit = ((double)buflen) * rounds_buf / run_secs / 1024 / 1024;
+ printf("Sum of rounds is %ld\n"
+ "Average throughput(MB/s) is %.2f\n"
+ "Total throughput(MB/s) is %.2f\n",
+ sum, (double)sum / i * loop_unit, (double)sum * loop_unit);
+
+ exit(0);
+}
diff --git a/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/isal_multithread_perf.h b/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/isal_multithread_perf.h
new file mode 100644
index 000000000..4f38705dd
--- /dev/null
+++ b/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/isal_multithread_perf.h
@@ -0,0 +1,52 @@
+
+#ifndef ISAL_MULTITHREAD_PERF_H_
+#define ISAL_MULTITHREAD_PERF_H_
+
+#include "isa-l_crypto.h"
+
+/* multibuffer hash */
+void *md5_ossl_func(void *arg);
+void *md5_mb_func(void *arg);
+void *sha1_ossl_func(void *arg);
+void *sha1_mb_func(void *arg);
+void *sha256_ossl_func(void *arg);
+void *sha256_mb_func(void *arg);
+void *sha512_ossl_func(void *arg);
+void *sha512_mb_func(void *arg);
+
+/* aes */
+void *cbc_128_dec_func(void *arg);
+void *cbc_192_dec_func(void *arg);
+void *cbc_256_dec_func(void *arg);
+void *xts_128_enc_func(void *arg);
+void *xts_256_enc_func(void *arg);
+#define AAD_LENGTH 16
+void *gcm_128_enc_func(void *arg);
+void *gcm_256_enc_func(void *arg);
+
+
+typedef struct {
+ char *name;
+ void *(*thread_func) (void *arg);
+ uint32_t rounds_nbuf; /* bufs number of one processing round */
+} alg_method;
+
+
+/* Global parameters*/
+extern long long run_secs;
+extern uint32_t num_threads;
+extern uint32_t buflen;
+extern uint32_t prememcpy;
+extern uint32_t postmemcpy;
+
+extern pthread_mutex_t count_lock;
+extern pthread_cond_t count_cond;
+extern volatile uint32_t count;
+
+extern int verbose;
+#define printfv(format, args...) { \
+ if (verbose) \
+ printf (format, ##args); \
+}
+
+#endif /* ISAL_MULTITHREAD_PERF_H_ */
diff --git a/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/md5_thread.c b/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/md5_thread.c
new file mode 100644
index 000000000..f63b3785b
--- /dev/null
+++ b/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/md5_thread.c
@@ -0,0 +1,213 @@
+
+#include <pthread.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <openssl/md5.h>
+#include <openssl/sha.h>
+
+#include "isal_multithread_perf.h"
+
+#ifndef HASH_THREAD
+/* MD5 related params and structures*/
+#define DIGEST_NWORDS MD5_DIGEST_NWORDS
+#define MB_BUFS MD5_MAX_LANES
+#define HASH_CTX_MGR MD5_HASH_CTX_MGR
+#define HASH_CTX MD5_HASH_CTX
+
+#define OSSL_THREAD_FUNC md5_ossl_func
+#define OSSL_HASH_FUNC MD5
+#define MB_THREAD_FUNC md5_mb_func
+#define CTX_MGR_INIT md5_ctx_mgr_init
+#define CTX_MGR_SUBMIT md5_ctx_mgr_submit
+#define CTX_MGR_FLUSH md5_ctx_mgr_flush
+
+#define rounds_buf MD5_MAX_LANES
+
+#endif // HASH_THREAD
+
+typedef uint32_t hash_digests[DIGEST_NWORDS];
+
+void *OSSL_THREAD_FUNC(void *arg)
+{
+ int32_t id = *((int *)arg);
+ uint32_t i = 0, j = 0;
+ char *hash_buf[rounds_buf] = { NULL }; /* hash buf is used to do hash compute */
+ char *carry_buf[rounds_buf] = { NULL }; /* carry buf is used to do memory movement */
+ hash_digests digest;
+ uint64_t round = -1;
+ struct timeval start_tv, stop_tv;
+ long long secs = run_secs;
+
+ printfv("Thread %i is started\n", id);
+ /* memory allocate */
+ for (j = 0; j < rounds_buf; j++) {
+ carry_buf[j] = (char *)calloc((size_t)buflen, 1);
+ if (carry_buf[j] == NULL) {
+ printf("calloc failed test aborted\n");
+ goto out;
+ }
+
+ hash_buf[j] = (char *)calloc((size_t)buflen, 1);
+ if (hash_buf[j] == NULL) {
+ printf("calloc failed test aborted\n");
+ goto out;
+ }
+
+ /* Create the random data */
+ for (i = 0; i < buflen; i += 1024) {
+ carry_buf[j][i] = i % 256;
+ hash_buf[j][i] = i % 256;
+ }
+ }
+
+ /* Thread sync */
+ pthread_mutex_lock(&count_lock);
+ count++;
+ if (count == num_threads) {
+ pthread_cond_broadcast(&count_cond);
+ } else {
+ pthread_cond_wait(&count_cond, &count_lock);
+ }
+ pthread_mutex_unlock(&count_lock);
+
+ printfv("Thread %i is ready\n", id);
+ /* hash func starts to run */
+ round = 0;
+ gettimeofday(&start_tv, 0);
+ gettimeofday(&stop_tv, 0);
+ while (secs > (stop_tv.tv_sec - start_tv.tv_sec)) {
+ for (j = 0; j < rounds_buf; j++) {
+ /* Pre mem-operation */
+ if (prememcpy)
+ memcpy(hash_buf[j], carry_buf[j], buflen);
+
+ /* Calculate hash digest */
+ OSSL_HASH_FUNC((char *)hash_buf[j], buflen, (unsigned char *)&digest);
+
+ /* Post mem-operation */
+ if (postmemcpy)
+ memcpy(carry_buf[j], hash_buf[j], buflen);
+ }
+ round++;
+
+ gettimeofday(&stop_tv, 0);
+ }
+ printfv("thread %2i, openssl_func rounds %ld\n", id, round);
+
+ out:
+ for (j = 0; j < rounds_buf; j++) {
+ free(carry_buf[j]);
+ free(hash_buf[j]);
+ }
+
+ pthread_exit((void *)round);
+}
+
+void *MB_THREAD_FUNC(void *arg)
+{
+ int32_t id = *((int *)arg);
+ uint32_t i = 0, j = 0;
+ char *hash_buf[rounds_buf] = { NULL }; /* hash buf is used to do hash compute */
+ char *carry_buf[rounds_buf] = { NULL }; /* carry buf is used to do memory movement */
+ hash_digests *digests[rounds_buf];
+ uint64_t round = -1;
+ struct timeval start_tv, stop_tv;
+ long long secs = run_secs;
+ int ret;
+
+ HASH_CTX_MGR *mgr = NULL;
+ HASH_CTX *ctxpool = NULL, *ctx = NULL;
+
+ printfv("Thread %i is started\n", id);
+ /* Memory allocate */
+ for (j = 0; j < rounds_buf; j++) {
+ carry_buf[j] = (char *)calloc((size_t)buflen, 1);
+ if (carry_buf[j] == NULL) {
+ printf("calloc failed test aborted\n");
+ goto out;
+ }
+
+ hash_buf[j] = (char *)calloc((size_t)buflen, 1);
+ if (hash_buf[j] == NULL) {
+ printf("calloc failed test aborted\n");
+ goto out;
+ }
+
+ digests[j] = (hash_digests *) calloc(sizeof(hash_digests), 1);
+
+ /* Create the random data */
+ for (i = 0; i < buflen; i += 1024) {
+ carry_buf[j][i] = i % 256;
+ hash_buf[j][i] = i % 256;
+ }
+ }
+
+ ctxpool = (HASH_CTX *) calloc(rounds_buf, sizeof(HASH_CTX));
+ for (i = 0; i < rounds_buf; i++) {
+ hash_ctx_init(&ctxpool[i]);
+ ctxpool[i].user_data = (void *)((uint64_t) i);
+ }
+ ret = posix_memalign((void *)&mgr, 16, sizeof(HASH_CTX_MGR));
+ if ((ret != 0) || (mgr == NULL)) {
+ printf("posix_memalign failed test aborted\n");
+ goto out;
+ }
+ CTX_MGR_INIT(mgr);
+
+ printfv("Thread %i gets to wait\n", id);
+ /* Thread sync */
+ pthread_mutex_lock(&count_lock);
+ count++;
+ if (count == num_threads) {
+ pthread_cond_broadcast(&count_cond);
+ } else {
+ pthread_cond_wait(&count_cond, &count_lock);
+ }
+ pthread_mutex_unlock(&count_lock);
+
+ printfv("Thread %i is ready\n", id);
+ /* hash func starts to run */
+ round = 0;
+ gettimeofday(&start_tv, 0);
+ gettimeofday(&stop_tv, 0);
+ while (secs > (stop_tv.tv_sec - start_tv.tv_sec)) {
+ for (j = 0; j < rounds_buf; j += MB_BUFS) {
+ for (i = 0; i < MB_BUFS; i++) {
+ /* Pre mem-operation */
+ if (prememcpy)
+ memcpy(hash_buf[j + i], carry_buf[j + i], buflen);
+
+ CTX_MGR_SUBMIT(mgr, &ctxpool[j + i], hash_buf[j + i], buflen,
+ HASH_ENTIRE);
+ }
+
+ /* Calculate hash digest */
+ while (CTX_MGR_FLUSH(mgr)) ;
+ for (i = 0; i < MB_BUFS; i++) {
+ /* Post mem-operation */
+ if (postmemcpy)
+ memcpy(carry_buf[j + i], hash_buf[j + i], buflen);
+ }
+ }
+ round++;
+
+ gettimeofday(&stop_tv, 0);
+ }
+ printfv("thread %2i, multibuffer_func rounds %ld\n", id, round);
+
+ out:
+ free(ctxpool);
+ free(mgr);
+ for (j = 0; j < rounds_buf; j++) {
+ free(carry_buf[j]);
+ free(digests[j]);
+ free(hash_buf[j]);
+ }
+
+ pthread_exit((void *)round);
+}
diff --git a/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/sha1_thread.c b/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/sha1_thread.c
new file mode 100644
index 000000000..5ec7eb04a
--- /dev/null
+++ b/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/sha1_thread.c
@@ -0,0 +1,20 @@
+
+#define HASH_THREAD
+/* sha1 related params and structures*/
+#define DIGEST_NWORDS SHA1_DIGEST_NWORDS
+#define MB_BUFS SHA1_MAX_LANES
+#define HASH_CTX_MGR SHA1_HASH_CTX_MGR
+#define HASH_CTX SHA1_HASH_CTX
+
+#define OSSL_THREAD_FUNC sha1_ossl_func
+#define OSSL_HASH_FUNC SHA1
+#define MB_THREAD_FUNC sha1_mb_func
+#define CTX_MGR_INIT sha1_ctx_mgr_init
+#define CTX_MGR_SUBMIT sha1_ctx_mgr_submit
+#define CTX_MGR_FLUSH sha1_ctx_mgr_flush
+
+#define rounds_buf SHA1_MAX_LANES
+
+#include "md5_thread.c"
+
+#undef HASH_THREAD
diff --git a/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/sha256_thread.c b/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/sha256_thread.c
new file mode 100644
index 000000000..c155c19d4
--- /dev/null
+++ b/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/sha256_thread.c
@@ -0,0 +1,20 @@
+
+#define HASH_THREAD
+/* sha256 related params and structures*/
+#define DIGEST_NWORDS SHA256_DIGEST_NWORDS
+#define MB_BUFS SHA256_MAX_LANES
+#define HASH_CTX_MGR SHA256_HASH_CTX_MGR
+#define HASH_CTX SHA256_HASH_CTX
+
+#define OSSL_THREAD_FUNC sha256_ossl_func
+#define OSSL_HASH_FUNC SHA256
+#define MB_THREAD_FUNC sha256_mb_func
+#define CTX_MGR_INIT sha256_ctx_mgr_init
+#define CTX_MGR_SUBMIT sha256_ctx_mgr_submit
+#define CTX_MGR_FLUSH sha256_ctx_mgr_flush
+
+#define rounds_buf SHA256_MAX_LANES
+
+#include "md5_thread.c"
+
+#undef HASH_THREAD
diff --git a/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/sha512_thread.c b/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/sha512_thread.c
new file mode 100644
index 000000000..5861835a8
--- /dev/null
+++ b/src/crypto/isa-l/isa-l_crypto/examples/saturation_test/sha512_thread.c
@@ -0,0 +1,20 @@
+
+#define HASH_THREAD
+/* sha512 related params and structures*/
+#define DIGEST_NWORDS (SHA512_DIGEST_NWORDS * 2)
+#define MB_BUFS SHA512_MAX_LANES
+#define HASH_CTX_MGR SHA512_HASH_CTX_MGR
+#define HASH_CTX SHA512_HASH_CTX
+
+#define OSSL_THREAD_FUNC sha512_ossl_func
+#define OSSL_HASH_FUNC SHA512
+#define MB_THREAD_FUNC sha512_mb_func
+#define CTX_MGR_INIT sha512_ctx_mgr_init
+#define CTX_MGR_SUBMIT sha512_ctx_mgr_submit
+#define CTX_MGR_FLUSH sha512_ctx_mgr_flush
+
+#define rounds_buf SHA512_MAX_LANES
+
+#include "md5_thread.c"
+
+#undef HASH_THREAD