@@ -95,7 +95,7 @@ static uint32_t pseudo_hash(__rte_unused const void *keys,
__rte_unused uint32_t key_len,
__rte_unused uint32_t init_val)
{
- return 3;
+ return 3 | (3 << 16);
}
RTE_LOG_REGISTER(hash_logtype_test, test.hash, INFO);
@@ -115,8 +115,10 @@ static void print_key_info(const char *msg, const struct flow_key *key,
rte_log(RTE_LOG_DEBUG, hash_logtype_test, " @ pos %d\n", pos);
}
+#define KEY_PER_BUCKET 8
+
/* Keys used by unit test functions */
-static struct flow_key keys[5] = { {
+static struct flow_key keys[KEY_PER_BUCKET+1] = { {
.ip_src = RTE_IPV4(0x03, 0x02, 0x01, 0x00),
.ip_dst = RTE_IPV4(0x07, 0x06, 0x05, 0x04),
.port_src = 0x0908,
@@ -146,6 +148,30 @@ static struct flow_key keys[5] = { {
.port_src = 0x4948,
.port_dst = 0x4b4a,
.proto = 0x4c,
+}, {
+ .ip_src = RTE_IPV4(0x53, 0x52, 0x51, 0x50),
+ .ip_dst = RTE_IPV4(0x57, 0x56, 0x55, 0x54),
+ .port_src = 0x5958,
+ .port_dst = 0x5b5a,
+ .proto = 0x5c,
+}, {
+ .ip_src = RTE_IPV4(0x63, 0x62, 0x61, 0x60),
+ .ip_dst = RTE_IPV4(0x67, 0x66, 0x65, 0x64),
+ .port_src = 0x6968,
+ .port_dst = 0x6b6a,
+ .proto = 0x6c,
+}, {
+ .ip_src = RTE_IPV4(0x73, 0x72, 0x71, 0x70),
+ .ip_dst = RTE_IPV4(0x77, 0x76, 0x75, 0x74),
+ .port_src = 0x7978,
+ .port_dst = 0x7b7a,
+ .proto = 0x7c,
+}, {
+ .ip_src = RTE_IPV4(0x83, 0x82, 0x81, 0x80),
+ .ip_dst = RTE_IPV4(0x87, 0x86, 0x85, 0x84),
+ .port_src = 0x8988,
+ .port_dst = 0x8b8a,
+ .proto = 0x8c,
} };
/* Parameters used for hash table in unit test functions. Name set later. */
@@ -783,13 +809,15 @@ static int test_five_keys(void)
/*
* Add keys to the same bucket until bucket full.
- * - add 5 keys to the same bucket (hash created with 4 keys per bucket):
- * first 4 successful, 5th successful, pushing existing item in bucket
- * - lookup the 5 keys: 5 hits
- * - add the 5 keys again: 5 OK
- * - lookup the 5 keys: 5 hits (updated data)
- * - delete the 5 keys: 5 OK
- * - lookup the 5 keys: 5 misses
+ * - add 9 keys to the same bucket (hash created with 8 keys per bucket):
+ * first 8 successful, 9th successful, pushing existing item in bucket
+ * - lookup the 9 keys: 9 hits
+ * - bulk lookup for all the 9 keys: 9 hits
+ * - add the 9 keys again: 9 OK
+ * - lookup the 9 keys: 9 hits (updated data)
+ * - delete the 9 keys: 9 OK
+ * - lookup the 9 keys: 9 misses
+ * - bulk lookup for all the 9 keys: 9 misses
*/
static int test_full_bucket(void)
{
@@ -801,16 +829,17 @@ static int test_full_bucket(void)
.hash_func_init_val = 0,
.socket_id = 0,
};
+ const void *key_array[KEY_PER_BUCKET+1] = {0};
struct rte_hash *handle;
- int pos[5];
- int expected_pos[5];
+ int pos[KEY_PER_BUCKET+1];
+ int expected_pos[KEY_PER_BUCKET+1];
unsigned i;
-
+ int ret;
handle = rte_hash_create(¶ms_pseudo_hash);
RETURN_IF_ERROR(handle == NULL, "hash creation failed");
/* Fill bucket */
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < KEY_PER_BUCKET; i++) {
pos[i] = rte_hash_add_key(handle, &keys[i]);
print_key_info("Add", &keys[i], pos[i]);
RETURN_IF_ERROR(pos[i] < 0,
@@ -821,22 +850,36 @@ static int test_full_bucket(void)
* This should work and will push one of the items
* in the bucket because it is full
*/
- pos[4] = rte_hash_add_key(handle, &keys[4]);
- print_key_info("Add", &keys[4], pos[4]);
- RETURN_IF_ERROR(pos[4] < 0,
- "failed to add key (pos[4]=%d)", pos[4]);
- expected_pos[4] = pos[4];
+ pos[KEY_PER_BUCKET] = rte_hash_add_key(handle, &keys[KEY_PER_BUCKET]);
+ print_key_info("Add", &keys[KEY_PER_BUCKET], pos[KEY_PER_BUCKET]);
+ RETURN_IF_ERROR(pos[KEY_PER_BUCKET] < 0,
+ "failed to add key (pos[%d]=%d)", KEY_PER_BUCKET, pos[KEY_PER_BUCKET]);
+ expected_pos[KEY_PER_BUCKET] = pos[KEY_PER_BUCKET];
/* Lookup */
- for (i = 0; i < 5; i++) {
+ for (i = 0; i < KEY_PER_BUCKET+1; i++) {
pos[i] = rte_hash_lookup(handle, &keys[i]);
print_key_info("Lkp", &keys[i], pos[i]);
RETURN_IF_ERROR(pos[i] != expected_pos[i],
"failed to find key (pos[%u]=%d)", i, pos[i]);
}
+ for (i = 0; i < KEY_PER_BUCKET+1; i++)
+ key_array[i] = &keys[i];
+
+ /*Bulk lookup after add with same hash*/
+ ret = rte_hash_lookup_bulk(handle, key_array, KEY_PER_BUCKET+1, (int32_t *)pos);
+ RETURN_IF_ERROR(ret, "rte_hash_lookup_bulk returned an error: %d\n", ret);
+ for (i = 0; i < KEY_PER_BUCKET+1; i++) {
+ print_key_info("Blk_Lkp", key_array[i], pos[i]);
+ RETURN_IF_ERROR(pos[i] != expected_pos[i],
+ "failed to find key (pos[%u]=%d)", i, pos[i]);
+ }
+
+
+
/* Add - update */
- for (i = 0; i < 5; i++) {
+ for (i = 0; i < KEY_PER_BUCKET+1; i++) {
pos[i] = rte_hash_add_key(handle, &keys[i]);
print_key_info("Add", &keys[i], pos[i]);
RETURN_IF_ERROR(pos[i] != expected_pos[i],
@@ -844,7 +887,7 @@ static int test_full_bucket(void)
}
/* Lookup */
- for (i = 0; i < 5; i++) {
+ for (i = 0; i < KEY_PER_BUCKET+1; i++) {
pos[i] = rte_hash_lookup(handle, &keys[i]);
print_key_info("Lkp", &keys[i], pos[i]);
RETURN_IF_ERROR(pos[i] != expected_pos[i],
@@ -869,7 +912,7 @@ static int test_full_bucket(void)
RETURN_IF_ERROR(pos[1] < 0, "failed to add key (pos[1]=%d)", pos[1]);
/* Delete */
- for (i = 0; i < 5; i++) {
+ for (i = 0; i < KEY_PER_BUCKET+1; i++) {
pos[i] = rte_hash_del_key(handle, &keys[i]);
print_key_info("Del", &keys[i], pos[i]);
RETURN_IF_ERROR(pos[i] != expected_pos[i],
@@ -877,13 +920,23 @@ static int test_full_bucket(void)
}
/* Lookup */
- for (i = 0; i < 5; i++) {
+ for (i = 0; i < KEY_PER_BUCKET+1; i++) {
pos[i] = rte_hash_lookup(handle, &keys[i]);
print_key_info("Lkp", &keys[i], pos[i]);
RETURN_IF_ERROR(pos[i] != -ENOENT,
"fail: found non-existent key (pos[%u]=%d)", i, pos[i]);
}
+ /* Bulk Lookup on empty table*/
+ ret = rte_hash_lookup_bulk(handle, &key_array[0], KEY_PER_BUCKET+1, (int32_t *)pos);
+ RETURN_IF_ERROR(ret, "rte_hash_lookup_bulk returned an error: %d\n", ret);
+ for (i = 0; i < KEY_PER_BUCKET+1; i++) {
+ print_key_info("Blk_Lkp", key_array[i], pos[i]);
+ RETURN_IF_ERROR(pos[i] != -ENOENT,
+ "failed to find key (pos[%u]=%d)", i, pos[i]);
+ }
+
+
rte_hash_free(handle);
/* Cover the NULL case. */