"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-ipsec-mb.c" (15 Mar 2019, 17300 Bytes) of package /linux/privat/stress-ng-0.09.56.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "stress-ipsec-mb.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.09.52_vs_0.09.54.

    1 /*
    2  * Copyright (C) 2013-2019 Canonical, Ltd.
    3  *
    4  * This program is free software; you can redistribute it and/or
    5  * modify it under the terms of the GNU General Public License
    6  * as published by the Free Software Foundation; either version 2
    7  * of the License, or (at your option) any later version.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  *
   14  * You should have received a copy of the GNU General Public License
   15  * along with this program; if not, write to the Free Software
   16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
   17  *
   18  * This code is a complete clean re-write of the stress tool by
   19  * Colin Ian King <colin.king@canonical.com> and attempts to be
   20  * backwardly compatible with the stress tool by Amos Waterland
   21  * <apw@rossby.metr.ou.edu> but has more stress tests and more
   22  * functionality.
   23  *
   24  */
   25 #include "stress-ng.h"
   26 
   27 
   28 #if defined(HAVE_INTEL_IPSEC_MB_H) &&   \
   29     defined(HAVE_LIB_IPSEC_MB) &&   \
   30     defined(STRESS_X86) &&      \
   31     (defined(__x86_64__) || defined(__x86_64)) && \
   32     defined(IMB_FEATURE_SSE4_2) &&  \
   33     defined(IMB_FEATURE_CMOV) &&    \
   34     defined(IMB_FEATURE_AESNI) &&   \
   35     defined(IMB_FEATURE_AVX) &&     \
   36     defined(IMB_FEATURE_AVX2) &&    \
   37     defined(IMB_FEATURE_AVX512_SKX) 
   38 
   39 #define FEATURE_SSE     (IMB_FEATURE_SSE4_2 | IMB_FEATURE_CMOV | IMB_FEATURE_AESNI)
   40 #define FEATURE_AVX     (IMB_FEATURE_AVX | IMB_FEATURE_CMOV | IMB_FEATURE_AESNI)
   41 #define FEATURE_AVX2        (FEATURE_AVX | IMB_FEATURE_AVX2)
   42 #define FEATURE_AVX512      (FEATURE_AVX2 | IMB_FEATURE_AVX512_SKX)
   43 
   44 /*
   45  *  stress_ipsec_mb_features()
   46  *  get list of CPU feature bits
   47  */
   48 static int stress_ipsec_mb_features(const args_t *args, MB_MGR *p_mgr)
   49 {
   50     int features;
   51 
   52     features = p_mgr->features;
   53 
   54     if (args->instance == 0) {
   55         char str[128] = "";
   56 
   57         if ((features & FEATURE_SSE) == FEATURE_SSE)
   58             strcat(str, " sse");
   59         if ((features & FEATURE_AVX) == FEATURE_AVX)
   60             strcat(str, " avx");
   61         if ((features & FEATURE_AVX2) == FEATURE_AVX2)
   62             strcat(str, " avx2");
   63         if ((features & FEATURE_AVX512) == FEATURE_AVX512)
   64             strcat(str, " avx512");
   65 
   66         pr_inf("%s: features:%s\n", args->name, str);
   67     }
   68     return features;
   69 }
   70 
   71 /*
   72  *  stress_ipsec_mb_supported()
   73  *  check if ipsec_mb is supported
   74  */
   75 static int stress_ipsec_mb_supported(void)
   76 {
   77     /* Intel CPU? */
   78     if (!cpu_is_x86()) {
   79         pr_inf("ipsec_mb stressor will be skipped, "
   80             "not a recognised Intel CPU\n");
   81         return -1;
   82     }
   83     return 0;
   84 }
   85 
   86 /*
   87  *  stress_rnd_fill()
   88  *  fill uint32_t aligned buf with n bytes of random data
   89  */
   90 static void stress_rnd_fill(uint8_t *buf, size_t n)
   91 {
   92     register uint32_t *ptr = (uint32_t *)buf;
   93     register uint32_t *end = (uint32_t *)(buf + n);
   94 
   95     while (ptr < end)
   96         *(ptr++) = mwc32();
   97 }
   98 
   99 /*
  100  *  stress_job_empty()
  101  *  empty job queue
  102  */
  103 static inline void stress_job_empty(struct MB_MGR *mb_mgr)
  104 {
  105     while (IMB_FLUSH_JOB(mb_mgr))
  106         ;
  107 }
  108 
  109 static void stress_sha(
  110     const args_t *args,
  111     struct MB_MGR *mb_mgr,
  112     const uint8_t *data,
  113     const size_t data_len,
  114     const int jobs)
  115 {
  116     int j;
  117     const int sha_digest_size = 64;
  118     struct JOB_AES_HMAC *job;
  119     uint8_t digest[jobs * sha_digest_size];
  120 
  121     stress_rnd_fill(digest, sizeof(digest));
  122 
  123     stress_job_empty(mb_mgr);
  124 
  125     for (j = 0; j < jobs; j++) {
  126         uint8_t *auth = digest + (j * sha_digest_size);
  127 
  128         job = IMB_GET_NEXT_JOB(mb_mgr);
  129         (void)memset(job, 0, sizeof(*job));
  130 
  131         job->cipher_direction = ENCRYPT;
  132         job->chain_order = HASH_CIPHER;
  133         job->auth_tag_output = auth;
  134         job->auth_tag_output_len_in_bytes = sha_digest_size;
  135         job->src = data;
  136         job->msg_len_to_hash_in_bytes = data_len;
  137         job->cipher_mode = NULL_CIPHER;
  138         job->hash_alg = PLAIN_SHA_512;
  139         job = IMB_SUBMIT_JOB(mb_mgr);
  140         (void)job;
  141     }
  142 
  143     for (j = 0; j < jobs; j++) {
  144         job = IMB_FLUSH_JOB(mb_mgr);
  145         if (!job)
  146             break;
  147         if (job->status != STS_COMPLETED) {
  148             pr_err("%s: sha: job %d not completed\n",
  149                 args->name, j);
  150         }
  151     }
  152     if (j != jobs)
  153         pr_err("%s: sha: only processed %d of %d jobs\n",
  154             args->name, j, jobs);
  155 }
  156 
  157 static void stress_des(
  158     const args_t *args,
  159     struct MB_MGR *mb_mgr,
  160     const uint8_t *data,
  161     const size_t data_len,
  162     const int jobs)
  163 {
  164     int j;
  165     struct JOB_AES_HMAC *job;
  166 
  167     uint8_t encoded[jobs * data_len] ALIGNED(16);
  168     uint8_t k[32] ALIGNED(16);
  169     uint8_t iv[16] ALIGNED(16);
  170     uint32_t enc_keys[15*4] ALIGNED(16);
  171     uint32_t dec_keys[15*4] ALIGNED(16);
  172 
  173     stress_rnd_fill(k, sizeof(k));
  174     stress_rnd_fill(iv, sizeof(iv));
  175     stress_job_empty(mb_mgr);
  176     IMB_AES_KEYEXP_256(mb_mgr, k, enc_keys, dec_keys);
  177 
  178     for (j = 0; j < jobs; j++) {
  179         uint8_t *dst = encoded + (j * data_len);
  180 
  181         job = IMB_GET_NEXT_JOB(mb_mgr);
  182         (void)memset(job, 0, sizeof(*job));
  183 
  184         job->cipher_direction = ENCRYPT;
  185         job->chain_order = CIPHER_HASH;
  186         job->src = data;
  187         job->dst = dst;
  188         job->cipher_mode = CBC;
  189         job->aes_enc_key_expanded = enc_keys;
  190         job->aes_dec_key_expanded = dec_keys;
  191         job->aes_key_len_in_bytes = sizeof(k);
  192         job->iv = iv;
  193         job->iv_len_in_bytes = sizeof(iv);
  194         job->cipher_start_src_offset_in_bytes = 0;
  195         job->msg_len_to_cipher_in_bytes = data_len;
  196         job->user_data = dst;
  197         job->user_data2 = (void *)((uint64_t)j);
  198         job->hash_alg = NULL_HASH;
  199         job = IMB_SUBMIT_JOB(mb_mgr);
  200         (void)job;
  201     }
  202 
  203     for (j = 0; j < jobs; j++) {
  204         job = IMB_FLUSH_JOB(mb_mgr);
  205         if (!job)
  206             break;
  207         if (job->status != STS_COMPLETED) {
  208             pr_err("%s: des: job %d not completed\n",
  209                 args->name, j);
  210         }
  211     }
  212     if (j != jobs)
  213         pr_err("%s: des: only processed %d of %d jobs\n",
  214             args->name, j, jobs);
  215 }
  216 
  217 static void stress_cmac(
  218     const args_t *args,
  219     struct MB_MGR *mb_mgr,
  220     const uint8_t *data,
  221     const size_t data_len,
  222     const int jobs)
  223 {
  224     int j;
  225     struct JOB_AES_HMAC *job;
  226 
  227     uint8_t key[16] ALIGNED(16);
  228     uint32_t expkey[4 * 15] ALIGNED(16);
  229     uint32_t dust[4 * 15] ALIGNED(16);
  230     uint32_t skey1[4], skey2[4];
  231     uint8_t output[jobs * data_len] ALIGNED(16);
  232 
  233     stress_rnd_fill(key, sizeof(key));
  234     IMB_AES_KEYEXP_128(mb_mgr, key, expkey, dust);
  235     IMB_AES_CMAC_SUBKEY_GEN_128(mb_mgr, expkey, skey1, skey2);
  236     stress_job_empty(mb_mgr);
  237 
  238     for (j = 0; j < jobs; j++) {
  239         uint8_t *dst = output + (j * 16);
  240 
  241         job = IMB_GET_NEXT_JOB(mb_mgr);
  242         (void)memset(job, 0, sizeof(*job));
  243 
  244         job->cipher_direction = ENCRYPT;
  245         job->chain_order = HASH_CIPHER;
  246         job->cipher_mode = NULL_CIPHER;
  247         job->hash_alg = AES_CMAC;
  248         job->src = data;
  249         job->hash_start_src_offset_in_bytes = 0;
  250         job->msg_len_to_hash_in_bytes = data_len;
  251         job->auth_tag_output = dst;
  252         job->auth_tag_output_len_in_bytes = 16;
  253         job->u.CMAC._key_expanded = expkey;
  254         job->u.CMAC._skey1 = skey1;
  255         job->u.CMAC._skey2 = skey2;
  256         job->user_data = dst;
  257         job = IMB_SUBMIT_JOB(mb_mgr);
  258         (void)job;
  259     }
  260 
  261     for (j = 0; j < jobs; j++) {
  262         job = IMB_FLUSH_JOB(mb_mgr);
  263         if (!job)
  264             break;
  265         if (job->status != STS_COMPLETED) {
  266             pr_err("%s: cmac: job %d not completed\n",
  267                 args->name, j);
  268         }
  269     }
  270     if (j != jobs)
  271         pr_err("%s: cmac: only processed %d of %d jobs\n",
  272             args->name, j, jobs);
  273 }
  274 
  275 static void stress_ctr(
  276     const args_t *args,
  277     struct MB_MGR *mb_mgr,
  278     const uint8_t *data,
  279     const size_t data_len,
  280     const int jobs)
  281 {
  282     int j;
  283     struct JOB_AES_HMAC *job;
  284 
  285     uint8_t encoded[jobs * data_len] ALIGNED(16);
  286     uint8_t key[32] ALIGNED(16);
  287     uint8_t iv[12] ALIGNED(16);     /* 4 byte nonce + 8 byte IV */
  288     uint32_t expkey[4 * 15] ALIGNED(16);
  289     uint32_t dust[4 * 15] ALIGNED(16);
  290 
  291     stress_rnd_fill(key, sizeof(key));
  292     stress_rnd_fill(iv, sizeof(iv));
  293     IMB_AES_KEYEXP_256(mb_mgr, key, expkey, dust);
  294     stress_job_empty(mb_mgr);
  295 
  296     for (j = 0; j < jobs; j++) {
  297         uint8_t *dst = encoded + (j * data_len);
  298 
  299         job = IMB_GET_NEXT_JOB(mb_mgr);
  300         (void)memset(job, 0, sizeof(*job));
  301 
  302         job->cipher_direction = ENCRYPT;
  303         job->chain_order = CIPHER_HASH;
  304         job->cipher_mode = CNTR;
  305         job->hash_alg = NULL_HASH;
  306         job->src = data;
  307         job->dst = dst;
  308         job->aes_enc_key_expanded = expkey;
  309         job->aes_dec_key_expanded = expkey;
  310         job->aes_key_len_in_bytes = sizeof(key);
  311         job->iv = iv;
  312         job->iv_len_in_bytes = sizeof(iv);
  313         job->cipher_start_src_offset_in_bytes = 0;
  314         job->msg_len_to_cipher_in_bytes = data_len;
  315         job = IMB_SUBMIT_JOB(mb_mgr);
  316         (void)job;
  317     }
  318 
  319     for (j = 0; j < jobs; j++) {
  320         job = IMB_FLUSH_JOB(mb_mgr);
  321         if (!job)
  322             break;
  323         if (job->status != STS_COMPLETED) {
  324             pr_err("%s: ctr: job %d not completed\n",
  325                 args->name, j);
  326         }
  327     }
  328     if (j != jobs)
  329         pr_err("%s: ctr: only processed %d of %d jobs\n",
  330             args->name, j, jobs);
  331 }
  332 
  333 static void stress_hmac_md5(
  334     const args_t *args,
  335     struct MB_MGR *mb_mgr,
  336     const uint8_t *data,
  337     const size_t data_len,
  338     const int jobs)
  339 {
  340     int j;
  341     size_t i;
  342     struct JOB_AES_HMAC *job;
  343 
  344     const int digest_size = 16;
  345     const int block_size = 64;
  346     uint8_t key[block_size] ALIGNED(16);
  347     uint8_t buf[block_size] ALIGNED(16);
  348     uint8_t ipad_hash[digest_size] ALIGNED(16);
  349     uint8_t opad_hash[digest_size] ALIGNED(16);
  350     uint8_t output[jobs * digest_size] ALIGNED(16);
  351 
  352     stress_rnd_fill(key, sizeof(key));
  353     for (i = 0; i < sizeof(key); i++)
  354         buf[i] = key[i] ^ 0x36;
  355     IMB_MD5_ONE_BLOCK(mb_mgr, buf, ipad_hash);
  356     for (i = 0; i < sizeof(key); i++)
  357         buf[i] = key[i] ^ 0x5c;
  358     IMB_MD5_ONE_BLOCK(mb_mgr, buf, opad_hash);
  359 
  360     stress_job_empty(mb_mgr);
  361 
  362     for (j = 0; j < jobs; j++) {
  363         uint8_t *dst = output + (j * digest_size);
  364 
  365         job = IMB_GET_NEXT_JOB(mb_mgr);
  366         (void)memset(job, 0, sizeof(*job));
  367 
  368         job->aes_enc_key_expanded = NULL;
  369         job->aes_dec_key_expanded = NULL;
  370         job->cipher_direction = ENCRYPT;
  371         job->chain_order = HASH_CIPHER;
  372         job->dst = NULL;
  373         job->aes_key_len_in_bytes = 0;
  374         job->auth_tag_output = dst;
  375         job->auth_tag_output_len_in_bytes = digest_size;
  376         job->iv = NULL;
  377         job->iv_len_in_bytes = 0;
  378         job->src = data;
  379         job->cipher_start_src_offset_in_bytes = 0;
  380         job->msg_len_to_cipher_in_bytes = 0;
  381         job->hash_start_src_offset_in_bytes = 0;
  382         job->msg_len_to_hash_in_bytes = data_len;
  383         job->u.HMAC._hashed_auth_key_xor_ipad = ipad_hash;
  384         job->u.HMAC._hashed_auth_key_xor_opad = opad_hash;
  385         job->cipher_mode = NULL_CIPHER;
  386         job->hash_alg = MD5;
  387         job->user_data = dst;
  388         job = IMB_SUBMIT_JOB(mb_mgr);
  389         (void)job;
  390     }
  391 
  392     for (j = 0; j < jobs; j++) {
  393         job = IMB_FLUSH_JOB(mb_mgr);
  394         if (!job)
  395             break;
  396         if (job->status != STS_COMPLETED) {
  397             pr_err("%s: hmac md5: job %d not completed\n",
  398                 args->name, j);
  399         }
  400     }
  401     if (j != jobs)
  402         pr_err("%s: hmac md5: only processed %d of %d jobs\n",
  403             args->name, j, jobs);
  404 }
  405 
  406 static void stress_hmac_sha1(
  407     const args_t *args,
  408     struct MB_MGR *mb_mgr,
  409     const uint8_t *data,
  410     const size_t data_len,
  411     const int jobs)
  412 {
  413     int j;
  414     size_t i;
  415     struct JOB_AES_HMAC *job;
  416 
  417     const int digest_size = 20;
  418     const int block_size = 64;
  419     uint8_t key[block_size] ALIGNED(16);
  420     uint8_t buf[block_size] ALIGNED(16);
  421     uint8_t ipad_hash[digest_size] ALIGNED(16);
  422     uint8_t opad_hash[digest_size] ALIGNED(16);
  423     uint8_t output[jobs * digest_size] ALIGNED(16);
  424 
  425     stress_rnd_fill(key, sizeof(key));
  426     for (i = 0; i < sizeof(key); i++)
  427         buf[i] = key[i] ^ 0x36;
  428     IMB_MD5_ONE_BLOCK(mb_mgr, buf, ipad_hash);
  429     for (i = 0; i < sizeof(key); i++)
  430         buf[i] = key[i] ^ 0x5c;
  431     IMB_MD5_ONE_BLOCK(mb_mgr, buf, opad_hash);
  432 
  433     stress_job_empty(mb_mgr);
  434 
  435     for (j = 0; j < jobs; j++) {
  436         uint8_t *dst = output + (j * digest_size);
  437 
  438         job = IMB_GET_NEXT_JOB(mb_mgr);
  439         (void)memset(job, 0, sizeof(*job));
  440 
  441         job->aes_enc_key_expanded = NULL;
  442         job->aes_dec_key_expanded = NULL;
  443         job->cipher_direction = ENCRYPT;
  444         job->chain_order = HASH_CIPHER;
  445         job->dst = NULL;
  446         job->aes_key_len_in_bytes = 0;
  447         job->auth_tag_output = dst;
  448         job->auth_tag_output_len_in_bytes = digest_size;
  449         job->iv = NULL;
  450         job->iv_len_in_bytes = 0;
  451         job->src = data;
  452         job->cipher_start_src_offset_in_bytes = 0;
  453         job->msg_len_to_cipher_in_bytes = 0;
  454         job->hash_start_src_offset_in_bytes = 0;
  455         job->msg_len_to_hash_in_bytes = data_len;
  456         job->u.HMAC._hashed_auth_key_xor_ipad = ipad_hash;
  457         job->u.HMAC._hashed_auth_key_xor_opad = opad_hash;
  458         job->cipher_mode = NULL_CIPHER;
  459         job->hash_alg = SHA1;
  460         job->user_data = dst;
  461         job = IMB_SUBMIT_JOB(mb_mgr);
  462         (void)job;
  463     }
  464 
  465     for (j = 0; j < jobs; j++) {
  466         job = IMB_FLUSH_JOB(mb_mgr);
  467         if (!job)
  468             break;
  469         if (job->status != STS_COMPLETED) {
  470             pr_err("%s: hmac sha1: job %d not completed\n",
  471                 args->name, j);
  472         }
  473     }
  474     if (j != jobs)
  475         pr_err("%s: hmac sha1: only processed %d of %d jobs\n",
  476             args->name, j, jobs);
  477 }
  478 
  479 static void stress_hmac_sha512(
  480     const args_t *args,
  481     struct MB_MGR *mb_mgr,
  482     const uint8_t *data,
  483     const size_t data_len,
  484     const int jobs)
  485 {
  486     int j;
  487     size_t i;
  488     struct JOB_AES_HMAC *job;
  489 
  490     const int digest_size = SHA512_DIGEST_SIZE_IN_BYTES;
  491     const int block_size = SHA_512_BLOCK_SIZE;
  492     uint8_t rndkey[block_size] ALIGNED(16);
  493     uint8_t key[block_size] ALIGNED(16);
  494     uint8_t buf[block_size] ALIGNED(16);
  495     uint8_t ipad_hash[digest_size] ALIGNED(16);
  496     uint8_t opad_hash[digest_size] ALIGNED(16);
  497     uint8_t output[jobs * digest_size] ALIGNED(16);
  498 
  499     stress_rnd_fill(rndkey, sizeof(rndkey));
  500 
  501     IMB_SHA512(mb_mgr, rndkey, SHA_512_BLOCK_SIZE, key);
  502 
  503     for (i = 0; i < sizeof(key); i++)
  504         buf[i] = key[i] ^ 0x36;
  505     IMB_SHA512_ONE_BLOCK(mb_mgr, buf, ipad_hash);
  506     for (i = 0; i < sizeof(key); i++)
  507         buf[i] = key[i] ^ 0x5c;
  508     IMB_SHA512_ONE_BLOCK(mb_mgr, buf, opad_hash);
  509 
  510     stress_job_empty(mb_mgr);
  511 
  512     for (j = 0; j < jobs; j++) {
  513         uint8_t *dst = output + (j * digest_size);
  514 
  515         job = IMB_GET_NEXT_JOB(mb_mgr);
  516         (void)memset(job, 0, sizeof(*job));
  517 
  518         job->aes_enc_key_expanded = NULL;
  519         job->aes_dec_key_expanded = NULL;
  520         job->cipher_direction = ENCRYPT;
  521         job->chain_order = HASH_CIPHER;
  522         job->dst = NULL;
  523         job->aes_key_len_in_bytes = 0;
  524         job->auth_tag_output = dst;
  525         job->auth_tag_output_len_in_bytes = digest_size;
  526         job->iv = NULL;
  527         job->iv_len_in_bytes = 0;
  528         job->src = data;
  529         job->cipher_start_src_offset_in_bytes = 0;
  530         job->msg_len_to_cipher_in_bytes = 0;
  531         job->hash_start_src_offset_in_bytes = 0;
  532         job->msg_len_to_hash_in_bytes = data_len;
  533         job->u.HMAC._hashed_auth_key_xor_ipad = ipad_hash;
  534         job->u.HMAC._hashed_auth_key_xor_opad = opad_hash;
  535         job->cipher_mode = NULL_CIPHER;
  536         job->hash_alg = SHA_512;
  537         job->user_data = dst;
  538         job = IMB_SUBMIT_JOB(mb_mgr);
  539         (void)job;
  540     }
  541 
  542     for (j = 0; j < jobs; j++) {
  543         job = IMB_FLUSH_JOB(mb_mgr);
  544         if (!job)
  545             break;
  546         if (job->status != STS_COMPLETED) {
  547             pr_err("%s: hmac sha512: job %d not completed\n",
  548                 args->name, j);
  549         }
  550     }
  551     if (j != jobs)
  552         pr_err("%s: hmac sha512: only processed %d of %d jobs\n",
  553             args->name, j, jobs);
  554 }
  555 
  556 
  557 typedef struct {
  558     const int features;
  559     const char *name;
  560     void (*init_func)(MB_MGR *p_mgr);
  561 } init_mb_t;
  562 
  563 init_mb_t init_mb[] = {
  564     { FEATURE_SSE,      "sse",      init_mb_mgr_sse },
  565     { FEATURE_AVX,      "avx",      init_mb_mgr_avx },
  566     { FEATURE_AVX2,     "avx2",     init_mb_mgr_avx2 },
  567     { FEATURE_AVX512,   "avx512",   init_mb_mgr_avx512 },
  568 };
  569 
  570 /*
  571  *  stress_ipsec_mb()
  572  *      stress Intel ipsec_mb instruction
  573  */
  574 static int stress_ipsec_mb(const args_t *args)
  575 {
  576     MB_MGR *p_mgr = NULL;
  577     int features;
  578     uint8_t data[8192] ALIGNED(64);
  579     const size_t n_features = SIZEOF_ARRAY(init_mb);
  580     double t[n_features];
  581     size_t i;
  582     uint64_t count = 0;
  583     bool got_features = false;
  584 
  585     p_mgr = alloc_mb_mgr(0);
  586     if (!p_mgr) {
  587         pr_inf("%s: failed to setup Intel IPSEC MB library, skipping\n", args->name);
  588         return EXIT_NO_RESOURCE;
  589     }
  590     if (imb_get_version() < IMB_VERSION(0, 51, 0)) {
  591         pr_inf("%s: version %s of Intel IPSEC MB library is too low, skipping\n", 
  592             args->name, imb_get_version_str());
  593         free_mb_mgr(p_mgr);
  594         return EXIT_NOT_IMPLEMENTED;
  595     }
  596 
  597     features = stress_ipsec_mb_features(args, p_mgr);
  598 
  599     for (i = 0; i < n_features; i++) {
  600         t[i] = 0.0;
  601         if ((init_mb[i].features & features) == init_mb[i].features) {
  602             got_features = true;
  603             break;
  604         }
  605     }
  606     if (!got_features) {
  607         pr_inf("%s: not enough CPU features to support Intel IPSEC MB library, skipping\n", args->name);
  608         free_mb_mgr(p_mgr);
  609         return EXIT_NOT_IMPLEMENTED;
  610     }
  611 
  612     stress_rnd_fill(data, sizeof(data));
  613 
  614     do {
  615         for (i = 0; i < n_features; i++) {
  616             if ((init_mb[i].features & features) == init_mb[i].features) {
  617                 double t1, t2;
  618 
  619                 t1 = time_now();
  620                 init_mb[i].init_func(p_mgr);
  621                 stress_cmac(args, p_mgr, data, sizeof(data), 1);
  622                 stress_ctr(args, p_mgr, data, sizeof(data), 1);
  623                 stress_des(args, p_mgr, data, sizeof(data), 1);
  624                 stress_hmac_md5(args, p_mgr, data, sizeof(data), 1);
  625                 stress_hmac_sha1(args, p_mgr, data, sizeof(data), 1);
  626                 stress_hmac_sha512(args, p_mgr, data, sizeof(data), 1);
  627                 stress_sha(args, p_mgr, data, sizeof(data), 1);
  628                 t2 = time_now();
  629                 t[i] += (t2 - t1);
  630             }
  631         }
  632         count++;
  633         inc_counter(args);
  634     } while (keep_stressing());
  635 
  636     for (i = 0; i < n_features; i++) {
  637         if (((init_mb[i].features & features) == init_mb[i].features) && (t[i] > 0.0))
  638             pr_dbg("%s: %s %.3f bogo/ops per second\n",
  639                 args->name, init_mb[i].name,
  640                 (float)count / t[i]);
  641     }
  642 
  643     free_mb_mgr(p_mgr);
  644 
  645     return EXIT_SUCCESS;
  646 }
  647 
  648 stressor_info_t stress_ipsec_mb_info = {
  649     .stressor = stress_ipsec_mb,
  650     .supported = stress_ipsec_mb_supported,
  651     .class = CLASS_CPU
  652 };
  653 #else
  654 
  655 static int stress_ipsec_mb_supported(void)
  656 {
  657     pr_inf("ipsec_mb stressor will be skipped, CPU "
  658         "needs to be an x86-64 and a recent IPSEC MB library is required.\n");
  659     return -1;
  660 }
  661 
  662 stressor_info_t stress_ipsec_mb_info = {
  663     .stressor = stress_not_implemented,
  664     .supported = stress_ipsec_mb_supported,
  665     .class = CLASS_CPU
  666 };
  667 #endif