From: Jack Bond-Preston <jack.bond-preston@foss.arm.com>
To: Kai Ji <kai.ji@intel.com>
Cc: dev@dpdk.org, Wathsala Vithanage <wathsala.vithanage@arm.com>
Subject: [PATCH v2 4/5] crypto/openssl: per-qp auth context clones
Date: Mon, 3 Jun 2024 18:43:47 +0000 [thread overview]
Message-ID: <20240603184348.1310331-5-jack.bond-preston@foss.arm.com> (raw)
In-Reply-To: <20240603184348.1310331-1-jack.bond-preston@foss.arm.com>
Currently EVP auth ctxs (e.g. EVP_MD_CTX, EVP_MAC_CTX) are allocated,
copied to (from openssl_session), and then freed for every auth
operation (ie. per packet). This is very inefficient, and avoidable.
Make each openssl_session hold an array of structures, containing
pointers to per-queue-pair cipher and auth context copies. These are
populated on first use by allocating a new context and copying from the
main context. These copies can then be used in a thread-safe manner by
different worker lcores simultaneously. Consequently the auth context
allocation and copy only has to happen once - the first time a given qp
uses an openssl_session. This brings about a large performance boost.
Throughput performance uplift measurements for HMAC-SHA1 generate on
Ampere Altra Max platform:
1 worker lcore
| buffer sz (B) | prev (Gbps) | optimised (Gbps) | uplift |
|-----------------+---------------+--------------------+----------|
| 64 | 0.63 | 1.42 | 123.5% |
| 256 | 2.24 | 4.40 | 96.4% |
| 1024 | 6.15 | 9.26 | 50.6% |
| 2048 | 8.68 | 11.38 | 31.1% |
| 4096 | 10.92 | 12.84 | 17.6% |
8 worker lcores
| buffer sz (B) | prev (Gbps) | optimised (Gbps) | uplift |
|-----------------+---------------+--------------------+----------|
| 64 | 0.93 | 11.35 | 1122.5% |
| 256 | 3.70 | 35.30 | 853.7% |
| 1024 | 15.22 | 74.27 | 387.8% |
| 2048 | 30.20 | 91.08 | 201.6% |
| 4096 | 56.92 | 102.76 | 80.5% |
Signed-off-by: Jack Bond-Preston <jack.bond-preston@foss.arm.com>
Reviewed-by: Wathsala Vithanage <wathsala.vithanage@arm.com>
---
drivers/crypto/openssl/compat.h | 26 ++++
drivers/crypto/openssl/openssl_pmd_private.h | 25 +++-
drivers/crypto/openssl/rte_openssl_pmd.c | 144 ++++++++++++++-----
drivers/crypto/openssl/rte_openssl_pmd_ops.c | 7 +-
4 files changed, 161 insertions(+), 41 deletions(-)
diff --git a/drivers/crypto/openssl/compat.h b/drivers/crypto/openssl/compat.h
index 9f9167c4f1..4c5ddfbf3a 100644
--- a/drivers/crypto/openssl/compat.h
+++ b/drivers/crypto/openssl/compat.h
@@ -5,6 +5,32 @@
#ifndef __RTA_COMPAT_H__
#define __RTA_COMPAT_H__
+#if OPENSSL_VERSION_NUMBER > 0x30000000L
+static __rte_always_inline void
+free_hmac_ctx(EVP_MAC_CTX *ctx)
+{
+ EVP_MAC_CTX_free(ctx);
+}
+
+static __rte_always_inline void
+free_cmac_ctx(EVP_MAC_CTX *ctx)
+{
+ EVP_MAC_CTX_free(ctx);
+}
+#else
+static __rte_always_inline void
+free_hmac_ctx(HMAC_CTX *ctx)
+{
+ HMAC_CTX_free(ctx);
+}
+
+static __rte_always_inline void
+free_cmac_ctx(CMAC_CTX *ctx)
+{
+ CMAC_CTX_free(ctx);
+}
+#endif
+
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
static __rte_always_inline int
diff --git a/drivers/crypto/openssl/openssl_pmd_private.h b/drivers/crypto/openssl/openssl_pmd_private.h
index bad7dcf2f5..a50e4d4918 100644
--- a/drivers/crypto/openssl/openssl_pmd_private.h
+++ b/drivers/crypto/openssl/openssl_pmd_private.h
@@ -80,6 +80,20 @@ struct __rte_cache_aligned openssl_qp {
*/
};
+struct evp_ctx_pair {
+ EVP_CIPHER_CTX *cipher;
+ union {
+ EVP_MD_CTX *auth;
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ EVP_MAC_CTX *hmac;
+ EVP_MAC_CTX *cmac;
+#else
+ HMAC_CTX *hmac;
+ CMAC_CTX *cmac;
+#endif
+ };
+};
+
/** OPENSSL crypto private session structure */
struct __rte_cache_aligned openssl_session {
enum openssl_chain_order chain_order;
@@ -168,11 +182,12 @@ struct __rte_cache_aligned openssl_session {
uint16_t ctx_copies_len;
/* < number of entries in ctx_copies */
- EVP_CIPHER_CTX *qp_ctx[];
- /**< Flexible array member of per-queue-pair pointers to copies of EVP
- * context structure. Cipher contexts are not safe to use from multiple
- * cores simultaneously, so maintaining these copies allows avoiding
- * per-buffer copying into a temporary context.
+ struct evp_ctx_pair qp_ctx[];
+ /**< Flexible array member of per-queue-pair structures, each containing
+ * pointers to copies of the cipher and auth EVP contexts. Cipher
+ * contexts are not safe to use from multiple cores simultaneously, so
+ * maintaining these copies allows avoiding per-buffer copying into a
+ * temporary context.
*/
};
diff --git a/drivers/crypto/openssl/rte_openssl_pmd.c b/drivers/crypto/openssl/rte_openssl_pmd.c
index ebd1cab667..743b20c5b0 100644
--- a/drivers/crypto/openssl/rte_openssl_pmd.c
+++ b/drivers/crypto/openssl/rte_openssl_pmd.c
@@ -864,40 +864,45 @@ openssl_set_session_parameters(struct openssl_session *sess,
void
openssl_reset_session(struct openssl_session *sess)
{
+ /* Free all the qp_ctx entries. */
for (uint16_t i = 0; i < sess->ctx_copies_len; i++) {
- if (sess->qp_ctx[i] != NULL) {
- EVP_CIPHER_CTX_free(sess->qp_ctx[i]);
- sess->qp_ctx[i] = NULL;
+ if (sess->qp_ctx[i].cipher != NULL) {
+ EVP_CIPHER_CTX_free(sess->qp_ctx[i].cipher);
+ sess->qp_ctx[i].cipher = NULL;
+ }
+
+ switch (sess->auth.mode) {
+ case OPENSSL_AUTH_AS_AUTH:
+ EVP_MD_CTX_destroy(sess->qp_ctx[i].auth);
+ sess->qp_ctx[i].auth = NULL;
+ break;
+ case OPENSSL_AUTH_AS_HMAC:
+ free_hmac_ctx(sess->qp_ctx[i].hmac);
+ sess->qp_ctx[i].hmac = NULL;
+ break;
+ case OPENSSL_AUTH_AS_CMAC:
+ free_cmac_ctx(sess->qp_ctx[i].cmac);
+ sess->qp_ctx[i].cmac = NULL;
+ break;
}
}
EVP_CIPHER_CTX_free(sess->cipher.ctx);
- if (sess->chain_order == OPENSSL_CHAIN_CIPHER_BPI)
- EVP_CIPHER_CTX_free(sess->cipher.bpi_ctx);
-
switch (sess->auth.mode) {
case OPENSSL_AUTH_AS_AUTH:
EVP_MD_CTX_destroy(sess->auth.auth.ctx);
break;
case OPENSSL_AUTH_AS_HMAC:
- EVP_PKEY_free(sess->auth.hmac.pkey);
-# if OPENSSL_VERSION_NUMBER >= 0x30000000L
- EVP_MAC_CTX_free(sess->auth.hmac.ctx);
-# else
- HMAC_CTX_free(sess->auth.hmac.ctx);
-# endif
+ free_hmac_ctx(sess->auth.hmac.ctx);
break;
case OPENSSL_AUTH_AS_CMAC:
-# if OPENSSL_VERSION_NUMBER >= 0x30000000L
- EVP_MAC_CTX_free(sess->auth.cmac.ctx);
-# else
- CMAC_CTX_free(sess->auth.cmac.ctx);
-# endif
- break;
- default:
+ free_cmac_ctx(sess->auth.cmac.ctx);
break;
}
+
+ if (sess->chain_order == OPENSSL_CHAIN_CIPHER_BPI)
+ EVP_CIPHER_CTX_free(sess->cipher.bpi_ctx);
}
/** Provide session for operation */
@@ -1443,6 +1448,9 @@ process_openssl_auth_mac(struct rte_mbuf *mbuf_src, uint8_t *dst, int offset,
if (m == 0)
goto process_auth_err;
+ if (EVP_MAC_init(ctx, NULL, 0, NULL) <= 0)
+ goto process_auth_err;
+
src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
l = rte_pktmbuf_data_len(m) - offset;
@@ -1469,11 +1477,9 @@ process_openssl_auth_mac(struct rte_mbuf *mbuf_src, uint8_t *dst, int offset,
if (EVP_MAC_final(ctx, dst, &dstlen, DIGEST_LENGTH_MAX) != 1)
goto process_auth_err;
- EVP_MAC_CTX_free(ctx);
return 0;
process_auth_err:
- EVP_MAC_CTX_free(ctx);
OPENSSL_LOG(ERR, "Process openssl auth failed");
return -EINVAL;
}
@@ -1592,7 +1598,7 @@ get_local_cipher_ctx(struct openssl_session *sess, struct openssl_qp *qp)
if (sess->ctx_copies_len == 0)
return sess->cipher.ctx;
- EVP_CIPHER_CTX **lctx = &sess->qp_ctx[qp->id];
+ EVP_CIPHER_CTX **lctx = &sess->qp_ctx[qp->id].cipher;
if (unlikely(*lctx == NULL)) {
#if OPENSSL_VERSION_NUMBER >= 0x30200000L
@@ -1607,6 +1613,86 @@ get_local_cipher_ctx(struct openssl_session *sess, struct openssl_qp *qp)
return *lctx;
}
+static inline EVP_MD_CTX *
+get_local_auth_ctx(struct openssl_session *sess, struct openssl_qp *qp)
+{
+ /* If the array is not being used, just return the main context. */
+ if (sess->ctx_copies_len == 0)
+ return sess->auth.auth.ctx;
+
+ EVP_MD_CTX **lctx = &sess->qp_ctx[qp->id].auth;
+
+ if (unlikely(*lctx == NULL)) {
+#if OPENSSL_VERSION_NUMBER >= 0x30100000L
+ /* EVP_MD_CTX_dup() added in OSSL 3.1 */
+ *lctx = EVP_MD_CTX_dup(sess->auth.auth.ctx);
+#else
+ *lctx = EVP_MD_CTX_new();
+ EVP_MD_CTX_copy(*lctx, sess->auth.auth.ctx);
+#endif
+ }
+
+ return *lctx;
+}
+
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+static inline EVP_MAC_CTX *
+#else
+static inline HMAC_CTX *
+#endif
+get_local_hmac_ctx(struct openssl_session *sess, struct openssl_qp *qp)
+{
+ if (sess->ctx_copies_len == 0)
+ return sess->auth.hmac.ctx;
+
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ EVP_MAC_CTX **lctx =
+#else
+ HMAC_CTX **lctx =
+#endif
+ &sess->qp_ctx[qp->id].hmac;
+
+ if (unlikely(*lctx == NULL)) {
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ *lctx = EVP_MAC_CTX_dup(sess->auth.hmac.ctx);
+#else
+ *lctx = HMAC_CTX_new();
+ HMAC_CTX_copy(*lctx, sess->auth.hmac.ctx);
+#endif
+ }
+
+ return *lctx;
+}
+
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+static inline EVP_MAC_CTX *
+#else
+static inline CMAC_CTX *
+#endif
+get_local_cmac_ctx(struct openssl_session *sess, struct openssl_qp *qp)
+{
+ if (sess->ctx_copies_len == 0)
+ return sess->auth.cmac.ctx;
+
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ EVP_MAC_CTX **lctx =
+#else
+ CMAC_CTX **lctx =
+#endif
+ &sess->qp_ctx[qp->id].cmac;
+
+ if (unlikely(*lctx == NULL)) {
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ *lctx = EVP_MAC_CTX_dup(sess->auth.cmac.ctx);
+#else
+ *lctx = CMAC_CTX_new();
+ CMAC_CTX_copy(*lctx, sess->auth.cmac.ctx);
+#endif
+ }
+
+ return *lctx;
+}
+
/** Process auth/cipher combined operation */
static void
process_openssl_combined_op(struct openssl_qp *qp, struct rte_crypto_op *op,
@@ -1855,41 +1941,33 @@ process_openssl_auth_op(struct openssl_qp *qp, struct rte_crypto_op *op,
switch (sess->auth.mode) {
case OPENSSL_AUTH_AS_AUTH:
- ctx_a = EVP_MD_CTX_create();
- EVP_MD_CTX_copy_ex(ctx_a, sess->auth.auth.ctx);
+ ctx_a = get_local_auth_ctx(sess, qp);
status = process_openssl_auth(mbuf_src, dst,
op->sym->auth.data.offset, NULL, NULL, srclen,
ctx_a, sess->auth.auth.evp_algo);
- EVP_MD_CTX_destroy(ctx_a);
break;
case OPENSSL_AUTH_AS_HMAC:
+ ctx_h = get_local_hmac_ctx(sess, qp);
# if OPENSSL_VERSION_NUMBER >= 0x30000000L
- ctx_h = EVP_MAC_CTX_dup(sess->auth.hmac.ctx);
status = process_openssl_auth_mac(mbuf_src, dst,
op->sym->auth.data.offset, srclen,
ctx_h);
# else
- ctx_h = HMAC_CTX_new();
- HMAC_CTX_copy(ctx_h, sess->auth.hmac.ctx);
status = process_openssl_auth_hmac(mbuf_src, dst,
op->sym->auth.data.offset, srclen,
ctx_h);
- HMAC_CTX_free(ctx_h);
# endif
break;
case OPENSSL_AUTH_AS_CMAC:
+ ctx_c = get_local_cmac_ctx(sess, qp);
# if OPENSSL_VERSION_NUMBER >= 0x30000000L
- ctx_c = EVP_MAC_CTX_dup(sess->auth.cmac.ctx);
status = process_openssl_auth_mac(mbuf_src, dst,
op->sym->auth.data.offset, srclen,
ctx_c);
# else
- ctx_c = CMAC_CTX_new();
- CMAC_CTX_copy(ctx_c, sess->auth.cmac.ctx);
status = process_openssl_auth_cmac(mbuf_src, dst,
op->sym->auth.data.offset, srclen,
ctx_c);
- CMAC_CTX_free(ctx_c);
# endif
break;
default:
diff --git a/drivers/crypto/openssl/rte_openssl_pmd_ops.c b/drivers/crypto/openssl/rte_openssl_pmd_ops.c
index 4209c6ab6f..1bbb855a59 100644
--- a/drivers/crypto/openssl/rte_openssl_pmd_ops.c
+++ b/drivers/crypto/openssl/rte_openssl_pmd_ops.c
@@ -805,7 +805,7 @@ openssl_pmd_sym_session_get_size(struct rte_cryptodev *dev)
unsigned int max_nb_qps = ((struct openssl_private *)
dev->data->dev_private)->max_nb_qpairs;
return sizeof(struct openssl_session) +
- (sizeof(void *) * max_nb_qps);
+ (sizeof(struct evp_ctx_pair) * max_nb_qps);
}
/*
@@ -818,10 +818,11 @@ openssl_pmd_sym_session_get_size(struct rte_cryptodev *dev)
/*
* Otherwise, the size of the flexible array member should be enough to
- * fit pointers to per-qp contexts.
+ * fit pointers to per-qp contexts. This is twice the number of queue
+ * pairs, to allow for auth and cipher contexts.
*/
return sizeof(struct openssl_session) +
- (sizeof(void *) * dev->data->nb_queue_pairs);
+ (sizeof(struct evp_ctx_pair) * dev->data->nb_queue_pairs);
}
/** Returns the size of the asymmetric session structure */
--
2.34.1
next prev parent reply other threads:[~2024-06-03 19:21 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-06-03 16:01 [PATCH 0/5] OpenSSL PMD Optimisations Jack Bond-Preston
2024-06-03 16:01 ` [PATCH 1/5] crypto/openssl: fix GCM and CCM thread unsafe ctxs Jack Bond-Preston
2024-06-03 16:12 ` Jack Bond-Preston
2024-06-03 16:01 ` [PATCH 2/5] crypto/openssl: only init 3DES-CTR key + impl once Jack Bond-Preston
2024-06-03 16:01 ` [PATCH 3/5] crypto/openssl: per-qp cipher context clones Jack Bond-Preston
2024-06-03 16:01 ` [PATCH 4/5] crypto/openssl: per-qp auth " Jack Bond-Preston
2024-06-03 16:30 ` Jack Bond-Preston
2024-06-03 16:01 ` [PATCH 5/5] crypto/openssl: only set cipher padding once Jack Bond-Preston
2024-06-03 18:43 ` [PATCH v2 0/5] OpenSSL PMD Optimisations Jack Bond-Preston
2024-06-03 18:43 ` [PATCH v2 1/5] crypto/openssl: fix GCM and CCM thread unsafe ctxs Jack Bond-Preston
2024-06-03 18:43 ` [PATCH v2 2/5] crypto/openssl: only init 3DES-CTR key + impl once Jack Bond-Preston
2024-06-03 18:43 ` [PATCH v2 3/5] crypto/openssl: per-qp cipher context clones Jack Bond-Preston
2024-06-03 18:43 ` Jack Bond-Preston [this message]
2024-06-03 18:43 ` [PATCH v2 5/5] crypto/openssl: only set cipher padding once Jack Bond-Preston
2024-06-03 18:59 ` [PATCH v2 0/5] OpenSSL PMD Optimisations Jack Bond-Preston
2024-06-03 18:59 ` [PATCH v2 1/5] crypto/openssl: fix GCM and CCM thread unsafe ctxs Jack Bond-Preston
2024-06-03 18:59 ` [PATCH v2 2/5] crypto/openssl: only init 3DES-CTR key + impl once Jack Bond-Preston
2024-06-03 18:59 ` [PATCH v2 3/5] crypto/openssl: per-qp cipher context clones Jack Bond-Preston
2024-06-03 18:59 ` [PATCH v2 4/5] crypto/openssl: per-qp auth " Jack Bond-Preston
2024-06-03 18:59 ` [PATCH v2 5/5] crypto/openssl: only set cipher padding once Jack Bond-Preston
2024-06-06 10:20 ` [PATCH v3 0/5] OpenSSL PMD Optimisations Jack Bond-Preston
2024-06-06 10:20 ` [PATCH v3 1/5] crypto/openssl: fix GCM and CCM thread unsafe ctxs Jack Bond-Preston
2024-06-06 10:44 ` [EXTERNAL] " Akhil Goyal
2024-06-06 10:20 ` [PATCH v3 2/5] crypto/openssl: only init 3DES-CTR key + impl once Jack Bond-Preston
2024-06-06 10:20 ` [PATCH v3 3/5] crypto/openssl: per-qp cipher context clones Jack Bond-Preston
2024-06-06 10:20 ` [PATCH v3 4/5] crypto/openssl: per-qp auth " Jack Bond-Preston
2024-06-06 10:20 ` [PATCH v3 5/5] crypto/openssl: only set cipher padding once Jack Bond-Preston
2024-06-07 12:47 ` [PATCH v4 0/5] OpenSSL PMD Optimisations Jack Bond-Preston
2024-06-07 12:47 ` [PATCH v4 1/5] crypto/openssl: fix GCM and CCM thread unsafe ctxs Jack Bond-Preston
2024-07-01 12:55 ` Ji, Kai
2024-07-02 15:39 ` [EXTERNAL] " Akhil Goyal
2024-07-03 10:49 ` Jack Bond-Preston
2024-07-03 13:46 ` Jack Bond-Preston
2024-06-07 12:47 ` [PATCH v4 2/5] crypto/openssl: only init 3DES-CTR key + impl once Jack Bond-Preston
2024-07-01 12:55 ` Ji, Kai
2024-06-07 12:47 ` [PATCH v4 3/5] crypto/openssl: per-qp cipher context clones Jack Bond-Preston
2024-07-01 12:56 ` Ji, Kai
2024-06-07 12:47 ` [PATCH v4 4/5] crypto/openssl: per-qp auth " Jack Bond-Preston
2024-07-01 12:55 ` Ji, Kai
2024-06-07 12:47 ` [PATCH v4 5/5] crypto/openssl: only set cipher padding once Jack Bond-Preston
2024-07-01 12:56 ` Ji, Kai
2024-06-24 16:14 ` [PATCH 0/5] OpenSSL PMD Optimisations Ji, Kai
2024-07-03 13:45 ` [PATCH v5 " Jack Bond-Preston
2024-07-03 13:45 ` [PATCH v5 1/5] crypto/openssl: fix GCM and CCM thread unsafe ctxs Jack Bond-Preston
2024-07-03 15:20 ` [EXTERNAL] " Akhil Goyal
2024-07-03 13:45 ` [PATCH v5 2/5] crypto/openssl: only init 3DES-CTR key + impl once Jack Bond-Preston
2024-07-03 13:45 ` [PATCH v5 3/5] crypto/openssl: per-qp cipher context clones Jack Bond-Preston
2024-07-03 13:45 ` [PATCH v5 4/5] crypto/openssl: per-qp auth " Jack Bond-Preston
2024-07-03 13:45 ` [PATCH v5 5/5] crypto/openssl: only set cipher padding once Jack Bond-Preston
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240603184348.1310331-5-jack.bond-preston@foss.arm.com \
--to=jack.bond-preston@foss.arm.com \
--cc=dev@dpdk.org \
--cc=kai.ji@intel.com \
--cc=wathsala.vithanage@arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).