aboutsummaryrefslogtreecommitdiff
path: root/test/performance
diff options
context:
space:
mode:
Diffstat (limited to 'test/performance')
-rw-r--r--test/performance/odp_bench_packet.c6
-rw-r--r--test/performance/odp_crypto.c1
-rw-r--r--test/performance/odp_ipsec.c415
-rwxr-xr-xtest/performance/odp_ipsec_run.sh4
-rw-r--r--test/performance/odp_pktio_ordered.c2
-rw-r--r--test/performance/odp_random.c445
-rw-r--r--test/performance/odp_sched_pktio.c3
7 files changed, 614 insertions, 262 deletions
diff --git a/test/performance/odp_bench_packet.c b/test/performance/odp_bench_packet.c
index 0354ef9b8..23fd17bea 100644
--- a/test/performance/odp_bench_packet.c
+++ b/test/performance/odp_bench_packet.c
@@ -756,7 +756,7 @@ static int bench_packet_headroom(void)
for (i = 0; i < TEST_REPEAT_COUNT; i++)
ret += odp_packet_headroom(gbl_args->pkt_tbl[i]);
- return i;
+ return i + ret;
}
static int bench_packet_tailroom(void)
@@ -767,7 +767,7 @@ static int bench_packet_tailroom(void)
for (i = 0; i < TEST_REPEAT_COUNT; i++)
ret += odp_packet_tailroom(gbl_args->pkt_tbl[i]);
- return i;
+ return i + ret;
}
static int bench_packet_tail(void)
@@ -1412,7 +1412,7 @@ static int bench_packet_has_ref(void)
for (i = 0; i < TEST_REPEAT_COUNT; i++)
ret += odp_packet_has_ref(pkt_tbl[i]);
- return i;
+ return i + ret;
}
static int bench_packet_subtype(void)
diff --git a/test/performance/odp_crypto.c b/test/performance/odp_crypto.c
index a26d072e9..45e770d42 100644
--- a/test/performance/odp_crypto.c
+++ b/test/performance/odp_crypto.c
@@ -610,7 +610,6 @@ create_session_from_config(odp_crypto_session_t *session,
odp_crypto_session_param_init(&params);
memcpy(&params, &config->session, sizeof(odp_crypto_session_param_t));
params.op = ODP_CRYPTO_OP_ENCODE;
- params.pref_mode = ODP_CRYPTO_SYNC;
/* Lookup the packet pool */
pkt_pool = odp_pool_lookup("packet_pool");
diff --git a/test/performance/odp_ipsec.c b/test/performance/odp_ipsec.c
index 5f1f9d4ef..c464ba0d7 100644
--- a/test/performance/odp_ipsec.c
+++ b/test/performance/odp_ipsec.c
@@ -1,4 +1,6 @@
/* Copyright (c) 2018, Linaro Limited
+ * Copyright (c) 2022, Marvell
+ * Copyright (c) 2022, Nokia
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -18,11 +20,14 @@
#include <odp_api.h>
#include <odp/helper/odph_api.h>
+#include <inttypes.h>
/** @def POOL_NUM_PKT
* Number of packets in the pool
*/
-#define POOL_NUM_PKT 64
+#define POOL_NUM_PKT 4096
+
+#define MAX_DEQUEUE_BURST 16
static uint8_t test_salt[16] = "0123456789abcdef";
@@ -97,11 +102,11 @@ typedef struct {
int in_flight;
/**
- * Number of iteration to repeat crypto operation to get good
- * average number. Specified through -i or --terations option.
+ * Number of packets to be IPsec processed to get good average number.
+ * Specified through -c or --count option.
* Default is 10000.
*/
- int iteration_count;
+ int packet_count;
/**
* Payload size to test. If 0 set of predefined payload sizes
@@ -139,6 +144,19 @@ typedef struct {
* Specified through -u argument.
*/
int ah;
+
+ /*
+ * Burst size.
+ * Prepare and submit as many packets for IPsec processing in each
+ * iteration of the loop.
+ */
+ int burst_size;
+
+ /*
+ * Use vector packet completion from IPsec APIs.
+ * Specified through -v or --vector argument.
+ */
+ uint32_t vec_pkt_size;
} ipsec_args_t;
/*
@@ -516,7 +534,7 @@ print_result(ipsec_args_t *cargs,
throughput = (1000000.0 / result->elapsed) * payload_length / 1024;
printf("%30.30s %15d %15d %15.3f %15.3f %15.3f %15d\n",
- config->name, cargs->iteration_count, payload_length,
+ config->name, cargs->packet_count, payload_length,
result->elapsed, result->rusage_self, result->rusage_thread,
throughput);
}
@@ -584,28 +602,49 @@ static uint8_t test_data[] = {
0x08, 0x00, 0xfb, 0x37, 0x12, 0x34, 0x00, 0x00
};
-static odp_packet_t
-make_packet(odp_pool_t pkt_pool, unsigned int payload_length)
+static inline void debug_packets(int debug, odp_packet_t *pkt, int num_pkts)
{
- odp_packet_t pkt;
+ if (odp_likely(!debug))
+ return;
+ for (int i = 0; i < num_pkts; i++)
+ odp_packet_print_data(pkt[i], 0, odp_packet_len(pkt[i]));
+}
- if (payload_length < sizeof(test_data))
- return ODP_PACKET_INVALID;
+static int
+make_packet_multi(odp_pool_t pkt_pool, unsigned int payload_length,
+ odp_packet_t pkt[], int num)
+{
+ int i, ret;
+
+ ret = odp_packet_alloc_multi(pkt_pool, payload_length, pkt, num);
+ if (ret != num) {
+ ODPH_ERR("Could not allocate buffer\n");
+ if (ret > 0)
+ odp_packet_free_sp(pkt, ret);
+ return -1;
+ }
+
+ for (i = 0; i < num; i++) {
+ odp_packet_copy_from_mem(pkt[i], 0, sizeof(test_data), test_data);
+ odp_packet_l3_offset_set(pkt[i], 0);
- pkt = odp_packet_alloc(pkt_pool, payload_length);
- if (pkt == ODP_PACKET_INVALID) {
- ODPH_ERR("failed to allocate buffer\n");
- return pkt;
+ uint8_t *mem = odp_packet_data(pkt[i]);
+ ((odph_ipv4hdr_t *)mem)->tot_len = odp_cpu_to_be_16(payload_length);
+ memset(mem + sizeof(test_data), 1, payload_length - sizeof(test_data));
}
- odp_packet_copy_from_mem(pkt, 0, sizeof(test_data), test_data);
- odp_packet_l3_offset_set(pkt, 0);
+ return 0;
+}
- uint8_t *mem = odp_packet_data(pkt);
- ((odph_ipv4hdr_t *)mem)->tot_len = odp_cpu_to_be_16(payload_length);
- memset(mem + sizeof(test_data), 1, payload_length - sizeof(test_data));
+static inline void check_ipsec_result(odp_packet_t ipsec_pkt)
+{
+ odp_ipsec_packet_result_t result;
- return pkt;
+ if (odp_unlikely(odp_ipsec_result(&result, ipsec_pkt)))
+ ODPH_ERR("odp_ipsec_result() failed\n");
+ else if (odp_unlikely(result.status.error.all))
+ ODPH_ERR("IPsec processing error: %" PRIu32 "\n",
+ result.status.error.all);
}
/**
@@ -619,10 +658,13 @@ run_measure_one(ipsec_args_t *cargs,
time_record_t *start,
time_record_t *end)
{
+ int in_flight, pkts_allowed, num_out, num_pkts, rc = 0;
+ const int max_in_flight = cargs->in_flight;
+ const int burst_size = cargs->burst_size;
+ const int packet_count = cargs->packet_count;
+ const int debug = cargs->debug_packets;
odp_ipsec_out_param_t param;
odp_pool_t pkt_pool;
- odp_packet_t pkt = ODP_PACKET_INVALID;
- int rc = 0;
pkt_pool = odp_pool_lookup("packet_pool");
if (pkt_pool == ODP_POOL_INVALID) {
@@ -630,6 +672,9 @@ run_measure_one(ipsec_args_t *cargs,
return -1;
}
+ if (payload_length < sizeof(test_data))
+ return -1;
+
int packets_sent = 0;
int packets_received = 0;
@@ -641,43 +686,53 @@ run_measure_one(ipsec_args_t *cargs,
fill_time_record(start);
- while ((packets_sent < cargs->iteration_count) ||
- (packets_received < cargs->iteration_count)) {
- if ((packets_sent < cargs->iteration_count) &&
- (packets_sent - packets_received <
- cargs->in_flight)) {
- odp_packet_t out_pkt;
- int num_out = 1;
+ while ((packets_sent < packet_count) ||
+ (packets_received < packet_count)) {
+ num_pkts = packet_count - packets_sent;
+
+ /* Enqueue up to burst size */
+ num_pkts = num_pkts > burst_size ? burst_size : num_pkts;
+
+ /* Enqueue up to (max in flight - current in flight) */
+ in_flight = packets_sent - packets_received;
+ pkts_allowed = max_in_flight - in_flight;
- pkt = make_packet(pkt_pool, payload_length);
- if (ODP_PACKET_INVALID == pkt)
+ /* Enqueue either a burst of packets or skip */
+ num_pkts = num_pkts > pkts_allowed ? 0 : num_pkts;
+
+ if (odp_likely(num_pkts)) {
+ odp_packet_t out_pkt[num_pkts];
+ odp_packet_t pkt[num_pkts];
+ int i;
+
+ if (odp_unlikely(make_packet_multi(pkt_pool,
+ payload_length,
+ pkt,
+ num_pkts)))
return -1;
- if (cargs->debug_packets)
- odp_packet_print_data(pkt, 0,
- odp_packet_len(pkt));
+ debug_packets(debug, pkt, num_pkts);
+ num_out = num_pkts;
- rc = odp_ipsec_out(&pkt, 1,
- &out_pkt, &num_out,
+ rc = odp_ipsec_out(pkt, num_pkts,
+ out_pkt, &num_out,
&param);
- if (rc <= 0) {
- ODPH_ERR("failed odp_ipsec_out: rc = %d\n", rc);
- odp_packet_free(pkt);
+ if (odp_unlikely(rc <= 0)) {
+ ODPH_ERR("Failed odp_ipsec_out: rc = %d\n", rc);
+ odp_packet_free_sp(pkt, num_pkts);
break;
}
- if (odp_packet_has_error(out_pkt)) {
- odp_ipsec_packet_result_t result;
- odp_ipsec_result(&result, out_pkt);
- ODPH_ERR("Received error packet: %d\n",
- result.status.error.all);
- }
+ for (i = 0; i < num_out; i++)
+ check_ipsec_result(out_pkt[i]);
+
packets_sent += rc;
packets_received += num_out;
- if (cargs->debug_packets)
- odp_packet_print_data(out_pkt, 0,
- odp_packet_len(out_pkt));
- odp_packet_free(out_pkt);
+ debug_packets(debug, out_pkt, num_out);
+
+ if (odp_unlikely(rc != num_pkts))
+ odp_packet_free_sp(&pkt[rc], num_pkts - rc);
+ odp_packet_free_sp(out_pkt, num_out);
}
}
@@ -686,6 +741,46 @@ run_measure_one(ipsec_args_t *cargs,
return rc < 0 ? rc : 0;
}
+static uint32_t dequeue_burst(odp_queue_t polled_queue,
+ odp_event_t *events,
+ int max_burst)
+{
+ int num = 0;
+
+ if (polled_queue != ODP_QUEUE_INVALID) {
+ int rc = odp_queue_deq_multi(polled_queue,
+ events,
+ max_burst);
+ num = odp_likely(rc >= 0) ? rc : 0;
+ } else {
+ num = odp_schedule_multi(NULL,
+ ODP_SCHED_NO_WAIT,
+ events,
+ max_burst);
+ }
+ return num;
+}
+
+static inline uint32_t vec_pkt_handle(int debug, odp_event_t ev)
+{
+ odp_packet_vector_t vec = odp_packet_vector_from_event(ev);
+ uint32_t vec_size = odp_packet_vector_size(vec);
+ odp_packet_t *pkt_tbl;
+ uint32_t j;
+
+ odp_packet_vector_tbl(vec, &pkt_tbl);
+
+ for (j = 0; j < vec_size; j++)
+ check_ipsec_result(pkt_tbl[j]);
+
+ debug_packets(debug, pkt_tbl, vec_size);
+
+ odp_packet_free_sp(pkt_tbl, vec_size);
+ odp_packet_vector_free(vec);
+
+ return vec_size;
+}
+
static int
run_measure_one_async(ipsec_args_t *cargs,
odp_ipsec_sa_t sa,
@@ -693,11 +788,14 @@ run_measure_one_async(ipsec_args_t *cargs,
time_record_t *start,
time_record_t *end)
{
+ int in_flight, packets_allowed, num_pkts, rc = 0;
+ const int max_in_flight = cargs->in_flight;
+ const int burst_size = cargs->burst_size;
+ const int packet_count = cargs->packet_count;
+ const int debug = cargs->debug_packets;
odp_ipsec_out_param_t param;
odp_pool_t pkt_pool;
- odp_queue_t out_queue;
- odp_packet_t pkt = ODP_PACKET_INVALID;
- int rc = 0;
+ odp_queue_t polled_queue = ODP_QUEUE_INVALID;
pkt_pool = odp_pool_lookup("packet_pool");
if (pkt_pool == ODP_POOL_INVALID) {
@@ -705,12 +803,17 @@ run_measure_one_async(ipsec_args_t *cargs,
return -1;
}
- out_queue = odp_queue_lookup("ipsec-out");
- if (out_queue == ODP_QUEUE_INVALID) {
- ODPH_ERR("ipsec-out queue not found\n");
- return -1;
+ if (cargs->poll) {
+ polled_queue = odp_queue_lookup("ipsec-out");
+ if (polled_queue == ODP_QUEUE_INVALID) {
+ ODPH_ERR("ipsec-out queue not found\n");
+ return -1;
+ }
}
+ if (payload_length < sizeof(test_data))
+ return -1;
+
int packets_sent = 0;
int packets_received = 0;
@@ -722,55 +825,78 @@ run_measure_one_async(ipsec_args_t *cargs,
fill_time_record(start);
- while ((packets_sent < cargs->iteration_count) ||
- (packets_received < cargs->iteration_count)) {
- odp_event_t ev;
+ while ((packets_sent < packet_count) ||
+ (packets_received < packet_count)) {
+
+ num_pkts = packet_count - packets_sent;
+
+ /* Enqueue up to burst size */
+ num_pkts = num_pkts > burst_size ? burst_size : num_pkts;
+
+ /* Enqueue up to (max in flight - current in flight) */
+ in_flight = packets_sent - packets_received;
+ packets_allowed = max_in_flight - in_flight;
- if ((packets_sent < cargs->iteration_count) &&
- (packets_sent - packets_received <
- cargs->in_flight)) {
- pkt = make_packet(pkt_pool, payload_length);
- if (ODP_PACKET_INVALID == pkt)
+ if (num_pkts > 0 && num_pkts <= packets_allowed) {
+ odp_packet_t pkt[num_pkts];
+
+ if (odp_unlikely(make_packet_multi(pkt_pool,
+ payload_length,
+ pkt,
+ num_pkts)))
return -1;
- if (cargs->debug_packets)
- odp_packet_print_data(pkt, 0,
- odp_packet_len(pkt));
+ debug_packets(debug, pkt, num_pkts);
- rc = odp_ipsec_out_enq(&pkt, 1,
- &param);
- if (rc <= 0) {
- ODPH_ERR("failed odp_crypto_packet_op_enq: rc = %d\n",
+ rc = odp_ipsec_out_enq(pkt, num_pkts, &param);
+ if (odp_unlikely(rc <= 0)) {
+ ODPH_ERR("Failed odp_ipsec_out_enq: rc = %d\n",
rc);
- odp_packet_free(pkt);
+ odp_packet_free_sp(pkt, num_pkts);
break;
}
+
+ if (odp_unlikely(rc != num_pkts))
+ odp_packet_free_sp(&pkt[rc], num_pkts - rc);
+
packets_sent += rc;
- }
+ } else {
+ odp_packet_t pkt_out[max_in_flight];
+ uint32_t i = 0;
+
+ /*
+ * Dequeue packets until we can enqueue the next burst
+ * or until we have received all remaining packets
+ * when there are no more packets to be sent.
+ */
+ while (num_pkts > packets_allowed ||
+ (num_pkts == 0 && packets_received < packet_count)) {
+ odp_event_t events[MAX_DEQUEUE_BURST];
+ uint32_t num;
+
+ num = dequeue_burst(polled_queue, events, MAX_DEQUEUE_BURST);
+
+ for (uint32_t n = 0; n < num; n++) {
+ if (odp_event_type(events[n]) == ODP_EVENT_PACKET_VECTOR) {
+ uint32_t vec_size;
+
+ vec_size = vec_pkt_handle(debug, events[n]);
+ packets_received += vec_size - 1;
+ packets_allowed += vec_size - 1;
+ } else {
+ pkt_out[i] = odp_ipsec_packet_from_event(events[n]);
+ check_ipsec_result(pkt_out[i]);
+ i++;
+ }
+
+ }
+ packets_received += num;
+ packets_allowed += num;
+ }
+ debug_packets(debug, pkt_out, i);
- if (cargs->schedule)
- ev = odp_schedule(NULL,
- ODP_SCHED_NO_WAIT);
- else
- ev = odp_queue_deq(out_queue);
-
- while (ev != ODP_EVENT_INVALID) {
- odp_packet_t out_pkt;
- odp_ipsec_packet_result_t result;
-
- out_pkt = odp_ipsec_packet_from_event(ev);
- odp_ipsec_result(&result, out_pkt);
-
- if (cargs->debug_packets)
- odp_packet_print_data(out_pkt, 0,
- odp_packet_len(out_pkt));
- odp_packet_free(out_pkt);
- packets_received++;
- if (cargs->schedule)
- ev = odp_schedule(NULL,
- ODP_SCHED_NO_WAIT);
- else
- ev = odp_queue_deq(out_queue);
+ if (i)
+ odp_packet_free_sp(pkt_out, i);
}
}
@@ -843,13 +969,13 @@ run_measure_one_config(ipsec_args_t *cargs,
break;
count = get_elapsed_usec(&start, &end);
- result.elapsed = count / cargs->iteration_count;
+ result.elapsed = count / cargs->packet_count;
count = get_rusage_self_diff(&start, &end);
- result.rusage_self = count / cargs->iteration_count;
+ result.rusage_self = count / cargs->packet_count;
count = get_rusage_thread_diff(&start, &end);
- result.rusage_thread = count / cargs->iteration_count;
+ result.rusage_thread = count / cargs->packet_count;
print_result(cargs, payloads[i],
config, &result);
@@ -913,7 +1039,9 @@ static void usage(char *progname)
print_config_names(" ");
printf(" -d, --debug Enable dump of processed packets.\n"
" -f, --flight <number> Max number of packet processed in parallel (default 1)\n"
- " -i, --iterations <number> Number of iterations.\n"
+ " -c, --count <number> Number of packets (default 10000)\n"
+ " -b, --burst <number> Number of packets in one IPsec API submission (default 1)\n"
+ " -v, --vector <number> Enable vector packet completion from IPsec APIs with specified vector size.\n"
" -l, --payload Payload length.\n"
" -s, --schedule Use scheduler for completion events.\n"
" -p, --poll Poll completion queue for completion events.\n"
@@ -932,7 +1060,9 @@ static void parse_args(int argc, char *argv[], ipsec_args_t *cargs)
{"debug", no_argument, NULL, 'd'},
{"flight", optional_argument, NULL, 'f'},
{"help", no_argument, NULL, 'h'},
- {"iterations", optional_argument, NULL, 'i'},
+ {"count", optional_argument, NULL, 'c'},
+ {"burst", optional_argument, NULL, 'b'},
+ {"vector", optional_argument, NULL, 'v'},
{"payload", optional_argument, NULL, 'l'},
{"sessions", optional_argument, NULL, 'm'},
{"poll", no_argument, NULL, 'p'},
@@ -942,11 +1072,13 @@ static void parse_args(int argc, char *argv[], ipsec_args_t *cargs)
{NULL, 0, NULL, 0}
};
- static const char *shortopts = "+a:c:df:hi:m:nl:sptu";
+ static const char *shortopts = "+a:b:c:df:hm:nl:sptuv:";
cargs->in_flight = 1;
cargs->debug_packets = 0;
- cargs->iteration_count = 10000;
+ cargs->packet_count = 10000;
+ cargs->burst_size = 1;
+ cargs->vec_pkt_size = 0;
cargs->payload_length = 0;
cargs->alg_config = NULL;
cargs->schedule = 0;
@@ -971,8 +1103,24 @@ static void parse_args(int argc, char *argv[], ipsec_args_t *cargs)
case 'd':
cargs->debug_packets = 1;
break;
- case 'i':
- cargs->iteration_count = atoi(optarg);
+ case 'c':
+ cargs->packet_count = atoi(optarg);
+ break;
+ case 'b':
+ if (optarg == NULL)
+ cargs->burst_size = 32;
+ else
+ cargs->burst_size = atoi(optarg);
+ if (cargs->burst_size > POOL_NUM_PKT) {
+ printf("Invalid burst size (max allowed: %d)\n", POOL_NUM_PKT);
+ exit(-1);
+ }
+ break;
+ case 'v':
+ if (optarg == NULL)
+ cargs->vec_pkt_size = 32;
+ else
+ cargs->vec_pkt_size = atoi(optarg);
break;
case 'f':
cargs->in_flight = atoi(optarg);
@@ -1001,6 +1149,11 @@ static void parse_args(int argc, char *argv[], ipsec_args_t *cargs)
}
}
+ if (cargs->in_flight < cargs->burst_size) {
+ printf("-f (flight) must be greater than or equal to -b (burst)\n");
+ exit(-1);
+ }
+
optind = 1; /* reset 'extern optind' from the getopt lib */
if (cargs->schedule && cargs->poll) {
@@ -1012,6 +1165,7 @@ static void parse_args(int argc, char *argv[], ipsec_args_t *cargs)
int main(int argc, char *argv[])
{
+ odp_pool_t vec_pool = ODP_POOL_INVALID;
ipsec_args_t cargs;
odp_pool_t pool;
odp_queue_param_t qparam;
@@ -1105,11 +1259,54 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
+ if (cargs.vec_pkt_size) {
+ if (capa.vector.max_pools < 1) {
+ ODPH_ERR("Vector packet pool not available");
+ exit(EXIT_FAILURE);
+ }
+
+ if (!ipsec_capa.vector.supported) {
+ ODPH_ERR("Vector packet completion not supported by IPsec.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (capa.vector.max_size < cargs.vec_pkt_size) {
+ ODPH_ERR("Vector size larger than max size supported by vector pool.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (!cargs.schedule && !cargs.poll) {
+ ODPH_ERR("Vector packet is not supported with sync APIs.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Create vector pool */
+ odp_pool_param_init(&param);
+ param.vector.num = POOL_NUM_PKT;
+ param.vector.max_size = cargs.vec_pkt_size;
+ param.type = ODP_POOL_VECTOR;
+ vec_pool = odp_pool_create("vector_pool", &param);
+
+ if (vec_pool == ODP_POOL_INVALID) {
+ ODPH_ERR("Vector packet pool create failed.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ odp_pool_print(vec_pool);
+ }
+
odp_ipsec_config_init(&config);
config.max_num_sa = 2;
config.inbound.chksums.all_chksum = 0;
config.outbound.all_chksum = 0;
+ if (vec_pool != ODP_POOL_INVALID) {
+ config.vector.enable = true;
+ config.vector.pool = vec_pool;
+ config.vector.max_size = cargs.vec_pkt_size;
+ config.vector.max_tmo_ns = ipsec_capa.vector.max_tmo_ns;
+ }
+
odp_queue_param_init(&qparam);
if (cargs.schedule) {
odp_schedule_config(NULL);
@@ -1196,6 +1393,14 @@ int main(int argc, char *argv[])
if (cargs.schedule || cargs.poll)
odp_queue_destroy(out_queue);
+
+ if (cargs.vec_pkt_size) {
+ if (odp_pool_destroy(vec_pool)) {
+ ODPH_ERR("Error: vector pool destroy\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
if (odp_pool_destroy(pool)) {
ODPH_ERR("Error: pool destroy\n");
exit(EXIT_FAILURE);
diff --git a/test/performance/odp_ipsec_run.sh b/test/performance/odp_ipsec_run.sh
index 1974a7c55..2ddb48d07 100755
--- a/test/performance/odp_ipsec_run.sh
+++ b/test/performance/odp_ipsec_run.sh
@@ -7,9 +7,9 @@
TEST_DIR="${TEST_DIR:-$(dirname $0)}"
-# Run with a small number of iterations in make check
+# Run with a small number of packets in make check
-$TEST_DIR/odp_ipsec${EXEEXT} -i 100
+$TEST_DIR/odp_ipsec${EXEEXT} -c 100
if [ $? -ne 0 ] ; then
echo Test FAILED
diff --git a/test/performance/odp_pktio_ordered.c b/test/performance/odp_pktio_ordered.c
index 37a0899b6..130eb4688 100644
--- a/test/performance/odp_pktio_ordered.c
+++ b/test/performance/odp_pktio_ordered.c
@@ -1258,7 +1258,7 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
- if ((unsigned)gbl_args->appl.num_flows > capa.max_output_queues)
+ if ((uint32_t)gbl_args->appl.num_flows > capa.max_output_queues)
gbl_args->appl.num_flows = capa.max_output_queues;
}
diff --git a/test/performance/odp_random.c b/test/performance/odp_random.c
index 622a58c65..46134ac0c 100644
--- a/test/performance/odp_random.c
+++ b/test/performance/odp_random.c
@@ -14,20 +14,52 @@
#include <odp_api.h>
#include <odp/helper/odph_api.h>
+#define PSEUDO_RANDOM (-1)
+
#define MB (1024ull * 1024ull)
+typedef struct test_global_t test_global_t;
+
+typedef struct thread_arg_t {
+ test_global_t *global;
+ int thread_idx;
+ uint8_t *data;
+
+} thread_arg_t;
+
+struct test_global_t {
+ odp_barrier_t barrier;
+ odp_random_kind_t type;
+ uint8_t *data;
+ uint32_t rounds;
+
+ thread_arg_t thread_arg[ODP_THREAD_COUNT_MAX];
+
+ struct {
+ uint64_t nsec[ODP_THREAD_COUNT_MAX];
+ uint64_t sum[ODP_THREAD_COUNT_MAX];
+ uint64_t min[ODP_THREAD_COUNT_MAX];
+ uint64_t max[ODP_THREAD_COUNT_MAX];
+ } stat;
+};
+
/* Command line options */
typedef struct {
+ int mode;
int num_threads;
uint32_t size;
uint32_t rounds;
+ uint64_t delay;
+
} options_t;
static options_t options;
static const options_t options_def = {
+ .mode = 0,
.num_threads = 1,
.size = 256,
.rounds = 100000,
+ .delay = 0,
};
static void print_usage(void)
@@ -37,13 +69,18 @@ static void print_usage(void)
"\n"
"Usage: odp_random [options]\n"
"\n"
+ " -m, --mode Test mode select (default: 0):\n"
+ " 0: Data throughput\n"
+ " 1: Data generation latency (size: 8B by default)\n"
" -t, --threads Number of worker threads (default %u)\n"
" -s, --size Size of buffer in bytes (default %u)\n"
" -r, --rounds Number of test rounds (default %u)\n"
" Divided by 100 for ODP_RANDOM_TRUE\n"
+ " -d, --delay Delay (nsec) between buffer fills (default %" PRIu64 ").\n"
+ " Affects only latency mode.\n"
" -h, --help This help\n"
"\n",
- options_def.num_threads, options_def.size, options_def.rounds);
+ options_def.num_threads, options_def.size, options_def.rounds, options_def.delay);
}
static int parse_options(int argc, char *argv[])
@@ -53,16 +90,19 @@ static int parse_options(int argc, char *argv[])
int ret = 0;
static const struct option longopts[] = {
+ { "mode", required_argument, NULL, 'm' },
{ "threads", required_argument, NULL, 't' },
{ "size", required_argument, NULL, 's' },
{ "rounds", required_argument, NULL, 'r' },
+ { "delay", required_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' },
{ NULL, 0, NULL, 0 }
};
- static const char *shortopts = "+t:s:r:h";
+ static const char *shortopts = "+m:t:s:r:d:h";
options = options_def;
+ options.size = 0;
while (1) {
opt = getopt_long(argc, argv, shortopts, longopts, &long_index);
@@ -71,6 +111,9 @@ static int parse_options(int argc, char *argv[])
break;
switch (opt) {
+ case 'm':
+ options.mode = atoi(optarg);
+ break;
case 't':
options.num_threads = atol(optarg);
break;
@@ -80,6 +123,9 @@ static int parse_options(int argc, char *argv[])
case 'r':
options.rounds = atol(optarg);
break;
+ case 'd':
+ options.delay = atol(optarg);
+ break;
case 'h':
/* fall through */
default:
@@ -89,170 +135,216 @@ static int parse_options(int argc, char *argv[])
}
}
- if (options.size < 1) {
- ODPH_ERR("Invalid size: %" PRIu32 "\n", options.size);
+ if (options.num_threads < 1 || options.num_threads > ODP_THREAD_COUNT_MAX) {
+ ODPH_ERR("Bad number of threads: %i\n", options.num_threads);
return -1;
}
+ if (options.size == 0) {
+ options.size = options_def.size;
+
+ if (options.mode)
+ options.size = 8;
+ }
+
+ printf("\nOptions:\n");
+ printf("------------------------\n");
+ printf(" mode: %i\n", options.mode);
+ printf(" threads: %i\n", options.num_threads);
+ printf(" size: %u\n", options.size);
+ printf(" rounds: %u\n", options.rounds);
+ printf(" delay: %" PRIu64 "\n", options.delay);
+ printf("\n");
+
return ret;
}
-const char *shm_name = "odp_random_test";
+static inline void random_data_loop(odp_random_kind_t type, uint32_t rounds,
+ uint8_t *data, uint32_t size)
+{
+ uint32_t i;
+ int32_t ret;
-typedef struct test_shm_t {
- odp_barrier_t barrier;
- odp_random_kind_t type;
- uint64_t nsec[ODP_THREAD_COUNT_MAX];
-} test_shm_t;
+ if ((int)type == PSEUDO_RANDOM) {
+ uint64_t seed = 0;
-static test_shm_t *shm_lookup(void)
-{
- test_shm_t *shm = NULL;
- odp_shm_t shm_hdl = odp_shm_lookup(shm_name);
+ for (i = 0; i < rounds; i++) {
+ uint32_t pos = 0;
- if (shm_hdl != ODP_SHM_INVALID)
- shm = (test_shm_t *)odp_shm_addr(shm_hdl);
+ while (pos < size) {
+ ret = odp_random_test_data(data + pos, size - pos, &seed);
- return shm;
-}
+ if (ret < 0) {
+ ODPH_ERR("odp_random_test_data() failed\n");
+ exit(EXIT_FAILURE);
+ }
-static uint32_t type_rounds(odp_random_kind_t type)
-{
- switch (type) {
- case ODP_RANDOM_TRUE:
- return options.rounds / 100;
- default:
- return options.rounds;
+ pos += ret;
+ }
+ }
+ } else {
+ for (i = 0; i < rounds; i++) {
+ uint32_t pos = 0;
+
+ while (pos < size) {
+ ret = odp_random_data(data + pos, size - pos, type);
+
+ if (ret < 0) {
+ ODPH_ERR("odp_random_data() failed\n");
+ exit(EXIT_FAILURE);
+ }
+
+ pos += ret;
+ }
+ }
}
}
-static int test_random(void *p)
+static int test_random_perf(void *ptr)
{
- (void)p;
-
- uint8_t *buf, *data;
- const unsigned long page = ODP_PAGE_SIZE;
odp_time_t start;
uint64_t nsec;
- uint32_t rounds;
- test_shm_t *shm = shm_lookup();
+ thread_arg_t *thread_arg = ptr;
+ test_global_t *global = thread_arg->global;
+ odp_random_kind_t type = global->type;
+ int thread_idx = thread_arg->thread_idx;
+ uint8_t *data = thread_arg->data;
+ uint32_t size = options.size;
+ uint32_t rounds = global->rounds;
- if (!shm) {
- ODPH_ERR("Failed to look up shm %s\n", shm_name);
- exit(EXIT_FAILURE);
- }
+ /* One warm up round */
+ random_data_loop(type, 1, data, size);
- rounds = type_rounds(shm->type);
+ odp_barrier_wait(&global->barrier);
- /* One extra page for alignment. */
- buf = (uint8_t *)malloc(options.size + page);
-
- if (!buf) {
- ODPH_ERR("Memory allocation failed.\n");
- exit(EXIT_FAILURE);
- }
-
- /* Align to start of page. */
- data = (uint8_t *)(((uintptr_t)buf + (page - 1)) & ~(page - 1));
-
- odp_barrier_wait(&shm->barrier);
+ /* Test run */
start = odp_time_local();
- for (uint32_t i = 0; i < rounds; i++) {
- uint32_t pos = 0;
-
- while (pos < options.size) {
- int32_t n = odp_random_data(data + pos,
- options.size - pos,
- shm->type);
-
- if (n < 0) {
- ODPH_ERR("odp_random_data() failed\n");
- exit(EXIT_FAILURE);
- }
-
- pos += n;
- }
- }
+ random_data_loop(type, rounds, data, size);
nsec = odp_time_diff_ns(odp_time_local(), start);
- shm->nsec[odp_thread_id()] = nsec;
- free(buf);
+
+ global->stat.nsec[thread_idx] = nsec;
return 0;
}
-static int test_random_test(void *p)
+static inline void random_data_latency(test_global_t *global, int thread_idx,
+ uint32_t rounds, uint8_t *data, uint32_t size)
{
- (void)p;
-
- uint8_t *buf, *data;
- const unsigned long page = ODP_PAGE_SIZE;
- odp_time_t start;
+ uint32_t i;
+ int32_t ret;
+ odp_time_t t1, t2, start;
uint64_t nsec;
+ odp_random_kind_t type = global->type;
+ uint64_t delay = options.delay;
+ uint64_t min = UINT64_MAX;
+ uint64_t max = 0;
+ uint64_t sum = 0;
uint64_t seed = 0;
- uint32_t rounds;
- test_shm_t *shm = shm_lookup();
-
- if (!shm) {
- ODPH_ERR("Failed to look up shm %s\n", shm_name);
- exit(EXIT_FAILURE);
- }
-
- rounds = type_rounds(shm->type);
-
- /* One extra page for alignment. */
- buf = (uint8_t *)malloc(options.size + page);
-
- if (!buf) {
- ODPH_ERR("Memory allocation failed.\n");
- exit(EXIT_FAILURE);
- }
-
- /* Align to start of page. */
- data = (uint8_t *)(((uintptr_t)buf + (page - 1)) & ~(page - 1));
- odp_barrier_wait(&shm->barrier);
start = odp_time_local();
- for (uint32_t i = 0; i < rounds; i++) {
+ for (i = 0; i < rounds; i++) {
uint32_t pos = 0;
- while (pos < options.size) {
- int32_t n = odp_random_test_data(data + pos,
- options.size - pos,
- &seed);
+ if (delay)
+ odp_time_wait_ns(delay);
- if (n < 0) {
- ODPH_ERR("odp_random_data() failed\n");
- exit(EXIT_FAILURE);
- }
+ if ((int)type == PSEUDO_RANDOM) {
+ t1 = odp_time_local_strict();
+ while (pos < size) {
+ ret = odp_random_test_data(data + pos, size - pos, &seed);
+
+ if (ret < 0) {
+ ODPH_ERR("odp_random_test_data() failed\n");
+ exit(EXIT_FAILURE);
+ }
- pos += n;
+ pos += ret;
+ }
+ t2 = odp_time_local_strict();
+ } else {
+ t1 = odp_time_local_strict();
+ while (pos < size) {
+ ret = odp_random_data(data + pos, size - pos, type);
+
+ if (ret < 0) {
+ ODPH_ERR("odp_random_data() failed\n");
+ exit(EXIT_FAILURE);
+ }
+
+ pos += ret;
+ }
+ t2 = odp_time_local_strict();
}
+
+ nsec = odp_time_diff_ns(t2, t1);
+ sum += nsec;
+
+ if (nsec > max)
+ max = nsec;
+ if (nsec < min)
+ min = nsec;
}
nsec = odp_time_diff_ns(odp_time_local(), start);
- shm->nsec[odp_thread_id()] = nsec;
- free(buf);
+
+ global->stat.nsec[thread_idx] = nsec;
+ global->stat.sum[thread_idx] = sum;
+ global->stat.min[thread_idx] = min;
+ global->stat.max[thread_idx] = max;
+}
+
+static int test_random_latency(void *ptr)
+{
+ thread_arg_t *thread_arg = ptr;
+ test_global_t *global = thread_arg->global;
+ odp_random_kind_t type = global->type;
+ int thread_idx = thread_arg->thread_idx;
+ uint8_t *data = thread_arg->data;
+ uint32_t size = options.size;
+ uint32_t rounds = global->rounds;
+
+ /* One warm up round */
+ random_data_loop(type, 1, data, size);
+
+ odp_barrier_wait(&global->barrier);
+
+ /* Test run */
+ random_data_latency(global, thread_idx, rounds, data, size);
return 0;
}
-static void test_type(odp_instance_t instance, test_shm_t *shm,
- odp_random_kind_t type)
+static uint32_t type_rounds(odp_random_kind_t type)
+{
+ switch (type) {
+ case ODP_RANDOM_TRUE:
+ return options.rounds / 100;
+ default:
+ return options.rounds;
+ }
+}
+
+static void test_type(odp_instance_t instance, test_global_t *global, odp_random_kind_t type)
{
- memset(shm, 0, sizeof(test_shm_t));
- shm->type = type;
- odp_barrier_init(&shm->barrier, options.num_threads);
+ int i;
+ int num_threads = options.num_threads;
+ uint32_t rounds = type_rounds(type);
+ uint32_t size = options.size;
+
+ memset(&global->stat, 0, sizeof(global->stat));
+ global->type = type;
+ global->rounds = rounds;
+ odp_barrier_init(&global->barrier, num_threads);
odp_cpumask_t cpumask;
odph_thread_common_param_t thr_common;
- odph_thread_param_t thr_param;
- odph_thread_t thr_worker[options.num_threads];
+ odph_thread_param_t thr_param[num_threads];
+ odph_thread_t thr_worker[num_threads];
- if (odp_cpumask_default_worker(&cpumask, options.num_threads) !=
- options.num_threads) {
+ if (odp_cpumask_default_worker(&cpumask, num_threads) != num_threads) {
ODPH_ERR("Failed to get default CPU mask.\n");
exit(EXIT_FAILURE);
}
@@ -260,35 +352,36 @@ static void test_type(odp_instance_t instance, test_shm_t *shm,
odph_thread_common_param_init(&thr_common);
thr_common.instance = instance;
thr_common.cpumask = &cpumask;
- thr_common.share_param = 1;
- odph_thread_param_init(&thr_param);
- thr_param.thr_type = ODP_THREAD_WORKER;
- thr_param.start = test_random;
+ for (i = 0; i < num_threads; i++) {
+ odph_thread_param_init(&thr_param[i]);
+ thr_param[i].thr_type = ODP_THREAD_WORKER;
+ thr_param[i].arg = &global->thread_arg[i];
- if (type == (odp_random_kind_t)-1)
- thr_param.start = test_random_test;
+ if (options.mode == 0)
+ thr_param[i].start = test_random_perf;
+ else
+ thr_param[i].start = test_random_latency;
+ }
memset(&thr_worker, 0, sizeof(thr_worker));
- if (odph_thread_create(thr_worker, &thr_common, &thr_param,
- options.num_threads) != options.num_threads) {
+ if (odph_thread_create(thr_worker, &thr_common, thr_param, num_threads) != num_threads) {
ODPH_ERR("Failed to create worker threads.\n");
exit(EXIT_FAILURE);
}
- if (odph_thread_join(thr_worker, options.num_threads) !=
- options.num_threads) {
+ if (odph_thread_join(thr_worker, num_threads) != num_threads) {
ODPH_ERR("Failed to join worker threads.\n");
exit(EXIT_FAILURE);
}
double mb, seconds, nsec = 0;
- for (int i = 0; i < ODP_THREAD_COUNT_MAX; i++)
- nsec += shm->nsec[i];
+ for (i = 0; i < num_threads; i++)
+ nsec += global->stat.nsec[i];
- nsec /= options.num_threads;
+ nsec /= num_threads;
switch (type) {
case ODP_RANDOM_BASIC:
@@ -304,25 +397,53 @@ static void test_type(odp_instance_t instance, test_shm_t *shm,
printf("odp_random_test_data\n");
}
- uint32_t rounds = type_rounds(type);
-
printf("--------------------\n");
- printf("threads: %d size: %u B rounds: %u ", options.num_threads,
- options.size, rounds);
- mb = (uint64_t)options.num_threads * (uint64_t)options.size *
- (uint64_t)rounds;
+ printf("threads: %d size: %u B rounds: %u ", num_threads, size, rounds);
+ mb = (uint64_t)num_threads * (uint64_t)size * (uint64_t)rounds;
mb /= MB;
seconds = (double)nsec / (double)ODP_TIME_SEC_IN_NS;
printf("MB: %.3f seconds: %.3f ", mb, seconds);
printf("MB/s: %.3f ", mb / seconds);
- printf("MB/s/thread: %.3f", mb / seconds / (double)options.num_threads);
- printf("\n\n");
+ printf("MB/s/thread: %.3f\n", mb / seconds / (double)num_threads);
+
+ if (options.mode) {
+ double ave;
+ uint64_t min = UINT64_MAX;
+ uint64_t max = 0;
+ uint64_t sum = 0;
+
+ printf(" latency (nsec)\n");
+ printf(" thread min max ave\n");
+ for (i = 0; i < num_threads; i++) {
+ ave = (double)global->stat.sum[i] / rounds;
+ sum += global->stat.sum[i];
+
+ if (global->stat.min[i] < min)
+ min = global->stat.min[i];
+
+ if (global->stat.max[i] > max)
+ max = global->stat.max[i];
+
+ printf("%8i %8" PRIu64 " %8" PRIu64 " %10.1f\n", i, global->stat.min[i],
+ global->stat.max[i], ave);
+ }
+
+ printf(" all %8" PRIu64 " %8" PRIu64 " %10.1f\n",
+ min, max, ((double)sum / rounds) / num_threads);
+ }
+
+ printf("\n");
}
int main(int argc, char **argv)
{
odp_instance_t instance;
odp_init_t init;
+ odp_shm_t shm_glb, shm_data;
+ test_global_t *global;
+ int num_threads, i;
+ uint64_t tot_size, size;
+ uint8_t *addr;
if (parse_options(argc, argv))
exit(EXIT_FAILURE);
@@ -352,31 +473,59 @@ int main(int argc, char **argv)
odp_sys_info_print();
- test_shm_t *shm = NULL;
- odp_shm_t shm_hdl = odp_shm_reserve(shm_name, sizeof(test_shm_t), 64,
- 0);
+ global = NULL;
+ shm_glb = odp_shm_reserve("test_globals", sizeof(test_global_t), ODP_CACHE_LINE_SIZE, 0);
+
+ if (shm_glb != ODP_SHM_INVALID)
+ global = (test_global_t *)odp_shm_addr(shm_glb);
+
+ if (!global) {
+ ODPH_ERR("Failed to reserve shm\n");
+ exit(EXIT_FAILURE);
+ }
+
+ memset(global, 0, sizeof(test_global_t));
+
+ num_threads = options.num_threads;
+ addr = NULL;
+ size = ODP_CACHE_LINE_SIZE + ODP_CACHE_LINE_ROUNDUP(options.size);
+ tot_size = num_threads * size;
+ shm_data = odp_shm_reserve("test_data", tot_size, ODP_CACHE_LINE_SIZE, 0);
- if (shm_hdl != ODP_SHM_INVALID)
- shm = (test_shm_t *)odp_shm_addr(shm_hdl);
+ if (shm_data != ODP_SHM_INVALID)
+ addr = odp_shm_addr(shm_data);
- if (!shm) {
- ODPH_ERR("Failed to reserve shm %s\n", shm_name);
+ if (!addr) {
+ ODPH_ERR("Failed to reserve shm: size %" PRIu64 " bytes\n", tot_size);
exit(EXIT_FAILURE);
}
+ for (i = 0; i < num_threads; i++) {
+ global->thread_arg[i].global = global;
+ global->thread_arg[i].thread_idx = i;
+ global->thread_arg[i].data = addr + i * size;
+ }
+
+ odp_shm_print_all();
+
switch (odp_random_max_kind()) {
case ODP_RANDOM_TRUE:
- test_type(instance, shm, ODP_RANDOM_TRUE);
+ test_type(instance, global, ODP_RANDOM_TRUE);
/* fall through */
case ODP_RANDOM_CRYPTO:
- test_type(instance, shm, ODP_RANDOM_CRYPTO);
+ test_type(instance, global, ODP_RANDOM_CRYPTO);
/* fall through */
default:
- test_type(instance, shm, ODP_RANDOM_BASIC);
- test_type(instance, shm, -1);
+ test_type(instance, global, ODP_RANDOM_BASIC);
+ test_type(instance, global, PSEUDO_RANDOM);
+ }
+
+ if (odp_shm_free(shm_data)) {
+ ODPH_ERR("odp_shm_free() failed\n");
+ exit(EXIT_FAILURE);
}
- if (odp_shm_free(shm_hdl)) {
+ if (odp_shm_free(shm_glb)) {
ODPH_ERR("odp_shm_free() failed\n");
exit(EXIT_FAILURE);
}
diff --git a/test/performance/odp_sched_pktio.c b/test/performance/odp_sched_pktio.c
index 77c1d260f..11be9d367 100644
--- a/test/performance/odp_sched_pktio.c
+++ b/test/performance/odp_sched_pktio.c
@@ -862,10 +862,9 @@ static int open_pktios(test_global_t *test_global)
odp_pktin_queue_param_t pktin_param;
odp_pktout_queue_param_t pktout_param;
odp_schedule_sync_t sched_sync;
- unsigned int num_queue;
+ uint32_t num_queue, j;
char *name;
int i, num_pktio, ret;
- unsigned int j;
num_pktio = test_global->opt.num_pktio;
num_queue = test_global->opt.num_pktio_queue;