* [dpdk-dev] [PATCH v1 1/7] net: define Mellanox ether type for embed metadata
2017-11-23 16:13 [dpdk-dev] [PATCH v1 0/7] net/mlx5: IPsec offload support Nelio Laranjeiro
@ 2017-11-23 16:13 ` Nelio Laranjeiro
2017-11-23 16:13 ` [dpdk-dev] [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 [flat|nested] 8+ messages in thread
* [dpdk-dev] [PATCH v1 2/7] net/mlx5: handle the IPsec support from Verbs
2017-11-23 16:13 [dpdk-dev] [PATCH v1 0/7] net/mlx5: IPsec offload support Nelio Laranjeiro
2017-11-23 16:13 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 8+ messages in thread
* [dpdk-dev] [PATCH v1 3/7] net/mlx5: add IPsec Tx/Rx offload support
2017-11-23 16:13 [dpdk-dev] [PATCH v1 0/7] net/mlx5: IPsec offload support Nelio Laranjeiro
2017-11-23 16:13 ` [dpdk-dev] [PATCH v1 1/7] net: define Mellanox ether type for embed metadata Nelio Laranjeiro
2017-11-23 16:13 ` [dpdk-dev] [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 ` [dpdk-dev] [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, ðertype, 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 [flat|nested] 8+ messages in thread
* [dpdk-dev] [PATCH v1 4/7] net/mlx5: add security capability function
2017-11-23 16:13 [dpdk-dev] [PATCH v1 0/7] net/mlx5: IPsec offload support Nelio Laranjeiro
` (2 preceding siblings ...)
2017-11-23 16:13 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 8+ messages in thread
* [dpdk-dev] [PATCH v1 5/7] net/mlx5: simplify error handling in flow action parsing
2017-11-23 16:13 [dpdk-dev] [PATCH v1 0/7] net/mlx5: IPsec offload support Nelio Laranjeiro
` (3 preceding siblings ...)
2017-11-23 16:13 ` [dpdk-dev] [PATCH v1 4/7] net/mlx5: add security capability function Nelio Laranjeiro
@ 2017-11-23 16:13 ` Nelio Laranjeiro
2017-11-23 16:13 ` [dpdk-dev] [PATCH v1 6/7] net/mlx5: support security flow action Nelio Laranjeiro
2017-11-23 16:13 ` [dpdk-dev] [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 [flat|nested] 8+ messages in thread
* [dpdk-dev] [PATCH v1 6/7] net/mlx5: support security flow action
2017-11-23 16:13 [dpdk-dev] [PATCH v1 0/7] net/mlx5: IPsec offload support Nelio Laranjeiro
` (4 preceding siblings ...)
2017-11-23 16:13 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 8+ messages in thread
* [dpdk-dev] [PATCH v1 7/7] net/mlx5: add device parameter to enabled IPsec
2017-11-23 16:13 [dpdk-dev] [PATCH v1 0/7] net/mlx5: IPsec offload support Nelio Laranjeiro
` (5 preceding siblings ...)
2017-11-23 16:13 ` [dpdk-dev] [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 [flat|nested] 8+ messages in thread