From patchwork Thu Jul 1 06:57:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: danat@marvell.com X-Patchwork-Id: 95097 X-Patchwork-Delegate: gakhil@marvell.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 8A301A0A0C; Thu, 1 Jul 2021 08:57:30 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 5AC394067C; Thu, 1 Jul 2021 08:57:30 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id B5ECB40141 for ; Thu, 1 Jul 2021 08:57:28 +0200 (CEST) Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.16.0.43/8.16.0.43) with SMTP id 1616tXKL028691 for ; Wed, 30 Jun 2021 23:57:27 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : mime-version : content-type; s=pfpt0220; bh=2O3sNhoUd3YSch5YgdlIbcedgtZeABWvfFDahWzHaBY=; b=AW/CajlMo1mbR79ZChh7ggc7sZAujFdj8tgkM3Sgxd28KwFUePfeM+nKc5bMANdAAMcA kZfpsOwgce6U6LObBQtaAHyus9sfAQmvpsqqdKGfvqiQyaPJ0OBwscD7aV+gd6qWJcE2 MXs24JeOYCqnr0nUykoJDVaMpfu4ptA9PDNRoy1sS19kyEXSy7qWdcS3W0N8smFI4ekW 15Ln5ymdcCY6veRSy6dM2G9aCyV87a1lzXVdWgmzC+A5dxJJgoU8JgPKFXhmZprJee6g AgTY+84151Isq+kaItualFTp3XJWVztJ2VFKV0sXai81+My6qe9Y0j7vC+JgDANJyP7B LA== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0a-0016f401.pphosted.com with ESMTP id 39h2h4hg13-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Wed, 30 Jun 2021 23:57:27 -0700 Received: from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Wed, 30 Jun 2021 23:57:26 -0700 Received: from jupiter077.il.marvell.com (10.69.176.80) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server id 15.0.1497.18 via Frontend Transport; Wed, 30 Jun 2021 23:57:24 -0700 From: To: CC: , , , Date: Thu, 1 Jul 2021 09:57:05 +0300 Message-ID: <20210701065705.30961-1-danat@marvell.com> X-Mailer: git-send-email 2.17.1 MIME-Version: 1.0 X-Proofpoint-GUID: ocH6fitIMIKBtTS-xFnd_5W6xIfQ6bkA X-Proofpoint-ORIG-GUID: ocH6fitIMIKBtTS-xFnd_5W6xIfQ6bkA X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.391, 18.0.790 definitions=2021-07-01_01:2021-06-30, 2021-07-01 signatures=0 Subject: [dpdk-dev] [PATCH] crypto/mvsam: IPSec full offload support X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Michael Shamis This patch provides the support for IPSec protocol offload to the hardware. Following security operations are added: - session_create - session_destroy - capabilities_get Signed-off-by: Michael Shamis Reviewed-by: Liron Himi Tested-by: Liron Himi --- drivers/crypto/mvsam/meson.build | 2 +- drivers/crypto/mvsam/mrvl_pmd_private.h | 8 +- drivers/crypto/mvsam/rte_mrvl_pmd.c | 331 +++++++++++++++++++++--- drivers/crypto/mvsam/rte_mrvl_pmd_ops.c | 176 +++++++++++++ 4 files changed, 483 insertions(+), 34 deletions(-) diff --git a/drivers/crypto/mvsam/meson.build b/drivers/crypto/mvsam/meson.build index b4c55b5ff..db1787db6 100644 --- a/drivers/crypto/mvsam/meson.build +++ b/drivers/crypto/mvsam/meson.build @@ -14,4 +14,4 @@ ext_deps += dep sources = files('rte_mrvl_pmd.c', 'rte_mrvl_pmd_ops.c') -deps += ['bus_vdev', 'common_mvep'] +deps += ['bus_vdev', 'common_mvep', 'security'] diff --git a/drivers/crypto/mvsam/mrvl_pmd_private.h b/drivers/crypto/mvsam/mrvl_pmd_private.h index e575330ef..719d73d82 100644 --- a/drivers/crypto/mvsam/mrvl_pmd_private.h +++ b/drivers/crypto/mvsam/mrvl_pmd_private.h @@ -82,11 +82,17 @@ struct mrvl_crypto_src_table { } __rte_cache_aligned; /** Set and validate MRVL crypto session parameters */ -extern int +int mrvl_crypto_set_session_parameters(struct mrvl_crypto_session *sess, const struct rte_crypto_sym_xform *xform); +int +mrvl_ipsec_set_session_parameters(struct mrvl_crypto_session *sess, + struct rte_security_ipsec_xform *ipsec_xform, + struct rte_crypto_sym_xform *crypto_xform); + /** device specific operations function pointer structure */ extern struct rte_cryptodev_ops *rte_mrvl_crypto_pmd_ops; +extern struct rte_security_ops *rte_mrvl_security_pmd_ops; #endif /* _MRVL_PMD_PRIVATE_H_ */ diff --git a/drivers/crypto/mvsam/rte_mrvl_pmd.c b/drivers/crypto/mvsam/rte_mrvl_pmd.c index bec51c9ff..3d21319e5 100644 --- a/drivers/crypto/mvsam/rte_mrvl_pmd.c +++ b/drivers/crypto/mvsam/rte_mrvl_pmd.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -461,6 +462,96 @@ mrvl_crypto_set_session_parameters(struct mrvl_crypto_session *sess, return 0; } +static int +replay_wsz_to_mask(uint32_t replay_win_sz) +{ + int mask = 0; + + switch (replay_win_sz) { + case 0: + mask = SAM_ANTI_REPLY_MASK_NONE; + break; + case 32: + mask = SAM_ANTI_REPLY_MASK_32B; + break; + case 64: + mask = SAM_ANTI_REPLY_MASK_64B; + break; + case 128: + mask = SAM_ANTI_REPLY_MASK_128B; + break; + default: + MRVL_LOG(ERR, "Invalid antireplay window size"); + return -EINVAL; + } + + return mask; +} + +/** + * Parse IPSEC session parameters. + * + * @param sess Poiner to security session + * @param ipsec_xform Pointer to configuration structure IPSEC operations. + * @param crypto_xform Pointer to chain for crypto operations. + * @returns 0 in case of success, negative value otherwise. + */ +int +mrvl_ipsec_set_session_parameters(struct mrvl_crypto_session *sess, + struct rte_security_ipsec_xform *ipsec_xform, + struct rte_crypto_sym_xform *crypto_xform) +{ + int seq_mask_size; + + /* Filter out spurious/broken requests */ + if (ipsec_xform == NULL || crypto_xform == NULL) + return -EINVAL; + + /* Crypto parameters handling */ + if (mrvl_crypto_set_session_parameters(sess, crypto_xform)) + return -EINVAL; + + seq_mask_size = replay_wsz_to_mask(ipsec_xform->replay_win_sz); + if (seq_mask_size < 0) + return -EINVAL; + + /* IPSEC protocol parameters handling */ + sess->sam_sess_params.proto = SAM_PROTO_IPSEC; + sess->sam_sess_params.u.ipsec.is_esp = + (ipsec_xform->proto == RTE_SECURITY_IPSEC_SA_PROTO_ESP) ? + 1 : 0; + sess->sam_sess_params.u.ipsec.is_ip6 = 0; + sess->sam_sess_params.u.ipsec.is_tunnel = + (ipsec_xform->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) ? + 1 : 0; + sess->sam_sess_params.u.ipsec.is_esn = ipsec_xform->options.esn; + sess->sam_sess_params.u.ipsec.seq_mask_size = seq_mask_size; + + sess->sam_sess_params.u.ipsec.tunnel.u.ipv4.sip = + (uint8_t *)(&ipsec_xform->tunnel.ipv4.src_ip.s_addr); + sess->sam_sess_params.u.ipsec.tunnel.u.ipv4.dip = + (uint8_t *)&(ipsec_xform->tunnel.ipv4.dst_ip.s_addr); + + sess->sam_sess_params.u.ipsec.tunnel.u.ipv4.dscp = + ipsec_xform->tunnel.ipv4.dscp; + sess->sam_sess_params.u.ipsec.tunnel.u.ipv4.ttl = + ipsec_xform->tunnel.ipv4.ttl; + sess->sam_sess_params.u.ipsec.tunnel.u.ipv4.df = + ipsec_xform->tunnel.ipv4.df; + sess->sam_sess_params.u.ipsec.tunnel.copy_dscp = + ipsec_xform->options.copy_dscp; + sess->sam_sess_params.u.ipsec.tunnel.copy_flabel = + ipsec_xform->options.copy_flabel; + sess->sam_sess_params.u.ipsec.tunnel.copy_df = + ipsec_xform->options.copy_df; + + sess->sam_sess_params.u.ipsec.is_natt = 0; + sess->sam_sess_params.u.ipsec.spi = ipsec_xform->spi; + sess->sam_sess_params.u.ipsec.seq = 0; + + return 0; +} + /* *----------------------------------------------------------------------------- * Process Operations @@ -480,7 +571,7 @@ mrvl_crypto_set_session_parameters(struct mrvl_crypto_session *sess, * @param op Pointer to DPDK crypto operation struct [In]. */ static inline int -mrvl_request_prepare(struct sam_cio_op_params *request, +mrvl_request_prepare_crp(struct sam_cio_op_params *request, struct sam_buf_info *src_bd, struct sam_buf_info *dst_bd, struct rte_crypto_op *op) @@ -499,7 +590,8 @@ mrvl_request_prepare(struct sam_cio_op_params *request, } sess = (struct mrvl_crypto_session *)get_sym_session_private_data( - op->sym->session, cryptodev_driver_id); + op->sym->session, + cryptodev_driver_id); if (unlikely(sess == NULL)) { MRVL_LOG(ERR, "Session was not created for this device!"); return -EINVAL; @@ -569,7 +661,7 @@ mrvl_request_prepare(struct sam_cio_op_params *request, request->cipher_len = op->sym->aead.data.length; request->cipher_offset = op->sym->aead.data.offset; request->cipher_iv = rte_crypto_op_ctod_offset(op, uint8_t *, - sess->cipher_iv_offset); + sess->cipher_iv_offset); request->auth_aad = op->sym->aead.aad.data; request->auth_offset = request->cipher_offset; @@ -645,6 +737,108 @@ mrvl_request_prepare(struct sam_cio_op_params *request, return -1; } +/** + * Prepare a single security protocol request. + * + * This function basically translates DPDK security request into one + * understandable by MUDSK's SAM. If this is a first request in a session, + * it starts the session. + * + * @param request Pointer to pre-allocated && reset request buffer [Out]. + * @param src_bd Pointer to pre-allocated source descriptor [Out]. + * @param dst_bd Pointer to pre-allocated destination descriptor [Out]. + * @param op Pointer to DPDK crypto operation struct [In]. + */ +static inline int +mrvl_request_prepare_sec(struct sam_cio_ipsec_params *request, + struct sam_buf_info *src_bd, + struct sam_buf_info *dst_bd, + struct rte_crypto_op *op) +{ + struct mrvl_crypto_session *sess; + struct rte_mbuf *src_mbuf, *dst_mbuf; + uint16_t segments_nb; + int i; + + if (unlikely(op->sess_type != RTE_CRYPTO_OP_SECURITY_SESSION)) { + MRVL_LOG(ERR, "MRVL SECURITY: sess_type is not SECURITY_SESSION"); + return -EINVAL; + } + + sess = (struct mrvl_crypto_session *)get_sec_session_private_data( + op->sym->sec_session); + if (unlikely(sess == NULL)) { + MRVL_LOG(ERR, "Session was not created for this device! %d", + cryptodev_driver_id); + return -EINVAL; + } + + request->sa = sess->sam_sess; + request->cookie = op; + src_mbuf = op->sym->m_src; + segments_nb = src_mbuf->nb_segs; + /* The following conditions must be met: + * - Destination buffer is required when segmented source buffer + * - Segmented destination buffer is not supported + */ + if ((segments_nb > 1) && (!op->sym->m_dst)) { + MRVL_LOG(ERR, "op->sym->m_dst = NULL!"); + return -1; + } + /* For non SG case: + * If application delivered us null dst buffer, it means it expects + * us to deliver the result in src buffer. + */ + dst_mbuf = op->sym->m_dst ? op->sym->m_dst : op->sym->m_src; + + if (!rte_pktmbuf_is_contiguous(dst_mbuf)) { + MRVL_LOG(ERR, "Segmented destination buffer not supported!"); + return -1; + } + + request->num_bufs = segments_nb; + for (i = 0; i < segments_nb; i++) { + /* Empty source. */ + if (rte_pktmbuf_data_len(src_mbuf) == 0) { + /* EIP does not support 0 length buffers. */ + MRVL_LOG(ERR, "Buffer length == 0 not supported!"); + return -1; + } + src_bd[i].vaddr = rte_pktmbuf_mtod(src_mbuf, void *); + src_bd[i].paddr = rte_pktmbuf_iova(src_mbuf); + src_bd[i].len = rte_pktmbuf_data_len(src_mbuf); + + src_mbuf = src_mbuf->next; + } + request->src = src_bd; + + /* Empty destination. */ + if (rte_pktmbuf_data_len(dst_mbuf) == 0) { + /* Make dst buffer fit at least source data. */ + if (rte_pktmbuf_append(dst_mbuf, + rte_pktmbuf_data_len(op->sym->m_src)) == NULL) { + MRVL_LOG(ERR, "Unable to set big enough dst buffer!"); + return -1; + } + } + + request->dst = dst_bd; + dst_bd->vaddr = rte_pktmbuf_mtod(dst_mbuf, void *); + dst_bd->paddr = rte_pktmbuf_iova(dst_mbuf); + + /* + * We can use all available space in dst_mbuf, + * not only what's used currently. + */ + dst_bd->len = dst_mbuf->buf_len - rte_pktmbuf_headroom(dst_mbuf); + + + request->l3_offset = 0; + request->pkt_size = rte_pktmbuf_pkt_len(op->sym->m_src); + + return 0; +} + /* *----------------------------------------------------------------------------- * PMD Framework handlers @@ -664,10 +858,15 @@ mrvl_crypto_pmd_enqueue_burst(void *queue_pair, struct rte_crypto_op **ops, uint16_t nb_ops) { uint16_t iter_ops = 0; - uint16_t to_enq = 0; + uint16_t to_enq_crp = 0; + uint16_t to_enq_sec = 0; uint16_t consumed = 0; int ret; - struct sam_cio_op_params requests[nb_ops]; + struct sam_cio_op_params requests_crp[nb_ops]; + struct sam_cio_ipsec_params requests_sec[nb_ops]; + uint16_t indx_map_crp[nb_ops]; + uint16_t indx_map_sec[nb_ops]; + /* * SAM does not store bd pointers, so on-stack scope will be enough. */ @@ -679,53 +878,98 @@ mrvl_crypto_pmd_enqueue_burst(void *queue_pair, struct rte_crypto_op **ops, return 0; /* Prepare the burst. */ - memset(&requests, 0, sizeof(requests)); + memset(&requests_crp, 0, sizeof(requests_crp)); + memset(&requests_sec, 0, sizeof(requests_sec)); memset(&src_bd, 0, sizeof(src_bd)); /* Iterate through */ for (; iter_ops < nb_ops; ++iter_ops) { /* store the op id for debug */ - src_bd[iter_ops].iter_ops = iter_ops; - if (mrvl_request_prepare(&requests[iter_ops], - src_bd[iter_ops].src_bd, - &dst_bd[iter_ops], - ops[iter_ops]) < 0) { - MRVL_LOG(ERR, "Error while preparing parameters!"); - qp->stats.enqueue_err_count++; - ops[iter_ops]->status = RTE_CRYPTO_OP_STATUS_ERROR; - - /* - * Number of handled ops is increased - * (even if the result of handling is error). - */ - ++consumed; - break; + if (ops[iter_ops]->sess_type == RTE_CRYPTO_OP_WITH_SESSION) { + src_bd[iter_ops].iter_ops = to_enq_crp; + indx_map_crp[to_enq_crp] = iter_ops; + + if (mrvl_request_prepare_crp(&requests_crp[to_enq_crp], + src_bd[iter_ops].src_bd, + &dst_bd[iter_ops], + ops[iter_ops]) < 0) { + MRVL_LOG(ERR, + "Error while preparing parameters!"); + qp->stats.enqueue_err_count++; + ops[iter_ops]->status = + RTE_CRYPTO_OP_STATUS_ERROR; + /* + * Number of handled ops is increased + * (even if the result of handling is error). + */ + ++consumed; + + break; + } + /* Increase the number of ops to enqueue. */ + ++to_enq_crp; + } else { + src_bd[iter_ops].iter_ops = to_enq_sec; + indx_map_sec[to_enq_sec] = iter_ops; + if (mrvl_request_prepare_sec(&requests_sec[to_enq_sec], + src_bd[iter_ops].src_bd, + &dst_bd[iter_ops], + ops[iter_ops]) < 0) { + MRVL_LOG(ERR, + "Error while preparing parameters!"); + qp->stats.enqueue_err_count++; + ops[iter_ops]->status = + RTE_CRYPTO_OP_STATUS_ERROR; + /* + * Number of handled ops is increased + * (even if the result of handling is error). + */ + ++consumed; + + break; + } + /* Increase the number of ops to enqueue. */ + ++to_enq_sec; } ops[iter_ops]->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; - /* Increase the number of ops to enqueue. */ - ++to_enq; } /* for (; iter_ops < nb_ops;... */ - if (to_enq > 0) { + if (to_enq_crp > 0) { /* Send the burst */ - ret = sam_cio_enq(qp->cio, requests, &to_enq); - consumed += to_enq; + ret = sam_cio_enq(qp->cio, requests_crp, &to_enq_crp); + consumed += to_enq_crp; if (ret < 0) { /* * Trust SAM that in this case returned value will be at * some point correct (now it is returned unmodified). */ - qp->stats.enqueue_err_count += to_enq; - for (iter_ops = 0; iter_ops < to_enq; ++iter_ops) - ops[iter_ops]->status = + qp->stats.enqueue_err_count += to_enq_crp; + for (int iter = 0; iter < to_enq_crp; ++iter) + ops[indx_map_crp[iter]]->status = + RTE_CRYPTO_OP_STATUS_ERROR; + } + } + + if (to_enq_sec > 0) { + /* Send the burst */ + ret = sam_cio_enq_ipsec(qp->cio, requests_sec, &to_enq_sec); + consumed += to_enq_sec; + if (ret < 0) { + /* + * Trust SAM that in this case returned value will be at + * some point correct (now it is returned unmodified). + */ + qp->stats.enqueue_err_count += to_enq_sec; + for (int iter = 0; iter < to_enq_crp; ++iter) + ops[indx_map_sec[iter]]->status = RTE_CRYPTO_OP_STATUS_ERROR; } } - qp->stats.enqueued_count += to_enq; + qp->stats.enqueued_count += to_enq_sec + to_enq_crp; return consumed; } @@ -747,6 +991,7 @@ mrvl_crypto_pmd_dequeue_burst(void *queue_pair, struct sam_cio *cio = qp->cio; struct sam_cio_op_result results[nb_ops]; uint16_t i; + struct rte_mbuf *dst; ret = sam_cio_deq(cio, results, &nb_ops); if (ret < 0) { @@ -766,6 +1011,16 @@ mrvl_crypto_pmd_dequeue_burst(void *queue_pair, switch (results[i].status) { case SAM_CIO_OK: ops[i]->status = RTE_CRYPTO_OP_STATUS_SUCCESS; + if (ops[i]->sess_type == + RTE_CRYPTO_OP_SECURITY_SESSION) { + + if (ops[i]->sym->m_dst) + dst = ops[i]->sym->m_dst; + else + dst = ops[i]->sym->m_src; + dst->pkt_len = results[i].out_len; + dst->data_len = results[i].out_len; + } break; case SAM_CIO_ERR_ICV: MRVL_LOG(DEBUG, "CIO returned SAM_CIO_ERR_ICV."); @@ -799,6 +1054,7 @@ cryptodev_mrvl_crypto_create(const char *name, struct rte_cryptodev *dev; struct mrvl_crypto_private *internals; struct sam_init_params sam_params; + struct rte_security_ctx *security_instance; int ret = -EINVAL; dev = rte_cryptodev_pmd_create(name, &vdev->device, @@ -819,7 +1075,8 @@ cryptodev_mrvl_crypto_create(const char *name, RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING | RTE_CRYPTODEV_FF_HW_ACCELERATED | RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT | - RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT; + RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT | + RTE_CRYPTODEV_FF_SECURITY; internals = dev->data->dev_private; @@ -832,7 +1089,17 @@ cryptodev_mrvl_crypto_create(const char *name, sam_params.max_num_sessions = internals->max_nb_sessions; - /* sam_set_debug_flags(3); */ + /* Initialize security_ctx only for primary process*/ + security_instance = rte_malloc("rte_security_instances_ops", + sizeof(struct rte_security_ctx), 0); + if (security_instance == NULL) + return -ENOMEM; + security_instance->device = (void *)dev; + security_instance->ops = rte_mrvl_security_pmd_ops; + security_instance->sess_cnt = 0; + dev->security_ctx = security_instance; + + /*sam_set_debug_flags(3);*/ ret = sam_init(&sam_params); if (ret) diff --git a/drivers/crypto/mvsam/rte_mrvl_pmd_ops.c b/drivers/crypto/mvsam/rte_mrvl_pmd_ops.c index c61bdca36..e4dfda7fa 100644 --- a/drivers/crypto/mvsam/rte_mrvl_pmd_ops.c +++ b/drivers/crypto/mvsam/rte_mrvl_pmd_ops.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "mrvl_pmd_private.h" @@ -823,3 +824,178 @@ static struct rte_cryptodev_ops mrvl_crypto_pmd_ops = { }; struct rte_cryptodev_ops *rte_mrvl_crypto_pmd_ops = &mrvl_crypto_pmd_ops; + +/* IPSEC full offloading */ + +/** Configure the session from a crypto xform chain (PMD ops callback). + * + * @param dev Pointer to the device structure. + * @param conf Pointer to the security session configuration structure. + * @param sess Pointer to the empty session structure. + * @param mempool Pointer to memory pool. + * @returns 0 upon success, negative value otherwise. + */ +static int +mrvl_crypto_pmd_security_session_create(__rte_unused void *dev, + struct rte_security_session_conf *conf, + struct rte_security_session *sess, + struct rte_mempool *mempool) +{ + struct mrvl_crypto_session *mrvl_sess; + void *sess_private_data; + int ret; + + if (sess == NULL) { + MRVL_LOG(ERR, "Invalid session struct."); + return -EINVAL; + } + + if (rte_mempool_get(mempool, &sess_private_data)) { + MRVL_LOG(ERR, "Couldn't get object from session mempool."); + return -ENOMEM; + } + + switch (conf->protocol) { + case RTE_SECURITY_PROTOCOL_IPSEC: + mrvl_sess = (struct mrvl_crypto_session *)sess_private_data; + + struct rte_security_ipsec_xform *ipsec_xform = &conf->ipsec; + struct rte_crypto_sym_xform *crypto_xform = conf->crypto_xform; + + ret = mrvl_ipsec_set_session_parameters(mrvl_sess, + ipsec_xform, + crypto_xform); + if (ret != 0) { + MRVL_LOG(ERR, "Failed to configure session parameters."); + + /* Return session to mempool */ + rte_mempool_put(mempool, sess_private_data); + return ret; + } + + if (mrvl_sess->sam_sess_params.cipher_mode == SAM_CIPHER_GCM) { + /* Nonce is must for all counter modes */ + mrvl_sess->sam_sess_params.cipher_iv = + (uint8_t *)&(conf->ipsec.salt); + } + + ret = sam_session_create(&mrvl_sess->sam_sess_params, + &mrvl_sess->sam_sess); + if (ret < 0) { + MRVL_LOG(ERR, "PMD: failed to create IPSEC session."); + /* Return session to mempool */ + rte_mempool_put(mempool, sess_private_data); + return ret; + } + break; + case RTE_SECURITY_PROTOCOL_MACSEC: + return -ENOTSUP; + default: + return -EINVAL; + } + + set_sec_session_private_data(sess, sess_private_data); + + return ret; +} + +/** Clear the memory of session so it doesn't leave key material behind */ +static int +mrvl_crypto_pmd_security_session_destroy(void *dev __rte_unused, + struct rte_security_session *sess) +{ + void *sess_priv = get_sec_session_private_data(sess); + + /* Zero out the whole structure */ + if (sess_priv) { + struct mrvl_crypto_session *mrvl_sess = + (struct mrvl_crypto_session *)sess_priv; + struct rte_mempool *sess_mp = rte_mempool_from_obj(sess_priv); + + if (mrvl_sess->sam_sess && + sam_session_destroy(mrvl_sess->sam_sess) < 0) { + MRVL_LOG(ERR, "Error while destroying session!"); + } + + rte_free(mrvl_sess->sam_sess_params.cipher_key); + rte_free(mrvl_sess->sam_sess_params.auth_key); + rte_free(mrvl_sess->sam_sess_params.cipher_iv); + memset(sess, 0, sizeof(struct rte_security_session)); + set_sec_session_private_data(sess, NULL); + rte_mempool_put(sess_mp, sess_priv); + } + return 0; +} + +static const +struct rte_security_capability mrvl_crypto_pmd_sec_security_cap[] = { + { /* IPsec Lookaside Protocol offload ESP Tunnel Egress */ + .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL, + .protocol = RTE_SECURITY_PROTOCOL_IPSEC, + .ipsec = { + .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP, + .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL, + .direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS, + .options = { 0 }, + .replay_win_sz_max = 128 + }, + .crypto_capabilities = mrvl_crypto_pmd_capabilities + }, + { /* IPsec Lookaside Protocol offload ESP Tunnel Ingress */ + .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL, + .protocol = RTE_SECURITY_PROTOCOL_IPSEC, + .ipsec = { + .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP, + .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL, + .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS, + .options = { 0 }, + .replay_win_sz_max = 128 + }, + .crypto_capabilities = mrvl_crypto_pmd_capabilities + }, + { /* IPsec Lookaside Protocol offload ESP Transport Egress */ + .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL, + .protocol = RTE_SECURITY_PROTOCOL_IPSEC, + .ipsec = { + .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP, + .mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT, + .direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS, + .options = { 0 }, + .replay_win_sz_max = 128 + }, + .crypto_capabilities = mrvl_crypto_pmd_capabilities + }, + { /* IPsec Lookaside Protocol offload ESP Transport Ingress */ + .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL, + .protocol = RTE_SECURITY_PROTOCOL_IPSEC, + .ipsec = { + .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP, + .mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT, + .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS, + .options = { 0 }, + .replay_win_sz_max = 128 + }, + .crypto_capabilities = mrvl_crypto_pmd_capabilities + }, + { + .action = RTE_SECURITY_ACTION_TYPE_NONE + } +}; + +static const struct rte_security_capability * +mrvl_crypto_pmd_security_capabilities_get(void *device __rte_unused) +{ + return mrvl_crypto_pmd_sec_security_cap; +} + +struct rte_security_ops mrvl_sec_security_pmd_ops = { + .session_create = mrvl_crypto_pmd_security_session_create, + .session_update = NULL, + .session_stats_get = NULL, + .session_destroy = mrvl_crypto_pmd_security_session_destroy, + .set_pkt_metadata = NULL, + .capabilities_get = mrvl_crypto_pmd_security_capabilities_get +}; + +struct rte_security_ops *rte_mrvl_security_pmd_ops = &mrvl_sec_security_pmd_ops; +