From: Dmitry Eremin-Solenikov <[email protected]> Add functions implementing IPsec events support.
Signed-off-by: Dmitry Eremin-Solenikov <[email protected]> --- /** Email created from pull request 28 (lumag:ipsec) ** https://github.com/Linaro/odp/pull/28 ** Patch: https://github.com/Linaro/odp/pull/28.patch ** Base sha: 900dd9e2d3d2ae751ab2bc4e11dbd48ea7ed7030 ** Merge commit sha: 56945703e4054023470e63b004391db311215076 **/ platform/linux-generic/Makefile.am | 1 + .../include/odp/api/plat/event_types.h | 3 +- platform/linux-generic/include/odp_internal.h | 4 + .../linux-generic/include/odp_ipsec_internal.h | 150 ++++++++++++ platform/linux-generic/odp_event.c | 7 + platform/linux-generic/odp_init.c | 13 + platform/linux-generic/odp_ipsec.c | 20 +- platform/linux-generic/odp_ipsec_events.c | 270 +++++++++++++++++++++ 8 files changed, 457 insertions(+), 11 deletions(-) create mode 100644 platform/linux-generic/include/odp_ipsec_internal.h create mode 100644 platform/linux-generic/odp_ipsec_events.c diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am index 79f0e70..478c123 100644 --- a/platform/linux-generic/Makefile.am +++ b/platform/linux-generic/Makefile.am @@ -206,6 +206,7 @@ __LIB__libodp_linux_la_SOURCES = \ odp_init.c \ odp_impl.c \ odp_ipsec.c \ + odp_ipsec_events.c \ odp_name_table.c \ odp_packet.c \ odp_packet_flags.c \ diff --git a/platform/linux-generic/include/odp/api/plat/event_types.h b/platform/linux-generic/include/odp/api/plat/event_types.h index 0f51783..cb3a1f8 100644 --- a/platform/linux-generic/include/odp/api/plat/event_types.h +++ b/platform/linux-generic/include/odp/api/plat/event_types.h @@ -39,7 +39,8 @@ typedef enum odp_event_type_t { ODP_EVENT_PACKET = 2, ODP_EVENT_TIMEOUT = 3, ODP_EVENT_CRYPTO_COMPL = 4, - ODP_EVENT_IPSEC_RESULT = 5 + ODP_EVENT_IPSEC_RESULT = 5, + ODP_EVENT_IPSEC_STATUS = 6 } odp_event_type_t; /** diff --git a/platform/linux-generic/include/odp_internal.h b/platform/linux-generic/include/odp_internal.h index 90e2a62..ca8a262 100644 --- a/platform/linux-generic/include/odp_internal.h +++ b/platform/linux-generic/include/odp_internal.h @@ -70,6 +70,7 @@ enum init_stage { CLASSIFICATION_INIT, TRAFFIC_MNGR_INIT, NAME_TABLE_INIT, + IPSEC_EVENTS_INIT, MODULES_INIT, ALL_INIT /* All init stages completed */ }; @@ -129,6 +130,9 @@ int _odp_ishm_init_local(void); int _odp_ishm_term_global(void); int _odp_ishm_term_local(void); +int odp_ipsec_events_init_global(void); +int odp_ipsec_events_term_global(void); + int _odp_modules_init_global(void); int cpuinfo_parser(FILE *file, system_info_t *sysinfo); diff --git a/platform/linux-generic/include/odp_ipsec_internal.h b/platform/linux-generic/include/odp_ipsec_internal.h new file mode 100644 index 0000000..9f644a8 --- /dev/null +++ b/platform/linux-generic/include/odp_ipsec_internal.h @@ -0,0 +1,150 @@ +/* Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * @file + * + * ODP internal IPsec routines + */ + +#ifndef ODP_IPSEC_INTERNAL_H_ +#define ODP_IPSEC_INTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <odp/api/std_types.h> +#include <odp/api/plat/strong_types.h> + +#include <odp/api/ipsec.h> + +/** @ingroup odp_ipsec + * @{ + */ + +typedef ODP_HANDLE_T(ipsec_result_t); + +#define ODP_IPSEC_RESULT_INVALID \ + _odp_cast_scalar(ipsec_result_t, 0xffffffff) + +typedef ODP_HANDLE_T(ipsec_status_t); + +#define ODP_IPSEC_STATUS_INVALID \ + _odp_cast_scalar(ipsec_status_t, 0xffffffff) + +typedef struct ipsec_ctx_s ipsec_ctx_t; + +/** + * @internal Free IPsec context + * + * Frees the IPsec context into the pool it was allocated from. + * + * @param ctx IPsec context + */ +void _odp_ipsec_ctx_free(ipsec_ctx_t *ctx); + +/** + * @internal Process context filling operation result information + * + * Processes IPsec operation context related to completed operation, extracting + * operation result information. This function may update context provided via + * pointer to opaque context pointer. + * + * @param ctx IPsec context pointer. + * @param[out] result Pointer to operation result for output. May be + * NULL, if application is interested only on the + * number of packets. + * + * @return Number of packets remaining in the event. + * @retval <0 On failure + */ +int _odp_ipsec_ctx_result(ipsec_ctx_t *ctx, odp_ipsec_op_result_t *result); + +/** + * @internal Get ipsec_result handle from event + * + * Converts an ODP_EVENT_IPSEC_RESULT type event to an IPsec result event. + * + * @param ev Event handle + * + * @return IPsec result handle + * + * @see odp_event_type() + */ +ipsec_result_t _odp_ipsec_result_from_event(odp_event_t ev); + +/** + * @internal Free IPsec result event + * + * Frees the ipsec_result into the ipsec_result pool it was allocated from. + * + * @param res IPsec result handle + */ +void _odp_ipsec_result_free(ipsec_result_t res); + +/** + * @internal Send ODP_IPSEC_RESULT event + * + * Sends the ipsec_result event using provided information + * + * @param queue destination queue + * @param ctx IPsec context for the operation + * + * @retval 0 on success + * @retval <0 on failure + */ +int _odp_ipsec_result_send(odp_queue_t queue, ipsec_ctx_t *ctx); + +/** + * @internal Get ipsec_status handle from event + * + * Converts an ODP_EVENT_IPSEC_STATUS type event to an IPsec status event. + * + * @param ev Event handle + * + * @return IPsec status handle + * + * @see odp_event_type() + */ +ipsec_status_t _odp_ipsec_status_from_event(odp_event_t ev); + +/** + * @internal Free IPsec status event + * + * Frees the ipsec_status into the ipsec_status pool it was allocated from. + * + * @param res IPsec status handle + */ +void _odp_ipsec_status_free(ipsec_status_t status); + +/** + * @internal Send ODP_IPSEC_STATUS event + * + * Sends the ipsec_status event using provided information + * + * @param queue destination queue + * @param id status id + * @param ret status value + * @param sa SA respective to the operation + * + * @retval 0 on success + * @retval <0 on failure + */ +int _odp_ipsec_status_send(odp_queue_t queue, + odp_ipsec_status_id_t id, + int ret, + odp_ipsec_sa_t sa); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/linux-generic/odp_event.c b/platform/linux-generic/odp_event.c index d71f446..fd0a5ff 100644 --- a/platform/linux-generic/odp_event.c +++ b/platform/linux-generic/odp_event.c @@ -11,6 +11,7 @@ #include <odp/api/timer.h> #include <odp/api/pool.h> #include <odp_buffer_internal.h> +#include <odp_ipsec_internal.h> #include <odp_buffer_inlines.h> #include <odp_debug_internal.h> @@ -34,6 +35,12 @@ void odp_event_free(odp_event_t event) case ODP_EVENT_CRYPTO_COMPL: odp_crypto_compl_free(odp_crypto_compl_from_event(event)); break; + case ODP_EVENT_IPSEC_RESULT: + _odp_ipsec_result_free(_odp_ipsec_result_from_event(event)); + break; + case ODP_EVENT_IPSEC_STATUS: + _odp_ipsec_status_free(_odp_ipsec_status_from_event(event)); + break; default: ODP_ABORT("Invalid event type: %d\n", odp_event_type(event)); } diff --git a/platform/linux-generic/odp_init.c b/platform/linux-generic/odp_init.c index 685e02f..647c05e 100644 --- a/platform/linux-generic/odp_init.c +++ b/platform/linux-generic/odp_init.c @@ -266,6 +266,12 @@ int odp_init_global(odp_instance_t *instance, } stage = NAME_TABLE_INIT; + if (odp_ipsec_events_init_global()) { + ODP_ERR("ODP IPsec events init failed.\n"); + goto init_failed; + } + stage = IPSEC_EVENTS_INIT; + if (_odp_modules_init_global()) { ODP_ERR("ODP modules init failed\n"); goto init_failed; @@ -296,6 +302,13 @@ int _odp_term_global(enum init_stage stage) switch (stage) { case ALL_INIT: case MODULES_INIT: + case IPSEC_EVENTS_INIT: + if (odp_ipsec_events_term_global()) { + ODP_ERR("ODP IPsec events term failed.\n"); + rc = -1; + } + /* Fall through */ + case NAME_TABLE_INIT: if (_odp_int_name_tbl_term_global()) { ODP_ERR("Name table term failed.\n"); diff --git a/platform/linux-generic/odp_ipsec.c b/platform/linux-generic/odp_ipsec.c index 10918df..0e00462 100644 --- a/platform/linux-generic/odp_ipsec.c +++ b/platform/linux-generic/odp_ipsec.c @@ -6,8 +6,11 @@ #include <odp/api/ipsec.h> +#include <odp_ipsec_internal.h> + #include <string.h> + int odp_ipsec_capability(odp_ipsec_capability_t *capa) { memset(capa, 0, sizeof(odp_ipsec_capability_t)); @@ -73,6 +76,11 @@ int odp_ipsec_sa_destroy(odp_ipsec_sa_t sa) return -1; } +void _odp_ipsec_ctx_free(ipsec_ctx_t *ctx) +{ + (void)ctx; +} + int odp_ipsec_in(const odp_ipsec_op_param_t *input, odp_ipsec_op_result_t *output) { @@ -114,18 +122,10 @@ int odp_ipsec_out_inline(const odp_ipsec_op_param_t *op_param, return -1; } -int odp_ipsec_result(odp_ipsec_op_result_t *result, odp_event_t event) +int _odp_ipsec_ctx_result(ipsec_ctx_t *ctx, odp_ipsec_op_result_t *result) { + (void)ctx; (void)result; - (void)event; - - return -1; -} - -int odp_ipsec_status(odp_ipsec_status_t *status, odp_event_t event) -{ - (void)status; - (void)event; return -1; } diff --git a/platform/linux-generic/odp_ipsec_events.c b/platform/linux-generic/odp_ipsec_events.c new file mode 100644 index 0000000..5f2e649 --- /dev/null +++ b/platform/linux-generic/odp_ipsec_events.c @@ -0,0 +1,270 @@ +/* Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <odp/api/ipsec.h> +#include <odp/api/shared_memory.h> + +#include <odp_buffer_internal.h> +#include <odp_buffer_inlines.h> +#include <odp_debug_internal.h> +#include <odp_ipsec_internal.h> +#include <odp_pool_internal.h> + +typedef struct { + /* common buffer header */ + odp_buffer_hdr_t buf_hdr; + + ipsec_ctx_t *ctx; +} ipsec_result_hdr_t; + +typedef struct { + /* common buffer header */ + odp_buffer_hdr_t buf_hdr; + + odp_ipsec_status_t status; +} ipsec_status_hdr_t; + +static odp_pool_t ipsec_result_pool = ODP_POOL_INVALID; +static odp_pool_t ipsec_status_pool = ODP_POOL_INVALID; + +#define IPSEC_EVENTS_POOL_BUF_COUNT 1024 + +int odp_ipsec_events_init_global(void) +{ + odp_pool_param_t param; + + param.buf.size = sizeof(ipsec_result_hdr_t); + param.buf.align = 0; + param.buf.num = IPSEC_EVENTS_POOL_BUF_COUNT; + param.type = ODP_POOL_BUFFER; + + ipsec_result_pool = odp_pool_create("ipsec_result_pool", ¶m); + if (ODP_POOL_INVALID == ipsec_result_pool) { + ODP_ERR("Error: result pool create failed.\n"); + goto err_result; + } + + param.buf.size = sizeof(ipsec_status_hdr_t); + param.buf.align = 0; + param.buf.num = IPSEC_EVENTS_POOL_BUF_COUNT; + param.type = ODP_POOL_BUFFER; + + ipsec_status_pool = odp_pool_create("ipsec_status_pool", ¶m); + if (ODP_POOL_INVALID == ipsec_status_pool) { + ODP_ERR("Error: status pool create failed.\n"); + goto err_status; + } + + return 0; + +err_status: + (void)odp_pool_destroy(ipsec_result_pool); +err_result: + return -1; +} + +int odp_ipsec_events_term_global(void) +{ + int ret = 0; + int rc = 0; + + ret = odp_pool_destroy(ipsec_status_pool); + if (ret < 0) { + ODP_ERR("status pool destroy failed"); + rc = -1; + } + + ret = odp_pool_destroy(ipsec_result_pool); + if (ret < 0) { + ODP_ERR("result pool destroy failed"); + rc = -1; + } + + return rc; +} + +ipsec_result_t _odp_ipsec_result_from_event(odp_event_t ev) +{ + ODP_ASSERT(ODP_EVENT_INVALID != ev); + ODP_ASSERT(ODP_EVENT_IPSEC_RESULT == odp_event_type(ev)); + + return (ipsec_result_t)ev; +} + +static +odp_event_t ipsec_result_to_event(ipsec_result_t res) +{ + ODP_ASSERT(ODP_IPSEC_RESULT_INVALID != res); + + return (odp_event_t)res; +} + +static +ipsec_result_hdr_t *ipsec_result_hdr_from_buf(odp_buffer_t buf) +{ + return (ipsec_result_hdr_t *)(void *)buf_hdl_to_hdr(buf); +} + +static +ipsec_result_hdr_t *ipsec_result_hdr(ipsec_result_t res) +{ + odp_buffer_t buf = odp_buffer_from_event(ipsec_result_to_event(res)); + + return ipsec_result_hdr_from_buf(buf); +} + +static +ipsec_result_t _odp_ipsec_result_alloc(void) +{ + odp_buffer_t buf = odp_buffer_alloc(ipsec_result_pool); + + if (odp_unlikely(buf == ODP_BUFFER_INVALID)) + return ODP_IPSEC_RESULT_INVALID; + + _odp_buffer_event_type_set(buf, ODP_EVENT_IPSEC_RESULT); + + return _odp_ipsec_result_from_event(odp_buffer_to_event(buf)); +} + +void _odp_ipsec_result_free(ipsec_result_t res) +{ + odp_event_t ev = ipsec_result_to_event(res); + ipsec_result_hdr_t *res_hdr = ipsec_result_hdr(res); + + _odp_ipsec_ctx_free(res_hdr->ctx); + + odp_buffer_free(odp_buffer_from_event(ev)); +} + +int _odp_ipsec_result_send(odp_queue_t queue, ipsec_ctx_t *ctx) +{ + ipsec_result_t ipsec_ev; + ipsec_result_hdr_t *res_hdr; + + ipsec_ev = _odp_ipsec_result_alloc(); + if (odp_unlikely(ODP_IPSEC_RESULT_INVALID == ipsec_ev)) + return -1; + + res_hdr = ipsec_result_hdr(ipsec_ev); + res_hdr->ctx = ctx; + + if (odp_queue_enq(queue, ipsec_result_to_event(ipsec_ev))) { + _odp_ipsec_result_free(ipsec_ev); + return -1; + } + + return 0; +} + +int odp_ipsec_result(odp_ipsec_op_result_t *result, odp_event_t event) +{ + ipsec_result_t ipsec_ev; + ipsec_result_hdr_t *res_hdr; + + ODP_ASSERT(ODP_EVENT_INVALID != event); + + ipsec_ev = _odp_ipsec_result_from_event(event); + ODP_ASSERT(ODP_IPSEC_RESULT_INVALID != ipsec_ev); + + res_hdr = ipsec_result_hdr(ipsec_ev); + + return _odp_ipsec_ctx_result(res_hdr->ctx, result); +} + + +ipsec_status_t _odp_ipsec_status_from_event(odp_event_t ev) +{ + ODP_ASSERT(ODP_EVENT_INVALID != ev); + ODP_ASSERT(ODP_EVENT_IPSEC_STATUS == odp_event_type(ev)); + + return (ipsec_status_t)ev; +} + +static +odp_event_t ipsec_status_to_event(ipsec_status_t status) +{ + ODP_ASSERT(ODP_IPSEC_STATUS_INVALID != status); + + return (odp_event_t)status; +} + +static +ipsec_status_hdr_t *ipsec_status_hdr_from_buf(odp_buffer_t buf) +{ + return (ipsec_status_hdr_t *)(void *)buf_hdl_to_hdr(buf); +} + +static +ipsec_status_hdr_t *ipsec_status_hdr(ipsec_status_t status) +{ + odp_buffer_t buf = odp_buffer_from_event(ipsec_status_to_event(status)); + + return ipsec_status_hdr_from_buf(buf); +} + +static +ipsec_status_t odp_ipsec_status_alloc(void) +{ + odp_buffer_t buf = odp_buffer_alloc(ipsec_status_pool); + + if (odp_unlikely(buf == ODP_BUFFER_INVALID)) + return ODP_IPSEC_STATUS_INVALID; + + _odp_buffer_event_type_set(buf, ODP_EVENT_IPSEC_STATUS); + + return _odp_ipsec_status_from_event(odp_buffer_to_event(buf)); +} + +void _odp_ipsec_status_free(ipsec_status_t status) +{ + odp_event_t ev = ipsec_status_to_event(status); + + odp_buffer_free(odp_buffer_from_event(ev)); +} + +int _odp_ipsec_status_send(odp_queue_t queue, + odp_ipsec_status_id_t id, + int ret, + odp_ipsec_sa_t sa) +{ + ipsec_status_t ipsec_ev = odp_ipsec_status_alloc(); + ipsec_status_hdr_t *status_hdr; + + if (ODP_IPSEC_STATUS_INVALID == ipsec_ev) + return -1; + + status_hdr = ipsec_status_hdr(ipsec_ev); + + status_hdr->status.id = id; + status_hdr->status.ret = ret; + status_hdr->status.sa = sa; + + if (odp_queue_enq(queue, ipsec_status_to_event(ipsec_ev))) { + _odp_ipsec_status_free(ipsec_ev); + return -1; + } + + return 0; +} + +int odp_ipsec_status(odp_ipsec_status_t *status, odp_event_t event) +{ + ipsec_status_t ipsec_ev; + ipsec_status_hdr_t *status_hdr; + + if (odp_unlikely(ODP_EVENT_INVALID == event)) + return -1; + + ipsec_ev = _odp_ipsec_status_from_event(event); + if (odp_unlikely(ODP_IPSEC_STATUS_INVALID == ipsec_ev)) + return -1; + + status_hdr = ipsec_status_hdr(ipsec_ev); + + *status = status_hdr->status; + + return 0; +}
