LCOV - code coverage report
Current view: top level - plugins/unittest - crypto_test.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 477 654 72.9 %
Date: 2023-07-05 22:20:52 Functions: 15 17 88.2 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2019 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : #include <vlib/vlib.h>
      16             : #include <vppinfra/time.h>
      17             : #include <vppinfra/cache.h>
      18             : #include <vppinfra/error.h>
      19             : #include <vnet/crypto/crypto.h>
      20             : #include <unittest/crypto/crypto.h>
      21             : 
      22             : crypto_test_main_t crypto_test_main;
      23             : 
      24             : static int
      25         260 : sort_registrations (void *a0, void *a1)
      26             : {
      27         260 :   unittest_crypto_test_registration_t **r0 = a0;
      28         260 :   unittest_crypto_test_registration_t **r1 = a1;
      29             : 
      30         260 :   return (strncmp (r0[0]->name, r1[0]->name, 256));
      31             : }
      32             : 
      33             : static void
      34           3 : print_results (vlib_main_t * vm, unittest_crypto_test_registration_t ** rv,
      35             :                vnet_crypto_op_t * ops, vnet_crypto_op_chunk_t * chunks,
      36             :                u32 n_ops, crypto_test_main_t * tm)
      37             : {
      38             :   int i;
      39             :   unittest_crypto_test_registration_t *r;
      40             :   vnet_crypto_op_chunk_t *chp;
      41           3 :   u8 *s = 0, *err = 0;
      42             :   vnet_crypto_op_t *op;
      43             : 
      44         101 :   vec_foreach (op, ops)
      45             :   {
      46          98 :     int fail = 0;
      47          98 :     r = rv[op->user_data];
      48          98 :     unittest_crypto_test_data_t *exp_pt = 0, *exp_ct = 0, exp_pt_data;
      49          98 :     unittest_crypto_test_data_t *exp_digest = 0, *exp_tag = 0;
      50          98 :     unittest_crypto_test_data_t *exp_pt_chunks = 0, *exp_ct_chunks = 0;
      51             : 
      52          98 :     switch (vnet_crypto_get_op_type (op->op))
      53             :       {
      54          12 :       case VNET_CRYPTO_OP_TYPE_AEAD_ENCRYPT:
      55          12 :         exp_tag = &r->tag;
      56             :         /* fall through */
      57          19 :       case VNET_CRYPTO_OP_TYPE_ENCRYPT:
      58          19 :         exp_ct = &r->ciphertext;
      59          19 :         exp_ct_chunks = r->ct_chunks;
      60          19 :         break;
      61          27 :       case VNET_CRYPTO_OP_TYPE_AEAD_DECRYPT:
      62             :       case VNET_CRYPTO_OP_TYPE_DECRYPT:
      63          27 :         if (r->plaintext_incremental)
      64             :           {
      65           8 :             exp_pt_data.length = r->plaintext_incremental;
      66           8 :             exp_pt_data.data = tm->inc_data;
      67           8 :             exp_pt = &exp_pt_data;
      68             :           }
      69             :         else
      70             :           {
      71          19 :             exp_pt = &r->plaintext;
      72          19 :             exp_pt_chunks = r->pt_chunks;
      73             :           }
      74          27 :         break;
      75          47 :       case VNET_CRYPTO_OP_TYPE_HMAC:
      76          47 :         exp_digest = &r->digest;
      77          47 :         break;
      78           5 :       case VNET_CRYPTO_OP_TYPE_HASH:
      79           5 :         exp_digest = &r->digest;
      80           5 :         break;
      81           0 :       default:
      82           0 :         ASSERT (0);
      83             :       }
      84             : 
      85          98 :     vec_reset_length (err);
      86             : 
      87          98 :     if (op->status != VNET_CRYPTO_OP_STATUS_COMPLETED)
      88           0 :       err = format (err, "%sengine error: %U", vec_len (err) ? ", " : "",
      89           0 :                     format_vnet_crypto_op_status, op->status);
      90             : 
      91          98 :     if (op->flags & VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS)
      92             :       {
      93           7 :         if (exp_ct_chunks)
      94             :           {
      95           2 :             chp = vec_elt_at_index (chunks, op->chunk_index);
      96           7 :             for (i = 0; i < op->n_chunks; i++)
      97             :               {
      98           5 :                 if (memcmp (chp->dst, exp_ct_chunks[i].data, chp->len))
      99           0 :                   err = format (err, "%sciphertext mismatch [chunk %d]",
     100           0 :                                 vec_len (err) ? ", " : "", i);
     101           5 :                 chp += 1;
     102             :               }
     103             :           }
     104             : 
     105           7 :         if (exp_pt_chunks)
     106             :           {
     107           2 :             chp = vec_elt_at_index (chunks, op->chunk_index);
     108           7 :             for (i = 0; i < op->n_chunks; i++)
     109             :               {
     110           5 :                 if (memcmp (chp->dst, exp_pt_chunks[i].data, chp->len))
     111           0 :                   err = format (err, "%splaintext mismatch [chunk %d]",
     112           0 :                                 vec_len (err) ? ", " : "", i);
     113           5 :                 chp += 1;
     114             :               }
     115             :           }
     116             :       }
     117             :     else
     118             :       {
     119          91 :         if (exp_ct && memcmp (op->dst, exp_ct->data, exp_ct->length) != 0)
     120           0 :           err = format (err, "%sciphertext mismatch",
     121           0 :                         vec_len (err) ? ", " : "");
     122             : 
     123          91 :         if (exp_pt && memcmp (op->dst, exp_pt->data, exp_pt->length) != 0)
     124           0 :           err = format (err, "%splaintext mismatch",
     125           0 :                         vec_len (err) ? ", " : "");
     126             :       }
     127             : 
     128          98 :     if (exp_tag && memcmp (op->tag, exp_tag->data, exp_tag->length) != 0)
     129           0 :       err = format (err, "%stag mismatch", vec_len (err) ? ", " : "");
     130             : 
     131          98 :     if (exp_digest &&
     132          52 :         memcmp (op->digest, exp_digest->data, exp_digest->length) != 0)
     133           0 :       err = format (err, "%sdigest mismatch", vec_len (err) ? ", " : "");
     134             : 
     135          98 :     vec_reset_length (s);
     136         196 :     s = format (s, "%s (%U)", r->name, format_vnet_crypto_op, op->op,
     137          98 :                 r->is_chained);
     138             : 
     139          98 :     if (vec_len (err))
     140           0 :       fail = 1;
     141             : 
     142          98 :     vlib_cli_output (vm, "%-60v%s%v", s, vec_len (err) ? "FAIL: " : "OK",
     143             :                      err);
     144          98 :     if (tm->verbose)
     145             :       {
     146           0 :         if (tm->verbose == 2)
     147           0 :           fail = 1;
     148             : 
     149           0 :         if (exp_ct && fail)
     150           0 :           vlib_cli_output (vm, "Expected ciphertext:\n%U"
     151             :                            "\nCalculated ciphertext:\n%U",
     152             :                            format_hexdump, exp_ct->data, exp_ct->length,
     153             :                            format_hexdump, op->dst, exp_ct->length);
     154           0 :         if (exp_pt && fail)
     155           0 :           vlib_cli_output (vm, "Expected plaintext:\n%U"
     156             :                            "\nCalculated plaintext:\n%U",
     157             :                            format_hexdump, exp_pt->data, exp_pt->length,
     158             :                            format_hexdump, op->dst, exp_pt->length);
     159           0 :         if (r->tag.length && fail)
     160           0 :           vlib_cli_output (vm, "Expected tag:\n%U"
     161             :                            "\nCalculated tag:\n%U",
     162             :                            format_hexdump, r->tag.data, r->tag.length,
     163           0 :                            format_hexdump, op->tag, op->tag_len);
     164           0 :         if (exp_digest && fail)
     165           0 :           vlib_cli_output (vm, "Expected digest:\n%U"
     166             :                            "\nCalculated Digest:\n%U",
     167             :                            format_hexdump, exp_digest->data,
     168             :                            exp_digest->length, format_hexdump, op->digest,
     169           0 :                            op->digest_len);
     170             :       }
     171             :   }
     172           3 :   vec_free (err);
     173           3 :   vec_free (s);
     174           3 : }
     175             : 
     176             : static void
     177           1 : validate_data (u8 ** data, u32 len)
     178             : {
     179             :   u32 i, diff, old_len;
     180           1 :   if (vec_len (data[0]) >= len)
     181           0 :     return;
     182             : 
     183           1 :   old_len = vec_len (data[0]);
     184           1 :   diff = len - vec_len (data[0]);
     185           1 :   vec_validate (data[0], old_len + diff - 1);
     186        2049 :   for (i = old_len; i < len; i++)
     187        2048 :     data[0][i] = (u8) i;
     188             : }
     189             : 
     190             : static void
     191           1 : generate_digest (vlib_main_t * vm,
     192             :                  unittest_crypto_test_registration_t * r,
     193             :                  vnet_crypto_op_id_t id)
     194             : {
     195           1 :   crypto_test_main_t *cm = &crypto_test_main;
     196             :   vnet_crypto_op_t op[1];
     197           1 :   vnet_crypto_op_init (op, id);
     198           1 :   vec_validate (r->digest.data, r->digest.length - 1);
     199           1 :   op->src = cm->inc_data;
     200           1 :   op->len = r->plaintext_incremental;
     201           1 :   op->digest = r->digest.data;
     202           1 :   op->digest_len = r->digest.length;
     203           2 :   op->key_index = vnet_crypto_key_add (vm, r->alg,
     204           1 :                                        cm->inc_data, r->key.length);
     205             : 
     206             :   /* at this point openssl is set for each algo */
     207           1 :   vnet_crypto_process_ops (vm, op, 1);
     208           1 : }
     209             : 
     210             : static int
     211           1 : restore_engines (u32 * engs)
     212             : {
     213           1 :   vnet_crypto_main_t *cm = &crypto_main;
     214             :   u32 i;
     215             :   vnet_crypto_engine_t *ce;
     216             : 
     217          36 :   for (i = 1; i < VNET_CRYPTO_N_OP_IDS; i++)
     218             :     {
     219          35 :       vnet_crypto_op_data_t *od = &cm->opt_data[i];
     220             : 
     221          35 :       if (engs[i] != ~0)
     222             :         {
     223          35 :           ce = vec_elt_at_index (cm->engines, engs[i]);
     224          35 :           od->active_engine_index_simple = engs[i];
     225          35 :           cm->ops_handlers[i] = ce->ops_handlers[i];
     226             :         }
     227             :     }
     228             : 
     229           1 :   return 0;
     230             : }
     231             : 
     232             : static int
     233           1 : save_current_engines (u32 * engs)
     234             : {
     235           1 :   vnet_crypto_main_t *cm = &crypto_main;
     236             :   uword *p;
     237             :   u32 i;
     238             :   vnet_crypto_engine_t *ce;
     239             : 
     240           1 :   p = hash_get_mem (cm->engine_index_by_name, "openssl");
     241           1 :   if (!p)
     242           0 :     return -1;
     243             : 
     244           1 :   ce = vec_elt_at_index (cm->engines, p[0]);
     245             : 
     246             :   /* set openssl for all crypto algs to generate expected data */
     247          36 :   for (i = 1; i < VNET_CRYPTO_N_OP_IDS; i++)
     248             :     {
     249          35 :       vnet_crypto_op_data_t *od = &cm->opt_data[i];
     250          35 :       if (od->active_engine_index_simple != ~0)
     251             :         {
     252             :           /* save engine index */
     253          35 :           engs[i] = od->active_engine_index_simple;
     254          35 :           od->active_engine_index_simple = ce - cm->engines;
     255          35 :           cm->ops_handlers[i] = ce->ops_handlers[i];
     256             :         }
     257             :     }
     258             : 
     259           1 :   return 0;
     260             : }
     261             : 
     262             : static clib_error_t *
     263           1 : test_crypto_incremental (vlib_main_t * vm, crypto_test_main_t * tm,
     264             :                          unittest_crypto_test_registration_t ** rv, u32 n_ops,
     265             :                          u32 computed_data_total_len)
     266             : {
     267           1 :   vnet_crypto_main_t *cm = &crypto_main;
     268             :   vnet_crypto_alg_data_t *ad;
     269           1 :   vnet_crypto_key_index_t *key_indices = 0;
     270             :   u32 i;
     271             :   unittest_crypto_test_registration_t *r;
     272           1 :   vnet_crypto_op_t *ops = 0, *op;
     273           1 :   u8 *encrypted_data = 0, *decrypted_data = 0, *s = 0, *err = 0;
     274             : 
     275           1 :   if (n_ops == 0)
     276           0 :     return 0;
     277             : 
     278           1 :   vec_validate_aligned (encrypted_data, computed_data_total_len - 1,
     279             :                         CLIB_CACHE_LINE_BYTES);
     280           1 :   vec_validate_aligned (decrypted_data, computed_data_total_len - 1,
     281             :                         CLIB_CACHE_LINE_BYTES);
     282           1 :   vec_validate_aligned (ops, n_ops - 1, CLIB_CACHE_LINE_BYTES);
     283           1 :   computed_data_total_len = 0;
     284             : 
     285           1 :   op = ops;
     286             :   /* first stage: encrypt only */
     287             : 
     288          10 :   vec_foreach_index (i, rv)
     289             :   {
     290           9 :     r = rv[i];
     291             :     int t;
     292           9 :     ad = vec_elt_at_index (cm->algs, r->alg);
     293          63 :     for (t = 0; t < VNET_CRYPTO_OP_N_TYPES; t++)
     294             :       {
     295          54 :         vnet_crypto_op_id_t id = ad->op_by_type[t];
     296             : 
     297          54 :         if (id == 0)
     298          37 :           continue;
     299             : 
     300          17 :         switch (t)
     301             :           {
     302           2 :           case VNET_CRYPTO_OP_TYPE_ENCRYPT:
     303           2 :             vnet_crypto_op_init (op, id);
     304           2 :             op->iv = tm->inc_data;
     305           4 :             op->key_index = vnet_crypto_key_add (vm, r->alg,
     306           2 :                                                  tm->inc_data, r->key.length);
     307           2 :             vec_add1 (key_indices, op->key_index);
     308           2 :             op->len = r->plaintext_incremental;
     309           2 :             op->src = tm->inc_data;
     310           2 :             op->dst = encrypted_data + computed_data_total_len;
     311           2 :             computed_data_total_len += r->plaintext_incremental;
     312           2 :             op->user_data = i;
     313           2 :             op++;
     314           2 :             break;
     315           6 :           case VNET_CRYPTO_OP_TYPE_AEAD_ENCRYPT:
     316           6 :             vnet_crypto_op_init (op, id);
     317           6 :             op->iv = tm->inc_data;
     318          12 :             op->key_index = vnet_crypto_key_add (vm, r->alg,
     319           6 :                                                  tm->inc_data, r->key.length);
     320           6 :             vec_add1 (key_indices, op->key_index);
     321           6 :             op->aad = tm->inc_data;
     322           6 :             op->aad_len = r->aad.length;
     323           6 :             op->len = r->plaintext_incremental;
     324           6 :             op->dst = encrypted_data + computed_data_total_len;
     325           6 :             computed_data_total_len += r->plaintext_incremental;
     326           6 :             op->src = tm->inc_data;
     327           6 :             op->tag = encrypted_data + computed_data_total_len;
     328           6 :             computed_data_total_len += r->tag.length;
     329           6 :             op->tag_len = r->tag.length;
     330           6 :             op->user_data = i;
     331           6 :             op++;
     332           6 :             break;
     333           1 :           case VNET_CRYPTO_OP_TYPE_HMAC:
     334             :             /* compute hmac in the next stage */
     335           1 :             op->op = VNET_CRYPTO_OP_NONE;
     336           1 :             computed_data_total_len += r->digest.length;
     337           1 :             op->user_data = i;
     338           1 :             op++;
     339           1 :             break;
     340           8 :           default:
     341           8 :             break;
     342             :           };
     343             :       }
     344             :   }
     345             : 
     346           1 :   vnet_crypto_process_ops (vm, ops, n_ops);
     347           1 :   computed_data_total_len = 0;
     348             : 
     349             :   /* second stage: hash/decrypt previously encrypted data */
     350           1 :   op = ops;
     351             : 
     352          10 :   vec_foreach_index (i, rv)
     353             :   {
     354           9 :     r = rv[i];
     355             :     int t;
     356           9 :     ad = vec_elt_at_index (cm->algs, r->alg);
     357          63 :     for (t = 0; t < VNET_CRYPTO_OP_N_TYPES; t++)
     358             :       {
     359          54 :         vnet_crypto_op_id_t id = ad->op_by_type[t];
     360             : 
     361          54 :         if (id == 0)
     362          37 :           continue;
     363             : 
     364          17 :         switch (t)
     365             :           {
     366           2 :           case VNET_CRYPTO_OP_TYPE_DECRYPT:
     367           2 :             vnet_crypto_op_init (op, id);
     368           2 :             op->iv = tm->inc_data;
     369           4 :             op->key_index = vnet_crypto_key_add (vm, r->alg,
     370           2 :                                                  tm->inc_data, r->key.length);
     371           2 :             vec_add1 (key_indices, op->key_index);
     372           2 :             op->len = r->plaintext_incremental;
     373           2 :             op->src = encrypted_data + computed_data_total_len;
     374           2 :             op->dst = decrypted_data + computed_data_total_len;
     375           2 :             computed_data_total_len += r->plaintext_incremental;
     376           2 :             op->user_data = i;
     377           2 :             op++;
     378           2 :             break;
     379           6 :           case VNET_CRYPTO_OP_TYPE_AEAD_DECRYPT:
     380           6 :             vnet_crypto_op_init (op, id);
     381           6 :             op->iv = tm->inc_data;
     382          12 :             op->key_index = vnet_crypto_key_add (vm, r->alg,
     383           6 :                                                  tm->inc_data, r->key.length);
     384           6 :             vec_add1 (key_indices, op->key_index);
     385           6 :             op->aad = tm->inc_data;
     386           6 :             op->aad_len = r->aad.length;
     387           6 :             op->len = r->plaintext_incremental;
     388           6 :             op->dst = decrypted_data + computed_data_total_len;
     389           6 :             op->src = encrypted_data + computed_data_total_len;
     390           6 :             computed_data_total_len += r->plaintext_incremental;
     391             : 
     392           6 :             op->tag = encrypted_data + computed_data_total_len;
     393           6 :             computed_data_total_len += r->tag.length;
     394           6 :             op->tag_len = r->tag.length;
     395           6 :             op->user_data = i;
     396           6 :             op++;
     397           6 :             break;
     398           1 :           case VNET_CRYPTO_OP_TYPE_HMAC:
     399           1 :             vnet_crypto_op_init (op, id);
     400           2 :             op->key_index = vnet_crypto_key_add (vm, r->alg,
     401           1 :                                                  tm->inc_data, r->key.length);
     402           1 :             vec_add1 (key_indices, op->key_index);
     403           1 :             op->src = tm->inc_data;
     404           1 :             op->len = r->plaintext_incremental;
     405           1 :             op->digest_len = r->digest.length;
     406           1 :             op->digest = encrypted_data + computed_data_total_len;
     407           1 :             computed_data_total_len += r->digest.length;
     408           1 :             op->user_data = i;
     409           1 :             op++;
     410           1 :             break;
     411           8 :           default:
     412           8 :             break;
     413             :           };
     414             : 
     415             :       }
     416             :   }
     417             : 
     418           1 :   vnet_crypto_process_ops (vm, ops, n_ops);
     419           1 :   print_results (vm, rv, ops, 0, n_ops, tm);
     420             : 
     421          18 :   vec_foreach_index (i, key_indices) vnet_crypto_key_del (vm, key_indices[i]);
     422           1 :   vec_free (tm->inc_data);
     423           1 :   vec_free (ops);
     424           1 :   vec_free (encrypted_data);
     425           1 :   vec_free (decrypted_data);
     426           1 :   vec_free (err);
     427           1 :   vec_free (s);
     428           1 :   return 0;
     429             : }
     430             : 
     431             : static clib_error_t *
     432           1 : test_crypto_static (vlib_main_t * vm, crypto_test_main_t * tm,
     433             :                     unittest_crypto_test_registration_t ** rv, u32 n_ops,
     434             :                     u32 n_chained_ops, u32 computed_data_total_len)
     435             : {
     436             :   unittest_crypto_test_data_t *pt, *ct;
     437           1 :   vnet_crypto_op_chunk_t *chunks = 0, ch;
     438             :   unittest_crypto_test_registration_t *r;
     439           1 :   vnet_crypto_op_t *ops = 0, *op, *chained_ops = 0;
     440           1 :   vnet_crypto_op_t *current_chained_op = 0, *current_op = 0;
     441           1 :   vnet_crypto_main_t *cm = &crypto_main;
     442             :   vnet_crypto_alg_data_t *ad;
     443           1 :   vnet_crypto_key_index_t *key_indices = 0;
     444           1 :   u8 *computed_data = 0;
     445             :   u32 i;
     446             : 
     447           1 :   vec_sort_with_function (rv, sort_registrations);
     448             : 
     449           1 :   vec_validate_aligned (computed_data, computed_data_total_len - 1,
     450             :                         CLIB_CACHE_LINE_BYTES);
     451           1 :   vec_validate_aligned (ops, n_ops - 1, CLIB_CACHE_LINE_BYTES);
     452           1 :   vec_validate_aligned (chained_ops, n_chained_ops - 1,
     453             :                         CLIB_CACHE_LINE_BYTES);
     454           1 :   computed_data_total_len = 0;
     455             : 
     456           1 :   current_op = ops;
     457           1 :   current_chained_op = chained_ops;
     458             :   /* *INDENT-OFF* */
     459          71 :   vec_foreach_index (i, rv)
     460             :     {
     461          70 :       r = rv[i];
     462             :       int t;
     463          70 :       ad = vec_elt_at_index (cm->algs, r->alg);
     464         490 :       for (t = 0; t < VNET_CRYPTO_OP_N_TYPES; t++)
     465             :         {
     466         420 :           vnet_crypto_op_id_t id = ad->op_by_type[t];
     467             : 
     468         420 :           if (id == 0)
     469         331 :             continue;
     470             : 
     471          89 :           if (r->is_chained)
     472             :           {
     473           7 :             op = current_chained_op;
     474           7 :             current_chained_op += 1;
     475             :           }
     476             :           else
     477             :           {
     478          82 :             op = current_op;
     479          82 :             current_op += 1;
     480             :           }
     481             : 
     482          89 :           vnet_crypto_op_init (op, id);
     483             : 
     484          89 :           switch (t)
     485             :             {
     486          14 :             case VNET_CRYPTO_OP_TYPE_ENCRYPT:
     487             :             case VNET_CRYPTO_OP_TYPE_DECRYPT:
     488          14 :               op->iv = r->iv.data;
     489          28 :               op->key_index = vnet_crypto_key_add (vm, r->alg,
     490             :                                                    r->key.data,
     491          14 :                                                    r->key.length);
     492          14 :               vec_add1 (key_indices, op->key_index);
     493             : 
     494          14 :               if (r->is_chained)
     495             :               {
     496           2 :               pt = r->pt_chunks;
     497           2 :               ct = r->ct_chunks;
     498           2 :               op->flags |= VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS;
     499           2 :               op->chunk_index = vec_len (chunks);
     500           6 :               while (pt->data)
     501             :                 {
     502           4 :                   ch.src = t == VNET_CRYPTO_OP_TYPE_ENCRYPT ?
     503           4 :                     pt->data : ct->data;
     504           4 :                   ch.len = pt->length;
     505           4 :                   ch.dst = computed_data + computed_data_total_len;
     506           4 :                   computed_data_total_len += pt->length;
     507           4 :                   vec_add1 (chunks, ch);
     508           4 :                   op->n_chunks++;
     509           4 :                   pt++;
     510           4 :                   ct++;
     511             :                 }
     512             :               }
     513             :               else
     514             :               {
     515          12 :               op->len = r->plaintext.length;
     516          12 :               op->src = t == VNET_CRYPTO_OP_TYPE_ENCRYPT ?
     517          12 :                 r->plaintext.data : r->ciphertext.data;
     518          12 :               op->dst = computed_data + computed_data_total_len;
     519          12 :               computed_data_total_len += r->ciphertext.length;
     520             :               }
     521          14 :               break;
     522          24 :             case VNET_CRYPTO_OP_TYPE_AEAD_ENCRYPT:
     523             :             case VNET_CRYPTO_OP_TYPE_AEAD_DECRYPT:
     524          24 :               if (r->is_chained)
     525             :               {
     526           2 :               op->iv = r->iv.data;
     527           4 :               op->key_index = vnet_crypto_key_add (vm, r->alg,
     528             :                                                    r->key.data,
     529           2 :                                                    r->key.length);
     530           2 :               vec_add1 (key_indices, op->key_index);
     531           2 :               op->aad = r->aad.data;
     532           2 :               op->aad_len = r->aad.length;
     533           2 :               if (t == VNET_CRYPTO_OP_TYPE_AEAD_ENCRYPT)
     534             :                 {
     535           1 :                   pt = r->pt_chunks;
     536           1 :                   op->flags |= VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS;
     537           1 :                   op->chunk_index = vec_len (chunks);
     538           4 :                   while (pt->data)
     539             :                     {
     540           3 :                       clib_memset (&ch, 0, sizeof (ch));
     541           3 :                       ch.src = pt->data;
     542           3 :                       ch.len = pt->length;
     543           3 :                       ch.dst = computed_data + computed_data_total_len;
     544           3 :                       computed_data_total_len += pt->length;
     545           3 :                       vec_add1 (chunks, ch);
     546           3 :                       op->n_chunks++;
     547           3 :                       pt++;
     548             :                     }
     549           1 :                   op->tag = computed_data + computed_data_total_len;
     550           1 :                   computed_data_total_len += r->tag.length;
     551             :                 }
     552             :               else
     553             :                 {
     554           1 :                   ct = r->ct_chunks;
     555           1 :                   op->flags |= VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS;
     556           1 :                   op->chunk_index = vec_len (chunks);
     557           4 :                   while (ct->data)
     558             :                     {
     559           3 :                       clib_memset (&ch, 0, sizeof (ch));
     560           3 :                       ch.src = ct->data;
     561           3 :                       ch.len = ct->length;
     562           3 :                       ch.dst = computed_data + computed_data_total_len;
     563           3 :                       computed_data_total_len += ct->length;
     564           3 :                       vec_add1 (chunks, ch);
     565           3 :                       op->n_chunks++;
     566           3 :                       ct++;
     567             :                     }
     568           1 :                   op->tag = r->tag.data;
     569             :                 }
     570           2 :               op->tag_len = r->tag.length;
     571             :               }
     572             :               else
     573             :               {
     574          22 :               op->iv = r->iv.data;
     575          44 :               op->key_index = vnet_crypto_key_add (vm, r->alg,
     576             :                                                    r->key.data,
     577          22 :                                                    r->key.length);
     578          22 :               vec_add1 (key_indices, op->key_index);
     579          22 :               op->aad = r->aad.data;
     580          22 :               op->aad_len = r->aad.length;
     581          22 :               op->len = r->plaintext.length;
     582          22 :               op->dst = computed_data + computed_data_total_len;
     583          22 :               computed_data_total_len += r->ciphertext.length;
     584             : 
     585          22 :               if (t == VNET_CRYPTO_OP_TYPE_AEAD_ENCRYPT)
     586             :                 {
     587          11 :                   op->src = r->plaintext.data;
     588          11 :                   op->tag = computed_data + computed_data_total_len;
     589          11 :                   computed_data_total_len += r->tag.length;
     590             :                 }
     591             :               else
     592             :                 {
     593          11 :                   op->tag = r->tag.data;
     594          11 :                   op->src = r->ciphertext.data;
     595             :                 }
     596          22 :               op->tag_len = r->tag.length;
     597             :               }
     598          24 :               break;
     599          46 :             case VNET_CRYPTO_OP_TYPE_HMAC:
     600          46 :               if (r->is_chained)
     601             :               {
     602           6 :               op->key_index = vnet_crypto_key_add (vm, r->alg,
     603             :                                                    r->key.data,
     604           3 :                                                    r->key.length);
     605           3 :               vec_add1 (key_indices, op->key_index);
     606           3 :               op->digest_len = r->digest.length;
     607           3 :               op->digest = computed_data + computed_data_total_len;
     608           3 :               computed_data_total_len += r->digest.length;
     609           3 :               pt = r->pt_chunks;
     610           3 :               op->flags |= VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS;
     611           3 :               op->chunk_index = vec_len (chunks);
     612          11 :               while (pt->data)
     613             :                 {
     614           8 :                   clib_memset (&ch, 0, sizeof (ch));
     615           8 :                   ch.src = pt->data;
     616           8 :                   ch.len = pt->length;
     617           8 :                   vec_add1 (chunks, ch);
     618           8 :                   op->n_chunks++;
     619           8 :                   pt++;
     620             :                 }
     621             :               }
     622             :               else
     623             :               {
     624          86 :               op->key_index = vnet_crypto_key_add (vm, r->alg,
     625             :                                                    r->key.data,
     626          43 :                                                    r->key.length);
     627          43 :               vec_add1 (key_indices, op->key_index);
     628          43 :               op->digest_len = r->digest.length;
     629          43 :               op->digest = computed_data + computed_data_total_len;
     630          43 :               computed_data_total_len += r->digest.length;
     631          43 :               op->src = r->plaintext.data;
     632          43 :               op->len = r->plaintext.length;
     633             :               }
     634          46 :               break;
     635           5 :             case VNET_CRYPTO_OP_TYPE_HASH:
     636           5 :               op->digest = computed_data + computed_data_total_len;
     637           5 :               computed_data_total_len += r->digest.length;
     638           5 :               op->src = r->plaintext.data;
     639           5 :               op->len = r->plaintext.length;
     640           5 :               break;
     641           0 :             default:
     642           0 :               break;
     643             :             };
     644             : 
     645          89 :           op->user_data = i;
     646             :         }
     647             :     }
     648             :   /* *INDENT-ON* */
     649             : 
     650           1 :   vnet_crypto_process_ops (vm, ops, vec_len (ops));
     651           1 :   vnet_crypto_process_chained_ops (vm, chained_ops, chunks,
     652           1 :                                    vec_len (chained_ops));
     653             : 
     654           1 :   print_results (vm, rv, ops, chunks, vec_len (ops), tm);
     655           1 :   print_results (vm, rv, chained_ops, chunks, vec_len (chained_ops), tm);
     656             : 
     657          85 :   vec_foreach_index (i, key_indices) vnet_crypto_key_del (vm, key_indices[i]);
     658             : 
     659           1 :   vec_free (computed_data);
     660           1 :   vec_free (ops);
     661           1 :   vec_free (chained_ops);
     662           1 :   vec_free (chunks);
     663           1 :   return 0;
     664             : }
     665             : 
     666             : static u32
     667           0 : test_crypto_get_key_sz (vnet_crypto_alg_t alg)
     668             : {
     669           0 :   switch (alg)
     670             :     {
     671             : #define _(n, s, l) \
     672             :   case VNET_CRYPTO_ALG_##n: \
     673             :     return l;
     674             :   /* *INDENT-OFF* */
     675           0 :   foreach_crypto_cipher_alg
     676           0 :   foreach_crypto_aead_alg
     677             :   /* *INDENT-ON* */
     678             : #undef _
     679           0 :     case VNET_CRYPTO_ALG_HMAC_MD5:
     680             :     case VNET_CRYPTO_ALG_HMAC_SHA1:
     681           0 :       return 20;
     682           0 :     case VNET_CRYPTO_ALG_HMAC_SHA224:
     683           0 :       return 28;
     684           0 :     case VNET_CRYPTO_ALG_HMAC_SHA256:
     685           0 :       return 32;
     686           0 :     case VNET_CRYPTO_ALG_HMAC_SHA384:
     687           0 :       return 48;
     688           0 :     case VNET_CRYPTO_ALG_HMAC_SHA512:
     689           0 :       return 64;
     690           0 :     default:
     691           0 :       return 0;
     692             :     }
     693             :   return 0;
     694             : }
     695             : 
     696             : static clib_error_t *
     697           1 : test_crypto (vlib_main_t * vm, crypto_test_main_t * tm)
     698             : {
     699           1 :   clib_error_t *err = 0;
     700           1 :   vnet_crypto_main_t *cm = &crypto_main;
     701           1 :   unittest_crypto_test_registration_t *r = tm->test_registrations;
     702           1 :   unittest_crypto_test_registration_t **static_tests = 0, **inc_tests = 0;
     703           1 :   u32 i, j, n_ops_static = 0, n_ops_incr = 0, n_chained_ops = 0;
     704             :   vnet_crypto_alg_data_t *ad;
     705           1 :   u32 computed_data_total_len = 0;
     706           1 :   u32 computed_data_total_incr_len = 0;
     707           1 :   u32 saved_engs[VNET_CRYPTO_N_OP_IDS] = { ~0, };
     708             :   unittest_crypto_test_data_t *ct;
     709             : 
     710             :   /* pre-allocate plaintext data with reasonable length */
     711           1 :   validate_data (&tm->inc_data, 2048);
     712             : 
     713           1 :   int rc = save_current_engines (saved_engs);
     714           1 :   if (rc)
     715           0 :     return clib_error_return (0, "failed to set default crypto engine!");
     716             : 
     717             :   /* construct registration vector */
     718          80 :   while (r)
     719             :     {
     720          79 :       if (r->plaintext_incremental)
     721           9 :         vec_add1 (inc_tests, r);
     722             :       else
     723          70 :         vec_add1 (static_tests, r);
     724             : 
     725          79 :       ad = vec_elt_at_index (cm->algs, r->alg);
     726             : 
     727         553 :       for (i = 0; i < VNET_CRYPTO_OP_N_TYPES; i++)
     728             :         {
     729         474 :           vnet_crypto_op_id_t id = ad->op_by_type[i];
     730             : 
     731         474 :           if (id == 0)
     732         368 :             continue;
     733             : 
     734         106 :           switch (i)
     735             :             {
     736           9 :             case VNET_CRYPTO_OP_TYPE_ENCRYPT:
     737           9 :               if (r->plaintext_incremental)
     738             :                 {
     739           2 :                   computed_data_total_incr_len += r->plaintext_incremental;
     740           2 :                   n_ops_incr += 1;
     741             :                 }
     742             :               /* fall though */
     743             :             case VNET_CRYPTO_OP_TYPE_DECRYPT:
     744             :             case VNET_CRYPTO_OP_TYPE_AEAD_DECRYPT:
     745          36 :               if (r->is_chained)
     746             :                 {
     747           3 :                   ct = r->ct_chunks;
     748           3 :                   j = 0;
     749          10 :                   while (ct->data)
     750             :                     {
     751           7 :                       if (j > CRYPTO_TEST_MAX_OP_CHUNKS)
     752           0 :                         return clib_error_return (0,
     753             :                                                   "test case '%s' exceeds extra data!",
     754             :                                                   r->name);
     755           7 :                       computed_data_total_len += ct->length;
     756           7 :                       ct++;
     757           7 :                       j++;
     758             :                     }
     759           3 :                   n_chained_ops += 1;
     760             :                 }
     761          33 :               else if (!r->plaintext_incremental)
     762             :                 {
     763          23 :                   computed_data_total_len += r->ciphertext.length;
     764          23 :                   n_ops_static += 1;
     765             :                 }
     766          36 :               break;
     767          18 :             case VNET_CRYPTO_OP_TYPE_AEAD_ENCRYPT:
     768          18 :               if (r->plaintext_incremental)
     769             :                 {
     770           6 :                   computed_data_total_incr_len += r->plaintext_incremental;
     771           6 :                   computed_data_total_incr_len += r->tag.length;
     772           6 :                   n_ops_incr += 1;
     773             :                 }
     774             :               else
     775             :                 {
     776          12 :                   computed_data_total_len += r->ciphertext.length;
     777          12 :                   computed_data_total_len += r->tag.length;
     778          12 :                   if (r->is_chained)
     779             :                     {
     780           1 :                       ct = r->ct_chunks;
     781           1 :                       j = 0;
     782           4 :                       while (ct->data)
     783             :                         {
     784           3 :                           if (j > CRYPTO_TEST_MAX_OP_CHUNKS)
     785           0 :                             return clib_error_return (0,
     786             :                                                       "test case '%s' exceeds extra data!",
     787             :                                                       r->name);
     788           3 :                           computed_data_total_len += ct->length;
     789           3 :                           ct++;
     790           3 :                           j++;
     791             :                         }
     792           1 :                       n_chained_ops += 1;
     793             :                     }
     794             :                   else
     795          11 :                     n_ops_static += 1;
     796             :                 }
     797          18 :               break;
     798          47 :             case VNET_CRYPTO_OP_TYPE_HMAC:
     799          47 :               if (r->plaintext_incremental)
     800             :                 {
     801           1 :                   computed_data_total_incr_len += r->digest.length;
     802           1 :                   n_ops_incr += 1;
     803           1 :                   generate_digest (vm, r, id);
     804             :                 }
     805             :               else
     806             :                 {
     807          46 :                   computed_data_total_len += r->digest.length;
     808          46 :                   if (r->is_chained)
     809           3 :                     n_chained_ops += 1;
     810             :                   else
     811          43 :                     n_ops_static += 1;
     812             :                 }
     813          47 :               break;
     814           5 :             case VNET_CRYPTO_OP_TYPE_HASH:
     815           5 :               computed_data_total_len += r->digest.length;
     816           5 :               n_ops_static += 1;
     817           5 :               break;
     818           0 :             default:
     819           0 :               break;
     820             :             };
     821             :         }
     822             : 
     823             :       /* next: */
     824          79 :       r = r->next;
     825             :     }
     826           1 :   restore_engines (saved_engs);
     827             : 
     828           1 :   err = test_crypto_static (vm, tm, static_tests, n_ops_static, n_chained_ops,
     829             :                             computed_data_total_len);
     830           1 :   if (err)
     831           0 :     goto done;
     832             : 
     833           1 :   err = test_crypto_incremental (vm, tm, inc_tests, n_ops_incr,
     834             :                                  computed_data_total_incr_len);
     835             : 
     836           1 :   r = tm->test_registrations;
     837          80 :   while (r)
     838             :     {
     839          79 :       if (r->plaintext_incremental)
     840           9 :         vec_free (r->digest.data);
     841          79 :       r = r->next;
     842             :     }
     843             : 
     844           1 : done:
     845           1 :   vec_free (inc_tests);
     846           1 :   vec_free (static_tests);
     847           1 :   return err;
     848             : }
     849             : 
     850             : static clib_error_t *
     851           0 : test_crypto_perf (vlib_main_t * vm, crypto_test_main_t * tm)
     852             : {
     853           0 :   vnet_crypto_main_t *cm = &crypto_main;
     854           0 :   clib_error_t *err = 0;
     855           0 :   u32 n_buffers, n_alloc = 0, warmup_rounds, rounds;
     856           0 :   u32 *buffer_indices = 0;
     857           0 :   vnet_crypto_op_t *ops1 = 0, *ops2 = 0, *op1, *op2;
     858           0 :   vnet_crypto_alg_data_t *ad = vec_elt_at_index (cm->algs, tm->alg);
     859           0 :   vnet_crypto_key_index_t key_index = ~0;
     860             :   u8 key[64];
     861           0 :   int buffer_size = vlib_buffer_get_default_data_size (vm);
     862           0 :   u64 seed = clib_cpu_time_now ();
     863           0 :   u64 t0[5], t1[5], t2[5], n_bytes = 0;
     864             :   int i, j;
     865             : 
     866           0 :   if (tm->buffer_size > buffer_size)
     867           0 :     return clib_error_return (0, "buffer size must be <= %u", buffer_size);
     868             : 
     869           0 :   rounds = tm->rounds ? tm->rounds : 100;
     870           0 :   n_buffers = tm->n_buffers ? tm->n_buffers : 256;
     871           0 :   buffer_size = tm->buffer_size ? tm->buffer_size : 2048;
     872           0 :   warmup_rounds = tm->warmup_rounds ? tm->warmup_rounds : 100;
     873             : 
     874           0 :   if (buffer_size > vlib_buffer_get_default_data_size (vm))
     875           0 :     return clib_error_return (0, "buffer size too big");
     876             : 
     877           0 :   vec_validate_aligned (buffer_indices, n_buffers - 1, CLIB_CACHE_LINE_BYTES);
     878           0 :   vec_validate_aligned (ops1, n_buffers - 1, CLIB_CACHE_LINE_BYTES);
     879           0 :   vec_validate_aligned (ops2, n_buffers - 1, CLIB_CACHE_LINE_BYTES);
     880             : 
     881           0 :   n_alloc = vlib_buffer_alloc (vm, buffer_indices, n_buffers);
     882           0 :   if (n_alloc != n_buffers)
     883             :     {
     884           0 :       if (n_alloc)
     885           0 :         vlib_buffer_free (vm, buffer_indices, n_alloc);
     886           0 :       err = clib_error_return (0, "buffer alloc failure");
     887           0 :       goto done;
     888             :     }
     889             : 
     890           0 :   vlib_cli_output (vm, "%U: n_buffers %u buffer-size %u rounds %u "
     891             :                    "warmup-rounds %u",
     892           0 :                    format_vnet_crypto_alg, tm->alg, n_buffers, buffer_size,
     893             :                    rounds, warmup_rounds);
     894           0 :   vlib_cli_output (vm, "   cpu-freq %.2f GHz",
     895           0 :                    (f64) vm->clib_time.clocks_per_second * 1e-9);
     896             : 
     897           0 :   vnet_crypto_op_type_t ot = 0;
     898             : 
     899           0 :   for (i = 0; i < sizeof (key); i++)
     900           0 :     key[i] = i;
     901             : 
     902           0 :   key_index = vnet_crypto_key_add (vm, tm->alg, key,
     903           0 :                                    test_crypto_get_key_sz (tm->alg));
     904             : 
     905           0 :   for (i = 0; i < VNET_CRYPTO_OP_N_TYPES; i++)
     906             :     {
     907           0 :       vnet_crypto_op_id_t id = ad->op_by_type[i];
     908           0 :       if (id == 0)
     909           0 :         continue;
     910           0 :       ot = i;
     911           0 :       break;
     912             :     }
     913             : 
     914           0 :   for (i = 0; i < n_buffers; i++)
     915             :     {
     916           0 :       vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
     917           0 :       op1 = ops1 + i;
     918           0 :       op2 = ops2 + i;
     919             : 
     920           0 :       switch (ot)
     921             :         {
     922           0 :         case VNET_CRYPTO_OP_TYPE_ENCRYPT:
     923             :         case VNET_CRYPTO_OP_TYPE_DECRYPT:
     924           0 :           vnet_crypto_op_init (op1,
     925             :                                ad->op_by_type[VNET_CRYPTO_OP_TYPE_ENCRYPT]);
     926           0 :           vnet_crypto_op_init (op2,
     927             :                                ad->op_by_type[VNET_CRYPTO_OP_TYPE_DECRYPT]);
     928           0 :           op1->src = op2->src = op1->dst = op2->dst = b->data;
     929           0 :           op1->key_index = op2->key_index = key_index;
     930           0 :           op1->iv = op2->iv = b->data - 64;
     931           0 :           n_bytes += op1->len = op2->len = buffer_size;
     932           0 :           break;
     933           0 :         case VNET_CRYPTO_OP_TYPE_AEAD_ENCRYPT:
     934             :         case VNET_CRYPTO_OP_TYPE_AEAD_DECRYPT:
     935           0 :           vnet_crypto_op_init (op1,
     936             :                                ad->op_by_type
     937             :                                [VNET_CRYPTO_OP_TYPE_AEAD_ENCRYPT]);
     938           0 :           vnet_crypto_op_init (op2,
     939             :                                ad->op_by_type
     940             :                                [VNET_CRYPTO_OP_TYPE_AEAD_DECRYPT]);
     941           0 :           op1->src = op2->src = op1->dst = op2->dst = b->data;
     942           0 :           op1->key_index = op2->key_index = key_index;
     943           0 :           op1->tag = op2->tag = b->data - 32;
     944           0 :           op1->iv = op2->iv = b->data - 64;
     945           0 :           op1->aad = op2->aad = b->data - VLIB_BUFFER_PRE_DATA_SIZE;
     946           0 :           op1->aad_len = op2->aad_len = 64;
     947           0 :           op1->tag_len = op2->tag_len = 16;
     948           0 :           n_bytes += op1->len = op2->len = buffer_size;
     949           0 :           break;
     950           0 :         case VNET_CRYPTO_OP_TYPE_HMAC:
     951           0 :           vnet_crypto_op_init (op1, ad->op_by_type[VNET_CRYPTO_OP_TYPE_HMAC]);
     952           0 :           op1->src = b->data;
     953           0 :           op1->key_index = key_index;
     954           0 :           op1->iv = 0;
     955           0 :           op1->digest = b->data - VLIB_BUFFER_PRE_DATA_SIZE;
     956           0 :           op1->digest_len = 0;
     957           0 :           n_bytes += op1->len = buffer_size;
     958           0 :           break;
     959           0 :         default:
     960           0 :           return 0;
     961             :         }
     962             : 
     963           0 :       for (j = -VLIB_BUFFER_PRE_DATA_SIZE; j < buffer_size; j += 8)
     964           0 :         *(u64 *) (b->data + j) = 1 + random_u64 (&seed);
     965             :     }
     966             : 
     967           0 :   for (i = 0; i < 5; i++)
     968             :     {
     969           0 :       for (j = 0; j < warmup_rounds; j++)
     970             :         {
     971           0 :           vnet_crypto_process_ops (vm, ops1, n_buffers);
     972           0 :           if (ot != VNET_CRYPTO_OP_TYPE_HMAC)
     973           0 :             vnet_crypto_process_ops (vm, ops2, n_buffers);
     974             :         }
     975             : 
     976           0 :       t0[i] = clib_cpu_time_now ();
     977           0 :       for (j = 0; j < rounds; j++)
     978           0 :         vnet_crypto_process_ops (vm, ops1, n_buffers);
     979           0 :       t1[i] = clib_cpu_time_now ();
     980             : 
     981           0 :       if (ot != VNET_CRYPTO_OP_TYPE_HMAC)
     982             :         {
     983           0 :           for (j = 0; j < rounds; j++)
     984           0 :             vnet_crypto_process_ops (vm, ops2, n_buffers);
     985           0 :           t2[i] = clib_cpu_time_now ();
     986             :         }
     987             :     }
     988             : 
     989           0 :   for (i = 0; i < 5; i++)
     990             :     {
     991           0 :       f64 tpb1 = (f64) (t1[i] - t0[i]) / (n_bytes * rounds);
     992           0 :       f64 gbps1 = vm->clib_time.clocks_per_second * 1e-9 * 8 / tpb1;
     993             :       f64 tpb2, gbps2;
     994             : 
     995           0 :       if (ot != VNET_CRYPTO_OP_TYPE_HMAC)
     996             :         {
     997           0 :           tpb2 = (f64) (t2[i] - t1[i]) / (n_bytes * rounds);
     998           0 :           gbps2 = vm->clib_time.clocks_per_second * 1e-9 * 8 / tpb2;
     999           0 :           vlib_cli_output (vm, "%-2u: encrypt %.03f ticks/byte, %.02f Gbps; "
    1000             :                            "decrypt %.03f ticks/byte, %.02f Gbps",
    1001             :                            i + 1, tpb1, gbps1, tpb2, gbps2);
    1002             :         }
    1003             :       else
    1004             :         {
    1005           0 :           vlib_cli_output (vm, "%-2u: hash %.03f ticks/byte, %.02f Gbps\n",
    1006             :                            i + 1, tpb1, gbps1);
    1007             :         }
    1008             :     }
    1009             : 
    1010           0 : done:
    1011           0 :   if (n_alloc)
    1012           0 :     vlib_buffer_free (vm, buffer_indices, n_alloc);
    1013             : 
    1014           0 :   if (key_index != ~0)
    1015           0 :     vnet_crypto_key_del (vm, key_index);
    1016             : 
    1017           0 :   vec_free (buffer_indices);
    1018           0 :   vec_free (ops1);
    1019           0 :   vec_free (ops2);
    1020           0 :   return err;
    1021             : }
    1022             : 
    1023             : static clib_error_t *
    1024           1 : test_crypto_command_fn (vlib_main_t * vm,
    1025             :                         unformat_input_t * input, vlib_cli_command_t * cmd)
    1026             : {
    1027           1 :   crypto_test_main_t *tm = &crypto_test_main;
    1028             :   unittest_crypto_test_registration_t *tr;
    1029           1 :   int is_perf = 0;
    1030             : 
    1031           1 :   tr = tm->test_registrations;
    1032           1 :   memset (tm, 0, sizeof (crypto_test_main_t));
    1033           1 :   tm->test_registrations = tr;
    1034           1 :   tm->alg = ~0;
    1035             : 
    1036           1 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    1037             :     {
    1038           0 :       if (unformat (input, "verbose"))
    1039           0 :         tm->verbose = 1;
    1040           0 :       else if (unformat (input, "detail"))
    1041           0 :         tm->verbose = 2;
    1042             :       else
    1043           0 :         if (unformat (input, "perf %U", unformat_vnet_crypto_alg, &tm->alg))
    1044           0 :         is_perf = 1;
    1045           0 :       else if (unformat (input, "buffers %u", &tm->n_buffers))
    1046             :         ;
    1047           0 :       else if (unformat (input, "rounds %u", &tm->rounds))
    1048             :         ;
    1049           0 :       else if (unformat (input, "warmup-rounds %u", &tm->warmup_rounds))
    1050             :         ;
    1051           0 :       else if (unformat (input, "buffer-size %u", &tm->buffer_size))
    1052             :         ;
    1053             :       else
    1054           0 :         return clib_error_return (0, "unknown input '%U'",
    1055             :                                   format_unformat_error, input);
    1056             :     }
    1057             : 
    1058           1 :   if (is_perf)
    1059           0 :     return test_crypto_perf (vm, tm);
    1060             :   else
    1061           1 :     return test_crypto (vm, tm);
    1062             : }
    1063             : 
    1064             : /* *INDENT-OFF* */
    1065       16239 : VLIB_CLI_COMMAND (test_crypto_command, static) =
    1066             : {
    1067             :   .path = "test crypto",
    1068             :   .short_help = "test crypto",
    1069             :   .function = test_crypto_command_fn,
    1070             : };
    1071             : /* *INDENT-ON* */
    1072             : 
    1073             : static clib_error_t *
    1074         559 : crypto_test_init (vlib_main_t * vm)
    1075             : {
    1076         559 :   return (0);
    1077             : }
    1078             : 
    1079        1679 : VLIB_INIT_FUNCTION (crypto_test_init);
    1080             : 
    1081             : /*
    1082             :  * fd.io coding-style-patch-verification: ON
    1083             :  *
    1084             :  * Local Variables:
    1085             :  * eval: (c-set-style "gnu")
    1086             :  * End:
    1087             :  */

Generated by: LCOV version 1.14