LCOV - code coverage report
Current view: top level - plugins/unittest - hash_test.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 11 89 12.4 %
Date: 2023-07-05 22:20:52 Functions: 12 15 80.0 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: Apache-2.0
       3             :  * Copyright(c) 2021 Cisco Systems, Inc.
       4             :  */
       5             : 
       6             : #include <vlib/vlib.h>
       7             : #include <vppinfra/time.h>
       8             : #include <vppinfra/cache.h>
       9             : #include <vppinfra/error.h>
      10             : #include <vnet/hash/hash.h>
      11             : #include <vnet/ethernet/ethernet.h>
      12             : 
      13             : #define HASH_TEST_DATA_SIZE 2048
      14             : 
      15             : typedef struct _hash_test_data
      16             : {
      17             :   const char *name;
      18             :   const char *description;
      19             :   u8 *data;
      20             :   u32 data_size;
      21             :   vnet_hash_fn_type_t ftype;
      22             :   struct _hash_test_data *next;
      23             : } hash_test_data_t;
      24             : 
      25             : typedef struct
      26             : {
      27             :   int verbose;
      28             : 
      29             :   char *hash_name;
      30             :   u32 warmup_rounds;
      31             :   u32 rounds;
      32             :   u32 n_buffers;
      33             : 
      34             :   hash_test_data_t *hash_test_data;
      35             : } hash_test_main_t;
      36             : 
      37             : hash_test_main_t hash_test_main;
      38             : 
      39             : #define HASH_TEST_REGISTER_DATA(x, ...)                                       \
      40             :   __VA_ARGS__ hash_test_data_t __hash_test_data_##x;                          \
      41             :   static void __clib_constructor __hash_test_data_fn_##x (void)               \
      42             :   {                                                                           \
      43             :     hash_test_main_t *htm = &hash_test_main;                                  \
      44             :     __hash_test_data_##x.next = htm->hash_test_data;                          \
      45             :     htm->hash_test_data = &__hash_test_data_##x;                              \
      46             :   }                                                                           \
      47             :   __VA_ARGS__ hash_test_data_t __hash_test_data_##x
      48             : 
      49             : // qinq
      50             : u8 eth_qinq_ipv4_tcp_data[72] = {
      51             :   0x02, 0xfe, 0x39, 0xe5, 0x09, 0x8f, 0x02, 0xfe, 0x2d, 0x18, 0x63, 0x18,
      52             :   0x88, 0xa8, 0x03, 0xe8, 0x81, 0x00, 0x03, 0xe8, 0x08, 0x00, 0x45, 0x00,
      53             :   0x05, 0xdc, 0xdb, 0x42, 0x40, 0x00, 0x40, 0x06, 0xc4, 0x85, 0xc0, 0xa8,
      54             :   0x0a, 0x02, 0xc0, 0xa8, 0x0a, 0x01, 0xd8, 0xde, 0x14, 0x51, 0x34, 0x93,
      55             :   0xa8, 0x1b, 0x7b, 0xef, 0x2e, 0x7e, 0x80, 0x10, 0x00, 0xe5, 0xc7, 0x03,
      56             :   0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0xce, 0xaa, 0x00, 0x2f, 0xf2, 0xc3
      57             : };
      58             : 
      59         559 : HASH_TEST_REGISTER_DATA (eth_qinq_ipv4_tcp, static) = {
      60             :   .name = "eth-qinq-ipv4-tcp",
      61             :   .description = "Ethernet QinQ IPv4 TCP",
      62             :   .data = eth_qinq_ipv4_tcp_data,
      63             :   .data_size = sizeof (eth_qinq_ipv4_tcp_data),
      64             :   .ftype = VNET_HASH_FN_TYPE_ETHERNET,
      65             : };
      66             : 
      67             : // vlan
      68             : u8 eth_vlan_ipv4_tcp_data[68] = {
      69             :   0x02, 0xfe, 0x39, 0xe5, 0x09, 0x8f, 0x02, 0xfe, 0x2d, 0x18, 0x63, 0x18,
      70             :   0x81, 0x00, 0x03, 0xe8, 0x08, 0x00, 0x45, 0x00, 0x05, 0xdc, 0xdb, 0x42,
      71             :   0x40, 0x00, 0x40, 0x06, 0xc4, 0x85, 0xc0, 0xa8, 0x0a, 0x02, 0xc0, 0xa8,
      72             :   0x0a, 0x01, 0xd8, 0xde, 0x14, 0x51, 0x34, 0x93, 0xa8, 0x1b, 0x7b, 0xef,
      73             :   0x2e, 0x7e, 0x80, 0x10, 0x00, 0xe5, 0xc7, 0x03, 0x00, 0x00, 0x01, 0x01,
      74             :   0x08, 0x0a, 0xce, 0xaa, 0x00, 0x2f, 0xf2, 0xc3
      75             : };
      76             : 
      77         559 : HASH_TEST_REGISTER_DATA (eth_vlan_ipv4_tcp, static) = {
      78             :   .name = "eth-vlan-ipv4-tcp",
      79             :   .description = "Ethernet Vlan IPv4 TCP",
      80             :   .data = eth_vlan_ipv4_tcp_data,
      81             :   .data_size = sizeof (eth_vlan_ipv4_tcp_data),
      82             :   .ftype = VNET_HASH_FN_TYPE_ETHERNET,
      83             : };
      84             : 
      85             : // ethernet
      86             : u8 eth_ipv4_tcp_data[64] = {
      87             :   0x02, 0xfe, 0x39, 0xe5, 0x09, 0x8f, 0x02, 0xfe, 0x2d, 0x18, 0x63, 0x18, 0x08,
      88             :   0x00, 0x45, 0x00, 0x05, 0xdc, 0xdb, 0x42, 0x40, 0x00, 0x40, 0x06, 0xc4, 0x85,
      89             :   0xc0, 0xa8, 0x0a, 0x02, 0xc0, 0xa8, 0x0a, 0x01, 0xd8, 0xde, 0x14, 0x51, 0x34,
      90             :   0x93, 0xa8, 0x1b, 0x7b, 0xef, 0x2e, 0x7e, 0x80, 0x10, 0x00, 0xe5, 0xc7, 0x03,
      91             :   0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0xce, 0xaa, 0x00, 0x2f, 0xf2, 0xc3
      92             : };
      93             : 
      94         559 : HASH_TEST_REGISTER_DATA (eth_ipv4_tcp, static) = {
      95             :   .name = "eth-ipv4-tcp",
      96             :   .description = "Ethernet IPv4 TCP",
      97             :   .data = eth_ipv4_tcp_data,
      98             :   .data_size = sizeof (eth_ipv4_tcp_data),
      99             :   .ftype = VNET_HASH_FN_TYPE_ETHERNET,
     100             : };
     101             : 
     102             : // udp
     103             : u8 eth_ipv4_udp_data[42] = { 0x62, 0x36, 0xbe, 0xff, 0x91, 0x20, 0x5e,
     104             :                              0x2c, 0xaf, 0x2e, 0x1e, 0x51, 0x08, 0x00,
     105             :                              0x45, 0x00, 0x05, 0xc4, 0x9d, 0xc3, 0x40,
     106             :                              0x00, 0x33, 0x11, 0x49, 0x61, 0x3e, 0xd2,
     107             :                              0x12, 0x28, 0x0a, 0x09, 0x00, 0x02, 0x14,
     108             :                              0x58, 0xc0, 0xd8, 0x05, 0xb0, 0x75, 0xbd };
     109             : 
     110         559 : HASH_TEST_REGISTER_DATA (eth_ipv4_udp, static) = {
     111             :   .name = "eth-ipv4-udp",
     112             :   .description = "Ethernet IPv4 UDP",
     113             :   .data = eth_ipv4_udp_data,
     114             :   .data_size = sizeof (eth_ipv4_udp_data),
     115             :   .ftype = VNET_HASH_FN_TYPE_ETHERNET,
     116             : };
     117             : 
     118             : // ipv4
     119             : u8 ipv4_tcp_data[50] = { 0x45, 0x00, 0x05, 0xdc, 0xdb, 0x42, 0x40, 0x00, 0x40,
     120             :                          0x06, 0xc4, 0x85, 0xc0, 0xa8, 0x0a, 0x02, 0xc0, 0xa8,
     121             :                          0x0a, 0x01, 0xd8, 0xde, 0x14, 0x51, 0x34, 0x93, 0xa8,
     122             :                          0x1b, 0x7b, 0xef, 0x2e, 0x7e, 0x80, 0x10, 0x00, 0xe5,
     123             :                          0xc7, 0x03, 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0xce,
     124             :                          0xaa, 0x00, 0x2f, 0xf2, 0xc3 };
     125             : 
     126         559 : HASH_TEST_REGISTER_DATA (ipv4_tcp, static) = {
     127             :   .name = "ipv4-tcp",
     128             :   .description = "IPv4 TCP",
     129             :   .data = ipv4_tcp_data,
     130             :   .data_size = sizeof (ipv4_tcp_data),
     131             :   .ftype = VNET_HASH_FN_TYPE_IP,
     132             : };
     133             : 
     134             : u8 ipv4_icmp_data[84] = {
     135             :   0x45, 0x00, 0x00, 0x54, 0xb7, 0xe6, 0x40, 0x00, 0x40, 0x01, 0xed, 0x6e,
     136             :   0xc0, 0xa8, 0x0a, 0x01, 0xc0, 0xa8, 0x0a, 0x02, 0x08, 0x00, 0xc7, 0x84,
     137             :   0x00, 0x16, 0x00, 0x92, 0xfd, 0xdb, 0xd9, 0x60, 0x00, 0x00, 0x00, 0x00,
     138             :   0x91, 0xc3, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x12, 0x13,
     139             :   0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
     140             :   0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
     141             :   0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37
     142             : 
     143             : };
     144             : 
     145         559 : HASH_TEST_REGISTER_DATA (ipv4_icmp, static) = {
     146             :   .name = "ipv4-icmp",
     147             :   .description = "IPv4 ICMP",
     148             :   .data = ipv4_icmp_data,
     149             :   .data_size = sizeof (ipv4_icmp_data),
     150             :   .ftype = VNET_HASH_FN_TYPE_IP,
     151             : };
     152             : 
     153             : // ip6
     154             : u8 ipv6_icmp6_data[104] = {
     155             :   0x60, 0x0d, 0xf4, 0x97, 0x00, 0x40, 0x3a, 0x40, 0xfd, 0x01, 0x00, 0x00, 0x00,
     156             :   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xfd, 0x01,
     157             :   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
     158             :   0x01, 0x80, 0x00, 0x10, 0x84, 0xb1, 0x25, 0x00, 0x01, 0x22, 0x57, 0xf0, 0x60,
     159             :   0x00, 0x00, 0x00, 0x00, 0xcb, 0x4a, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
     160             :   0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
     161             :   0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
     162             :   0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37
     163             : };
     164             : 
     165         559 : HASH_TEST_REGISTER_DATA (ipv6_icmp6, static) = {
     166             :   .name = "ipv6-icmp6",
     167             :   .description = "IPv6 ICMP6",
     168             :   .data = ipv6_icmp6_data,
     169             :   .data_size = sizeof (ipv6_icmp6_data),
     170             :   .ftype = VNET_HASH_FN_TYPE_IP,
     171             : };
     172             : 
     173             : void
     174           0 : fill_buffers (vlib_main_t *vm, u32 *buffer_indices, u8 *data, u32 data_size,
     175             :               u32 n_buffers)
     176             : {
     177             :   int i, j;
     178           0 :   u64 seed = clib_cpu_time_now ();
     179           0 :   for (i = 0; i < n_buffers; i++)
     180             :     {
     181           0 :       vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
     182           0 :       clib_memcpy_fast (b->data, data, data_size);
     183           0 :       b->current_data = 0;
     184           0 :       for (j = data_size; j < HASH_TEST_DATA_SIZE; j += 8)
     185           0 :         *(u64 *) (b->data + j) = 1 + random_u64 (&seed);
     186           0 :       b->current_length = HASH_TEST_DATA_SIZE;
     187             :     }
     188           0 : }
     189             : 
     190             : static clib_error_t *
     191           0 : test_hash_perf (vlib_main_t *vm, hash_test_main_t *htm)
     192             : {
     193           0 :   clib_error_t *err = 0;
     194           0 :   u32 n_buffers, n_alloc = 0, warmup_rounds, rounds;
     195           0 :   u32 *buffer_indices = 0;
     196             :   u64 t0[5], t1[5];
     197             :   vnet_hash_fn_t hf;
     198           0 :   hash_test_data_t *hash_test_data = htm->hash_test_data;
     199           0 :   void **p = 0;
     200             :   int i, j;
     201             : 
     202           0 :   rounds = htm->rounds ? htm->rounds : 100;
     203           0 :   n_buffers = htm->n_buffers ? htm->n_buffers : 256;
     204           0 :   warmup_rounds = htm->warmup_rounds ? htm->warmup_rounds : 100;
     205             : 
     206           0 :   vec_validate_aligned (p, n_buffers - 1, CLIB_CACHE_LINE_BYTES);
     207           0 :   vec_validate_aligned (buffer_indices, n_buffers - 1, CLIB_CACHE_LINE_BYTES);
     208           0 :   n_alloc = vlib_buffer_alloc (vm, buffer_indices, n_buffers);
     209           0 :   if (n_alloc != n_buffers)
     210             :     {
     211           0 :       err = clib_error_return (0, "buffer alloc failure");
     212           0 :       goto done;
     213             :     }
     214             : 
     215           0 :   vlib_cli_output (vm,
     216             :                    "%s: n_buffers %u rounds %u "
     217             :                    "warmup-rounds %u",
     218             :                    htm->hash_name, n_buffers, rounds, warmup_rounds);
     219           0 :   vlib_cli_output (vm, "   cpu-freq %.2f GHz",
     220           0 :                    (f64) vm->clib_time.clocks_per_second * 1e-9);
     221             : 
     222           0 :   while (hash_test_data)
     223             :     {
     224           0 :       fill_buffers (vm, buffer_indices, hash_test_data->data,
     225             :                     hash_test_data->data_size, n_buffers);
     226             : 
     227           0 :       for (i = 0; i < n_buffers; i++)
     228             :         {
     229           0 :           vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
     230           0 :           p[i] = vlib_buffer_get_current (b);
     231             :         }
     232             : 
     233             :       hf =
     234           0 :         vnet_hash_function_from_name (htm->hash_name, hash_test_data->ftype);
     235             : 
     236           0 :       if (!hf)
     237             :         {
     238           0 :           err = clib_error_return (0, "wrong hash name");
     239           0 :           goto done;
     240             :         }
     241             : 
     242           0 :       for (i = 0; i < 5; i++)
     243           0 :         {
     244           0 :           u32 h[n_buffers];
     245           0 :           for (j = 0; j < warmup_rounds; j++)
     246             :             {
     247           0 :               hf (p, h, n_buffers);
     248             :             }
     249             : 
     250           0 :           t0[i] = clib_cpu_time_now ();
     251           0 :           for (j = 0; j < rounds; j++)
     252           0 :             hf (p, h, n_buffers);
     253           0 :           t1[i] = clib_cpu_time_now ();
     254             :         }
     255             : 
     256           0 :       vlib_cli_output (
     257             :         vm, "===========================================================");
     258           0 :       vlib_cli_output (vm, " Test: %s", hash_test_data->description);
     259           0 :       vlib_cli_output (
     260             :         vm, "===========================================================");
     261           0 :       for (i = 0; i < 5; i++)
     262             :         {
     263           0 :           f64 tpp1 = (f64) (t1[i] - t0[i]) / (n_buffers * rounds);
     264           0 :           f64 Mpps1 = vm->clib_time.clocks_per_second * 1e-6 / tpp1;
     265             : 
     266           0 :           vlib_cli_output (vm, "%-2u: %.03f ticks/packet, %.02f Mpps\n", i + 1,
     267             :                            tpp1, Mpps1);
     268             :         }
     269           0 :       hash_test_data = hash_test_data->next;
     270             :     }
     271             : 
     272           0 : done:
     273           0 :   if (n_alloc)
     274           0 :     vlib_buffer_free (vm, buffer_indices, n_alloc);
     275             : 
     276           0 :   vec_free (p);
     277           0 :   vec_free (buffer_indices);
     278           0 :   return err;
     279             : }
     280             : 
     281             : static clib_error_t *
     282           0 : test_hash_command_fn (vlib_main_t *vm, unformat_input_t *input,
     283             :                       vlib_cli_command_t *cmd)
     284             : {
     285           0 :   hash_test_main_t *tm = &hash_test_main;
     286           0 :   clib_error_t *err = 0;
     287             : 
     288           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     289             :     {
     290           0 :       if (unformat (input, "verbose"))
     291           0 :         tm->verbose = 1;
     292           0 :       else if (unformat (input, "detail"))
     293           0 :         tm->verbose = 2;
     294           0 :       else if (unformat (input, "perf %s", &tm->hash_name))
     295             :         ;
     296           0 :       else if (unformat (input, "buffers %u", &tm->n_buffers))
     297             :         ;
     298           0 :       else if (unformat (input, "rounds %u", &tm->rounds))
     299             :         ;
     300           0 :       else if (unformat (input, "warmup-rounds %u", &tm->warmup_rounds))
     301             :         ;
     302             :       else
     303             :         {
     304           0 :           err = clib_error_return (0, "unknown input '%U'",
     305             :                                    format_unformat_error, input);
     306           0 :           goto error;
     307             :         }
     308             :     }
     309             : 
     310           0 :   err = test_hash_perf (vm, tm);
     311             : 
     312           0 : error:
     313           0 :   vec_free (tm->hash_name);
     314             : 
     315           0 :   return err;
     316             : }
     317             : 
     318       16239 : VLIB_CLI_COMMAND (test_hash_command, static) = {
     319             :   .path = "test hash",
     320             :   .short_help = "test hash [perf <hash-name>] [buffers <n>] [rounds <n>] "
     321             :                 "[warmup-rounds <n>]",
     322             :   .function = test_hash_command_fn,
     323             : };
     324             : 
     325             : static clib_error_t *
     326         559 : hash_test_init (vlib_main_t *vm)
     327             : {
     328         559 :   return (0);
     329             : }
     330             : 
     331        3359 : VLIB_INIT_FUNCTION (hash_test_init);

Generated by: LCOV version 1.14