All of lore.kernel.org
 help / color / mirror / Atom feed
From: Pablo de Lara <pablo.de.lara.guarch@intel.com>
To: dev@dpdk.org
Cc: Pablo de Lara <pablo.de.lara.guarch@intel.com>,
	Byron Marohn <byron.marohn@intel.com>,
	Karla Saur <karla.saur@intel.com>,
	Saikrishna Edupuganti <saikrishna.edupuganti@intel.com>
Subject: [PATCH v3 2/5] app/test: add EFD functional and perf tests
Date: Thu, 12 Jan 2017 22:15:57 +0000	[thread overview]
Message-ID: <1484259360-198276-3-git-send-email-pablo.de.lara.guarch@intel.com> (raw)
In-Reply-To: <1484259360-198276-1-git-send-email-pablo.de.lara.guarch@intel.com>

Signed-off-by: Byron Marohn <byron.marohn@intel.com>
Signed-off-by: Karla Saur <karla.saur@intel.com>
Signed-off-by: Saikrishna Edupuganti <saikrishna.edupuganti@intel.com>
Signed-off-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>
Acked-by: Christian Maciocco <christian.maciocco@intel.com>
---
 MAINTAINERS              |   1 +
 app/test/Makefile        |   5 +-
 app/test/test_efd.c      | 494 +++++++++++++++++++++++++++++++++++++++++++++++
 app/test/test_efd_perf.c | 407 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 906 insertions(+), 1 deletion(-)
 create mode 100644 app/test/test_efd.c
 create mode 100644 app/test/test_efd_perf.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 9c60d67..d812962 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -532,6 +532,7 @@ EFD
 M: Byron Marohn <byron.marohn@intel.com>
 M: Pablo de Lara Guarch <pablo.de.lara.guarch@intel.com>
 F: lib/librte_efd/
+F: app/test/test_efd*
 
 Hashes
 M: Bruce Richardson <bruce.richardson@intel.com>
diff --git a/app/test/Makefile b/app/test/Makefile
index 5be023a..9de301f 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -1,6 +1,6 @@
 #   BSD LICENSE
 #
-#   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+#   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
 #   All rights reserved.
 #
 #   Redistribution and use in source and binary forms, with or without
@@ -123,6 +123,9 @@ SRCS-y += test_logs.c
 SRCS-y += test_memcpy.c
 SRCS-y += test_memcpy_perf.c
 
+SRCS-$(CONFIG_RTE_LIBRTE_EFD) += test_efd.c
+SRCS-$(CONFIG_RTE_LIBRTE_EFD) += test_efd_perf.c
+
 SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash.c
 SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_thash.c
 SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_perf.c
diff --git a/app/test/test_efd.c b/app/test/test_efd.c
new file mode 100644
index 0000000..d5c3bd9
--- /dev/null
+++ b/app/test/test_efd.c
@@ -0,0 +1,494 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_memcpy.h>
+#include <rte_malloc.h>
+#include <rte_efd.h>
+#include <rte_byteorder.h>
+#include <rte_random.h>
+#include <rte_debug.h>
+#include <rte_ip.h>
+
+#include "test.h"
+
+#define EFD_TEST_KEY_LEN 8
+#define TABLE_SIZE (1 << 21)
+#define ITERATIONS 3
+static unsigned int test_socket_id;
+
+/* 5-tuple key type */
+struct flow_key {
+	uint32_t ip_src;
+	uint32_t ip_dst;
+	uint16_t port_src;
+	uint16_t port_dst;
+	uint8_t proto;
+} __attribute__((packed));
+/*
+ * Print out result of unit test efd operation.
+ */
+#if defined(UNIT_TEST_EFD_VERBOSE)
+
+static void print_key_info(const char *msg, const struct flow_key *key,
+		efd_value_t val)
+{
+	const uint8_t *p = (const uint8_t *) key;
+	unsigned int i;
+
+	printf("%s key:0x", msg);
+	for (i = 0; i < sizeof(struct flow_key); i++)
+		printf("%02X", p[i]);
+
+	printf(" @ val %d\n", val);
+}
+#else
+
+static void print_key_info(__attribute__((unused)) const char *msg,
+		__attribute__((unused)) const struct flow_key *key,
+		__attribute__((unused)) efd_value_t val)
+{
+}
+#endif
+
+/* Keys used by unit test functions */
+static struct flow_key keys[5] = {
+	{
+		.ip_src = IPv4(0x03, 0x02, 0x01, 0x00),
+		.ip_dst = IPv4(0x07, 0x06, 0x05, 0x04),
+		.port_src = 0x0908,
+		.port_dst = 0x0b0a,
+		.proto = 0x0c,
+	},
+	{
+		.ip_src = IPv4(0x13, 0x12, 0x11, 0x10),
+		.ip_dst = IPv4(0x17, 0x16, 0x15, 0x14),
+		.port_src = 0x1918,
+		.port_dst = 0x1b1a,
+		.proto = 0x1c,
+	},
+	{
+		.ip_src = IPv4(0x23, 0x22, 0x21, 0x20),
+		.ip_dst = IPv4(0x27, 0x26, 0x25, 0x24),
+		.port_src = 0x2928,
+		.port_dst = 0x2b2a,
+		.proto = 0x2c,
+	},
+	{
+		.ip_src = IPv4(0x33, 0x32, 0x31, 0x30),
+		.ip_dst = IPv4(0x37, 0x36, 0x35, 0x34),
+		.port_src = 0x3938,
+		.port_dst = 0x3b3a,
+		.proto = 0x3c,
+	},
+	{
+		.ip_src = IPv4(0x43, 0x42, 0x41, 0x40),
+		.ip_dst = IPv4(0x47, 0x46, 0x45, 0x44),
+		.port_src = 0x4948,
+		.port_dst = 0x4b4a,
+		.proto = 0x4c,
+	}
+};
+/* Array to store the data */
+efd_value_t data[5];
+
+static inline uint8_t efd_get_all_sockets_bitmask(void)
+{
+	uint8_t all_cpu_sockets_bitmask = 0;
+	unsigned int i;
+	unsigned int next_lcore = rte_get_master_lcore();
+	const int val_true = 1, val_false = 0;
+	for (i = 0; i < rte_lcore_count(); i++) {
+		all_cpu_sockets_bitmask |= 1 << rte_lcore_to_socket_id(next_lcore);
+		next_lcore = rte_get_next_lcore(next_lcore, val_false, val_true);
+	}
+
+	return all_cpu_sockets_bitmask;
+}
+
+/*
+ * Basic sequence of operations for a single key:
+ *      - add
+ *      - lookup (hit)
+ *      - delete
+ * Note: lookup (miss) is not applicable since this is a filter
+ */
+static int test_add_delete(void)
+{
+	struct rte_efd_table *handle;
+	/* test with standard add/lookup/delete functions */
+	efd_value_t prev_value;
+	printf("Entering %s\n", __func__);
+
+	handle = rte_efd_create("test_add_delete",
+			TABLE_SIZE, sizeof(struct flow_key),
+			efd_get_all_sockets_bitmask(), test_socket_id);
+	TEST_ASSERT_NOT_NULL(handle, "Error creating the EFD table\n");
+
+	data[0] = mrand48() & ((1 << RTE_EFD_VALUE_NUM_BITS) - 1);
+	TEST_ASSERT_SUCCESS(rte_efd_update(handle, test_socket_id, &keys[0],
+			data[0]),
+			"Error inserting the key");
+	print_key_info("Add", &keys[0], data[0]);
+
+	TEST_ASSERT_EQUAL(rte_efd_lookup(handle, test_socket_id, &keys[0]),
+			data[0],
+			"failed to find key");
+
+	TEST_ASSERT_SUCCESS(rte_efd_delete(handle, test_socket_id, &keys[0],
+			&prev_value),
+			"failed to delete key");
+	TEST_ASSERT_EQUAL(prev_value, data[0],
+			"failed to delete the expected value, got %d, "
+			"expected %d", prev_value, data[0]);
+	print_key_info("Del", &keys[0], data[0]);
+
+	rte_efd_free(handle);
+
+	return 0;
+}
+
+/*
+ * Sequence of operations for a single key:
+ *      - add
+ *      - lookup: hit
+ *      - add: update
+ *      - lookup: hit (updated data)
+ *      - delete: hit
+ */
+static int test_add_update_delete(void)
+{
+	struct rte_efd_table *handle;
+	printf("Entering %s\n", __func__);
+	/* test with standard add/lookup/delete functions */
+	efd_value_t prev_value;
+	data[1] = mrand48() & ((1 << RTE_EFD_VALUE_NUM_BITS) - 1);
+
+	handle = rte_efd_create("test_add_update_delete", TABLE_SIZE,
+			sizeof(struct flow_key),
+			efd_get_all_sockets_bitmask(), test_socket_id);
+	TEST_ASSERT_NOT_NULL(handle, "Error creating the efd table\n");
+
+	TEST_ASSERT_SUCCESS(rte_efd_update(handle, test_socket_id, &keys[1],
+			data[1]), "Error inserting the key");
+	print_key_info("Add", &keys[1], data[1]);
+
+	TEST_ASSERT_EQUAL(rte_efd_lookup(handle, test_socket_id, &keys[1]),
+			data[1], "failed to find key");
+	print_key_info("Lkp", &keys[1], data[1]);
+
+	data[1] = data[1] + 1;
+	TEST_ASSERT_SUCCESS(rte_efd_update(handle, test_socket_id, &keys[1],
+			data[1]), "Error re-inserting the key");
+	print_key_info("Add", &keys[1], data[1]);
+
+	TEST_ASSERT_EQUAL(rte_efd_lookup(handle, test_socket_id, &keys[1]),
+			data[1], "failed to find key");
+	print_key_info("Lkp", &keys[1], data[1]);
+
+	TEST_ASSERT_SUCCESS(rte_efd_delete(handle, test_socket_id, &keys[1],
+			&prev_value), "failed to delete key");
+	TEST_ASSERT_EQUAL(prev_value, data[1],
+			"failed to delete the expected value, got %d, "
+			"expected %d", prev_value, data[1]);
+	print_key_info("Del", &keys[1], data[1]);
+
+
+	rte_efd_free(handle);
+	return 0;
+}
+
+/*
+ * Sequence of operations for find existing EFD table
+ *
+ *  - create table
+ *  - find existing table: hit
+ *  - find non-existing table: miss
+ *
+ */
+static int test_efd_find_existing(void)
+{
+	struct rte_efd_table *handle = NULL, *result = NULL;
+
+	printf("Entering %s\n", __func__);
+
+	/* Create EFD table. */
+	handle = rte_efd_create("efd_find_existing", TABLE_SIZE,
+			sizeof(struct flow_key),
+			efd_get_all_sockets_bitmask(), test_socket_id);
+	TEST_ASSERT_NOT_NULL(handle, "Error creating the efd table\n");
+
+	/* Try to find existing EFD table */
+	result = rte_efd_find_existing("efd_find_existing");
+	TEST_ASSERT_EQUAL(result, handle, "could not find existing efd table");
+
+	/* Try to find non-existing EFD table */
+	result = rte_efd_find_existing("efd_find_non_existing");
+	TEST_ASSERT_NULL(result, "found table that shouldn't exist");
+
+	/* Cleanup. */
+	rte_efd_free(handle);
+
+	return 0;
+}
+
+/*
+ * Sequence of operations for 5 keys
+ *      - add keys
+ *      - lookup keys: hit  (bulk)
+ *      - add keys (update)
+ *      - lookup keys: hit (updated data)
+ *      - delete keys : hit
+ */
+static int test_five_keys(void)
+{
+	struct rte_efd_table *handle;
+	const void *key_array[5] = {0};
+	efd_value_t result[5] = {0};
+	efd_value_t prev_value;
+	unsigned int i;
+	printf("Entering %s\n", __func__);
+
+	handle = rte_efd_create("test_five_keys", TABLE_SIZE,
+			sizeof(struct flow_key),
+			efd_get_all_sockets_bitmask(), test_socket_id);
+	TEST_ASSERT_NOT_NULL(handle, "Error creating the efd table\n");
+
+	/* Setup data */
+	for (i = 0; i < 5; i++)
+		data[i] = mrand48() & ((1 << RTE_EFD_VALUE_NUM_BITS) - 1);
+
+	/* Add */
+	for (i = 0; i < 5; i++) {
+		TEST_ASSERT_SUCCESS(rte_efd_update(handle, test_socket_id,
+				&keys[i], data[i]),
+				"Error inserting the key");
+		print_key_info("Add", &keys[i], data[i]);
+	}
+
+	/* Lookup */
+	for (i = 0; i < 5; i++)
+		key_array[i] = &keys[i];
+
+	rte_efd_lookup_bulk(handle, test_socket_id, 5,
+			(const void **) (void *) &key_array, result);
+
+	for (i = 0; i < 5; i++) {
+		TEST_ASSERT_EQUAL(result[i], data[i],
+				"bulk: failed to find key. Expected %d, got %d",
+				data[i], result[i]);
+		print_key_info("Lkp", &keys[i], data[i]);
+	}
+
+	/* Modify data (bulk) */
+	for (i = 0; i < 5; i++)
+		data[i] = data[i] + 1;
+
+	/* Add - update */
+	for (i = 0; i < 5; i++) {
+		TEST_ASSERT_SUCCESS(rte_efd_update(handle, test_socket_id,
+				&keys[i], data[i]),
+				"Error inserting the key");
+		print_key_info("Add", &keys[i], data[i]);
+	}
+
+	/* Lookup */
+	for (i = 0; i < 5; i++) {
+		TEST_ASSERT_EQUAL(rte_efd_lookup(handle, test_socket_id,
+				&keys[i]), data[i],
+				"failed to find key");
+		print_key_info("Lkp", &keys[i], data[i]);
+	}
+
+	/* Delete */
+	for (i = 0; i < 5; i++) {
+		TEST_ASSERT_SUCCESS(rte_efd_delete(handle, test_socket_id,
+				&keys[i], &prev_value),
+				"failed to delete key");
+		TEST_ASSERT_EQUAL(prev_value, data[i],
+				"failed to delete the expected value, got %d, "
+				"expected %d", prev_value, data[i]);
+		print_key_info("Del", &keys[i], data[i]);
+	}
+
+
+	rte_efd_free(handle);
+
+	return 0;
+}
+
+/*
+ * Test to see the average table utilization (entries added/max entries)
+ * before hitting a random entry that cannot be added
+ */
+static int test_average_table_utilization(void)
+{
+	struct rte_efd_table *handle = NULL;
+	uint32_t num_rules_in = TABLE_SIZE;
+	uint8_t simple_key[EFD_TEST_KEY_LEN];
+	unsigned int i, j;
+	unsigned int added_keys, average_keys_added = 0;
+
+	printf("Evaluating table utilization and correctness, please wait\n");
+	fflush(stdout);
+
+	for (j = 0; j < ITERATIONS; j++) {
+		handle = rte_efd_create("test_efd", num_rules_in,
+				EFD_TEST_KEY_LEN, efd_get_all_sockets_bitmask(),
+				test_socket_id);
+		if (handle == NULL) {
+			printf("efd table creation failed\n");
+			return -1;
+		}
+
+		unsigned int succeeded = 0;
+		unsigned int lost_keys = 0;
+
+		/* Add random entries until key cannot be added */
+		for (added_keys = 0; added_keys < num_rules_in; added_keys++) {
+
+			for (i = 0; i < EFD_TEST_KEY_LEN; i++)
+				simple_key[i] = rte_rand() & 0xFF;
+
+			efd_value_t val = simple_key[0];
+
+			if (rte_efd_update(handle, test_socket_id, simple_key,
+						val))
+				break; /* continue;*/
+			if (rte_efd_lookup(handle, test_socket_id, simple_key)
+					!= val)
+				lost_keys++;
+			else
+				succeeded++;
+		}
+
+		average_keys_added += succeeded;
+
+		/* Reset the table */
+		rte_efd_free(handle);
+
+		/* Print progress on operations */
+		printf("Added %10u	Succeeded %10u	Lost %10u\n",
+				added_keys, succeeded, lost_keys);
+		fflush(stdout);
+	}
+
+	average_keys_added /= ITERATIONS;
+
+	printf("\nAverage table utilization = %.2f%% (%u/%u)\n",
+			((double) average_keys_added / num_rules_in * 100),
+			average_keys_added, num_rules_in);
+
+	return 0;
+}
+
+/*
+ * Do tests for EFD creation with bad parameters.
+ */
+static int test_efd_creation_with_bad_parameters(void)
+{
+	struct rte_efd_table *handle, *tmp;
+	printf("Entering %s, **Errors are expected **\n", __func__);
+
+	handle = rte_efd_create("creation_with_bad_parameters_0", TABLE_SIZE, 0,
+			efd_get_all_sockets_bitmask(), test_socket_id);
+	if (handle != NULL) {
+		rte_efd_free(handle);
+		printf("Impossible creating EFD table successfully "
+			"if key_len in parameter is zero\n");
+		return -1;
+	}
+
+	handle = rte_efd_create("creation_with_bad_parameters_1", TABLE_SIZE,
+			sizeof(struct flow_key), 0, test_socket_id);
+	if (handle != NULL) {
+		rte_efd_free(handle);
+		printf("Impossible creating EFD table successfully "
+			"with invalid socket bitmask\n");
+		return -1;
+	}
+
+	handle = rte_efd_create("creation_with_bad_parameters_2", TABLE_SIZE,
+			sizeof(struct flow_key), efd_get_all_sockets_bitmask(),
+			255);
+	if (handle != NULL) {
+		rte_efd_free(handle);
+		printf("Impossible creating EFD table successfully "
+			"with invalid socket\n");
+		return -1;
+	}
+
+	/* test with same name should fail */
+	handle = rte_efd_create("same_name", TABLE_SIZE,
+			sizeof(struct flow_key),
+			efd_get_all_sockets_bitmask(), 0);
+	if (handle == NULL) {
+		printf("Cannot create first EFD table with 'same_name'\n");
+		return -1;
+	}
+	tmp = rte_efd_create("same_name", TABLE_SIZE, sizeof(struct flow_key),
+			efd_get_all_sockets_bitmask(), 0);
+	if (tmp != NULL) {
+		printf("Creation of EFD table with same name should fail\n");
+		rte_efd_free(handle);
+		rte_efd_free(tmp);
+		return -1;
+	}
+	rte_efd_free(handle);
+
+	printf("# Test successful. No more errors expected\n");
+
+	return 0;
+}
+
+static int
+test_efd(void)
+{
+
+	/* Unit tests */
+	if (test_add_delete() < 0)
+		return -1;
+	if (test_efd_find_existing() < 0)
+		return -1;
+	if (test_add_update_delete() < 0)
+		return -1;
+	if (test_five_keys() < 0)
+		return -1;
+	if (test_efd_creation_with_bad_parameters() < 0)
+		return -1;
+	if (test_average_table_utilization() < 0)
+		return -1;
+
+	return 0;
+}
+
+REGISTER_TEST_COMMAND(efd_autotest, test_efd);
diff --git a/app/test/test_efd_perf.c b/app/test/test_efd_perf.c
new file mode 100644
index 0000000..998a25b
--- /dev/null
+++ b/app/test/test_efd_perf.c
@@ -0,0 +1,407 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016-2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <inttypes.h>
+
+#include <rte_lcore.h>
+#include <rte_cycles.h>
+#include <rte_malloc.h>
+#include <rte_random.h>
+#include <rte_efd.h>
+#include <rte_memcpy.h>
+#include <rte_thash.h>
+
+#include "test.h"
+#define NUM_KEYSIZES 10
+#define NUM_SHUFFLES 10
+#define MAX_KEYSIZE 64
+#define MAX_ENTRIES (1 << 19)
+#define KEYS_TO_ADD (MAX_ENTRIES * 3 / 4) /* 75% table utilization */
+#define NUM_LOOKUPS (KEYS_TO_ADD * 5) /* Loop among keys added, several times */
+static unsigned int test_socket_id;
+
+static inline uint8_t efd_get_all_sockets_bitmask(void)
+{
+	uint8_t all_cpu_sockets_bitmask = 0;
+	unsigned int i;
+	unsigned int next_lcore = rte_get_master_lcore();
+	const int val_true = 1, val_false = 0;
+	for (i = 0; i < rte_lcore_count(); i++) {
+		all_cpu_sockets_bitmask |= 1 << rte_lcore_to_socket_id(next_lcore);
+		next_lcore = rte_get_next_lcore(next_lcore, val_false, val_true);
+	}
+
+	return all_cpu_sockets_bitmask;
+}
+
+enum operations {
+	ADD = 0,
+	LOOKUP,
+	LOOKUP_MULTI,
+	DELETE,
+	NUM_OPERATIONS
+};
+
+struct efd_perf_params {
+	struct rte_efd_table *efd_table;
+	uint32_t key_size;
+	unsigned int cycle;
+};
+
+static uint32_t hashtest_key_lens[] = {
+	/* standard key sizes */
+	4, 8, 16, 32, 48, 64,
+	/* IPv4 SRC + DST + protocol, unpadded */
+	9,
+	/* IPv4 5-tuple, unpadded */
+	13,
+	/* IPv6 5-tuple, unpadded */
+	37,
+	/* IPv6 5-tuple, padded to 8-byte boundary */
+	40
+};
+
+/* Array to store number of cycles per operation */
+uint64_t cycles[NUM_KEYSIZES][NUM_OPERATIONS];
+
+/* Array to store the data */
+efd_value_t data[KEYS_TO_ADD];
+
+/* Array to store all input keys */
+uint8_t keys[KEYS_TO_ADD][MAX_KEYSIZE];
+
+/* Shuffle the keys that have been added, so lookups will be totally random */
+static void
+shuffle_input_keys(struct efd_perf_params *params)
+{
+	efd_value_t temp_data;
+	unsigned int i;
+	uint32_t swap_idx;
+	uint8_t temp_key[MAX_KEYSIZE];
+
+	for (i = KEYS_TO_ADD - 1; i > 0; i--) {
+		swap_idx = rte_rand() % i;
+
+		memcpy(temp_key, keys[i], hashtest_key_lens[params->cycle]);
+		temp_data = data[i];
+
+		memcpy(keys[i], keys[swap_idx], hashtest_key_lens[params->cycle]);
+		data[i] = data[swap_idx];
+
+		memcpy(keys[swap_idx], temp_key, hashtest_key_lens[params->cycle]);
+		data[swap_idx] = temp_data;
+	}
+}
+
+static int key_compare(const void *key1, const void *key2)
+{
+	return memcmp(key1, key2, MAX_KEYSIZE);
+}
+
+/*
+ * TODO: we could "error proof" these as done in test_hash_perf.c ln 165:
+ *
+ * The current setup may give errors if too full in some cases which we check
+ * for. However, since EFD allows for ~99% capacity, these errors are rare for
+ * #"KEYS_TO_ADD" which is 75% capacity.
+ */
+static int
+setup_keys_and_data(struct efd_perf_params *params, unsigned int cycle)
+{
+	unsigned int i, j;
+	int num_duplicates;
+
+	params->key_size = hashtest_key_lens[cycle];
+	params->cycle = cycle;
+
+	/* Reset all arrays */
+	for (i = 0; i < params->key_size; i++)
+		keys[0][i] = 0;
+
+	/* Generate a list of keys, some of which may be duplicates */
+	for (i = 0; i < KEYS_TO_ADD; i++) {
+		for (j = 0; j < params->key_size; j++)
+			keys[i][j] = rte_rand() & 0xFF;
+
+		data[i] = rte_rand() & ((1 << RTE_EFD_VALUE_NUM_BITS) - 1);
+	}
+
+	/* Remove duplicates from the keys array */
+	do {
+		num_duplicates = 0;
+
+		/* Sort the list of keys to make it easier to find duplicates */
+		qsort(keys, KEYS_TO_ADD, MAX_KEYSIZE, key_compare);
+
+		/* Sift through the list of keys and look for duplicates */
+		int num_duplicates = 0;
+		for (i = 0; i < KEYS_TO_ADD - 1; i++) {
+			if (memcmp(keys[i], keys[i + 1], params->key_size) == 0) {
+				/* This key already exists, try again */
+				num_duplicates++;
+				for (j = 0; j < params->key_size; j++)
+					keys[i][j] = rte_rand() & 0xFF;
+			}
+		}
+	} while (num_duplicates != 0);
+
+	/* Shuffle the random values again */
+	shuffle_input_keys(params);
+
+	params->efd_table = rte_efd_create("test_efd_perf",
+			MAX_ENTRIES, params->key_size,
+			efd_get_all_sockets_bitmask(), test_socket_id);
+	TEST_ASSERT_NOT_NULL(params->efd_table, "Error creating the efd table\n");
+
+	return 0;
+}
+
+static int
+timed_adds(struct efd_perf_params *params)
+{
+	const uint64_t start_tsc = rte_rdtsc();
+	unsigned int i, a;
+	int32_t ret;
+
+	for (i = 0; i < KEYS_TO_ADD; i++) {
+		ret = rte_efd_update(params->efd_table, test_socket_id, keys[i],
+				data[i]);
+		if (ret != 0) {
+			printf("Error %d in rte_efd_update - key=0x", ret);
+			for (a = 0; a < params->key_size; a++)
+				printf("%02x", keys[i][a]);
+			printf(" value=%d\n", data[i]);
+
+			return -1;
+		}
+	}
+
+	const uint64_t end_tsc = rte_rdtsc();
+	const uint64_t time_taken = end_tsc - start_tsc;
+
+	cycles[params->cycle][ADD] = time_taken / KEYS_TO_ADD;
+	return 0;
+}
+
+static int
+timed_lookups(struct efd_perf_params *params)
+{
+	unsigned int i, j, a;
+	const uint64_t start_tsc = rte_rdtsc();
+	efd_value_t ret_data;
+
+	for (i = 0; i < NUM_LOOKUPS / KEYS_TO_ADD; i++) {
+		for (j = 0; j < KEYS_TO_ADD; j++) {
+			ret_data = rte_efd_lookup(params->efd_table,
+					test_socket_id, keys[j]);
+			if (ret_data != data[j]) {
+				printf("Value mismatch using rte_efd_lookup: "
+						"key #%d (0x", i);
+				for (a = 0; a < params->key_size; a++)
+					printf("%02x", keys[i][a]);
+				printf(")\n");
+				printf("  Expected %d, got %d\n", data[i],
+						ret_data);
+
+				return -1;
+			}
+
+		}
+	}
+
+	const uint64_t end_tsc = rte_rdtsc();
+	const uint64_t time_taken = end_tsc - start_tsc;
+
+	cycles[params->cycle][LOOKUP] = time_taken / NUM_LOOKUPS;
+
+	return 0;
+}
+
+static int
+timed_lookups_multi(struct efd_perf_params *params)
+{
+	unsigned int i, j, k, a;
+	efd_value_t result[RTE_EFD_BURST_MAX] = {0};
+	const void *keys_burst[RTE_EFD_BURST_MAX];
+	const uint64_t start_tsc = rte_rdtsc();
+
+	for (i = 0; i < NUM_LOOKUPS / KEYS_TO_ADD; i++) {
+		for (j = 0; j < KEYS_TO_ADD / RTE_EFD_BURST_MAX; j++) {
+			for (k = 0; k < RTE_EFD_BURST_MAX; k++)
+				keys_burst[k] = keys[j * RTE_EFD_BURST_MAX + k];
+
+			rte_efd_lookup_bulk(params->efd_table, test_socket_id,
+					RTE_EFD_BURST_MAX,
+					keys_burst, result);
+
+			for (k = 0; k < RTE_EFD_BURST_MAX; k++) {
+				uint32_t data_idx = j * RTE_EFD_BURST_MAX + k;
+				if (result[k] != data[data_idx]) {
+					printf("Value mismatch using "
+						"rte_efd_lookup_bulk: key #%d "
+						"(0x", i);
+					for (a = 0; a < params->key_size; a++)
+						printf("%02x",
+							keys[data_idx][a]);
+					printf(")\n");
+					printf("  Expected %d, got %d\n",
+						data[data_idx], result[k]);
+
+					return -1;
+				}
+			}
+		}
+	}
+
+	const uint64_t end_tsc = rte_rdtsc();
+	const uint64_t time_taken = end_tsc - start_tsc;
+
+	cycles[params->cycle][LOOKUP_MULTI] = time_taken / NUM_LOOKUPS;
+
+	return 0;
+}
+
+static int
+timed_deletes(struct efd_perf_params *params)
+{
+	unsigned int i, a;
+	const uint64_t start_tsc = rte_rdtsc();
+	int32_t ret;
+
+	for (i = 0; i < KEYS_TO_ADD; i++) {
+		ret = rte_efd_delete(params->efd_table, test_socket_id, keys[i],
+				NULL);
+
+		if (ret != 0) {
+			printf("Error %d in rte_efd_delete - key=0x", ret);
+			for (a = 0; a < params->key_size; a++)
+				printf("%02x", keys[i][a]);
+			printf("\n");
+
+			return -1;
+		}
+	}
+
+	const uint64_t end_tsc = rte_rdtsc();
+	const uint64_t time_taken = end_tsc - start_tsc;
+
+	cycles[params->cycle][DELETE] = time_taken / KEYS_TO_ADD;
+
+	return 0;
+}
+
+static void
+perform_frees(struct efd_perf_params *params)
+{
+	if (params->efd_table != NULL) {
+		rte_efd_free(params->efd_table);
+		params->efd_table = NULL;
+	}
+}
+
+static int
+exit_with_fail(const char *testname, struct efd_perf_params *params,
+		unsigned int i)
+{
+
+	printf("<<<<<Test %s failed at keysize %d iteration %d >>>>>\n",
+			testname, hashtest_key_lens[params->cycle], i);
+	perform_frees(params);
+	return -1;
+}
+
+static int
+run_all_tbl_perf_tests(void)
+{
+	unsigned int i, j;
+	struct efd_perf_params params;
+
+	printf("Measuring performance, please wait\n");
+	fflush(stdout);
+
+	test_socket_id = rte_socket_id();
+
+	for (i = 0; i < NUM_KEYSIZES; i++) {
+
+		if (setup_keys_and_data(&params, i) < 0) {
+			printf("Could not create keys/data/table\n");
+			return -1;
+		}
+
+		if (timed_adds(&params) < 0)
+			return exit_with_fail("timed_adds", &params, i);
+
+		for (j = 0; j < NUM_SHUFFLES; j++)
+			shuffle_input_keys(&params);
+
+		if (timed_lookups(&params) < 0)
+			return exit_with_fail("timed_lookups", &params, i);
+
+		if (timed_lookups_multi(&params) < 0)
+			return exit_with_fail("timed_lookups_multi", &params, i);
+
+		if (timed_deletes(&params) < 0)
+			return exit_with_fail("timed_deletes", &params, i);
+
+		/* Print a dot to show progress on operations */
+		printf(".");
+		fflush(stdout);
+
+		perform_frees(&params);
+	}
+
+	printf("\nResults (in CPU cycles/operation)\n");
+	printf("-----------------------------------\n");
+	printf("\n%-18s%-18s%-18s%-18s%-18s\n",
+			"Keysize", "Add", "Lookup", "Lookup_bulk", "Delete");
+	for (i = 0; i < NUM_KEYSIZES; i++) {
+		printf("%-18d", hashtest_key_lens[i]);
+		for (j = 0; j < NUM_OPERATIONS; j++)
+			printf("%-18"PRIu64, cycles[i][j]);
+		printf("\n");
+	}
+	return 0;
+}
+
+static int
+test_efd_perf(void)
+{
+
+	if (run_all_tbl_perf_tests() < 0)
+		return -1;
+
+	return 0;
+}
+
+REGISTER_TEST_COMMAND(efd_perf_autotest, test_efd_perf);
-- 
2.7.4

  parent reply	other threads:[~2017-01-12 22:15 UTC|newest]

Thread overview: 63+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-12-02 14:52 [PATCH 0/2] Elastic Flow Distributor Pablo de Lara
2016-12-02 14:52 ` [PATCH 1/2] efd: new Elastic Flow Distributor library Pablo de Lara
2016-12-02 14:52 ` [PATCH 2/2] examples/flow_distributor: sample app to demonstrate EFD usage Pablo de Lara
2017-01-07  1:06 ` [PATCH v2 0/5] Elastic Flow Distributor Pablo de Lara
2017-01-07  1:06   ` [PATCH v2 1/5] efd: new Elastic Flow Distributor library Pablo de Lara
2017-01-07  1:06   ` [PATCH v2 2/5] app/test: add EFD functional and perf tests Pablo de Lara
2017-01-07  1:06   ` [PATCH v2 3/5] examples/flow_distributor: sample app to demonstrate EFD usage Pablo de Lara
2017-01-07  1:06   ` [PATCH v2 4/5] doc: add EFD library section in Programmers guide Pablo de Lara
2017-01-07  1:06   ` [PATCH v2 5/5] doc: add flow distributor guide Pablo de Lara
2017-01-09 18:19   ` [PATCH v2 0/5] Elastic Flow Distributor Maciocco, Christian
2017-01-12 22:15   ` [PATCH v3 " Pablo de Lara
2017-01-12 22:15     ` [PATCH v3 1/5] efd: new Elastic Flow Distributor library Pablo de Lara
2017-01-12 22:15     ` Pablo de Lara [this message]
2017-01-12 22:15     ` [PATCH v3 3/5] examples/flow_distributor: sample app to demonstrate EFD usage Pablo de Lara
2017-01-12 22:15     ` [PATCH v3 4/5] doc: add EFD library section in Programmers guide Pablo de Lara
2017-01-12 22:16     ` [PATCH v3 5/5] doc: add flow distributor guide Pablo de Lara
2017-01-15 12:04     ` [PATCH v4 0/5] Elastic Flow Distributor Pablo de Lara
2017-01-15 12:04       ` [PATCH v4 1/5] efd: new Elastic Flow Distributor library Pablo de Lara
2017-01-16  4:25         ` Jerin Jacob
2017-01-16 15:34           ` De Lara Guarch, Pablo
2017-01-15 12:04       ` [PATCH v4 2/5] app/test: add EFD functional and perf tests Pablo de Lara
2017-01-15 12:04       ` [PATCH v4 3/5] examples/flow_distributor: sample app to demonstrate EFD usage Pablo de Lara
2017-01-15 12:04       ` [PATCH v4 4/5] doc: add EFD library section in Programmers guide Pablo de Lara
2017-01-16  4:15         ` Jerin Jacob
2017-01-16 15:33           ` De Lara Guarch, Pablo
2017-01-15 12:04       ` [PATCH v4 5/5] doc: add flow distributor guide Pablo de Lara
2017-01-16  9:43       ` [PATCH v5 0/5] Elastic Flow Distributor Pablo de Lara
2017-01-16  9:43         ` [PATCH v5 1/5] efd: new Elastic Flow Distributor library Pablo de Lara
2017-01-16  9:43         ` [PATCH v5 2/5] app/test: add EFD functional and perf tests Pablo de Lara
2017-01-16  9:43         ` [PATCH v5 3/5] examples/flow_distributor: sample app to demonstrate EFD usage Pablo de Lara
2017-01-16  9:43         ` [PATCH v5 4/5] doc: add EFD library section in Programmers guide Pablo de Lara
2017-01-16  9:43         ` [PATCH v5 5/5] doc: add flow distributor guide Pablo de Lara
2017-01-16 15:08         ` [PATCH v5 0/5] Elastic Flow Distributor Thomas Monjalon
2017-01-17  8:34           ` De Lara Guarch, Pablo
2017-01-16 19:21         ` [PATCH v6 " Pablo de Lara
2017-01-16 19:21           ` [PATCH v6 1/5] efd: new Elastic Flow Distributor library Pablo de Lara
2017-01-17 20:32             ` Thomas Monjalon
2017-01-17 21:11             ` Thomas Monjalon
2017-01-16 19:21           ` [PATCH v6 2/5] app/test: add EFD functional and perf tests Pablo de Lara
2017-01-16 19:21           ` [PATCH v6 3/5] examples/flow_distributor: sample app to demonstrate EFD usage Pablo de Lara
2017-01-16 19:21           ` [PATCH v6 4/5] doc: add EFD library section in Programmers guide Pablo de Lara
2017-01-16 19:21           ` [PATCH v6 5/5] doc: add flow distributor guide Pablo de Lara
2017-01-17 20:35             ` Thomas Monjalon
2017-01-17 20:29           ` [PATCH v6 0/5] Elastic Flow Distributor Thomas Monjalon
2017-01-17 22:10           ` [PATCH v7 0/6] " Pablo de Lara
2017-01-17 22:10             ` [PATCH v7 1/6] efd: new Elastic Flow Distributor library Pablo de Lara
2017-01-17 22:10             ` [PATCH v7 2/6] efd: add AVX2 vect lookup function Pablo de Lara
2017-01-17 22:10             ` [PATCH v7 3/6] app/test: add EFD functional and perf tests Pablo de Lara
2017-01-17 22:10             ` [PATCH v7 4/6] examples/flow_distributor: sample app to demonstrate EFD usage Pablo de Lara
2017-01-17 22:10             ` [PATCH v7 5/6] doc: add EFD library section in Programmers guide Pablo de Lara
2017-01-17 22:10             ` [PATCH v7 6/6] doc: add flow distributor guide Pablo de Lara
2017-01-17 22:18             ` [PATCH v7 0/6] Elastic Flow Distributor De Lara Guarch, Pablo
2017-01-17 22:23             ` [PATCH v8 " Pablo de Lara
2017-01-17 22:23               ` [PATCH v8 1/6] efd: new Elastic Flow Distributor library Pablo de Lara
2017-01-18 18:56                 ` Thomas Monjalon
2017-01-18 19:27                   ` De Lara Guarch, Pablo
2017-01-18 19:44                     ` Thomas Monjalon
2017-01-17 22:23               ` [PATCH v8 2/6] efd: add AVX2 vect lookup function Pablo de Lara
2017-01-17 22:23               ` [PATCH v8 3/6] app/test: add EFD functional and perf tests Pablo de Lara
2017-01-17 22:23               ` [PATCH v8 4/6] examples/flow_distributor: sample app to demonstrate EFD usage Pablo de Lara
2017-01-17 22:23               ` [PATCH v8 5/6] doc: add EFD library section in Programmers guide Pablo de Lara
2017-01-17 22:23               ` [PATCH v8 6/6] doc: add flow distributor guide Pablo de Lara
2017-01-18 19:57               ` [PATCH v8 0/6] Elastic Flow Distributor Thomas Monjalon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1484259360-198276-3-git-send-email-pablo.de.lara.guarch@intel.com \
    --to=pablo.de.lara.guarch@intel.com \
    --cc=byron.marohn@intel.com \
    --cc=dev@dpdk.org \
    --cc=karla.saur@intel.com \
    --cc=saikrishna.edupuganti@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.