new file mode 100644
@@ -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(¶ms, &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;
+}
+
new file mode 100644
@@ -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
Signed-off-by: Robbie King <robking@cisco.com> --- 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