From: Aviad Yehezkel <avia...@mellanox.com>

Signed-off-by: Aviad Yehezkel <avia...@mellanox.com>
Signed-off-by: Nelio Laranjeiro <nelio.laranje...@6wind.com>
---
 drivers/net/mlx5/Makefile     |   1 +
 drivers/net/mlx5/mlx5.c       |  12 ++
 drivers/net/mlx5/mlx5.h       |   2 +
 drivers/net/mlx5/mlx5_ipsec.c | 322 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 337 insertions(+)
 create mode 100644 drivers/net/mlx5/mlx5_ipsec.c

diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile
index b2dd86796..839d208b1 100644
--- a/drivers/net/mlx5/Makefile
+++ b/drivers/net/mlx5/Makefile
@@ -53,6 +53,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_rss.c
 SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_mr.c
 SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_flow.c
 SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_socket.c
+SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_ipsec.c
 
 # Basic CFLAGS.
 CFLAGS += -O3
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 00480cef0..e74026caf 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -57,6 +57,7 @@
 #include <rte_bus_pci.h>
 #include <rte_common.h>
 #include <rte_kvargs.h>
+#include <rte_security.h>
 
 #include "mlx5.h"
 #include "mlx5_utils.h"
@@ -114,6 +115,9 @@
         MLX5DV_CONTEXT_XFRM_FLAGS_ESP_AES_GCM_SPI_RSS_ONLY)
 #endif
 
+/* Dev ops structure defined in mlx5_ipsec.c */
+extern const struct rte_security_ops mlx5_security_ops;
+
 struct mlx5_args {
        int cqe_comp;
        int txq_inline;
@@ -942,6 +946,14 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct 
rte_pci_device *pci_dev)
                mlx5dv_set_context_attr(ctx, MLX5DV_CTX_ATTR_BUF_ALLOCATORS,
                                        (void *)((uintptr_t)&alctr));
 
+               if (priv->ipsec_en) {
+                       priv->security = (struct rte_security_ctx){
+                               .device = (void *)eth_dev,
+                               .ops = &mlx5_security_ops,
+                               .sess_cnt = 0,
+                       };
+                       eth_dev->security_ctx = &priv->security;
+               }
                /* Bring Ethernet device up. */
                DEBUG("forcing Ethernet interface up");
                priv_set_flags(priv, ~IFF_UP, IFF_UP);
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index c6a01d972..2927b851b 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -58,6 +58,7 @@
 #include <rte_interrupts.h>
 #include <rte_errno.h>
 #include <rte_flow.h>
+#include <rte_security.h>
 
 #include "mlx5_utils.h"
 #include "mlx5_rxtx.h"
@@ -150,6 +151,7 @@ struct priv {
        rte_spinlock_t lock; /* Lock for control functions. */
        int primary_socket; /* Unix socket for primary process. */
        struct rte_intr_handle intr_handle_socket; /* Interrupt handler. */
+       struct rte_security_ctx security; /* Security context. */
 };
 
 /**
diff --git a/drivers/net/mlx5/mlx5_ipsec.c b/drivers/net/mlx5/mlx5_ipsec.c
new file mode 100644
index 000000000..52a3add7a
--- /dev/null
+++ b/drivers/net/mlx5/mlx5_ipsec.c
@@ -0,0 +1,322 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright 2017 Mellanox.
+ *   Copyright 2017 6WIND S.A.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of 6WIND S.A. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Verbs header. */
+/* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */
+#ifdef PEDANTIC
+#pragma GCC diagnostic ignored "-Wpedantic"
+#endif
+#include <infiniband/verbs.h>
+#include <infiniband/mlx5dv.h>
+#ifdef PEDANTIC
+#pragma GCC diagnostic error "-Wpedantic"
+#endif
+
+#include <rte_malloc.h>
+#include <rte_security.h>
+#include <rte_cryptodev.h>
+#include <rte_security_driver.h>
+
+#include "mlx5.h"
+#include "mlx5_utils.h"
+#include "mlx5_autoconf.h"
+
+#ifdef HAVE_IBV_IPSEC_SUPPORT
+#define MLX5_IPSEC_SUPPORT_ERROR(cond) \
+       static_assert((cond), "Wrong verbs.h version for IPsec support," \
+                     " please contact Mellanox")
+
+/* Extra verifications, this API is not unstreamed yet. */
+MLX5_IPSEC_SUPPORT_ERROR(MLX5DV_CONTEXT_XFRM_FLAGS_ESP_AES_GCM_REQ_METADATA ==
+                        1u << 0);
+MLX5_IPSEC_SUPPORT_ERROR(MLX5DV_CONTEXT_XFRM_FLAGS_ESP_AES_GCM_RX == 1u << 1);
+MLX5_IPSEC_SUPPORT_ERROR(MLX5DV_CONTEXT_XFRM_FLAGS_ESP_AES_GCM_TX == 1u << 2);
+MLX5_IPSEC_SUPPORT_ERROR(MLX5DV_CONTEXT_XFRM_FLAGS_ESP_AES_GCM_SPI_RSS_ONLY ==
+                        1u << 3);
+#endif
+
+/* Security session. */
+struct mlx5_security_session {
+       struct rte_security_ipsec_xform ipsec_xform;
+       struct rte_eth_dev *dev;
+       struct ibv_action_xfrm  *ibv_action_xfrm;
+};
+
+/** MLX5 Crypto capabilities. */
+struct rte_cryptodev_capabilities mlx5_crypto_capabilities[] = {
+       /* AES GCM (128-bit) */
+       {
+               .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+               .sym = {
+                       .xform_type = RTE_CRYPTO_SYM_XFORM_AEAD,
+                       .aead = {
+                               .algo = RTE_CRYPTO_AEAD_AES_GCM,
+                               .block_size = 16,
+                               .key_size = {
+                                       .min = 16,
+                                       .max = 16,
+                                       .increment = 0,
+                               },
+                               .digest_size = {
+                                       .min = 16,
+                                       .max = 16,
+                                       .increment = 0,
+                               },
+                               .aad_size = {
+                                       .min = 8,
+                                       .max = 8,
+                                       .increment = 0,
+                               },
+                               .iv_size = {
+                                       .min = 12,
+                                       .max = 12,
+                                       .increment = 0,
+                               },
+                       },
+               },
+       },
+       /* AES GCM (256-bit) */
+       {
+               .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+               .sym = {
+                       .xform_type = RTE_CRYPTO_SYM_XFORM_AEAD,
+                       .aead = {
+                               .algo = RTE_CRYPTO_AEAD_AES_GCM,
+                               .block_size = 16,
+                               .key_size = {
+                                       .min = 32,
+                                       .max = 32,
+                                       .increment = 0,
+                               },
+                               .digest_size = {
+                                       .min = 16,
+                                       .max = 16,
+                                       .increment = 0,
+                               },
+                               .aad_size = {
+                                       .min = 8,
+                                       .max = 8,
+                                       .increment = 0,
+                               },
+                               .iv_size = {
+                                       .min = 12,
+                                       .max = 12,
+                                       .increment = 0,
+                               },
+                       },
+               },
+       },
+       /* None */
+       {
+               .op = RTE_CRYPTO_OP_TYPE_UNDEFINED,
+               .sym = {
+                       .xform_type = RTE_CRYPTO_SYM_XFORM_NOT_SPECIFIED
+               },
+       },
+};
+
+/** MLX5 Security capabilities. */
+static const struct rte_security_capability mlx5_security_capabilities[] = {
+#ifdef HAVE_IBV_IPSEC_SUPPORT
+       /* IPsec Inline Crypto ESP Transport Egress */
+       {
+               .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
+               .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},
+               },
+               .crypto_capabilities = mlx5_crypto_capabilities,
+               .ol_flags = RTE_SECURITY_TX_HW_TRAILER_OFFLOAD,
+       },
+       /* IPsec Inline Crypto ESP Transport Ingress */
+       {
+               .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
+               .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},
+               },
+               .crypto_capabilities = mlx5_crypto_capabilities,
+               .ol_flags = 0,
+       },
+       /* IPsec Inline Crypto ESP Tunnel Egress */
+       {
+               .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
+               .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},
+               },
+               .crypto_capabilities = mlx5_crypto_capabilities,
+               .ol_flags = RTE_SECURITY_TX_HW_TRAILER_OFFLOAD,
+       },
+       /* IPsec Inline Crypto ESP Tunnel Ingress */
+       {
+               .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
+               .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},
+               },
+               .crypto_capabilities = mlx5_crypto_capabilities,
+               .ol_flags = 0,
+       },
+#endif /* HAVE_IBV_IPSEC_SUPPORT */
+       {
+               .action = RTE_SECURITY_ACTION_TYPE_NONE
+       }
+};
+
+/**
+ * Security capabilities.
+ *
+ * @see rte_security_capability().
+ */
+static const struct rte_security_capability *
+mlx5_security_get_capabilities(void *dev __rte_unused)
+{
+       return mlx5_security_capabilities;
+}
+
+/**
+ * Create a security session.
+ *
+ * @see security_session_create_t().
+ */
+static int
+mlx5_security_create_session
+       (void *dev __rte_unused,
+        struct rte_security_session_conf *sess_conf __rte_unused,
+        struct rte_security_session *sess __rte_unused,
+        struct rte_mempool *mempool __rte_unused)
+{
+       int ret = -ENOTSUP;
+#ifdef HAVE_IBV_IPSEC_SUPPORT
+       struct mlx5_security_session *mlx5_sess = NULL;
+       struct priv *priv = ((struct rte_eth_dev *)dev)->data->dev_private;
+       struct ibv_action_xfrm_attr_esp_aes_gcm esp_aes_gcm;
+       struct mlx5dv_action_xfrm_attr_esp_aes_gcm mlx5_attr = {
+               .xfrm_flags = MLX5DV_ACTION_XFRM_FLAGS_REQUIRE_METADATA,
+               .comp_mask =
+                       MLX5DV_ACTION_XFRM_ATTR_ESP_AES_GCM_MASK_XFRM_FLAGS,
+       };
+
+       memset(&esp_aes_gcm, 0, sizeof(esp_aes_gcm));
+       if (sess_conf->action_type != RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
+               ERROR("Unknown rte security session type %d",
+                     sess_conf->action_type);
+               goto out;
+       }
+       if (sess_conf->protocol != RTE_SECURITY_PROTOCOL_IPSEC) {
+               ERROR("Unknown rte security session protocol %d",
+                     sess_conf->protocol);
+               goto out;
+       }
+       if (sess_conf->crypto_xform->type != RTE_CRYPTO_SYM_XFORM_AEAD) {
+               ERROR("Unsupported IPsec XFORM");
+               goto out;
+       }
+       if (sess_conf->crypto_xform->aead.algo != RTE_CRYPTO_AEAD_AES_GCM) {
+               ERROR("Unsupported IPsec AEAD algorithm");
+               goto out;
+       }
+       ret = rte_mempool_get(mempool, (void **)&mlx5_sess);
+       if (ret) {
+               ERROR("Failed to allocate security session");
+               ret = -ENOMEM;
+               goto out;
+       }
+       memcpy(&mlx5_sess->ipsec_xform, &sess_conf->ipsec,
+              sizeof(sess_conf->ipsec));
+       mlx5_sess->dev = dev;
+       set_sec_session_private_data(sess, mlx5_sess);
+       /* create action xfrm */
+       esp_aes_gcm.type = IBV_ACTION_XFRM_TYPE_ESP_AES_GCM;
+       esp_aes_gcm.key_length = sess_conf->crypto_xform->aead.key.length;
+       memcpy(esp_aes_gcm.key, sess_conf->crypto_xform->aead.key.data,
+              sess_conf->crypto_xform->aead.key.length);
+       memcpy(esp_aes_gcm.salt, &sess_conf->ipsec.salt,
+              sizeof(esp_aes_gcm.salt));
+       mlx5_sess->ibv_action_xfrm =
+               mlx5dv_create_action_xfrm_esp_aes_gcm(priv->ctx,
+                                                     &esp_aes_gcm,
+                                                     &mlx5_attr);
+       if (!mlx5_sess->ibv_action_xfrm) {
+               ERROR("Failed to create an action_xfrm rule");
+               ret = -EFAULT;
+               rte_free(mlx5_sess);
+       }
+out:
+#endif /* HAVE_IBV_IPSEC_SUPPORT */
+       return ret;
+}
+
+/**
+ * Destroy a security session.
+ *
+ * @see security_session_destroy_t().
+ */
+static int
+mlx5_security_destroy_session(void *dev __rte_unused,
+                             struct rte_security_session *sess __rte_unused)
+{
+#ifdef HAVE_IBV_IPSEC_SUPPORT
+       struct mlx5_security_session *mlx5_sess =
+               get_sec_session_private_data(sess);
+
+       if (dev != mlx5_sess->dev) {
+               ERROR("Attempt to clear session from wrong device");
+               return -EFAULT;
+       }
+       claim_zero(ibv_destroy_action_xfrm(mlx5_sess->ibv_action_xfrm));
+       rte_free(mlx5_sess);
+       return 0;
+#endif /* HAVE_IBV_IPSEC_SUPPORT */
+       return -ENOTSUP;
+}
+
+/* Security device operations. */
+const struct rte_security_ops mlx5_security_ops = {
+       .session_create = mlx5_security_create_session,
+       .session_destroy = mlx5_security_destroy_session,
+       .capabilities_get = mlx5_security_get_capabilities,
+};
-- 
2.11.0

Reply via email to