All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 0/7] net/mlx5: IPsec offload support
@ 2017-11-23 16:13 Nelio Laranjeiro
  2017-11-23 16:13 ` [PATCH v1 1/7] net: define Mellanox ether type for embed metadata Nelio Laranjeiro
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Nelio Laranjeiro @ 2017-11-23 16:13 UTC (permalink / raw)
  To: dev; +Cc: Yongseok Koh, Adrien Mazarguil

Add support for IPsec using rte_security on ConnectX-4 Lx INNOVA NIC.

This support is still in progress on all side (RDMA-Core and Linux Kernel) it
is only enable at compilation time when the expected symbols are present in
Verbs, even in such situation static assert are present to assure the offload
request can be understood by the NIC (those values may change once patches in
RDMA-Core are up-streamed).

Minor changes expected in v2:

 - Rebased on top of new offload API.
 - Eventual modifications to match upstream RDMA-Core and Linux Kernel
 - RSS on SPI.
 - ESN support.
 - Documentation update to explain how to use the INNOVA NIC.

Applies on top of:

 http://dpdk.org/dev/patchwork/patch/31592/

Aviad Yehezkel (2):
  net/mlx5: add IPsec Tx/Rx offload support
  net/mlx5: add security capability function

Nelio Laranjeiro (4):
  net: define Mellanox ether type for embed metadata
  net/mlx5: handle the IPsec support from Verbs
  net/mlx5: simplify error handling in flow action parsing
  net/mlx5: add device parameter to enabled IPsec

Shahaf Shuler (1):
  net/mlx5: support security flow action

 doc/guides/nics/mlx5.rst       |   9 +
 drivers/net/mlx5/Makefile      |   6 +
 drivers/net/mlx5/mlx5.c        |  52 ++++++
 drivers/net/mlx5/mlx5.h        |  10 ++
 drivers/net/mlx5/mlx5_ethdev.c |   4 +
 drivers/net/mlx5/mlx5_flow.c   | 395 +++++++++++++++++++++++++++++++++--------
 drivers/net/mlx5/mlx5_ipsec.c  | 318 +++++++++++++++++++++++++++++++++
 drivers/net/mlx5/mlx5_prm.h    |  39 ++++
 drivers/net/mlx5/mlx5_rxtx.c   | 104 ++++++++++-
 drivers/net/mlx5/mlx5_rxtx.h   |   4 +-
 drivers/net/mlx5/mlx5_txq.c    |   1 +
 lib/librte_net/rte_ether.h     |   2 +
 12 files changed, 861 insertions(+), 83 deletions(-)
 create mode 100644 drivers/net/mlx5/mlx5_ipsec.c

-- 
2.11.0

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v1 1/7] net: define Mellanox ether type for embed metadata
  2017-11-23 16:13 [PATCH v1 0/7] net/mlx5: IPsec offload support Nelio Laranjeiro
@ 2017-11-23 16:13 ` Nelio Laranjeiro
  2017-11-23 16:13 ` [PATCH v1 2/7] net/mlx5: handle the IPsec support from Verbs Nelio Laranjeiro
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Nelio Laranjeiro @ 2017-11-23 16:13 UTC (permalink / raw)
  To: dev; +Cc: Yongseok Koh, Adrien Mazarguil

Mellanox detains an Ethernet to embed additional metadata in Ethernet
frames [1].  This Ether type is necessary for some NIC to transform packets
using an offloading.

[1] http://standards-oui.ieee.org/ethertype/eth.txt
Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
---
 lib/librte_net/rte_ether.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/librte_net/rte_ether.h b/lib/librte_net/rte_ether.h
index 06d7b486c..f118b6e01 100644
--- a/lib/librte_net/rte_ether.h
+++ b/lib/librte_net/rte_ether.h
@@ -334,6 +334,8 @@ struct vxlan_hdr {
 #define ETHER_TYPE_SLOW 0x8809 /**< Slow protocols (LACP and Marker). */
 #define ETHER_TYPE_TEB  0x6558 /**< Transparent Ethernet Bridging. */
 #define ETHER_TYPE_LLDP 0x88CC /**< LLDP Protocol. */
+#define ETHER_TYPE_MLNX 0X8CE4
+/**< Mellanox additional metadata in Ethernet frames. */
 
 #define ETHER_VXLAN_HLEN (sizeof(struct udp_hdr) + sizeof(struct vxlan_hdr))
 /**< VXLAN tunnel header length. */
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v1 2/7] net/mlx5: handle the IPsec support from Verbs
  2017-11-23 16:13 [PATCH v1 0/7] net/mlx5: IPsec offload support Nelio Laranjeiro
  2017-11-23 16:13 ` [PATCH v1 1/7] net: define Mellanox ether type for embed metadata Nelio Laranjeiro
@ 2017-11-23 16:13 ` Nelio Laranjeiro
  2017-11-23 16:13 ` [PATCH v1 3/7] net/mlx5: add IPsec Tx/Rx offload support Nelio Laranjeiro
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Nelio Laranjeiro @ 2017-11-23 16:13 UTC (permalink / raw)
  To: dev; +Cc: Yongseok Koh, Adrien Mazarguil

Enable HAVE_VERBS_IPSEC_SUPPORT is associated code is available in
RDMA-Core.

Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
---
 drivers/net/mlx5/Makefile | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile
index a3984eb9f..b2dd86796 100644
--- a/drivers/net/mlx5/Makefile
+++ b/drivers/net/mlx5/Makefile
@@ -147,6 +147,11 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh
 		infiniband/verbs.h \
 		enum IBV_FLOW_SPEC_ACTION_COUNT \
 		$(AUTOCONF_OUTPUT)
+	$Q sh -- '$<' '$@' \
+		HAVE_IBV_IPSEC_SUPPORT \
+		infiniband/verbs.h \
+		enum IBV_FLOW_SPEC_ESP \
+		$(AUTOCONF_OUTPUT)
 
 # Create mlx5_autoconf.h or update it in case it differs from the new one.
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v1 3/7] net/mlx5: add IPsec Tx/Rx offload support
  2017-11-23 16:13 [PATCH v1 0/7] net/mlx5: IPsec offload support Nelio Laranjeiro
  2017-11-23 16:13 ` [PATCH v1 1/7] net: define Mellanox ether type for embed metadata Nelio Laranjeiro
  2017-11-23 16:13 ` [PATCH v1 2/7] net/mlx5: handle the IPsec support from Verbs Nelio Laranjeiro
@ 2017-11-23 16:13 ` Nelio Laranjeiro
  2017-11-23 16:13 ` [PATCH v1 4/7] net/mlx5: add security capability function Nelio Laranjeiro
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Nelio Laranjeiro @ 2017-11-23 16:13 UTC (permalink / raw)
  To: dev; +Cc: Aviad Yehezkel, Yongseok Koh, Adrien Mazarguil

From: Aviad Yehezkel <aviadye@mellanox.com>

This feature is only supported by ConnectX-4 Lx INNOVA NIC.  Having such
support will automatically disable and enable crypto offload device
arguments to make the PMD IPsec capable.

Signed-off-by: Aviad Yehezkel <aviadye@mellanox.com>
Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
---
 drivers/net/mlx5/mlx5.c        |   8 ++++
 drivers/net/mlx5/mlx5.h        |   1 +
 drivers/net/mlx5/mlx5_ethdev.c |   4 ++
 drivers/net/mlx5/mlx5_prm.h    |  39 ++++++++++++++++
 drivers/net/mlx5/mlx5_rxtx.c   | 104 ++++++++++++++++++++++++++++++++++++++---
 drivers/net/mlx5/mlx5_rxtx.h   |   4 +-
 drivers/net/mlx5/mlx5_txq.c    |   1 +
 7 files changed, 154 insertions(+), 7 deletions(-)

diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index cd66fe162..00480cef0 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -106,6 +106,14 @@
 #define MLX5DV_CONTEXT_FLAGS_CQE_128B_COMP (1 << 4)
 #endif
 
+#ifdef HAVE_IBV_IPSEC_SUPPORT
+#define MLX5_IPSEC_FLAGS \
+	(MLX5DV_CONTEXT_XFRM_FLAGS_ESP_AES_GCM_TX | \
+	 MLX5DV_CONTEXT_XFRM_FLAGS_ESP_AES_GCM_RX | \
+	 MLX5DV_CONTEXT_XFRM_FLAGS_ESP_AES_GCM_REQ_METADATA | \
+	 MLX5DV_CONTEXT_XFRM_FLAGS_ESP_AES_GCM_SPI_RSS_ONLY)
+#endif
+
 struct mlx5_args {
 	int cqe_comp;
 	int txq_inline;
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index e6a69b823..c6a01d972 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -117,6 +117,7 @@ struct priv {
 	unsigned int isolated:1; /* Whether isolated mode is enabled. */
 	unsigned int tx_vec_en:1; /* Whether Tx vector is enabled. */
 	unsigned int rx_vec_en:1; /* Whether Rx vector is enabled. */
+	unsigned int ipsec_en:1; /* Whether IPsec is enabled. */
 	unsigned int counter_set_supported:1; /* Counter set is supported. */
 	/* Whether Tx offloads for tunneled packets are supported. */
 	unsigned int max_tso_payload_sz; /* Maximum TCP payload for TSO. */
diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c
index ca9ad0fef..f0c7fba43 100644
--- a/drivers/net/mlx5/mlx5_ethdev.c
+++ b/drivers/net/mlx5/mlx5_ethdev.c
@@ -680,6 +680,10 @@ mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
 			 DEV_TX_OFFLOAD_TCP_CKSUM);
 	if (priv->tso)
 		info->tx_offload_capa |= DEV_TX_OFFLOAD_TCP_TSO;
+	if (priv->ipsec_en) {
+		info->tx_offload_capa |= DEV_TX_OFFLOAD_SECURITY;
+		info->rx_offload_capa |= DEV_RX_OFFLOAD_SECURITY;
+	}
 	if (priv->tunnel_en)
 		info->tx_offload_capa |= (DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM |
 					  DEV_TX_OFFLOAD_VXLAN_TNL_TSO |
diff --git a/drivers/net/mlx5/mlx5_prm.h b/drivers/net/mlx5/mlx5_prm.h
index 2de310bcb..bd6270671 100644
--- a/drivers/net/mlx5/mlx5_prm.h
+++ b/drivers/net/mlx5/mlx5_prm.h
@@ -342,4 +342,43 @@ mlx5_flow_mark_get(uint32_t val)
 #endif
 }
 
+/* IPsec offloads elements. */
+
+/* IPsec Rx code. */
+#define MLX5_IPSEC_RX_DECRYPTED 0x11
+#define MLX5_IPSEC_RX_AUTH_FAIL 0x12
+
+/* IPsec Tx code. */
+#define MLX5_IPSEC_TX_OFFLOAD 0x8
+
+/* Metadata length . */
+#define MLX5_METADATA_LEN 8
+
+/* Packet IPsec Rx metadata. */
+struct mlx5_rx_pkt_ipsec_metadata {
+	uint8_t reserved;
+	rte_be32_t sa_handle;
+} __rte_packed;
+
+/* Tx packet Metadata. */
+struct mlx5_tx_pkt_ipsec_metadata {
+	rte_be16_t mss_inv; /** MSS fixed point, used only in LSO. */
+	rte_be16_t seq; /** LSBs of the first TCP seq, only in LSO. */
+	uint8_t esp_next_proto; /* Next protocol of ESP. */
+} __rte_packed;
+
+/* Packet Metadata. */
+struct mlx5_pkt_metadata {
+	uint8_t syndrome;
+	union {
+		uint8_t raw[5];
+		struct mlx5_rx_pkt_ipsec_metadata rx;
+		struct mlx5_tx_pkt_ipsec_metadata tx;
+	} __rte_packed;
+	rte_be16_t ethertype;
+} __rte_packed;
+
+static_assert(sizeof(struct mlx5_pkt_metadata) == MLX5_METADATA_LEN,
+	      "wrong metadata size detected.");
+
 #endif /* RTE_PMD_MLX5_PRM_H_ */
diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c
index 28c0ad8ab..91ceb3c55 100644
--- a/drivers/net/mlx5/mlx5_rxtx.c
+++ b/drivers/net/mlx5/mlx5_rxtx.c
@@ -344,6 +344,7 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 	unsigned int j = 0;
 	unsigned int k = 0;
 	uint16_t max_elts;
+	const unsigned int ipsec_en = txq->ipsec_en;
 	uint16_t max_wqe;
 	unsigned int comp;
 	volatile struct mlx5_wqe_ctrl *last_wqe = NULL;
@@ -417,14 +418,43 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 			    rte_pktmbuf_mtod(*(pkts + 1), volatile void *));
 		cs_flags = txq_ol_cksum_to_cs(txq, buf);
 		raw = ((uint8_t *)(uintptr_t)wqe) + 2 * MLX5_WQE_DWORD_SIZE;
-		/* Replace the Ethernet type by the VLAN if necessary. */
+		addr += 2;
+		length -= 2;
+		/* Handle IPsec offload. */
+		if (ipsec_en && (buf->ol_flags & PKT_TX_SEC_OFFLOAD)) {
+			struct mlx5_pkt_metadata mdata = {
+				.syndrome = MLX5_IPSEC_TX_OFFLOAD,
+				.tx.esp_next_proto = buf->inner_esp_next_proto,
+			};
+			unsigned int len = 2 * ETHER_ADDR_LEN - 2;
+			rte_be16_t ethertype =
+				rte_cpu_to_be_16(ETHER_TYPE_MLNX);
+
+			if (buf->ol_flags & PKT_TX_TCP_CKSUM) {
+				txq->stats.oerrors++;
+				break;
+			}
+			/* Copy Destination and source mac address. */
+			memcpy((uint8_t *)raw, ((uint8_t *)addr), len);
+			raw += len;
+			addr += len;
+			length -= len;
+			/* Copy Metadata. */
+			memcpy((uint8_t *)raw, &ethertype, 2);
+			memcpy((uint8_t *)raw + 2, &mdata,
+			       MLX5_METADATA_LEN - 2);
+			memcpy((uint8_t *)raw + MLX5_METADATA_LEN,
+			       (uint8_t *)addr, 2);
+			addr += 2;
+			len -= 2;
+			raw += MLX5_METADATA_LEN + 2;
+			pkt_inline_sz += MLX5_METADATA_LEN;
+		}
 		if (buf->ol_flags & PKT_TX_VLAN_PKT) {
 			uint32_t vlan = rte_cpu_to_be_32(0x81000000 |
 							 buf->vlan_tci);
 			unsigned int len = 2 * ETHER_ADDR_LEN - 2;
 
-			addr += 2;
-			length -= 2;
 			/* Copy Destination and source mac address. */
 			memcpy((uint8_t *)raw, ((uint8_t *)addr), len);
 			/* Copy VLAN. */
@@ -435,10 +465,10 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 			addr += len + 2;
 			length -= (len + 2);
 		} else {
-			memcpy((uint8_t *)raw, ((uint8_t *)addr) + 2,
+			memcpy((uint8_t *)raw, ((uint8_t *)addr),
 			       MLX5_WQE_DWORD_SIZE);
-			length -= pkt_inline_sz;
-			addr += pkt_inline_sz;
+			length -= MLX5_WQE_DWORD_SIZE;
+			addr += MLX5_WQE_DWORD_SIZE;
 		}
 		raw += MLX5_WQE_DWORD_SIZE;
 		if (txq->tso_en) {
@@ -1572,6 +1602,59 @@ mlx5_tx_burst_empw(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)
 }
 
 /**
+ * Process an IPsec encrypted packet.
+ *
+ * @param pkt
+ *   Pointer to the first segment of the packet.
+ * @param len
+ *   Already gathered packet length.
+ *
+ * @return
+ *   new packet length on success, 0 on failure.
+ */
+static __rte_noinline int
+mlx5_rx_handle_ipsec(struct rte_mbuf *pkt, int len)
+{
+	struct mlx5_pkt_metadata *mdata;
+	struct ether_hdr *eth;
+
+	if (len < ETHER_HDR_LEN + MLX5_METADATA_LEN)
+		return 0;
+	eth = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
+	if (eth->ether_type != rte_cpu_to_be_16(ETHER_TYPE_MLNX))
+		goto out;
+	/* Use the metadata */
+	mdata = rte_pktmbuf_mtod_offset(pkt, struct mlx5_pkt_metadata *,
+					ETHER_HDR_LEN);
+	if (mdata->syndrome == MLX5_IPSEC_RX_DECRYPTED)
+		pkt->ol_flags |= PKT_RX_SEC_OFFLOAD;
+	else if (mdata->syndrome == MLX5_IPSEC_RX_AUTH_FAIL)
+		pkt->ol_flags |= PKT_RX_SEC_OFFLOAD_FAILED;
+	else
+		return 0;
+	/*
+	 * Move the data from the buffer:
+	 *
+	 *   6B    6B     2B     6B    2B
+	 * +-----+-----+-------+----+-------+
+	 * | DST | SRC | MType | MD | Etype |
+	 * +-----+-----+-------+----+-------+
+	 *
+	 * to:
+	 *     6B       6B    6B    2B
+	 * +---------+-----+-----+-------+
+	 * | Garbage | DST | SRC | EType |
+	 * +---------+-----+-----+-------+
+	 */
+	memmove((void *)((uintptr_t)mdata - 6), eth, 2 * ETHER_ADDR_LEN);
+	/* Ethertype is already in its new place */
+	rte_pktmbuf_adj(pkt, MLX5_METADATA_LEN);
+	len -= MLX5_METADATA_LEN;
+out:
+	return len;
+}
+
+/**
  * Translate RX completion flags to packet type.
  *
  * @param[in] cqe
@@ -1772,6 +1855,7 @@ mlx5_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
 	const unsigned int wqe_cnt = (1 << rxq->elts_n) - 1;
 	const unsigned int cqe_cnt = (1 << rxq->cqe_n) - 1;
 	const unsigned int sges_n = rxq->sges_n;
+	const unsigned int ipsec_en = rxq->ipsec_en;
 	struct rte_mbuf *pkt = NULL;
 	struct rte_mbuf *seg = NULL;
 	volatile struct mlx5_cqe *cqe =
@@ -1864,6 +1948,14 @@ mlx5_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
 			}
 			if (rxq->crc_present)
 				len -= ETHER_CRC_LEN;
+			if (ipsec_en) {
+				len = mlx5_rx_handle_ipsec(pkt, len);
+				if (unlikely(len == 0)) {
+					rte_mbuf_raw_free(rep);
+					++rxq->stats.idropped;
+					goto skip;
+				}
+			}
 			PKT_LEN(pkt) = len;
 		}
 		DATA_LEN(rep) = DATA_LEN(seg);
diff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h
index b8c7925a3..e219d01ee 100644
--- a/drivers/net/mlx5/mlx5_rxtx.h
+++ b/drivers/net/mlx5/mlx5_rxtx.h
@@ -115,7 +115,8 @@ struct mlx5_rxq_data {
 	unsigned int rss_hash:1; /* RSS hash result is enabled. */
 	unsigned int mark:1; /* Marked flow available on the queue. */
 	unsigned int pending_err:1; /* CQE error needs to be handled. */
-	unsigned int :14; /* Remaining bits. */
+	unsigned int ipsec_en:1; /* IPsec is enabled on this queue. */
+	unsigned int :13; /* Remaining bits. */
 	volatile uint32_t *rq_db;
 	volatile uint32_t *cq_db;
 	uint16_t port_id;
@@ -195,6 +196,7 @@ struct mlx5_txq_data {
 	uint16_t tunnel_en:1;
 	/* When set TX offload for tunneled packets are supported. */
 	uint16_t mpw_hdr_dseg:1; /* Enable DSEGs in the title WQEBB. */
+	uint16_t ipsec_en:1; /* Whether IPsec Tx offload is enabled. */
 	uint16_t max_inline; /* Multiple of RTE_CACHE_LINE_SIZE to inline. */
 	uint16_t inline_max_packet_sz; /* Max packet size for inlining. */
 	uint16_t mr_cache_idx; /* Index of last hit entry. */
diff --git a/drivers/net/mlx5/mlx5_txq.c b/drivers/net/mlx5/mlx5_txq.c
index a786a6b63..4d53c6da5 100644
--- a/drivers/net/mlx5/mlx5_txq.c
+++ b/drivers/net/mlx5/mlx5_txq.c
@@ -646,6 +646,7 @@ mlx5_priv_txq_new(struct priv *priv, uint16_t idx, uint16_t desc,
 	}
 	if (priv->tunnel_en)
 		tmpl->txq.tunnel_en = 1;
+	tmpl->txq.ipsec_en = priv->ipsec_en;
 	tmpl->txq.elts =
 		(struct rte_mbuf *(*)[1 << tmpl->txq.elts_n])(tmpl + 1);
 	tmpl->txq.stats.idx = idx;
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v1 4/7] net/mlx5: add security capability function
  2017-11-23 16:13 [PATCH v1 0/7] net/mlx5: IPsec offload support Nelio Laranjeiro
                   ` (2 preceding siblings ...)
  2017-11-23 16:13 ` [PATCH v1 3/7] net/mlx5: add IPsec Tx/Rx offload support Nelio Laranjeiro
@ 2017-11-23 16:13 ` Nelio Laranjeiro
  2017-11-23 16:13 ` [PATCH v1 5/7] net/mlx5: simplify error handling in flow action parsing Nelio Laranjeiro
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Nelio Laranjeiro @ 2017-11-23 16:13 UTC (permalink / raw)
  To: dev; +Cc: Aviad Yehezkel, Yongseok Koh, Adrien Mazarguil

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

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

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v1 5/7] net/mlx5: simplify error handling in flow action parsing
  2017-11-23 16:13 [PATCH v1 0/7] net/mlx5: IPsec offload support Nelio Laranjeiro
                   ` (3 preceding siblings ...)
  2017-11-23 16:13 ` [PATCH v1 4/7] net/mlx5: add security capability function Nelio Laranjeiro
@ 2017-11-23 16:13 ` Nelio Laranjeiro
  2017-11-23 16:13 ` [PATCH v1 6/7] net/mlx5: support security flow action Nelio Laranjeiro
  2017-11-23 16:13 ` [PATCH v1 7/7] net/mlx5: add device parameter to enabled IPsec Nelio Laranjeiro
  6 siblings, 0 replies; 8+ messages in thread
From: Nelio Laranjeiro @ 2017-11-23 16:13 UTC (permalink / raw)
  To: dev; +Cc: Yongseok Koh, Adrien Mazarguil

Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
---
 drivers/net/mlx5/mlx5_flow.c | 88 +++++++++++++++++++++-----------------------
 1 file changed, 41 insertions(+), 47 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 1eda83671..ff50470b5 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -654,6 +654,9 @@ priv_flow_convert_actions(struct priv *priv,
 			  struct rte_flow_error *error,
 			  struct mlx5_flow_parse *parser)
 {
+	int ret = 0;
+	const char *msg = NULL;
+	const struct rte_flow_action *action = NULL;
 	/*
 	 * Add default RSS configuration necessary for Verbs to create QP even
 	 * if no RSS is necessary.
@@ -674,7 +677,7 @@ priv_flow_convert_actions(struct priv *priv,
 			uint16_t found = 0;
 
 			if (!queue || (queue->index > (priv->rxqs_n - 1)))
-				goto exit_action_not_supported;
+				goto error;
 			for (n = 0; n < parser->queues_n; ++n) {
 				if (parser->queues[n] == queue->index) {
 					found = 1;
@@ -682,11 +685,10 @@ priv_flow_convert_actions(struct priv *priv,
 				}
 			}
 			if (parser->queues_n > 1 && !found) {
-				rte_flow_error_set(error, ENOTSUP,
-					   RTE_FLOW_ERROR_TYPE_ACTION,
-					   actions,
-					   "queue action not in RSS queues");
-				return -rte_errno;
+				ret = ENOTSUP;
+				action = actions;
+				msg = "queue action not in RSS queues";
+				goto error;
 			}
 			if (!found) {
 				parser->queues_n = 1;
@@ -699,11 +701,10 @@ priv_flow_convert_actions(struct priv *priv,
 			uint16_t n;
 
 			if (!rss || !rss->num) {
-				rte_flow_error_set(error, EINVAL,
-						   RTE_FLOW_ERROR_TYPE_ACTION,
-						   actions,
-						   "no valid queues");
-				return -rte_errno;
+				ret = EINVAL;
+				action = actions;
+				msg = "no valid queues";
+				goto error;
 			}
 			if (parser->queues_n == 1) {
 				uint16_t found = 0;
@@ -717,22 +718,18 @@ priv_flow_convert_actions(struct priv *priv,
 					}
 				}
 				if (!found) {
-					rte_flow_error_set(error, ENOTSUP,
-						   RTE_FLOW_ERROR_TYPE_ACTION,
-						   actions,
-						   "queue action not in RSS"
-						   " queues");
-					return -rte_errno;
+					ret = ENOTSUP;
+					action = actions;
+					msg = "queue action not in RSS queues";
+					goto error;
 				}
 			}
 			for (n = 0; n < rss->num; ++n) {
 				if (rss->queue[n] >= priv->rxqs_n) {
-					rte_flow_error_set(error, EINVAL,
-						   RTE_FLOW_ERROR_TYPE_ACTION,
-						   actions,
-						   "queue id > number of"
-						   " queues");
-					return -rte_errno;
+					ret = EINVAL;
+					action = actions;
+					msg = "queue id > number of queues";
+					goto error;
 				}
 			}
 			for (n = 0; n < rss->num; ++n)
@@ -740,11 +737,10 @@ priv_flow_convert_actions(struct priv *priv,
 			parser->queues_n = rss->num;
 			if (priv_flow_convert_rss_conf(priv, parser,
 						       rss->rss_conf)) {
-				rte_flow_error_set(error, EINVAL,
-						   RTE_FLOW_ERROR_TYPE_ACTION,
-						   actions,
-						   "wrong RSS configuration");
-				return -rte_errno;
+				ret = EINVAL;
+				action = actions;
+				msg = "wrong RSS configuration";
+				goto error;
 			}
 		} else if (actions->type == RTE_FLOW_ACTION_TYPE_MARK) {
 			const struct rte_flow_action_mark *mark =
@@ -752,18 +748,15 @@ priv_flow_convert_actions(struct priv *priv,
 				actions->conf;
 
 			if (!mark) {
-				rte_flow_error_set(error, EINVAL,
-						   RTE_FLOW_ERROR_TYPE_ACTION,
-						   actions,
-						   "mark must be defined");
-				return -rte_errno;
+				ret = EINVAL;
+				action = actions;
+				msg = "mark must be defined";
+				goto error;
 			} else if (mark->id >= MLX5_FLOW_MARK_MAX) {
-				rte_flow_error_set(error, ENOTSUP,
-						   RTE_FLOW_ERROR_TYPE_ACTION,
-						   actions,
-						   "mark must be between 0"
-						   " and 16777199");
-				return -rte_errno;
+				ret = ENOTSUP;
+				action = actions;
+				msg = "mark must be between 0 and 16777199";
+				goto error;
 			}
 			parser->mark = 1;
 			parser->mark_id = mark->id;
@@ -773,21 +766,22 @@ priv_flow_convert_actions(struct priv *priv,
 			   priv->counter_set_supported) {
 			parser->count = 1;
 		} else {
-			goto exit_action_not_supported;
+			goto error;
 		}
 	}
 	if (parser->drop && parser->mark)
 		parser->mark = 0;
 	if (!parser->queues_n && !parser->drop) {
-		rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE,
-				   NULL, "no valid action");
-		return -rte_errno;
+		ret = ENOTSUP;
+		msg = "no valid action";
+		goto error;
 	}
 	return 0;
-exit_action_not_supported:
-	rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
-			   actions, "action not supported");
-	return -rte_errno;
+error:
+	return rte_flow_error_set(error, ret,
+				  action ? RTE_FLOW_ERROR_TYPE_ACTION :
+				  RTE_FLOW_ERROR_TYPE_HANDLE,
+				  action, msg);
 }
 
 /**
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v1 6/7] net/mlx5: support security flow action
  2017-11-23 16:13 [PATCH v1 0/7] net/mlx5: IPsec offload support Nelio Laranjeiro
                   ` (4 preceding siblings ...)
  2017-11-23 16:13 ` [PATCH v1 5/7] net/mlx5: simplify error handling in flow action parsing Nelio Laranjeiro
@ 2017-11-23 16:13 ` Nelio Laranjeiro
  2017-11-23 16:13 ` [PATCH v1 7/7] net/mlx5: add device parameter to enabled IPsec Nelio Laranjeiro
  6 siblings, 0 replies; 8+ messages in thread
From: Nelio Laranjeiro @ 2017-11-23 16:13 UTC (permalink / raw)
  To: dev
  Cc: Shahaf Shuler, Yongseok Koh, Adrien Mazarguil, Aviad Yehezkel,
	Matan Barak

From: Shahaf Shuler <shahafs@mellanox.com>

Signed-off-by: Shahaf Shuler <shahafs@mellanox.com>
Signed-off-by: Aviad Yehezkel <aviadye@mellanox.com>
Signed-off-by: Matan Barak <matanb@mellanox.com>
Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
---
 drivers/net/mlx5/mlx5.h       |   7 +
 drivers/net/mlx5/mlx5_flow.c  | 309 ++++++++++++++++++++++++++++++++++++++----
 drivers/net/mlx5/mlx5_ipsec.c |  10 +-
 3 files changed, 289 insertions(+), 37 deletions(-)

diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 2927b851b..cb25beb3c 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -154,6 +154,13 @@ struct priv {
 	struct rte_security_ctx security; /* Security context. */
 };
 
+/* 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;
+};
+
 /**
  * Lock private structure to protect it from concurrent access in the
  * control path.
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index ff50470b5..704c47820 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -78,6 +78,20 @@ ibv_destroy_counter_set(struct ibv_counter_set *cs)
 }
 #endif
 
+#ifndef HAVE_IBV_IPSEC_SUPPORT
+/* Define dummy structure when IPsec is not available in Verbs. */
+
+/* Dummy spec ESP defined when missing in Verbs. */
+struct ibv_flow_spec_esp {
+	int dummy;
+};
+
+/* Dummy transform action defined when missing in Verbs. */
+struct ibv_flow_spec_action_xfrm {
+	int dummy;
+};
+#endif
+
 /* Dev ops structure defined in mlx5.c */
 extern const struct eth_dev_ops mlx5_dev_ops;
 extern const struct eth_dev_ops mlx5_dev_ops_isolate;
@@ -129,6 +143,14 @@ mlx5_flow_create_flag_mark(struct mlx5_flow_parse *parser, uint32_t mark_id);
 static int
 mlx5_flow_create_count(struct priv *priv, struct mlx5_flow_parse *parser);
 
+static int
+mlx5_flow_create_esp(const struct rte_flow_item *item,
+		     const void *default_mask,
+		     void *data);
+
+static void
+mlx5_flow_create_xfrm(struct mlx5_flow_parse *parser);
+
 /* Hash RX queue types. */
 enum hash_rxq_type {
 	HASH_RXQ_TCPV4,
@@ -244,6 +266,8 @@ struct rte_flow {
 	TAILQ_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */
 	uint32_t mark:1; /**< Set if the flow is marked. */
 	uint32_t drop:1; /**< Drop queue. */
+	uint32_t security:1; /**< Security flow. */
+	uint32_t ingress:1; /**< Ingress flow. */
 	uint16_t queues_n; /**< Number of entries in queue[]. */
 	uint16_t (*queues)[]; /**< Queues indexes to use. */
 	struct rte_eth_rss_conf rss_conf; /**< RSS configuration */
@@ -305,6 +329,7 @@ static const enum rte_flow_action_type valid_actions[] = {
 #ifdef HAVE_IBV_DEVICE_COUNTERS_SET_SUPPORT
 	RTE_FLOW_ACTION_TYPE_COUNT,
 #endif
+	RTE_FLOW_ACTION_TYPE_SECURITY,
 	RTE_FLOW_ACTION_TYPE_END,
 };
 
@@ -343,7 +368,8 @@ static const struct mlx5_flow_items mlx5_flow_items[] = {
 	},
 	[RTE_FLOW_ITEM_TYPE_IPV4] = {
 		.items = ITEMS(RTE_FLOW_ITEM_TYPE_UDP,
-			       RTE_FLOW_ITEM_TYPE_TCP),
+			       RTE_FLOW_ITEM_TYPE_TCP,
+			       RTE_FLOW_ITEM_TYPE_ESP),
 		.actions = valid_actions,
 		.mask = &(const struct rte_flow_item_ipv4){
 			.hdr = {
@@ -360,7 +386,8 @@ static const struct mlx5_flow_items mlx5_flow_items[] = {
 	},
 	[RTE_FLOW_ITEM_TYPE_IPV6] = {
 		.items = ITEMS(RTE_FLOW_ITEM_TYPE_UDP,
-			       RTE_FLOW_ITEM_TYPE_TCP),
+			       RTE_FLOW_ITEM_TYPE_TCP,
+			       RTE_FLOW_ITEM_TYPE_ESP),
 		.actions = valid_actions,
 		.mask = &(const struct rte_flow_item_ipv6){
 			.hdr = {
@@ -424,6 +451,17 @@ static const struct mlx5_flow_items mlx5_flow_items[] = {
 		.convert = mlx5_flow_create_vxlan,
 		.dst_sz = sizeof(struct ibv_flow_spec_tunnel),
 	},
+	[RTE_FLOW_ITEM_TYPE_ESP] = {
+		.actions = valid_actions,
+		.mask = &(const struct rte_flow_item_esp){
+			.hdr = {
+				.spi = 0xffffffff,
+			}
+		},
+		.mask_sz = sizeof(struct rte_flow_item_esp),
+		.convert = mlx5_flow_create_esp,
+		.dst_sz = sizeof(struct ibv_flow_spec_esp),
+	},
 };
 
 /** Structure to pass to the conversion function. */
@@ -434,6 +472,7 @@ struct mlx5_flow_parse {
 	uint32_t drop:1; /**< Target is a drop queue. */
 	uint32_t mark:1; /**< Mark is present in the flow. */
 	uint32_t count:1; /**< Count is present in the flow. */
+	uint32_t ingress:1; /** Flow is for ingress. */
 	uint32_t mark_id; /**< Mark identifier. */
 	uint16_t queues[RTE_MAX_QUEUES_PER_PORT]; /**< Queues indexes to use. */
 	uint16_t queues_n; /**< Number of entries in queue[]. */
@@ -441,6 +480,7 @@ struct mlx5_flow_parse {
 	uint8_t rss_key[40]; /**< copy of the RSS key. */
 	enum hash_rxq_type layer; /**< Last pattern layer detected. */
 	struct ibv_counter_set *cs; /**< Holds the counter set for the rule */
+	const struct mlx5_security_session *security; /**< Security session */
 	struct {
 		struct ibv_flow_attr *ibv_attr;
 		/**< Pointer to Verbs attributes. */
@@ -601,7 +641,6 @@ priv_flow_convert_attributes(struct priv *priv,
 			     struct mlx5_flow_parse *parser)
 {
 	(void)priv;
-	(void)parser;
 	if (attr->group) {
 		rte_flow_error_set(error, ENOTSUP,
 				   RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
@@ -616,20 +655,28 @@ priv_flow_convert_attributes(struct priv *priv,
 				   "priorities are not supported");
 		return -rte_errno;
 	}
-	if (attr->egress) {
+	if (attr->egress && attr->ingress) {
 		rte_flow_error_set(error, ENOTSUP,
 				   RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
 				   NULL,
-				   "egress is not supported");
+				   "egress with ingress is not supported");
 		return -rte_errno;
 	}
-	if (!attr->ingress) {
+	if (attr->ingress && attr->egress) {
 		rte_flow_error_set(error, ENOTSUP,
 				   RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
 				   NULL,
-				   "only ingress is supported");
+				   "ingress with egress is supported");
+		return -rte_errno;
+	}
+	if (!(attr->ingress ^ attr->egress)) {
+		rte_flow_error_set(error, ENOTSUP,
+				   RTE_FLOW_ERROR_TYPE_ATTR,
+				   NULL,
+				   "Missing Ingress of Egress");
 		return -rte_errno;
 	}
+	parser->ingress = attr->ingress;
 	return 0;
 }
 
@@ -649,10 +696,10 @@ priv_flow_convert_attributes(struct priv *priv,
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 static int
-priv_flow_convert_actions(struct priv *priv,
-			  const struct rte_flow_action actions[],
-			  struct rte_flow_error *error,
-			  struct mlx5_flow_parse *parser)
+priv_flow_convert_actions_ingress(struct priv *priv,
+				  const struct rte_flow_action actions[],
+				  struct rte_flow_error *error,
+				  struct mlx5_flow_parse *parser)
 {
 	int ret = 0;
 	const char *msg = NULL;
@@ -760,6 +807,27 @@ priv_flow_convert_actions(struct priv *priv,
 			}
 			parser->mark = 1;
 			parser->mark_id = mark->id;
+		} else if (actions->type == RTE_FLOW_ACTION_TYPE_SECURITY) {
+			if (!actions->conf) {
+				ret = EINVAL;
+				msg = "invalid security configuration";
+				action = actions;
+				goto error;
+			}
+			parser->security =
+				get_sec_session_private_data(actions->conf);
+			if (!parser->security) {
+				ret = EINVAL;
+				msg = "invalid security configuration";
+				action = actions;
+				goto error;
+			}
+			if (!priv->ipsec_en) {
+				ret = ENOTSUP;
+				msg = "action not supported";
+				action = actions;
+				goto error;
+			}
 		} else if (actions->type == RTE_FLOW_ACTION_TYPE_FLAG) {
 			parser->mark = 1;
 		} else if (actions->type == RTE_FLOW_ACTION_TYPE_COUNT &&
@@ -785,6 +853,84 @@ priv_flow_convert_actions(struct priv *priv,
 }
 
 /**
+ * Extract actions request to the parser.
+ *
+ * @param priv
+ *   Pointer to private structure.
+ * @param[in] actions
+ *   Associated actions (list terminated by the END action).
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL.
+ * @param[in, out] parser
+ *   Internal parser structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+priv_flow_convert_actions_egress(struct priv *priv,
+				 const struct rte_flow_action actions[],
+				 struct rte_flow_error *error,
+				 struct mlx5_flow_parse *parser)
+{
+	int ret;
+	const char *msg;
+	const struct rte_flow_action *action;
+
+	/*
+	 * Add default RSS configuration necessary for Verbs to create QP even
+	 * if no RSS is necessary.
+	 */
+	priv_flow_convert_rss_conf(priv, parser,
+				   (const struct rte_eth_rss_conf *)
+				   &priv->rss_conf);
+	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; ++actions) {
+		if (actions->type == RTE_FLOW_ACTION_TYPE_VOID) {
+			continue;
+		} else if (actions->type == RTE_FLOW_ACTION_TYPE_SECURITY) {
+			if (!actions->conf) {
+				ret = EINVAL;
+				msg = "invalid security configuration";
+				action = actions;
+				goto error;
+			}
+			parser->security =
+				get_sec_session_private_data(actions->conf);
+			if (!parser->security) {
+				ret = EINVAL;
+				msg = "invalid security configuration";
+				action = actions;
+				goto error;
+			}
+			if (!priv->ipsec_en) {
+				ret = ENOTSUP;
+				msg = "action not supported";
+				action = actions;
+				goto error;
+			}
+		} else {
+			ret = ENOTSUP;
+			msg = "action not supported";
+			action = actions;
+			goto error;
+		}
+	}
+	if (parser->drop) {
+		ret = EINVAL;
+		msg = "dropping in egress is not invalid";
+		action = NULL;
+		goto error;
+	}
+	return 0;
+error:
+	rte_flow_error_set(error, ret,
+			   action ? RTE_FLOW_ERROR_TYPE_ACTION :
+			   RTE_FLOW_ERROR_TYPE_HANDLE,
+			   action, msg);
+	return -rte_errno;
+}
+
+/**
  * Validate items.
  *
  * @param priv
@@ -847,7 +993,7 @@ priv_flow_convert_items_validate(struct priv *priv,
 			}
 			parser->inner = IBV_FLOW_SPEC_INNER;
 		}
-		if (parser->drop || parser->queues_n == 1) {
+		if (parser->drop || !parser->ingress || parser->queues_n == 1) {
 			parser->queue[HASH_RXQ_ETH].offset += cur_item->dst_sz;
 		} else {
 			for (n = 0; n != hash_rxq_init_n; ++n)
@@ -865,6 +1011,16 @@ priv_flow_convert_items_validate(struct priv *priv,
 		for (i = 0; i != hash_rxq_init_n; ++i)
 			parser->queue[i].offset += size;
 	}
+	if (parser->security) {
+		unsigned int size = sizeof(struct ibv_flow_spec_action_xfrm);
+
+		if (parser->drop || !parser->ingress) {
+			parser->queue[HASH_RXQ_ETH].offset += size;
+		} else {
+			for (i = 0; i != hash_rxq_init_n; ++i)
+				parser->queue[i].offset += size;
+		}
+	}
 	return 0;
 exit_item_not_supported:
 	rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
@@ -1064,7 +1220,12 @@ priv_flow_convert(struct priv *priv,
 	ret = priv_flow_convert_attributes(priv, attr, error, parser);
 	if (ret)
 		return ret;
-	ret = priv_flow_convert_actions(priv, actions, error, parser);
+	if (attr->ingress)
+		ret = priv_flow_convert_actions_ingress(priv, actions, error,
+							parser);
+	else
+		ret = priv_flow_convert_actions_egress(priv, actions, error,
+						       parser);
 	if (ret)
 		return ret;
 	ret = priv_flow_convert_items_validate(priv, items, error, parser);
@@ -1075,7 +1236,7 @@ priv_flow_convert(struct priv *priv,
 	 * Second step.
 	 * Allocate the memory space to store verbs specifications.
 	 */
-	if (parser->drop || parser->queues_n == 1) {
+	if (parser->drop || parser->queues_n == 1 || !parser->ingress) {
 		unsigned int priority =
 			attr->priority +
 			hash_rxq_init[HASH_RXQ_ETH].flow_priority;
@@ -1133,6 +1294,8 @@ priv_flow_convert(struct priv *priv,
 		if (!parser->cs)
 			goto exit_count_error;
 	}
+	if (parser->security)
+		mlx5_flow_create_xfrm(parser);
 	/*
 	 * Last step. Complete missing specification to reach the RSS
 	 * configuration.
@@ -1611,6 +1774,73 @@ mlx5_flow_create_count(struct priv *priv __rte_unused,
 }
 
 /**
+ * Convert ESP Item to Verbs specification.
+ *
+ * @param item[in]
+ *   Item specification.
+ * @param default_mask[in]
+ *   Default bit-masks to use when item->mask is not provided.
+ * @param data[in, out]
+ *   User structure.
+ *
+ * @return
+ *   0 on success, errno value on failure.
+ */
+static int
+mlx5_flow_create_esp(const struct rte_flow_item *item __rte_unused,
+		     const void *default_mask __rte_unused,
+		     void *data __rte_unused)
+{
+	int ret = ENOTSUP;
+#ifdef HAVE_IBV_IPSEC_SUPPORT
+	const struct rte_flow_item_esp *spec = item->spec;
+	const struct rte_flow_item_esp *mask = item->mask;
+	struct mlx5_flow_parse *parser = (struct mlx5_flow_parse *)data;
+	unsigned int size = sizeof(struct ibv_flow_spec_esp);
+	struct ibv_flow_spec_esp esp = {
+		.type = parser->inner | IBV_FLOW_SPEC_ESP,
+		.size = size,
+	};
+
+	ret = 0;
+	if (spec) {
+		if (!mask)
+			mask = default_mask;
+		esp.val.spi = htonl(spec->hdr.spi);
+		esp.val.seq = htonl(spec->hdr.seq);
+		esp.mask.spi = htonl(mask->hdr.spi);
+		esp.mask.seq = htonl(mask->hdr.seq);
+		esp.val.spi &= esp.mask.spi;
+		esp.val.seq &= esp.mask.seq;
+	}
+	mlx5_flow_create_copy(parser, &esp, size);
+#endif
+	return ret;
+}
+
+/**
+ * Convert XFRM action to Verbs specification.
+ *
+ * @param parser
+ *   Pointer to MLX5 flow parser structure.
+ */
+static void
+mlx5_flow_create_xfrm(struct mlx5_flow_parse *parser __rte_unused)
+{
+#ifdef HAVE_IBV_IPSEC_SUPPORT
+	unsigned int size = sizeof(struct ibv_flow_spec_action_xfrm);
+	struct ibv_flow_spec_action_xfrm xfrm_spec = {
+		.type = IBV_FLOW_SPEC_ACTION_XFRM,
+		.action = parser->security->ibv_action_xfrm,
+		.size = size,
+	};
+
+	assert(parser->security);
+	mlx5_flow_create_copy(parser, &xfrm_spec, size);
+#endif
+}
+
+/**
  * Complete flow rule creation with a drop queue.
  *
  * @param priv
@@ -1797,6 +2027,7 @@ priv_flow_create_action_queue(struct priv *priv,
 			(*priv->rxqs)[parser->queues[i]];
 
 		q->mark |= parser->mark;
+		q->ipsec_en |= !!(parser->security);
 	}
 	return 0;
 error:
@@ -1870,18 +2101,23 @@ priv_flow_create(struct priv *priv,
 	memcpy(flow->queues, parser.queues, parser.queues_n * sizeof(uint16_t));
 	flow->queues_n = parser.queues_n;
 	flow->mark = parser.mark;
+	flow->security = !!parser.security;
 	/* Copy RSS configuration. */
 	flow->rss_conf = parser.rss_conf;
 	flow->rss_conf.rss_key = flow->rss_key;
 	memcpy(flow->rss_key, parser.rss_key, parser.rss_conf.rss_key_len);
 	/* finalise the flow. */
-	if (parser.drop)
-		err = priv_flow_create_action_queue_drop(priv, &parser, flow,
-							 error);
-	else
-		err = priv_flow_create_action_queue(priv, &parser, flow, error);
-	if (err)
-		goto exit;
+	flow->ingress = parser.ingress;
+	if (parser.ingress) {
+		if (parser.drop)
+			err = priv_flow_create_action_queue_drop(priv, &parser,
+								 flow, error);
+		else
+			err = priv_flow_create_action_queue(priv, &parser, flow,
+							    error);
+		if (err)
+			goto exit;
+	}
 	TAILQ_INSERT_TAIL(list, flow, next);
 	DEBUG("Flow created %p", (void *)flow);
 	return flow;
@@ -1962,17 +2198,19 @@ priv_flow_destroy(struct priv *priv,
 	for (i = 0; i != flow->queues_n; ++i) {
 		struct rte_flow *tmp;
 		int mark = 0;
+		int ipsec = 0;
 
 		/*
 		 * To remove the mark from the queue, the queue must not be
 		 * present in any other marked flow (RSS or not).
+		 * Same thing for the IPsec.
 		 */
 		TAILQ_FOREACH(tmp, list, next) {
 			unsigned int j;
 			uint16_t *tqs = NULL;
 			uint16_t tq_n = 0;
 
-			if (!tmp->mark)
+			if (!tmp->mark && !tmp->security)
 				continue;
 			for (j = 0; j != hash_rxq_init_n; ++j) {
 				if (!tmp->frxq[j].hrxq)
@@ -1982,11 +2220,17 @@ priv_flow_destroy(struct priv *priv,
 			}
 			if (!tq_n)
 				continue;
-			for (j = 0; (j != tq_n) && !mark; j++)
-				if (tqs[j] == (*flow->queues)[i])
-					mark = 1;
+			for (j = 0; (j != tq_n) && !mark; j++) {
+				if (tqs[j] == (*flow->queues)[i]) {
+					mark |= (*priv->rxqs)
+						[(*flow->queues)[j]]->mark;
+					ipsec |= !!(*priv->rxqs)
+						[(*flow->queues)[j]]->ipsec_en;
+				}
+			}
 		}
 		(*priv->rxqs)[(*flow->queues)[i]]->mark = mark;
+		(*priv->rxqs)[(*flow->queues)[i]]->ipsec_en = ipsec;
 	}
 free:
 	if (flow->drop) {
@@ -2170,7 +2414,7 @@ priv_flow_stop(struct priv *priv, struct mlx5_flows *list)
 			/* Next flow. */
 			continue;
 		}
-		if (flow->mark) {
+		if (flow->mark || flow->security) {
 			struct mlx5_ind_table_ibv *ind_tbl = NULL;
 
 			for (i = 0; i != hash_rxq_init_n; ++i) {
@@ -2179,8 +2423,10 @@ priv_flow_stop(struct priv *priv, struct mlx5_flows *list)
 				ind_tbl = flow->frxq[i].hrxq->ind_table;
 			}
 			assert(ind_tbl);
-			for (i = 0; i != ind_tbl->queues_n; ++i)
+			for (i = 0; i != ind_tbl->queues_n; ++i) {
 				(*priv->rxqs)[ind_tbl->queues[i]]->mark = 0;
+				(*priv->rxqs)[ind_tbl->queues[i]]->ipsec_en = 0;
+			}
 		}
 		for (i = 0; i != hash_rxq_init_n; ++i) {
 			if (!flow->frxq[i].ibv_flow)
@@ -2263,10 +2509,13 @@ priv_flow_start(struct priv *priv, struct mlx5_flows *list)
 			}
 			DEBUG("Flow %p applied", (void *)flow);
 		}
-		if (!flow->mark)
+		if (!flow->mark && !flow->security)
 			continue;
-		for (i = 0; i != flow->queues_n; ++i)
-			(*priv->rxqs)[(*flow->queues)[i]]->mark = 1;
+		for (i = 0; i != flow->queues_n; ++i) {
+			(*priv->rxqs)[(*flow->queues)[i]]->mark = flow->mark;
+			(*priv->rxqs)[(*flow->queues)[i]]->ipsec_en =
+				flow->security;
+		}
 	}
 	return 0;
 }
diff --git a/drivers/net/mlx5/mlx5_ipsec.c b/drivers/net/mlx5/mlx5_ipsec.c
index 52a3add7a..e7086adbc 100644
--- a/drivers/net/mlx5/mlx5_ipsec.c
+++ b/drivers/net/mlx5/mlx5_ipsec.c
@@ -57,6 +57,9 @@
 		      " please contact Mellanox")
 
 /* Extra verifications, this API is not unstreamed yet. */
+MLX5_IPSEC_SUPPORT_ERROR(IBV_FLOW_ATTR_FLAGS_EGRESS == 1 << 2);
+MLX5_IPSEC_SUPPORT_ERROR(IBV_FLOW_SPEC_ESP == 0x34);
+MLX5_IPSEC_SUPPORT_ERROR(IBV_FLOW_SPEC_ACTION_XFRM == 0x1002);
 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);
@@ -65,13 +68,6 @@ 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) */
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v1 7/7] net/mlx5: add device parameter to enabled IPsec
  2017-11-23 16:13 [PATCH v1 0/7] net/mlx5: IPsec offload support Nelio Laranjeiro
                   ` (5 preceding siblings ...)
  2017-11-23 16:13 ` [PATCH v1 6/7] net/mlx5: support security flow action Nelio Laranjeiro
@ 2017-11-23 16:13 ` Nelio Laranjeiro
  6 siblings, 0 replies; 8+ messages in thread
From: Nelio Laranjeiro @ 2017-11-23 16:13 UTC (permalink / raw)
  To: dev; +Cc: Yongseok Koh, Adrien Mazarguil, Aviad Yehezkel

This feature still relies on some symbols from Verbs and thus the support
is only compile if the symbols are available.
Only ConnectX-4 Lx INNOVA are security capable.

Signed-off-by: Aviad Yehezkel <aviadye@mellanox.com>
Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
---
 doc/guides/nics/mlx5.rst |  9 +++++++++
 drivers/net/mlx5/mlx5.c  | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+)

diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst
index f9558da89..643c1dd5d 100644
--- a/doc/guides/nics/mlx5.rst
+++ b/doc/guides/nics/mlx5.rst
@@ -295,6 +295,15 @@ Run-time configuration
 
   Enabled by default.
 
+- ``ipsec_en`` parameter [int]
+
+  A nonzero value enables the IPsec feature on the port.
+  Enabling this feature enables, ``txq_inline`` with a size equal to
+  RTE_CACHE_LINE_SIZE and disables ``rx_vec_en``, ``tx_vec_en`` and
+  ``txq_mpw_en``.
+
+  Enabled by default on ConnectX-4 Lx INOVA.
+
 Prerequisites
 -------------
 
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index e74026caf..0a7e9ac34 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -95,6 +95,9 @@
 /* Device parameter to enable hardware Rx vector. */
 #define MLX5_RX_VEC_EN "rx_vec_en"
 
+/* Device parameter to enable hardware IPsec offload. */
+#define MLX5_IPSEC_EN "ipsec_en"
+
 /* Default PMD specific parameter value. */
 #define MLX5_ARG_UNSET (-1)
 
@@ -128,6 +131,7 @@ struct mlx5_args {
 	int tso;
 	int tx_vec_en;
 	int rx_vec_en;
+	int ipsec_en;
 };
 /**
  * Retrieve integer value from environment variable.
@@ -438,6 +442,8 @@ mlx5_args_check(const char *key, const char *val, void *opaque)
 		args->tx_vec_en = !!tmp;
 	} else if (strcmp(MLX5_RX_VEC_EN, key) == 0) {
 		args->rx_vec_en = !!tmp;
+	} else if (strcmp(MLX5_IPSEC_EN, key) == 0) {
+		args->ipsec_en = !!tmp;
 	} else {
 		WARN("%s: unknown parameter", key);
 		return -EINVAL;
@@ -469,6 +475,7 @@ mlx5_args(struct mlx5_args *args, struct rte_devargs *devargs)
 		MLX5_TSO,
 		MLX5_TX_VEC_EN,
 		MLX5_RX_VEC_EN,
+		MLX5_IPSEC_EN,
 		NULL,
 	};
 	struct rte_kvargs *kvlist;
@@ -528,6 +535,8 @@ mlx5_args_assign(struct priv *priv, struct mlx5_args *args)
 		priv->tx_vec_en = args->tx_vec_en;
 	if (args->rx_vec_en != MLX5_ARG_UNSET)
 		priv->rx_vec_en = args->rx_vec_en;
+	if (args->ipsec_en != MLX5_ARG_UNSET)
+		priv->ipsec_en = args->ipsec_en;
 }
 
 /**
@@ -556,6 +565,7 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 	unsigned int mps;
 	unsigned int cqe_comp;
 	unsigned int tunnel_en = 0;
+	unsigned int ipsec_en = 0;
 	int idx;
 	int i;
 	struct mlx5dv_context attrs_out;
@@ -645,6 +655,13 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 	ibv_dev = list[i];
 
 	DEBUG("device opened");
+#ifdef HAVE_IBV_IPSEC_SUPPORT
+	attrs_out.comp_mask |= MLX5DV_CONTEXT_MASK_XFRM_FLAGS;
+	mlx5dv_query_device(attr_ctx, &attrs_out);
+	if ((attrs_out.xfrm_flags & MLX5_IPSEC_FLAGS) == MLX5_IPSEC_FLAGS)
+		ipsec_en = 1;
+#endif
+	DEBUG("Tx/Rx IPsec offload is %ssupported", ipsec_en ? "" : "not ");
 	/*
 	 * Multi-packet send is supported by ConnectX-4 Lx PF as well
 	 * as all ConnectX-5 devices.
@@ -693,6 +710,7 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 			.tso = MLX5_ARG_UNSET,
 			.tx_vec_en = MLX5_ARG_UNSET,
 			.rx_vec_en = MLX5_ARG_UNSET,
+			.ipsec_en = MLX5_ARG_UNSET,
 		};
 
 		mlx5_dev[idx].ports |= test;
@@ -787,6 +805,7 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 		priv->mps = mps; /* Enable MPW by default if supported. */
 		priv->cqe_comp = cqe_comp;
 		priv->tunnel_en = tunnel_en;
+		priv->ipsec_en = ipsec_en;
 		/* Enable vector by default if supported. */
 		priv->tx_vec_en = 1;
 		priv->rx_vec_en = 1;
@@ -797,6 +816,19 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 			goto port_error;
 		}
 		mlx5_args_assign(priv, &args);
+		if (priv->ipsec_en) {
+#ifndef HAVE_IBV_IPSEC_SUPPORT
+			priv->ipsec_en = 0;
+			WARN("IPsec Offload not supported.");
+#else /* HAVE_IBV_IPSEC_SUPPORT */
+			priv->txq_inline = RTE_CACHE_LINE_SIZE;
+			priv->txqs_inline = 0;
+			priv->mps = MLX5_MPW_DISABLED;
+			priv->tx_vec_en = 0;
+			priv->rx_vec_en = 0;
+			WARN("IPsec offload enabled");
+#endif /* HAVE_IBV_IPSEC_SUPPORT */
+		}
 		if (ibv_query_device_ex(ctx, NULL, &device_attr_ex)) {
 			ERROR("ibv_query_device_ex() failed");
 			goto port_error;
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2017-11-23 16:13 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-23 16:13 [PATCH v1 0/7] net/mlx5: IPsec offload support Nelio Laranjeiro
2017-11-23 16:13 ` [PATCH v1 1/7] net: define Mellanox ether type for embed metadata Nelio Laranjeiro
2017-11-23 16:13 ` [PATCH v1 2/7] net/mlx5: handle the IPsec support from Verbs Nelio Laranjeiro
2017-11-23 16:13 ` [PATCH v1 3/7] net/mlx5: add IPsec Tx/Rx offload support Nelio Laranjeiro
2017-11-23 16:13 ` [PATCH v1 4/7] net/mlx5: add security capability function Nelio Laranjeiro
2017-11-23 16:13 ` [PATCH v1 5/7] net/mlx5: simplify error handling in flow action parsing Nelio Laranjeiro
2017-11-23 16:13 ` [PATCH v1 6/7] net/mlx5: support security flow action Nelio Laranjeiro
2017-11-23 16:13 ` [PATCH v1 7/7] net/mlx5: add device parameter to enabled IPsec Nelio Laranjeiro

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.