LCOV - code coverage report
Current view: top level - app/test - test_thash.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 279 340 82.1 %
Date: 2024-12-01 18:57:19 Functions: 25 25 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 112 260 43.1 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2015-2019 Vladimir Medvedkin <medvedkinv@gmail.com>
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <rte_common.h>
       6                 :            : #include <rte_eal.h>
       7                 :            : #include <rte_ip.h>
       8                 :            : #include <rte_random.h>
       9                 :            : #include <rte_malloc.h>
      10                 :            : #include <rte_byteorder.h>
      11                 :            : 
      12                 :            : #include "test.h"
      13                 :            : 
      14                 :            : #include <rte_thash.h>
      15                 :            : 
      16                 :            : #define HASH_MSK(reta_sz)       ((1 << reta_sz) - 1)
      17                 :            : #define TUPLE_SZ        (RTE_THASH_V4_L4_LEN * 4)
      18                 :            : 
      19                 :            : struct test_thash_v4 {
      20                 :            :         uint32_t        dst_ip;
      21                 :            :         uint32_t        src_ip;
      22                 :            :         uint16_t        dst_port;
      23                 :            :         uint16_t        src_port;
      24                 :            :         uint32_t        hash_l3;
      25                 :            :         uint32_t        hash_l3l4;
      26                 :            : };
      27                 :            : 
      28                 :            : struct test_thash_v6 {
      29                 :            :         struct rte_ipv6_addr dst_ip;
      30                 :            :         struct rte_ipv6_addr src_ip;
      31                 :            :         uint16_t        dst_port;
      32                 :            :         uint16_t        src_port;
      33                 :            :         uint32_t        hash_l3;
      34                 :            :         uint32_t        hash_l3l4;
      35                 :            : };
      36                 :            : 
      37                 :            : /*From 82599 Datasheet 7.1.2.8.3 RSS Verification Suite*/
      38                 :            : struct test_thash_v4 v4_tbl[] = {
      39                 :            : {RTE_IPV4(161, 142, 100, 80), RTE_IPV4(66, 9, 149, 187),
      40                 :            :         1766, 2794, 0x323e8fc2, 0x51ccc178},
      41                 :            : {RTE_IPV4(65, 69, 140, 83), RTE_IPV4(199, 92, 111, 2),
      42                 :            :         4739, 14230, 0xd718262a, 0xc626b0ea},
      43                 :            : {RTE_IPV4(12, 22, 207, 184), RTE_IPV4(24, 19, 198, 95),
      44                 :            :         38024, 12898, 0xd2d0a5de, 0x5c2b394a},
      45                 :            : {RTE_IPV4(209, 142, 163, 6), RTE_IPV4(38, 27, 205, 30),
      46                 :            :         2217, 48228, 0x82989176, 0xafc7327f},
      47                 :            : {RTE_IPV4(202, 188, 127, 2), RTE_IPV4(153, 39, 163, 191),
      48                 :            :         1303, 44251, 0x5d1809c5, 0x10e828a2},
      49                 :            : };
      50                 :            : 
      51                 :            : struct test_thash_v6 v6_tbl[] = {
      52                 :            : /*3ffe:2501:200:3::1*/
      53                 :            : {RTE_IPV6(0x3ffe, 0x2501, 0x0200, 0x0003, 0, 0, 0, 0x0001),
      54                 :            : /*3ffe:2501:200:1fff::7*/
      55                 :            : RTE_IPV6(0x3ffe, 0x2501, 0x0200, 0x1fff, 0, 0, 0, 0x0007),
      56                 :            : 1766, 2794, 0x2cc18cd5, 0x40207d3d},
      57                 :            : /*ff02::1*/
      58                 :            : {RTE_IPV6(0xff02, 0, 0, 0, 0, 0, 0, 0x0001),
      59                 :            : /*3ffe:501:8::260:97ff:fe40:efab*/
      60                 :            : RTE_IPV6(0x3ffe, 0x0501, 0x0008, 0, 0x0260, 0x97ff, 0xfe40, 0xefab),
      61                 :            : 4739, 14230, 0x0f0c461c, 0xdde51bbf},
      62                 :            : /*fe80::200:f8ff:fe21:67cf*/
      63                 :            : {RTE_IPV6(0xfe80, 0, 0, 0, 0x0200, 0xf8ff, 0xfe21, 0x67cf),
      64                 :            : /*3ffe:1900:4545:3:200:f8ff:fe21:67cf*/
      65                 :            : RTE_IPV6(0x3ffe, 0x1900, 0x4545, 0x0003, 0x0200, 0xf8ff, 0xfe21, 0x67cf),
      66                 :            : 38024, 44251, 0x4b61e985, 0x02d1feef},
      67                 :            : };
      68                 :            : 
      69                 :            : uint8_t default_rss_key[] = {
      70                 :            : 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
      71                 :            : 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
      72                 :            : 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
      73                 :            : 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
      74                 :            : 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa,
      75                 :            : };
      76                 :            : 
      77                 :            : static const uint8_t big_rss_key[] = {
      78                 :            :         0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
      79                 :            :         0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
      80                 :            :         0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
      81                 :            :         0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
      82                 :            :         0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa,
      83                 :            :         0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
      84                 :            :         0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
      85                 :            :         0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
      86                 :            :         0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
      87                 :            :         0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa,
      88                 :            :         0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
      89                 :            :         0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
      90                 :            :         0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
      91                 :            :         0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
      92                 :            :         0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa,
      93                 :            :         0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
      94                 :            :         0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
      95                 :            :         0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
      96                 :            :         0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
      97                 :            :         0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa,
      98                 :            :         0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
      99                 :            :         0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
     100                 :            :         0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
     101                 :            :         0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
     102                 :            :         0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa,
     103                 :            : };
     104                 :            : 
     105                 :            : static int
     106                 :          1 : test_toeplitz_hash_calc(void)
     107                 :            : {
     108                 :            :         uint32_t i;
     109                 :            :         union rte_thash_tuple tuple;
     110                 :            :         uint32_t rss_l3, rss_l3l4;
     111                 :            :         uint8_t rss_key_be[RTE_DIM(default_rss_key)];
     112                 :            :         struct rte_ipv6_hdr ipv6_hdr;
     113                 :            : 
     114                 :            :         /* Convert RSS key*/
     115                 :            :         rte_convert_rss_key((uint32_t *)&default_rss_key,
     116                 :            :                 (uint32_t *)rss_key_be, RTE_DIM(default_rss_key));
     117                 :            : 
     118                 :            : 
     119         [ +  + ]:          6 :         for (i = 0; i < RTE_DIM(v4_tbl); i++) {
     120                 :          5 :                 tuple.v4.src_addr = v4_tbl[i].src_ip;
     121                 :          5 :                 tuple.v4.dst_addr = v4_tbl[i].dst_ip;
     122                 :          5 :                 tuple.v4.sport = v4_tbl[i].src_port;
     123                 :          5 :                 tuple.v4.dport = v4_tbl[i].dst_port;
     124                 :            :                 /*Calculate hash with original key*/
     125                 :          5 :                 rss_l3 = rte_softrss((uint32_t *)&tuple,
     126                 :            :                                 RTE_THASH_V4_L3_LEN, default_rss_key);
     127                 :          5 :                 rss_l3l4 = rte_softrss((uint32_t *)&tuple,
     128                 :            :                                 RTE_THASH_V4_L4_LEN, default_rss_key);
     129         [ +  - ]:          5 :                 if ((rss_l3 != v4_tbl[i].hash_l3) ||
     130         [ +  - ]:          5 :                                 (rss_l3l4 != v4_tbl[i].hash_l3l4))
     131                 :            :                         return -TEST_FAILED;
     132                 :            :                 /*Calculate hash with converted key*/
     133                 :          5 :                 rss_l3 = rte_softrss_be((uint32_t *)&tuple,
     134                 :            :                                 RTE_THASH_V4_L3_LEN, rss_key_be);
     135                 :          5 :                 rss_l3l4 = rte_softrss_be((uint32_t *)&tuple,
     136                 :            :                                 RTE_THASH_V4_L4_LEN, rss_key_be);
     137   [ +  -  +  - ]:          5 :                 if ((rss_l3 != v4_tbl[i].hash_l3) ||
     138                 :            :                                 (rss_l3l4 != v4_tbl[i].hash_l3l4))
     139                 :            :                         return -TEST_FAILED;
     140                 :            :         }
     141         [ +  + ]:          4 :         for (i = 0; i < RTE_DIM(v6_tbl); i++) {
     142                 :            :                 /*Fill ipv6 hdr*/
     143                 :          3 :                 ipv6_hdr.src_addr = v6_tbl[i].src_ip;
     144                 :          3 :                 ipv6_hdr.dst_addr = v6_tbl[i].dst_ip;
     145                 :            :                 /*Load and convert ipv6 address into tuple*/
     146                 :            :                 rte_thash_load_v6_addrs(&ipv6_hdr, &tuple);
     147                 :          3 :                 tuple.v6.sport = v6_tbl[i].src_port;
     148                 :          3 :                 tuple.v6.dport = v6_tbl[i].dst_port;
     149                 :            :                 /*Calculate hash with original key*/
     150                 :          3 :                 rss_l3 = rte_softrss((uint32_t *)&tuple,
     151                 :            :                                 RTE_THASH_V6_L3_LEN, default_rss_key);
     152                 :          3 :                 rss_l3l4 = rte_softrss((uint32_t *)&tuple,
     153                 :            :                                 RTE_THASH_V6_L4_LEN, default_rss_key);
     154         [ +  - ]:          3 :                 if ((rss_l3 != v6_tbl[i].hash_l3) ||
     155         [ +  - ]:          3 :                                 (rss_l3l4 != v6_tbl[i].hash_l3l4))
     156                 :            :                         return -TEST_FAILED;
     157                 :            :                 /*Calculate hash with converted key*/
     158                 :          3 :                 rss_l3 = rte_softrss_be((uint32_t *)&tuple,
     159                 :            :                                 RTE_THASH_V6_L3_LEN, rss_key_be);
     160                 :          3 :                 rss_l3l4 = rte_softrss_be((uint32_t *)&tuple,
     161                 :            :                                 RTE_THASH_V6_L4_LEN, rss_key_be);
     162   [ +  -  +  - ]:          3 :                 if ((rss_l3 != v6_tbl[i].hash_l3) ||
     163                 :            :                                 (rss_l3l4 != v6_tbl[i].hash_l3l4))
     164                 :            :                         return -TEST_FAILED;
     165                 :            :         }
     166                 :            :         return TEST_SUCCESS;
     167                 :            : }
     168                 :            : 
     169                 :            : static int
     170                 :          1 : test_toeplitz_hash_gfni(void)
     171                 :            : {
     172                 :            :         uint32_t i;
     173                 :            :         union rte_thash_tuple tuple;
     174                 :            :         uint32_t rss_l3, rss_l3l4;
     175                 :            :         uint64_t rss_key_matrixes[RTE_DIM(default_rss_key)];
     176                 :            : 
     177         [ -  + ]:          1 :         if (!rte_thash_gfni_supported())
     178                 :            :                 return TEST_SKIPPED;
     179                 :            : 
     180                 :            :         /* Convert RSS key into matrixes */
     181                 :          0 :         rte_thash_complete_matrix(rss_key_matrixes, default_rss_key,
     182                 :            :                 RTE_DIM(default_rss_key));
     183                 :            : 
     184         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(v4_tbl); i++) {
     185         [ #  # ]:          0 :                 tuple.v4.src_addr = rte_cpu_to_be_32(v4_tbl[i].src_ip);
     186         [ #  # ]:          0 :                 tuple.v4.dst_addr = rte_cpu_to_be_32(v4_tbl[i].dst_ip);
     187         [ #  # ]:          0 :                 tuple.v4.sport = rte_cpu_to_be_16(v4_tbl[i].dst_port);
     188         [ #  # ]:          0 :                 tuple.v4.dport = rte_cpu_to_be_16(v4_tbl[i].src_port);
     189                 :            : 
     190                 :            :                 rss_l3 = rte_thash_gfni(rss_key_matrixes, (uint8_t *)&tuple,
     191                 :            :                                 RTE_THASH_V4_L3_LEN * 4);
     192                 :            :                 rss_l3l4 = rte_thash_gfni(rss_key_matrixes, (uint8_t *)&tuple,
     193                 :            :                                 RTE_THASH_V4_L4_LEN * 4);
     194         [ #  # ]:          0 :                 if ((rss_l3 != v4_tbl[i].hash_l3) ||
     195         [ #  # ]:          0 :                                 (rss_l3l4 != v4_tbl[i].hash_l3l4))
     196                 :            :                         return -TEST_FAILED;
     197                 :            :         }
     198                 :            : 
     199         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(v6_tbl); i++) {
     200                 :          0 :                 tuple.v6.src_addr = v6_tbl[i].src_ip;
     201                 :          0 :                 tuple.v6.dst_addr = v6_tbl[i].dst_ip;
     202         [ #  # ]:          0 :                 tuple.v6.sport = rte_cpu_to_be_16(v6_tbl[i].dst_port);
     203         [ #  # ]:          0 :                 tuple.v6.dport = rte_cpu_to_be_16(v6_tbl[i].src_port);
     204                 :            :                 rss_l3 = rte_thash_gfni(rss_key_matrixes, (uint8_t *)&tuple,
     205                 :            :                                 RTE_THASH_V6_L3_LEN * 4);
     206                 :            :                 rss_l3l4 = rte_thash_gfni(rss_key_matrixes, (uint8_t *)&tuple,
     207                 :            :                                 RTE_THASH_V6_L4_LEN * 4);
     208         [ #  # ]:          0 :                 if ((rss_l3 != v6_tbl[i].hash_l3) ||
     209         [ #  # ]:          0 :                                 (rss_l3l4 != v6_tbl[i].hash_l3l4))
     210                 :            :                         return -TEST_FAILED;
     211                 :            :         }
     212                 :            : 
     213                 :            :         return TEST_SUCCESS;
     214                 :            : }
     215                 :            : 
     216                 :            : #define DATA_SZ         4
     217                 :            : #define ITER            1000
     218                 :            : 
     219                 :            : enum {
     220                 :            :         SCALAR_DATA_BUF_1_HASH_IDX = 0,
     221                 :            :         SCALAR_DATA_BUF_2_HASH_IDX,
     222                 :            :         GFNI_DATA_BUF_1_HASH_IDX,
     223                 :            :         GFNI_DATA_BUF_2_HASH_IDX,
     224                 :            :         GFNI_BULK_DATA_BUF_1_HASH_IDX,
     225                 :            :         GFNI_BULK_DATA_BUF_2_HASH_IDX,
     226                 :            :         HASH_IDXES
     227                 :            : };
     228                 :            : 
     229                 :            : static int
     230                 :          1 : test_toeplitz_hash_rand_data(void)
     231                 :            : {
     232                 :            :         uint32_t data[2][DATA_SZ];
     233                 :            :         uint32_t scalar_data[2][DATA_SZ];
     234                 :          1 :         uint32_t hash[HASH_IDXES] = { 0 };
     235                 :            :         uint64_t rss_key_matrixes[RTE_DIM(default_rss_key)];
     236                 :            :         int i, j;
     237                 :            :         uint8_t *bulk_data[2];
     238                 :            : 
     239         [ -  + ]:          1 :         if (!rte_thash_gfni_supported())
     240                 :            :                 return TEST_SKIPPED;
     241                 :            : 
     242                 :          0 :         rte_thash_complete_matrix(rss_key_matrixes, default_rss_key,
     243                 :            :                 RTE_DIM(default_rss_key));
     244                 :            : 
     245         [ #  # ]:          0 :         for (i = 0; i < 2; i++)
     246                 :          0 :                 bulk_data[i] = (uint8_t *)data[i];
     247                 :            : 
     248         [ #  # ]:          0 :         for (i = 0; i < ITER; i++) {
     249         [ #  # ]:          0 :                 for (j = 0; j < DATA_SZ; j++) {
     250                 :          0 :                         data[0][j] = rte_rand();
     251                 :          0 :                         data[1][j] = rte_rand();
     252         [ #  # ]:          0 :                         scalar_data[0][j] = rte_cpu_to_be_32(data[0][j]);
     253         [ #  # ]:          0 :                         scalar_data[1][j] = rte_cpu_to_be_32(data[1][j]);
     254                 :            :                 }
     255                 :            : 
     256                 :          0 :                 hash[SCALAR_DATA_BUF_1_HASH_IDX] = rte_softrss(scalar_data[0],
     257                 :            :                         DATA_SZ, default_rss_key);
     258                 :          0 :                 hash[SCALAR_DATA_BUF_2_HASH_IDX] = rte_softrss(scalar_data[1],
     259                 :            :                         DATA_SZ, default_rss_key);
     260                 :          0 :                 hash[GFNI_DATA_BUF_1_HASH_IDX] = rte_thash_gfni(
     261                 :            :                         rss_key_matrixes, (uint8_t *)data[0],
     262                 :            :                         DATA_SZ * sizeof(uint32_t));
     263                 :          0 :                 hash[GFNI_DATA_BUF_2_HASH_IDX] = rte_thash_gfni(
     264                 :            :                         rss_key_matrixes, (uint8_t *)data[1],
     265                 :            :                         DATA_SZ * sizeof(uint32_t));
     266                 :            :                 rte_thash_gfni_bulk(rss_key_matrixes,
     267                 :            :                         DATA_SZ * sizeof(uint32_t), bulk_data,
     268                 :            :                         &hash[GFNI_BULK_DATA_BUF_1_HASH_IDX], 2);
     269                 :            : 
     270                 :          0 :                 if ((hash[SCALAR_DATA_BUF_1_HASH_IDX] !=
     271         [ #  # ]:          0 :                                 hash[GFNI_DATA_BUF_1_HASH_IDX]) ||
     272                 :            :                                 (hash[SCALAR_DATA_BUF_1_HASH_IDX] !=
     273         [ #  # ]:          0 :                                 hash[GFNI_BULK_DATA_BUF_1_HASH_IDX]) ||
     274                 :          0 :                                 (hash[SCALAR_DATA_BUF_2_HASH_IDX] !=
     275         [ #  # ]:          0 :                                 hash[GFNI_DATA_BUF_2_HASH_IDX]) ||
     276                 :            :                                 (hash[SCALAR_DATA_BUF_2_HASH_IDX] !=
     277         [ #  # ]:          0 :                                 hash[GFNI_BULK_DATA_BUF_2_HASH_IDX]))
     278                 :            : 
     279                 :            :                         return -TEST_FAILED;
     280                 :            :         }
     281                 :            : 
     282                 :            :         return TEST_SUCCESS;
     283                 :            : }
     284                 :            : 
     285                 :            : enum {
     286                 :            :         RSS_V4_IDX,
     287                 :            :         RSS_V6_IDX
     288                 :            : };
     289                 :            : 
     290                 :            : static int
     291                 :          1 : test_toeplitz_hash_gfni_bulk(void)
     292                 :            : {
     293                 :            :         uint32_t i;
     294                 :            :         union rte_thash_tuple tuple[2];
     295                 :            :         uint8_t *tuples[2];
     296                 :          1 :         uint32_t rss[2] = { 0 };
     297                 :            :         uint64_t rss_key_matrixes[RTE_DIM(default_rss_key)];
     298                 :            : 
     299         [ -  + ]:          1 :         if (!rte_thash_gfni_supported())
     300                 :            :                 return TEST_SKIPPED;
     301                 :            : 
     302                 :            :         /* Convert RSS key into matrixes */
     303                 :          0 :         rte_thash_complete_matrix(rss_key_matrixes, default_rss_key,
     304                 :            :                 RTE_DIM(default_rss_key));
     305                 :            : 
     306         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(tuples); i++) {
     307                 :            :                 /* allocate memory enough for a biggest tuple */
     308                 :          0 :                 tuples[i] = rte_zmalloc(NULL, RTE_THASH_V6_L4_LEN * 4, 0);
     309         [ #  # ]:          0 :                 if (tuples[i] == NULL)
     310                 :            :                         return -TEST_FAILED;
     311                 :            :         }
     312                 :            : 
     313         [ #  # ]:          0 :         for (i = 0; i < RTE_MIN(RTE_DIM(v4_tbl), RTE_DIM(v6_tbl)); i++) {
     314                 :            :                 /*Load IPv4 headers and copy it into the corresponding tuple*/
     315         [ #  # ]:          0 :                 tuple[0].v4.src_addr = rte_cpu_to_be_32(v4_tbl[i].src_ip);
     316         [ #  # ]:          0 :                 tuple[0].v4.dst_addr = rte_cpu_to_be_32(v4_tbl[i].dst_ip);
     317         [ #  # ]:          0 :                 tuple[0].v4.sport = rte_cpu_to_be_16(v4_tbl[i].dst_port);
     318         [ #  # ]:          0 :                 tuple[0].v4.dport = rte_cpu_to_be_16(v4_tbl[i].src_port);
     319         [ #  # ]:          0 :                 rte_memcpy(tuples[0], &tuple[0], RTE_THASH_V4_L4_LEN * 4);
     320                 :            : 
     321                 :            :                 /*Load IPv6 headers and copy it into the corresponding tuple*/
     322                 :          0 :                 tuple[1].v6.src_addr = v6_tbl[i].src_ip;
     323                 :          0 :                 tuple[1].v6.dst_addr = v6_tbl[i].dst_ip;
     324         [ #  # ]:          0 :                 tuple[1].v6.sport = rte_cpu_to_be_16(v6_tbl[i].dst_port);
     325         [ #  # ]:          0 :                 tuple[1].v6.dport = rte_cpu_to_be_16(v6_tbl[i].src_port);
     326         [ #  # ]:          0 :                 rte_memcpy(tuples[1], &tuple[1], RTE_THASH_V6_L4_LEN * 4);
     327                 :            : 
     328                 :            :                 rte_thash_gfni_bulk(rss_key_matrixes, RTE_THASH_V6_L4_LEN * 4,
     329                 :            :                         tuples, rss, 2);
     330                 :            : 
     331         [ #  # ]:          0 :                 if ((rss[RSS_V4_IDX] != v4_tbl[i].hash_l3l4) ||
     332         [ #  # ]:          0 :                                 (rss[RSS_V6_IDX] != v6_tbl[i].hash_l3l4))
     333                 :            :                         return -TEST_FAILED;
     334                 :            :         }
     335                 :            : 
     336                 :            :         return TEST_SUCCESS;
     337                 :            : }
     338                 :            : 
     339                 :            : static int
     340                 :          1 : test_big_tuple_gfni(void)
     341                 :            : {
     342                 :            :         uint32_t arr[16];
     343                 :            :         uint32_t arr_softrss[16];
     344                 :            :         uint32_t hash_1, hash_2;
     345                 :            :         uint64_t rss_key_matrixes[RTE_DIM(big_rss_key)];
     346                 :            :         unsigned int i, size = RTE_DIM(arr) * sizeof(uint32_t);
     347                 :            : 
     348         [ -  + ]:          1 :         if (!rte_thash_gfni_supported())
     349                 :            :                 return TEST_SKIPPED;
     350                 :            : 
     351                 :            :         /* Convert RSS key into matrixes */
     352                 :          0 :         rte_thash_complete_matrix(rss_key_matrixes, big_rss_key,
     353                 :            :                 RTE_DIM(big_rss_key));
     354                 :            : 
     355         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(arr); i++) {
     356                 :          0 :                 arr[i] = rte_rand();
     357         [ #  # ]:          0 :                 arr_softrss[i] = rte_be_to_cpu_32(arr[i]);
     358                 :            :         }
     359                 :            : 
     360                 :          0 :         hash_1 = rte_softrss(arr_softrss, RTE_DIM(arr), big_rss_key);
     361                 :            :         hash_2 = rte_thash_gfni(rss_key_matrixes, (uint8_t *)arr, size);
     362                 :            : 
     363         [ #  # ]:          0 :         if (hash_1 != hash_2)
     364                 :          0 :                 return -TEST_FAILED;
     365                 :            : 
     366                 :            :         return TEST_SUCCESS;
     367                 :            : }
     368                 :            : 
     369                 :            : static int
     370                 :          1 : test_create_invalid(void)
     371                 :            : {
     372                 :            :         struct rte_thash_ctx *ctx;
     373                 :            :         int key_len = 40;
     374                 :            :         int reta_sz = 7;
     375                 :            : 
     376                 :          1 :         ctx = rte_thash_init_ctx(NULL, key_len, reta_sz, NULL, 0);
     377         [ -  + ]:          1 :         RTE_TEST_ASSERT(ctx == NULL,
     378                 :            :                 "Call succeeded with invalid parameters\n");
     379                 :            : 
     380                 :          1 :         ctx = rte_thash_init_ctx("test", 0, reta_sz, NULL, 0);
     381         [ -  + ]:          1 :         RTE_TEST_ASSERT(ctx == NULL,
     382                 :            :                 "Call succeeded with invalid parameters\n");
     383                 :            : 
     384                 :          1 :         ctx = rte_thash_init_ctx(NULL, key_len, 1, NULL, 0);
     385         [ -  + ]:          1 :         RTE_TEST_ASSERT(ctx == NULL,
     386                 :            :                 "Call succeeded with invalid parameters\n");
     387                 :            : 
     388                 :          1 :         ctx = rte_thash_init_ctx(NULL, key_len, 17, NULL, 0);
     389         [ -  + ]:          1 :         RTE_TEST_ASSERT(ctx == NULL,
     390                 :            :                 "Call succeeded with invalid parameters\n");
     391                 :            : 
     392                 :            :         return TEST_SUCCESS;
     393                 :            : }
     394                 :            : 
     395                 :            : static int
     396                 :          1 : test_multiple_create(void)
     397                 :            : {
     398                 :            :         struct rte_thash_ctx *ctx;
     399                 :            :         int key_len = 40;
     400                 :            :         int reta_sz = 7;
     401                 :            :         int i;
     402                 :            : 
     403         [ +  + ]:        101 :         for (i = 0; i < 100; i++) {
     404                 :        100 :                 ctx = rte_thash_init_ctx("test", key_len, reta_sz, NULL, 0);
     405         [ -  + ]:        100 :                 RTE_TEST_ASSERT(ctx != NULL, "Can not create CTX\n");
     406                 :            : 
     407                 :        100 :                 rte_thash_free_ctx(ctx);
     408                 :            :         }
     409                 :            : 
     410                 :            :         return TEST_SUCCESS;
     411                 :            : }
     412                 :            : 
     413                 :            : static int
     414                 :          1 : test_free_null(void)
     415                 :            : {
     416                 :            :         struct rte_thash_ctx *ctx;
     417                 :            : 
     418                 :          1 :         ctx = rte_thash_init_ctx("test", 40, 7, NULL, 0);
     419         [ -  + ]:          1 :         RTE_TEST_ASSERT(ctx != NULL, "Can not create CTX\n");
     420                 :            : 
     421                 :          1 :         rte_thash_free_ctx(ctx);
     422                 :          1 :         rte_thash_free_ctx(NULL);
     423                 :            : 
     424                 :          1 :         return TEST_SUCCESS;
     425                 :            : }
     426                 :            : 
     427                 :            : static int
     428                 :          1 : test_add_invalid_helper(void)
     429                 :            : {
     430                 :            :         struct rte_thash_ctx *ctx;
     431                 :            :         const int key_len = 40;
     432                 :            :         int reta_sz = 7;
     433                 :            :         int ret;
     434                 :            : 
     435                 :          1 :         ctx = rte_thash_init_ctx("test", key_len, reta_sz, NULL, 0);
     436         [ -  + ]:          1 :         RTE_TEST_ASSERT(ctx != NULL, "can not create thash ctx\n");
     437                 :            : 
     438                 :          1 :         ret = rte_thash_add_helper(NULL, "test", reta_sz, 0);
     439         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret == -EINVAL,
     440                 :            :                 "Call succeeded with invalid parameters\n");
     441                 :            : 
     442                 :          1 :         ret = rte_thash_add_helper(ctx, NULL, reta_sz, 0);
     443         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret == -EINVAL,
     444                 :            :                 "Call succeeded with invalid parameters\n");
     445                 :            : 
     446                 :          1 :         ret = rte_thash_add_helper(ctx, "test", reta_sz - 1, 0);
     447         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret == -EINVAL,
     448                 :            :                 "Call succeeded with invalid parameters\n");
     449                 :            : 
     450                 :          1 :         ret = rte_thash_add_helper(ctx, "test", reta_sz, key_len * 8);
     451         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret == -EINVAL,
     452                 :            :                 "Call succeeded with invalid parameters\n");
     453                 :            : 
     454                 :          1 :         ret = rte_thash_add_helper(ctx, "first_range", reta_sz, 0);
     455         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret == 0, "Can not create helper\n");
     456                 :            : 
     457                 :          1 :         ret = rte_thash_add_helper(ctx, "first_range", reta_sz, 0);
     458         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret == -EEXIST,
     459                 :            :                 "Call succeeded with duplicated name\n");
     460                 :            : 
     461                 :            :         /*
     462                 :            :          * Create second helper with offset 3 * reta_sz.
     463                 :            :          * Note first_range helper created range in key:
     464                 :            :          * [0, 32 + length{= reta_sz} - 1), i.e [0, 37).
     465                 :            :          * second range is [44, 81)
     466                 :            :          */
     467                 :          1 :         ret = rte_thash_add_helper(ctx, "second_range", reta_sz,
     468                 :            :                 32 +  2 * reta_sz);
     469         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret == 0, "Can not create helper\n");
     470                 :            : 
     471                 :            :         /*
     472                 :            :          * Try to create overlapping with first_ and second_ ranges,
     473                 :            :          * i.e. [6, 49)
     474                 :            :          */
     475                 :          1 :         ret = rte_thash_add_helper(ctx, "third_range", 2 * reta_sz, reta_sz);
     476         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret == -EEXIST,
     477                 :            :                 "Call succeeded with overlapping ranges\n");
     478                 :            : 
     479                 :          1 :         rte_thash_free_ctx(ctx);
     480                 :            : 
     481                 :          1 :         return TEST_SUCCESS;
     482                 :            : }
     483                 :            : 
     484                 :            : static int
     485                 :          1 : test_find_existing(void)
     486                 :            : {
     487                 :            :         struct rte_thash_ctx *ctx, *ret_ctx;
     488                 :            : 
     489                 :          1 :         ctx = rte_thash_init_ctx("test", 40, 7, NULL, 0);
     490         [ -  + ]:          1 :         RTE_TEST_ASSERT(ctx != NULL, "can not create thash ctx\n");
     491                 :            : 
     492                 :          1 :         ret_ctx = rte_thash_find_existing("test");
     493         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret_ctx != NULL, "can not find existing ctx\n");
     494                 :            : 
     495                 :          1 :         rte_thash_free_ctx(ctx);
     496                 :            : 
     497                 :          1 :         return TEST_SUCCESS;
     498                 :            : }
     499                 :            : 
     500                 :            : static int
     501                 :          1 : test_get_helper(void)
     502                 :            : {
     503                 :            :         struct rte_thash_ctx *ctx;
     504                 :            :         struct rte_thash_subtuple_helper *h;
     505                 :            :         int ret;
     506                 :            : 
     507                 :          1 :         ctx = rte_thash_init_ctx("test", 40, 7, NULL, 0);
     508         [ -  + ]:          1 :         RTE_TEST_ASSERT(ctx != NULL, "Can not create thash ctx\n");
     509                 :            : 
     510                 :          1 :         h = rte_thash_get_helper(NULL, "first_range");
     511         [ -  + ]:          1 :         RTE_TEST_ASSERT(h == NULL, "Call succeeded with invalid parameters\n");
     512                 :            : 
     513                 :          1 :         h = rte_thash_get_helper(ctx, NULL);
     514         [ -  + ]:          1 :         RTE_TEST_ASSERT(h == NULL, "Call succeeded with invalid parameters\n");
     515                 :            : 
     516                 :          1 :         ret = rte_thash_add_helper(ctx, "first_range", 8, 0);
     517         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret == 0, "Can not create helper\n");
     518                 :            : 
     519                 :          1 :         h = rte_thash_get_helper(ctx, "first_range");
     520         [ -  + ]:          1 :         RTE_TEST_ASSERT(h != NULL, "Can not find helper\n");
     521                 :            : 
     522                 :          1 :         rte_thash_free_ctx(ctx);
     523                 :            : 
     524                 :          1 :         return TEST_SUCCESS;
     525                 :            : }
     526                 :            : 
     527                 :            : static int
     528                 :          1 : test_period_overflow(void)
     529                 :            : {
     530                 :            :         struct rte_thash_ctx *ctx;
     531                 :            :         int reta_sz = 7; /* reflects polynomial degree */
     532                 :            :         int ret;
     533                 :            : 
     534                 :            :         /* first create without RTE_THASH_IGNORE_PERIOD_OVERFLOW flag */
     535                 :          1 :         ctx = rte_thash_init_ctx("test", 40, reta_sz, NULL, 0);
     536         [ -  + ]:          1 :         RTE_TEST_ASSERT(ctx != NULL, "Can not create thash ctx\n");
     537                 :            : 
     538                 :            :         /* requested range > (2^reta_sz) - 1 */
     539                 :          1 :         ret = rte_thash_add_helper(ctx, "test", (1 << reta_sz), 0);
     540         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret == -ENOSPC,
     541                 :            :                 "Call succeeded with invalid parameters\n");
     542                 :            : 
     543                 :            :         /* requested range == len + 32 - 1, smaller than (2^reta_sz) - 1 */
     544                 :          1 :         ret = rte_thash_add_helper(ctx, "test", (1 << reta_sz) - 32, 0);
     545         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret == 0, "Can not create helper\n");
     546                 :            : 
     547                 :          1 :         rte_thash_free_ctx(ctx);
     548                 :            : 
     549                 :            :         /* create with RTE_THASH_IGNORE_PERIOD_OVERFLOW flag */
     550                 :          1 :         ctx = rte_thash_init_ctx("test", 40, reta_sz, NULL,
     551                 :            :                 RTE_THASH_IGNORE_PERIOD_OVERFLOW);
     552         [ -  + ]:          1 :         RTE_TEST_ASSERT(ctx != NULL, "Can not create thash ctx\n");
     553                 :            : 
     554                 :            :         /* requested range > (2^reta_sz - 1) */
     555                 :          1 :         ret = rte_thash_add_helper(ctx, "test", (1 << reta_sz) + 10, 0);
     556         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret == 0, "Can not create helper\n");
     557                 :            : 
     558                 :          1 :         rte_thash_free_ctx(ctx);
     559                 :            : 
     560                 :          1 :         return TEST_SUCCESS;
     561                 :            : }
     562                 :            : 
     563                 :            : static int
     564                 :          1 : test_predictable_rss_min_seq(void)
     565                 :          1 : {
     566                 :            :         struct rte_thash_ctx *ctx;
     567                 :            :         struct rte_thash_subtuple_helper *h;
     568                 :            :         const int key_len = 40;
     569                 :            :         int reta_sz = 6;
     570                 :          1 :         uint8_t initial_key[key_len];
     571                 :            :         const uint8_t *new_key;
     572                 :            :         int ret;
     573                 :            :         union rte_thash_tuple tuple;
     574                 :            :         uint32_t orig_hash, adj_hash, adj;
     575                 :            :         unsigned int desired_value = 27 & HASH_MSK(reta_sz);
     576                 :            :         uint16_t port_value = 22;
     577                 :            : 
     578                 :            :         memset(initial_key, 0, key_len);
     579                 :            : 
     580                 :          1 :         ctx = rte_thash_init_ctx("test", key_len, reta_sz, initial_key,
     581                 :            :                 RTE_THASH_MINIMAL_SEQ);
     582         [ -  + ]:          1 :         RTE_TEST_ASSERT(ctx != NULL, "can not create thash ctx\n");
     583                 :            : 
     584                 :          1 :         ret = rte_thash_add_helper(ctx, "snat", sizeof(uint16_t) * 8,
     585                 :            :                 offsetof(union rte_thash_tuple, v4.sport) * 8);
     586         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret == 0, "can not add helper, ret %d\n", ret);
     587                 :            : 
     588                 :          1 :         h = rte_thash_get_helper(ctx, "snat");
     589         [ -  + ]:          1 :         RTE_TEST_ASSERT(h != NULL, "can not find helper\n");
     590                 :            : 
     591                 :          1 :         new_key = rte_thash_get_key(ctx);
     592                 :          1 :         tuple.v4.src_addr = RTE_IPV4(0, 0, 0, 0);
     593                 :          1 :         tuple.v4.dst_addr = RTE_IPV4(0, 0, 0, 0);
     594                 :            :         tuple.v4.sport = 0;
     595                 :            :         tuple.v4.sport = rte_cpu_to_be_16(port_value);
     596                 :            :         tuple.v4.dport = 0;
     597                 :          1 :         tuple.v4.sctp_tag = rte_be_to_cpu_32(tuple.v4.sctp_tag);
     598                 :            : 
     599                 :          1 :         orig_hash = rte_softrss((uint32_t *)&tuple,
     600                 :            :                 RTE_THASH_V4_L4_LEN, new_key);
     601                 :          1 :         adj = rte_thash_get_complement(h, orig_hash, desired_value);
     602                 :            : 
     603         [ +  - ]:          1 :         tuple.v4.sctp_tag = rte_cpu_to_be_32(tuple.v4.sctp_tag);
     604         [ -  + ]:          1 :         tuple.v4.sport ^= rte_cpu_to_be_16(adj);
     605         [ -  + ]:          1 :         tuple.v4.sctp_tag = rte_be_to_cpu_32(tuple.v4.sctp_tag);
     606                 :            : 
     607                 :          1 :         adj_hash = rte_softrss((uint32_t *)&tuple,
     608                 :            :                 RTE_THASH_V4_L4_LEN, new_key);
     609         [ -  + ]:          1 :         RTE_TEST_ASSERT((adj_hash & HASH_MSK(reta_sz)) ==
     610                 :            :                 desired_value, "bad desired value\n");
     611                 :            : 
     612                 :          1 :         rte_thash_free_ctx(ctx);
     613                 :            : 
     614                 :          1 :         return TEST_SUCCESS;
     615                 :            : }
     616                 :            : 
     617                 :            : /*
     618                 :            :  * This test creates 7 subranges in the following order:
     619                 :            :  * range_one    = [56, 95),     len = 8, offset = 56
     620                 :            :  * range_two    = [64, 103),    len = 8, offset = 64
     621                 :            :  * range_three  = [120, 159),   len = 8, offset = 120
     622                 :            :  * range_four   = [48, 87),     len = 8, offset = 48
     623                 :            :  * range_five   = [57, 95),     len = 7, offset = 57
     624                 :            :  * range_six    = [40, 111),    len = 40, offset = 40
     625                 :            :  * range_seven  = [0, 39),      len = 8, offset = 0
     626                 :            :  */
     627                 :            : struct range {
     628                 :            :         const char *name;
     629                 :            :         int len;
     630                 :            :         int offset;
     631                 :            :         int byte_idx;
     632                 :            : };
     633                 :            : 
     634                 :            : struct range rng_arr[] = {
     635                 :            :         {"one",   8,  56,  7},
     636                 :            :         {"two",   8,  64,  8},
     637                 :            :         {"three", 8,  120, 15},
     638                 :            :         {"four",  8,  48,  6},
     639                 :            :         {"six",   40, 40,  9},
     640                 :            :         {"five",  7,  57,  7},
     641                 :            :         {"seven", 8,  0,   0}
     642                 :            : };
     643                 :            : 
     644                 :            : static int
     645                 :          1 : test_predictable_rss_multirange(void)
     646                 :            : {
     647                 :            :         struct rte_thash_ctx *ctx;
     648                 :            :         struct rte_thash_subtuple_helper *h[RTE_DIM(rng_arr)];
     649                 :            :         const uint8_t *new_key;
     650                 :            :         const int key_len = 40;
     651                 :            :         int reta_sz = 7;
     652                 :            :         unsigned int i, j, k;
     653                 :            :         int ret;
     654                 :          1 :         uint32_t desired_value = rte_rand() & HASH_MSK(reta_sz);
     655                 :          1 :         uint8_t tuples[RTE_DIM(rng_arr)][16] = { {0} };
     656                 :            :         uint32_t *ptr;
     657                 :            :         uint32_t hashes[RTE_DIM(rng_arr)];
     658                 :            :         uint32_t adj_hashes[RTE_DIM(rng_arr)];
     659                 :            :         uint32_t adj;
     660                 :            : 
     661                 :          1 :         ctx = rte_thash_init_ctx("test", key_len, reta_sz, NULL, 0);
     662         [ -  + ]:          1 :         RTE_TEST_ASSERT(ctx != NULL, "can not create thash ctx\n");
     663                 :            : 
     664         [ +  + ]:          8 :         for (i = 0; i < RTE_DIM(rng_arr); i++) {
     665                 :          7 :                 ret = rte_thash_add_helper(ctx, rng_arr[i].name,
     666                 :          7 :                         rng_arr[i].len, rng_arr[i].offset);
     667         [ -  + ]:          7 :                 RTE_TEST_ASSERT(ret == 0, "can not add helper\n");
     668                 :            : 
     669                 :          7 :                 h[i] = rte_thash_get_helper(ctx, rng_arr[i].name);
     670         [ -  + ]:          7 :                 RTE_TEST_ASSERT(h[i] != NULL, "can not find helper\n");
     671                 :            :         }
     672                 :          1 :         new_key = rte_thash_get_key(ctx);
     673                 :            : 
     674                 :            :         /*
     675                 :            :          * calculate hashes, complements, then adjust keys with
     676                 :            :          * complements and recalculate hashes
     677                 :            :          */
     678         [ +  + ]:          8 :         for (i = 0; i < RTE_DIM(rng_arr); i++) {
     679         [ +  + ]:        707 :                 for (k = 0; k < 100; k++) {
     680                 :            :                         /* init with random keys */
     681                 :        700 :                         ptr = (uint32_t *)&tuples[i][0];
     682         [ +  + ]:       3500 :                         for (j = 0; j < 4; j++)
     683                 :       2800 :                                 ptr[j] = rte_rand();
     684                 :            :                         /* convert keys from BE to CPU byte order */
     685         [ +  + ]:       3500 :                         for (j = 0; j < 4; j++)
     686         [ -  + ]:       5600 :                                 ptr[j] = rte_be_to_cpu_32(ptr[j]);
     687                 :            : 
     688                 :        700 :                         hashes[i] = rte_softrss(ptr, 4, new_key);
     689                 :        700 :                         adj = rte_thash_get_complement(h[i], hashes[i],
     690                 :            :                                 desired_value);
     691                 :            :                         /* convert back to BE to adjust the value */
     692         [ +  + ]:       3500 :                         for (j = 0; j < 4; j++)
     693         [ -  + ]:       5600 :                                 ptr[j] = rte_cpu_to_be_32(ptr[j]);
     694                 :            : 
     695                 :        700 :                         tuples[i][rng_arr[i].byte_idx] ^= adj;
     696                 :            : 
     697         [ +  + ]:       3500 :                         for (j = 0; j < 4; j++)
     698         [ -  + ]:       5600 :                                 ptr[j] = rte_be_to_cpu_32(ptr[j]);
     699                 :            : 
     700                 :        700 :                         adj_hashes[i] = rte_softrss(ptr, 4, new_key);
     701         [ -  + ]:        700 :                         RTE_TEST_ASSERT((adj_hashes[i] & HASH_MSK(reta_sz)) ==
     702                 :            :                                 desired_value,
     703                 :            :                                 "bad desired value for %d tuple\n", i);
     704                 :            :                 }
     705                 :            :         }
     706                 :            : 
     707                 :          1 :         rte_thash_free_ctx(ctx);
     708                 :            : 
     709                 :          1 :         return TEST_SUCCESS;
     710                 :            : }
     711                 :            : 
     712                 :            : static int
     713                 :          3 : cmp_tuple_eq(void *userdata, uint8_t *tuple)
     714                 :            : {
     715                 :          3 :         return memcmp(userdata, tuple, TUPLE_SZ);
     716                 :            : }
     717                 :            : 
     718                 :            : static int
     719                 :          1 : test_adjust_tuple(void)
     720                 :            : {
     721                 :            :         struct rte_thash_ctx *ctx;
     722                 :            :         struct rte_thash_subtuple_helper *h;
     723                 :            :         const int key_len = 40;
     724                 :            :         const uint8_t *new_key;
     725                 :            :         uint8_t tuple[TUPLE_SZ];
     726                 :            :         uint32_t tmp_tuple[TUPLE_SZ / sizeof(uint32_t)];
     727                 :            :         uint32_t tuple_copy[TUPLE_SZ / sizeof(uint32_t)];
     728                 :            :         uint32_t hash;
     729                 :            :         int reta_sz = CHAR_BIT;
     730                 :            :         int ret;
     731                 :          1 :         unsigned int i, desired_value = rte_rand() & HASH_MSK(reta_sz);
     732                 :            : 
     733                 :            :         memset(tuple, 0xab, TUPLE_SZ);
     734                 :            : 
     735                 :          1 :         ctx = rte_thash_init_ctx("test", key_len, reta_sz, NULL, 0);
     736         [ -  + ]:          1 :         RTE_TEST_ASSERT(ctx != NULL, "can not create thash ctx\n");
     737                 :            : 
     738                 :            :         /*
     739                 :            :          * set offset to be in the middle of a byte
     740                 :            :          * set size of the subtuple to be 2 * rets_sz
     741                 :            :          * to have the room for random bits
     742                 :            :          */
     743                 :          1 :         ret = rte_thash_add_helper(ctx, "test", reta_sz * 2,
     744                 :            :                 (5 * CHAR_BIT) + 4);
     745         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret == 0, "can not add helper, ret %d\n", ret);
     746                 :            : 
     747                 :          1 :         new_key = rte_thash_get_key(ctx);
     748                 :            : 
     749                 :          1 :         h = rte_thash_get_helper(ctx, "test");
     750         [ -  + ]:          1 :         RTE_TEST_ASSERT(h != NULL, "can not find helper\n");
     751                 :            : 
     752                 :          1 :         ret = rte_thash_adjust_tuple(ctx, h, tuple, TUPLE_SZ, desired_value,
     753                 :            :                 1, NULL, NULL);
     754         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret == 0, "can not adjust tuple, ret %d\n", ret);
     755                 :            : 
     756         [ +  + ]:          4 :         for (i = 0; i < (TUPLE_SZ / 4); i++)
     757                 :          3 :                 tmp_tuple[i] =
     758         [ -  + ]:          3 :                         rte_be_to_cpu_32(*(uint32_t *)&tuple[i * 4]);
     759                 :            : 
     760                 :          1 :         hash = rte_softrss(tmp_tuple, TUPLE_SZ / 4, new_key);
     761         [ -  + ]:          1 :         RTE_TEST_ASSERT((hash & HASH_MSK(reta_sz)) ==
     762                 :            :                 desired_value, "bad desired value\n");
     763                 :            : 
     764                 :            : 
     765                 :            :         /* Pass previously calculated tuple to callback function */
     766                 :            :         memcpy(tuple_copy, tuple, TUPLE_SZ);
     767                 :            : 
     768                 :            :         memset(tuple, 0xab, TUPLE_SZ);
     769                 :          1 :         ret = rte_thash_adjust_tuple(ctx, h, tuple, TUPLE_SZ, desired_value,
     770                 :            :                 1, cmp_tuple_eq, tuple_copy);
     771         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret == -EEXIST,
     772                 :            :                 "adjust tuple didn't indicate collision\n");
     773                 :            : 
     774                 :            :         /*
     775                 :            :          * Make the function to generate random bits into subtuple
     776                 :            :          * after first adjustment attempt.
     777                 :            :          */
     778                 :            :         memset(tuple, 0xab, TUPLE_SZ);
     779                 :          1 :         ret = rte_thash_adjust_tuple(ctx, h, tuple, TUPLE_SZ, desired_value,
     780                 :            :                 2, cmp_tuple_eq, tuple_copy);
     781         [ -  + ]:          1 :         RTE_TEST_ASSERT(ret == 0, "can not adjust tuple, ret %d\n", ret);
     782                 :            : 
     783         [ +  + ]:          4 :         for (i = 0; i < (TUPLE_SZ / 4); i++)
     784                 :          3 :                 tmp_tuple[i] =
     785         [ -  + ]:          3 :                         rte_be_to_cpu_32(*(uint32_t *)&tuple[i * 4]);
     786                 :            : 
     787                 :          1 :         hash = rte_softrss(tmp_tuple, TUPLE_SZ / 4, new_key);
     788         [ -  + ]:          1 :         RTE_TEST_ASSERT((hash & HASH_MSK(reta_sz)) ==
     789                 :            :                 desired_value, "bad desired value\n");
     790                 :            : 
     791                 :          1 :         rte_thash_free_ctx(ctx);
     792                 :            : 
     793                 :          1 :         return TEST_SUCCESS;
     794                 :            : }
     795                 :            : 
     796                 :            : static uint32_t
     797                 :        180 : calc_tuple_hash(const uint8_t tuple[TUPLE_SZ], const uint8_t *key)
     798                 :            : {
     799                 :            :         uint32_t i, hash;
     800                 :            :         uint32_t tmp[TUPLE_SZ / sizeof(uint32_t)];
     801                 :            : 
     802         [ +  + ]:        720 :         for (i = 0; i < RTE_DIM(tmp); i++)
     803         [ -  + ]:       1080 :                 tmp[i] = rte_be_to_cpu_32(
     804                 :            :                         *(const uint32_t *)&tuple[i * sizeof(uint32_t)]);
     805                 :            : 
     806                 :        180 :         hash = rte_softrss(tmp, RTE_DIM(tmp), key);
     807                 :        180 :         return hash;
     808                 :            : }
     809                 :            : 
     810                 :            : static int
     811                 :        120 : check_adj_tuple(const uint8_t tuple[TUPLE_SZ], const uint8_t *key,
     812                 :            :                 uint32_t dhv, uint32_t ohv, uint32_t adjust, uint32_t reta_sz,
     813                 :            :                 const char *prefix)
     814                 :            : {
     815                 :            :         uint32_t hash, hashlsb;
     816                 :            : 
     817                 :        120 :         hash = calc_tuple_hash(tuple, key);
     818                 :        120 :         hashlsb = hash & HASH_MSK(reta_sz);
     819                 :            : 
     820                 :            :         printf("%s(%s) for tuple:\n", __func__, prefix);
     821                 :        120 :         rte_memdump(stdout, NULL, tuple, TUPLE_SZ);
     822                 :            :         printf("\treta_sz: %u,\n"
     823                 :            :                 "\torig hash: %#x,\n"
     824                 :            :                 "\tdesired: %#x,\n"
     825                 :            :                 "\tadjust: %#x,\n"
     826                 :            :                 "\tactual: %#x,\n",
     827                 :            :                reta_sz, ohv, dhv, adjust, hashlsb);
     828                 :            : 
     829         [ +  - ]:        120 :         if (dhv == hashlsb) {
     830                 :            :                 printf("\t***Succeeded\n");
     831                 :        120 :                 return 0;
     832                 :            :         }
     833                 :            : 
     834                 :            :         printf("\t***Failed\n");
     835                 :          0 :         return -1;
     836                 :            : }
     837                 :            : 
     838                 :            : static int
     839                 :         60 : test_adjust_tuple_mb(uint32_t reta_sz, uint32_t bofs)
     840                 :            : {
     841                 :            :         struct rte_thash_ctx *ctx;
     842                 :            :         struct rte_thash_subtuple_helper *h;
     843                 :            :         const int key_len = 40;
     844                 :            :         const uint8_t *new_key;
     845                 :            :         uint8_t orig_tuple[TUPLE_SZ];
     846                 :            :         uint8_t tuple_1[TUPLE_SZ];
     847                 :            :         uint8_t tuple_2[TUPLE_SZ];
     848                 :            :         uint32_t orig_hash;
     849                 :            :         int rc, ret;
     850                 :            :         uint32_t adj_bits;
     851                 :         60 :         unsigned int random = rte_rand();
     852                 :         60 :         unsigned int desired_value = random & HASH_MSK(reta_sz);
     853                 :            : 
     854                 :            :         const uint32_t h_offset = offsetof(union rte_thash_tuple, v4.dport) * CHAR_BIT;
     855                 :         60 :         const uint32_t h_size = sizeof(uint16_t) * CHAR_BIT - bofs;
     856                 :            : 
     857                 :            :         printf("===%s(reta_sz=%u,bofs=%u)===\n", __func__, reta_sz, bofs);
     858                 :            : 
     859                 :            :         memset(orig_tuple, 0xab, sizeof(orig_tuple));
     860                 :            : 
     861                 :         60 :         ctx = rte_thash_init_ctx("test", key_len, reta_sz, NULL, 0);
     862         [ -  + ]:         60 :         RTE_TEST_ASSERT(ctx != NULL, "can not create thash ctx\n");
     863                 :            : 
     864                 :         60 :         ret = rte_thash_add_helper(ctx, "test", h_size, h_offset);
     865         [ -  + ]:         60 :         RTE_TEST_ASSERT(ret == 0, "can not add helper, ret %d\n", ret);
     866                 :            : 
     867                 :         60 :         new_key = rte_thash_get_key(ctx);
     868                 :            : 
     869                 :         60 :         h = rte_thash_get_helper(ctx, "test");
     870                 :            : 
     871                 :         60 :         orig_hash = calc_tuple_hash(orig_tuple, new_key);
     872                 :            : 
     873                 :         60 :         adj_bits = rte_thash_get_complement(h, orig_hash, desired_value);
     874                 :            : 
     875                 :            :         /* use method #1, update tuple manually */
     876                 :            :         memcpy(tuple_1, orig_tuple, sizeof(tuple_1));
     877                 :            :         {
     878                 :            :                 uint16_t nv, ov, *p;
     879                 :            : 
     880                 :            :                 p = (uint16_t *)(tuple_1 + h_offset / CHAR_BIT);
     881                 :         60 :                 ov = p[0];
     882         [ -  + ]:         60 :                 nv = ov ^ rte_cpu_to_be_16(adj_bits << bofs);
     883                 :         60 :                 printf("%s#%d: ov=%#hx, nv=%#hx, adj=%#x;\n",
     884                 :            :                         __func__, __LINE__, ov, nv, adj_bits);
     885                 :         60 :                 p[0] = nv;
     886                 :            :         }
     887                 :            : 
     888                 :         60 :         rc = check_adj_tuple(tuple_1, new_key, desired_value, orig_hash,
     889                 :            :                 adj_bits, reta_sz, "method #1");
     890                 :            :         if (h_offset % CHAR_BIT == 0)
     891                 :         60 :                 ret |= rc;
     892                 :            : 
     893                 :            :         /* use method #2, use library function to adjust tuple */
     894                 :            :         memcpy(tuple_2, orig_tuple, sizeof(tuple_2));
     895                 :            : 
     896                 :         60 :         rte_thash_adjust_tuple(ctx, h, tuple_2, sizeof(tuple_2),
     897                 :            :                 desired_value, 1, NULL, NULL);
     898                 :         60 :         ret |= check_adj_tuple(tuple_2, new_key, desired_value, orig_hash,
     899                 :            :                 adj_bits, reta_sz, "method #2");
     900                 :            : 
     901                 :         60 :         rte_thash_free_ctx(ctx);
     902                 :            : 
     903                 :         60 :         ret |= memcmp(tuple_1, tuple_2, sizeof(tuple_1));
     904                 :            : 
     905                 :            :         printf("%s EXIT=======\n", __func__);
     906                 :         60 :         return ret;
     907                 :            : }
     908                 :            : 
     909                 :            : static int
     910                 :          1 : test_adjust_tuple_mult_reta(void)
     911                 :            : {
     912                 :            :         uint32_t i, j, np, nt;
     913                 :            : 
     914                 :            :         nt = 0, np = 0;
     915         [ +  + ]:          9 :         for (i = 0; i < CHAR_BIT; i++) {
     916         [ +  + ]:         68 :                 for (j = 6; j <= RTE_THASH_RETA_SZ_MAX - i; j++) {
     917                 :         60 :                         np += (test_adjust_tuple_mb(j, i) == 0);
     918                 :         60 :                         nt++;
     919                 :            :                 }
     920                 :            :         }
     921                 :            : 
     922                 :            :         printf("%s: tests executed: %u, test passed: %u\n", __func__, nt, np);
     923         [ -  + ]:          1 :         RTE_TEST_ASSERT(nt == np, "%u subtests failed", nt - np);
     924                 :            :         return TEST_SUCCESS;
     925                 :            : }
     926                 :            : 
     927                 :            : #define RETA_SZ_LOG             11
     928                 :            : #define RSS_KEY_SZ              40
     929                 :            : #define RETA_SZ                 (1 << RETA_SZ_LOG)
     930                 :            : #define NB_HASH_ITER    RETA_SZ
     931                 :            : #define NB_TEST_ITER    10
     932                 :            : 
     933                 :            : static inline void
     934                 :         30 : run_hash_calc_loop(uint8_t *key, union rte_thash_tuple *tuple,
     935                 :            :                                         unsigned int *rss_reta_hits)
     936                 :            : {
     937                 :            :         uint32_t rss_hash;
     938                 :            :         int i;
     939                 :            : 
     940         [ +  + ]:      61470 :         for (i = 0; i < NB_HASH_ITER; i++) {
     941                 :            :                 /* variable part starts from the most significant bit */
     942                 :      61440 :                 tuple->v4.dport = (i << (sizeof(tuple->v4.dport) * CHAR_BIT -
     943                 :            :                         RETA_SZ_LOG));
     944                 :            :                 /*
     945                 :            :                  * swap sport and dport on LE arch since rte_softrss()
     946                 :            :                  * works with host byte order uint32_t values
     947                 :            :                  */
     948         [ -  + ]:      61440 :                 tuple->v4.dport = rte_cpu_to_be_16(tuple->v4.dport);
     949         [ -  + ]:      61440 :                 tuple->v4.sctp_tag = rte_be_to_cpu_32(tuple->v4.sctp_tag);
     950                 :      61440 :                 rss_hash = rte_softrss((uint32_t *)tuple,
     951                 :            :                                 RTE_THASH_V4_L4_LEN, key);
     952                 :            :                 /* unroll swap, required only for sport */
     953         [ -  + ]:      61440 :                 tuple->v4.sctp_tag = rte_cpu_to_be_32(tuple->v4.sctp_tag);
     954                 :      61440 :                 rss_reta_hits[rss_hash & (RETA_SZ - 1)]++;
     955                 :            :         }
     956                 :         30 : }
     957                 :            : 
     958                 :            : static int
     959                 :         10 : hash_calc_iteration(unsigned int *min_before, unsigned int *max_before,
     960                 :            :                 unsigned int *min_after, unsigned int *max_after,
     961                 :            :                 unsigned int *min_default, unsigned int *max_default)
     962                 :            : {
     963                 :         10 :         uint8_t key[RSS_KEY_SZ] = {0};
     964                 :            :         union rte_thash_tuple tuple;
     965                 :         10 :         unsigned int rss_reta_hits_before_adjust[RETA_SZ] = {0};
     966                 :         10 :         unsigned int rss_reta_hits_after_adjust[RETA_SZ] = {0};
     967                 :         10 :         unsigned int rss_reta_hits_default_key[RETA_SZ] = {0};
     968                 :            :         int i;
     969                 :            : 
     970         [ +  + ]:        410 :         for (i = 0; i < RSS_KEY_SZ; i++)
     971                 :        400 :                 key[i] = rte_rand();
     972                 :            : 
     973                 :         10 :         tuple.v4.src_addr = rte_rand();
     974                 :         10 :         tuple.v4.dst_addr = rte_rand();
     975                 :         10 :         tuple.v4.sport = rte_rand();
     976                 :            : 
     977                 :         10 :         run_hash_calc_loop(key, &tuple, rss_reta_hits_before_adjust);
     978                 :            : 
     979                 :         10 :         int ret = rte_thash_gen_key(key, RSS_KEY_SZ, RETA_SZ_LOG,
     980                 :            :                 offsetof(union rte_thash_tuple, v4.dport)*CHAR_BIT,
     981                 :            :                 RETA_SZ_LOG);
     982                 :            : 
     983         [ -  + ]:         10 :         if (ret) {
     984                 :            :                 printf("Can't generate key\n");
     985                 :          0 :                 return -1;
     986                 :            :         }
     987                 :            : 
     988                 :         10 :         run_hash_calc_loop(key, &tuple, rss_reta_hits_after_adjust);
     989                 :            : 
     990                 :         10 :         run_hash_calc_loop(default_rss_key, &tuple, rss_reta_hits_default_key);
     991                 :            : 
     992         [ +  + ]:      20490 :         for (i = 0; i < RETA_SZ; i++) {
     993                 :      20480 :                 *min_before = RTE_MIN(*min_before, rss_reta_hits_before_adjust[i]);
     994                 :      20480 :                 *max_before = RTE_MAX(*max_before, rss_reta_hits_before_adjust[i]);
     995                 :      20480 :                 *min_after = RTE_MIN(*min_after, rss_reta_hits_after_adjust[i]);
     996                 :      20480 :                 *max_after = RTE_MAX(*max_after, rss_reta_hits_after_adjust[i]);
     997                 :      20480 :                 *min_default = RTE_MIN(*min_default, rss_reta_hits_default_key[i]);
     998                 :      20480 :                 *max_default = RTE_MAX(*max_default, rss_reta_hits_default_key[i]);
     999                 :            :         }
    1000                 :            : 
    1001                 :            :         return 0;
    1002                 :            : }
    1003                 :            : 
    1004                 :            : static int
    1005                 :          1 : test_keygen(void)
    1006                 :            : {
    1007                 :            :         int i, ret;
    1008                 :          1 :         unsigned int min_before = UINT32_MAX;
    1009                 :          1 :         unsigned int min_after = UINT32_MAX;
    1010                 :          1 :         unsigned int min_default = UINT32_MAX;
    1011                 :          1 :         unsigned int max_before = 0;
    1012                 :          1 :         unsigned int max_after = 0;
    1013                 :          1 :         unsigned int max_default = 0;
    1014                 :            : 
    1015         [ +  + ]:         11 :         for (i = 0; i < NB_TEST_ITER; i++) {
    1016                 :            :                 /* calculates the worst distribution for each key */
    1017                 :         10 :                 ret = hash_calc_iteration(&min_before, &max_before, &min_after,
    1018                 :            :                         &max_after, &min_default, &max_default);
    1019         [ -  + ]:         10 :                 if (ret)
    1020                 :          0 :                         return ret;
    1021                 :            :         }
    1022                 :            : 
    1023                 :          1 :         printf("RSS before key adjustment: min=%d, max=%d\n",
    1024                 :            :                 min_before, max_before);
    1025                 :          1 :         printf("RSS after key adjustment: min=%d, max=%d\n",
    1026                 :            :                 min_after, max_after);
    1027                 :          1 :         printf("RSS default key: min=%d, max=%d\n",
    1028                 :            :                 min_default, max_default);
    1029                 :            : 
    1030                 :          1 :         return TEST_SUCCESS;
    1031                 :            : }
    1032                 :            : 
    1033                 :            : static struct unit_test_suite thash_tests = {
    1034                 :            :         .suite_name = "thash autotest",
    1035                 :            :         .setup = NULL,
    1036                 :            :         .teardown = NULL,
    1037                 :            :         .unit_test_cases = {
    1038                 :            :         TEST_CASE(test_toeplitz_hash_calc),
    1039                 :            :         TEST_CASE(test_toeplitz_hash_gfni),
    1040                 :            :         TEST_CASE(test_toeplitz_hash_rand_data),
    1041                 :            :         TEST_CASE(test_toeplitz_hash_gfni_bulk),
    1042                 :            :         TEST_CASE(test_big_tuple_gfni),
    1043                 :            :         TEST_CASE(test_create_invalid),
    1044                 :            :         TEST_CASE(test_multiple_create),
    1045                 :            :         TEST_CASE(test_free_null),
    1046                 :            :         TEST_CASE(test_add_invalid_helper),
    1047                 :            :         TEST_CASE(test_find_existing),
    1048                 :            :         TEST_CASE(test_get_helper),
    1049                 :            :         TEST_CASE(test_period_overflow),
    1050                 :            :         TEST_CASE(test_predictable_rss_min_seq),
    1051                 :            :         TEST_CASE(test_predictable_rss_multirange),
    1052                 :            :         TEST_CASE(test_adjust_tuple),
    1053                 :            :         TEST_CASE(test_adjust_tuple_mult_reta),
    1054                 :            :         TEST_CASE(test_keygen),
    1055                 :            :         TEST_CASES_END()
    1056                 :            :         }
    1057                 :            : };
    1058                 :            : 
    1059                 :            : static int
    1060                 :          1 : test_thash(void)
    1061                 :            : {
    1062                 :          1 :         return unit_test_suite_runner(&thash_tests);
    1063                 :            : }
    1064                 :            : 
    1065                 :        251 : REGISTER_FAST_TEST(thash_autotest, true, true, test_thash);

Generated by: LCOV version 1.14