* [PATCH v2 01/10] mailmap: update contributor entry
2023-09-26 2:49 ` [PATCH v2 00/10] add the support of ipsec offload Chaoyong He
@ 2023-09-26 2:49 ` Chaoyong He
2023-09-26 2:49 ` [PATCH v2 02/10] net/nfp: add TLVs capability parsing Chaoyong He
` (10 subsequent siblings)
11 siblings, 0 replies; 42+ messages in thread
From: Chaoyong He @ 2023-09-26 2:49 UTC (permalink / raw)
To: dev; +Cc: oss-drivers, Shihong Wang, Chaoyong He
From: Shihong Wang <shihong.wang@corigine.com>
Add contributor entries to .mailmap file.
Signed-off-by: Shihong Wang <shihong.wang@corigine.com>
Reviewed-by: Chaoyong He <chaoyong.he@corigine.com>
---
.mailmap | 2 ++
1 file changed, 2 insertions(+)
diff --git a/.mailmap b/.mailmap
index 276325211c..5abd5810e2 100644
--- a/.mailmap
+++ b/.mailmap
@@ -200,6 +200,7 @@ Carolyn Wyborny <carolyn.wyborny@intel.com>
Chaeyong Chong <cychong@gmail.com>
Chaitanya Babu Talluri <tallurix.chaitanya.babu@intel.com>
Chandubabu Namburu <chandu@amd.com>
+Chang Miao <chang.miao@corigine.com>
Changchun Ouyang <changchun.ouyang@intel.com>
Changpeng Liu <changpeng.liu@intel.com>
Changqing Wu <changqingx.wu@intel.com>
@@ -1265,6 +1266,7 @@ Shelton Chia <jiaxt@sinogrid.com>
Shepard Siegel <shepard.siegel@atomicrules.com>
Shesha Sreenivasamurthy <shesha@cisco.com>
Shibin Koikkara Reeny <shibin.koikkara.reeny@intel.com>
+Shihong Wang <shihong.wang@corigine.com>
Shijith Thotton <sthotton@marvell.com> <shijith.thotton@caviumnetworks.com>
Shiqi Liu <835703180@qq.com>
Shiri Kuzin <shirik@nvidia.com> <shirik@mellanox.com>
--
2.39.1
^ permalink raw reply [flat|nested] 42+ messages in thread
* [PATCH v2 02/10] net/nfp: add TLVs capability parsing
2023-09-26 2:49 ` [PATCH v2 00/10] add the support of ipsec offload Chaoyong He
2023-09-26 2:49 ` [PATCH v2 01/10] mailmap: update contributor entry Chaoyong He
@ 2023-09-26 2:49 ` Chaoyong He
2023-09-26 2:49 ` [PATCH v2 03/10] net/nfp: add mailbox to support IPsec offload Chaoyong He
` (9 subsequent siblings)
11 siblings, 0 replies; 42+ messages in thread
From: Chaoyong He @ 2023-09-26 2:49 UTC (permalink / raw)
To: dev; +Cc: oss-drivers, Shihong Wang, Chang Miao, Chaoyong He
From: Shihong Wang <shihong.wang@corigine.com>
Add TLV capabilities to the BAR, TLVs is fit for expressing
capabilities of applications running on programmable hardware.
Declares a TLV capability start at offset 0x58, up to 0x0d90.
The used space can be wrapped with RESERVED.
Signed-off-by: Shihong Wang <shihong.wang@corigine.com>
Signed-off-by: Chang Miao <chang.miao@corigine.com>
Reviewed-by: Chaoyong He <chaoyong.he@corigine.com>
---
drivers/net/nfp/meson.build | 1 +
drivers/net/nfp/nfp_common.h | 13 +++
drivers/net/nfp/nfp_ctrl.c | 153 +++++++++++++++++++++++++++++++++++
drivers/net/nfp/nfp_ctrl.h | 121 +++++++++++++++++++++++++++
drivers/net/nfp/nfp_ethdev.c | 6 ++
5 files changed, 294 insertions(+)
create mode 100644 drivers/net/nfp/nfp_ctrl.c
diff --git a/drivers/net/nfp/meson.build b/drivers/net/nfp/meson.build
index d422269c4b..e78bcb8b75 100644
--- a/drivers/net/nfp/meson.build
+++ b/drivers/net/nfp/meson.build
@@ -27,6 +27,7 @@ sources = files(
'nfpcore/nfp_target.c',
'nfpcore/nfp6000_pcie.c',
'nfp_common.c',
+ 'nfp_ctrl.c',
'nfp_rxtx.c',
'nfp_cpp_bridge.c',
'nfp_ethdev_vf.c',
diff --git a/drivers/net/nfp/nfp_common.h b/drivers/net/nfp/nfp_common.h
index b0372c3dc6..4a19c18466 100644
--- a/drivers/net/nfp/nfp_common.h
+++ b/drivers/net/nfp/nfp_common.h
@@ -64,6 +64,17 @@ enum nfp_net_meta_format {
NFP_NET_METAFORMAT_CHAINED,
};
+/* Parsed control BAR TLV capabilities */
+struct nfp_net_tlv_caps {
+ uint32_t me_freq_mhz; /**< ME clock_freq (MHz) */
+ uint32_t mbox_off; /**< VNIC mailbox area offset */
+ uint32_t mbox_len; /**< VNIC mailbox area length */
+ uint32_t repr_cap; /**< Capabilities for representors */
+ uint32_t mbox_cmsg_types; /**< Cmsgs which can be passed through the mailbox */
+ uint32_t vnic_stats_off; /**< Offset of vNIC stats area */
+ uint32_t vnic_stats_cnt; /**< Number of vNIC stats */
+};
+
struct nfp_pf_dev {
/* Backpointer to associated pci device */
struct rte_pci_device *pci_dev;
@@ -163,6 +174,8 @@ struct nfp_net_hw {
uint8_t idx;
/* Internal port number as seen from NFP */
uint8_t nfp_idx;
+
+ struct nfp_net_tlv_caps tlv_caps;
};
struct nfp_net_adapter {
diff --git a/drivers/net/nfp/nfp_ctrl.c b/drivers/net/nfp/nfp_ctrl.c
new file mode 100644
index 0000000000..c61d3fd158
--- /dev/null
+++ b/drivers/net/nfp/nfp_ctrl.c
@@ -0,0 +1,153 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2023 Corigine Systems, Inc.
+ * All rights reserved.
+ */
+
+#include "nfp_ctrl.h"
+
+#include <ethdev_pci.h>
+
+#include "nfpcore/nfp_platform.h"
+
+#include "nfp_common.h"
+#include "nfp_logs.h"
+
+/* Mailbox Me clock freq */
+#define NFP_NET_CFG_MBOX_FREQ_MHZ 1200
+
+static void
+nfp_net_tlv_caps_reset(struct nfp_net_tlv_caps *caps)
+{
+ memset(caps, 0, sizeof(*caps));
+ caps->me_freq_mhz = NFP_NET_CFG_MBOX_FREQ_MHZ;
+ caps->mbox_off = NFP_NET_CFG_MBOX_BASE;
+ caps->mbox_len = NFP_NET_CFG_MBOX_VAL_MAX_SZ;
+}
+
+int
+nfp_net_tlv_caps_parse(struct rte_eth_dev *dev)
+{
+ uint32_t hdr;
+ uint8_t *end;
+ uint8_t *data;
+ uint32_t length;
+ uint32_t offset;
+ uint32_t tlv_type;
+ uint32_t tlv_offset;
+ struct nfp_net_hw *hw;
+ struct nfp_net_tlv_caps *caps;
+
+ hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ caps = &hw->tlv_caps;
+ nfp_net_tlv_caps_reset(caps);
+
+ data = hw->ctrl_bar + NFP_NET_CFG_TLV_BASE;
+ end = hw->ctrl_bar + NFP_NET_CFG_BAR_SZ;
+
+ hdr = rte_read32(data);
+ if (hdr == 0) {
+ PMD_DRV_LOG(INFO, "TLV is empty!");
+ return 0;
+ }
+
+ for (; ; data += length) {
+ offset = data - hw->ctrl_bar;
+
+ if (data + NFP_NET_CFG_TLV_VALUE > end) {
+ PMD_DRV_LOG(ERR, "Reached end of BAR without END TLV");
+ return -EINVAL;
+ }
+
+ hdr = rte_read32(data);
+
+ length = FIELD_GET(NFP_NET_CFG_TLV_HEADER_LENGTH, hdr);
+ if ((length & (NFP_NET_CFG_TLV_LENGTH_INC - 1)) != 0) {
+ PMD_DRV_LOG(ERR, "TLV size not multiple of 4B len: %u", length);
+ return -EINVAL;
+ }
+
+ /* Advance past the header */
+ data += NFP_NET_CFG_TLV_VALUE;
+ if (data + length > end) {
+ PMD_DRV_LOG(ERR, "Oversized TLV offset: %u len: %u",
+ offset, length);
+ return -EINVAL;
+ }
+
+ tlv_type = FIELD_GET(NFP_NET_CFG_TLV_HEADER_TYPE, hdr);
+
+ switch (tlv_type) {
+ case NFP_NET_CFG_TLV_TYPE_UNKNOWN:
+ PMD_DRV_LOG(ERR, "Unknown TLV at offset: %u", offset);
+ return -EINVAL;
+ case NFP_NET_CFG_TLV_TYPE_RESERVED:
+ break;
+ case NFP_NET_CFG_TLV_TYPE_END:
+ if (length == 0)
+ return 0;
+
+ PMD_DRV_LOG(ERR, "END TLV should be empty, has len: %u", length);
+ return -EINVAL;
+ case NFP_NET_CFG_TLV_TYPE_ME_FREQ:
+ if (length != NFP_NET_CFG_TLV_LENGTH_INC) {
+ PMD_DRV_LOG(ERR, "ME FREQ TLV should be 4B, is %u", length);
+ return -EINVAL;
+ }
+
+ caps->me_freq_mhz = rte_read32(data);
+ break;
+ case NFP_NET_CFG_TLV_TYPE_MBOX:
+ caps->mbox_len = length;
+
+ if (length != 0)
+ caps->mbox_off = data - hw->ctrl_bar;
+ else
+ caps->mbox_off = 0;
+ break;
+ case NFP_NET_CFG_TLV_TYPE_EXPERIMENTAL0:
+ /* FALLTHROUGH */
+ case NFP_NET_CFG_TLV_TYPE_EXPERIMENTAL1:
+ PMD_DRV_LOG(ERR, "Experimental TLV type: %u offset: %u len: %u",
+ tlv_type, offset, length);
+ /* Skip, not process */
+ break;
+ case NFP_NET_CFG_TLV_TYPE_REPR_CAP:
+ if (length == 0) {
+ PMD_DRV_LOG(ERR, "REPR CAP TLV with length 0");
+ return -EINVAL;
+ }
+
+ caps->repr_cap = rte_read32(data);
+ break;
+ case NFP_NET_CFG_TLV_TYPE_MBOX_CMSG_TYPES:
+ if (length != 0)
+ caps->mbox_cmsg_types = rte_read32(data);
+ break;
+ case NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS:
+ break;
+ case NFP_NET_CFG_TLV_TYPE_VNIC_STATS:
+ tlv_offset = data - hw->ctrl_bar;
+ if ((tlv_offset & (NFP_NET_CFG_TLV_STATS_OFFSET - 1)) != 0) {
+ PMD_DRV_LOG(ERR, "VNIC STATS TLV misaligned, ignoring offset: %u len: %u",
+ offset, length);
+ break;
+ }
+
+ caps->vnic_stats_off = tlv_offset;
+ caps->vnic_stats_cnt = length / 10;
+ break;
+ case NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS_RX_SCAN:
+ break;
+ default:
+ if (FIELD_GET(NFP_NET_CFG_TLV_HEADER_REQUIRED, hdr) == 0)
+ break;
+
+ PMD_DRV_LOG(ERR, "Unknown TLV type: %u offset: %u len: %u",
+ tlv_type, offset, length);
+ return -EINVAL;
+ }
+ }
+
+ PMD_DRV_LOG(ERR, "Reached end of BAR without END TLV");
+ return -EINVAL;
+}
diff --git a/drivers/net/nfp/nfp_ctrl.h b/drivers/net/nfp/nfp_ctrl.h
index 53727992a9..80a4196bea 100644
--- a/drivers/net/nfp/nfp_ctrl.h
+++ b/drivers/net/nfp/nfp_ctrl.h
@@ -8,6 +8,8 @@
#include <stdint.h>
+#include <ethdev_driver.h>
+
/*
* Configuration BAR size.
*
@@ -207,6 +209,9 @@ struct nfp_net_fw_ver {
#define NFP_NET_CFG_RX_OFFSET 0x0050
#define NFP_NET_CFG_RX_OFFSET_DYNAMIC 0 /* Prepend mode */
+/* Start anchor of the TLV area */
+#define NFP_NET_CFG_TLV_BASE 0x0058
+
/**
* Reuse spare address to contain the offset from the start of
* the host buffer where the first byte of the received frame
@@ -434,6 +439,122 @@ struct nfp_net_fw_ver {
#define NFP_PF_CSR_SLICE_SIZE (32 * 1024)
+/*
+ * General use mailbox area (0x1800 - 0x19ff)
+ * 4B used for update command and 4B return code followed by
+ * a max of 504B of variable length value.
+ */
+#define NFP_NET_CFG_MBOX_BASE 0x1800
+#define NFP_NET_CFG_MBOX_VAL 0x1808
+#define NFP_NET_CFG_MBOX_VAL_MAX_SZ 0x1F8
+
+/*
+ * TLV capabilities
+ * @NFP_NET_CFG_TLV_TYPE: Offset of type within the TLV
+ * @NFP_NET_CFG_TLV_TYPE_REQUIRED: Driver must be able to parse the TLV
+ * @NFP_NET_CFG_TLV_LENGTH: Offset of length within the TLV
+ * @NFP_NET_CFG_TLV_LENGTH_INC: TLV length increments
+ * @NFP_NET_CFG_TLV_VALUE: Offset of value with the TLV
+ * @NFP_NET_CFG_TLV_STATS_OFFSET: Length of TLV stats offset
+ *
+ * List of simple TLV structures, first one starts at @NFP_NET_CFG_TLV_BASE.
+ * Last structure must be of type @NFP_NET_CFG_TLV_TYPE_END. Presence of TLVs
+ * is indicated by @NFP_NET_CFG_TLV_BASE being non-zero. TLV structures may
+ * fill the entire remainder of the BAR or be shorter. FW must make sure TLVs
+ * don't conflict with other features which allocate space beyond
+ * @NFP_NET_CFG_TLV_BASE. @NFP_NET_CFG_TLV_TYPE_RESERVED should be used to wrap
+ * space used by such features.
+ *
+ * Note that the 4 byte TLV header is not counted in %NFP_NET_CFG_TLV_LENGTH.
+ */
+#define NFP_NET_CFG_TLV_TYPE 0x00
+#define NFP_NET_CFG_TLV_TYPE_REQUIRED 0x8000
+#define NFP_NET_CFG_TLV_LENGTH 0x02
+#define NFP_NET_CFG_TLV_LENGTH_INC 4
+#define NFP_NET_CFG_TLV_VALUE 0x04
+#define NFP_NET_CFG_TLV_STATS_OFFSET 0x08
+
+#define NFP_NET_CFG_TLV_HEADER_REQUIRED 0x80000000
+#define NFP_NET_CFG_TLV_HEADER_TYPE 0x7fff0000
+#define NFP_NET_CFG_TLV_HEADER_LENGTH 0x0000ffff
+
+/*
+ * Capability TLV types
+ *
+ * @NFP_NET_CFG_TLV_TYPE_UNKNOWN:
+ * Special TLV type to catch bugs, should never be encountered. Drivers should
+ * treat encountering this type as error and refuse to probe.
+ *
+ * @NFP_NET_CFG_TLV_TYPE_RESERVED:
+ * Reserved space, may contain legacy fixed-offset fields, or be used for
+ * padding. The use of this type should be otherwise avoided.
+ *
+ * @NFP_NET_CFG_TLV_TYPE_END:
+ * Empty, end of TLV list. Must be the last TLV. Drivers will stop processing
+ * further TLVs when encountered.
+ *
+ * @NFP_NET_CFG_TLV_TYPE_ME_FREQ:
+ * Single word, ME frequency in MHz as used in calculation for
+ * @NFP_NET_CFG_RXR_IRQ_MOD and @NFP_NET_CFG_TXR_IRQ_MOD.
+ *
+ * @NFP_NET_CFG_TLV_TYPE_MBOX:
+ * Variable, mailbox area. Overwrites the default location which is
+ * @NFP_NET_CFG_MBOX_BASE and length @NFP_NET_CFG_MBOX_VAL_MAX_SZ.
+ *
+ * @NFP_NET_CFG_TLV_TYPE_EXPERIMENTAL0:
+ * @NFP_NET_CFG_TLV_TYPE_EXPERIMENTAL1:
+ * Variable, experimental IDs. IDs designated for internal development and
+ * experiments before a stable TLV ID has been allocated to a feature. Should
+ * never be present in production FW.
+ *
+ * @NFP_NET_CFG_TLV_TYPE_REPR_CAP:
+ * Single word, equivalent of %NFP_NET_CFG_CAP for representors, features which
+ * can be used on representors.
+ *
+ * @NFP_NET_CFG_TLV_TYPE_MBOX_CMSG_TYPES:
+ * Variable, bitmap of control message types supported by the mailbox handler.
+ * Bit 0 corresponds to message type 0, bit 1 to 1, etc. Control messages are
+ * encapsulated into simple TLVs, with an end TLV and written to the Mailbox.
+ *
+ * @NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS:
+ * 8 words, bitmaps of supported and enabled crypto operations.
+ * First 16B (4 words) contains a bitmap of supported crypto operations,
+ * and next 16B contain the enabled operations.
+ * This capability is obsoleted by ones with better sync methods.
+ *
+ * @NFP_NET_CFG_TLV_TYPE_VNIC_STATS:
+ * Variable, per-vNIC statistics, data should be 8B aligned (FW should insert
+ * zero-length RESERVED TLV to pad).
+ * TLV data has two sections. First is an array of statistics' IDs (2B each).
+ * Second 8B statistics themselves. Statistics are 8B aligned, meaning there
+ * may be a padding between sections.
+ * Number of statistics can be determined as floor(tlv.length / (2 + 8)).
+ * This TLV overwrites %NFP_NET_CFG_STATS_* values (statistics in this TLV
+ * duplicate the old ones, so driver should be careful not to unnecessarily
+ * render both).
+ *
+ * @NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS_RX_SCAN:
+ * Same as %NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS, but crypto TLS does stream scan
+ * RX sync, rather than kernel-assisted sync.
+ *
+ * @NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS_LENGTH:
+ * CRYPTO OPS TLV should be at least 32B.
+ */
+#define NFP_NET_CFG_TLV_TYPE_UNKNOWN 0
+#define NFP_NET_CFG_TLV_TYPE_RESERVED 1
+#define NFP_NET_CFG_TLV_TYPE_END 2
+#define NFP_NET_CFG_TLV_TYPE_ME_FREQ 3
+#define NFP_NET_CFG_TLV_TYPE_MBOX 4
+#define NFP_NET_CFG_TLV_TYPE_EXPERIMENTAL0 5
+#define NFP_NET_CFG_TLV_TYPE_EXPERIMENTAL1 6
+#define NFP_NET_CFG_TLV_TYPE_REPR_CAP 7
+#define NFP_NET_CFG_TLV_TYPE_MBOX_CMSG_TYPES 10
+#define NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS 11
+#define NFP_NET_CFG_TLV_TYPE_VNIC_STATS 12
+#define NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS_RX_SCAN 13
+
+int nfp_net_tlv_caps_parse(struct rte_eth_dev *dev);
+
/*
* nfp_net_cfg_ctrl_rss() - Get RSS flag based on firmware's capability
* @hw_cap: The firmware's capabilities
diff --git a/drivers/net/nfp/nfp_ethdev.c b/drivers/net/nfp/nfp_ethdev.c
index 241595be9d..7dc93f7c43 100644
--- a/drivers/net/nfp/nfp_ethdev.c
+++ b/drivers/net/nfp/nfp_ethdev.c
@@ -549,6 +549,12 @@ nfp_net_init(struct rte_eth_dev *eth_dev)
if (err != 0)
return err;
+ err = nfp_net_tlv_caps_parse(eth_dev);
+ if (err != 0) {
+ PMD_INIT_LOG(ERR, "Failed to parser TLV caps");
+ return err;
+ }
+
nfp_net_ethdev_ops_mount(hw, eth_dev);
hw->eth_xstats_base = rte_malloc("rte_eth_xstat", sizeof(struct rte_eth_xstat) *
--
2.39.1
^ permalink raw reply [flat|nested] 42+ messages in thread
* [PATCH v2 03/10] net/nfp: add mailbox to support IPsec offload
2023-09-26 2:49 ` [PATCH v2 00/10] add the support of ipsec offload Chaoyong He
2023-09-26 2:49 ` [PATCH v2 01/10] mailmap: update contributor entry Chaoyong He
2023-09-26 2:49 ` [PATCH v2 02/10] net/nfp: add TLVs capability parsing Chaoyong He
@ 2023-09-26 2:49 ` Chaoyong He
2023-09-26 2:49 ` [PATCH v2 04/10] net/nfp: initialize IPsec related content Chaoyong He
` (8 subsequent siblings)
11 siblings, 0 replies; 42+ messages in thread
From: Chaoyong He @ 2023-09-26 2:49 UTC (permalink / raw)
To: dev; +Cc: oss-drivers, Shihong Wang, Chang Miao, Chaoyong He
From: Shihong Wang <shihong.wang@corigine.com>
Add general use per-vNIC mailbox area and use it for IPsec SA
offload support and get Rx/Tx packet statistics.
Signed-off-by: Shihong Wang <shihong.wang@corigine.com>
Signed-off-by: Chang Miao <chang.miao@corigine.com>
Reviewed-by: Chaoyong He <chaoyong.he@corigine.com>
---
drivers/net/nfp/nfp_common.c | 41 ++++++++++++++++++++++++++++++++++++
drivers/net/nfp/nfp_common.h | 1 +
drivers/net/nfp/nfp_ctrl.h | 6 ++++++
3 files changed, 48 insertions(+)
diff --git a/drivers/net/nfp/nfp_common.c b/drivers/net/nfp/nfp_common.c
index 40027dbdfc..31dab3ae9b 100644
--- a/drivers/net/nfp/nfp_common.c
+++ b/drivers/net/nfp/nfp_common.c
@@ -320,6 +320,47 @@ nfp_net_ext_reconfig(struct nfp_net_hw *hw, uint32_t ctrl_ext, uint32_t update)
return 0;
}
+/**
+ * Reconfigure the firmware via the mailbox
+ *
+ * @param hw
+ * Device to reconfigure
+ * @param mbox_cmd
+ * The value for the mailbox command
+ *
+ * @return
+ * - (0) if OK to reconfigure by the mailbox.
+ * - (-EIO) if I/O err and fail to reconfigure by the mailbox
+ */
+int
+nfp_net_mbox_reconfig(struct nfp_net_hw *hw,
+ uint32_t mbox_cmd)
+{
+ int ret;
+ uint32_t mbox;
+
+ mbox = hw->tlv_caps.mbox_off;
+
+ rte_spinlock_lock(&hw->reconfig_lock);
+
+ nn_cfg_writeq(hw, mbox + NFP_NET_CFG_MBOX_SIMPLE_CMD, mbox_cmd);
+ nn_cfg_writel(hw, NFP_NET_CFG_UPDATE, NFP_NET_CFG_UPDATE_MBOX);
+
+ rte_wmb();
+
+ ret = __nfp_net_reconfig(hw, NFP_NET_CFG_UPDATE_MBOX);
+
+ rte_spinlock_unlock(&hw->reconfig_lock);
+
+ if (ret != 0) {
+ PMD_DRV_LOG(ERR, "Error nft net mailbox reconfig: mbox=%#08x update=%#08x",
+ mbox_cmd, NFP_NET_CFG_UPDATE_MBOX);
+ return -EIO;
+ }
+
+ return nn_cfg_readl(hw, mbox + NFP_NET_CFG_MBOX_SIMPLE_RET);
+}
+
/*
* Configure an Ethernet device. This function must be invoked first
* before any other function in the Ethernet API. This function can
diff --git a/drivers/net/nfp/nfp_common.h b/drivers/net/nfp/nfp_common.h
index 4a19c18466..64f0af94c1 100644
--- a/drivers/net/nfp/nfp_common.h
+++ b/drivers/net/nfp/nfp_common.h
@@ -335,6 +335,7 @@ nfp_qcp_queue_offset(const struct nfp_dev_info *dev_info,
/* Prototypes for common NFP functions */
int nfp_net_reconfig(struct nfp_net_hw *hw, uint32_t ctrl, uint32_t update);
int nfp_net_ext_reconfig(struct nfp_net_hw *hw, uint32_t ctrl_ext, uint32_t update);
+int nfp_net_mbox_reconfig(struct nfp_net_hw *hw, uint32_t mbox_cmd);
int nfp_net_configure(struct rte_eth_dev *dev);
int nfp_net_common_init(struct rte_pci_device *pci_dev, struct nfp_net_hw *hw);
void nfp_net_log_device_information(const struct nfp_net_hw *hw);
diff --git a/drivers/net/nfp/nfp_ctrl.h b/drivers/net/nfp/nfp_ctrl.h
index 80a4196bea..d539846d02 100644
--- a/drivers/net/nfp/nfp_ctrl.h
+++ b/drivers/net/nfp/nfp_ctrl.h
@@ -123,6 +123,7 @@
#define NFP_NET_CFG_UPDATE_IRQMOD (0x1 << 8) /* IRQ mod change */
#define NFP_NET_CFG_UPDATE_VXLAN (0x1 << 9) /* VXLAN port change */
#define NFP_NET_CFG_UPDATE_MACADDR (0x1 << 11) /* MAC address change */
+#define NFP_NET_CFG_UPDATE_MBOX (0x1 << 12) /**< Mailbox update */
#define NFP_NET_CFG_UPDATE_ERR (0x1U << 31) /* A error occurred */
#define NFP_NET_CFG_TXRS_ENABLE 0x0008
#define NFP_NET_CFG_RXRS_ENABLE 0x0010
@@ -447,6 +448,11 @@ struct nfp_net_fw_ver {
#define NFP_NET_CFG_MBOX_BASE 0x1800
#define NFP_NET_CFG_MBOX_VAL 0x1808
#define NFP_NET_CFG_MBOX_VAL_MAX_SZ 0x1F8
+#define NFP_NET_CFG_MBOX_SIMPLE_CMD 0x0
+#define NFP_NET_CFG_MBOX_SIMPLE_RET 0x4
+#define NFP_NET_CFG_MBOX_SIMPLE_VAL 0x8
+
+#define NFP_NET_CFG_MBOX_CMD_IPSEC 3
/*
* TLV capabilities
--
2.39.1
^ permalink raw reply [flat|nested] 42+ messages in thread
* [PATCH v2 04/10] net/nfp: initialize IPsec related content
2023-09-26 2:49 ` [PATCH v2 00/10] add the support of ipsec offload Chaoyong He
` (2 preceding siblings ...)
2023-09-26 2:49 ` [PATCH v2 03/10] net/nfp: add mailbox to support IPsec offload Chaoyong He
@ 2023-09-26 2:49 ` Chaoyong He
2023-09-26 2:49 ` [PATCH v2 05/10] net/nfp: get security capabilities and session size Chaoyong He
` (7 subsequent siblings)
11 siblings, 0 replies; 42+ messages in thread
From: Chaoyong He @ 2023-09-26 2:49 UTC (permalink / raw)
To: dev; +Cc: oss-drivers, Chang Miao, Shihong Wang, Chaoyong He
From: Chang Miao <chang.miao@corigine.com>
If enable IPsec capability bit, driver need to Initialize IPsec.
Set security context and security offload capabilities in datapath.
Define private session and add SA array for each PF to save all
SA data in driver. Add internal mbuf dynamic flag and field to save
IPsec related data to dynamic mbuf field.
Signed-off-by: Chang Miao <chang.miao@corigine.com>
Signed-off-by: Shihong Wang <shihong.wang@corigine.com>
Reviewed-by: Chaoyong He <chaoyong.he@corigine.com>
---
drivers/net/nfp/meson.build | 3 +-
drivers/net/nfp/nfp_common.c | 7 ++
drivers/net/nfp/nfp_common.h | 2 +
drivers/net/nfp/nfp_ctrl.h | 3 +
drivers/net/nfp/nfp_ethdev.c | 15 ++++
drivers/net/nfp/nfp_ipsec.c | 131 +++++++++++++++++++++++++++
drivers/net/nfp/nfp_ipsec.h | 169 +++++++++++++++++++++++++++++++++++
drivers/net/nfp/nfp_rxtx.h | 12 +++
8 files changed, 341 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/nfp/nfp_ipsec.c
create mode 100644 drivers/net/nfp/nfp_ipsec.h
diff --git a/drivers/net/nfp/meson.build b/drivers/net/nfp/meson.build
index e78bcb8b75..3912566134 100644
--- a/drivers/net/nfp/meson.build
+++ b/drivers/net/nfp/meson.build
@@ -33,8 +33,9 @@ sources = files(
'nfp_ethdev_vf.c',
'nfp_ethdev.c',
'nfp_flow.c',
+ 'nfp_ipsec.c',
'nfp_logs.c',
'nfp_mtr.c',
)
-deps += ['hash']
+deps += ['hash', 'security']
diff --git a/drivers/net/nfp/nfp_common.c b/drivers/net/nfp/nfp_common.c
index 31dab3ae9b..5683afc40a 100644
--- a/drivers/net/nfp/nfp_common.c
+++ b/drivers/net/nfp/nfp_common.c
@@ -1200,6 +1200,7 @@ nfp_net_tx_desc_limits(struct nfp_net_hw *hw,
int
nfp_net_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
{
+ uint32_t cap_extend;
uint16_t min_rx_desc;
uint16_t max_rx_desc;
uint16_t min_tx_desc;
@@ -1256,6 +1257,12 @@ nfp_net_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
if (hw->cap & NFP_NET_CFG_CTRL_GATHER)
dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_MULTI_SEGS;
+ cap_extend = nn_cfg_readl(hw, NFP_NET_CFG_CAP_WORD1);
+ if ((cap_extend & NFP_NET_CFG_CTRL_IPSEC) != 0) {
+ dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_SECURITY;
+ dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_SECURITY;
+ }
+
dev_info->default_rxconf = (struct rte_eth_rxconf) {
.rx_thresh = {
.pthresh = DEFAULT_RX_PTHRESH,
diff --git a/drivers/net/nfp/nfp_common.h b/drivers/net/nfp/nfp_common.h
index 64f0af94c1..b434b031cc 100644
--- a/drivers/net/nfp/nfp_common.h
+++ b/drivers/net/nfp/nfp_common.h
@@ -176,6 +176,8 @@ struct nfp_net_hw {
uint8_t nfp_idx;
struct nfp_net_tlv_caps tlv_caps;
+
+ struct nfp_net_ipsec_data *ipsec_data;
};
struct nfp_net_adapter {
diff --git a/drivers/net/nfp/nfp_ctrl.h b/drivers/net/nfp/nfp_ctrl.h
index d539846d02..361739a4b9 100644
--- a/drivers/net/nfp/nfp_ctrl.h
+++ b/drivers/net/nfp/nfp_ctrl.h
@@ -238,6 +238,9 @@ struct nfp_net_fw_ver {
*/
#define NFP_NET_CFG_CTRL_WORD1 0x0098
#define NFP_NET_CFG_CTRL_PKT_TYPE (0x1 << 0)
+#define NFP_NET_CFG_CTRL_IPSEC (0x1 << 1) /**< IPsec offload */
+#define NFP_NET_CFG_CTRL_IPSEC_SM_LOOKUP (0x1 << 3) /**< SA short match lookup */
+#define NFP_NET_CFG_CTRL_IPSEC_LM_LOOKUP (0x1 << 4) /**< SA long match lookup */
#define NFP_NET_CFG_CAP_WORD1 0x00a4
diff --git a/drivers/net/nfp/nfp_ethdev.c b/drivers/net/nfp/nfp_ethdev.c
index 7dc93f7c43..ebc5538291 100644
--- a/drivers/net/nfp/nfp_ethdev.c
+++ b/drivers/net/nfp/nfp_ethdev.c
@@ -18,6 +18,7 @@
#include "nfpcore/nfp6000_pcie.h"
#include "nfp_cpp_bridge.h"
+#include "nfp_ipsec.h"
#include "nfp_logs.h"
static int
@@ -140,6 +141,10 @@ nfp_net_start(struct rte_eth_dev *dev)
if ((cap_extend & NFP_NET_CFG_CTRL_PKT_TYPE) != 0)
ctrl_extend = NFP_NET_CFG_CTRL_PKT_TYPE;
+ if ((cap_extend & NFP_NET_CFG_CTRL_IPSEC) != 0)
+ ctrl_extend |= NFP_NET_CFG_CTRL_IPSEC_SM_LOOKUP
+ | NFP_NET_CFG_CTRL_IPSEC_LM_LOOKUP;
+
update = NFP_NET_CFG_UPDATE_GEN;
if (nfp_net_ext_reconfig(hw, ctrl_extend, update) < 0)
return -EIO;
@@ -278,6 +283,9 @@ nfp_net_close(struct rte_eth_dev *dev)
nfp_net_close_rx_queue(dev);
+ /* Clear ipsec */
+ nfp_ipsec_uninit(dev);
+
/* Cancel possible impending LSC work here before releasing the port*/
rte_eal_alarm_cancel(nfp_net_dev_interrupt_delayed_handler,
(void *)dev);
@@ -555,6 +563,12 @@ nfp_net_init(struct rte_eth_dev *eth_dev)
return err;
}
+ err = nfp_ipsec_init(eth_dev);
+ if (err != 0) {
+ PMD_INIT_LOG(ERR, "Failed to init IPsec module");
+ return err;
+ }
+
nfp_net_ethdev_ops_mount(hw, eth_dev);
hw->eth_xstats_base = rte_malloc("rte_eth_xstat", sizeof(struct rte_eth_xstat) *
@@ -867,6 +881,7 @@ nfp_init_app_fw_nic(struct nfp_pf_dev *pf_dev,
if (app_fw_nic->ports[i] && app_fw_nic->ports[i]->eth_dev) {
struct rte_eth_dev *tmp_dev;
tmp_dev = app_fw_nic->ports[i]->eth_dev;
+ nfp_ipsec_uninit(tmp_dev);
rte_eth_dev_release_port(tmp_dev);
app_fw_nic->ports[i] = NULL;
}
diff --git a/drivers/net/nfp/nfp_ipsec.c b/drivers/net/nfp/nfp_ipsec.c
new file mode 100644
index 0000000000..f16ce97703
--- /dev/null
+++ b/drivers/net/nfp/nfp_ipsec.c
@@ -0,0 +1,131 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2023 Corigine Systems, Inc.
+ * All rights reserved.
+ */
+
+#include "nfp_ipsec.h"
+
+#include <rte_malloc.h>
+#include <rte_security_driver.h>
+
+#include <ethdev_driver.h>
+#include <ethdev_pci.h>
+
+#include "nfp_common.h"
+#include "nfp_ctrl.h"
+#include "nfp_logs.h"
+#include "nfp_rxtx.h"
+
+static const struct rte_security_ops nfp_security_ops;
+
+static int
+nfp_ipsec_ctx_create(struct rte_eth_dev *dev,
+ struct nfp_net_ipsec_data *data)
+{
+ struct rte_security_ctx *ctx;
+ static const struct rte_mbuf_dynfield pkt_md_dynfield = {
+ .name = "nfp_ipsec_crypto_pkt_metadata",
+ .size = sizeof(struct nfp_tx_ipsec_desc_msg),
+ .align = __alignof__(struct nfp_tx_ipsec_desc_msg),
+ };
+
+ ctx = rte_zmalloc("security_ctx",
+ sizeof(struct rte_security_ctx), 0);
+ if (ctx == NULL) {
+ PMD_INIT_LOG(ERR, "Failed to malloc security_ctx");
+ return -ENOMEM;
+ }
+
+ ctx->device = dev;
+ ctx->ops = &nfp_security_ops;
+ ctx->sess_cnt = 0;
+ dev->security_ctx = ctx;
+
+ data->pkt_dynfield_offset = rte_mbuf_dynfield_register(&pkt_md_dynfield);
+ if (data->pkt_dynfield_offset < 0) {
+ PMD_INIT_LOG(ERR, "Failed to register mbuf esn_dynfield");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+int
+nfp_ipsec_init(struct rte_eth_dev *dev)
+{
+ int ret;
+ uint32_t cap_extend;
+ struct nfp_net_hw *hw;
+ struct nfp_net_ipsec_data *data;
+
+ hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+ cap_extend = nn_cfg_readl(hw, NFP_NET_CFG_CAP_WORD1);
+ if ((cap_extend & NFP_NET_CFG_CTRL_IPSEC) == 0) {
+ PMD_INIT_LOG(INFO, "Unsupported IPsec extend capability");
+ return 0;
+ }
+
+ data = rte_zmalloc("ipsec_data", sizeof(struct nfp_net_ipsec_data), 0);
+ if (data == NULL) {
+ PMD_INIT_LOG(ERR, "Failed to malloc ipsec_data");
+ return -ENOMEM;
+ }
+
+ data->pkt_dynfield_offset = -1;
+ data->sa_free_cnt = NFP_NET_IPSEC_MAX_SA_CNT;
+ hw->ipsec_data = data;
+
+ ret = nfp_ipsec_ctx_create(dev, data);
+ if (ret != 0) {
+ PMD_INIT_LOG(ERR, "Failed to create IPsec ctx");
+ goto ipsec_cleanup;
+ }
+
+ return 0;
+
+ipsec_cleanup:
+ nfp_ipsec_uninit(dev);
+
+ return ret;
+}
+
+static void
+nfp_ipsec_ctx_destroy(struct rte_eth_dev *dev)
+{
+ if (dev->security_ctx != NULL)
+ rte_free(dev->security_ctx);
+}
+
+void
+nfp_ipsec_uninit(struct rte_eth_dev *dev)
+{
+ uint16_t i;
+ uint32_t cap_extend;
+ struct nfp_net_hw *hw;
+ struct nfp_ipsec_session *priv_session;
+
+ hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+ cap_extend = nn_cfg_readl(hw, NFP_NET_CFG_CAP_WORD1);
+ if ((cap_extend & NFP_NET_CFG_CTRL_IPSEC) == 0) {
+ PMD_INIT_LOG(INFO, "Unsupported IPsec extend capability");
+ return;
+ }
+
+ nfp_ipsec_ctx_destroy(dev);
+
+ if (hw->ipsec_data == NULL) {
+ PMD_INIT_LOG(INFO, "IPsec data is NULL!");
+ return;
+ }
+
+ for (i = 0; i < NFP_NET_IPSEC_MAX_SA_CNT; i++) {
+ priv_session = hw->ipsec_data->sa_entries[i];
+ if (priv_session != NULL)
+ memset(priv_session, 0, sizeof(struct nfp_ipsec_session));
+ }
+
+ rte_free(hw->ipsec_data);
+}
+
diff --git a/drivers/net/nfp/nfp_ipsec.h b/drivers/net/nfp/nfp_ipsec.h
new file mode 100644
index 0000000000..531bc60c5a
--- /dev/null
+++ b/drivers/net/nfp/nfp_ipsec.h
@@ -0,0 +1,169 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2023 Corigine Systems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef __NFP_IPSEC_H__
+#define __NFP_IPSEC_H__
+
+#include <rte_security.h>
+
+#define NFP_NET_IPSEC_MAX_SA_CNT (16 * 1024)
+
+struct ipsec_aesgcm { /**< AES-GCM-ESP fields */
+ uint32_t salt; /**< Initialized with SA */
+ uint32_t iv[2]; /**< Firmware use only */
+ uint32_t cntrl;
+ uint32_t zeros[4]; /**< Init to 0 with SA */
+ uint32_t len_auth[2]; /**< Firmware use only */
+ uint32_t len_cipher[2];
+ uint32_t spare[4];
+};
+
+struct sa_ctrl_word {
+ uint32_t hash :4; /**< From nfp_ipsec_hash_type */
+ uint32_t cimode :4; /**< From nfp_ipsec_cipher_mode */
+ uint32_t cipher :4; /**< From nfp_ipsec_cipher */
+ uint32_t mode :2; /**< From nfp_ipsec_mode */
+ uint32_t proto :2; /**< From nfp_ipsec_prot */
+ uint32_t spare :1; /**< Should be 0 */
+ uint32_t ena_arw:1; /**< Anti-Replay Window */
+ uint32_t ext_seq:1; /**< 64-bit Sequence Num */
+ uint32_t ext_arw:1; /**< 64b Anti-Replay Window */
+ uint32_t spare1 :9; /**< Must be set to 0 */
+ uint32_t encap_dsbl:1; /**< Encap/decap disable */
+ uint32_t gen_seq:1; /**< Firmware Generate Seq #'s */
+ uint32_t spare2 :1; /**< Must be set to 0 */
+};
+
+struct ipsec_add_sa {
+ uint32_t cipher_key[8]; /**< Cipher Key */
+ union {
+ uint32_t auth_key[16]; /**< Authentication Key */
+ struct ipsec_aesgcm aesgcm_fields;
+ };
+ struct sa_ctrl_word ctrl_word;
+ uint32_t spi; /**< SPI Value */
+ uint16_t pmtu_limit; /**< PMTU Limit */
+ uint32_t spare :1;
+ uint32_t frag_check :1; /**< Stateful fragment checking flag */
+ uint32_t bypass_DSCP:1; /**< Bypass DSCP Flag */
+ uint32_t df_ctrl :2; /**< DF Control bits */
+ uint32_t ipv6 :1; /**< Outbound IPv6 addr format */
+ uint32_t udp_enable :1; /**< Add/Remove UDP header for NAT */
+ uint32_t tfc_enable :1; /**< Traffic Flw Confidentiality */
+ uint8_t spare1;
+ uint32_t soft_byte_cnt; /**< Soft lifetime byte count */
+ uint32_t hard_byte_cnt; /**< Hard lifetime byte count */
+ uint32_t src_ip[4]; /**< Src IP addr */
+ uint32_t dst_ip[4]; /**< Dst IP addr */
+ uint16_t natt_dst_port; /**< NAT-T UDP Header dst port */
+ uint16_t natt_src_port; /**< NAT-T UDP Header src port */
+ uint32_t soft_lifetime_limit; /**< Soft lifetime time limit */
+ uint32_t hard_lifetime_limit; /**< Hard lifetime time limit */
+ uint32_t sa_time_lo; /**< SA creation time lower 32bits, Ucode fills this in */
+ uint32_t sa_time_hi; /**< SA creation time high 32bits, Ucode fills this in */
+ uint16_t spare2;
+ uint16_t tfc_padding; /**< Traffic Flow Confidential Pad */
+};
+
+struct ipsec_inv_sa {
+ uint32_t spare;
+};
+
+struct ipsec_discard_stats {
+ uint32_t discards_auth; /**< Auth failures */
+ uint32_t discards_unsupported; /**< Unsupported crypto mode */
+ uint32_t discards_alignment; /**< Alignment error */
+ uint32_t discards_hard_bytelimit; /**< Hard byte Count limit */
+ uint32_t discards_seq_num_wrap; /**< Sequ Number wrap */
+ uint32_t discards_pmtu_exceeded; /**< PMTU Limit exceeded*/
+ uint32_t discards_arw_old_seq; /**< Anti-Replay seq small */
+ uint32_t discards_arw_replay; /**< Anti-Replay seq rcvd */
+ uint32_t discards_ctrl_word; /**< Bad SA Control word */
+ uint32_t discards_ip_hdr_len; /**< Hdr offset from too high */
+ uint32_t discards_eop_buf; /**< No EOP buffer */
+ uint32_t ipv4_id_counter; /**< IPv4 ID field counter */
+ uint32_t discards_isl_fail; /**< Inbound SPD Lookup failure */
+ uint32_t discards_ext_unfound; /**< Ext header end */
+ uint32_t discards_max_ext_hdrs; /**< Max ext header */
+ uint32_t discards_non_ext_hdrs; /**< Non-extension headers */
+ uint32_t discards_ext_hdr_too_big; /**< Ext header chain */
+ uint32_t discards_hard_timelimit; /**< Time Limit */
+};
+
+struct ipsec_get_sa_stats {
+ uint32_t seq_lo; /**< Sequence Number (low 32bits) */
+ uint32_t seq_high; /**< Sequence Number (high 32bits)*/
+ uint32_t arw_counter_lo; /**< Anti-replay wndw cntr */
+ uint32_t arw_counter_high; /**< Anti-replay wndw cntr */
+ uint32_t arw_bitmap_lo; /**< Anti-replay wndw bitmap */
+ uint32_t arw_bitmap_high; /**< Anti-replay wndw bitmap */
+ uint32_t spare:1;
+ uint32_t soft_byte_exceeded :1; /**< Soft lifetime byte cnt exceeded*/
+ uint32_t hard_byte_exceeded :1; /**< Hard lifetime byte cnt exceeded*/
+ uint32_t soft_time_exceeded :1; /**< Soft lifetime time limit exceeded*/
+ uint32_t hard_time_exceeded :1; /**< Hard lifetime time limit exceeded*/
+ uint32_t spare1:27;
+ uint32_t lifetime_byte_count;
+ uint32_t pkt_count;
+ struct ipsec_discard_stats sa_discard_stats;
+};
+
+struct ipsec_get_seq {
+ uint32_t seq_nums; /**< Sequence numbers to allocate */
+ uint32_t seq_num_low; /**< Return start seq num 31:00 */
+ uint32_t seq_num_hi; /**< Return start seq num 63:32 */
+};
+
+struct nfp_ipsec_msg {
+ union {
+ struct {
+ /** NFP IPsec SA cmd message codes */
+ uint16_t cmd;
+ /** NFP IPsec SA response message */
+ uint16_t rsp;
+ /** NFP IPsec SA index in driver SA table */
+ uint16_t sa_idx;
+ /** Reserved */
+ uint16_t spare;
+ union {
+ /** IPsec configure message for add SA */
+ struct ipsec_add_sa cfg_add_sa;
+ /** IPsec configure message for del SA */
+ struct ipsec_inv_sa cfg_inv_sa;
+ /** IPsec configure message for get SA stats */
+ struct ipsec_get_sa_stats cfg_get_stats;
+ /** IPsec configure message for get SA seq numbers */
+ struct ipsec_get_seq cfg_get_seq;
+ };
+ };
+ uint32_t raw[64];
+ };
+};
+
+struct nfp_ipsec_session {
+ /** Opaque user defined data */
+ void *user_data;
+ /** NFP sa_entries database parameter index */
+ uint32_t sa_index;
+ /** Point to physical ports ethernet device */
+ struct rte_eth_dev *dev;
+ /** SA related NPF configuration data */
+ struct ipsec_add_sa msg;
+ /** Security association configuration data */
+ struct rte_security_ipsec_xform ipsec;
+ /** Security session action type */
+ enum rte_security_session_action_type action;
+} __rte_cache_aligned;
+
+struct nfp_net_ipsec_data {
+ int pkt_dynfield_offset;
+ uint32_t sa_free_cnt;
+ struct nfp_ipsec_session *sa_entries[NFP_NET_IPSEC_MAX_SA_CNT];
+};
+
+int nfp_ipsec_init(struct rte_eth_dev *dev);
+void nfp_ipsec_uninit(struct rte_eth_dev *dev);
+
+#endif /* __NFP_IPSEC_H__ */
diff --git a/drivers/net/nfp/nfp_rxtx.h b/drivers/net/nfp/nfp_rxtx.h
index ddbf97e46c..4e8558074e 100644
--- a/drivers/net/nfp/nfp_rxtx.h
+++ b/drivers/net/nfp/nfp_rxtx.h
@@ -43,6 +43,18 @@ struct nfp_net_dp_buf {
struct rte_mbuf *mbuf;
};
+struct nfp_tx_ipsec_desc_msg {
+ uint32_t sa_idx; /**< SA index in driver table */
+ uint32_t enc; /**< IPsec enable flag */
+ union {
+ uint64_t value;
+ struct {
+ uint32_t low;
+ uint32_t hi;
+ };
+ } esn; /**< Extended Sequence Number */
+};
+
struct nfp_net_txq {
/** Backpointer to nfp_net structure */
struct nfp_net_hw *hw;
--
2.39.1
^ permalink raw reply [flat|nested] 42+ messages in thread
* [PATCH v2 05/10] net/nfp: get security capabilities and session size
2023-09-26 2:49 ` [PATCH v2 00/10] add the support of ipsec offload Chaoyong He
` (3 preceding siblings ...)
2023-09-26 2:49 ` [PATCH v2 04/10] net/nfp: initialize IPsec related content Chaoyong He
@ 2023-09-26 2:49 ` Chaoyong He
2023-09-26 2:49 ` [PATCH v2 06/10] net/nfp: get IPsec Rx/Tx packet statistics Chaoyong He
` (6 subsequent siblings)
11 siblings, 0 replies; 42+ messages in thread
From: Chaoyong He @ 2023-09-26 2:49 UTC (permalink / raw)
To: dev; +Cc: oss-drivers, Shihong Wang, Chaoyong He
From: Shihong Wang <shihong.wang@corigine.com>
Add full protocol offload as well as inline crypto IPsec
capabilities and return these for rte_security.
Return size of security session for rte_security.
Signed-off-by: Shihong Wang <shihong.wang@corigine.com>
Reviewed-by: Chaoyong He <chaoyong.he@corigine.com>
---
drivers/net/nfp/nfp_ipsec.c | 357 +++++++++++++++++++++++++++++++++++-
1 file changed, 356 insertions(+), 1 deletion(-)
diff --git a/drivers/net/nfp/nfp_ipsec.c b/drivers/net/nfp/nfp_ipsec.c
index f16ce97703..51770def9d 100644
--- a/drivers/net/nfp/nfp_ipsec.c
+++ b/drivers/net/nfp/nfp_ipsec.c
@@ -5,6 +5,7 @@
#include "nfp_ipsec.h"
+#include <rte_cryptodev.h>
#include <rte_malloc.h>
#include <rte_security_driver.h>
@@ -16,7 +17,361 @@
#include "nfp_logs.h"
#include "nfp_rxtx.h"
-static const struct rte_security_ops nfp_security_ops;
+static const struct rte_cryptodev_capabilities nfp_crypto_caps[] = {
+ {
+ .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ .sym = {
+ .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+ .auth = {
+ .algo = RTE_CRYPTO_AUTH_MD5_HMAC,
+ .block_size = 64,
+ .key_size = {
+ .min = 16,
+ .max = 16,
+ .increment = 0
+ },
+ .digest_size = {
+ .min = 12,
+ .max = 16,
+ .increment = 4
+ },
+ },
+ },
+ },
+ {
+ .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ .sym = {
+ .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+ .auth = {
+ .algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .block_size = 64,
+ .key_size = {
+ .min = 20,
+ .max = 64,
+ .increment = 1
+ },
+ .digest_size = {
+ .min = 10,
+ .max = 12,
+ .increment = 2
+ },
+ },
+ },
+ },
+ {
+ .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ .sym = {
+ .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+ .auth = {
+ .algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
+ .block_size = 64,
+ .key_size = {
+ .min = 32,
+ .max = 32,
+ .increment = 0
+ },
+ .digest_size = {
+ .min = 12,
+ .max = 16,
+ .increment = 4
+ },
+ },
+ },
+ },
+ {
+ .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ .sym = {
+ .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+ .auth = {
+ .algo = RTE_CRYPTO_AUTH_SHA384_HMAC,
+ .block_size = 128,
+ .key_size = {
+ .min = 48,
+ .max = 48,
+ .increment = 0
+ },
+ .digest_size = {
+ .min = 12,
+ .max = 24,
+ .increment = 12
+ },
+ },
+ },
+ },
+ {
+ .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ .sym = {
+ .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+ .auth = {
+ .algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
+ .block_size = 128,
+ .key_size = {
+ .min = 64,
+ .max = 64,
+ .increment = 1
+ },
+ .digest_size = {
+ .min = 12,
+ .max = 32,
+ .increment = 4
+ },
+ },
+ },
+ },
+ {
+ .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ .sym = {
+ .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+ .cipher = {
+ .algo = RTE_CRYPTO_CIPHER_3DES_CBC,
+ .block_size = 8,
+ .key_size = {
+ .min = 24,
+ .max = 24,
+ .increment = 0
+ },
+ .iv_size = {
+ .min = 8,
+ .max = 16,
+ .increment = 8
+ },
+ },
+ },
+ },
+ {
+ .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ .sym = {
+ .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+ .cipher = {
+ .algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .block_size = 16,
+ .key_size = {
+ .min = 16,
+ .max = 32,
+ .increment = 8
+ },
+ .iv_size = {
+ .min = 8,
+ .max = 16,
+ .increment = 8
+ },
+ },
+ },
+ },
+ {
+ .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 = 32,
+ .increment = 8
+ },
+ .digest_size = {
+ .min = 16,
+ .max = 16,
+ .increment = 0
+ },
+ .aad_size = {
+ .min = 0,
+ .max = 1024,
+ .increment = 1
+ },
+ .iv_size = {
+ .min = 8,
+ .max = 16,
+ .increment = 4
+ }
+ },
+ },
+ },
+ {
+ .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ .sym = {
+ .xform_type = RTE_CRYPTO_SYM_XFORM_AEAD,
+ .aead = {
+ .algo = RTE_CRYPTO_AEAD_CHACHA20_POLY1305,
+ .block_size = 16,
+ .key_size = {
+ .min = 32,
+ .max = 32,
+ .increment = 0
+ },
+ .digest_size = {
+ .min = 16,
+ .max = 16,
+ .increment = 0
+ },
+ .aad_size = {
+ .min = 0,
+ .max = 1024,
+ .increment = 1
+ },
+ .iv_size = {
+ .min = 8,
+ .max = 16,
+ .increment = 4
+ }
+ },
+ },
+ },
+ {
+ .op = RTE_CRYPTO_OP_TYPE_UNDEFINED,
+ .sym = {
+ .xform_type = RTE_CRYPTO_SYM_XFORM_NOT_SPECIFIED
+ },
+ }
+};
+
+static const struct rte_security_capability nfp_security_caps[] = {
+ { /* IPsec Inline Crypto Tunnel Egress */
+ .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+ .direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .options = {
+ .udp_encap = 1,
+ .stats = 1,
+ .esn = 1
+ }
+ },
+ .crypto_capabilities = nfp_crypto_caps
+ },
+ { /* IPsec Inline Crypto Tunnel Ingress */
+ .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+ .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .options = {
+ .udp_encap = 1,
+ .stats = 1,
+ .esn = 1
+ }
+ },
+ .crypto_capabilities = nfp_crypto_caps,
+ .ol_flags = RTE_SECURITY_TX_OLOAD_NEED_MDATA
+ },
+ { /* IPsec Inline Crypto Transport Egress */
+ .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
+ .direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .options = {
+ .udp_encap = 1,
+ .stats = 1,
+ .esn = 1
+ }
+ },
+ .crypto_capabilities = nfp_crypto_caps
+ },
+ { /* IPsec Inline Crypto Transport Ingress */
+ .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
+ .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .options = {
+ .udp_encap = 1,
+ .stats = 1,
+ .esn = 1
+ }
+ },
+ .crypto_capabilities = nfp_crypto_caps,
+ .ol_flags = RTE_SECURITY_TX_OLOAD_NEED_MDATA
+ },
+ { /* IPsec Inline Protocol Tunnel Egress */
+ .action = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+ .direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .options = {
+ .udp_encap = 1,
+ .stats = 1,
+ .esn = 1
+ }
+ },
+ .crypto_capabilities = nfp_crypto_caps
+ },
+ { /* IPsec Inline Protocol Tunnel Ingress */
+ .action = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+ .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .options = {
+ .udp_encap = 1,
+ .stats = 1,
+ .esn = 1
+ }
+ },
+ .crypto_capabilities = nfp_crypto_caps,
+ .ol_flags = RTE_SECURITY_TX_OLOAD_NEED_MDATA
+ },
+ { /* IPsec Inline Protocol Transport Egress */
+ .action = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
+ .direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .options = {
+ .udp_encap = 1,
+ .stats = 1,
+ .esn = 1
+ }
+ },
+ .crypto_capabilities = nfp_crypto_caps
+ },
+ { /* IPsec Inline Protocol Transport Ingress */
+ .action = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
+ .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .options = {
+ .udp_encap = 1,
+ .stats = 1,
+ .esn = 1
+ }
+ },
+ .crypto_capabilities = nfp_crypto_caps,
+ .ol_flags = RTE_SECURITY_TX_OLOAD_NEED_MDATA
+ },
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_NONE
+ }
+};
+
+static const struct rte_security_capability *
+nfp_crypto_capabilities_get(void *device __rte_unused)
+{
+ return nfp_security_caps;
+}
+
+static uint32_t
+nfp_security_session_get_size(void *device __rte_unused)
+{
+ return sizeof(struct nfp_ipsec_session);
+}
+
+static const struct rte_security_ops nfp_security_ops = {
+ .session_get_size = nfp_security_session_get_size,
+ .capabilities_get = nfp_crypto_capabilities_get,
+};
static int
nfp_ipsec_ctx_create(struct rte_eth_dev *dev,
--
2.39.1
^ permalink raw reply [flat|nested] 42+ messages in thread
* [PATCH v2 06/10] net/nfp: get IPsec Rx/Tx packet statistics
2023-09-26 2:49 ` [PATCH v2 00/10] add the support of ipsec offload Chaoyong He
` (4 preceding siblings ...)
2023-09-26 2:49 ` [PATCH v2 05/10] net/nfp: get security capabilities and session size Chaoyong He
@ 2023-09-26 2:49 ` Chaoyong He
2023-09-26 2:49 ` [PATCH v2 07/10] net/nfp: create security session Chaoyong He
` (5 subsequent siblings)
11 siblings, 0 replies; 42+ messages in thread
From: Chaoyong He @ 2023-09-26 2:49 UTC (permalink / raw)
To: dev; +Cc: oss-drivers, Shihong Wang, Chaoyong He
From: Shihong Wang <shihong.wang@corigine.com>
IPsec packet processing is mostly carried out in hardware.
The hardware statistics on successful packets and discarded
packets. The driver can obtain these statistics by Mailbox.
Signed-off-by: Shihong Wang <shihong.wang@corigine.com>
Reviewed-by: Chaoyong He <chaoyong.he@corigine.com>
---
drivers/net/nfp/nfp_ipsec.c | 149 ++++++++++++++++++++++++++++++++++++
1 file changed, 149 insertions(+)
diff --git a/drivers/net/nfp/nfp_ipsec.c b/drivers/net/nfp/nfp_ipsec.c
index 51770def9d..d4292c3b90 100644
--- a/drivers/net/nfp/nfp_ipsec.c
+++ b/drivers/net/nfp/nfp_ipsec.c
@@ -356,6 +356,154 @@ static const struct rte_security_capability nfp_security_caps[] = {
}
};
+/* IPsec config message cmd codes */
+enum nfp_ipsec_cfg_msg_cmd_codes {
+ NFP_IPSEC_CFG_MSG_ADD_SA, /**< Add a new SA */
+ NFP_IPSEC_CFG_MSG_INV_SA, /**< Invalidate an existing SA */
+ NFP_IPSEC_CFG_MSG_MODIFY_SA, /**< Modify an existing SA */
+ NFP_IPSEC_CFG_MSG_GET_SA_STATS, /**< Report SA counters, flags, etc. */
+ NFP_IPSEC_CFG_MSG_GET_SEQ_NUMS, /**< Allocate sequence numbers */
+ NFP_IPSEC_CFG_MSG_LAST
+};
+
+enum nfp_ipsec_cfg_msg_rsp_codes {
+ NFP_IPSEC_CFG_MSG_OK,
+ NFP_IPSEC_CFG_MSG_FAILED,
+ NFP_IPSEC_CFG_MSG_SA_VALID,
+ NFP_IPSEC_CFG_MSG_SA_HASH_ADD_FAILED,
+ NFP_IPSEC_CFG_MSG_SA_HASH_DEL_FAILED,
+ NFP_IPSEC_CFG_MSG_SA_INVALID_CMD
+};
+
+static int
+nfp_ipsec_cfg_cmd_issue(struct nfp_net_hw *hw,
+ struct nfp_ipsec_msg *msg)
+{
+ int ret;
+ uint32_t i;
+ uint32_t msg_size;
+
+ msg_size = RTE_DIM(msg->raw);
+ msg->rsp = NFP_IPSEC_CFG_MSG_OK;
+
+ for (i = 0; i < msg_size; i++)
+ nn_cfg_writel(hw, NFP_NET_CFG_MBOX_VAL + 4 * i, msg->raw[i]);
+
+ ret = nfp_net_mbox_reconfig(hw, NFP_NET_CFG_MBOX_CMD_IPSEC);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to IPsec reconfig mbox");
+ return ret;
+ }
+
+ /*
+ * Not all commands and callers make use of response message data. But
+ * leave this up to the caller and always read and store the full
+ * response. One example where the data is needed is for statistics.
+ */
+ for (i = 0; i < msg_size; i++)
+ msg->raw[i] = nn_cfg_readl(hw, NFP_NET_CFG_MBOX_VAL + 4 * i);
+
+ switch (msg->rsp) {
+ case NFP_IPSEC_CFG_MSG_OK:
+ ret = 0;
+ break;
+ case NFP_IPSEC_CFG_MSG_SA_INVALID_CMD:
+ ret = -EINVAL;
+ break;
+ case NFP_IPSEC_CFG_MSG_SA_VALID:
+ ret = -EEXIST;
+ break;
+ case NFP_IPSEC_CFG_MSG_FAILED:
+ /* FALLTHROUGH */
+ case NFP_IPSEC_CFG_MSG_SA_HASH_ADD_FAILED:
+ /* FALLTHROUGH */
+ case NFP_IPSEC_CFG_MSG_SA_HASH_DEL_FAILED:
+ ret = -EIO;
+ break;
+ default:
+ ret = -EDOM;
+ }
+
+ return ret;
+}
+
+/**
+ * Get discards packet statistics for each SA
+ *
+ * The sa_discard_stats contains the statistics of discards packets
+ * of an SA. This function calculates the sum total of discarded packets.
+ *
+ * @param errors
+ * The value is SA discards packet sum total
+ * @param sa_discard_stats
+ * The struct is SA discards packet Statistics
+ */
+static void
+nfp_get_errorstats(uint64_t *errors,
+ struct ipsec_discard_stats *sa_discard_stats)
+{
+ uint32_t i;
+ uint32_t len;
+ uint32_t *perror;
+
+ perror = &sa_discard_stats->discards_auth;
+ len = sizeof(struct ipsec_discard_stats) / sizeof(uint32_t);
+
+ for (i = 0; i < len; i++)
+ *errors += *perror++;
+
+ *errors -= sa_discard_stats->ipv4_id_counter;
+}
+
+static int
+nfp_security_session_get_stats(void *device,
+ struct rte_security_session *session,
+ struct rte_security_stats *stats)
+{
+ int ret;
+ struct nfp_net_hw *hw;
+ struct nfp_ipsec_msg msg;
+ struct rte_eth_dev *eth_dev;
+ struct ipsec_get_sa_stats *cfg_s;
+ struct rte_security_ipsec_stats *ips_s;
+ struct nfp_ipsec_session *priv_session;
+ enum rte_security_ipsec_sa_direction direction;
+
+ eth_dev = device;
+ priv_session = SECURITY_GET_SESS_PRIV(session);
+ memset(&msg, 0, sizeof(msg));
+ msg.cmd = NFP_IPSEC_CFG_MSG_GET_SA_STATS;
+ msg.sa_idx = priv_session->sa_index;
+ hw = NFP_NET_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
+
+ ret = nfp_ipsec_cfg_cmd_issue(hw, &msg);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to get SA stats");
+ return ret;
+ }
+
+ cfg_s = &msg.cfg_get_stats;
+ direction = priv_session->ipsec.direction;
+ memset(stats, 0, sizeof(struct rte_security_stats)); /* Start with zeros */
+ stats->protocol = RTE_SECURITY_PROTOCOL_IPSEC;
+ ips_s = &stats->ipsec;
+
+ /* Only display SA if any counters are non-zero */
+ if (cfg_s->lifetime_byte_count != 0 || cfg_s->pkt_count != 0) {
+ if (direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) {
+ ips_s->ipackets = cfg_s->pkt_count;
+ ips_s->ibytes = cfg_s->lifetime_byte_count;
+ nfp_get_errorstats(&ips_s->ierrors, &cfg_s->sa_discard_stats);
+ } else {
+ ips_s->opackets = cfg_s->pkt_count;
+ ips_s->obytes = cfg_s->lifetime_byte_count;
+ nfp_get_errorstats(&ips_s->oerrors, &cfg_s->sa_discard_stats);
+ }
+ }
+
+ return 0;
+}
+
static const struct rte_security_capability *
nfp_crypto_capabilities_get(void *device __rte_unused)
{
@@ -370,6 +518,7 @@ nfp_security_session_get_size(void *device __rte_unused)
static const struct rte_security_ops nfp_security_ops = {
.session_get_size = nfp_security_session_get_size,
+ .session_stats_get = nfp_security_session_get_stats,
.capabilities_get = nfp_crypto_capabilities_get,
};
--
2.39.1
^ permalink raw reply [flat|nested] 42+ messages in thread
* [PATCH v2 07/10] net/nfp: create security session
2023-09-26 2:49 ` [PATCH v2 00/10] add the support of ipsec offload Chaoyong He
` (5 preceding siblings ...)
2023-09-26 2:49 ` [PATCH v2 06/10] net/nfp: get IPsec Rx/Tx packet statistics Chaoyong He
@ 2023-09-26 2:49 ` Chaoyong He
2023-09-26 2:49 ` [PATCH v2 08/10] net/nfp: update " Chaoyong He
` (4 subsequent siblings)
11 siblings, 0 replies; 42+ messages in thread
From: Chaoyong He @ 2023-09-26 2:49 UTC (permalink / raw)
To: dev; +Cc: oss-drivers, Chang Miao, Shihong Wang, Chaoyong He
From: Chang Miao <chang.miao@corigine.com>
Create security session to manage IPsec protocol specific message
and crypto parameters. This session support full protocol offload
and inline crypto operation with NIC devices.
Signed-off-by: Chang Miao <chang.miao@corigine.com>
Signed-off-by: Shihong Wang <shihong.wang@corigine.com>
Reviewed-by: Chaoyong He <chaoyong.he@corigine.com>
---
drivers/net/nfp/nfp_ipsec.c | 703 ++++++++++++++++++++++++++++++++++++
1 file changed, 703 insertions(+)
diff --git a/drivers/net/nfp/nfp_ipsec.c b/drivers/net/nfp/nfp_ipsec.c
index d4292c3b90..5280180028 100644
--- a/drivers/net/nfp/nfp_ipsec.c
+++ b/drivers/net/nfp/nfp_ipsec.c
@@ -17,6 +17,8 @@
#include "nfp_logs.h"
#include "nfp_rxtx.h"
+#define NFP_UDP_ESP_PORT 4500
+
static const struct rte_cryptodev_capabilities nfp_crypto_caps[] = {
{
.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
@@ -375,6 +377,62 @@ enum nfp_ipsec_cfg_msg_rsp_codes {
NFP_IPSEC_CFG_MSG_SA_INVALID_CMD
};
+enum nfp_ipsec_mode {
+ NFP_IPSEC_MODE_TRANSPORT,
+ NFP_IPSEC_MODE_TUNNEL,
+};
+
+enum nfp_ipsec_protocol {
+ NFP_IPSEC_PROTOCOL_AH,
+ NFP_IPSEC_PROTOCOL_ESP,
+};
+
+/* Cipher modes */
+enum nfp_ipsec_cimode {
+ NFP_IPSEC_CIMODE_ECB,
+ NFP_IPSEC_CIMODE_CBC,
+ NFP_IPSEC_CIMODE_CFB,
+ NFP_IPSEC_CIMODE_OFB,
+ NFP_IPSEC_CIMODE_CTR,
+};
+
+/* Hash types */
+enum nfp_ipsec_hash_type {
+ NFP_IPSEC_HASH_NONE,
+ NFP_IPSEC_HASH_MD5_96,
+ NFP_IPSEC_HASH_SHA1_96,
+ NFP_IPSEC_HASH_SHA256_96,
+ NFP_IPSEC_HASH_SHA384_96,
+ NFP_IPSEC_HASH_SHA512_96,
+ NFP_IPSEC_HASH_MD5_128,
+ NFP_IPSEC_HASH_SHA1_80,
+ NFP_IPSEC_HASH_SHA256_128,
+ NFP_IPSEC_HASH_SHA384_192,
+ NFP_IPSEC_HASH_SHA512_256,
+ NFP_IPSEC_HASH_GF128_128,
+ NFP_IPSEC_HASH_POLY1305_128,
+};
+
+/* Cipher types */
+enum nfp_ipsec_cipher_type {
+ NFP_IPSEC_CIPHER_NULL,
+ NFP_IPSEC_CIPHER_3DES,
+ NFP_IPSEC_CIPHER_AES128,
+ NFP_IPSEC_CIPHER_AES192,
+ NFP_IPSEC_CIPHER_AES256,
+ NFP_IPSEC_CIPHER_AES128_NULL,
+ NFP_IPSEC_CIPHER_AES192_NULL,
+ NFP_IPSEC_CIPHER_AES256_NULL,
+ NFP_IPSEC_CIPHER_CHACHA20,
+};
+
+/* Don't Fragment types */
+enum nfp_ipsec_df_type {
+ NFP_IPSEC_DF_CLEAR,
+ NFP_IPSEC_DF_SET,
+ NFP_IPSEC_DF_COPY,
+};
+
static int
nfp_ipsec_cfg_cmd_issue(struct nfp_net_hw *hw,
struct nfp_ipsec_msg *msg)
@@ -427,6 +485,650 @@ nfp_ipsec_cfg_cmd_issue(struct nfp_net_hw *hw,
return ret;
}
+/**
+ * Get valid SA index from SA table
+ *
+ * @param data
+ * SA table pointer
+ * @param sa_idx
+ * SA table index pointer
+ *
+ * @return
+ * Negative number on full or repeat, 0 on success
+ *
+ * Note: multiple sockets may create same SA session.
+ */
+static void
+nfp_get_sa_entry(struct nfp_net_ipsec_data *data,
+ int *sa_idx)
+{
+ uint32_t i;
+
+ for (i = 0; i < NFP_NET_IPSEC_MAX_SA_CNT; i++) {
+ if (data->sa_entries[i] == NULL) {
+ *sa_idx = i;
+ break;
+ }
+ }
+}
+
+static void
+nfp_aesgcm_iv_update(struct ipsec_add_sa *cfg,
+ uint16_t iv_len,
+ const char *iv_string)
+{
+ int i;
+ char *save;
+ char *iv_b;
+ char *iv_str;
+ uint8_t *cfg_iv;
+
+ iv_str = strdup(iv_string);
+ cfg_iv = (uint8_t *)cfg->aesgcm_fields.iv;
+
+ for (i = 0; i < iv_len; i++) {
+ iv_b = strtok_r(i ? NULL : iv_str, ",", &save);
+ if (iv_b == NULL)
+ break;
+
+ cfg_iv[i] = strtoul(iv_b, NULL, 0);
+ }
+
+ *(uint32_t *)cfg_iv = rte_be_to_cpu_32(*(uint32_t *)cfg_iv);
+ *(uint32_t *)&cfg_iv[4] = rte_be_to_cpu_32(*(uint32_t *)&cfg_iv[4]);
+
+ free(iv_str);
+}
+
+static int
+set_aes_keylen(uint32_t key_length,
+ struct ipsec_add_sa *cfg)
+{
+ switch (key_length << 3) {
+ case 128:
+ cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_AES128;
+ break;
+ case 192:
+ cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_AES192;
+ break;
+ case 256:
+ cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_AES256;
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "AES cipher key length is illegal!");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* Map rte_security_session_conf aead algo to NFP aead algo */
+static int
+nfp_aead_map(struct rte_eth_dev *eth_dev,
+ struct rte_crypto_aead_xform *aead,
+ uint32_t key_length,
+ struct ipsec_add_sa *cfg)
+{
+ int ret;
+ uint32_t i;
+ uint32_t index;
+ uint16_t iv_len;
+ uint32_t offset;
+ uint32_t device_id;
+ const char *iv_str;
+ const uint32_t *key;
+ struct nfp_net_hw *hw;
+
+ hw = NFP_NET_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
+ device_id = hw->device_id;
+ offset = 0;
+
+ switch (aead->algo) {
+ case RTE_CRYPTO_AEAD_AES_GCM:
+ if (aead->digest_length != 16) {
+ PMD_DRV_LOG(ERR, "ICV must be 128bit with RTE_CRYPTO_AEAD_AES_GCM!");
+ return -EINVAL;
+ }
+
+ cfg->ctrl_word.cimode = NFP_IPSEC_CIMODE_CTR;
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_GF128_128;
+
+ ret = set_aes_keylen(key_length, cfg);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to set AES_GCM key length!");
+ return -EINVAL;
+ }
+
+ break;
+ case RTE_CRYPTO_AEAD_CHACHA20_POLY1305:
+ if (device_id != PCI_DEVICE_ID_NFP3800_PF_NIC) {
+ PMD_DRV_LOG(ERR, "Unsupported aead CHACHA20_POLY1305 algorithm!");
+ return -EINVAL;
+ }
+
+ if (aead->digest_length != 16) {
+ PMD_DRV_LOG(ERR, "ICV must be 128bit with RTE_CRYPTO_AEAD_CHACHA20_POLY1305");
+ return -EINVAL;
+ }
+
+ /* Aead->alg_key_len includes 32-bit salt */
+ if (key_length != 32) {
+ PMD_DRV_LOG(ERR, "Unsupported CHACHA20 key length");
+ return -EINVAL;
+ }
+
+ /* The CHACHA20's mode is not configured */
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_POLY1305_128;
+ cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_CHACHA20;
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "Unsupported aead algorithm!");
+ return -EINVAL;
+ }
+
+ key = (const uint32_t *)(aead->key.data);
+
+ /*
+ * The CHACHA20's key order needs to be adjusted based on hardware design.
+ * Unadjusted order: {K0, K1, K2, K3, K4, K5, K6, K7}
+ * Adjusted order: {K4, K5, K6, K7, K0, K1, K2, K3}
+ */
+ if (aead->algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305)
+ offset = key_length / sizeof(cfg->cipher_key[0]) << 1;
+
+ for (i = 0; i < key_length / sizeof(cfg->cipher_key[0]); i++) {
+ index = (i + offset) % (key_length / sizeof(cfg->cipher_key[0]));
+ cfg->cipher_key[index] = rte_cpu_to_be_32(*key++);
+ }
+
+ /*
+ * The iv of the FW is equal to ESN by default. Reading the
+ * iv of the configuration information is not supported.
+ */
+ iv_str = getenv("ETH_SEC_IV_OVR");
+ if (iv_str != NULL) {
+ iv_len = aead->iv.length;
+ nfp_aesgcm_iv_update(cfg, iv_len, iv_str);
+ }
+
+ return 0;
+}
+
+/* Map rte_security_session_conf cipher algo to NFP cipher algo */
+static int
+nfp_cipher_map(struct rte_eth_dev *eth_dev,
+ struct rte_crypto_cipher_xform *cipher,
+ uint32_t key_length,
+ struct ipsec_add_sa *cfg)
+{
+ int ret;
+ uint32_t i;
+ uint32_t device_id;
+ const uint32_t *key;
+ struct nfp_net_hw *hw;
+
+ hw = NFP_NET_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
+ device_id = hw->device_id;
+
+ switch (cipher->algo) {
+ case RTE_CRYPTO_CIPHER_NULL:
+ cfg->ctrl_word.cimode = NFP_IPSEC_CIMODE_CBC;
+ cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_NULL;
+ break;
+ case RTE_CRYPTO_CIPHER_3DES_CBC:
+ if (device_id == PCI_DEVICE_ID_NFP3800_PF_NIC) {
+ PMD_DRV_LOG(ERR, "Unsupported 3DESCBC encryption algorithm!");
+ return -EINVAL;
+ }
+
+ cfg->ctrl_word.cimode = NFP_IPSEC_CIMODE_CBC;
+ cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_3DES;
+ break;
+ case RTE_CRYPTO_CIPHER_AES_CBC:
+ cfg->ctrl_word.cimode = NFP_IPSEC_CIMODE_CBC;
+ ret = set_aes_keylen(key_length, cfg);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to set cipher key length!");
+ return -EINVAL;
+ }
+
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "Unsupported cipher alg!");
+ return -EINVAL;
+ }
+
+ key = (const uint32_t *)(cipher->key.data);
+ if (key_length > sizeof(cfg->cipher_key)) {
+ PMD_DRV_LOG(ERR, "Insufficient space for offloaded key");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < key_length / sizeof(cfg->cipher_key[0]); i++)
+ cfg->cipher_key[i] = rte_cpu_to_be_32(*key++);
+
+ return 0;
+}
+
+static void
+set_md5hmac(struct ipsec_add_sa *cfg,
+ uint32_t *digest_length)
+{
+ switch (*digest_length) {
+ case 96:
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_MD5_96;
+ break;
+ case 128:
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_MD5_128;
+ break;
+ default:
+ *digest_length = 0;
+ }
+}
+
+static void
+set_sha1hmac(struct ipsec_add_sa *cfg,
+ uint32_t *digest_length)
+{
+ switch (*digest_length) {
+ case 96:
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA1_96;
+ break;
+ case 80:
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA1_80;
+ break;
+ default:
+ *digest_length = 0;
+ }
+}
+
+static void
+set_sha2_256hmac(struct ipsec_add_sa *cfg,
+ uint32_t *digest_length)
+{
+ switch (*digest_length) {
+ case 96:
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA256_96;
+ break;
+ case 128:
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA256_128;
+ break;
+ default:
+ *digest_length = 0;
+ }
+}
+
+static void
+set_sha2_384hmac(struct ipsec_add_sa *cfg,
+ uint32_t *digest_length)
+{
+ switch (*digest_length) {
+ case 96:
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA384_96;
+ break;
+ case 192:
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA384_192;
+ break;
+ default:
+ *digest_length = 0;
+ }
+}
+
+static void
+set_sha2_512hmac(struct ipsec_add_sa *cfg,
+ uint32_t *digest_length)
+{
+ switch (*digest_length) {
+ case 96:
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA512_96;
+ break;
+ case 256:
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA512_256;
+ break;
+ default:
+ *digest_length = 0;
+ }
+}
+
+/* Map rte_security_session_conf auth algo to NFP auth algo */
+static int
+nfp_auth_map(struct rte_eth_dev *eth_dev,
+ struct rte_crypto_auth_xform *auth,
+ uint32_t digest_length,
+ struct ipsec_add_sa *cfg)
+{
+ uint32_t i;
+ uint8_t key_length;
+ uint32_t device_id;
+ const uint32_t *key;
+ struct nfp_net_hw *hw;
+
+ if (digest_length == 0) {
+ PMD_DRV_LOG(ERR, "Auth digest length is illegal!");
+ return -EINVAL;
+ }
+
+ hw = NFP_NET_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
+ device_id = hw->device_id;
+ digest_length = digest_length << 3;
+
+ switch (auth->algo) {
+ case RTE_CRYPTO_AUTH_NULL:
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_NONE;
+ digest_length = 1;
+ break;
+ case RTE_CRYPTO_AUTH_MD5_HMAC:
+ if (device_id == PCI_DEVICE_ID_NFP3800_PF_NIC) {
+ PMD_DRV_LOG(ERR, "Unsupported MD5HMAC authentication algorithm!");
+ return -EINVAL;
+ }
+
+ set_md5hmac(cfg, &digest_length);
+ break;
+ case RTE_CRYPTO_AUTH_SHA1_HMAC:
+ set_sha1hmac(cfg, &digest_length);
+ break;
+ case RTE_CRYPTO_AUTH_SHA256_HMAC:
+ set_sha2_256hmac(cfg, &digest_length);
+ break;
+ case RTE_CRYPTO_AUTH_SHA384_HMAC:
+ set_sha2_384hmac(cfg, &digest_length);
+ break;
+ case RTE_CRYPTO_AUTH_SHA512_HMAC:
+ set_sha2_512hmac(cfg, &digest_length);
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "Unsupported auth alg!");
+ return -EINVAL;
+ }
+
+ if (digest_length == 0) {
+ PMD_DRV_LOG(ERR, "Unsupported authentication algorithm digest length");
+ return -EINVAL;
+ }
+
+ key = (const uint32_t *)(auth->key.data);
+ key_length = auth->key.length;
+ if (key_length > sizeof(cfg->auth_key)) {
+ PMD_DRV_LOG(ERR, "Insufficient space for offloaded auth key!");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < key_length / sizeof(cfg->auth_key[0]); i++)
+ cfg->auth_key[i] = rte_cpu_to_be_32(*key++);
+
+ return 0;
+}
+
+static int
+nfp_crypto_msg_build(struct rte_eth_dev *eth_dev,
+ struct rte_security_session_conf *conf,
+ struct nfp_ipsec_msg *msg)
+{
+ int ret;
+ struct ipsec_add_sa *cfg;
+ struct rte_crypto_sym_xform *cur;
+ struct rte_crypto_sym_xform *next;
+ enum rte_security_ipsec_sa_direction direction;
+
+ cur = conf->crypto_xform;
+ if (cur == NULL) {
+ PMD_DRV_LOG(ERR, "Unsupported crypto_xform is NULL!");
+ return -EINVAL;
+ }
+
+ next = cur->next;
+ direction = conf->ipsec.direction;
+ cfg = &msg->cfg_add_sa;
+
+ switch (cur->type) {
+ case RTE_CRYPTO_SYM_XFORM_AEAD:
+ /* Aead transforms can be used for either inbound/outbound IPsec SAs */
+ if (next != NULL) {
+ PMD_DRV_LOG(ERR, "Next crypto_xform type should be NULL!");
+ return -EINVAL;
+ }
+
+ ret = nfp_aead_map(eth_dev, &cur->aead, cur->aead.key.length, cfg);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to map aead alg!");
+ return ret;
+ }
+
+ cfg->aesgcm_fields.salt = rte_cpu_to_be_32(conf->ipsec.salt);
+ break;
+ case RTE_CRYPTO_SYM_XFORM_AUTH:
+ /* Only support Auth + Cipher for inbound */
+ if (direction != RTE_SECURITY_IPSEC_SA_DIR_INGRESS) {
+ PMD_DRV_LOG(ERR, "Direction should be INGRESS, but it is not!");
+ return -EINVAL;
+ }
+
+ if (next == NULL || next->type != RTE_CRYPTO_SYM_XFORM_CIPHER) {
+ PMD_DRV_LOG(ERR, "Next crypto_xfrm should be cipher, but it is not!");
+ return -EINVAL;
+ }
+
+ ret = nfp_auth_map(eth_dev, &cur->auth, cur->auth.digest_length, cfg);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to map auth alg!");
+ return ret;
+ }
+
+ ret = nfp_cipher_map(eth_dev, &next->cipher, next->cipher.key.length, cfg);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to map cipher alg!");
+ return ret;
+ }
+
+ break;
+ case RTE_CRYPTO_SYM_XFORM_CIPHER:
+ /* Only support Cipher + Auth for outbound */
+ if (direction != RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
+ PMD_DRV_LOG(ERR, "Direction should be EGRESS, but it is not!");
+ return -EINVAL;
+ }
+
+ if (next == NULL || next->type != RTE_CRYPTO_SYM_XFORM_AUTH) {
+ PMD_DRV_LOG(ERR, "Next crypto_xfrm should be auth, but it is not!");
+ return -EINVAL;
+ }
+
+ ret = nfp_cipher_map(eth_dev, &cur->cipher, cur->cipher.key.length, cfg);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to map cipher alg!");
+ return ret;
+ }
+
+ ret = nfp_auth_map(eth_dev, &next->auth, next->auth.digest_length, cfg);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to map auth alg!");
+ return ret;
+ }
+
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "Unsupported crypto_xform type!");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+nfp_ipsec_msg_build(struct rte_eth_dev *eth_dev,
+ struct rte_security_session_conf *conf,
+ struct nfp_ipsec_msg *msg)
+{
+ int ret;
+ uint32_t i;
+ struct ipsec_add_sa *cfg;
+ enum rte_security_ipsec_tunnel_type type;
+
+ cfg = &msg->cfg_add_sa;
+ cfg->spi = conf->ipsec.spi;
+ cfg->pmtu_limit = 0xffff;
+
+ /*
+ * UDP encapsulation
+ *
+ * 1: Do UDP encapsulation/decapsulation
+ * 0: No UDP encapsulation
+ */
+ if (conf->ipsec.options.udp_encap == 1) {
+ cfg->udp_enable = 1;
+ cfg->natt_dst_port = NFP_UDP_ESP_PORT;
+ cfg->natt_src_port = NFP_UDP_ESP_PORT;
+ }
+
+ if (conf->ipsec.options.copy_df == 1)
+ cfg->df_ctrl = NFP_IPSEC_DF_COPY;
+ else if (conf->ipsec.tunnel.ipv4.df != 0)
+ cfg->df_ctrl = NFP_IPSEC_DF_SET;
+ else
+ cfg->df_ctrl = NFP_IPSEC_DF_CLEAR;
+
+ switch (conf->action_type) {
+ case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO:
+ cfg->ctrl_word.encap_dsbl = 1;
+ break;
+ case RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL:
+ cfg->ctrl_word.encap_dsbl = 0;
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "Unsupported IPsec action for offload, action: %d",
+ conf->action_type);
+ return -EINVAL;
+ }
+
+ switch (conf->ipsec.proto) {
+ case RTE_SECURITY_IPSEC_SA_PROTO_ESP:
+ cfg->ctrl_word.proto = NFP_IPSEC_PROTOCOL_ESP;
+ break;
+ case RTE_SECURITY_IPSEC_SA_PROTO_AH:
+ cfg->ctrl_word.proto = NFP_IPSEC_PROTOCOL_AH;
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "Unsupported IPsec protocol for offload, protocol: %d",
+ conf->ipsec.proto);
+ return -EINVAL;
+ }
+
+ switch (conf->ipsec.mode) {
+ case RTE_SECURITY_IPSEC_SA_MODE_TUNNEL:
+ type = conf->ipsec.tunnel.type;
+ cfg->ctrl_word.mode = NFP_IPSEC_MODE_TUNNEL;
+ if (type == RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
+ cfg->src_ip[0] = conf->ipsec.tunnel.ipv4.src_ip.s_addr;
+ cfg->dst_ip[0] = conf->ipsec.tunnel.ipv4.dst_ip.s_addr;
+ cfg->ipv6 = 0;
+ } else if (type == RTE_SECURITY_IPSEC_TUNNEL_IPV6) {
+ memcpy(cfg->src_ip, conf->ipsec.tunnel.ipv6.src_addr.s6_addr, 16);
+ memcpy(cfg->dst_ip, conf->ipsec.tunnel.ipv6.dst_addr.s6_addr, 16);
+ cfg->ipv6 = 1;
+ } else {
+ PMD_DRV_LOG(ERR, "Unsupported address family!");
+ return -EINVAL;
+ }
+
+ break;
+ case RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT:
+ type = conf->ipsec.tunnel.type;
+ cfg->ctrl_word.mode = NFP_IPSEC_MODE_TRANSPORT;
+ if (type == RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
+ cfg->src_ip[0] = 0;
+ cfg->dst_ip[0] = 0;
+ cfg->ipv6 = 0;
+ } else if (type == RTE_SECURITY_IPSEC_TUNNEL_IPV6) {
+ for (i = 0; i < 4; i++) {
+ cfg->src_ip[i] = 0;
+ cfg->dst_ip[i] = 0;
+ }
+ cfg->ipv6 = 1;
+ } else {
+ PMD_DRV_LOG(ERR, "Unsupported address family!");
+ return -EINVAL;
+ }
+
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "Unsupported IPsec mode for offload, mode: %d",
+ conf->ipsec.mode);
+ return -EINVAL;
+ }
+
+ ret = nfp_crypto_msg_build(eth_dev, conf, msg);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to build auth/crypto/aead msg!");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int
+nfp_crypto_create_session(void *device,
+ struct rte_security_session_conf *conf,
+ struct rte_security_session *session)
+{
+ int ret;
+ int sa_idx;
+ struct nfp_net_hw *hw;
+ struct nfp_ipsec_msg msg;
+ struct rte_eth_dev *eth_dev;
+ struct nfp_ipsec_session *priv_session;
+
+ /* Only support IPsec at present */
+ if (conf->protocol != RTE_SECURITY_PROTOCOL_IPSEC) {
+ PMD_DRV_LOG(ERR, "Unsupported non-IPsec offload!");
+ return -EINVAL;
+ }
+
+ sa_idx = -1;
+ eth_dev = device;
+ priv_session = SECURITY_GET_SESS_PRIV(session);
+ hw = NFP_NET_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
+
+ if (hw->ipsec_data->sa_free_cnt == 0) {
+ PMD_DRV_LOG(ERR, "No space in SA table, spi: %d", conf->ipsec.spi);
+ return -EINVAL;
+ }
+
+ nfp_get_sa_entry(hw->ipsec_data, &sa_idx);
+
+ if (sa_idx < 0) {
+ PMD_DRV_LOG(ERR, "Failed to get SA entry!");
+ return -EINVAL;
+ }
+
+ memset(&msg, 0, sizeof(msg));
+ ret = nfp_ipsec_msg_build(eth_dev, conf, &msg);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to build IPsec msg!");
+ return -EINVAL;
+ }
+
+ msg.cmd = NFP_IPSEC_CFG_MSG_ADD_SA;
+ msg.sa_idx = sa_idx;
+ ret = nfp_ipsec_cfg_cmd_issue(hw, &msg);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to add SA to nic");
+ return -EINVAL;
+ }
+
+ priv_session->action = conf->action_type;
+ priv_session->ipsec = conf->ipsec;
+ priv_session->msg = msg.cfg_add_sa;
+ priv_session->sa_index = sa_idx;
+ priv_session->dev = eth_dev;
+ priv_session->user_data = conf->userdata;
+
+ hw->ipsec_data->sa_free_cnt--;
+ hw->ipsec_data->sa_entries[sa_idx] = priv_session;
+
+ return 0;
+}
+
/**
* Get discards packet statistics for each SA
*
@@ -517,6 +1219,7 @@ nfp_security_session_get_size(void *device __rte_unused)
}
static const struct rte_security_ops nfp_security_ops = {
+ .session_create = nfp_crypto_create_session,
.session_get_size = nfp_security_session_get_size,
.session_stats_get = nfp_security_session_get_stats,
.capabilities_get = nfp_crypto_capabilities_get,
--
2.39.1
^ permalink raw reply [flat|nested] 42+ messages in thread
* [PATCH v2 08/10] net/nfp: update security session
2023-09-26 2:49 ` [PATCH v2 00/10] add the support of ipsec offload Chaoyong He
` (6 preceding siblings ...)
2023-09-26 2:49 ` [PATCH v2 07/10] net/nfp: create security session Chaoyong He
@ 2023-09-26 2:49 ` Chaoyong He
2023-09-26 2:49 ` [PATCH v2 09/10] net/nfp: support IPsec Rx and Tx offload Chaoyong He
` (3 subsequent siblings)
11 siblings, 0 replies; 42+ messages in thread
From: Chaoyong He @ 2023-09-26 2:49 UTC (permalink / raw)
To: dev; +Cc: oss-drivers, Shihong Wang, Chaoyong He
From: Shihong Wang <shihong.wang@corigine.com>
Update the configuration information in priv_session when
the configuration parameters of sess_conf change.
Signed-off-by: Shihong Wang <shihong.wang@corigine.com>
Reviewed-by: Chaoyong He <chaoyong.he@corigine.com>
---
drivers/net/nfp/nfp_ipsec.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/drivers/net/nfp/nfp_ipsec.c b/drivers/net/nfp/nfp_ipsec.c
index 5280180028..0022532027 100644
--- a/drivers/net/nfp/nfp_ipsec.c
+++ b/drivers/net/nfp/nfp_ipsec.c
@@ -1129,6 +1129,30 @@ nfp_crypto_create_session(void *device,
return 0;
}
+static int
+nfp_crypto_update_session(void *device __rte_unused,
+ struct rte_security_session *session,
+ struct rte_security_session_conf *conf)
+{
+ struct nfp_ipsec_session *priv_session;
+
+ priv_session = SECURITY_GET_SESS_PRIV(session);
+ if (priv_session == NULL)
+ return -EINVAL;
+
+ /* Update IPsec ESN value */
+ if (priv_session->msg.ctrl_word.ext_seq != 0 && conf->ipsec.options.esn != 0) {
+ /*
+ * Store in nfp_ipsec_session for outbound SA for use
+ * in nfp_security_set_pkt_metadata() function.
+ */
+ priv_session->ipsec.esn.hi = conf->ipsec.esn.hi;
+ priv_session->ipsec.esn.low = conf->ipsec.esn.low;
+ }
+
+ return 0;
+}
+
/**
* Get discards packet statistics for each SA
*
@@ -1220,6 +1244,7 @@ nfp_security_session_get_size(void *device __rte_unused)
static const struct rte_security_ops nfp_security_ops = {
.session_create = nfp_crypto_create_session,
+ .session_update = nfp_crypto_update_session,
.session_get_size = nfp_security_session_get_size,
.session_stats_get = nfp_security_session_get_stats,
.capabilities_get = nfp_crypto_capabilities_get,
--
2.39.1
^ permalink raw reply [flat|nested] 42+ messages in thread
* [PATCH v2 09/10] net/nfp: support IPsec Rx and Tx offload
2023-09-26 2:49 ` [PATCH v2 00/10] add the support of ipsec offload Chaoyong He
` (7 preceding siblings ...)
2023-09-26 2:49 ` [PATCH v2 08/10] net/nfp: update " Chaoyong He
@ 2023-09-26 2:49 ` Chaoyong He
2023-09-26 2:49 ` [PATCH v2 10/10] net/nfp: destroy security session Chaoyong He
` (2 subsequent siblings)
11 siblings, 0 replies; 42+ messages in thread
From: Chaoyong He @ 2023-09-26 2:49 UTC (permalink / raw)
To: dev; +Cc: oss-drivers, Shihong Wang, Chang Miao, Chaoyong He
From: Shihong Wang <shihong.wang@corigine.com>
The Rx path checks the ipsec metadata and base on the
crypto status sets ol_flags in the rte_mbuf.
The Tx path write IPsec message to mbuf metadata based
on mbuf dynamic field.
Signed-off-by: Shihong Wang <shihong.wang@corigine.com>
Signed-off-by: Chang Miao <chang.miao@corigine.com>
Reviewed-by: Chaoyong He <chaoyong.he@corigine.com>
---
doc/guides/nics/nfp.rst | 31 +++++++++++++
drivers/net/nfp/nfd3/nfp_nfd3_dp.c | 24 ++++++++++
drivers/net/nfp/nfdk/nfp_nfdk_dp.c | 24 ++++++++++
drivers/net/nfp/nfp_ctrl.h | 1 +
drivers/net/nfp/nfp_ipsec.c | 42 +++++++++++++++++
drivers/net/nfp/nfp_ipsec.h | 6 +++
drivers/net/nfp/nfp_rxtx.c | 74 ++++++++++++++++++++++++++++++
drivers/net/nfp/nfp_rxtx.h | 5 ++
8 files changed, 207 insertions(+)
diff --git a/doc/guides/nics/nfp.rst b/doc/guides/nics/nfp.rst
index 456a22dcbc..fee1860f4a 100644
--- a/doc/guides/nics/nfp.rst
+++ b/doc/guides/nics/nfp.rst
@@ -348,6 +348,18 @@ Metadata with L2 (1W/4B)
The vlan[0] is the innermost VLAN
The vlan[1] is the QinQ info
+NFP_NET_META_IPSEC
+The IPsec type requires 4 bit.
+The SA index value is 32 bit which need 1 data field.
+::
+
+ ----------------------------------------------------------------
+ 3 2 1 0
+ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | sa_idx |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
TX
~~
@@ -363,3 +375,22 @@ NFP_NET_META_VLAN
^ ^
NOTE: | TCI |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+NFP_NET_META_IPSEC
+The IPsec type requires 12 bit, because it requires three data fields.
+::
+
+ ----------------------------------------------------------------
+ 3 2 1 0
+ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | sa_idx |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | nfp_ipsec_force_seq_low |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | nfp_ipsec_force_seq_hi |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ The sa_idx is 32 bit which need 1 data field.
+ The nfp_ipsec_force_seq_low & nfp_ipsec_force_seq_hi is Anti-re-anti-count,
+ which is 64 bit need two data fields.
diff --git a/drivers/net/nfp/nfd3/nfp_nfd3_dp.c b/drivers/net/nfp/nfd3/nfp_nfd3_dp.c
index ab0747fc16..64928254d8 100644
--- a/drivers/net/nfp/nfd3/nfp_nfd3_dp.c
+++ b/drivers/net/nfp/nfd3/nfp_nfd3_dp.c
@@ -147,10 +147,13 @@ nfp_net_nfd3_set_meta_data(struct nfp_net_meta_raw *meta_data,
char *meta;
uint8_t layer = 0;
uint32_t meta_info;
+ uint32_t cap_extend;
struct nfp_net_hw *hw;
uint8_t vlan_layer = 0;
+ uint8_t ipsec_layer = 0;
hw = txq->hw;
+ cap_extend = nn_cfg_readl(hw, NFP_NET_CFG_CAP_WORD1);
if ((pkt->ol_flags & RTE_MBUF_F_TX_VLAN) != 0 &&
(hw->ctrl & NFP_NET_CFG_CTRL_TXVLAN_V2) != 0) {
@@ -160,6 +163,18 @@ nfp_net_nfd3_set_meta_data(struct nfp_net_meta_raw *meta_data,
meta_data->header |= NFP_NET_META_VLAN;
}
+ if ((pkt->ol_flags & RTE_MBUF_F_TX_SEC_OFFLOAD) != 0 &&
+ (cap_extend & NFP_NET_CFG_CTRL_IPSEC) != 0) {
+ uint32_t ipsec_type = NFP_NET_META_IPSEC |
+ NFP_NET_META_IPSEC << NFP_NET_META_FIELD_SIZE |
+ NFP_NET_META_IPSEC << (2 * NFP_NET_META_FIELD_SIZE);
+ if (meta_data->length == 0)
+ meta_data->length = NFP_NET_META_FIELD_SIZE;
+ uint8_t ipsec_offset = meta_data->length - NFP_NET_META_FIELD_SIZE;
+ meta_data->header |= (ipsec_type << ipsec_offset);
+ meta_data->length += 3 * NFP_NET_META_FIELD_SIZE;
+ }
+
if (meta_data->length == 0)
return;
@@ -180,6 +195,15 @@ nfp_net_nfd3_set_meta_data(struct nfp_net_meta_raw *meta_data,
nfp_net_set_meta_vlan(meta_data, pkt, layer);
vlan_layer++;
break;
+ case NFP_NET_META_IPSEC:
+ if (ipsec_layer > 2) {
+ PMD_DRV_LOG(ERR, "At most 3 layers of ipsec is supported for now.");
+ return;
+ }
+
+ nfp_net_set_meta_ipsec(meta_data, txq, pkt, layer, ipsec_layer);
+ ipsec_layer++;
+ break;
default:
PMD_DRV_LOG(ERR, "The metadata type not supported");
return;
diff --git a/drivers/net/nfp/nfdk/nfp_nfdk_dp.c b/drivers/net/nfp/nfdk/nfp_nfdk_dp.c
index a85734f121..d4bd5edb0a 100644
--- a/drivers/net/nfp/nfdk/nfp_nfdk_dp.c
+++ b/drivers/net/nfp/nfdk/nfp_nfdk_dp.c
@@ -177,13 +177,16 @@ nfp_net_nfdk_set_meta_data(struct rte_mbuf *pkt,
char *meta;
uint8_t layer = 0;
uint32_t meta_type;
+ uint32_t cap_extend;
struct nfp_net_hw *hw;
uint32_t header_offset;
uint8_t vlan_layer = 0;
+ uint8_t ipsec_layer = 0;
struct nfp_net_meta_raw meta_data;
memset(&meta_data, 0, sizeof(meta_data));
hw = txq->hw;
+ cap_extend = nn_cfg_readl(hw, NFP_NET_CFG_CAP_WORD1);
if ((pkt->ol_flags & RTE_MBUF_F_TX_VLAN) != 0 &&
(hw->ctrl & NFP_NET_CFG_CTRL_TXVLAN_V2) != 0) {
@@ -193,6 +196,18 @@ nfp_net_nfdk_set_meta_data(struct rte_mbuf *pkt,
meta_data.header |= NFP_NET_META_VLAN;
}
+ if ((pkt->ol_flags & RTE_MBUF_F_TX_SEC_OFFLOAD) != 0 &&
+ (cap_extend & NFP_NET_CFG_CTRL_IPSEC) != 0) {
+ uint32_t ipsec_type = NFP_NET_META_IPSEC |
+ NFP_NET_META_IPSEC << NFP_NET_META_FIELD_SIZE |
+ NFP_NET_META_IPSEC << (2 * NFP_NET_META_FIELD_SIZE);
+ if (meta_data.length == 0)
+ meta_data.length = NFP_NET_META_FIELD_SIZE;
+ uint8_t ipsec_offset = meta_data.length - NFP_NET_META_FIELD_SIZE;
+ meta_data.header |= (ipsec_type << ipsec_offset);
+ meta_data.length += 3 * NFP_NET_META_FIELD_SIZE;
+ }
+
if (meta_data.length == 0)
return;
@@ -215,6 +230,15 @@ nfp_net_nfdk_set_meta_data(struct rte_mbuf *pkt,
nfp_net_set_meta_vlan(&meta_data, pkt, layer);
vlan_layer++;
break;
+ case NFP_NET_META_IPSEC:
+ if (ipsec_layer > 2) {
+ PMD_DRV_LOG(ERR, "At most 3 layers of ipsec is supported for now.");
+ return;
+ }
+
+ nfp_net_set_meta_ipsec(&meta_data, txq, pkt, layer, ipsec_layer);
+ ipsec_layer++;
+ break;
default:
PMD_DRV_LOG(ERR, "The metadata type not supported");
return;
diff --git a/drivers/net/nfp/nfp_ctrl.h b/drivers/net/nfp/nfp_ctrl.h
index 361739a4b9..3488df6ba8 100644
--- a/drivers/net/nfp/nfp_ctrl.h
+++ b/drivers/net/nfp/nfp_ctrl.h
@@ -39,6 +39,7 @@
#define NFP_NET_META_HASH 1 /* next field carries hash type */
#define NFP_NET_META_VLAN 4
#define NFP_NET_META_PORTID 5
+#define NFP_NET_META_IPSEC 9
#define NFP_META_PORT_ID_CTRL ~0U
diff --git a/drivers/net/nfp/nfp_ipsec.c b/drivers/net/nfp/nfp_ipsec.c
index 0022532027..8626c6323d 100644
--- a/drivers/net/nfp/nfp_ipsec.c
+++ b/drivers/net/nfp/nfp_ipsec.c
@@ -1153,6 +1153,47 @@ nfp_crypto_update_session(void *device __rte_unused,
return 0;
}
+static int
+nfp_security_set_pkt_metadata(void *device,
+ struct rte_security_session *session,
+ struct rte_mbuf *m,
+ void *params)
+{
+ int offset;
+ uint64_t *sqn;
+ struct nfp_net_hw *hw;
+ struct rte_eth_dev *eth_dev;
+ struct nfp_ipsec_session *priv_session;
+
+ sqn = params;
+ eth_dev = device;
+ priv_session = SECURITY_GET_SESS_PRIV(session);
+ hw = NFP_NET_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
+
+ if (priv_session->ipsec.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
+ struct nfp_tx_ipsec_desc_msg *desc_md;
+
+ offset = hw->ipsec_data->pkt_dynfield_offset;
+ desc_md = RTE_MBUF_DYNFIELD(m, offset, struct nfp_tx_ipsec_desc_msg *);
+
+ if (priv_session->msg.ctrl_word.ext_seq != 0 && sqn != NULL) {
+ desc_md->esn.low = rte_cpu_to_be_32(*sqn);
+ desc_md->esn.hi = rte_cpu_to_be_32(*sqn >> 32);
+ } else if (priv_session->msg.ctrl_word.ext_seq != 0) {
+ desc_md->esn.low = rte_cpu_to_be_32(priv_session->ipsec.esn.low);
+ desc_md->esn.hi = rte_cpu_to_be_32(priv_session->ipsec.esn.hi);
+ } else {
+ desc_md->esn.low = rte_cpu_to_be_32(priv_session->ipsec.esn.value);
+ desc_md->esn.hi = 0;
+ }
+
+ desc_md->enc = 1;
+ desc_md->sa_idx = rte_cpu_to_be_32(priv_session->sa_index);
+ }
+
+ return 0;
+}
+
/**
* Get discards packet statistics for each SA
*
@@ -1247,6 +1288,7 @@ static const struct rte_security_ops nfp_security_ops = {
.session_update = nfp_crypto_update_session,
.session_get_size = nfp_security_session_get_size,
.session_stats_get = nfp_security_session_get_stats,
+ .set_pkt_metadata = nfp_security_set_pkt_metadata,
.capabilities_get = nfp_crypto_capabilities_get,
};
diff --git a/drivers/net/nfp/nfp_ipsec.h b/drivers/net/nfp/nfp_ipsec.h
index 531bc60c5a..cacb05f13e 100644
--- a/drivers/net/nfp/nfp_ipsec.h
+++ b/drivers/net/nfp/nfp_ipsec.h
@@ -163,6 +163,12 @@ struct nfp_net_ipsec_data {
struct nfp_ipsec_session *sa_entries[NFP_NET_IPSEC_MAX_SA_CNT];
};
+enum nfp_ipsec_meta_layer {
+ NFP_IPSEC_META_SAIDX, /**< Order of SA index in metadata */
+ NFP_IPSEC_META_SEQLOW, /**< Order of Sequence Number (low 32bits) in metadata */
+ NFP_IPSEC_META_SEQHI, /**< Order of Sequence Number (high 32bits) in metadata */
+};
+
int nfp_ipsec_init(struct rte_eth_dev *dev);
void nfp_ipsec_uninit(struct rte_eth_dev *dev);
diff --git a/drivers/net/nfp/nfp_rxtx.c b/drivers/net/nfp/nfp_rxtx.c
index e74aba7439..66a5d6cb3a 100644
--- a/drivers/net/nfp/nfp_rxtx.c
+++ b/drivers/net/nfp/nfp_rxtx.c
@@ -8,11 +8,13 @@
#include "nfp_rxtx.h"
#include <ethdev_pci.h>
+#include <rte_security.h>
#include "nfd3/nfp_nfd3.h"
#include "nfdk/nfp_nfdk.h"
#include "flower/nfp_flower.h"
+#include "nfp_ipsec.h"
#include "nfp_logs.h"
/* Maximum number of supported VLANs in parsed form packet metadata. */
@@ -25,8 +27,10 @@
* read-only after it have been recorded during parsing by nfp_net_parse_meta().
*
* @port_id: Port id value
+ * @sa_idx: IPsec SA index
* @hash: RSS hash value
* @hash_type: RSS hash type
+ * @ipsec_type: IPsec type
* @vlan_layer: The layers of VLAN info which are passed from nic.
* Only this number of entries of the @vlan array are valid.
*
@@ -44,8 +48,10 @@
*/
struct nfp_meta_parsed {
uint32_t port_id;
+ uint32_t sa_idx;
uint32_t hash;
uint8_t hash_type;
+ uint8_t ipsec_type;
uint8_t vlan_layer;
struct {
uint8_t offload;
@@ -304,6 +310,10 @@ nfp_net_parse_chained_meta(uint8_t *meta_base,
meta->vlan[meta->vlan_layer].tpid = NFP_NET_META_TPID(vlan_info);
++meta->vlan_layer;
break;
+ case NFP_NET_META_IPSEC:
+ meta->sa_idx = rte_be_to_cpu_32(*(rte_be32_t *)meta_offset);
+ meta->ipsec_type = meta_info & NFP_NET_META_FIELD_MASK;
+ break;
default:
/* Unsupported metadata can be a performance issue */
return false;
@@ -429,6 +439,39 @@ nfp_net_parse_meta_qinq(const struct nfp_meta_parsed *meta,
mb->ol_flags |= RTE_MBUF_F_RX_QINQ | RTE_MBUF_F_RX_QINQ_STRIPPED;
}
+/*
+ * Set mbuf IPsec Offload features based on metadata info.
+ *
+ * The IPsec Offload features is prepended to the mbuf ol_flags.
+ * Extract and decode metadata info and set the mbuf ol_flags.
+ */
+static void
+nfp_net_parse_meta_ipsec(struct nfp_meta_parsed *meta,
+ struct nfp_net_rxq *rxq,
+ struct rte_mbuf *mbuf)
+{
+ int offset;
+ uint32_t sa_idx;
+ struct nfp_net_hw *hw;
+ struct nfp_tx_ipsec_desc_msg *desc_md;
+
+ hw = rxq->hw;
+ sa_idx = meta->sa_idx;
+
+ if (meta->ipsec_type != NFP_NET_META_IPSEC)
+ return;
+
+ if (sa_idx >= NFP_NET_IPSEC_MAX_SA_CNT) {
+ mbuf->ol_flags |= RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED;
+ } else {
+ mbuf->ol_flags |= RTE_MBUF_F_RX_SEC_OFFLOAD;
+ offset = hw->ipsec_data->pkt_dynfield_offset;
+ desc_md = RTE_MBUF_DYNFIELD(mbuf, offset, struct nfp_tx_ipsec_desc_msg *);
+ desc_md->sa_idx = sa_idx;
+ desc_md->enc = 0;
+ }
+}
+
/* nfp_net_parse_meta() - Parse the metadata from packet */
static void
nfp_net_parse_meta(struct nfp_net_rx_desc *rxds,
@@ -453,6 +496,7 @@ nfp_net_parse_meta(struct nfp_net_rx_desc *rxds,
nfp_net_parse_meta_hash(meta, rxq, mb);
nfp_net_parse_meta_vlan(meta, rxds, rxq, mb);
nfp_net_parse_meta_qinq(meta, rxq, mb);
+ nfp_net_parse_meta_ipsec(meta, rxq, mb);
} else {
PMD_RX_LOG(DEBUG, "RX chained metadata format is wrong!");
}
@@ -1035,6 +1079,36 @@ nfp_net_set_meta_vlan(struct nfp_net_meta_raw *meta_data,
meta_data->data[layer] = rte_cpu_to_be_32(tpid << 16 | vlan_tci);
}
+void
+nfp_net_set_meta_ipsec(struct nfp_net_meta_raw *meta_data,
+ struct nfp_net_txq *txq,
+ struct rte_mbuf *pkt,
+ uint8_t layer,
+ uint8_t ipsec_layer)
+{
+ int offset;
+ struct nfp_net_hw *hw;
+ struct nfp_tx_ipsec_desc_msg *desc_md;
+
+ hw = txq->hw;
+ offset = hw->ipsec_data->pkt_dynfield_offset;
+ desc_md = RTE_MBUF_DYNFIELD(pkt, offset, struct nfp_tx_ipsec_desc_msg *);
+
+ switch (ipsec_layer) {
+ case NFP_IPSEC_META_SAIDX:
+ meta_data->data[layer] = desc_md->sa_idx;
+ break;
+ case NFP_IPSEC_META_SEQLOW:
+ meta_data->data[layer] = desc_md->esn.low;
+ break;
+ case NFP_IPSEC_META_SEQHI:
+ meta_data->data[layer] = desc_md->esn.hi;
+ break;
+ default:
+ break;
+ }
+}
+
int
nfp_net_tx_queue_setup(struct rte_eth_dev *dev,
uint16_t queue_idx,
diff --git a/drivers/net/nfp/nfp_rxtx.h b/drivers/net/nfp/nfp_rxtx.h
index 4e8558074e..3c7138f7d6 100644
--- a/drivers/net/nfp/nfp_rxtx.h
+++ b/drivers/net/nfp/nfp_rxtx.h
@@ -257,5 +257,10 @@ int nfp_net_tx_free_bufs(struct nfp_net_txq *txq);
void nfp_net_set_meta_vlan(struct nfp_net_meta_raw *meta_data,
struct rte_mbuf *pkt,
uint8_t layer);
+void nfp_net_set_meta_ipsec(struct nfp_net_meta_raw *meta_data,
+ struct nfp_net_txq *txq,
+ struct rte_mbuf *pkt,
+ uint8_t layer,
+ uint8_t ipsec_layer);
#endif /* _NFP_RXTX_H_ */
--
2.39.1
^ permalink raw reply [flat|nested] 42+ messages in thread
* [PATCH v2 10/10] net/nfp: destroy security session
2023-09-26 2:49 ` [PATCH v2 00/10] add the support of ipsec offload Chaoyong He
` (8 preceding siblings ...)
2023-09-26 2:49 ` [PATCH v2 09/10] net/nfp: support IPsec Rx and Tx offload Chaoyong He
@ 2023-09-26 2:49 ` Chaoyong He
2023-09-27 14:20 ` [PATCH v2 00/10] add the support of ipsec offload Ferruh Yigit
2023-09-29 2:08 ` [PATCH v3 0/9] " Chaoyong He
11 siblings, 0 replies; 42+ messages in thread
From: Chaoyong He @ 2023-09-26 2:49 UTC (permalink / raw)
To: dev; +Cc: oss-drivers, Shihong Wang, Chaoyong He
From: Shihong Wang <shihong.wang@corigine.com>
Delete SA from NIC and destroy security session.
Signed-off-by: Shihong Wang <shihong.wang@corigine.com>
Reviewed-by: Chaoyong He <chaoyong.he@corigine.com>
---
drivers/net/nfp/nfp_ipsec.c | 53 +++++++++++++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/drivers/net/nfp/nfp_ipsec.c b/drivers/net/nfp/nfp_ipsec.c
index 8626c6323d..56906f6e81 100644
--- a/drivers/net/nfp/nfp_ipsec.c
+++ b/drivers/net/nfp/nfp_ipsec.c
@@ -1283,11 +1283,64 @@ nfp_security_session_get_size(void *device __rte_unused)
return sizeof(struct nfp_ipsec_session);
}
+static int
+nfp_crypto_remove_sa(struct rte_eth_dev *eth_dev,
+ struct nfp_ipsec_session *priv_session)
+{
+ int ret;
+ uint32_t sa_index;
+ struct nfp_net_hw *hw;
+ struct nfp_ipsec_msg cfg;
+
+ sa_index = priv_session->sa_index;
+ hw = NFP_NET_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
+
+ cfg.cmd = NFP_IPSEC_CFG_MSG_INV_SA;
+ cfg.sa_idx = sa_index;
+ ret = nfp_ipsec_cfg_cmd_issue(hw, &cfg);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to remove SA!");
+ return -EINVAL;
+ }
+
+ hw->ipsec_data->sa_free_cnt++;
+ hw->ipsec_data->sa_entries[sa_index] = NULL;
+
+ return 0;
+}
+
+static int
+nfp_crypto_remove_session(void *device,
+ struct rte_security_session *session)
+{
+ int ret;
+ struct rte_eth_dev *eth_dev;
+ struct nfp_ipsec_session *priv_session;
+
+ eth_dev = device;
+ priv_session = SECURITY_GET_SESS_PRIV(session);
+ if (eth_dev != priv_session->dev) {
+ PMD_DRV_LOG(ERR, "Session not bound to this device");
+ return -ENODEV;
+ }
+
+ ret = nfp_crypto_remove_sa(eth_dev, priv_session);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to remove session");
+ return -EFAULT;
+ }
+
+ memset(priv_session, 0, sizeof(struct nfp_ipsec_session));
+
+ return 0;
+}
+
static const struct rte_security_ops nfp_security_ops = {
.session_create = nfp_crypto_create_session,
.session_update = nfp_crypto_update_session,
.session_get_size = nfp_security_session_get_size,
.session_stats_get = nfp_security_session_get_stats,
+ .session_destroy = nfp_crypto_remove_session,
.set_pkt_metadata = nfp_security_set_pkt_metadata,
.capabilities_get = nfp_crypto_capabilities_get,
};
--
2.39.1
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 00/10] add the support of ipsec offload
2023-09-26 2:49 ` [PATCH v2 00/10] add the support of ipsec offload Chaoyong He
` (9 preceding siblings ...)
2023-09-26 2:49 ` [PATCH v2 10/10] net/nfp: destroy security session Chaoyong He
@ 2023-09-27 14:20 ` Ferruh Yigit
2023-09-28 2:05 ` Chaoyong He
2023-09-29 2:08 ` [PATCH v3 0/9] " Chaoyong He
11 siblings, 1 reply; 42+ messages in thread
From: Ferruh Yigit @ 2023-09-27 14:20 UTC (permalink / raw)
To: Chaoyong He, dev; +Cc: oss-drivers
On 9/26/2023 3:49 AM, Chaoyong He wrote:
> This patch series add the support of ipsec offload feature, includes:
> * Implement the communication channel between PMD and firmware through
> mailbox.
> * Implement the ipsec offload related APIs based the security framework.
> * Implement the ipsec packets process logics in the data path.
>
> ---
> v2:
> * Fix one spell error cause check warning.
> * Try to fix one compile error in Alpine environment of CI.
> ---
>
> Chang Miao (2):
> net/nfp: initialize IPsec related content
> net/nfp: create security session
>
> Shihong Wang (8):
> mailmap: update contributor entry
> net/nfp: add TLVs capability parsing
> net/nfp: add mailbox to support IPsec offload
> net/nfp: get security capabilities and session size
> net/nfp: get IPsec Rx/Tx packet statistics
> net/nfp: update security session
> net/nfp: support IPsec Rx and Tx offload
> net/nfp: destroy security session
>
Hi Chaoyong,
Patchset looks good, but adding ipsec support to driver seems
significant enough to document in the release notes, what do you think?
^ permalink raw reply [flat|nested] 42+ messages in thread
* RE: [PATCH v2 00/10] add the support of ipsec offload
2023-09-27 14:20 ` [PATCH v2 00/10] add the support of ipsec offload Ferruh Yigit
@ 2023-09-28 2:05 ` Chaoyong He
2023-09-28 9:33 ` Ferruh Yigit
0 siblings, 1 reply; 42+ messages in thread
From: Chaoyong He @ 2023-09-28 2:05 UTC (permalink / raw)
To: Ferruh Yigit, dev; +Cc: oss-drivers
> On 9/26/2023 3:49 AM, Chaoyong He wrote:
> > This patch series add the support of ipsec offload feature, includes:
> > * Implement the communication channel between PMD and firmware through
> > mailbox.
> > * Implement the ipsec offload related APIs based the security framework.
> > * Implement the ipsec packets process logics in the data path.
> >
> > ---
> > v2:
> > * Fix one spell error cause check warning.
> > * Try to fix one compile error in Alpine environment of CI.
> > ---
> >
> > Chang Miao (2):
> > net/nfp: initialize IPsec related content
> > net/nfp: create security session
> >
> > Shihong Wang (8):
> > mailmap: update contributor entry
> > net/nfp: add TLVs capability parsing
> > net/nfp: add mailbox to support IPsec offload
> > net/nfp: get security capabilities and session size
> > net/nfp: get IPsec Rx/Tx packet statistics
> > net/nfp: update security session
> > net/nfp: support IPsec Rx and Tx offload
> > net/nfp: destroy security session
> >
>
> Hi Chaoyong,
>
> Patchset looks good, but adding ipsec support to driver seems significant enough
> to document in the release notes, what do you think?
Yeah, I agree. I will try to add that in the next version.
A separate commit for that or squash that into the final commit of this patch series,
which one you think is better?
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 00/10] add the support of ipsec offload
2023-09-28 2:05 ` Chaoyong He
@ 2023-09-28 9:33 ` Ferruh Yigit
0 siblings, 0 replies; 42+ messages in thread
From: Ferruh Yigit @ 2023-09-28 9:33 UTC (permalink / raw)
To: Chaoyong He, dev; +Cc: oss-drivers
On 9/28/2023 3:05 AM, Chaoyong He wrote:
>> On 9/26/2023 3:49 AM, Chaoyong He wrote:
>>> This patch series add the support of ipsec offload feature, includes:
>>> * Implement the communication channel between PMD and firmware through
>>> mailbox.
>>> * Implement the ipsec offload related APIs based the security framework.
>>> * Implement the ipsec packets process logics in the data path.
>>>
>>> ---
>>> v2:
>>> * Fix one spell error cause check warning.
>>> * Try to fix one compile error in Alpine environment of CI.
>>> ---
>>>
>>> Chang Miao (2):
>>> net/nfp: initialize IPsec related content
>>> net/nfp: create security session
>>>
>>> Shihong Wang (8):
>>> mailmap: update contributor entry
>>> net/nfp: add TLVs capability parsing
>>> net/nfp: add mailbox to support IPsec offload
>>> net/nfp: get security capabilities and session size
>>> net/nfp: get IPsec Rx/Tx packet statistics
>>> net/nfp: update security session
>>> net/nfp: support IPsec Rx and Tx offload
>>> net/nfp: destroy security session
>>>
>>
>> Hi Chaoyong,
>>
>> Patchset looks good, but adding ipsec support to driver seems significant enough
>> to document in the release notes, what do you think?
>
> Yeah, I agree. I will try to add that in the next version.
> A separate commit for that or squash that into the final commit of this patch series,
> which one you think is better?
>
Squashing to the most relevant commit it better,
this creates a link between the documentation and the code which is
useful when back tracing a feature in the git history.
^ permalink raw reply [flat|nested] 42+ messages in thread
* [PATCH v3 0/9] add the support of ipsec offload
2023-09-26 2:49 ` [PATCH v2 00/10] add the support of ipsec offload Chaoyong He
` (10 preceding siblings ...)
2023-09-27 14:20 ` [PATCH v2 00/10] add the support of ipsec offload Ferruh Yigit
@ 2023-09-29 2:08 ` Chaoyong He
2023-09-29 2:08 ` [PATCH v3 1/9] net/nfp: add TLVs capability parsing Chaoyong He
` (9 more replies)
11 siblings, 10 replies; 42+ messages in thread
From: Chaoyong He @ 2023-09-29 2:08 UTC (permalink / raw)
To: dev; +Cc: oss-drivers, Chaoyong He
This patch series add the support of ipsec offload feature, includes:
* Implement the communication channel between PMD and firmware through
mailbox.
* Implement the ipsec offload related APIs based the security framework.
* Implement the ipsec packets process logics in the data path.
---
v3:
* Squash the update of mailmap file.
* Add a entry in the release note.
* Remove some unnecessary logic in the TLVs capability parsing function.
v2:
* Fix one spell error cause check warning.
* Try to fix one compile error in Alpine environment of CI.
---
Chang Miao (2):
net/nfp: initialize IPsec related content
net/nfp: create security session
Shihong Wang (7):
net/nfp: add TLVs capability parsing
net/nfp: add mailbox to support IPsec offload
net/nfp: get security capabilities and session size
net/nfp: get IPsec Rx/Tx packet statistics
net/nfp: update security session
net/nfp: support IPsec Rx and Tx offload
net/nfp: destroy security session
.mailmap | 2 +
doc/guides/nics/nfp.rst | 31 +
doc/guides/rel_notes/release_23_11.rst | 5 +
drivers/net/nfp/meson.build | 4 +-
drivers/net/nfp/nfd3/nfp_nfd3_dp.c | 24 +
drivers/net/nfp/nfdk/nfp_nfdk_dp.c | 24 +
drivers/net/nfp/nfp_common.c | 48 +
drivers/net/nfp/nfp_common.h | 12 +
drivers/net/nfp/nfp_ctrl.c | 110 ++
drivers/net/nfp/nfp_ctrl.h | 124 ++
drivers/net/nfp/nfp_ethdev.c | 21 +
drivers/net/nfp/nfp_ipsec.c | 1453 ++++++++++++++++++++++++
drivers/net/nfp/nfp_ipsec.h | 180 +++
drivers/net/nfp/nfp_rxtx.c | 74 ++
drivers/net/nfp/nfp_rxtx.h | 17 +
15 files changed, 2128 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/nfp/nfp_ctrl.c
create mode 100644 drivers/net/nfp/nfp_ipsec.c
create mode 100644 drivers/net/nfp/nfp_ipsec.h
--
2.39.1
^ permalink raw reply [flat|nested] 42+ messages in thread
* [PATCH v3 1/9] net/nfp: add TLVs capability parsing
2023-09-29 2:08 ` [PATCH v3 0/9] " Chaoyong He
@ 2023-09-29 2:08 ` Chaoyong He
2023-09-29 2:08 ` [PATCH v3 2/9] net/nfp: add mailbox to support IPsec offload Chaoyong He
` (8 subsequent siblings)
9 siblings, 0 replies; 42+ messages in thread
From: Chaoyong He @ 2023-09-29 2:08 UTC (permalink / raw)
To: dev; +Cc: oss-drivers, Shihong Wang, Chang Miao, Chaoyong He
From: Shihong Wang <shihong.wang@corigine.com>
Add TLV capabilities to the BAR, TLVs is fit for expressing
capabilities of applications running on programmable hardware.
The TVL capabilities is needed for the upcoming mailbox channel.
Also add contributor entries to .mailmap file.
Signed-off-by: Shihong Wang <shihong.wang@corigine.com>
Signed-off-by: Chang Miao <chang.miao@corigine.com>
Reviewed-by: Chaoyong He <chaoyong.he@corigine.com>
---
.mailmap | 2 +
drivers/net/nfp/meson.build | 1 +
drivers/net/nfp/nfp_common.h | 9 +++
drivers/net/nfp/nfp_ctrl.c | 110 +++++++++++++++++++++++++++++++++
drivers/net/nfp/nfp_ctrl.h | 114 +++++++++++++++++++++++++++++++++++
drivers/net/nfp/nfp_ethdev.c | 6 ++
6 files changed, 242 insertions(+)
create mode 100644 drivers/net/nfp/nfp_ctrl.c
diff --git a/.mailmap b/.mailmap
index 276325211c..5abd5810e2 100644
--- a/.mailmap
+++ b/.mailmap
@@ -200,6 +200,7 @@ Carolyn Wyborny <carolyn.wyborny@intel.com>
Chaeyong Chong <cychong@gmail.com>
Chaitanya Babu Talluri <tallurix.chaitanya.babu@intel.com>
Chandubabu Namburu <chandu@amd.com>
+Chang Miao <chang.miao@corigine.com>
Changchun Ouyang <changchun.ouyang@intel.com>
Changpeng Liu <changpeng.liu@intel.com>
Changqing Wu <changqingx.wu@intel.com>
@@ -1265,6 +1266,7 @@ Shelton Chia <jiaxt@sinogrid.com>
Shepard Siegel <shepard.siegel@atomicrules.com>
Shesha Sreenivasamurthy <shesha@cisco.com>
Shibin Koikkara Reeny <shibin.koikkara.reeny@intel.com>
+Shihong Wang <shihong.wang@corigine.com>
Shijith Thotton <sthotton@marvell.com> <shijith.thotton@caviumnetworks.com>
Shiqi Liu <835703180@qq.com>
Shiri Kuzin <shirik@nvidia.com> <shirik@mellanox.com>
diff --git a/drivers/net/nfp/meson.build b/drivers/net/nfp/meson.build
index d422269c4b..e78bcb8b75 100644
--- a/drivers/net/nfp/meson.build
+++ b/drivers/net/nfp/meson.build
@@ -27,6 +27,7 @@ sources = files(
'nfpcore/nfp_target.c',
'nfpcore/nfp6000_pcie.c',
'nfp_common.c',
+ 'nfp_ctrl.c',
'nfp_rxtx.c',
'nfp_cpp_bridge.c',
'nfp_ethdev_vf.c',
diff --git a/drivers/net/nfp/nfp_common.h b/drivers/net/nfp/nfp_common.h
index b0372c3dc6..b02475b403 100644
--- a/drivers/net/nfp/nfp_common.h
+++ b/drivers/net/nfp/nfp_common.h
@@ -64,6 +64,13 @@ enum nfp_net_meta_format {
NFP_NET_METAFORMAT_CHAINED,
};
+/* Parsed control BAR TLV capabilities */
+struct nfp_net_tlv_caps {
+ uint32_t mbox_off; /**< VNIC mailbox area offset */
+ uint32_t mbox_len; /**< VNIC mailbox area length */
+ uint32_t mbox_cmsg_types; /**< Cmsgs which can be passed through the mailbox */
+};
+
struct nfp_pf_dev {
/* Backpointer to associated pci device */
struct rte_pci_device *pci_dev;
@@ -163,6 +170,8 @@ struct nfp_net_hw {
uint8_t idx;
/* Internal port number as seen from NFP */
uint8_t nfp_idx;
+
+ struct nfp_net_tlv_caps tlv_caps;
};
struct nfp_net_adapter {
diff --git a/drivers/net/nfp/nfp_ctrl.c b/drivers/net/nfp/nfp_ctrl.c
new file mode 100644
index 0000000000..6fc8cffd2e
--- /dev/null
+++ b/drivers/net/nfp/nfp_ctrl.c
@@ -0,0 +1,110 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2023 Corigine Systems, Inc.
+ * All rights reserved.
+ */
+
+#include "nfp_ctrl.h"
+
+#include <ethdev_pci.h>
+
+#include "nfpcore/nfp_platform.h"
+
+#include "nfp_common.h"
+#include "nfp_logs.h"
+
+static void
+nfp_net_tlv_caps_reset(struct nfp_net_tlv_caps *caps)
+{
+ memset(caps, 0, sizeof(*caps));
+ caps->mbox_off = NFP_NET_CFG_MBOX_BASE;
+ caps->mbox_len = NFP_NET_CFG_MBOX_VAL_MAX_SZ;
+}
+
+int
+nfp_net_tlv_caps_parse(struct rte_eth_dev *dev)
+{
+ uint32_t hdr;
+ uint8_t *end;
+ uint8_t *data;
+ uint32_t length;
+ uint32_t offset;
+ uint32_t tlv_type;
+ struct nfp_net_hw *hw;
+ struct nfp_net_tlv_caps *caps;
+
+ hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ caps = &hw->tlv_caps;
+ nfp_net_tlv_caps_reset(caps);
+
+ data = hw->ctrl_bar + NFP_NET_CFG_TLV_BASE;
+ end = hw->ctrl_bar + NFP_NET_CFG_BAR_SZ;
+
+ hdr = rte_read32(data);
+ if (hdr == 0) {
+ PMD_DRV_LOG(INFO, "TLV is empty!");
+ return 0;
+ }
+
+ for (; ; data += length) {
+ offset = data - hw->ctrl_bar;
+
+ if (data + NFP_NET_CFG_TLV_VALUE > end) {
+ PMD_DRV_LOG(ERR, "Reached end of BAR without END TLV");
+ return -EINVAL;
+ }
+
+ hdr = rte_read32(data);
+
+ length = FIELD_GET(NFP_NET_CFG_TLV_HEADER_LENGTH, hdr);
+ if ((length & (NFP_NET_CFG_TLV_LENGTH_INC - 1)) != 0) {
+ PMD_DRV_LOG(ERR, "TLV size not multiple of 4B len: %u", length);
+ return -EINVAL;
+ }
+
+ /* Advance past the header */
+ data += NFP_NET_CFG_TLV_VALUE;
+ if (data + length > end) {
+ PMD_DRV_LOG(ERR, "Oversized TLV offset: %u len: %u",
+ offset, length);
+ return -EINVAL;
+ }
+
+ tlv_type = FIELD_GET(NFP_NET_CFG_TLV_HEADER_TYPE, hdr);
+
+ switch (tlv_type) {
+ case NFP_NET_CFG_TLV_TYPE_UNKNOWN:
+ PMD_DRV_LOG(ERR, "Unknown TLV at offset: %u", offset);
+ return -EINVAL;
+ case NFP_NET_CFG_TLV_TYPE_RESERVED:
+ break;
+ case NFP_NET_CFG_TLV_TYPE_END:
+ if (length == 0)
+ return 0;
+
+ PMD_DRV_LOG(ERR, "END TLV should be empty, has len: %u", length);
+ return -EINVAL;
+ case NFP_NET_CFG_TLV_TYPE_MBOX:
+ caps->mbox_len = length;
+
+ if (length != 0)
+ caps->mbox_off = data - hw->ctrl_bar;
+ else
+ caps->mbox_off = 0;
+ break;
+ case NFP_NET_CFG_TLV_TYPE_MBOX_CMSG_TYPES:
+ if (length != 0)
+ caps->mbox_cmsg_types = rte_read32(data);
+ break;
+ default:
+ if (FIELD_GET(NFP_NET_CFG_TLV_HEADER_REQUIRED, hdr) == 0)
+ break;
+
+ PMD_DRV_LOG(ERR, "Unknown TLV type: %u offset: %u len: %u",
+ tlv_type, offset, length);
+ return -EINVAL;
+ }
+ }
+
+ PMD_DRV_LOG(ERR, "Reached end of BAR without END TLV");
+ return -EINVAL;
+}
diff --git a/drivers/net/nfp/nfp_ctrl.h b/drivers/net/nfp/nfp_ctrl.h
index 53727992a9..43fc9972a0 100644
--- a/drivers/net/nfp/nfp_ctrl.h
+++ b/drivers/net/nfp/nfp_ctrl.h
@@ -8,6 +8,8 @@
#include <stdint.h>
+#include <ethdev_driver.h>
+
/*
* Configuration BAR size.
*
@@ -207,6 +209,9 @@ struct nfp_net_fw_ver {
#define NFP_NET_CFG_RX_OFFSET 0x0050
#define NFP_NET_CFG_RX_OFFSET_DYNAMIC 0 /* Prepend mode */
+/* Start anchor of the TLV area */
+#define NFP_NET_CFG_TLV_BASE 0x0058
+
/**
* Reuse spare address to contain the offset from the start of
* the host buffer where the first byte of the received frame
@@ -434,6 +439,115 @@ struct nfp_net_fw_ver {
#define NFP_PF_CSR_SLICE_SIZE (32 * 1024)
+/*
+ * General use mailbox area (0x1800 - 0x19ff)
+ * 4B used for update command and 4B return code followed by
+ * a max of 504B of variable length value.
+ */
+#define NFP_NET_CFG_MBOX_BASE 0x1800
+#define NFP_NET_CFG_MBOX_VAL 0x1808
+#define NFP_NET_CFG_MBOX_VAL_MAX_SZ 0x1F8
+
+/*
+ * TLV capabilities
+ * @NFP_NET_CFG_TLV_TYPE: Offset of type within the TLV
+ * @NFP_NET_CFG_TLV_TYPE_REQUIRED: Driver must be able to parse the TLV
+ * @NFP_NET_CFG_TLV_LENGTH: Offset of length within the TLV
+ * @NFP_NET_CFG_TLV_LENGTH_INC: TLV length increments
+ * @NFP_NET_CFG_TLV_VALUE: Offset of value with the TLV
+ * @NFP_NET_CFG_TLV_STATS_OFFSET: Length of TLV stats offset
+ *
+ * List of simple TLV structures, first one starts at @NFP_NET_CFG_TLV_BASE.
+ * Last structure must be of type @NFP_NET_CFG_TLV_TYPE_END. Presence of TLVs
+ * is indicated by @NFP_NET_CFG_TLV_BASE being non-zero. TLV structures may
+ * fill the entire remainder of the BAR or be shorter. FW must make sure TLVs
+ * don't conflict with other features which allocate space beyond
+ * @NFP_NET_CFG_TLV_BASE. @NFP_NET_CFG_TLV_TYPE_RESERVED should be used to wrap
+ * space used by such features.
+ *
+ * Note that the 4 byte TLV header is not counted in %NFP_NET_CFG_TLV_LENGTH.
+ */
+#define NFP_NET_CFG_TLV_TYPE 0x00
+#define NFP_NET_CFG_TLV_TYPE_REQUIRED 0x8000
+#define NFP_NET_CFG_TLV_LENGTH 0x02
+#define NFP_NET_CFG_TLV_LENGTH_INC 4
+#define NFP_NET_CFG_TLV_VALUE 0x04
+#define NFP_NET_CFG_TLV_STATS_OFFSET 0x08
+
+#define NFP_NET_CFG_TLV_HEADER_REQUIRED 0x80000000
+#define NFP_NET_CFG_TLV_HEADER_TYPE 0x7fff0000
+#define NFP_NET_CFG_TLV_HEADER_LENGTH 0x0000ffff
+
+/*
+ * Capability TLV types
+ *
+ * @NFP_NET_CFG_TLV_TYPE_UNKNOWN:
+ * Special TLV type to catch bugs, should never be encountered. Drivers should
+ * treat encountering this type as error and refuse to probe.
+ *
+ * @NFP_NET_CFG_TLV_TYPE_RESERVED:
+ * Reserved space, may contain legacy fixed-offset fields, or be used for
+ * padding. The use of this type should be otherwise avoided.
+ *
+ * @NFP_NET_CFG_TLV_TYPE_END:
+ * Empty, end of TLV list. Must be the last TLV. Drivers will stop processing
+ * further TLVs when encountered.
+ *
+ * @NFP_NET_CFG_TLV_TYPE_ME_FREQ:
+ * Single word, ME frequency in MHz as used in calculation for
+ * @NFP_NET_CFG_RXR_IRQ_MOD and @NFP_NET_CFG_TXR_IRQ_MOD.
+ *
+ * @NFP_NET_CFG_TLV_TYPE_MBOX:
+ * Variable, mailbox area. Overwrites the default location which is
+ * @NFP_NET_CFG_MBOX_BASE and length @NFP_NET_CFG_MBOX_VAL_MAX_SZ.
+ *
+ * @NFP_NET_CFG_TLV_TYPE_EXPERIMENTAL0:
+ * @NFP_NET_CFG_TLV_TYPE_EXPERIMENTAL1:
+ * Variable, experimental IDs. IDs designated for internal development and
+ * experiments before a stable TLV ID has been allocated to a feature. Should
+ * never be present in production FW.
+ *
+ * @NFP_NET_CFG_TLV_TYPE_REPR_CAP:
+ * Single word, equivalent of %NFP_NET_CFG_CAP for representors, features which
+ * can be used on representors.
+ *
+ * @NFP_NET_CFG_TLV_TYPE_MBOX_CMSG_TYPES:
+ * Variable, bitmap of control message types supported by the mailbox handler.
+ * Bit 0 corresponds to message type 0, bit 1 to 1, etc. Control messages are
+ * encapsulated into simple TLVs, with an end TLV and written to the Mailbox.
+ *
+ * @NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS:
+ * 8 words, bitmaps of supported and enabled crypto operations.
+ * First 16B (4 words) contains a bitmap of supported crypto operations,
+ * and next 16B contain the enabled operations.
+ * This capability is obsoleted by ones with better sync methods.
+ *
+ * @NFP_NET_CFG_TLV_TYPE_VNIC_STATS:
+ * Variable, per-vNIC statistics, data should be 8B aligned (FW should insert
+ * zero-length RESERVED TLV to pad).
+ * TLV data has two sections. First is an array of statistics' IDs (2B each).
+ * Second 8B statistics themselves. Statistics are 8B aligned, meaning there
+ * may be a padding between sections.
+ * Number of statistics can be determined as floor(tlv.length / (2 + 8)).
+ * This TLV overwrites %NFP_NET_CFG_STATS_* values (statistics in this TLV
+ * duplicate the old ones, so driver should be careful not to unnecessarily
+ * render both).
+ *
+ * @NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS_RX_SCAN:
+ * Same as %NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS, but crypto TLS does stream scan
+ * RX sync, rather than kernel-assisted sync.
+ *
+ * @NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS_LENGTH:
+ * CRYPTO OPS TLV should be at least 32B.
+ */
+#define NFP_NET_CFG_TLV_TYPE_UNKNOWN 0
+#define NFP_NET_CFG_TLV_TYPE_RESERVED 1
+#define NFP_NET_CFG_TLV_TYPE_END 2
+#define NFP_NET_CFG_TLV_TYPE_MBOX 4
+#define NFP_NET_CFG_TLV_TYPE_MBOX_CMSG_TYPES 10
+
+int nfp_net_tlv_caps_parse(struct rte_eth_dev *dev);
+
/*
* nfp_net_cfg_ctrl_rss() - Get RSS flag based on firmware's capability
* @hw_cap: The firmware's capabilities
diff --git a/drivers/net/nfp/nfp_ethdev.c b/drivers/net/nfp/nfp_ethdev.c
index 241595be9d..7dc93f7c43 100644
--- a/drivers/net/nfp/nfp_ethdev.c
+++ b/drivers/net/nfp/nfp_ethdev.c
@@ -549,6 +549,12 @@ nfp_net_init(struct rte_eth_dev *eth_dev)
if (err != 0)
return err;
+ err = nfp_net_tlv_caps_parse(eth_dev);
+ if (err != 0) {
+ PMD_INIT_LOG(ERR, "Failed to parser TLV caps");
+ return err;
+ }
+
nfp_net_ethdev_ops_mount(hw, eth_dev);
hw->eth_xstats_base = rte_malloc("rte_eth_xstat", sizeof(struct rte_eth_xstat) *
--
2.39.1
^ permalink raw reply [flat|nested] 42+ messages in thread
* [PATCH v3 2/9] net/nfp: add mailbox to support IPsec offload
2023-09-29 2:08 ` [PATCH v3 0/9] " Chaoyong He
2023-09-29 2:08 ` [PATCH v3 1/9] net/nfp: add TLVs capability parsing Chaoyong He
@ 2023-09-29 2:08 ` Chaoyong He
2023-09-29 2:08 ` [PATCH v3 3/9] net/nfp: initialize IPsec related content Chaoyong He
` (7 subsequent siblings)
9 siblings, 0 replies; 42+ messages in thread
From: Chaoyong He @ 2023-09-29 2:08 UTC (permalink / raw)
To: dev; +Cc: oss-drivers, Shihong Wang, Chang Miao, Chaoyong He
From: Shihong Wang <shihong.wang@corigine.com>
Add general use per-vNIC mailbox area and use it for IPsec SA
offload support and get Rx/Tx packet statistics.
Signed-off-by: Shihong Wang <shihong.wang@corigine.com>
Signed-off-by: Chang Miao <chang.miao@corigine.com>
Reviewed-by: Chaoyong He <chaoyong.he@corigine.com>
---
drivers/net/nfp/nfp_common.c | 41 ++++++++++++++++++++++++++++++++++++
drivers/net/nfp/nfp_common.h | 1 +
drivers/net/nfp/nfp_ctrl.h | 6 ++++++
3 files changed, 48 insertions(+)
diff --git a/drivers/net/nfp/nfp_common.c b/drivers/net/nfp/nfp_common.c
index 40027dbdfc..31dab3ae9b 100644
--- a/drivers/net/nfp/nfp_common.c
+++ b/drivers/net/nfp/nfp_common.c
@@ -320,6 +320,47 @@ nfp_net_ext_reconfig(struct nfp_net_hw *hw, uint32_t ctrl_ext, uint32_t update)
return 0;
}
+/**
+ * Reconfigure the firmware via the mailbox
+ *
+ * @param hw
+ * Device to reconfigure
+ * @param mbox_cmd
+ * The value for the mailbox command
+ *
+ * @return
+ * - (0) if OK to reconfigure by the mailbox.
+ * - (-EIO) if I/O err and fail to reconfigure by the mailbox
+ */
+int
+nfp_net_mbox_reconfig(struct nfp_net_hw *hw,
+ uint32_t mbox_cmd)
+{
+ int ret;
+ uint32_t mbox;
+
+ mbox = hw->tlv_caps.mbox_off;
+
+ rte_spinlock_lock(&hw->reconfig_lock);
+
+ nn_cfg_writeq(hw, mbox + NFP_NET_CFG_MBOX_SIMPLE_CMD, mbox_cmd);
+ nn_cfg_writel(hw, NFP_NET_CFG_UPDATE, NFP_NET_CFG_UPDATE_MBOX);
+
+ rte_wmb();
+
+ ret = __nfp_net_reconfig(hw, NFP_NET_CFG_UPDATE_MBOX);
+
+ rte_spinlock_unlock(&hw->reconfig_lock);
+
+ if (ret != 0) {
+ PMD_DRV_LOG(ERR, "Error nft net mailbox reconfig: mbox=%#08x update=%#08x",
+ mbox_cmd, NFP_NET_CFG_UPDATE_MBOX);
+ return -EIO;
+ }
+
+ return nn_cfg_readl(hw, mbox + NFP_NET_CFG_MBOX_SIMPLE_RET);
+}
+
/*
* Configure an Ethernet device. This function must be invoked first
* before any other function in the Ethernet API. This function can
diff --git a/drivers/net/nfp/nfp_common.h b/drivers/net/nfp/nfp_common.h
index b02475b403..6487468d81 100644
--- a/drivers/net/nfp/nfp_common.h
+++ b/drivers/net/nfp/nfp_common.h
@@ -331,6 +331,7 @@ nfp_qcp_queue_offset(const struct nfp_dev_info *dev_info,
/* Prototypes for common NFP functions */
int nfp_net_reconfig(struct nfp_net_hw *hw, uint32_t ctrl, uint32_t update);
int nfp_net_ext_reconfig(struct nfp_net_hw *hw, uint32_t ctrl_ext, uint32_t update);
+int nfp_net_mbox_reconfig(struct nfp_net_hw *hw, uint32_t mbox_cmd);
int nfp_net_configure(struct rte_eth_dev *dev);
int nfp_net_common_init(struct rte_pci_device *pci_dev, struct nfp_net_hw *hw);
void nfp_net_log_device_information(const struct nfp_net_hw *hw);
diff --git a/drivers/net/nfp/nfp_ctrl.h b/drivers/net/nfp/nfp_ctrl.h
index 43fc9972a0..0e194538ad 100644
--- a/drivers/net/nfp/nfp_ctrl.h
+++ b/drivers/net/nfp/nfp_ctrl.h
@@ -123,6 +123,7 @@
#define NFP_NET_CFG_UPDATE_IRQMOD (0x1 << 8) /* IRQ mod change */
#define NFP_NET_CFG_UPDATE_VXLAN (0x1 << 9) /* VXLAN port change */
#define NFP_NET_CFG_UPDATE_MACADDR (0x1 << 11) /* MAC address change */
+#define NFP_NET_CFG_UPDATE_MBOX (0x1 << 12) /**< Mailbox update */
#define NFP_NET_CFG_UPDATE_ERR (0x1U << 31) /* A error occurred */
#define NFP_NET_CFG_TXRS_ENABLE 0x0008
#define NFP_NET_CFG_RXRS_ENABLE 0x0010
@@ -447,6 +448,11 @@ struct nfp_net_fw_ver {
#define NFP_NET_CFG_MBOX_BASE 0x1800
#define NFP_NET_CFG_MBOX_VAL 0x1808
#define NFP_NET_CFG_MBOX_VAL_MAX_SZ 0x1F8
+#define NFP_NET_CFG_MBOX_SIMPLE_CMD 0x0
+#define NFP_NET_CFG_MBOX_SIMPLE_RET 0x4
+#define NFP_NET_CFG_MBOX_SIMPLE_VAL 0x8
+
+#define NFP_NET_CFG_MBOX_CMD_IPSEC 3
/*
* TLV capabilities
--
2.39.1
^ permalink raw reply [flat|nested] 42+ messages in thread
* [PATCH v3 3/9] net/nfp: initialize IPsec related content
2023-09-29 2:08 ` [PATCH v3 0/9] " Chaoyong He
2023-09-29 2:08 ` [PATCH v3 1/9] net/nfp: add TLVs capability parsing Chaoyong He
2023-09-29 2:08 ` [PATCH v3 2/9] net/nfp: add mailbox to support IPsec offload Chaoyong He
@ 2023-09-29 2:08 ` Chaoyong He
2023-09-29 10:00 ` Ferruh Yigit
2023-09-29 2:08 ` [PATCH v3 4/9] net/nfp: get security capabilities and session size Chaoyong He
` (6 subsequent siblings)
9 siblings, 1 reply; 42+ messages in thread
From: Chaoyong He @ 2023-09-29 2:08 UTC (permalink / raw)
To: dev; +Cc: oss-drivers, Chang Miao, Shihong Wang, Chaoyong He
From: Chang Miao <chang.miao@corigine.com>
If enable IPsec capability bit, driver need to Initialize IPsec.
Set security context and security offload capabilities in datapath.
Define private session and add SA array for each PF to save all
SA data in driver. Add internal mbuf dynamic flag and field to save
IPsec related data to dynamic mbuf field.
Also update the relase note, add the inline IPsec offload section for NFP
PMD.
Signed-off-by: Chang Miao <chang.miao@corigine.com>
Signed-off-by: Shihong Wang <shihong.wang@corigine.com>
Reviewed-by: Chaoyong He <chaoyong.he@corigine.com>
---
doc/guides/rel_notes/release_23_11.rst | 5 +
drivers/net/nfp/meson.build | 3 +-
drivers/net/nfp/nfp_common.c | 7 +
drivers/net/nfp/nfp_common.h | 2 +
drivers/net/nfp/nfp_ctrl.h | 3 +
drivers/net/nfp/nfp_ethdev.c | 15 +++
drivers/net/nfp/nfp_ipsec.c | 131 +++++++++++++++++++
drivers/net/nfp/nfp_ipsec.h | 174 +++++++++++++++++++++++++
drivers/net/nfp/nfp_rxtx.h | 12 ++
9 files changed, 351 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/nfp/nfp_ipsec.c
create mode 100644 drivers/net/nfp/nfp_ipsec.h
diff --git a/doc/guides/rel_notes/release_23_11.rst b/doc/guides/rel_notes/release_23_11.rst
index d5f8325a99..de755e54bf 100644
--- a/doc/guides/rel_notes/release_23_11.rst
+++ b/doc/guides/rel_notes/release_23_11.rst
@@ -38,6 +38,11 @@ DPDK Release 23.11
which also added support for standard atomics
(Ref: https://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html)
+ * **Added inline IPsec offload feature for NFP PMD.**
+
+ Added the inline IPsec offload feature based on the security framework for
+ NFP PMD.
+
New Features
------------
diff --git a/drivers/net/nfp/meson.build b/drivers/net/nfp/meson.build
index e78bcb8b75..3912566134 100644
--- a/drivers/net/nfp/meson.build
+++ b/drivers/net/nfp/meson.build
@@ -33,8 +33,9 @@ sources = files(
'nfp_ethdev_vf.c',
'nfp_ethdev.c',
'nfp_flow.c',
+ 'nfp_ipsec.c',
'nfp_logs.c',
'nfp_mtr.c',
)
-deps += ['hash']
+deps += ['hash', 'security']
diff --git a/drivers/net/nfp/nfp_common.c b/drivers/net/nfp/nfp_common.c
index 31dab3ae9b..5683afc40a 100644
--- a/drivers/net/nfp/nfp_common.c
+++ b/drivers/net/nfp/nfp_common.c
@@ -1200,6 +1200,7 @@ nfp_net_tx_desc_limits(struct nfp_net_hw *hw,
int
nfp_net_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
{
+ uint32_t cap_extend;
uint16_t min_rx_desc;
uint16_t max_rx_desc;
uint16_t min_tx_desc;
@@ -1256,6 +1257,12 @@ nfp_net_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
if (hw->cap & NFP_NET_CFG_CTRL_GATHER)
dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_MULTI_SEGS;
+ cap_extend = nn_cfg_readl(hw, NFP_NET_CFG_CAP_WORD1);
+ if ((cap_extend & NFP_NET_CFG_CTRL_IPSEC) != 0) {
+ dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_SECURITY;
+ dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_SECURITY;
+ }
+
dev_info->default_rxconf = (struct rte_eth_rxconf) {
.rx_thresh = {
.pthresh = DEFAULT_RX_PTHRESH,
diff --git a/drivers/net/nfp/nfp_common.h b/drivers/net/nfp/nfp_common.h
index 6487468d81..bc3a948231 100644
--- a/drivers/net/nfp/nfp_common.h
+++ b/drivers/net/nfp/nfp_common.h
@@ -172,6 +172,8 @@ struct nfp_net_hw {
uint8_t nfp_idx;
struct nfp_net_tlv_caps tlv_caps;
+
+ struct nfp_net_ipsec_data *ipsec_data;
};
struct nfp_net_adapter {
diff --git a/drivers/net/nfp/nfp_ctrl.h b/drivers/net/nfp/nfp_ctrl.h
index 0e194538ad..99890a33a1 100644
--- a/drivers/net/nfp/nfp_ctrl.h
+++ b/drivers/net/nfp/nfp_ctrl.h
@@ -238,6 +238,9 @@ struct nfp_net_fw_ver {
*/
#define NFP_NET_CFG_CTRL_WORD1 0x0098
#define NFP_NET_CFG_CTRL_PKT_TYPE (0x1 << 0)
+#define NFP_NET_CFG_CTRL_IPSEC (0x1 << 1) /**< IPsec offload */
+#define NFP_NET_CFG_CTRL_IPSEC_SM_LOOKUP (0x1 << 3) /**< SA short match lookup */
+#define NFP_NET_CFG_CTRL_IPSEC_LM_LOOKUP (0x1 << 4) /**< SA long match lookup */
#define NFP_NET_CFG_CAP_WORD1 0x00a4
diff --git a/drivers/net/nfp/nfp_ethdev.c b/drivers/net/nfp/nfp_ethdev.c
index 7dc93f7c43..ebc5538291 100644
--- a/drivers/net/nfp/nfp_ethdev.c
+++ b/drivers/net/nfp/nfp_ethdev.c
@@ -18,6 +18,7 @@
#include "nfpcore/nfp6000_pcie.h"
#include "nfp_cpp_bridge.h"
+#include "nfp_ipsec.h"
#include "nfp_logs.h"
static int
@@ -140,6 +141,10 @@ nfp_net_start(struct rte_eth_dev *dev)
if ((cap_extend & NFP_NET_CFG_CTRL_PKT_TYPE) != 0)
ctrl_extend = NFP_NET_CFG_CTRL_PKT_TYPE;
+ if ((cap_extend & NFP_NET_CFG_CTRL_IPSEC) != 0)
+ ctrl_extend |= NFP_NET_CFG_CTRL_IPSEC_SM_LOOKUP
+ | NFP_NET_CFG_CTRL_IPSEC_LM_LOOKUP;
+
update = NFP_NET_CFG_UPDATE_GEN;
if (nfp_net_ext_reconfig(hw, ctrl_extend, update) < 0)
return -EIO;
@@ -278,6 +283,9 @@ nfp_net_close(struct rte_eth_dev *dev)
nfp_net_close_rx_queue(dev);
+ /* Clear ipsec */
+ nfp_ipsec_uninit(dev);
+
/* Cancel possible impending LSC work here before releasing the port*/
rte_eal_alarm_cancel(nfp_net_dev_interrupt_delayed_handler,
(void *)dev);
@@ -555,6 +563,12 @@ nfp_net_init(struct rte_eth_dev *eth_dev)
return err;
}
+ err = nfp_ipsec_init(eth_dev);
+ if (err != 0) {
+ PMD_INIT_LOG(ERR, "Failed to init IPsec module");
+ return err;
+ }
+
nfp_net_ethdev_ops_mount(hw, eth_dev);
hw->eth_xstats_base = rte_malloc("rte_eth_xstat", sizeof(struct rte_eth_xstat) *
@@ -867,6 +881,7 @@ nfp_init_app_fw_nic(struct nfp_pf_dev *pf_dev,
if (app_fw_nic->ports[i] && app_fw_nic->ports[i]->eth_dev) {
struct rte_eth_dev *tmp_dev;
tmp_dev = app_fw_nic->ports[i]->eth_dev;
+ nfp_ipsec_uninit(tmp_dev);
rte_eth_dev_release_port(tmp_dev);
app_fw_nic->ports[i] = NULL;
}
diff --git a/drivers/net/nfp/nfp_ipsec.c b/drivers/net/nfp/nfp_ipsec.c
new file mode 100644
index 0000000000..f16ce97703
--- /dev/null
+++ b/drivers/net/nfp/nfp_ipsec.c
@@ -0,0 +1,131 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2023 Corigine Systems, Inc.
+ * All rights reserved.
+ */
+
+#include "nfp_ipsec.h"
+
+#include <rte_malloc.h>
+#include <rte_security_driver.h>
+
+#include <ethdev_driver.h>
+#include <ethdev_pci.h>
+
+#include "nfp_common.h"
+#include "nfp_ctrl.h"
+#include "nfp_logs.h"
+#include "nfp_rxtx.h"
+
+static const struct rte_security_ops nfp_security_ops;
+
+static int
+nfp_ipsec_ctx_create(struct rte_eth_dev *dev,
+ struct nfp_net_ipsec_data *data)
+{
+ struct rte_security_ctx *ctx;
+ static const struct rte_mbuf_dynfield pkt_md_dynfield = {
+ .name = "nfp_ipsec_crypto_pkt_metadata",
+ .size = sizeof(struct nfp_tx_ipsec_desc_msg),
+ .align = __alignof__(struct nfp_tx_ipsec_desc_msg),
+ };
+
+ ctx = rte_zmalloc("security_ctx",
+ sizeof(struct rte_security_ctx), 0);
+ if (ctx == NULL) {
+ PMD_INIT_LOG(ERR, "Failed to malloc security_ctx");
+ return -ENOMEM;
+ }
+
+ ctx->device = dev;
+ ctx->ops = &nfp_security_ops;
+ ctx->sess_cnt = 0;
+ dev->security_ctx = ctx;
+
+ data->pkt_dynfield_offset = rte_mbuf_dynfield_register(&pkt_md_dynfield);
+ if (data->pkt_dynfield_offset < 0) {
+ PMD_INIT_LOG(ERR, "Failed to register mbuf esn_dynfield");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+int
+nfp_ipsec_init(struct rte_eth_dev *dev)
+{
+ int ret;
+ uint32_t cap_extend;
+ struct nfp_net_hw *hw;
+ struct nfp_net_ipsec_data *data;
+
+ hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+ cap_extend = nn_cfg_readl(hw, NFP_NET_CFG_CAP_WORD1);
+ if ((cap_extend & NFP_NET_CFG_CTRL_IPSEC) == 0) {
+ PMD_INIT_LOG(INFO, "Unsupported IPsec extend capability");
+ return 0;
+ }
+
+ data = rte_zmalloc("ipsec_data", sizeof(struct nfp_net_ipsec_data), 0);
+ if (data == NULL) {
+ PMD_INIT_LOG(ERR, "Failed to malloc ipsec_data");
+ return -ENOMEM;
+ }
+
+ data->pkt_dynfield_offset = -1;
+ data->sa_free_cnt = NFP_NET_IPSEC_MAX_SA_CNT;
+ hw->ipsec_data = data;
+
+ ret = nfp_ipsec_ctx_create(dev, data);
+ if (ret != 0) {
+ PMD_INIT_LOG(ERR, "Failed to create IPsec ctx");
+ goto ipsec_cleanup;
+ }
+
+ return 0;
+
+ipsec_cleanup:
+ nfp_ipsec_uninit(dev);
+
+ return ret;
+}
+
+static void
+nfp_ipsec_ctx_destroy(struct rte_eth_dev *dev)
+{
+ if (dev->security_ctx != NULL)
+ rte_free(dev->security_ctx);
+}
+
+void
+nfp_ipsec_uninit(struct rte_eth_dev *dev)
+{
+ uint16_t i;
+ uint32_t cap_extend;
+ struct nfp_net_hw *hw;
+ struct nfp_ipsec_session *priv_session;
+
+ hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+ cap_extend = nn_cfg_readl(hw, NFP_NET_CFG_CAP_WORD1);
+ if ((cap_extend & NFP_NET_CFG_CTRL_IPSEC) == 0) {
+ PMD_INIT_LOG(INFO, "Unsupported IPsec extend capability");
+ return;
+ }
+
+ nfp_ipsec_ctx_destroy(dev);
+
+ if (hw->ipsec_data == NULL) {
+ PMD_INIT_LOG(INFO, "IPsec data is NULL!");
+ return;
+ }
+
+ for (i = 0; i < NFP_NET_IPSEC_MAX_SA_CNT; i++) {
+ priv_session = hw->ipsec_data->sa_entries[i];
+ if (priv_session != NULL)
+ memset(priv_session, 0, sizeof(struct nfp_ipsec_session));
+ }
+
+ rte_free(hw->ipsec_data);
+}
+
diff --git a/drivers/net/nfp/nfp_ipsec.h b/drivers/net/nfp/nfp_ipsec.h
new file mode 100644
index 0000000000..06792199c6
--- /dev/null
+++ b/drivers/net/nfp/nfp_ipsec.h
@@ -0,0 +1,174 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2023 Corigine Systems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef __NFP_IPSEC_H__
+#define __NFP_IPSEC_H__
+
+#include <rte_security.h>
+
+#define NFP_NET_IPSEC_MAX_SA_CNT (16 * 1024)
+
+struct ipsec_aesgcm { /**< AES-GCM-ESP fields */
+ uint32_t salt; /**< Initialized with SA */
+ uint32_t iv[2]; /**< Firmware use only */
+ uint32_t cntrl;
+ uint32_t zeros[4]; /**< Init to 0 with SA */
+ uint32_t len_auth[2]; /**< Firmware use only */
+ uint32_t len_cipher[2];
+ uint32_t spare[4];
+};
+
+struct sa_ctrl_word {
+ uint32_t hash :4; /**< From nfp_ipsec_hash_type */
+ uint32_t cimode :4; /**< From nfp_ipsec_cipher_mode */
+ uint32_t cipher :4; /**< From nfp_ipsec_cipher */
+ uint32_t mode :2; /**< From nfp_ipsec_mode */
+ uint32_t proto :2; /**< From nfp_ipsec_prot */
+ uint32_t spare :1; /**< Should be 0 */
+ uint32_t ena_arw:1; /**< Anti-Replay Window */
+ uint32_t ext_seq:1; /**< 64-bit Sequence Num */
+ uint32_t ext_arw:1; /**< 64b Anti-Replay Window */
+ uint32_t spare1 :9; /**< Must be set to 0 */
+ uint32_t encap_dsbl:1; /**< Encap/decap disable */
+ uint32_t gen_seq:1; /**< Firmware Generate Seq #'s */
+ uint32_t spare2 :1; /**< Must be set to 0 */
+};
+
+union nfp_ip_addr {
+ struct in6_addr v6;
+ struct in_addr v4;
+};
+
+struct ipsec_add_sa {
+ uint32_t cipher_key[8]; /**< Cipher Key */
+ union {
+ uint32_t auth_key[16]; /**< Authentication Key */
+ struct ipsec_aesgcm aesgcm_fields;
+ };
+ struct sa_ctrl_word ctrl_word;
+ uint32_t spi; /**< SPI Value */
+ uint16_t pmtu_limit; /**< PMTU Limit */
+ uint32_t spare :1;
+ uint32_t frag_check :1; /**< Stateful fragment checking flag */
+ uint32_t bypass_DSCP:1; /**< Bypass DSCP Flag */
+ uint32_t df_ctrl :2; /**< DF Control bits */
+ uint32_t ipv6 :1; /**< Outbound IPv6 addr format */
+ uint32_t udp_enable :1; /**< Add/Remove UDP header for NAT */
+ uint32_t tfc_enable :1; /**< Traffic Flw Confidentiality */
+ uint8_t spare1;
+ uint32_t soft_byte_cnt; /**< Soft lifetime byte count */
+ uint32_t hard_byte_cnt; /**< Hard lifetime byte count */
+ union nfp_ip_addr src_ip; /**< Src IP addr */
+ union nfp_ip_addr dst_ip; /**< Dst IP addr */
+ uint16_t natt_dst_port; /**< NAT-T UDP Header dst port */
+ uint16_t natt_src_port; /**< NAT-T UDP Header src port */
+ uint32_t soft_lifetime_limit; /**< Soft lifetime time limit */
+ uint32_t hard_lifetime_limit; /**< Hard lifetime time limit */
+ uint32_t sa_time_lo; /**< SA creation time lower 32bits, Ucode fills this in */
+ uint32_t sa_time_hi; /**< SA creation time high 32bits, Ucode fills this in */
+ uint16_t spare2;
+ uint16_t tfc_padding; /**< Traffic Flow Confidential Pad */
+};
+
+struct ipsec_inv_sa {
+ uint32_t spare;
+};
+
+struct ipsec_discard_stats {
+ uint32_t discards_auth; /**< Auth failures */
+ uint32_t discards_unsupported; /**< Unsupported crypto mode */
+ uint32_t discards_alignment; /**< Alignment error */
+ uint32_t discards_hard_bytelimit; /**< Hard byte Count limit */
+ uint32_t discards_seq_num_wrap; /**< Sequ Number wrap */
+ uint32_t discards_pmtu_exceeded; /**< PMTU Limit exceeded*/
+ uint32_t discards_arw_old_seq; /**< Anti-Replay seq small */
+ uint32_t discards_arw_replay; /**< Anti-Replay seq rcvd */
+ uint32_t discards_ctrl_word; /**< Bad SA Control word */
+ uint32_t discards_ip_hdr_len; /**< Hdr offset from too high */
+ uint32_t discards_eop_buf; /**< No EOP buffer */
+ uint32_t ipv4_id_counter; /**< IPv4 ID field counter */
+ uint32_t discards_isl_fail; /**< Inbound SPD Lookup failure */
+ uint32_t discards_ext_unfound; /**< Ext header end */
+ uint32_t discards_max_ext_hdrs; /**< Max ext header */
+ uint32_t discards_non_ext_hdrs; /**< Non-extension headers */
+ uint32_t discards_ext_hdr_too_big; /**< Ext header chain */
+ uint32_t discards_hard_timelimit; /**< Time Limit */
+};
+
+struct ipsec_get_sa_stats {
+ uint32_t seq_lo; /**< Sequence Number (low 32bits) */
+ uint32_t seq_high; /**< Sequence Number (high 32bits)*/
+ uint32_t arw_counter_lo; /**< Anti-replay wndw cntr */
+ uint32_t arw_counter_high; /**< Anti-replay wndw cntr */
+ uint32_t arw_bitmap_lo; /**< Anti-replay wndw bitmap */
+ uint32_t arw_bitmap_high; /**< Anti-replay wndw bitmap */
+ uint32_t spare:1;
+ uint32_t soft_byte_exceeded :1; /**< Soft lifetime byte cnt exceeded*/
+ uint32_t hard_byte_exceeded :1; /**< Hard lifetime byte cnt exceeded*/
+ uint32_t soft_time_exceeded :1; /**< Soft lifetime time limit exceeded*/
+ uint32_t hard_time_exceeded :1; /**< Hard lifetime time limit exceeded*/
+ uint32_t spare1:27;
+ uint32_t lifetime_byte_count;
+ uint32_t pkt_count;
+ struct ipsec_discard_stats sa_discard_stats;
+};
+
+struct ipsec_get_seq {
+ uint32_t seq_nums; /**< Sequence numbers to allocate */
+ uint32_t seq_num_low; /**< Return start seq num 31:00 */
+ uint32_t seq_num_hi; /**< Return start seq num 63:32 */
+};
+
+struct nfp_ipsec_msg {
+ union {
+ struct {
+ /** NFP IPsec SA cmd message codes */
+ uint16_t cmd;
+ /** NFP IPsec SA response message */
+ uint16_t rsp;
+ /** NFP IPsec SA index in driver SA table */
+ uint16_t sa_idx;
+ /** Reserved */
+ uint16_t spare;
+ union {
+ /** IPsec configure message for add SA */
+ struct ipsec_add_sa cfg_add_sa;
+ /** IPsec configure message for del SA */
+ struct ipsec_inv_sa cfg_inv_sa;
+ /** IPsec configure message for get SA stats */
+ struct ipsec_get_sa_stats cfg_get_stats;
+ /** IPsec configure message for get SA seq numbers */
+ struct ipsec_get_seq cfg_get_seq;
+ };
+ };
+ uint32_t raw[64];
+ };
+};
+
+struct nfp_ipsec_session {
+ /** Opaque user defined data */
+ void *user_data;
+ /** NFP sa_entries database parameter index */
+ uint32_t sa_index;
+ /** Point to physical ports ethernet device */
+ struct rte_eth_dev *dev;
+ /** SA related NPF configuration data */
+ struct ipsec_add_sa msg;
+ /** Security association configuration data */
+ struct rte_security_ipsec_xform ipsec;
+ /** Security session action type */
+ enum rte_security_session_action_type action;
+} __rte_cache_aligned;
+
+struct nfp_net_ipsec_data {
+ int pkt_dynfield_offset;
+ uint32_t sa_free_cnt;
+ struct nfp_ipsec_session *sa_entries[NFP_NET_IPSEC_MAX_SA_CNT];
+};
+
+int nfp_ipsec_init(struct rte_eth_dev *dev);
+void nfp_ipsec_uninit(struct rte_eth_dev *dev);
+
+#endif /* __NFP_IPSEC_H__ */
diff --git a/drivers/net/nfp/nfp_rxtx.h b/drivers/net/nfp/nfp_rxtx.h
index ddbf97e46c..4e8558074e 100644
--- a/drivers/net/nfp/nfp_rxtx.h
+++ b/drivers/net/nfp/nfp_rxtx.h
@@ -43,6 +43,18 @@ struct nfp_net_dp_buf {
struct rte_mbuf *mbuf;
};
+struct nfp_tx_ipsec_desc_msg {
+ uint32_t sa_idx; /**< SA index in driver table */
+ uint32_t enc; /**< IPsec enable flag */
+ union {
+ uint64_t value;
+ struct {
+ uint32_t low;
+ uint32_t hi;
+ };
+ } esn; /**< Extended Sequence Number */
+};
+
struct nfp_net_txq {
/** Backpointer to nfp_net structure */
struct nfp_net_hw *hw;
--
2.39.1
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v3 3/9] net/nfp: initialize IPsec related content
2023-09-29 2:08 ` [PATCH v3 3/9] net/nfp: initialize IPsec related content Chaoyong He
@ 2023-09-29 10:00 ` Ferruh Yigit
0 siblings, 0 replies; 42+ messages in thread
From: Ferruh Yigit @ 2023-09-29 10:00 UTC (permalink / raw)
To: Chaoyong He, dev; +Cc: oss-drivers, Chang Miao, Shihong Wang
On 9/29/2023 3:08 AM, Chaoyong He wrote:
> From: Chang Miao <chang.miao@corigine.com>
>
> If enable IPsec capability bit, driver need to Initialize IPsec.
> Set security context and security offload capabilities in datapath.
> Define private session and add SA array for each PF to save all
> SA data in driver. Add internal mbuf dynamic flag and field to save
> IPsec related data to dynamic mbuf field.
>
> Also update the relase note, add the inline IPsec offload section for NFP
> PMD.
>
> Signed-off-by: Chang Miao <chang.miao@corigine.com>
> Signed-off-by: Shihong Wang <shihong.wang@corigine.com>
> Reviewed-by: Chaoyong He <chaoyong.he@corigine.com>
>
<...>
> @@ -38,6 +38,11 @@ DPDK Release 23.11
> which also added support for standard atomics
> (Ref: https://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html)
>
> + * **Added inline IPsec offload feature for NFP PMD.**
> +
> + Added the inline IPsec offload feature based on the security framework for
> + NFP PMD.
> +
> New Features
> ------------
>
Moving release notes update to "New Features" section below while merging.
^ permalink raw reply [flat|nested] 42+ messages in thread
* [PATCH v3 4/9] net/nfp: get security capabilities and session size
2023-09-29 2:08 ` [PATCH v3 0/9] " Chaoyong He
` (2 preceding siblings ...)
2023-09-29 2:08 ` [PATCH v3 3/9] net/nfp: initialize IPsec related content Chaoyong He
@ 2023-09-29 2:08 ` Chaoyong He
2023-09-29 2:08 ` [PATCH v3 5/9] net/nfp: get IPsec Rx/Tx packet statistics Chaoyong He
` (5 subsequent siblings)
9 siblings, 0 replies; 42+ messages in thread
From: Chaoyong He @ 2023-09-29 2:08 UTC (permalink / raw)
To: dev; +Cc: oss-drivers, Shihong Wang, Chaoyong He
From: Shihong Wang <shihong.wang@corigine.com>
Add full protocol offload as well as inline crypto IPsec
capabilities and return these for rte_security.
Return size of security session for rte_security.
Signed-off-by: Shihong Wang <shihong.wang@corigine.com>
Reviewed-by: Chaoyong He <chaoyong.he@corigine.com>
---
drivers/net/nfp/nfp_ipsec.c | 357 +++++++++++++++++++++++++++++++++++-
1 file changed, 356 insertions(+), 1 deletion(-)
diff --git a/drivers/net/nfp/nfp_ipsec.c b/drivers/net/nfp/nfp_ipsec.c
index f16ce97703..51770def9d 100644
--- a/drivers/net/nfp/nfp_ipsec.c
+++ b/drivers/net/nfp/nfp_ipsec.c
@@ -5,6 +5,7 @@
#include "nfp_ipsec.h"
+#include <rte_cryptodev.h>
#include <rte_malloc.h>
#include <rte_security_driver.h>
@@ -16,7 +17,361 @@
#include "nfp_logs.h"
#include "nfp_rxtx.h"
-static const struct rte_security_ops nfp_security_ops;
+static const struct rte_cryptodev_capabilities nfp_crypto_caps[] = {
+ {
+ .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ .sym = {
+ .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+ .auth = {
+ .algo = RTE_CRYPTO_AUTH_MD5_HMAC,
+ .block_size = 64,
+ .key_size = {
+ .min = 16,
+ .max = 16,
+ .increment = 0
+ },
+ .digest_size = {
+ .min = 12,
+ .max = 16,
+ .increment = 4
+ },
+ },
+ },
+ },
+ {
+ .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ .sym = {
+ .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+ .auth = {
+ .algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .block_size = 64,
+ .key_size = {
+ .min = 20,
+ .max = 64,
+ .increment = 1
+ },
+ .digest_size = {
+ .min = 10,
+ .max = 12,
+ .increment = 2
+ },
+ },
+ },
+ },
+ {
+ .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ .sym = {
+ .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+ .auth = {
+ .algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
+ .block_size = 64,
+ .key_size = {
+ .min = 32,
+ .max = 32,
+ .increment = 0
+ },
+ .digest_size = {
+ .min = 12,
+ .max = 16,
+ .increment = 4
+ },
+ },
+ },
+ },
+ {
+ .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ .sym = {
+ .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+ .auth = {
+ .algo = RTE_CRYPTO_AUTH_SHA384_HMAC,
+ .block_size = 128,
+ .key_size = {
+ .min = 48,
+ .max = 48,
+ .increment = 0
+ },
+ .digest_size = {
+ .min = 12,
+ .max = 24,
+ .increment = 12
+ },
+ },
+ },
+ },
+ {
+ .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ .sym = {
+ .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+ .auth = {
+ .algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
+ .block_size = 128,
+ .key_size = {
+ .min = 64,
+ .max = 64,
+ .increment = 1
+ },
+ .digest_size = {
+ .min = 12,
+ .max = 32,
+ .increment = 4
+ },
+ },
+ },
+ },
+ {
+ .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ .sym = {
+ .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+ .cipher = {
+ .algo = RTE_CRYPTO_CIPHER_3DES_CBC,
+ .block_size = 8,
+ .key_size = {
+ .min = 24,
+ .max = 24,
+ .increment = 0
+ },
+ .iv_size = {
+ .min = 8,
+ .max = 16,
+ .increment = 8
+ },
+ },
+ },
+ },
+ {
+ .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ .sym = {
+ .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+ .cipher = {
+ .algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .block_size = 16,
+ .key_size = {
+ .min = 16,
+ .max = 32,
+ .increment = 8
+ },
+ .iv_size = {
+ .min = 8,
+ .max = 16,
+ .increment = 8
+ },
+ },
+ },
+ },
+ {
+ .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 = 32,
+ .increment = 8
+ },
+ .digest_size = {
+ .min = 16,
+ .max = 16,
+ .increment = 0
+ },
+ .aad_size = {
+ .min = 0,
+ .max = 1024,
+ .increment = 1
+ },
+ .iv_size = {
+ .min = 8,
+ .max = 16,
+ .increment = 4
+ }
+ },
+ },
+ },
+ {
+ .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ .sym = {
+ .xform_type = RTE_CRYPTO_SYM_XFORM_AEAD,
+ .aead = {
+ .algo = RTE_CRYPTO_AEAD_CHACHA20_POLY1305,
+ .block_size = 16,
+ .key_size = {
+ .min = 32,
+ .max = 32,
+ .increment = 0
+ },
+ .digest_size = {
+ .min = 16,
+ .max = 16,
+ .increment = 0
+ },
+ .aad_size = {
+ .min = 0,
+ .max = 1024,
+ .increment = 1
+ },
+ .iv_size = {
+ .min = 8,
+ .max = 16,
+ .increment = 4
+ }
+ },
+ },
+ },
+ {
+ .op = RTE_CRYPTO_OP_TYPE_UNDEFINED,
+ .sym = {
+ .xform_type = RTE_CRYPTO_SYM_XFORM_NOT_SPECIFIED
+ },
+ }
+};
+
+static const struct rte_security_capability nfp_security_caps[] = {
+ { /* IPsec Inline Crypto Tunnel Egress */
+ .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+ .direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .options = {
+ .udp_encap = 1,
+ .stats = 1,
+ .esn = 1
+ }
+ },
+ .crypto_capabilities = nfp_crypto_caps
+ },
+ { /* IPsec Inline Crypto Tunnel Ingress */
+ .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+ .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .options = {
+ .udp_encap = 1,
+ .stats = 1,
+ .esn = 1
+ }
+ },
+ .crypto_capabilities = nfp_crypto_caps,
+ .ol_flags = RTE_SECURITY_TX_OLOAD_NEED_MDATA
+ },
+ { /* IPsec Inline Crypto Transport Egress */
+ .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
+ .direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .options = {
+ .udp_encap = 1,
+ .stats = 1,
+ .esn = 1
+ }
+ },
+ .crypto_capabilities = nfp_crypto_caps
+ },
+ { /* IPsec Inline Crypto Transport Ingress */
+ .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
+ .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .options = {
+ .udp_encap = 1,
+ .stats = 1,
+ .esn = 1
+ }
+ },
+ .crypto_capabilities = nfp_crypto_caps,
+ .ol_flags = RTE_SECURITY_TX_OLOAD_NEED_MDATA
+ },
+ { /* IPsec Inline Protocol Tunnel Egress */
+ .action = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+ .direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .options = {
+ .udp_encap = 1,
+ .stats = 1,
+ .esn = 1
+ }
+ },
+ .crypto_capabilities = nfp_crypto_caps
+ },
+ { /* IPsec Inline Protocol Tunnel Ingress */
+ .action = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+ .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .options = {
+ .udp_encap = 1,
+ .stats = 1,
+ .esn = 1
+ }
+ },
+ .crypto_capabilities = nfp_crypto_caps,
+ .ol_flags = RTE_SECURITY_TX_OLOAD_NEED_MDATA
+ },
+ { /* IPsec Inline Protocol Transport Egress */
+ .action = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
+ .direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .options = {
+ .udp_encap = 1,
+ .stats = 1,
+ .esn = 1
+ }
+ },
+ .crypto_capabilities = nfp_crypto_caps
+ },
+ { /* IPsec Inline Protocol Transport Ingress */
+ .action = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
+ .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .options = {
+ .udp_encap = 1,
+ .stats = 1,
+ .esn = 1
+ }
+ },
+ .crypto_capabilities = nfp_crypto_caps,
+ .ol_flags = RTE_SECURITY_TX_OLOAD_NEED_MDATA
+ },
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_NONE
+ }
+};
+
+static const struct rte_security_capability *
+nfp_crypto_capabilities_get(void *device __rte_unused)
+{
+ return nfp_security_caps;
+}
+
+static uint32_t
+nfp_security_session_get_size(void *device __rte_unused)
+{
+ return sizeof(struct nfp_ipsec_session);
+}
+
+static const struct rte_security_ops nfp_security_ops = {
+ .session_get_size = nfp_security_session_get_size,
+ .capabilities_get = nfp_crypto_capabilities_get,
+};
static int
nfp_ipsec_ctx_create(struct rte_eth_dev *dev,
--
2.39.1
^ permalink raw reply [flat|nested] 42+ messages in thread
* [PATCH v3 5/9] net/nfp: get IPsec Rx/Tx packet statistics
2023-09-29 2:08 ` [PATCH v3 0/9] " Chaoyong He
` (3 preceding siblings ...)
2023-09-29 2:08 ` [PATCH v3 4/9] net/nfp: get security capabilities and session size Chaoyong He
@ 2023-09-29 2:08 ` Chaoyong He
2023-09-29 2:08 ` [PATCH v3 6/9] net/nfp: create security session Chaoyong He
` (4 subsequent siblings)
9 siblings, 0 replies; 42+ messages in thread
From: Chaoyong He @ 2023-09-29 2:08 UTC (permalink / raw)
To: dev; +Cc: oss-drivers, Shihong Wang, Chaoyong He
From: Shihong Wang <shihong.wang@corigine.com>
IPsec packet processing is mostly carried out in hardware.
The hardware statistics on successful packets and discarded
packets. The driver can obtain these statistics by Mailbox.
Signed-off-by: Shihong Wang <shihong.wang@corigine.com>
Reviewed-by: Chaoyong He <chaoyong.he@corigine.com>
---
drivers/net/nfp/nfp_ipsec.c | 149 ++++++++++++++++++++++++++++++++++++
1 file changed, 149 insertions(+)
diff --git a/drivers/net/nfp/nfp_ipsec.c b/drivers/net/nfp/nfp_ipsec.c
index 51770def9d..d4292c3b90 100644
--- a/drivers/net/nfp/nfp_ipsec.c
+++ b/drivers/net/nfp/nfp_ipsec.c
@@ -356,6 +356,154 @@ static const struct rte_security_capability nfp_security_caps[] = {
}
};
+/* IPsec config message cmd codes */
+enum nfp_ipsec_cfg_msg_cmd_codes {
+ NFP_IPSEC_CFG_MSG_ADD_SA, /**< Add a new SA */
+ NFP_IPSEC_CFG_MSG_INV_SA, /**< Invalidate an existing SA */
+ NFP_IPSEC_CFG_MSG_MODIFY_SA, /**< Modify an existing SA */
+ NFP_IPSEC_CFG_MSG_GET_SA_STATS, /**< Report SA counters, flags, etc. */
+ NFP_IPSEC_CFG_MSG_GET_SEQ_NUMS, /**< Allocate sequence numbers */
+ NFP_IPSEC_CFG_MSG_LAST
+};
+
+enum nfp_ipsec_cfg_msg_rsp_codes {
+ NFP_IPSEC_CFG_MSG_OK,
+ NFP_IPSEC_CFG_MSG_FAILED,
+ NFP_IPSEC_CFG_MSG_SA_VALID,
+ NFP_IPSEC_CFG_MSG_SA_HASH_ADD_FAILED,
+ NFP_IPSEC_CFG_MSG_SA_HASH_DEL_FAILED,
+ NFP_IPSEC_CFG_MSG_SA_INVALID_CMD
+};
+
+static int
+nfp_ipsec_cfg_cmd_issue(struct nfp_net_hw *hw,
+ struct nfp_ipsec_msg *msg)
+{
+ int ret;
+ uint32_t i;
+ uint32_t msg_size;
+
+ msg_size = RTE_DIM(msg->raw);
+ msg->rsp = NFP_IPSEC_CFG_MSG_OK;
+
+ for (i = 0; i < msg_size; i++)
+ nn_cfg_writel(hw, NFP_NET_CFG_MBOX_VAL + 4 * i, msg->raw[i]);
+
+ ret = nfp_net_mbox_reconfig(hw, NFP_NET_CFG_MBOX_CMD_IPSEC);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to IPsec reconfig mbox");
+ return ret;
+ }
+
+ /*
+ * Not all commands and callers make use of response message data. But
+ * leave this up to the caller and always read and store the full
+ * response. One example where the data is needed is for statistics.
+ */
+ for (i = 0; i < msg_size; i++)
+ msg->raw[i] = nn_cfg_readl(hw, NFP_NET_CFG_MBOX_VAL + 4 * i);
+
+ switch (msg->rsp) {
+ case NFP_IPSEC_CFG_MSG_OK:
+ ret = 0;
+ break;
+ case NFP_IPSEC_CFG_MSG_SA_INVALID_CMD:
+ ret = -EINVAL;
+ break;
+ case NFP_IPSEC_CFG_MSG_SA_VALID:
+ ret = -EEXIST;
+ break;
+ case NFP_IPSEC_CFG_MSG_FAILED:
+ /* FALLTHROUGH */
+ case NFP_IPSEC_CFG_MSG_SA_HASH_ADD_FAILED:
+ /* FALLTHROUGH */
+ case NFP_IPSEC_CFG_MSG_SA_HASH_DEL_FAILED:
+ ret = -EIO;
+ break;
+ default:
+ ret = -EDOM;
+ }
+
+ return ret;
+}
+
+/**
+ * Get discards packet statistics for each SA
+ *
+ * The sa_discard_stats contains the statistics of discards packets
+ * of an SA. This function calculates the sum total of discarded packets.
+ *
+ * @param errors
+ * The value is SA discards packet sum total
+ * @param sa_discard_stats
+ * The struct is SA discards packet Statistics
+ */
+static void
+nfp_get_errorstats(uint64_t *errors,
+ struct ipsec_discard_stats *sa_discard_stats)
+{
+ uint32_t i;
+ uint32_t len;
+ uint32_t *perror;
+
+ perror = &sa_discard_stats->discards_auth;
+ len = sizeof(struct ipsec_discard_stats) / sizeof(uint32_t);
+
+ for (i = 0; i < len; i++)
+ *errors += *perror++;
+
+ *errors -= sa_discard_stats->ipv4_id_counter;
+}
+
+static int
+nfp_security_session_get_stats(void *device,
+ struct rte_security_session *session,
+ struct rte_security_stats *stats)
+{
+ int ret;
+ struct nfp_net_hw *hw;
+ struct nfp_ipsec_msg msg;
+ struct rte_eth_dev *eth_dev;
+ struct ipsec_get_sa_stats *cfg_s;
+ struct rte_security_ipsec_stats *ips_s;
+ struct nfp_ipsec_session *priv_session;
+ enum rte_security_ipsec_sa_direction direction;
+
+ eth_dev = device;
+ priv_session = SECURITY_GET_SESS_PRIV(session);
+ memset(&msg, 0, sizeof(msg));
+ msg.cmd = NFP_IPSEC_CFG_MSG_GET_SA_STATS;
+ msg.sa_idx = priv_session->sa_index;
+ hw = NFP_NET_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
+
+ ret = nfp_ipsec_cfg_cmd_issue(hw, &msg);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to get SA stats");
+ return ret;
+ }
+
+ cfg_s = &msg.cfg_get_stats;
+ direction = priv_session->ipsec.direction;
+ memset(stats, 0, sizeof(struct rte_security_stats)); /* Start with zeros */
+ stats->protocol = RTE_SECURITY_PROTOCOL_IPSEC;
+ ips_s = &stats->ipsec;
+
+ /* Only display SA if any counters are non-zero */
+ if (cfg_s->lifetime_byte_count != 0 || cfg_s->pkt_count != 0) {
+ if (direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) {
+ ips_s->ipackets = cfg_s->pkt_count;
+ ips_s->ibytes = cfg_s->lifetime_byte_count;
+ nfp_get_errorstats(&ips_s->ierrors, &cfg_s->sa_discard_stats);
+ } else {
+ ips_s->opackets = cfg_s->pkt_count;
+ ips_s->obytes = cfg_s->lifetime_byte_count;
+ nfp_get_errorstats(&ips_s->oerrors, &cfg_s->sa_discard_stats);
+ }
+ }
+
+ return 0;
+}
+
static const struct rte_security_capability *
nfp_crypto_capabilities_get(void *device __rte_unused)
{
@@ -370,6 +518,7 @@ nfp_security_session_get_size(void *device __rte_unused)
static const struct rte_security_ops nfp_security_ops = {
.session_get_size = nfp_security_session_get_size,
+ .session_stats_get = nfp_security_session_get_stats,
.capabilities_get = nfp_crypto_capabilities_get,
};
--
2.39.1
^ permalink raw reply [flat|nested] 42+ messages in thread
* [PATCH v3 6/9] net/nfp: create security session
2023-09-29 2:08 ` [PATCH v3 0/9] " Chaoyong He
` (4 preceding siblings ...)
2023-09-29 2:08 ` [PATCH v3 5/9] net/nfp: get IPsec Rx/Tx packet statistics Chaoyong He
@ 2023-09-29 2:08 ` Chaoyong He
2023-09-29 2:08 ` [PATCH v3 7/9] net/nfp: update " Chaoyong He
` (3 subsequent siblings)
9 siblings, 0 replies; 42+ messages in thread
From: Chaoyong He @ 2023-09-29 2:08 UTC (permalink / raw)
To: dev; +Cc: oss-drivers, Chang Miao, Shihong Wang, Chaoyong He
From: Chang Miao <chang.miao@corigine.com>
Create security session to manage IPsec protocol specific message
and crypto parameters. This session support full protocol offload
and inline crypto operation with NIC devices.
Signed-off-by: Chang Miao <chang.miao@corigine.com>
Signed-off-by: Shihong Wang <shihong.wang@corigine.com>
Reviewed-by: Chaoyong He <chaoyong.he@corigine.com>
---
drivers/net/nfp/nfp_ipsec.c | 698 ++++++++++++++++++++++++++++++++++++
1 file changed, 698 insertions(+)
diff --git a/drivers/net/nfp/nfp_ipsec.c b/drivers/net/nfp/nfp_ipsec.c
index d4292c3b90..74627d2845 100644
--- a/drivers/net/nfp/nfp_ipsec.c
+++ b/drivers/net/nfp/nfp_ipsec.c
@@ -17,6 +17,8 @@
#include "nfp_logs.h"
#include "nfp_rxtx.h"
+#define NFP_UDP_ESP_PORT 4500
+
static const struct rte_cryptodev_capabilities nfp_crypto_caps[] = {
{
.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
@@ -375,6 +377,62 @@ enum nfp_ipsec_cfg_msg_rsp_codes {
NFP_IPSEC_CFG_MSG_SA_INVALID_CMD
};
+enum nfp_ipsec_mode {
+ NFP_IPSEC_MODE_TRANSPORT,
+ NFP_IPSEC_MODE_TUNNEL,
+};
+
+enum nfp_ipsec_protocol {
+ NFP_IPSEC_PROTOCOL_AH,
+ NFP_IPSEC_PROTOCOL_ESP,
+};
+
+/* Cipher modes */
+enum nfp_ipsec_cimode {
+ NFP_IPSEC_CIMODE_ECB,
+ NFP_IPSEC_CIMODE_CBC,
+ NFP_IPSEC_CIMODE_CFB,
+ NFP_IPSEC_CIMODE_OFB,
+ NFP_IPSEC_CIMODE_CTR,
+};
+
+/* Hash types */
+enum nfp_ipsec_hash_type {
+ NFP_IPSEC_HASH_NONE,
+ NFP_IPSEC_HASH_MD5_96,
+ NFP_IPSEC_HASH_SHA1_96,
+ NFP_IPSEC_HASH_SHA256_96,
+ NFP_IPSEC_HASH_SHA384_96,
+ NFP_IPSEC_HASH_SHA512_96,
+ NFP_IPSEC_HASH_MD5_128,
+ NFP_IPSEC_HASH_SHA1_80,
+ NFP_IPSEC_HASH_SHA256_128,
+ NFP_IPSEC_HASH_SHA384_192,
+ NFP_IPSEC_HASH_SHA512_256,
+ NFP_IPSEC_HASH_GF128_128,
+ NFP_IPSEC_HASH_POLY1305_128,
+};
+
+/* Cipher types */
+enum nfp_ipsec_cipher_type {
+ NFP_IPSEC_CIPHER_NULL,
+ NFP_IPSEC_CIPHER_3DES,
+ NFP_IPSEC_CIPHER_AES128,
+ NFP_IPSEC_CIPHER_AES192,
+ NFP_IPSEC_CIPHER_AES256,
+ NFP_IPSEC_CIPHER_AES128_NULL,
+ NFP_IPSEC_CIPHER_AES192_NULL,
+ NFP_IPSEC_CIPHER_AES256_NULL,
+ NFP_IPSEC_CIPHER_CHACHA20,
+};
+
+/* Don't Fragment types */
+enum nfp_ipsec_df_type {
+ NFP_IPSEC_DF_CLEAR,
+ NFP_IPSEC_DF_SET,
+ NFP_IPSEC_DF_COPY,
+};
+
static int
nfp_ipsec_cfg_cmd_issue(struct nfp_net_hw *hw,
struct nfp_ipsec_msg *msg)
@@ -427,6 +485,645 @@ nfp_ipsec_cfg_cmd_issue(struct nfp_net_hw *hw,
return ret;
}
+/**
+ * Get valid SA index from SA table
+ *
+ * @param data
+ * SA table pointer
+ * @param sa_idx
+ * SA table index pointer
+ *
+ * @return
+ * Negative number on full or repeat, 0 on success
+ *
+ * Note: multiple sockets may create same SA session.
+ */
+static void
+nfp_get_sa_entry(struct nfp_net_ipsec_data *data,
+ int *sa_idx)
+{
+ uint32_t i;
+
+ for (i = 0; i < NFP_NET_IPSEC_MAX_SA_CNT; i++) {
+ if (data->sa_entries[i] == NULL) {
+ *sa_idx = i;
+ break;
+ }
+ }
+}
+
+static void
+nfp_aesgcm_iv_update(struct ipsec_add_sa *cfg,
+ uint16_t iv_len,
+ const char *iv_string)
+{
+ int i;
+ char *save;
+ char *iv_b;
+ char *iv_str;
+ uint8_t *cfg_iv;
+
+ iv_str = strdup(iv_string);
+ cfg_iv = (uint8_t *)cfg->aesgcm_fields.iv;
+
+ for (i = 0; i < iv_len; i++) {
+ iv_b = strtok_r(i ? NULL : iv_str, ",", &save);
+ if (iv_b == NULL)
+ break;
+
+ cfg_iv[i] = strtoul(iv_b, NULL, 0);
+ }
+
+ *(uint32_t *)cfg_iv = rte_be_to_cpu_32(*(uint32_t *)cfg_iv);
+ *(uint32_t *)&cfg_iv[4] = rte_be_to_cpu_32(*(uint32_t *)&cfg_iv[4]);
+
+ free(iv_str);
+}
+
+static int
+set_aes_keylen(uint32_t key_length,
+ struct ipsec_add_sa *cfg)
+{
+ switch (key_length << 3) {
+ case 128:
+ cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_AES128;
+ break;
+ case 192:
+ cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_AES192;
+ break;
+ case 256:
+ cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_AES256;
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "AES cipher key length is illegal!");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* Map rte_security_session_conf aead algo to NFP aead algo */
+static int
+nfp_aead_map(struct rte_eth_dev *eth_dev,
+ struct rte_crypto_aead_xform *aead,
+ uint32_t key_length,
+ struct ipsec_add_sa *cfg)
+{
+ int ret;
+ uint32_t i;
+ uint32_t index;
+ uint16_t iv_len;
+ uint32_t offset;
+ uint32_t device_id;
+ const char *iv_str;
+ const uint32_t *key;
+ struct nfp_net_hw *hw;
+
+ hw = NFP_NET_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
+ device_id = hw->device_id;
+ offset = 0;
+
+ switch (aead->algo) {
+ case RTE_CRYPTO_AEAD_AES_GCM:
+ if (aead->digest_length != 16) {
+ PMD_DRV_LOG(ERR, "ICV must be 128bit with RTE_CRYPTO_AEAD_AES_GCM!");
+ return -EINVAL;
+ }
+
+ cfg->ctrl_word.cimode = NFP_IPSEC_CIMODE_CTR;
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_GF128_128;
+
+ ret = set_aes_keylen(key_length, cfg);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to set AES_GCM key length!");
+ return -EINVAL;
+ }
+
+ break;
+ case RTE_CRYPTO_AEAD_CHACHA20_POLY1305:
+ if (device_id != PCI_DEVICE_ID_NFP3800_PF_NIC) {
+ PMD_DRV_LOG(ERR, "Unsupported aead CHACHA20_POLY1305 algorithm!");
+ return -EINVAL;
+ }
+
+ if (aead->digest_length != 16) {
+ PMD_DRV_LOG(ERR, "ICV must be 128bit with RTE_CRYPTO_AEAD_CHACHA20_POLY1305");
+ return -EINVAL;
+ }
+
+ /* Aead->alg_key_len includes 32-bit salt */
+ if (key_length != 32) {
+ PMD_DRV_LOG(ERR, "Unsupported CHACHA20 key length");
+ return -EINVAL;
+ }
+
+ /* The CHACHA20's mode is not configured */
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_POLY1305_128;
+ cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_CHACHA20;
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "Unsupported aead algorithm!");
+ return -EINVAL;
+ }
+
+ key = (const uint32_t *)(aead->key.data);
+
+ /*
+ * The CHACHA20's key order needs to be adjusted based on hardware design.
+ * Unadjusted order: {K0, K1, K2, K3, K4, K5, K6, K7}
+ * Adjusted order: {K4, K5, K6, K7, K0, K1, K2, K3}
+ */
+ if (aead->algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305)
+ offset = key_length / sizeof(cfg->cipher_key[0]) << 1;
+
+ for (i = 0; i < key_length / sizeof(cfg->cipher_key[0]); i++) {
+ index = (i + offset) % (key_length / sizeof(cfg->cipher_key[0]));
+ cfg->cipher_key[index] = rte_cpu_to_be_32(*key++);
+ }
+
+ /*
+ * The iv of the FW is equal to ESN by default. Reading the
+ * iv of the configuration information is not supported.
+ */
+ iv_str = getenv("ETH_SEC_IV_OVR");
+ if (iv_str != NULL) {
+ iv_len = aead->iv.length;
+ nfp_aesgcm_iv_update(cfg, iv_len, iv_str);
+ }
+
+ return 0;
+}
+
+/* Map rte_security_session_conf cipher algo to NFP cipher algo */
+static int
+nfp_cipher_map(struct rte_eth_dev *eth_dev,
+ struct rte_crypto_cipher_xform *cipher,
+ uint32_t key_length,
+ struct ipsec_add_sa *cfg)
+{
+ int ret;
+ uint32_t i;
+ uint32_t device_id;
+ const uint32_t *key;
+ struct nfp_net_hw *hw;
+
+ hw = NFP_NET_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
+ device_id = hw->device_id;
+
+ switch (cipher->algo) {
+ case RTE_CRYPTO_CIPHER_NULL:
+ cfg->ctrl_word.cimode = NFP_IPSEC_CIMODE_CBC;
+ cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_NULL;
+ break;
+ case RTE_CRYPTO_CIPHER_3DES_CBC:
+ if (device_id == PCI_DEVICE_ID_NFP3800_PF_NIC) {
+ PMD_DRV_LOG(ERR, "Unsupported 3DESCBC encryption algorithm!");
+ return -EINVAL;
+ }
+
+ cfg->ctrl_word.cimode = NFP_IPSEC_CIMODE_CBC;
+ cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_3DES;
+ break;
+ case RTE_CRYPTO_CIPHER_AES_CBC:
+ cfg->ctrl_word.cimode = NFP_IPSEC_CIMODE_CBC;
+ ret = set_aes_keylen(key_length, cfg);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to set cipher key length!");
+ return -EINVAL;
+ }
+
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "Unsupported cipher alg!");
+ return -EINVAL;
+ }
+
+ key = (const uint32_t *)(cipher->key.data);
+ if (key_length > sizeof(cfg->cipher_key)) {
+ PMD_DRV_LOG(ERR, "Insufficient space for offloaded key");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < key_length / sizeof(cfg->cipher_key[0]); i++)
+ cfg->cipher_key[i] = rte_cpu_to_be_32(*key++);
+
+ return 0;
+}
+
+static void
+set_md5hmac(struct ipsec_add_sa *cfg,
+ uint32_t *digest_length)
+{
+ switch (*digest_length) {
+ case 96:
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_MD5_96;
+ break;
+ case 128:
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_MD5_128;
+ break;
+ default:
+ *digest_length = 0;
+ }
+}
+
+static void
+set_sha1hmac(struct ipsec_add_sa *cfg,
+ uint32_t *digest_length)
+{
+ switch (*digest_length) {
+ case 96:
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA1_96;
+ break;
+ case 80:
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA1_80;
+ break;
+ default:
+ *digest_length = 0;
+ }
+}
+
+static void
+set_sha2_256hmac(struct ipsec_add_sa *cfg,
+ uint32_t *digest_length)
+{
+ switch (*digest_length) {
+ case 96:
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA256_96;
+ break;
+ case 128:
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA256_128;
+ break;
+ default:
+ *digest_length = 0;
+ }
+}
+
+static void
+set_sha2_384hmac(struct ipsec_add_sa *cfg,
+ uint32_t *digest_length)
+{
+ switch (*digest_length) {
+ case 96:
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA384_96;
+ break;
+ case 192:
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA384_192;
+ break;
+ default:
+ *digest_length = 0;
+ }
+}
+
+static void
+set_sha2_512hmac(struct ipsec_add_sa *cfg,
+ uint32_t *digest_length)
+{
+ switch (*digest_length) {
+ case 96:
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA512_96;
+ break;
+ case 256:
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA512_256;
+ break;
+ default:
+ *digest_length = 0;
+ }
+}
+
+/* Map rte_security_session_conf auth algo to NFP auth algo */
+static int
+nfp_auth_map(struct rte_eth_dev *eth_dev,
+ struct rte_crypto_auth_xform *auth,
+ uint32_t digest_length,
+ struct ipsec_add_sa *cfg)
+{
+ uint32_t i;
+ uint8_t key_length;
+ uint32_t device_id;
+ const uint32_t *key;
+ struct nfp_net_hw *hw;
+
+ if (digest_length == 0) {
+ PMD_DRV_LOG(ERR, "Auth digest length is illegal!");
+ return -EINVAL;
+ }
+
+ hw = NFP_NET_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
+ device_id = hw->device_id;
+ digest_length = digest_length << 3;
+
+ switch (auth->algo) {
+ case RTE_CRYPTO_AUTH_NULL:
+ cfg->ctrl_word.hash = NFP_IPSEC_HASH_NONE;
+ digest_length = 1;
+ break;
+ case RTE_CRYPTO_AUTH_MD5_HMAC:
+ if (device_id == PCI_DEVICE_ID_NFP3800_PF_NIC) {
+ PMD_DRV_LOG(ERR, "Unsupported MD5HMAC authentication algorithm!");
+ return -EINVAL;
+ }
+
+ set_md5hmac(cfg, &digest_length);
+ break;
+ case RTE_CRYPTO_AUTH_SHA1_HMAC:
+ set_sha1hmac(cfg, &digest_length);
+ break;
+ case RTE_CRYPTO_AUTH_SHA256_HMAC:
+ set_sha2_256hmac(cfg, &digest_length);
+ break;
+ case RTE_CRYPTO_AUTH_SHA384_HMAC:
+ set_sha2_384hmac(cfg, &digest_length);
+ break;
+ case RTE_CRYPTO_AUTH_SHA512_HMAC:
+ set_sha2_512hmac(cfg, &digest_length);
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "Unsupported auth alg!");
+ return -EINVAL;
+ }
+
+ if (digest_length == 0) {
+ PMD_DRV_LOG(ERR, "Unsupported authentication algorithm digest length");
+ return -EINVAL;
+ }
+
+ key = (const uint32_t *)(auth->key.data);
+ key_length = auth->key.length;
+ if (key_length > sizeof(cfg->auth_key)) {
+ PMD_DRV_LOG(ERR, "Insufficient space for offloaded auth key!");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < key_length / sizeof(cfg->auth_key[0]); i++)
+ cfg->auth_key[i] = rte_cpu_to_be_32(*key++);
+
+ return 0;
+}
+
+static int
+nfp_crypto_msg_build(struct rte_eth_dev *eth_dev,
+ struct rte_security_session_conf *conf,
+ struct nfp_ipsec_msg *msg)
+{
+ int ret;
+ struct ipsec_add_sa *cfg;
+ struct rte_crypto_sym_xform *cur;
+ struct rte_crypto_sym_xform *next;
+ enum rte_security_ipsec_sa_direction direction;
+
+ cur = conf->crypto_xform;
+ if (cur == NULL) {
+ PMD_DRV_LOG(ERR, "Unsupported crypto_xform is NULL!");
+ return -EINVAL;
+ }
+
+ next = cur->next;
+ direction = conf->ipsec.direction;
+ cfg = &msg->cfg_add_sa;
+
+ switch (cur->type) {
+ case RTE_CRYPTO_SYM_XFORM_AEAD:
+ /* Aead transforms can be used for either inbound/outbound IPsec SAs */
+ if (next != NULL) {
+ PMD_DRV_LOG(ERR, "Next crypto_xform type should be NULL!");
+ return -EINVAL;
+ }
+
+ ret = nfp_aead_map(eth_dev, &cur->aead, cur->aead.key.length, cfg);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to map aead alg!");
+ return ret;
+ }
+
+ cfg->aesgcm_fields.salt = rte_cpu_to_be_32(conf->ipsec.salt);
+ break;
+ case RTE_CRYPTO_SYM_XFORM_AUTH:
+ /* Only support Auth + Cipher for inbound */
+ if (direction != RTE_SECURITY_IPSEC_SA_DIR_INGRESS) {
+ PMD_DRV_LOG(ERR, "Direction should be INGRESS, but it is not!");
+ return -EINVAL;
+ }
+
+ if (next == NULL || next->type != RTE_CRYPTO_SYM_XFORM_CIPHER) {
+ PMD_DRV_LOG(ERR, "Next crypto_xfrm should be cipher, but it is not!");
+ return -EINVAL;
+ }
+
+ ret = nfp_auth_map(eth_dev, &cur->auth, cur->auth.digest_length, cfg);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to map auth alg!");
+ return ret;
+ }
+
+ ret = nfp_cipher_map(eth_dev, &next->cipher, next->cipher.key.length, cfg);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to map cipher alg!");
+ return ret;
+ }
+
+ break;
+ case RTE_CRYPTO_SYM_XFORM_CIPHER:
+ /* Only support Cipher + Auth for outbound */
+ if (direction != RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
+ PMD_DRV_LOG(ERR, "Direction should be EGRESS, but it is not!");
+ return -EINVAL;
+ }
+
+ if (next == NULL || next->type != RTE_CRYPTO_SYM_XFORM_AUTH) {
+ PMD_DRV_LOG(ERR, "Next crypto_xfrm should be auth, but it is not!");
+ return -EINVAL;
+ }
+
+ ret = nfp_cipher_map(eth_dev, &cur->cipher, cur->cipher.key.length, cfg);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to map cipher alg!");
+ return ret;
+ }
+
+ ret = nfp_auth_map(eth_dev, &next->auth, next->auth.digest_length, cfg);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to map auth alg!");
+ return ret;
+ }
+
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "Unsupported crypto_xform type!");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+nfp_ipsec_msg_build(struct rte_eth_dev *eth_dev,
+ struct rte_security_session_conf *conf,
+ struct nfp_ipsec_msg *msg)
+{
+ int ret;
+ struct ipsec_add_sa *cfg;
+ enum rte_security_ipsec_tunnel_type type;
+
+ cfg = &msg->cfg_add_sa;
+ cfg->spi = conf->ipsec.spi;
+ cfg->pmtu_limit = 0xffff;
+
+ /*
+ * UDP encapsulation
+ *
+ * 1: Do UDP encapsulation/decapsulation
+ * 0: No UDP encapsulation
+ */
+ if (conf->ipsec.options.udp_encap == 1) {
+ cfg->udp_enable = 1;
+ cfg->natt_dst_port = NFP_UDP_ESP_PORT;
+ cfg->natt_src_port = NFP_UDP_ESP_PORT;
+ }
+
+ if (conf->ipsec.options.copy_df == 1)
+ cfg->df_ctrl = NFP_IPSEC_DF_COPY;
+ else if (conf->ipsec.tunnel.ipv4.df != 0)
+ cfg->df_ctrl = NFP_IPSEC_DF_SET;
+ else
+ cfg->df_ctrl = NFP_IPSEC_DF_CLEAR;
+
+ switch (conf->action_type) {
+ case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO:
+ cfg->ctrl_word.encap_dsbl = 1;
+ break;
+ case RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL:
+ cfg->ctrl_word.encap_dsbl = 0;
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "Unsupported IPsec action for offload, action: %d",
+ conf->action_type);
+ return -EINVAL;
+ }
+
+ switch (conf->ipsec.proto) {
+ case RTE_SECURITY_IPSEC_SA_PROTO_ESP:
+ cfg->ctrl_word.proto = NFP_IPSEC_PROTOCOL_ESP;
+ break;
+ case RTE_SECURITY_IPSEC_SA_PROTO_AH:
+ cfg->ctrl_word.proto = NFP_IPSEC_PROTOCOL_AH;
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "Unsupported IPsec protocol for offload, protocol: %d",
+ conf->ipsec.proto);
+ return -EINVAL;
+ }
+
+ switch (conf->ipsec.mode) {
+ case RTE_SECURITY_IPSEC_SA_MODE_TUNNEL:
+ type = conf->ipsec.tunnel.type;
+ cfg->ctrl_word.mode = NFP_IPSEC_MODE_TUNNEL;
+ if (type == RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
+ cfg->src_ip.v4 = conf->ipsec.tunnel.ipv4.src_ip;
+ cfg->dst_ip.v4 = conf->ipsec.tunnel.ipv4.dst_ip;
+ cfg->ipv6 = 0;
+ } else if (type == RTE_SECURITY_IPSEC_TUNNEL_IPV6) {
+ cfg->src_ip.v6 = conf->ipsec.tunnel.ipv6.src_addr;
+ cfg->dst_ip.v6 = conf->ipsec.tunnel.ipv6.dst_addr;
+ cfg->ipv6 = 1;
+ } else {
+ PMD_DRV_LOG(ERR, "Unsupported address family!");
+ return -EINVAL;
+ }
+
+ break;
+ case RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT:
+ type = conf->ipsec.tunnel.type;
+ cfg->ctrl_word.mode = NFP_IPSEC_MODE_TRANSPORT;
+ if (type == RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
+ memset(&cfg->src_ip, 0, sizeof(cfg->src_ip));
+ cfg->ipv6 = 0;
+ } else if (type == RTE_SECURITY_IPSEC_TUNNEL_IPV6) {
+ memset(&cfg->src_ip, 0, sizeof(cfg->src_ip));
+ cfg->ipv6 = 1;
+ } else {
+ PMD_DRV_LOG(ERR, "Unsupported address family!");
+ return -EINVAL;
+ }
+
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "Unsupported IPsec mode for offload, mode: %d",
+ conf->ipsec.mode);
+ return -EINVAL;
+ }
+
+ ret = nfp_crypto_msg_build(eth_dev, conf, msg);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to build auth/crypto/aead msg!");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int
+nfp_crypto_create_session(void *device,
+ struct rte_security_session_conf *conf,
+ struct rte_security_session *session)
+{
+ int ret;
+ int sa_idx;
+ struct nfp_net_hw *hw;
+ struct nfp_ipsec_msg msg;
+ struct rte_eth_dev *eth_dev;
+ struct nfp_ipsec_session *priv_session;
+
+ /* Only support IPsec at present */
+ if (conf->protocol != RTE_SECURITY_PROTOCOL_IPSEC) {
+ PMD_DRV_LOG(ERR, "Unsupported non-IPsec offload!");
+ return -EINVAL;
+ }
+
+ sa_idx = -1;
+ eth_dev = device;
+ priv_session = SECURITY_GET_SESS_PRIV(session);
+ hw = NFP_NET_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
+
+ if (hw->ipsec_data->sa_free_cnt == 0) {
+ PMD_DRV_LOG(ERR, "No space in SA table, spi: %d", conf->ipsec.spi);
+ return -EINVAL;
+ }
+
+ nfp_get_sa_entry(hw->ipsec_data, &sa_idx);
+
+ if (sa_idx < 0) {
+ PMD_DRV_LOG(ERR, "Failed to get SA entry!");
+ return -EINVAL;
+ }
+
+ memset(&msg, 0, sizeof(msg));
+ ret = nfp_ipsec_msg_build(eth_dev, conf, &msg);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to build IPsec msg!");
+ return -EINVAL;
+ }
+
+ msg.cmd = NFP_IPSEC_CFG_MSG_ADD_SA;
+ msg.sa_idx = sa_idx;
+ ret = nfp_ipsec_cfg_cmd_issue(hw, &msg);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to add SA to nic");
+ return -EINVAL;
+ }
+
+ priv_session->action = conf->action_type;
+ priv_session->ipsec = conf->ipsec;
+ priv_session->msg = msg.cfg_add_sa;
+ priv_session->sa_index = sa_idx;
+ priv_session->dev = eth_dev;
+ priv_session->user_data = conf->userdata;
+
+ hw->ipsec_data->sa_free_cnt--;
+ hw->ipsec_data->sa_entries[sa_idx] = priv_session;
+
+ return 0;
+}
+
/**
* Get discards packet statistics for each SA
*
@@ -517,6 +1214,7 @@ nfp_security_session_get_size(void *device __rte_unused)
}
static const struct rte_security_ops nfp_security_ops = {
+ .session_create = nfp_crypto_create_session,
.session_get_size = nfp_security_session_get_size,
.session_stats_get = nfp_security_session_get_stats,
.capabilities_get = nfp_crypto_capabilities_get,
--
2.39.1
^ permalink raw reply [flat|nested] 42+ messages in thread
* [PATCH v3 7/9] net/nfp: update security session
2023-09-29 2:08 ` [PATCH v3 0/9] " Chaoyong He
` (5 preceding siblings ...)
2023-09-29 2:08 ` [PATCH v3 6/9] net/nfp: create security session Chaoyong He
@ 2023-09-29 2:08 ` Chaoyong He
2023-09-29 2:08 ` [PATCH v3 8/9] net/nfp: support IPsec Rx and Tx offload Chaoyong He
` (2 subsequent siblings)
9 siblings, 0 replies; 42+ messages in thread
From: Chaoyong He @ 2023-09-29 2:08 UTC (permalink / raw)
To: dev; +Cc: oss-drivers, Shihong Wang, Chaoyong He
From: Shihong Wang <shihong.wang@corigine.com>
Update the configuration information in priv_session when
the configuration parameters of sess_conf change.
Signed-off-by: Shihong Wang <shihong.wang@corigine.com>
Reviewed-by: Chaoyong He <chaoyong.he@corigine.com>
---
drivers/net/nfp/nfp_ipsec.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/drivers/net/nfp/nfp_ipsec.c b/drivers/net/nfp/nfp_ipsec.c
index 74627d2845..33c77f0b74 100644
--- a/drivers/net/nfp/nfp_ipsec.c
+++ b/drivers/net/nfp/nfp_ipsec.c
@@ -1124,6 +1124,30 @@ nfp_crypto_create_session(void *device,
return 0;
}
+static int
+nfp_crypto_update_session(void *device __rte_unused,
+ struct rte_security_session *session,
+ struct rte_security_session_conf *conf)
+{
+ struct nfp_ipsec_session *priv_session;
+
+ priv_session = SECURITY_GET_SESS_PRIV(session);
+ if (priv_session == NULL)
+ return -EINVAL;
+
+ /* Update IPsec ESN value */
+ if (priv_session->msg.ctrl_word.ext_seq != 0 && conf->ipsec.options.esn != 0) {
+ /*
+ * Store in nfp_ipsec_session for outbound SA for use
+ * in nfp_security_set_pkt_metadata() function.
+ */
+ priv_session->ipsec.esn.hi = conf->ipsec.esn.hi;
+ priv_session->ipsec.esn.low = conf->ipsec.esn.low;
+ }
+
+ return 0;
+}
+
/**
* Get discards packet statistics for each SA
*
@@ -1215,6 +1239,7 @@ nfp_security_session_get_size(void *device __rte_unused)
static const struct rte_security_ops nfp_security_ops = {
.session_create = nfp_crypto_create_session,
+ .session_update = nfp_crypto_update_session,
.session_get_size = nfp_security_session_get_size,
.session_stats_get = nfp_security_session_get_stats,
.capabilities_get = nfp_crypto_capabilities_get,
--
2.39.1
^ permalink raw reply [flat|nested] 42+ messages in thread
* [PATCH v3 8/9] net/nfp: support IPsec Rx and Tx offload
2023-09-29 2:08 ` [PATCH v3 0/9] " Chaoyong He
` (6 preceding siblings ...)
2023-09-29 2:08 ` [PATCH v3 7/9] net/nfp: update " Chaoyong He
@ 2023-09-29 2:08 ` Chaoyong He
2023-09-29 2:08 ` [PATCH v3 9/9] net/nfp: destroy security session Chaoyong He
2023-09-29 10:05 ` [PATCH v3 0/9] add the support of ipsec offload Ferruh Yigit
9 siblings, 0 replies; 42+ messages in thread
From: Chaoyong He @ 2023-09-29 2:08 UTC (permalink / raw)
To: dev; +Cc: oss-drivers, Shihong Wang, Chang Miao, Chaoyong He
From: Shihong Wang <shihong.wang@corigine.com>
The Rx path checks the ipsec metadata and base on the
crypto status sets ol_flags in the rte_mbuf.
The Tx path write IPsec message to mbuf metadata based
on mbuf dynamic field.
Signed-off-by: Shihong Wang <shihong.wang@corigine.com>
Signed-off-by: Chang Miao <chang.miao@corigine.com>
Reviewed-by: Chaoyong He <chaoyong.he@corigine.com>
---
doc/guides/nics/nfp.rst | 31 +++++++++++++
drivers/net/nfp/nfd3/nfp_nfd3_dp.c | 24 ++++++++++
drivers/net/nfp/nfdk/nfp_nfdk_dp.c | 24 ++++++++++
drivers/net/nfp/nfp_ctrl.h | 1 +
drivers/net/nfp/nfp_ipsec.c | 42 +++++++++++++++++
drivers/net/nfp/nfp_ipsec.h | 6 +++
drivers/net/nfp/nfp_rxtx.c | 74 ++++++++++++++++++++++++++++++
drivers/net/nfp/nfp_rxtx.h | 5 ++
8 files changed, 207 insertions(+)
diff --git a/doc/guides/nics/nfp.rst b/doc/guides/nics/nfp.rst
index 456a22dcbc..fee1860f4a 100644
--- a/doc/guides/nics/nfp.rst
+++ b/doc/guides/nics/nfp.rst
@@ -348,6 +348,18 @@ Metadata with L2 (1W/4B)
The vlan[0] is the innermost VLAN
The vlan[1] is the QinQ info
+NFP_NET_META_IPSEC
+The IPsec type requires 4 bit.
+The SA index value is 32 bit which need 1 data field.
+::
+
+ ----------------------------------------------------------------
+ 3 2 1 0
+ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | sa_idx |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
TX
~~
@@ -363,3 +375,22 @@ NFP_NET_META_VLAN
^ ^
NOTE: | TCI |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+NFP_NET_META_IPSEC
+The IPsec type requires 12 bit, because it requires three data fields.
+::
+
+ ----------------------------------------------------------------
+ 3 2 1 0
+ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | sa_idx |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | nfp_ipsec_force_seq_low |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | nfp_ipsec_force_seq_hi |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ The sa_idx is 32 bit which need 1 data field.
+ The nfp_ipsec_force_seq_low & nfp_ipsec_force_seq_hi is Anti-re-anti-count,
+ which is 64 bit need two data fields.
diff --git a/drivers/net/nfp/nfd3/nfp_nfd3_dp.c b/drivers/net/nfp/nfd3/nfp_nfd3_dp.c
index ab0747fc16..64928254d8 100644
--- a/drivers/net/nfp/nfd3/nfp_nfd3_dp.c
+++ b/drivers/net/nfp/nfd3/nfp_nfd3_dp.c
@@ -147,10 +147,13 @@ nfp_net_nfd3_set_meta_data(struct nfp_net_meta_raw *meta_data,
char *meta;
uint8_t layer = 0;
uint32_t meta_info;
+ uint32_t cap_extend;
struct nfp_net_hw *hw;
uint8_t vlan_layer = 0;
+ uint8_t ipsec_layer = 0;
hw = txq->hw;
+ cap_extend = nn_cfg_readl(hw, NFP_NET_CFG_CAP_WORD1);
if ((pkt->ol_flags & RTE_MBUF_F_TX_VLAN) != 0 &&
(hw->ctrl & NFP_NET_CFG_CTRL_TXVLAN_V2) != 0) {
@@ -160,6 +163,18 @@ nfp_net_nfd3_set_meta_data(struct nfp_net_meta_raw *meta_data,
meta_data->header |= NFP_NET_META_VLAN;
}
+ if ((pkt->ol_flags & RTE_MBUF_F_TX_SEC_OFFLOAD) != 0 &&
+ (cap_extend & NFP_NET_CFG_CTRL_IPSEC) != 0) {
+ uint32_t ipsec_type = NFP_NET_META_IPSEC |
+ NFP_NET_META_IPSEC << NFP_NET_META_FIELD_SIZE |
+ NFP_NET_META_IPSEC << (2 * NFP_NET_META_FIELD_SIZE);
+ if (meta_data->length == 0)
+ meta_data->length = NFP_NET_META_FIELD_SIZE;
+ uint8_t ipsec_offset = meta_data->length - NFP_NET_META_FIELD_SIZE;
+ meta_data->header |= (ipsec_type << ipsec_offset);
+ meta_data->length += 3 * NFP_NET_META_FIELD_SIZE;
+ }
+
if (meta_data->length == 0)
return;
@@ -180,6 +195,15 @@ nfp_net_nfd3_set_meta_data(struct nfp_net_meta_raw *meta_data,
nfp_net_set_meta_vlan(meta_data, pkt, layer);
vlan_layer++;
break;
+ case NFP_NET_META_IPSEC:
+ if (ipsec_layer > 2) {
+ PMD_DRV_LOG(ERR, "At most 3 layers of ipsec is supported for now.");
+ return;
+ }
+
+ nfp_net_set_meta_ipsec(meta_data, txq, pkt, layer, ipsec_layer);
+ ipsec_layer++;
+ break;
default:
PMD_DRV_LOG(ERR, "The metadata type not supported");
return;
diff --git a/drivers/net/nfp/nfdk/nfp_nfdk_dp.c b/drivers/net/nfp/nfdk/nfp_nfdk_dp.c
index a85734f121..d4bd5edb0a 100644
--- a/drivers/net/nfp/nfdk/nfp_nfdk_dp.c
+++ b/drivers/net/nfp/nfdk/nfp_nfdk_dp.c
@@ -177,13 +177,16 @@ nfp_net_nfdk_set_meta_data(struct rte_mbuf *pkt,
char *meta;
uint8_t layer = 0;
uint32_t meta_type;
+ uint32_t cap_extend;
struct nfp_net_hw *hw;
uint32_t header_offset;
uint8_t vlan_layer = 0;
+ uint8_t ipsec_layer = 0;
struct nfp_net_meta_raw meta_data;
memset(&meta_data, 0, sizeof(meta_data));
hw = txq->hw;
+ cap_extend = nn_cfg_readl(hw, NFP_NET_CFG_CAP_WORD1);
if ((pkt->ol_flags & RTE_MBUF_F_TX_VLAN) != 0 &&
(hw->ctrl & NFP_NET_CFG_CTRL_TXVLAN_V2) != 0) {
@@ -193,6 +196,18 @@ nfp_net_nfdk_set_meta_data(struct rte_mbuf *pkt,
meta_data.header |= NFP_NET_META_VLAN;
}
+ if ((pkt->ol_flags & RTE_MBUF_F_TX_SEC_OFFLOAD) != 0 &&
+ (cap_extend & NFP_NET_CFG_CTRL_IPSEC) != 0) {
+ uint32_t ipsec_type = NFP_NET_META_IPSEC |
+ NFP_NET_META_IPSEC << NFP_NET_META_FIELD_SIZE |
+ NFP_NET_META_IPSEC << (2 * NFP_NET_META_FIELD_SIZE);
+ if (meta_data.length == 0)
+ meta_data.length = NFP_NET_META_FIELD_SIZE;
+ uint8_t ipsec_offset = meta_data.length - NFP_NET_META_FIELD_SIZE;
+ meta_data.header |= (ipsec_type << ipsec_offset);
+ meta_data.length += 3 * NFP_NET_META_FIELD_SIZE;
+ }
+
if (meta_data.length == 0)
return;
@@ -215,6 +230,15 @@ nfp_net_nfdk_set_meta_data(struct rte_mbuf *pkt,
nfp_net_set_meta_vlan(&meta_data, pkt, layer);
vlan_layer++;
break;
+ case NFP_NET_META_IPSEC:
+ if (ipsec_layer > 2) {
+ PMD_DRV_LOG(ERR, "At most 3 layers of ipsec is supported for now.");
+ return;
+ }
+
+ nfp_net_set_meta_ipsec(&meta_data, txq, pkt, layer, ipsec_layer);
+ ipsec_layer++;
+ break;
default:
PMD_DRV_LOG(ERR, "The metadata type not supported");
return;
diff --git a/drivers/net/nfp/nfp_ctrl.h b/drivers/net/nfp/nfp_ctrl.h
index 99890a33a1..55073c3cea 100644
--- a/drivers/net/nfp/nfp_ctrl.h
+++ b/drivers/net/nfp/nfp_ctrl.h
@@ -39,6 +39,7 @@
#define NFP_NET_META_HASH 1 /* next field carries hash type */
#define NFP_NET_META_VLAN 4
#define NFP_NET_META_PORTID 5
+#define NFP_NET_META_IPSEC 9
#define NFP_META_PORT_ID_CTRL ~0U
diff --git a/drivers/net/nfp/nfp_ipsec.c b/drivers/net/nfp/nfp_ipsec.c
index 33c77f0b74..d1d593f18c 100644
--- a/drivers/net/nfp/nfp_ipsec.c
+++ b/drivers/net/nfp/nfp_ipsec.c
@@ -1148,6 +1148,47 @@ nfp_crypto_update_session(void *device __rte_unused,
return 0;
}
+static int
+nfp_security_set_pkt_metadata(void *device,
+ struct rte_security_session *session,
+ struct rte_mbuf *m,
+ void *params)
+{
+ int offset;
+ uint64_t *sqn;
+ struct nfp_net_hw *hw;
+ struct rte_eth_dev *eth_dev;
+ struct nfp_ipsec_session *priv_session;
+
+ sqn = params;
+ eth_dev = device;
+ priv_session = SECURITY_GET_SESS_PRIV(session);
+ hw = NFP_NET_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
+
+ if (priv_session->ipsec.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
+ struct nfp_tx_ipsec_desc_msg *desc_md;
+
+ offset = hw->ipsec_data->pkt_dynfield_offset;
+ desc_md = RTE_MBUF_DYNFIELD(m, offset, struct nfp_tx_ipsec_desc_msg *);
+
+ if (priv_session->msg.ctrl_word.ext_seq != 0 && sqn != NULL) {
+ desc_md->esn.low = rte_cpu_to_be_32(*sqn);
+ desc_md->esn.hi = rte_cpu_to_be_32(*sqn >> 32);
+ } else if (priv_session->msg.ctrl_word.ext_seq != 0) {
+ desc_md->esn.low = rte_cpu_to_be_32(priv_session->ipsec.esn.low);
+ desc_md->esn.hi = rte_cpu_to_be_32(priv_session->ipsec.esn.hi);
+ } else {
+ desc_md->esn.low = rte_cpu_to_be_32(priv_session->ipsec.esn.value);
+ desc_md->esn.hi = 0;
+ }
+
+ desc_md->enc = 1;
+ desc_md->sa_idx = rte_cpu_to_be_32(priv_session->sa_index);
+ }
+
+ return 0;
+}
+
/**
* Get discards packet statistics for each SA
*
@@ -1242,6 +1283,7 @@ static const struct rte_security_ops nfp_security_ops = {
.session_update = nfp_crypto_update_session,
.session_get_size = nfp_security_session_get_size,
.session_stats_get = nfp_security_session_get_stats,
+ .set_pkt_metadata = nfp_security_set_pkt_metadata,
.capabilities_get = nfp_crypto_capabilities_get,
};
diff --git a/drivers/net/nfp/nfp_ipsec.h b/drivers/net/nfp/nfp_ipsec.h
index 06792199c6..aaebb80fe1 100644
--- a/drivers/net/nfp/nfp_ipsec.h
+++ b/drivers/net/nfp/nfp_ipsec.h
@@ -168,6 +168,12 @@ struct nfp_net_ipsec_data {
struct nfp_ipsec_session *sa_entries[NFP_NET_IPSEC_MAX_SA_CNT];
};
+enum nfp_ipsec_meta_layer {
+ NFP_IPSEC_META_SAIDX, /**< Order of SA index in metadata */
+ NFP_IPSEC_META_SEQLOW, /**< Order of Sequence Number (low 32bits) in metadata */
+ NFP_IPSEC_META_SEQHI, /**< Order of Sequence Number (high 32bits) in metadata */
+};
+
int nfp_ipsec_init(struct rte_eth_dev *dev);
void nfp_ipsec_uninit(struct rte_eth_dev *dev);
diff --git a/drivers/net/nfp/nfp_rxtx.c b/drivers/net/nfp/nfp_rxtx.c
index e74aba7439..66a5d6cb3a 100644
--- a/drivers/net/nfp/nfp_rxtx.c
+++ b/drivers/net/nfp/nfp_rxtx.c
@@ -8,11 +8,13 @@
#include "nfp_rxtx.h"
#include <ethdev_pci.h>
+#include <rte_security.h>
#include "nfd3/nfp_nfd3.h"
#include "nfdk/nfp_nfdk.h"
#include "flower/nfp_flower.h"
+#include "nfp_ipsec.h"
#include "nfp_logs.h"
/* Maximum number of supported VLANs in parsed form packet metadata. */
@@ -25,8 +27,10 @@
* read-only after it have been recorded during parsing by nfp_net_parse_meta().
*
* @port_id: Port id value
+ * @sa_idx: IPsec SA index
* @hash: RSS hash value
* @hash_type: RSS hash type
+ * @ipsec_type: IPsec type
* @vlan_layer: The layers of VLAN info which are passed from nic.
* Only this number of entries of the @vlan array are valid.
*
@@ -44,8 +48,10 @@
*/
struct nfp_meta_parsed {
uint32_t port_id;
+ uint32_t sa_idx;
uint32_t hash;
uint8_t hash_type;
+ uint8_t ipsec_type;
uint8_t vlan_layer;
struct {
uint8_t offload;
@@ -304,6 +310,10 @@ nfp_net_parse_chained_meta(uint8_t *meta_base,
meta->vlan[meta->vlan_layer].tpid = NFP_NET_META_TPID(vlan_info);
++meta->vlan_layer;
break;
+ case NFP_NET_META_IPSEC:
+ meta->sa_idx = rte_be_to_cpu_32(*(rte_be32_t *)meta_offset);
+ meta->ipsec_type = meta_info & NFP_NET_META_FIELD_MASK;
+ break;
default:
/* Unsupported metadata can be a performance issue */
return false;
@@ -429,6 +439,39 @@ nfp_net_parse_meta_qinq(const struct nfp_meta_parsed *meta,
mb->ol_flags |= RTE_MBUF_F_RX_QINQ | RTE_MBUF_F_RX_QINQ_STRIPPED;
}
+/*
+ * Set mbuf IPsec Offload features based on metadata info.
+ *
+ * The IPsec Offload features is prepended to the mbuf ol_flags.
+ * Extract and decode metadata info and set the mbuf ol_flags.
+ */
+static void
+nfp_net_parse_meta_ipsec(struct nfp_meta_parsed *meta,
+ struct nfp_net_rxq *rxq,
+ struct rte_mbuf *mbuf)
+{
+ int offset;
+ uint32_t sa_idx;
+ struct nfp_net_hw *hw;
+ struct nfp_tx_ipsec_desc_msg *desc_md;
+
+ hw = rxq->hw;
+ sa_idx = meta->sa_idx;
+
+ if (meta->ipsec_type != NFP_NET_META_IPSEC)
+ return;
+
+ if (sa_idx >= NFP_NET_IPSEC_MAX_SA_CNT) {
+ mbuf->ol_flags |= RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED;
+ } else {
+ mbuf->ol_flags |= RTE_MBUF_F_RX_SEC_OFFLOAD;
+ offset = hw->ipsec_data->pkt_dynfield_offset;
+ desc_md = RTE_MBUF_DYNFIELD(mbuf, offset, struct nfp_tx_ipsec_desc_msg *);
+ desc_md->sa_idx = sa_idx;
+ desc_md->enc = 0;
+ }
+}
+
/* nfp_net_parse_meta() - Parse the metadata from packet */
static void
nfp_net_parse_meta(struct nfp_net_rx_desc *rxds,
@@ -453,6 +496,7 @@ nfp_net_parse_meta(struct nfp_net_rx_desc *rxds,
nfp_net_parse_meta_hash(meta, rxq, mb);
nfp_net_parse_meta_vlan(meta, rxds, rxq, mb);
nfp_net_parse_meta_qinq(meta, rxq, mb);
+ nfp_net_parse_meta_ipsec(meta, rxq, mb);
} else {
PMD_RX_LOG(DEBUG, "RX chained metadata format is wrong!");
}
@@ -1035,6 +1079,36 @@ nfp_net_set_meta_vlan(struct nfp_net_meta_raw *meta_data,
meta_data->data[layer] = rte_cpu_to_be_32(tpid << 16 | vlan_tci);
}
+void
+nfp_net_set_meta_ipsec(struct nfp_net_meta_raw *meta_data,
+ struct nfp_net_txq *txq,
+ struct rte_mbuf *pkt,
+ uint8_t layer,
+ uint8_t ipsec_layer)
+{
+ int offset;
+ struct nfp_net_hw *hw;
+ struct nfp_tx_ipsec_desc_msg *desc_md;
+
+ hw = txq->hw;
+ offset = hw->ipsec_data->pkt_dynfield_offset;
+ desc_md = RTE_MBUF_DYNFIELD(pkt, offset, struct nfp_tx_ipsec_desc_msg *);
+
+ switch (ipsec_layer) {
+ case NFP_IPSEC_META_SAIDX:
+ meta_data->data[layer] = desc_md->sa_idx;
+ break;
+ case NFP_IPSEC_META_SEQLOW:
+ meta_data->data[layer] = desc_md->esn.low;
+ break;
+ case NFP_IPSEC_META_SEQHI:
+ meta_data->data[layer] = desc_md->esn.hi;
+ break;
+ default:
+ break;
+ }
+}
+
int
nfp_net_tx_queue_setup(struct rte_eth_dev *dev,
uint16_t queue_idx,
diff --git a/drivers/net/nfp/nfp_rxtx.h b/drivers/net/nfp/nfp_rxtx.h
index 4e8558074e..3c7138f7d6 100644
--- a/drivers/net/nfp/nfp_rxtx.h
+++ b/drivers/net/nfp/nfp_rxtx.h
@@ -257,5 +257,10 @@ int nfp_net_tx_free_bufs(struct nfp_net_txq *txq);
void nfp_net_set_meta_vlan(struct nfp_net_meta_raw *meta_data,
struct rte_mbuf *pkt,
uint8_t layer);
+void nfp_net_set_meta_ipsec(struct nfp_net_meta_raw *meta_data,
+ struct nfp_net_txq *txq,
+ struct rte_mbuf *pkt,
+ uint8_t layer,
+ uint8_t ipsec_layer);
#endif /* _NFP_RXTX_H_ */
--
2.39.1
^ permalink raw reply [flat|nested] 42+ messages in thread
* [PATCH v3 9/9] net/nfp: destroy security session
2023-09-29 2:08 ` [PATCH v3 0/9] " Chaoyong He
` (7 preceding siblings ...)
2023-09-29 2:08 ` [PATCH v3 8/9] net/nfp: support IPsec Rx and Tx offload Chaoyong He
@ 2023-09-29 2:08 ` Chaoyong He
2023-09-29 10:05 ` [PATCH v3 0/9] add the support of ipsec offload Ferruh Yigit
9 siblings, 0 replies; 42+ messages in thread
From: Chaoyong He @ 2023-09-29 2:08 UTC (permalink / raw)
To: dev; +Cc: oss-drivers, Shihong Wang, Chaoyong He
From: Shihong Wang <shihong.wang@corigine.com>
Delete SA from NIC and destroy security session.
Signed-off-by: Shihong Wang <shihong.wang@corigine.com>
Reviewed-by: Chaoyong He <chaoyong.he@corigine.com>
---
drivers/net/nfp/nfp_ipsec.c | 53 +++++++++++++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/drivers/net/nfp/nfp_ipsec.c b/drivers/net/nfp/nfp_ipsec.c
index d1d593f18c..9edb096a58 100644
--- a/drivers/net/nfp/nfp_ipsec.c
+++ b/drivers/net/nfp/nfp_ipsec.c
@@ -1278,11 +1278,64 @@ nfp_security_session_get_size(void *device __rte_unused)
return sizeof(struct nfp_ipsec_session);
}
+static int
+nfp_crypto_remove_sa(struct rte_eth_dev *eth_dev,
+ struct nfp_ipsec_session *priv_session)
+{
+ int ret;
+ uint32_t sa_index;
+ struct nfp_net_hw *hw;
+ struct nfp_ipsec_msg cfg;
+
+ sa_index = priv_session->sa_index;
+ hw = NFP_NET_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
+
+ cfg.cmd = NFP_IPSEC_CFG_MSG_INV_SA;
+ cfg.sa_idx = sa_index;
+ ret = nfp_ipsec_cfg_cmd_issue(hw, &cfg);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to remove SA!");
+ return -EINVAL;
+ }
+
+ hw->ipsec_data->sa_free_cnt++;
+ hw->ipsec_data->sa_entries[sa_index] = NULL;
+
+ return 0;
+}
+
+static int
+nfp_crypto_remove_session(void *device,
+ struct rte_security_session *session)
+{
+ int ret;
+ struct rte_eth_dev *eth_dev;
+ struct nfp_ipsec_session *priv_session;
+
+ eth_dev = device;
+ priv_session = SECURITY_GET_SESS_PRIV(session);
+ if (eth_dev != priv_session->dev) {
+ PMD_DRV_LOG(ERR, "Session not bound to this device");
+ return -ENODEV;
+ }
+
+ ret = nfp_crypto_remove_sa(eth_dev, priv_session);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to remove session");
+ return -EFAULT;
+ }
+
+ memset(priv_session, 0, sizeof(struct nfp_ipsec_session));
+
+ return 0;
+}
+
static const struct rte_security_ops nfp_security_ops = {
.session_create = nfp_crypto_create_session,
.session_update = nfp_crypto_update_session,
.session_get_size = nfp_security_session_get_size,
.session_stats_get = nfp_security_session_get_stats,
+ .session_destroy = nfp_crypto_remove_session,
.set_pkt_metadata = nfp_security_set_pkt_metadata,
.capabilities_get = nfp_crypto_capabilities_get,
};
--
2.39.1
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v3 0/9] add the support of ipsec offload
2023-09-29 2:08 ` [PATCH v3 0/9] " Chaoyong He
` (8 preceding siblings ...)
2023-09-29 2:08 ` [PATCH v3 9/9] net/nfp: destroy security session Chaoyong He
@ 2023-09-29 10:05 ` Ferruh Yigit
9 siblings, 0 replies; 42+ messages in thread
From: Ferruh Yigit @ 2023-09-29 10:05 UTC (permalink / raw)
To: Chaoyong He, dev; +Cc: oss-drivers
On 9/29/2023 3:08 AM, Chaoyong He wrote:
> This patch series add the support of ipsec offload feature, includes:
> * Implement the communication channel between PMD and firmware through
> mailbox.
> * Implement the ipsec offload related APIs based the security framework.
> * Implement the ipsec packets process logics in the data path.
>
> ---
> v3:
> * Squash the update of mailmap file.
> * Add a entry in the release note.
> * Remove some unnecessary logic in the TLVs capability parsing function.
> v2:
> * Fix one spell error cause check warning.
> * Try to fix one compile error in Alpine environment of CI.
> ---
>
> Chang Miao (2):
> net/nfp: initialize IPsec related content
> net/nfp: create security session
>
> Shihong Wang (7):
> net/nfp: add TLVs capability parsing
> net/nfp: add mailbox to support IPsec offload
> net/nfp: get security capabilities and session size
> net/nfp: get IPsec Rx/Tx packet statistics
> net/nfp: update security session
> net/nfp: support IPsec Rx and Tx offload
> net/nfp: destroy security session
>
Series applied to dpdk-next-net/main, thanks.
^ permalink raw reply [flat|nested] 42+ messages in thread