[dpdk-dev,v1,4/7] net/mlx5: add security capability function

Message ID 00d00234598a20dd78f102701eaadd63aba6603b.1511453340.git.nelio.laranjeiro@6wind.com (mailing list archive)
State Superseded, archived
Headers

Checks

Context Check Description
ci/Intel-compilation fail apply patch file failure
ci/checkpatch success coding style OK

Commit Message

Nélio Laranjeiro Nov. 23, 2017, 4:13 p.m. UTC
  From: Aviad Yehezkel <aviadye@mellanox.com>

Signed-off-by: Aviad Yehezkel <aviadye@mellanox.com>
Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@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
  

Patch

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,
+};