diff options
Diffstat (limited to 'test/performance/odp_ipsec.c')
-rw-r--r-- | test/performance/odp_ipsec.c | 415 |
1 files changed, 310 insertions, 105 deletions
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, ¶m); - 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, - ¶m); - if (rc <= 0) { - ODPH_ERR("failed odp_crypto_packet_op_enq: rc = %d\n", + rc = odp_ipsec_out_enq(pkt, num_pkts, ¶m); + 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(¶m); + 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", ¶m); + + 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); |