X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=app%2Ftest%2Ftest_lpm_perf.c;h=e858716f909b5c1469c135b47cb775e3ae64b321;hb=ecdc927b99f2bdf3e5951998c7fda9726071bc38;hp=58076795ec3aff02974418a847f0c4e93b2912cf;hpb=0f392d91b9977fdb879ef595839806c29b150c14;p=dpdk.git diff --git a/app/test/test_lpm_perf.c b/app/test/test_lpm_perf.c index 58076795ec..e858716f90 100644 --- a/app/test/test_lpm_perf.c +++ b/app/test/test_lpm_perf.c @@ -3,6 +3,17 @@ * Copyright(c) 2020 Arm Limited */ +#include "test.h" + +#ifdef RTE_EXEC_ENV_WINDOWS +static int +test_lpm_perf(void) +{ + printf("lpm_perf not supported on Windows, skipping test\n"); + return TEST_SKIPPED; +} + +#else #include #include #include @@ -15,7 +26,6 @@ #include #include -#include "test.h" #include "test_xmmt_ops.h" struct rte_lpm *lpm; @@ -23,7 +33,7 @@ static struct rte_rcu_qsbr *rv; static volatile uint8_t writer_done; static volatile uint32_t thr_id; static uint64_t gwrite_cycles; -static uint64_t gwrites; +static uint32_t num_writers; /* LPM APIs are not thread safe, use mutex to provide thread safety */ static pthread_mutex_t lpm_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -60,6 +70,8 @@ static uint32_t num_ldepth_route_entries; #define NUM_ROUTE_ENTRIES num_route_entries #define NUM_LDEPTH_ROUTE_ENTRIES num_ldepth_route_entries +#define TOTAL_WRITES (RCU_ITERATIONS * NUM_LDEPTH_ROUTE_ENTRIES) + enum { IP_CLASS_A, IP_CLASS_B, @@ -429,362 +441,154 @@ test_lpm_rcu_qsbr_writer(void *arg) { unsigned int i, j, si, ei; uint64_t begin, total_cycles; - uint8_t core_id = (uint8_t)((uintptr_t)arg); uint32_t next_hop_add = 0xAA; + uint8_t pos_core = (uint8_t)((uintptr_t)arg); - RTE_SET_USED(arg); - /* 2 writer threads are used */ - if (core_id % 2 == 0) { - si = 0; - ei = NUM_LDEPTH_ROUTE_ENTRIES / 2; - } else { - si = NUM_LDEPTH_ROUTE_ENTRIES / 2; - ei = NUM_LDEPTH_ROUTE_ENTRIES; - } + si = (pos_core * NUM_LDEPTH_ROUTE_ENTRIES) / num_writers; + ei = ((pos_core + 1) * NUM_LDEPTH_ROUTE_ENTRIES) / num_writers; /* Measure add/delete. */ begin = rte_rdtsc_precise(); for (i = 0; i < RCU_ITERATIONS; i++) { /* Add all the entries */ for (j = si; j < ei; j++) { - pthread_mutex_lock(&lpm_mutex); + if (num_writers > 1) + pthread_mutex_lock(&lpm_mutex); if (rte_lpm_add(lpm, large_ldepth_route_table[j].ip, large_ldepth_route_table[j].depth, next_hop_add) != 0) { printf("Failed to add iteration %d, route# %d\n", i, j); + goto error; } - pthread_mutex_unlock(&lpm_mutex); + if (num_writers > 1) + pthread_mutex_unlock(&lpm_mutex); } /* Delete all the entries */ for (j = si; j < ei; j++) { - pthread_mutex_lock(&lpm_mutex); + if (num_writers > 1) + pthread_mutex_lock(&lpm_mutex); if (rte_lpm_delete(lpm, large_ldepth_route_table[j].ip, large_ldepth_route_table[j].depth) != 0) { printf("Failed to delete iteration %d, route# %d\n", i, j); + goto error; } - pthread_mutex_unlock(&lpm_mutex); + if (num_writers > 1) + pthread_mutex_unlock(&lpm_mutex); } } total_cycles = rte_rdtsc_precise() - begin; __atomic_fetch_add(&gwrite_cycles, total_cycles, __ATOMIC_RELAXED); - __atomic_fetch_add(&gwrites, - 2 * NUM_LDEPTH_ROUTE_ENTRIES * RCU_ITERATIONS, - __ATOMIC_RELAXED); - - return 0; -} - -/* - * Functional test: - * 2 writers, rest are readers - */ -static int -test_lpm_rcu_perf_multi_writer(void) -{ - struct rte_lpm_config config; - size_t sz; - unsigned int i; - uint16_t core_id; - struct rte_lpm_rcu_config rcu_cfg = {0}; - - if (rte_lcore_count() < 3) { - printf("Not enough cores for lpm_rcu_perf_autotest, expecting at least 3\n"); - return TEST_SKIPPED; - } - - num_cores = 0; - RTE_LCORE_FOREACH_SLAVE(core_id) { - enabled_core_ids[num_cores] = core_id; - num_cores++; - } - - printf("\nPerf test: 2 writers, %d readers, RCU integration enabled\n", - num_cores - 2); - - /* Create LPM table */ - config.max_rules = NUM_LDEPTH_ROUTE_ENTRIES; - config.number_tbl8s = NUM_LDEPTH_ROUTE_ENTRIES; - config.flags = 0; - lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config); - TEST_LPM_ASSERT(lpm != NULL); - - /* Init RCU variable */ - sz = rte_rcu_qsbr_get_memsize(num_cores); - rv = (struct rte_rcu_qsbr *)rte_zmalloc("rcu0", sz, - RTE_CACHE_LINE_SIZE); - rte_rcu_qsbr_init(rv, num_cores); - - rcu_cfg.v = rv; - /* Assign the RCU variable to LPM */ - if (rte_lpm_rcu_qsbr_add(lpm, &rcu_cfg) != 0) { - printf("RCU variable assignment failed\n"); - goto error; - } - - writer_done = 0; - __atomic_store_n(&gwrite_cycles, 0, __ATOMIC_RELAXED); - __atomic_store_n(&gwrites, 0, __ATOMIC_RELAXED); - - __atomic_store_n(&thr_id, 0, __ATOMIC_SEQ_CST); - - /* Launch reader threads */ - for (i = 2; i < num_cores; i++) - rte_eal_remote_launch(test_lpm_rcu_qsbr_reader, NULL, - enabled_core_ids[i]); - - /* Launch writer threads */ - for (i = 0; i < 2; i++) - rte_eal_remote_launch(test_lpm_rcu_qsbr_writer, - (void *)(uintptr_t)i, - enabled_core_ids[i]); - - /* Wait for writer threads */ - for (i = 0; i < 2; i++) - if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0) - goto error; - - printf("Total LPM Adds: %d\n", - 2 * ITERATIONS * NUM_LDEPTH_ROUTE_ENTRIES); - printf("Total LPM Deletes: %d\n", - 2 * ITERATIONS * NUM_LDEPTH_ROUTE_ENTRIES); - printf("Average LPM Add/Del: %"PRIu64" cycles\n", - __atomic_load_n(&gwrite_cycles, __ATOMIC_RELAXED) / - __atomic_load_n(&gwrites, __ATOMIC_RELAXED) - ); - - /* Wait and check return value from reader threads */ - writer_done = 1; - for (i = 2; i < num_cores; i++) - if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0) - goto error; - - rte_lpm_free(lpm); - rte_free(rv); - lpm = NULL; - rv = NULL; - - /* Test without RCU integration */ - printf("\nPerf test: 2 writers, %d readers, RCU integration disabled\n", - num_cores - 2); - - /* Create LPM table */ - config.max_rules = NUM_LDEPTH_ROUTE_ENTRIES; - config.number_tbl8s = NUM_LDEPTH_ROUTE_ENTRIES; - config.flags = 0; - lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config); - TEST_LPM_ASSERT(lpm != NULL); - - writer_done = 0; - __atomic_store_n(&gwrite_cycles, 0, __ATOMIC_RELAXED); - __atomic_store_n(&gwrites, 0, __ATOMIC_RELAXED); - __atomic_store_n(&thr_id, 0, __ATOMIC_SEQ_CST); - - /* Launch reader threads */ - for (i = 2; i < num_cores; i++) - rte_eal_remote_launch(test_lpm_reader, NULL, - enabled_core_ids[i]); - - /* Launch writer threads */ - for (i = 0; i < 2; i++) - rte_eal_remote_launch(test_lpm_rcu_qsbr_writer, - (void *)(uintptr_t)i, - enabled_core_ids[i]); - - /* Wait for writer threads */ - for (i = 0; i < 2; i++) - if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0) - goto error; - - printf("Total LPM Adds: %d\n", - 2 * ITERATIONS * NUM_LDEPTH_ROUTE_ENTRIES); - printf("Total LPM Deletes: %d\n", - 2 * ITERATIONS * NUM_LDEPTH_ROUTE_ENTRIES); - printf("Average LPM Add/Del: %"PRIu64" cycles\n", - __atomic_load_n(&gwrite_cycles, __ATOMIC_RELAXED) / - __atomic_load_n(&gwrites, __ATOMIC_RELAXED) - ); - - writer_done = 1; - /* Wait and check return value from reader threads */ - for (i = 2; i < num_cores; i++) - if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0) - goto error; - - rte_lpm_free(lpm); return 0; error: - writer_done = 1; - /* Wait until all readers have exited */ - rte_eal_mp_wait_lcore(); - - rte_lpm_free(lpm); - rte_free(rv); - + if (num_writers > 1) + pthread_mutex_unlock(&lpm_mutex); return -1; } /* * Functional test: - * Single writer, rest are readers + * 1/2 writers, rest are readers */ static int -test_lpm_rcu_perf(void) +test_lpm_rcu_perf_multi_writer(uint8_t use_rcu) { struct rte_lpm_config config; - uint64_t begin, total_cycles; size_t sz; unsigned int i, j; uint16_t core_id; - uint32_t next_hop_add = 0xAA; struct rte_lpm_rcu_config rcu_cfg = {0}; + int (*reader_f)(void *arg) = NULL; - if (rte_lcore_count() < 2) { - printf("Not enough cores for lpm_rcu_perf_autotest, expecting at least 2\n"); + if (rte_lcore_count() < 3) { + printf("Not enough cores for lpm_rcu_perf_autotest, expecting at least 3\n"); return TEST_SKIPPED; } num_cores = 0; - RTE_LCORE_FOREACH_SLAVE(core_id) { + RTE_LCORE_FOREACH_WORKER(core_id) { enabled_core_ids[num_cores] = core_id; num_cores++; } - printf("\nPerf test: 1 writer, %d readers, RCU integration enabled\n", - num_cores); - - /* Create LPM table */ - config.max_rules = NUM_LDEPTH_ROUTE_ENTRIES; - config.number_tbl8s = NUM_LDEPTH_ROUTE_ENTRIES; - config.flags = 0; - lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config); - TEST_LPM_ASSERT(lpm != NULL); - - /* Init RCU variable */ - sz = rte_rcu_qsbr_get_memsize(num_cores); - rv = (struct rte_rcu_qsbr *)rte_zmalloc("rcu0", sz, - RTE_CACHE_LINE_SIZE); - rte_rcu_qsbr_init(rv, num_cores); - - rcu_cfg.v = rv; - /* Assign the RCU variable to LPM */ - if (rte_lpm_rcu_qsbr_add(lpm, &rcu_cfg) != 0) { - printf("RCU variable assignment failed\n"); - goto error; - } - - writer_done = 0; - __atomic_store_n(&thr_id, 0, __ATOMIC_SEQ_CST); - - /* Launch reader threads */ - for (i = 0; i < num_cores; i++) - rte_eal_remote_launch(test_lpm_rcu_qsbr_reader, NULL, - enabled_core_ids[i]); - - /* Measure add/delete. */ - begin = rte_rdtsc_precise(); - for (i = 0; i < RCU_ITERATIONS; i++) { - /* Add all the entries */ - for (j = 0; j < NUM_LDEPTH_ROUTE_ENTRIES; j++) - if (rte_lpm_add(lpm, large_ldepth_route_table[j].ip, - large_ldepth_route_table[j].depth, - next_hop_add) != 0) { - printf("Failed to add iteration %d, route# %d\n", - i, j); - goto error; - } - - /* Delete all the entries */ - for (j = 0; j < NUM_LDEPTH_ROUTE_ENTRIES; j++) - if (rte_lpm_delete(lpm, large_ldepth_route_table[j].ip, - large_ldepth_route_table[j].depth) != 0) { - printf("Failed to delete iteration %d, route# %d\n", - i, j); + for (j = 1; j < 3; j++) { + if (use_rcu) + printf("\nPerf test: %d writer(s), %d reader(s)," + " RCU integration enabled\n", j, num_cores - j); + else + printf("\nPerf test: %d writer(s), %d reader(s)," + " RCU integration disabled\n", j, num_cores - j); + + num_writers = j; + + /* Create LPM table */ + config.max_rules = NUM_LDEPTH_ROUTE_ENTRIES; + config.number_tbl8s = NUM_LDEPTH_ROUTE_ENTRIES; + config.flags = 0; + lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config); + TEST_LPM_ASSERT(lpm != NULL); + + /* Init RCU variable */ + if (use_rcu) { + sz = rte_rcu_qsbr_get_memsize(num_cores); + rv = (struct rte_rcu_qsbr *)rte_zmalloc("rcu0", sz, + RTE_CACHE_LINE_SIZE); + rte_rcu_qsbr_init(rv, num_cores); + + rcu_cfg.v = rv; + /* Assign the RCU variable to LPM */ + if (rte_lpm_rcu_qsbr_add(lpm, &rcu_cfg) != 0) { + printf("RCU variable assignment failed\n"); goto error; } - } - total_cycles = rte_rdtsc_precise() - begin; - printf("Total LPM Adds: %d\n", ITERATIONS * NUM_LDEPTH_ROUTE_ENTRIES); - printf("Total LPM Deletes: %d\n", - ITERATIONS * NUM_LDEPTH_ROUTE_ENTRIES); - printf("Average LPM Add/Del: %g cycles\n", - (double)total_cycles / (NUM_LDEPTH_ROUTE_ENTRIES * ITERATIONS)); + reader_f = test_lpm_rcu_qsbr_reader; + } else + reader_f = test_lpm_reader; - writer_done = 1; - /* Wait and check return value from reader threads */ - for (i = 0; i < num_cores; i++) - if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0) - goto error; - - rte_lpm_free(lpm); - rte_free(rv); - lpm = NULL; - rv = NULL; + writer_done = 0; + __atomic_store_n(&gwrite_cycles, 0, __ATOMIC_RELAXED); - /* Test without RCU integration */ - printf("\nPerf test: 1 writer, %d readers, RCU integration disabled\n", - num_cores); - - /* Create LPM table */ - config.max_rules = NUM_LDEPTH_ROUTE_ENTRIES; - config.number_tbl8s = NUM_LDEPTH_ROUTE_ENTRIES; - config.flags = 0; - lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config); - TEST_LPM_ASSERT(lpm != NULL); + __atomic_store_n(&thr_id, 0, __ATOMIC_SEQ_CST); - writer_done = 0; - __atomic_store_n(&thr_id, 0, __ATOMIC_SEQ_CST); + /* Launch reader threads */ + for (i = j; i < num_cores; i++) + rte_eal_remote_launch(reader_f, NULL, + enabled_core_ids[i]); - /* Launch reader threads */ - for (i = 0; i < num_cores; i++) - rte_eal_remote_launch(test_lpm_reader, NULL, - enabled_core_ids[i]); + /* Launch writer threads */ + for (i = 0; i < j; i++) + rte_eal_remote_launch(test_lpm_rcu_qsbr_writer, + (void *)(uintptr_t)i, + enabled_core_ids[i]); - /* Measure add/delete. */ - begin = rte_rdtsc_precise(); - for (i = 0; i < RCU_ITERATIONS; i++) { - /* Add all the entries */ - for (j = 0; j < NUM_LDEPTH_ROUTE_ENTRIES; j++) - if (rte_lpm_add(lpm, large_ldepth_route_table[j].ip, - large_ldepth_route_table[j].depth, - next_hop_add) != 0) { - printf("Failed to add iteration %d, route# %d\n", - i, j); + /* Wait for writer threads */ + for (i = 0; i < j; i++) + if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0) goto error; - } - /* Delete all the entries */ - for (j = 0; j < NUM_LDEPTH_ROUTE_ENTRIES; j++) - if (rte_lpm_delete(lpm, large_ldepth_route_table[j].ip, - large_ldepth_route_table[j].depth) != 0) { - printf("Failed to delete iteration %d, route# %d\n", - i, j); - goto error; - } + printf("Total LPM Adds: %d\n", TOTAL_WRITES); + printf("Total LPM Deletes: %d\n", TOTAL_WRITES); + printf("Average LPM Add/Del: %"PRIu64" cycles\n", + __atomic_load_n(&gwrite_cycles, __ATOMIC_RELAXED) + / TOTAL_WRITES); + + writer_done = 1; + /* Wait until all readers have exited */ + for (i = j; i < num_cores; i++) + rte_eal_wait_lcore(enabled_core_ids[i]); + + rte_lpm_free(lpm); + rte_free(rv); + lpm = NULL; + rv = NULL; } - total_cycles = rte_rdtsc_precise() - begin; - - printf("Total LPM Adds: %d\n", ITERATIONS * NUM_LDEPTH_ROUTE_ENTRIES); - printf("Total LPM Deletes: %d\n", - ITERATIONS * NUM_LDEPTH_ROUTE_ENTRIES); - printf("Average LPM Add/Del: %g cycles\n", - (double)total_cycles / (NUM_LDEPTH_ROUTE_ENTRIES * ITERATIONS)); - - writer_done = 1; - /* Wait and check return value from reader threads */ - for (i = 0; i < num_cores; i++) - if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0) - printf("Warning: lcore %u not finished.\n", - enabled_core_ids[i]); - - rte_lpm_free(lpm); return 0; @@ -960,11 +764,15 @@ test_lpm_perf(void) rte_lpm_delete_all(lpm); rte_lpm_free(lpm); - test_lpm_rcu_perf(); + if (test_lpm_rcu_perf_multi_writer(0) < 0) + return -1; - test_lpm_rcu_perf_multi_writer(); + if (test_lpm_rcu_perf_multi_writer(1) < 0) + return -1; return 0; } +#endif /* !RTE_EXEC_ENV_WINDOWS */ + REGISTER_TEST_COMMAND(lpm_perf_autotest, test_lpm_perf);