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", &param);
+       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", &param);
+       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;
+}

Reply via email to