1*4418919fSjohnjiang /* SPDX-License-Identifier: BSD-3-Clause 2*4418919fSjohnjiang * Copyright(c) 2017 Intel Corporation 3*4418919fSjohnjiang */ 4*4418919fSjohnjiang 5*4418919fSjohnjiang /* This test is for membership library's simple feature test */ 6*4418919fSjohnjiang 7*4418919fSjohnjiang #include <rte_memcpy.h> 8*4418919fSjohnjiang #include <rte_malloc.h> 9*4418919fSjohnjiang #include <rte_member.h> 10*4418919fSjohnjiang #include <rte_byteorder.h> 11*4418919fSjohnjiang #include <rte_random.h> 12*4418919fSjohnjiang #include <rte_debug.h> 13*4418919fSjohnjiang #include <rte_ip.h> 14*4418919fSjohnjiang 15*4418919fSjohnjiang #include "test.h" 16*4418919fSjohnjiang 17*4418919fSjohnjiang struct rte_member_setsum *setsum_ht; 18*4418919fSjohnjiang struct rte_member_setsum *setsum_cache; 19*4418919fSjohnjiang struct rte_member_setsum *setsum_vbf; 20*4418919fSjohnjiang 21*4418919fSjohnjiang /* 5-tuple key type */ 22*4418919fSjohnjiang struct flow_key { 23*4418919fSjohnjiang uint32_t ip_src; 24*4418919fSjohnjiang uint32_t ip_dst; 25*4418919fSjohnjiang uint16_t port_src; 26*4418919fSjohnjiang uint16_t port_dst; 27*4418919fSjohnjiang uint8_t proto; 28*4418919fSjohnjiang } __attribute__((packed)); 29*4418919fSjohnjiang 30*4418919fSjohnjiang /* Set ID Macros for multimatch test usage */ 31*4418919fSjohnjiang #define M_MATCH_S 1 /* Not start with 0 since by default 0 means no match */ 32*4418919fSjohnjiang #define M_MATCH_E 15 33*4418919fSjohnjiang #define M_MATCH_STEP 2 34*4418919fSjohnjiang #define M_MATCH_CNT \ 35*4418919fSjohnjiang (1 + (M_MATCH_E - M_MATCH_S) / M_MATCH_STEP) 36*4418919fSjohnjiang 37*4418919fSjohnjiang 38*4418919fSjohnjiang #define NUM_SAMPLES 5 39*4418919fSjohnjiang #define MAX_MATCH 32 40*4418919fSjohnjiang 41*4418919fSjohnjiang /* Keys used by unit test functions */ 42*4418919fSjohnjiang static struct flow_key keys[NUM_SAMPLES] = { 43*4418919fSjohnjiang { 44*4418919fSjohnjiang .ip_src = RTE_IPV4(0x03, 0x02, 0x01, 0x00), 45*4418919fSjohnjiang .ip_dst = RTE_IPV4(0x07, 0x06, 0x05, 0x04), 46*4418919fSjohnjiang .port_src = 0x0908, 47*4418919fSjohnjiang .port_dst = 0x0b0a, 48*4418919fSjohnjiang .proto = 0x0c, 49*4418919fSjohnjiang }, 50*4418919fSjohnjiang { 51*4418919fSjohnjiang .ip_src = RTE_IPV4(0x13, 0x12, 0x11, 0x10), 52*4418919fSjohnjiang .ip_dst = RTE_IPV4(0x17, 0x16, 0x15, 0x14), 53*4418919fSjohnjiang .port_src = 0x1918, 54*4418919fSjohnjiang .port_dst = 0x1b1a, 55*4418919fSjohnjiang .proto = 0x1c, 56*4418919fSjohnjiang }, 57*4418919fSjohnjiang { 58*4418919fSjohnjiang .ip_src = RTE_IPV4(0x23, 0x22, 0x21, 0x20), 59*4418919fSjohnjiang .ip_dst = RTE_IPV4(0x27, 0x26, 0x25, 0x24), 60*4418919fSjohnjiang .port_src = 0x2928, 61*4418919fSjohnjiang .port_dst = 0x2b2a, 62*4418919fSjohnjiang .proto = 0x2c, 63*4418919fSjohnjiang }, 64*4418919fSjohnjiang { 65*4418919fSjohnjiang .ip_src = RTE_IPV4(0x33, 0x32, 0x31, 0x30), 66*4418919fSjohnjiang .ip_dst = RTE_IPV4(0x37, 0x36, 0x35, 0x34), 67*4418919fSjohnjiang .port_src = 0x3938, 68*4418919fSjohnjiang .port_dst = 0x3b3a, 69*4418919fSjohnjiang .proto = 0x3c, 70*4418919fSjohnjiang }, 71*4418919fSjohnjiang { 72*4418919fSjohnjiang .ip_src = RTE_IPV4(0x43, 0x42, 0x41, 0x40), 73*4418919fSjohnjiang .ip_dst = RTE_IPV4(0x47, 0x46, 0x45, 0x44), 74*4418919fSjohnjiang .port_src = 0x4948, 75*4418919fSjohnjiang .port_dst = 0x4b4a, 76*4418919fSjohnjiang .proto = 0x4c, 77*4418919fSjohnjiang } 78*4418919fSjohnjiang }; 79*4418919fSjohnjiang 80*4418919fSjohnjiang uint32_t test_set[NUM_SAMPLES] = {1, 2, 3, 4, 5}; 81*4418919fSjohnjiang 82*4418919fSjohnjiang #define ITERATIONS 3 83*4418919fSjohnjiang #define KEY_SIZE 4 84*4418919fSjohnjiang 85*4418919fSjohnjiang #define MAX_ENTRIES (1 << 16) 86*4418919fSjohnjiang uint8_t generated_keys[MAX_ENTRIES][KEY_SIZE]; 87*4418919fSjohnjiang 88*4418919fSjohnjiang static struct rte_member_parameters params = { 89*4418919fSjohnjiang .num_keys = MAX_ENTRIES, /* Total hash table entries. */ 90*4418919fSjohnjiang .key_len = KEY_SIZE, /* Length of hash key. */ 91*4418919fSjohnjiang 92*4418919fSjohnjiang /* num_set and false_positive_rate only relevant to vBF */ 93*4418919fSjohnjiang .num_set = 16, 94*4418919fSjohnjiang .false_positive_rate = 0.03, 95*4418919fSjohnjiang .prim_hash_seed = 1, 96*4418919fSjohnjiang .sec_hash_seed = 11, 97*4418919fSjohnjiang .socket_id = 0 /* NUMA Socket ID for memory. */ 98*4418919fSjohnjiang }; 99*4418919fSjohnjiang 100*4418919fSjohnjiang /* 101*4418919fSjohnjiang * Sequence of operations for find existing setsummary 102*4418919fSjohnjiang * 103*4418919fSjohnjiang * - create setsum 104*4418919fSjohnjiang * - find existing setsum: hit 105*4418919fSjohnjiang * - find non-existing setsum: miss 106*4418919fSjohnjiang * 107*4418919fSjohnjiang */ 108*4418919fSjohnjiang static int 109*4418919fSjohnjiang test_member_find_existing(void) 110*4418919fSjohnjiang { 111*4418919fSjohnjiang struct rte_member_setsum *tmp_setsum = NULL, *result = NULL; 112*4418919fSjohnjiang struct rte_member_parameters tmp_params = { 113*4418919fSjohnjiang .name = "member_find_existing", 114*4418919fSjohnjiang .num_keys = MAX_ENTRIES, /* Total hash table entries. */ 115*4418919fSjohnjiang .key_len = KEY_SIZE, /* Length of hash key. */ 116*4418919fSjohnjiang .type = RTE_MEMBER_TYPE_HT, 117*4418919fSjohnjiang .num_set = 32, 118*4418919fSjohnjiang .false_positive_rate = 0.03, 119*4418919fSjohnjiang .prim_hash_seed = 1, 120*4418919fSjohnjiang .sec_hash_seed = 11, 121*4418919fSjohnjiang .socket_id = 0 /* NUMA Socket ID for memory. */ 122*4418919fSjohnjiang }; 123*4418919fSjohnjiang 124*4418919fSjohnjiang /* Create */ 125*4418919fSjohnjiang tmp_setsum = rte_member_create(&tmp_params); 126*4418919fSjohnjiang TEST_ASSERT(tmp_setsum != NULL, "setsum creation failed"); 127*4418919fSjohnjiang 128*4418919fSjohnjiang /* Try to find existing hash table */ 129*4418919fSjohnjiang result = rte_member_find_existing("member_find_existing"); 130*4418919fSjohnjiang TEST_ASSERT(result == tmp_setsum, "could not find existing setsum"); 131*4418919fSjohnjiang 132*4418919fSjohnjiang /* Try to find non-existing hash table */ 133*4418919fSjohnjiang result = rte_member_find_existing("member_find_non_existing"); 134*4418919fSjohnjiang TEST_ASSERT(result == NULL, "found setsum that shouldn't exist"); 135*4418919fSjohnjiang 136*4418919fSjohnjiang /* Cleanup. */ 137*4418919fSjohnjiang rte_member_free(tmp_setsum); 138*4418919fSjohnjiang 139*4418919fSjohnjiang return 0; 140*4418919fSjohnjiang } 141*4418919fSjohnjiang 142*4418919fSjohnjiang /* 143*4418919fSjohnjiang * Test for bad creating parameters 144*4418919fSjohnjiang */ 145*4418919fSjohnjiang static int 146*4418919fSjohnjiang test_member_create_bad_param(void) 147*4418919fSjohnjiang { 148*4418919fSjohnjiang struct rte_member_setsum *bad_setsum = NULL; 149*4418919fSjohnjiang struct rte_member_parameters bad_params = { 150*4418919fSjohnjiang .num_keys = MAX_ENTRIES, /* Total hash table entries. */ 151*4418919fSjohnjiang .key_len = KEY_SIZE, /* Length of hash key. */ 152*4418919fSjohnjiang .type = RTE_MEMBER_TYPE_HT, 153*4418919fSjohnjiang .num_set = 32, 154*4418919fSjohnjiang .false_positive_rate = 0.03, 155*4418919fSjohnjiang .prim_hash_seed = 1, 156*4418919fSjohnjiang .sec_hash_seed = 11, 157*4418919fSjohnjiang .socket_id = 0 /* NUMA Socket ID for memory. */ 158*4418919fSjohnjiang }; 159*4418919fSjohnjiang 160*4418919fSjohnjiang printf("Expected error section begin...\n"); 161*4418919fSjohnjiang bad_params.name = "bad_param1"; 162*4418919fSjohnjiang bad_params.num_set = 0; 163*4418919fSjohnjiang bad_params.type = RTE_MEMBER_TYPE_VBF; 164*4418919fSjohnjiang /* Test with 0 set for vBF should fail */ 165*4418919fSjohnjiang bad_setsum = rte_member_create(&bad_params); 166*4418919fSjohnjiang if (bad_setsum != NULL) { 167*4418919fSjohnjiang rte_member_free(bad_setsum); 168*4418919fSjohnjiang printf("Impossible creating setsum successfully with invalid " 169*4418919fSjohnjiang "number of set for vBF\n"); 170*4418919fSjohnjiang return -1; 171*4418919fSjohnjiang } 172*4418919fSjohnjiang 173*4418919fSjohnjiang bad_params.name = "bad_param2"; 174*4418919fSjohnjiang bad_params.false_positive_rate = 0; 175*4418919fSjohnjiang bad_params.num_set = 32; 176*4418919fSjohnjiang /* Test with 0 false positive for vBF should fail */ 177*4418919fSjohnjiang bad_setsum = rte_member_create(&bad_params); 178*4418919fSjohnjiang if (bad_setsum != NULL) { 179*4418919fSjohnjiang rte_member_free(bad_setsum); 180*4418919fSjohnjiang printf("Impossible creating setsum successfully with invalid " 181*4418919fSjohnjiang "false positive rate for vBF\n"); 182*4418919fSjohnjiang return -1; 183*4418919fSjohnjiang } 184*4418919fSjohnjiang 185*4418919fSjohnjiang bad_params.name = "bad_param3"; 186*4418919fSjohnjiang bad_params.false_positive_rate = 0.03; 187*4418919fSjohnjiang bad_params.num_keys = 0; 188*4418919fSjohnjiang /* Test with 0 key per BF for vBF should fail */ 189*4418919fSjohnjiang bad_setsum = rte_member_create(&bad_params); 190*4418919fSjohnjiang if (bad_setsum != NULL) { 191*4418919fSjohnjiang rte_member_free(bad_setsum); 192*4418919fSjohnjiang printf("Impossible creating setsum successfully with invalid " 193*4418919fSjohnjiang "num_keys for vBF\n"); 194*4418919fSjohnjiang return -1; 195*4418919fSjohnjiang } 196*4418919fSjohnjiang 197*4418919fSjohnjiang bad_params.name = "bad_param4"; 198*4418919fSjohnjiang bad_params.type = RTE_MEMBER_TYPE_HT; 199*4418919fSjohnjiang bad_params.num_keys = RTE_MEMBER_BUCKET_ENTRIES / 2; 200*4418919fSjohnjiang /* Test with less than 1 bucket for HTSS should fail */ 201*4418919fSjohnjiang bad_setsum = rte_member_create(&bad_params); 202*4418919fSjohnjiang if (bad_setsum != NULL) { 203*4418919fSjohnjiang rte_member_free(bad_setsum); 204*4418919fSjohnjiang printf("Impossible creating setsum successfully with too few " 205*4418919fSjohnjiang "number of keys(entries) for HT\n"); 206*4418919fSjohnjiang return -1; 207*4418919fSjohnjiang } 208*4418919fSjohnjiang 209*4418919fSjohnjiang bad_params.name = "bad_param5"; 210*4418919fSjohnjiang bad_params.num_keys = RTE_MEMBER_ENTRIES_MAX + 1; 211*4418919fSjohnjiang /* Test with more than maximum entries for HTSS should fail */ 212*4418919fSjohnjiang bad_setsum = rte_member_create(&bad_params); 213*4418919fSjohnjiang if (bad_setsum != NULL) { 214*4418919fSjohnjiang rte_member_free(bad_setsum); 215*4418919fSjohnjiang printf("Impossible creating setsum successfully with to many " 216*4418919fSjohnjiang "number of keys(entries) for HT\n"); 217*4418919fSjohnjiang return -1; 218*4418919fSjohnjiang } 219*4418919fSjohnjiang 220*4418919fSjohnjiang bad_params.name = "bad_param5"; 221*4418919fSjohnjiang /* Test with same name should fail */ 222*4418919fSjohnjiang bad_setsum = rte_member_create(&bad_params); 223*4418919fSjohnjiang if (bad_setsum != NULL) { 224*4418919fSjohnjiang rte_member_free(bad_setsum); 225*4418919fSjohnjiang printf("Impossible creating setsum successfully with existed " 226*4418919fSjohnjiang "name\n"); 227*4418919fSjohnjiang return -1; 228*4418919fSjohnjiang } 229*4418919fSjohnjiang printf("Expected error section end...\n"); 230*4418919fSjohnjiang rte_member_free(bad_setsum); 231*4418919fSjohnjiang return 0; 232*4418919fSjohnjiang } 233*4418919fSjohnjiang 234*4418919fSjohnjiang /* Create test setsummaries. */ 235*4418919fSjohnjiang static int test_member_create(void) 236*4418919fSjohnjiang { 237*4418919fSjohnjiang params.key_len = sizeof(struct flow_key); 238*4418919fSjohnjiang 239*4418919fSjohnjiang params.name = "test_member_ht"; 240*4418919fSjohnjiang params.is_cache = 0; 241*4418919fSjohnjiang params.type = RTE_MEMBER_TYPE_HT; 242*4418919fSjohnjiang setsum_ht = rte_member_create(¶ms); 243*4418919fSjohnjiang 244*4418919fSjohnjiang params.name = "test_member_cache"; 245*4418919fSjohnjiang params.is_cache = 1; 246*4418919fSjohnjiang setsum_cache = rte_member_create(¶ms); 247*4418919fSjohnjiang 248*4418919fSjohnjiang params.name = "test_member_vbf"; 249*4418919fSjohnjiang params.type = RTE_MEMBER_TYPE_VBF; 250*4418919fSjohnjiang setsum_vbf = rte_member_create(¶ms); 251*4418919fSjohnjiang 252*4418919fSjohnjiang if (setsum_ht == NULL || setsum_cache == NULL || setsum_vbf == NULL) { 253*4418919fSjohnjiang printf("Creation of setsums fail\n"); 254*4418919fSjohnjiang return -1; 255*4418919fSjohnjiang } 256*4418919fSjohnjiang printf("Creation of setsums success\n"); 257*4418919fSjohnjiang return 0; 258*4418919fSjohnjiang } 259*4418919fSjohnjiang 260*4418919fSjohnjiang static int test_member_insert(void) 261*4418919fSjohnjiang { 262*4418919fSjohnjiang int ret_ht, ret_cache, ret_vbf, i; 263*4418919fSjohnjiang 264*4418919fSjohnjiang for (i = 0; i < NUM_SAMPLES; i++) { 265*4418919fSjohnjiang ret_ht = rte_member_add(setsum_ht, &keys[i], test_set[i]); 266*4418919fSjohnjiang ret_cache = rte_member_add(setsum_cache, &keys[i], 267*4418919fSjohnjiang test_set[i]); 268*4418919fSjohnjiang ret_vbf = rte_member_add(setsum_vbf, &keys[i], test_set[i]); 269*4418919fSjohnjiang TEST_ASSERT(ret_ht >= 0 && ret_cache >= 0 && ret_vbf >= 0, 270*4418919fSjohnjiang "insert error"); 271*4418919fSjohnjiang } 272*4418919fSjohnjiang printf("insert key success\n"); 273*4418919fSjohnjiang return 0; 274*4418919fSjohnjiang } 275*4418919fSjohnjiang 276*4418919fSjohnjiang static int test_member_lookup(void) 277*4418919fSjohnjiang { 278*4418919fSjohnjiang int ret_ht, ret_cache, ret_vbf, i; 279*4418919fSjohnjiang uint16_t set_ht, set_cache, set_vbf; 280*4418919fSjohnjiang member_set_t set_ids_ht[NUM_SAMPLES] = {0}; 281*4418919fSjohnjiang member_set_t set_ids_cache[NUM_SAMPLES] = {0}; 282*4418919fSjohnjiang member_set_t set_ids_vbf[NUM_SAMPLES] = {0}; 283*4418919fSjohnjiang 284*4418919fSjohnjiang uint32_t num_key_ht = NUM_SAMPLES; 285*4418919fSjohnjiang uint32_t num_key_cache = NUM_SAMPLES; 286*4418919fSjohnjiang uint32_t num_key_vbf = NUM_SAMPLES; 287*4418919fSjohnjiang 288*4418919fSjohnjiang const void *key_array[NUM_SAMPLES]; 289*4418919fSjohnjiang 290*4418919fSjohnjiang /* Single lookup test */ 291*4418919fSjohnjiang for (i = 0; i < NUM_SAMPLES; i++) { 292*4418919fSjohnjiang ret_ht = rte_member_lookup(setsum_ht, &keys[i], &set_ht); 293*4418919fSjohnjiang ret_cache = rte_member_lookup(setsum_cache, &keys[i], 294*4418919fSjohnjiang &set_cache); 295*4418919fSjohnjiang ret_vbf = rte_member_lookup(setsum_vbf, &keys[i], &set_vbf); 296*4418919fSjohnjiang TEST_ASSERT(ret_ht >= 0 && ret_cache >= 0 && ret_vbf >= 0, 297*4418919fSjohnjiang "single lookup function error"); 298*4418919fSjohnjiang 299*4418919fSjohnjiang TEST_ASSERT(set_ht == test_set[i] && 300*4418919fSjohnjiang set_cache == test_set[i] && 301*4418919fSjohnjiang set_vbf == test_set[i], 302*4418919fSjohnjiang "single lookup set value error"); 303*4418919fSjohnjiang } 304*4418919fSjohnjiang printf("lookup single key success\n"); 305*4418919fSjohnjiang 306*4418919fSjohnjiang /* Bulk lookup test */ 307*4418919fSjohnjiang for (i = 0; i < NUM_SAMPLES; i++) 308*4418919fSjohnjiang key_array[i] = &keys[i]; 309*4418919fSjohnjiang 310*4418919fSjohnjiang ret_ht = rte_member_lookup_bulk(setsum_ht, key_array, 311*4418919fSjohnjiang num_key_ht, set_ids_ht); 312*4418919fSjohnjiang 313*4418919fSjohnjiang ret_cache = rte_member_lookup_bulk(setsum_cache, key_array, 314*4418919fSjohnjiang num_key_cache, set_ids_cache); 315*4418919fSjohnjiang 316*4418919fSjohnjiang ret_vbf = rte_member_lookup_bulk(setsum_vbf, key_array, 317*4418919fSjohnjiang num_key_vbf, set_ids_vbf); 318*4418919fSjohnjiang 319*4418919fSjohnjiang TEST_ASSERT(ret_ht >= 0 && ret_cache >= 0 && ret_vbf >= 0, 320*4418919fSjohnjiang "bulk lookup function error"); 321*4418919fSjohnjiang 322*4418919fSjohnjiang for (i = 0; i < NUM_SAMPLES; i++) { 323*4418919fSjohnjiang TEST_ASSERT((set_ids_ht[i] == test_set[i]) && 324*4418919fSjohnjiang (set_ids_cache[i] == test_set[i]) && 325*4418919fSjohnjiang (set_ids_vbf[i] == test_set[i]), 326*4418919fSjohnjiang "bulk lookup result error"); 327*4418919fSjohnjiang } 328*4418919fSjohnjiang 329*4418919fSjohnjiang return 0; 330*4418919fSjohnjiang } 331*4418919fSjohnjiang 332*4418919fSjohnjiang static int test_member_delete(void) 333*4418919fSjohnjiang { 334*4418919fSjohnjiang int ret_ht, ret_cache, ret_vbf, i; 335*4418919fSjohnjiang uint16_t set_ht, set_cache, set_vbf; 336*4418919fSjohnjiang const void *key_array[NUM_SAMPLES]; 337*4418919fSjohnjiang member_set_t set_ids_ht[NUM_SAMPLES] = {0}; 338*4418919fSjohnjiang member_set_t set_ids_cache[NUM_SAMPLES] = {0}; 339*4418919fSjohnjiang member_set_t set_ids_vbf[NUM_SAMPLES] = {0}; 340*4418919fSjohnjiang uint32_t num_key_ht = NUM_SAMPLES; 341*4418919fSjohnjiang uint32_t num_key_cache = NUM_SAMPLES; 342*4418919fSjohnjiang uint32_t num_key_vbf = NUM_SAMPLES; 343*4418919fSjohnjiang 344*4418919fSjohnjiang /* Delete part of all inserted keys */ 345*4418919fSjohnjiang for (i = 0; i < NUM_SAMPLES / 2; i++) { 346*4418919fSjohnjiang ret_ht = rte_member_delete(setsum_ht, &keys[i], test_set[i]); 347*4418919fSjohnjiang ret_cache = rte_member_delete(setsum_cache, &keys[i], 348*4418919fSjohnjiang test_set[i]); 349*4418919fSjohnjiang ret_vbf = rte_member_delete(setsum_vbf, &keys[i], test_set[i]); 350*4418919fSjohnjiang /* VBF does not support delete yet, so return error code */ 351*4418919fSjohnjiang TEST_ASSERT(ret_ht >= 0 && ret_cache >= 0, 352*4418919fSjohnjiang "key deletion function error"); 353*4418919fSjohnjiang TEST_ASSERT(ret_vbf < 0, 354*4418919fSjohnjiang "vbf does not support deletion, error"); 355*4418919fSjohnjiang } 356*4418919fSjohnjiang 357*4418919fSjohnjiang for (i = 0; i < NUM_SAMPLES; i++) 358*4418919fSjohnjiang key_array[i] = &keys[i]; 359*4418919fSjohnjiang 360*4418919fSjohnjiang ret_ht = rte_member_lookup_bulk(setsum_ht, key_array, 361*4418919fSjohnjiang num_key_ht, set_ids_ht); 362*4418919fSjohnjiang 363*4418919fSjohnjiang ret_cache = rte_member_lookup_bulk(setsum_cache, key_array, 364*4418919fSjohnjiang num_key_cache, set_ids_cache); 365*4418919fSjohnjiang 366*4418919fSjohnjiang ret_vbf = rte_member_lookup_bulk(setsum_vbf, key_array, 367*4418919fSjohnjiang num_key_vbf, set_ids_vbf); 368*4418919fSjohnjiang 369*4418919fSjohnjiang TEST_ASSERT(ret_ht >= 0 && ret_cache >= 0 && ret_vbf >= 0, 370*4418919fSjohnjiang "bulk lookup function error"); 371*4418919fSjohnjiang 372*4418919fSjohnjiang for (i = 0; i < NUM_SAMPLES / 2; i++) { 373*4418919fSjohnjiang TEST_ASSERT((set_ids_ht[i] == RTE_MEMBER_NO_MATCH) && 374*4418919fSjohnjiang (set_ids_cache[i] == RTE_MEMBER_NO_MATCH), 375*4418919fSjohnjiang "bulk lookup result error"); 376*4418919fSjohnjiang } 377*4418919fSjohnjiang 378*4418919fSjohnjiang for (i = NUM_SAMPLES / 2; i < NUM_SAMPLES; i++) { 379*4418919fSjohnjiang TEST_ASSERT((set_ids_ht[i] == test_set[i]) && 380*4418919fSjohnjiang (set_ids_cache[i] == test_set[i]) && 381*4418919fSjohnjiang (set_ids_vbf[i] == test_set[i]), 382*4418919fSjohnjiang "bulk lookup result error"); 383*4418919fSjohnjiang } 384*4418919fSjohnjiang 385*4418919fSjohnjiang /* Delete the left of inserted keys */ 386*4418919fSjohnjiang for (i = NUM_SAMPLES / 2; i < NUM_SAMPLES; i++) { 387*4418919fSjohnjiang ret_ht = rte_member_delete(setsum_ht, &keys[i], test_set[i]); 388*4418919fSjohnjiang ret_cache = rte_member_delete(setsum_cache, &keys[i], 389*4418919fSjohnjiang test_set[i]); 390*4418919fSjohnjiang ret_vbf = rte_member_delete(setsum_vbf, &keys[i], test_set[i]); 391*4418919fSjohnjiang /* VBF does not support delete yet, so return error code */ 392*4418919fSjohnjiang TEST_ASSERT(ret_ht >= 0 && ret_cache >= 0, 393*4418919fSjohnjiang "key deletion function error"); 394*4418919fSjohnjiang TEST_ASSERT(ret_vbf < 0, 395*4418919fSjohnjiang "vbf does not support deletion, error"); 396*4418919fSjohnjiang } 397*4418919fSjohnjiang 398*4418919fSjohnjiang for (i = 0; i < NUM_SAMPLES; i++) { 399*4418919fSjohnjiang ret_ht = rte_member_lookup(setsum_ht, &keys[i], &set_ht); 400*4418919fSjohnjiang ret_cache = rte_member_lookup(setsum_cache, &keys[i], 401*4418919fSjohnjiang &set_cache); 402*4418919fSjohnjiang ret_vbf = rte_member_lookup(setsum_vbf, &keys[i], &set_vbf); 403*4418919fSjohnjiang TEST_ASSERT(ret_ht >= 0 && ret_cache >= 0, 404*4418919fSjohnjiang "key lookup function error"); 405*4418919fSjohnjiang TEST_ASSERT(set_ht == RTE_MEMBER_NO_MATCH && 406*4418919fSjohnjiang ret_cache == RTE_MEMBER_NO_MATCH, 407*4418919fSjohnjiang "key deletion failed"); 408*4418919fSjohnjiang } 409*4418919fSjohnjiang /* Reset vbf for other following tests */ 410*4418919fSjohnjiang rte_member_reset(setsum_vbf); 411*4418919fSjohnjiang 412*4418919fSjohnjiang printf("delete success\n"); 413*4418919fSjohnjiang return 0; 414*4418919fSjohnjiang } 415*4418919fSjohnjiang 416*4418919fSjohnjiang static int test_member_multimatch(void) 417*4418919fSjohnjiang { 418*4418919fSjohnjiang int ret_ht, ret_vbf, ret_cache; 419*4418919fSjohnjiang member_set_t set_ids_ht[MAX_MATCH] = {0}; 420*4418919fSjohnjiang member_set_t set_ids_vbf[MAX_MATCH] = {0}; 421*4418919fSjohnjiang member_set_t set_ids_cache[MAX_MATCH] = {0}; 422*4418919fSjohnjiang 423*4418919fSjohnjiang member_set_t set_ids_ht_m[NUM_SAMPLES][MAX_MATCH] = {{0} }; 424*4418919fSjohnjiang member_set_t set_ids_vbf_m[NUM_SAMPLES][MAX_MATCH] = {{0} }; 425*4418919fSjohnjiang member_set_t set_ids_cache_m[NUM_SAMPLES][MAX_MATCH] = {{0} }; 426*4418919fSjohnjiang 427*4418919fSjohnjiang uint32_t match_count_ht[NUM_SAMPLES]; 428*4418919fSjohnjiang uint32_t match_count_vbf[NUM_SAMPLES]; 429*4418919fSjohnjiang uint32_t match_count_cache[NUM_SAMPLES]; 430*4418919fSjohnjiang 431*4418919fSjohnjiang uint32_t num_key_ht = NUM_SAMPLES; 432*4418919fSjohnjiang uint32_t num_key_vbf = NUM_SAMPLES; 433*4418919fSjohnjiang uint32_t num_key_cache = NUM_SAMPLES; 434*4418919fSjohnjiang 435*4418919fSjohnjiang const void *key_array[NUM_SAMPLES]; 436*4418919fSjohnjiang 437*4418919fSjohnjiang uint32_t i, j; 438*4418919fSjohnjiang 439*4418919fSjohnjiang /* Same key at most inserted 2*entry_per_bucket times for HT mode */ 440*4418919fSjohnjiang for (i = M_MATCH_S; i <= M_MATCH_E; i += M_MATCH_STEP) { 441*4418919fSjohnjiang for (j = 0; j < NUM_SAMPLES; j++) { 442*4418919fSjohnjiang ret_ht = rte_member_add(setsum_ht, &keys[j], i); 443*4418919fSjohnjiang ret_vbf = rte_member_add(setsum_vbf, &keys[j], i); 444*4418919fSjohnjiang ret_cache = rte_member_add(setsum_cache, &keys[j], i); 445*4418919fSjohnjiang 446*4418919fSjohnjiang TEST_ASSERT(ret_ht >= 0 && ret_vbf >= 0 && 447*4418919fSjohnjiang ret_cache >= 0, 448*4418919fSjohnjiang "insert function error"); 449*4418919fSjohnjiang } 450*4418919fSjohnjiang } 451*4418919fSjohnjiang 452*4418919fSjohnjiang /* Single multimatch test */ 453*4418919fSjohnjiang for (i = 0; i < NUM_SAMPLES; i++) { 454*4418919fSjohnjiang ret_vbf = rte_member_lookup_multi(setsum_vbf, &keys[i], 455*4418919fSjohnjiang MAX_MATCH, set_ids_vbf); 456*4418919fSjohnjiang ret_ht = rte_member_lookup_multi(setsum_ht, &keys[i], 457*4418919fSjohnjiang MAX_MATCH, set_ids_ht); 458*4418919fSjohnjiang ret_cache = rte_member_lookup_multi(setsum_cache, &keys[i], 459*4418919fSjohnjiang MAX_MATCH, set_ids_cache); 460*4418919fSjohnjiang /* 461*4418919fSjohnjiang * For cache mode, keys overwrite when signature same. 462*4418919fSjohnjiang * the mutimatch should work like single match. 463*4418919fSjohnjiang */ 464*4418919fSjohnjiang TEST_ASSERT(ret_ht == M_MATCH_CNT && ret_vbf == M_MATCH_CNT && 465*4418919fSjohnjiang ret_cache == 1, 466*4418919fSjohnjiang "single lookup_multi error"); 467*4418919fSjohnjiang TEST_ASSERT(set_ids_cache[0] == M_MATCH_E, 468*4418919fSjohnjiang "single lookup_multi cache error"); 469*4418919fSjohnjiang 470*4418919fSjohnjiang for (j = 1; j <= M_MATCH_CNT; j++) { 471*4418919fSjohnjiang TEST_ASSERT(set_ids_ht[j-1] == j * M_MATCH_STEP - 1 && 472*4418919fSjohnjiang set_ids_vbf[j-1] == 473*4418919fSjohnjiang j * M_MATCH_STEP - 1, 474*4418919fSjohnjiang "single multimatch lookup error"); 475*4418919fSjohnjiang } 476*4418919fSjohnjiang } 477*4418919fSjohnjiang printf("lookup single key for multimatch success\n"); 478*4418919fSjohnjiang 479*4418919fSjohnjiang /* Bulk multimatch test */ 480*4418919fSjohnjiang for (i = 0; i < NUM_SAMPLES; i++) 481*4418919fSjohnjiang key_array[i] = &keys[i]; 482*4418919fSjohnjiang ret_vbf = rte_member_lookup_multi_bulk(setsum_vbf, 483*4418919fSjohnjiang &key_array[0], num_key_ht, MAX_MATCH, match_count_vbf, 484*4418919fSjohnjiang (member_set_t *)set_ids_vbf_m); 485*4418919fSjohnjiang 486*4418919fSjohnjiang ret_ht = rte_member_lookup_multi_bulk(setsum_ht, 487*4418919fSjohnjiang &key_array[0], num_key_vbf, MAX_MATCH, match_count_ht, 488*4418919fSjohnjiang (member_set_t *)set_ids_ht_m); 489*4418919fSjohnjiang 490*4418919fSjohnjiang ret_cache = rte_member_lookup_multi_bulk(setsum_cache, 491*4418919fSjohnjiang &key_array[0], num_key_cache, MAX_MATCH, 492*4418919fSjohnjiang match_count_cache, (member_set_t *)set_ids_cache_m); 493*4418919fSjohnjiang 494*4418919fSjohnjiang 495*4418919fSjohnjiang for (j = 0; j < NUM_SAMPLES; j++) { 496*4418919fSjohnjiang TEST_ASSERT(match_count_ht[j] == M_MATCH_CNT, 497*4418919fSjohnjiang "bulk multimatch lookup HT match count error"); 498*4418919fSjohnjiang TEST_ASSERT(match_count_vbf[j] == M_MATCH_CNT, 499*4418919fSjohnjiang "bulk multimatch lookup vBF match count error"); 500*4418919fSjohnjiang TEST_ASSERT(match_count_cache[j] == 1, 501*4418919fSjohnjiang "bulk multimatch lookup CACHE match count error"); 502*4418919fSjohnjiang TEST_ASSERT(set_ids_cache_m[j][0] == M_MATCH_E, 503*4418919fSjohnjiang "bulk multimatch lookup CACHE set value error"); 504*4418919fSjohnjiang 505*4418919fSjohnjiang for (i = 1; i <= M_MATCH_CNT; i++) { 506*4418919fSjohnjiang TEST_ASSERT(set_ids_ht_m[j][i-1] == 507*4418919fSjohnjiang i * M_MATCH_STEP - 1, 508*4418919fSjohnjiang "bulk multimatch lookup HT set value error"); 509*4418919fSjohnjiang TEST_ASSERT(set_ids_vbf_m[j][i-1] == 510*4418919fSjohnjiang i * M_MATCH_STEP - 1, 511*4418919fSjohnjiang "bulk multimatch lookup vBF set value error"); 512*4418919fSjohnjiang } 513*4418919fSjohnjiang } 514*4418919fSjohnjiang 515*4418919fSjohnjiang printf("lookup for bulk multimatch success\n"); 516*4418919fSjohnjiang 517*4418919fSjohnjiang return 0; 518*4418919fSjohnjiang } 519*4418919fSjohnjiang 520*4418919fSjohnjiang static int key_compare(const void *key1, const void *key2) 521*4418919fSjohnjiang { 522*4418919fSjohnjiang return memcmp(key1, key2, KEY_SIZE); 523*4418919fSjohnjiang } 524*4418919fSjohnjiang 525*4418919fSjohnjiang static void 526*4418919fSjohnjiang setup_keys_and_data(void) 527*4418919fSjohnjiang { 528*4418919fSjohnjiang unsigned int i, j; 529*4418919fSjohnjiang int num_duplicates; 530*4418919fSjohnjiang 531*4418919fSjohnjiang /* Reset all arrays */ 532*4418919fSjohnjiang for (i = 0; i < KEY_SIZE; i++) 533*4418919fSjohnjiang generated_keys[0][i] = 0; 534*4418919fSjohnjiang 535*4418919fSjohnjiang /* Generate a list of keys, some of which may be duplicates */ 536*4418919fSjohnjiang for (i = 0; i < MAX_ENTRIES; i++) { 537*4418919fSjohnjiang for (j = 0; j < KEY_SIZE; j++) 538*4418919fSjohnjiang generated_keys[i][j] = rte_rand() & 0xFF; 539*4418919fSjohnjiang } 540*4418919fSjohnjiang 541*4418919fSjohnjiang /* Remove duplicates from the keys array */ 542*4418919fSjohnjiang do { 543*4418919fSjohnjiang num_duplicates = 0; 544*4418919fSjohnjiang /* Sort the list of keys to make it easier to find duplicates */ 545*4418919fSjohnjiang qsort(generated_keys, MAX_ENTRIES, KEY_SIZE, key_compare); 546*4418919fSjohnjiang 547*4418919fSjohnjiang /* Sift through the list of keys and look for duplicates */ 548*4418919fSjohnjiang int num_duplicates = 0; 549*4418919fSjohnjiang for (i = 0; i < MAX_ENTRIES - 1; i++) { 550*4418919fSjohnjiang if (memcmp(generated_keys[i], generated_keys[i + 1], 551*4418919fSjohnjiang KEY_SIZE) == 0) { 552*4418919fSjohnjiang /* This key already exists, try again */ 553*4418919fSjohnjiang num_duplicates++; 554*4418919fSjohnjiang for (j = 0; j < KEY_SIZE; j++) 555*4418919fSjohnjiang generated_keys[i][j] = 556*4418919fSjohnjiang rte_rand() & 0xFF; 557*4418919fSjohnjiang } 558*4418919fSjohnjiang } 559*4418919fSjohnjiang } while (num_duplicates != 0); 560*4418919fSjohnjiang } 561*4418919fSjohnjiang 562*4418919fSjohnjiang static inline int 563*4418919fSjohnjiang add_generated_keys(struct rte_member_setsum *setsum, unsigned int *added_keys) 564*4418919fSjohnjiang { 565*4418919fSjohnjiang int ret = 0; 566*4418919fSjohnjiang 567*4418919fSjohnjiang for (*added_keys = 0; ret >= 0 && *added_keys < MAX_ENTRIES; 568*4418919fSjohnjiang (*added_keys)++) { 569*4418919fSjohnjiang uint16_t set = (rte_rand() & 0xf) + 1; 570*4418919fSjohnjiang ret = rte_member_add(setsum, &generated_keys[*added_keys], set); 571*4418919fSjohnjiang } 572*4418919fSjohnjiang return ret; 573*4418919fSjohnjiang } 574*4418919fSjohnjiang 575*4418919fSjohnjiang static inline int 576*4418919fSjohnjiang add_generated_keys_cache(struct rte_member_setsum *setsum, 577*4418919fSjohnjiang unsigned int *added_keys) 578*4418919fSjohnjiang { 579*4418919fSjohnjiang int ret = 0; 580*4418919fSjohnjiang 581*4418919fSjohnjiang for (*added_keys = 0; ret == 0 && *added_keys < MAX_ENTRIES; 582*4418919fSjohnjiang (*added_keys)++) { 583*4418919fSjohnjiang uint16_t set = (rte_rand() & 0xf) + 1; 584*4418919fSjohnjiang ret = rte_member_add(setsum, &generated_keys[*added_keys], set); 585*4418919fSjohnjiang } 586*4418919fSjohnjiang return ret; 587*4418919fSjohnjiang } 588*4418919fSjohnjiang 589*4418919fSjohnjiang static int 590*4418919fSjohnjiang test_member_loadfactor(void) 591*4418919fSjohnjiang { 592*4418919fSjohnjiang unsigned int j; 593*4418919fSjohnjiang unsigned int added_keys, average_keys_added = 0; 594*4418919fSjohnjiang int ret; 595*4418919fSjohnjiang 596*4418919fSjohnjiang setup_keys_and_data(); 597*4418919fSjohnjiang 598*4418919fSjohnjiang rte_member_free(setsum_ht); 599*4418919fSjohnjiang rte_member_free(setsum_cache); 600*4418919fSjohnjiang rte_member_free(setsum_vbf); 601*4418919fSjohnjiang 602*4418919fSjohnjiang params.key_len = KEY_SIZE; 603*4418919fSjohnjiang params.name = "test_member_ht"; 604*4418919fSjohnjiang params.is_cache = 0; 605*4418919fSjohnjiang params.type = RTE_MEMBER_TYPE_HT; 606*4418919fSjohnjiang setsum_ht = rte_member_create(¶ms); 607*4418919fSjohnjiang 608*4418919fSjohnjiang params.name = "test_member_cache"; 609*4418919fSjohnjiang params.is_cache = 1; 610*4418919fSjohnjiang setsum_cache = rte_member_create(¶ms); 611*4418919fSjohnjiang 612*4418919fSjohnjiang 613*4418919fSjohnjiang if (setsum_ht == NULL || setsum_cache == NULL) { 614*4418919fSjohnjiang printf("Creation of setsums fail\n"); 615*4418919fSjohnjiang return -1; 616*4418919fSjohnjiang } 617*4418919fSjohnjiang /* Test HT non-cache mode */ 618*4418919fSjohnjiang for (j = 0; j < ITERATIONS; j++) { 619*4418919fSjohnjiang /* Add random entries until key cannot be added */ 620*4418919fSjohnjiang ret = add_generated_keys(setsum_ht, &added_keys); 621*4418919fSjohnjiang if (ret != -ENOSPC) { 622*4418919fSjohnjiang printf("Unexpected error when adding keys\n"); 623*4418919fSjohnjiang return -1; 624*4418919fSjohnjiang } 625*4418919fSjohnjiang average_keys_added += added_keys; 626*4418919fSjohnjiang 627*4418919fSjohnjiang /* Reset the table */ 628*4418919fSjohnjiang rte_member_reset(setsum_ht); 629*4418919fSjohnjiang 630*4418919fSjohnjiang /* Print a dot to show progress on operations */ 631*4418919fSjohnjiang printf("."); 632*4418919fSjohnjiang fflush(stdout); 633*4418919fSjohnjiang } 634*4418919fSjohnjiang 635*4418919fSjohnjiang average_keys_added /= ITERATIONS; 636*4418919fSjohnjiang 637*4418919fSjohnjiang printf("\nKeys inserted when no space(non-cache) = %.2f%% (%u/%u)\n", 638*4418919fSjohnjiang ((double) average_keys_added / params.num_keys * 100), 639*4418919fSjohnjiang average_keys_added, params.num_keys); 640*4418919fSjohnjiang 641*4418919fSjohnjiang /* Test cache mode */ 642*4418919fSjohnjiang added_keys = average_keys_added = 0; 643*4418919fSjohnjiang for (j = 0; j < ITERATIONS; j++) { 644*4418919fSjohnjiang /* Add random entries until key cannot be added */ 645*4418919fSjohnjiang ret = add_generated_keys_cache(setsum_cache, &added_keys); 646*4418919fSjohnjiang if (ret != 1) { 647*4418919fSjohnjiang printf("Unexpected error when adding keys\n"); 648*4418919fSjohnjiang return -1; 649*4418919fSjohnjiang } 650*4418919fSjohnjiang average_keys_added += added_keys; 651*4418919fSjohnjiang 652*4418919fSjohnjiang /* Reset the table */ 653*4418919fSjohnjiang rte_member_reset(setsum_cache); 654*4418919fSjohnjiang 655*4418919fSjohnjiang /* Print a dot to show progress on operations */ 656*4418919fSjohnjiang printf("."); 657*4418919fSjohnjiang fflush(stdout); 658*4418919fSjohnjiang } 659*4418919fSjohnjiang 660*4418919fSjohnjiang average_keys_added /= ITERATIONS; 661*4418919fSjohnjiang 662*4418919fSjohnjiang printf("\nKeys inserted when eviction happens(cache)= %.2f%% (%u/%u)\n", 663*4418919fSjohnjiang ((double) average_keys_added / params.num_keys * 100), 664*4418919fSjohnjiang average_keys_added, params.num_keys); 665*4418919fSjohnjiang return 0; 666*4418919fSjohnjiang } 667*4418919fSjohnjiang 668*4418919fSjohnjiang static void 669*4418919fSjohnjiang perform_free(void) 670*4418919fSjohnjiang { 671*4418919fSjohnjiang rte_member_free(setsum_ht); 672*4418919fSjohnjiang rte_member_free(setsum_cache); 673*4418919fSjohnjiang rte_member_free(setsum_vbf); 674*4418919fSjohnjiang } 675*4418919fSjohnjiang 676*4418919fSjohnjiang static int 677*4418919fSjohnjiang test_member(void) 678*4418919fSjohnjiang { 679*4418919fSjohnjiang if (test_member_create_bad_param() < 0) 680*4418919fSjohnjiang return -1; 681*4418919fSjohnjiang 682*4418919fSjohnjiang if (test_member_find_existing() < 0) 683*4418919fSjohnjiang return -1; 684*4418919fSjohnjiang 685*4418919fSjohnjiang if (test_member_create() < 0) { 686*4418919fSjohnjiang perform_free(); 687*4418919fSjohnjiang return -1; 688*4418919fSjohnjiang } 689*4418919fSjohnjiang if (test_member_insert() < 0) { 690*4418919fSjohnjiang perform_free(); 691*4418919fSjohnjiang return -1; 692*4418919fSjohnjiang } 693*4418919fSjohnjiang if (test_member_lookup() < 0) { 694*4418919fSjohnjiang perform_free(); 695*4418919fSjohnjiang return -1; 696*4418919fSjohnjiang } 697*4418919fSjohnjiang if (test_member_delete() < 0) { 698*4418919fSjohnjiang perform_free(); 699*4418919fSjohnjiang return -1; 700*4418919fSjohnjiang } 701*4418919fSjohnjiang if (test_member_multimatch() < 0) { 702*4418919fSjohnjiang perform_free(); 703*4418919fSjohnjiang return -1; 704*4418919fSjohnjiang } 705*4418919fSjohnjiang if (test_member_loadfactor() < 0) { 706*4418919fSjohnjiang rte_member_free(setsum_ht); 707*4418919fSjohnjiang rte_member_free(setsum_cache); 708*4418919fSjohnjiang return -1; 709*4418919fSjohnjiang } 710*4418919fSjohnjiang 711*4418919fSjohnjiang perform_free(); 712*4418919fSjohnjiang return 0; 713*4418919fSjohnjiang } 714*4418919fSjohnjiang 715*4418919fSjohnjiang REGISTER_TEST_COMMAND(member_autotest, test_member); 716