Signed-off-by: Robbie King <[email protected]>
---
 example/ipsec/odp_ipsec_cache.c |  178 +++++++++++++++++++++++++++++++++++++++
 example/ipsec/odp_ipsec_cache.h |  127 ++++++++++++++++++++++++++++
 2 files changed, 305 insertions(+), 0 deletions(-)
 create mode 100644 example/ipsec/odp_ipsec_cache.c
 create mode 100644 example/ipsec/odp_ipsec_cache.h

diff --git a/example/ipsec/odp_ipsec_cache.c b/example/ipsec/odp_ipsec_cache.c
new file mode 100644
index 0000000..0ef95b4
--- /dev/null
+++ b/example/ipsec/odp_ipsec_cache.c
@@ -0,0 +1,178 @@
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <odp.h>
+#include <odp_align.h>
+#include <odp_crypto.h>
+#include <helper/odp_ipsec.h>
+
+#include <odp_ipsec_cache.h>
+
+/** Global pointer to ipsec_cache db */
+ipsec_cache_t *ipsec_cache;
+
+void init_ipsec_cache(void)
+{
+       ipsec_cache = odp_shm_reserve("shm_ipsec_cache",
+                                     sizeof(ipsec_cache_t),
+                                     ODP_CACHE_LINE_SIZE);
+       if (ipsec_cache == NULL) {
+               ODP_ERR("Error: shared mem alloc failed.\n");
+               exit(EXIT_FAILURE);
+       }
+       memset(ipsec_cache, 0, sizeof(*ipsec_cache));
+}
+
+int create_ipsec_cache_entry(sa_db_entry_t *cipher_sa,
+                            sa_db_entry_t *auth_sa,
+                            crypto_api_mode_e api_mode,
+                            bool in,
+                            odp_queue_t completionq,
+                            odp_buffer_t out_pool)
+{
+       odp_crypto_session_params_t params;
+       ipsec_cache_entry_t *entry;
+       enum odp_crypto_ses_create_err ses_create_rc;
+       odp_crypto_session_t session;
+
+       /* Verify we have a good entry */
+       entry = &ipsec_cache->array[ipsec_cache->index];
+       if (MAX_DB <= ipsec_cache->index)
+               return -1;
+
+       /* Setup parameters and call crypto library to create session */
+       params.op = (in) ? ODP_CRYPTO_OP_DECODE : ODP_CRYPTO_OP_ENCODE;
+       params.auth_cipher_text = TRUE;
+       if (CRYPTO_API_SYNC == api_mode) {
+               params.pref_mode   = ODP_CRYPTO_SYNC;
+               params.compl_queue = ODP_QUEUE_INVALID;
+               params.output_pool = ODP_BUFFER_POOL_INVALID;
+       } else {
+               params.pref_mode   = ODP_CRYPTO_ASYNC;
+               params.compl_queue = completionq;
+               params.output_pool = out_pool;
+       }
+
+       if (CRYPTO_API_ASYNC_NEW_BUFFER == api_mode)
+               entry->in_place = FALSE;
+       else
+               entry->in_place = TRUE;
+
+
+       /* Cipher */
+       if (cipher_sa) {
+               params.cipher_alg  = cipher_sa->alg.u.cipher;
+               params.cipher_key.data  = cipher_sa->key.data;
+               params.cipher_key.length  = cipher_sa->key.length;
+               params.iv.data = entry->state.iv;
+               params.iv.length = cipher_sa->iv_len;
+       } else {
+               params.cipher_alg = ODP_CIPHER_ALG_NULL;
+               params.iv.data = NULL;
+               params.iv.length = 0;
+       }
+
+       /* Auth */
+       if (auth_sa) {
+               params.auth_alg = auth_sa->alg.u.auth;
+               params.auth_key.data = auth_sa->key.data;
+               params.auth_key.length = auth_sa->key.length;
+       } else {
+               params.auth_alg = ODP_AUTH_ALG_NULL;
+       }
+
+       /* Generate an IV */
+       if (params.iv.length) {
+               size_t size = params.iv.length;
+
+               odp_hw_random_get(params.iv.data, &size, 1);
+       }
+
+       /* Synchronous session create for now */
+       if (odp_crypto_session_create(&params, &session, &ses_create_rc))
+               return -1;
+       if (ODP_CRYPTO_SES_CREATE_ERR_NONE != ses_create_rc)
+               return -1;
+
+       /* Copy remainder */
+       if (cipher_sa) {
+               entry->src_ip = cipher_sa->src_ip;
+               entry->dst_ip = cipher_sa->dst_ip;
+               entry->esp.alg = cipher_sa->alg.u.cipher;
+               entry->esp.spi = cipher_sa->spi;
+               entry->esp.block_len = cipher_sa->block_len;
+               entry->esp.iv_len = cipher_sa->iv_len;
+               memcpy(&entry->esp.key, &cipher_sa->key, sizeof(ipsec_key_t));
+       }
+       if (auth_sa) {
+               entry->src_ip = auth_sa->src_ip;
+               entry->dst_ip = auth_sa->dst_ip;
+               entry->ah.alg = auth_sa->alg.u.auth;
+               entry->ah.spi = auth_sa->spi;
+               entry->ah.icv_len = auth_sa->icv_len;
+               memcpy(&entry->ah.key, &auth_sa->key, sizeof(ipsec_key_t));
+       }
+
+       /* Initialize state */
+       entry->state.esp_seq = 0;
+       entry->state.ah_seq = 0;
+       entry->state.session = session;
+
+       /* Add entry to the appropriate list */
+       ipsec_cache->index++;
+       if (in) {
+               entry->next = ipsec_cache->in_list;
+               ipsec_cache->in_list = entry;
+       } else {
+               entry->next = ipsec_cache->out_list;
+               ipsec_cache->out_list = entry;
+       }
+
+       return 0;
+}
+
+ipsec_cache_entry_t *find_ipsec_cache_entry_in(uint32_t src_ip,
+                                              uint32_t dst_ip,
+                                              odp_ahhdr_t *ah,
+                                              odp_esphdr_t *esp)
+{
+       ipsec_cache_entry_t *entry = ipsec_cache->in_list;
+
+       /* Look for a hit */
+       for (; NULL != entry; entry = entry->next) {
+               if ((entry->src_ip != src_ip) || (entry->dst_ip != dst_ip))
+                       continue;
+               if (ah &&
+                   ((!entry->ah.alg) ||
+                    (entry->ah.spi != odp_be_to_cpu_32(ah->spi))))
+                       continue;
+               if (esp &&
+                   ((!entry->esp.alg) ||
+                    (entry->esp.spi != odp_be_to_cpu_32(esp->spi))))
+                       continue;
+               break;
+       }
+
+       return entry;
+}
+
+ipsec_cache_entry_t *find_ipsec_cache_entry_out(uint32_t src_ip,
+                                               uint32_t dst_ip,
+                                               uint8_t proto ODP_UNUSED)
+{
+       ipsec_cache_entry_t *entry = ipsec_cache->out_list;
+
+       /* Look for a hit */
+       for (; NULL != entry; entry = entry->next) {
+               if ((entry->src_ip == src_ip) && (entry->dst_ip == dst_ip))
+                       break;
+       }
+       return entry;
+}
+
diff --git a/example/ipsec/odp_ipsec_cache.h b/example/ipsec/odp_ipsec_cache.h
new file mode 100644
index 0000000..0b008c3
--- /dev/null
+++ b/example/ipsec/odp_ipsec_cache.h
@@ -0,0 +1,127 @@
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#ifndef ODP_IPSEC_CACHE_H_
+#define ODP_IPSEC_CACHE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp.h>
+#include <helper/odp_ipsec.h>
+
+#include <odp_ipsec_misc.h>
+#include <odp_ipsec_sa_db.h>
+
+/**
+ * Mode specified on command line indicating how to exercise API
+ */
+typedef enum {
+       CRYPTO_API_SYNC,              /**< Synchronous mode */
+       CRYPTO_API_ASYNC_IN_PLACE,    /**< Asynchronous in place */
+       CRYPTO_API_ASYNC_NEW_BUFFER   /**< Asynchronous new buffer */
+} crypto_api_mode_e;
+
+/**
+ * IPsec cache data base entry
+ */
+typedef struct ipsec_cache_entry_s {
+       struct ipsec_cache_entry_s  *next;        /**< Next entry on list */
+       bool                         in_place;    /**< Crypto API mode */
+       uint32_t                     src_ip;      /**< Source v4 address */
+       uint32_t                     dst_ip;      /**< Destination v4 address */
+       struct {
+               enum  odp_cipher_alg alg;         /**< Cipher algorithm */
+               uint32_t             spi;         /**< Cipher SPI */
+               uint32_t             block_len;   /**< Cipher block length */
+               uint32_t             iv_len;      /**< Cipher IV length */
+               ipsec_key_t          key;         /**< Cipher key */
+       } esp;
+       struct {
+               enum  odp_auth_alg   alg;         /**< Auth algorithm */
+               uint32_t             spi;         /**< Auth SPI */
+               uint32_t             icv_len;     /**< Auth ICV length */
+               ipsec_key_t          key;         /**< Auth key */
+       } ah;
+
+       /* Per SA state */
+       struct {
+               odp_crypto_session_t session;     /**< Crypto session handle */
+               uint32_t             esp_seq;     /**< ESP TX sequence number */
+               uint32_t             ah_seq;      /**< AH TX sequence number */
+               uint8_t              iv[32];      /**< ESP IV storage */
+       } state;
+} ipsec_cache_entry_t;
+
+/**
+ * IPsec cache data base global structure
+ */
+typedef struct ipsec_cache_s {
+       uint32_t             index;       /**< Index of next available entry */
+       ipsec_cache_entry_t *in_list;     /**< List of active input entries*/
+       ipsec_cache_entry_t *out_list;    /**< List of active output entries*/
+       ipsec_cache_entry_t  array[MAX_DB]; /**< Entry storage */
+} ipsec_cache_t;
+
+/** Global pointer to ipsec_cache db */
+extern ipsec_cache_t *ipsec_cache;
+
+/** Initialize IPsec cache */
+void init_ipsec_cache(void);
+
+/**
+ * Create an entry in the IPsec cache
+ *
+ * @param cipher_sa   Cipher SA DB entry pointer
+ * @param auth_sa     Auth SA DB entry pointer
+ * @param api_mode    Crypto API mode for testing
+ * @param in          Direction (input versus output)
+ * @param completionq Completion queue
+ * @param out_pool    Output buffer pool
+ *
+ * @return 0 if successful else -1
+ */
+int create_ipsec_cache_entry(sa_db_entry_t *cipher_sa,
+                            sa_db_entry_t *auth_sa,
+                            crypto_api_mode_e api_mode,
+                            bool in,
+                            odp_queue_t completionq,
+                            odp_buffer_t out_pool);
+
+/**
+ * Find a matching IPsec cache entry for input packet
+ *
+ * @param src_ip    Source IPv4 address
+ * @param dst_ip    Destination IPv4 address
+ * @param ah        Pointer to AH header in packet else NULL
+ * @param esp       Pointer to ESP header in packet else NULL
+ *
+ * @return pointer to IPsec cache entry else NULL
+ */
+ipsec_cache_entry_t *find_ipsec_cache_entry_in(uint32_t src_ip,
+                                              uint32_t dst_ip,
+                                              odp_ahhdr_t *ah,
+                                              odp_esphdr_t *esp);
+
+/**
+ * Find a matching IPsec cache entry for output packet
+ *
+ * @param src_ip    Source IPv4 address
+ * @param dst_ip    Destination IPv4 address
+ * @param proto     IPv4 protocol (currently all protocols match)
+ *
+ * @return pointer to IPsec cache entry else NULL
+ */
+ipsec_cache_entry_t *find_ipsec_cache_entry_out(uint32_t src_ip,
+                                               uint32_t dst_ip,
+                                               uint8_t proto ODP_UNUSED);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
-- 
1.7.7.6


_______________________________________________
lng-odp mailing list
[email protected]
http://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to