From: liujie5@linkdatatechnology.com
To: stephen@networkplumber.org
Cc: dev@dpdk.org, Jie Liu <liujie5@linkdatatechnology.com>
Subject: [PATCH v6 07/20] net/sxe2: support IPsec inline protocol offload
Date: Tue, 2 Jun 2026 23:52:26 +0800 [thread overview]
Message-ID: <20260602155240.1002602-8-liujie5@linkdatatechnology.com> (raw)
In-Reply-To: <20260602155240.1002602-1-liujie5@linkdatatechnology.com>
From: Jie Liu <liujie5@linkdatatechnology.com>
This patch adds support for IPsec inline protocol offload for both
inbound and outbound traffic.
- Implement rte_security_ops: session_create, session_destroy.
- Add hardware SA table management.
- Update Rx/Tx data path to handle security offload flags.
The hardware offloads the ESP encapsulation/decapsulation and
cryptographic processing.
Signed-off-by: Jie Liu <liujie5@linkdatatechnology.com>
---
drivers/net/sxe2/meson.build | 2 +
drivers/net/sxe2/sxe2_cmd_chnl.c | 197 ++++
drivers/net/sxe2/sxe2_cmd_chnl.h | 20 +
drivers/net/sxe2/sxe2_drv_cmd.h | 61 ++
drivers/net/sxe2/sxe2_ethdev.c | 14 +
drivers/net/sxe2/sxe2_ethdev.h | 3 +
drivers/net/sxe2/sxe2_ipsec.c | 1565 +++++++++++++++++++++++++++++
drivers/net/sxe2/sxe2_ipsec.h | 254 +++++
drivers/net/sxe2/sxe2_rx.c | 5 +
drivers/net/sxe2/sxe2_security.c | 335 ++++++
drivers/net/sxe2/sxe2_security.h | 77 ++
drivers/net/sxe2/sxe2_tx.c | 8 +
drivers/net/sxe2/sxe2_txrx_poll.c | 55 +
13 files changed, 2596 insertions(+)
create mode 100644 drivers/net/sxe2/sxe2_ipsec.c
create mode 100644 drivers/net/sxe2/sxe2_ipsec.h
create mode 100644 drivers/net/sxe2/sxe2_security.c
create mode 100644 drivers/net/sxe2/sxe2_security.h
diff --git a/drivers/net/sxe2/meson.build b/drivers/net/sxe2/meson.build
index f03ea15356..86973edc99 100644
--- a/drivers/net/sxe2/meson.build
+++ b/drivers/net/sxe2/meson.build
@@ -64,4 +64,6 @@ sources += files(
'sxe2_filter.c',
'sxe2_rss.c',
'sxe2_tm.c',
+ 'sxe2_ipsec.c',
+ 'sxe2_security.c',
)
diff --git a/drivers/net/sxe2/sxe2_cmd_chnl.c b/drivers/net/sxe2/sxe2_cmd_chnl.c
index 19323ffcc4..7711e8e57d 100644
--- a/drivers/net/sxe2/sxe2_cmd_chnl.c
+++ b/drivers/net/sxe2/sxe2_cmd_chnl.c
@@ -877,3 +877,200 @@ int32_t sxe2_drv_tm_commit(struct sxe2_adapter *adapter)
l_end:
return ret;
}
+
+
+int32_t sxe2_drv_ipsec_get_capa(struct sxe2_adapter *adapter)
+{
+ int32_t ret = -1;
+ struct sxe2_drv_cmd_params cmd = { 0 };
+ struct sxe2_drv_ipsec_capa_resq resp;
+ struct sxe2_common_device *cdev = adapter->cdev;
+
+ sxe2_drv_cmd_params_fill(adapter, &cmd, SXE2_DRV_CMD_IPSEC_CAP_GET,
+ NULL, 0,
+ &resp, sizeof(resp));
+ ret = sxe2_drv_cmd_exec(cdev, &cmd);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to get ipsec specifications, ret=%d", ret);
+ goto l_end;
+ }
+
+ adapter->security_ctx.ipsec_ctx.max_tx_sa = rte_le_to_cpu_16(resp.tx_sa_cnt);
+ adapter->security_ctx.ipsec_ctx.max_rx_sa = rte_le_to_cpu_16(resp.rx_sa_cnt);
+ adapter->security_ctx.ipsec_ctx.max_tcam = rte_le_to_cpu_16(resp.ip_id_cnt);
+ adapter->security_ctx.ipsec_ctx.max_udp_group = rte_le_to_cpu_16(resp.udp_group_cnt);
+
+ PMD_DEV_LOG_INFO(adapter, DRV, "Max tx sa:%u, max rx sa:%u, max tcam:%u, udp group:%u.",
+ rte_le_to_cpu_16(resp.tx_sa_cnt),
+ rte_le_to_cpu_16(resp.rx_sa_cnt),
+ rte_le_to_cpu_16(resp.ip_id_cnt),
+ rte_le_to_cpu_16(resp.udp_group_cnt));
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_drv_ipsec_resource_clear(struct sxe2_adapter *adapter)
+{
+ int32_t ret = -1;
+ struct sxe2_drv_cmd_params cmd = { 0 };
+ struct sxe2_common_device *cdev = adapter->cdev;
+
+ sxe2_drv_cmd_params_fill(adapter, &cmd, SXE2_DRV_CMD_IPSEC_RESOURCE_CLEAR,
+ NULL, 0,
+ NULL, 0);
+ ret = sxe2_drv_cmd_exec(cdev, &cmd);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to clear ipsec resource, ret=%d", ret);
+ goto l_end;
+ }
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_drv_ipsec_txsa_add(struct sxe2_adapter *adapter,
+ struct sxe2_ipsec_tx_sa *tx_sa)
+{
+ struct sxe2_drv_cmd_params cmd = { 0 };
+ struct sxe2_drv_ipsec_txsa_add_req req = { 0 };
+ struct sxe2_drv_ipsec_txsa_add_resp resp = { 0 };
+ struct sxe2_common_device *cdev = adapter->cdev;
+ int32_t ret = -1;
+ uint32_t mode = 0;
+ uint32_t i = 0;
+
+ if (tx_sa->algo == SXE2_IPSEC_ALGO_SM4_CBC_AND_SM3_96_HMAC)
+ mode |= IPSEC_TX_ENGINE_SM4;
+ if (tx_sa->mode == SXE2_IPSEC_MODE_ENC_AND_AUTH)
+ mode |= IPSEC_TX_ENCRYPT;
+ req.mode = rte_cpu_to_le_32(mode);
+ for (i = 0; i < SXE2_IPSEC_KEY_LEN; i++) {
+ req.encrypt_keys[i] = tx_sa->enc_key[i];
+ req.auth_keys[i] = tx_sa->auth_key[i];
+ }
+
+ sxe2_drv_cmd_params_fill(adapter, &cmd, SXE2_DRV_CMD_IPSEC_TXSA_ADD,
+ &req, sizeof(req),
+ &resp, sizeof(resp));
+
+ ret = sxe2_drv_cmd_exec(cdev, &cmd);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "failed to add tx sa, ret=%d", ret);
+ goto l_end;
+ }
+ tx_sa->hw_sa_id = rte_le_to_cpu_16(resp.index);
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_drv_ipsec_rxsa_add(struct sxe2_adapter *adapter,
+ struct sxe2_ipsec_rx_sa *rx_sa,
+ struct sxe2_ipsec_rx_tcam *rx_tcam,
+ struct sxe2_ipsec_rx_udp_group *rx_udp_group)
+{
+ struct sxe2_drv_cmd_params cmd = { 0 };
+ struct sxe2_drv_ipsec_rxsa_add_req req = { 0 };
+ struct sxe2_drv_ipsec_rxsa_add_resp resp = { 0 };
+ struct sxe2_common_device *cdev = adapter->cdev;
+ int32_t ret = -1;
+ uint32_t mode = 0;
+ uint32_t i = 0;
+
+ if (rx_sa->algo == SXE2_IPSEC_ALGO_SM4_CBC_AND_SM3_96_HMAC)
+ mode |= IPSEC_RX_ENGINE_SM4;
+ if (rx_sa->mode == SXE2_IPSEC_MODE_ENC_AND_AUTH)
+ mode |= IPSEC_RX_DECRYPT;
+ if (rx_tcam->ip_addr.type == RTE_SECURITY_IPSEC_TUNNEL_IPV6) {
+ mode |= IPSEC_RX_IPV6;
+ memcpy(req.ipaddr, rx_tcam->ip_addr.dst_ipv6, sizeof(req.ipaddr));
+ } else {
+ req.ipaddr[0] = rx_tcam->ip_addr.dst_ipv4;
+ }
+ req.mode = rte_cpu_to_le_32(mode);
+ req.spi = rte_cpu_to_le_32(rx_sa->spi);
+ if (rx_udp_group != NULL) {
+ req.udp_port = rte_cpu_to_le_32((uint32_t)rx_udp_group->udp_port);
+ req.sport_en = rx_udp_group->sport_en;
+ req.dport_en = rx_udp_group->dport_en;
+ }
+
+ PMD_DEV_LOG_INFO(adapter, DRV, "Add rx sa, mode: 0x%x, spi: 0x%x, udp_port: %u, "
+ "sport_en: %u, dport_en: %u.",
+ req.mode, req.spi, req.udp_port, req.sport_en, req.dport_en);
+
+ /* encrypt and auth keys */
+ for (i = 0; i < SXE2_IPSEC_KEY_LEN; i++) {
+ req.encrypt_keys[i] = rx_sa->enc_key[i];
+ req.auth_keys[i] = rx_sa->auth_key[i];
+ }
+
+ sxe2_drv_cmd_params_fill(adapter, &cmd, SXE2_DRV_CMD_IPSEC_RXSA_ADD,
+ &req, sizeof(req),
+ &resp, sizeof(resp));
+
+ ret = sxe2_drv_cmd_exec(cdev, &cmd);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to add rx sa, ret=%d", ret);
+ goto l_end;
+ }
+ rx_sa->hw_sa_id = rte_le_to_cpu_16(resp.sa_idx);
+ rx_sa->hw_ip_id = resp.ip_id;
+ rx_tcam->hw_ip_id = resp.ip_id;
+ rx_sa->hw_udp_group_id = resp.udp_group_id;
+ if (rx_udp_group != NULL)
+ rx_udp_group->hw_group_id = resp.udp_group_id;
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_drv_ipsec_rxsa_delete(struct sxe2_adapter *adapter,
+ struct sxe2_ipsec_rx_sa *rx_sa)
+{
+ struct sxe2_drv_ipsec_rxsa_del_req req = { 0 };
+ struct sxe2_drv_cmd_params cmd = { 0 };
+ struct sxe2_common_device *cdev = adapter->cdev;
+ int32_t ret = -1;
+
+ req.sa_idx = rte_cpu_to_le_16(rx_sa->hw_sa_id);
+ req.spi = rte_cpu_to_le_32(rx_sa->spi);
+ req.ip_id = rx_sa->hw_ip_id;
+ req.group_id = rx_sa->hw_udp_group_id;
+
+ sxe2_drv_cmd_params_fill(adapter, &cmd, SXE2_DRV_CMD_IPSEC_RXSA_DEL,
+ &req, sizeof(req),
+ NULL, 0);
+ ret = sxe2_drv_cmd_exec(cdev, &cmd);
+ if (ret)
+ PMD_DEV_LOG_ERR(adapter, DRV,
+ "Failed to delete rx sa, sa id: %u, spi: %u, "
+ "ip id: %u, udp group id: %u, ret: %d.",
+ rx_sa->hw_sa_id, rx_sa->spi, rx_sa->hw_ip_id,
+ rx_sa->hw_udp_group_id, ret);
+
+ return ret;
+}
+
+int32_t sxe2_drv_ipsec_txsa_delete(struct sxe2_adapter *adapter,
+ uint16_t sa_id)
+{
+ struct sxe2_drv_ipsec_txsa_del_req req = { 0 };
+ struct sxe2_drv_cmd_params cmd = { 0 };
+ struct sxe2_common_device *cdev = adapter->cdev;
+ int32_t ret = -1;
+
+ req.sa_idx = rte_cpu_to_le_16(sa_id);
+ sxe2_drv_cmd_params_fill(adapter, &cmd, SXE2_DRV_CMD_IPSEC_TXSA_DEL,
+ &req, sizeof(req),
+ NULL, 0);
+ ret = sxe2_drv_cmd_exec(cdev, &cmd);
+ if (ret)
+ PMD_DEV_LOG_ERR(adapter, DRV,
+ "Failed to delete tx sa, sa id: %u, ret: %d.",
+ sa_id, ret);
+
+ return ret;
+}
+
diff --git a/drivers/net/sxe2/sxe2_cmd_chnl.h b/drivers/net/sxe2/sxe2_cmd_chnl.h
index 77e689abcd..dac487fe7d 100644
--- a/drivers/net/sxe2/sxe2_cmd_chnl.h
+++ b/drivers/net/sxe2/sxe2_cmd_chnl.h
@@ -44,6 +44,26 @@ int32_t sxe2_drv_root_tree_alloc(struct rte_eth_dev *dev);
int32_t sxe2_drv_tm_commit(struct sxe2_adapter *adapter);
+int32_t sxe2_drv_ipsec_resource_clear(struct sxe2_adapter *adapter);
+
+int32_t sxe2_drv_ipsec_get_capa(struct sxe2_adapter *adapter);
+
+int32_t sxe2_drv_ipsec_rxsa_add(struct sxe2_adapter *adapter,
+ struct sxe2_ipsec_rx_sa *rx_sa,
+ struct sxe2_ipsec_rx_tcam *rx_tcam,
+ struct sxe2_ipsec_rx_udp_group *rx_udp_group);
+
+int32_t sxe2_drv_ipsec_txsa_add(struct sxe2_adapter *adapter,
+ struct sxe2_ipsec_tx_sa *tx_sa);
+
+int32_t sxe2_drv_ipsec_rxsa_delete(struct sxe2_adapter *adapter,
+ struct sxe2_ipsec_rx_sa *rx_sa);
+
+int32_t sxe2_drv_ipsec_txsa_delete(struct sxe2_adapter *adapter,
+ uint16_t sa_id);
+
+int32_t sxe2_drv_promisc_config(struct sxe2_adapter *adapter, bool set);
+
int32_t sxe2_drv_allmulti_config(struct sxe2_adapter *adapter, bool set);
int32_t sxe2_drv_uc_config(struct sxe2_adapter *adapter, struct rte_ether_addr *addr, bool add);
diff --git a/drivers/net/sxe2/sxe2_drv_cmd.h b/drivers/net/sxe2/sxe2_drv_cmd.h
index 01b59124c6..42d6d51498 100644
--- a/drivers/net/sxe2/sxe2_drv_cmd.h
+++ b/drivers/net/sxe2/sxe2_drv_cmd.h
@@ -375,6 +375,67 @@ struct __rte_aligned(4) __rte_packed_begin sxe2_tm_add_queue_msg {
struct sxe2_tm_info info;
} __rte_packed_end;
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_ipsec_capa_resq {
+ uint16_t tx_sa_cnt;
+ uint16_t rx_sa_cnt;
+ uint16_t ip_id_cnt;
+ uint16_t udp_group_cnt;
+} __rte_packed_end;
+
+#define SXE2_IPSEC_KEY_LEN (32)
+#define SXE2_IPV6_ADDR_LEN (4)
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_ipsec_txsa_add_req {
+ uint32_t mode;
+ uint8_t encrypt_keys[SXE2_IPSEC_KEY_LEN];
+ uint8_t auth_keys[SXE2_IPSEC_KEY_LEN];
+ bool func_type;
+ uint8_t func_id;
+ uint8_t drv_id;
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_ipsec_txsa_add_resp {
+ uint16_t index;
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_ipsec_rxsa_add_req {
+ uint32_t mode;
+ uint32_t spi;
+ uint32_t ipaddr[SXE2_IPV6_ADDR_LEN];
+ uint32_t udp_port;
+ uint8_t sport_en;
+ uint8_t dport_en;
+ uint8_t is_over_sdn;
+ uint8_t sdn_group_id;
+ uint8_t encrypt_keys[SXE2_IPSEC_KEY_LEN];
+ uint8_t auth_keys[SXE2_IPSEC_KEY_LEN];
+ bool func_type;
+ uint8_t func_id;
+ uint8_t drv_id;
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_ipsec_rxsa_add_resp {
+ uint8_t ip_id;
+ uint8_t udp_group_id;
+ uint16_t sa_idx;
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_ipsec_txsa_del_req {
+ uint16_t sa_idx;
+ bool func_type;
+ uint8_t func_id;
+ uint8_t drv_id;
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_ipsec_rxsa_del_req {
+ uint8_t ip_id;
+ uint8_t group_id;
+ uint16_t sa_idx;
+ uint32_t spi;
+ bool func_type;
+ uint8_t func_id;
+ uint8_t drv_id;
+} __rte_packed_end;
+
enum sxe2_drv_cmd_module {
SXE2_DRV_CMD_MODULE_HANDSHAKE = 0,
SXE2_DRV_CMD_MODULE_DEV = 1,
diff --git a/drivers/net/sxe2/sxe2_ethdev.c b/drivers/net/sxe2/sxe2_ethdev.c
index a095888c00..00c0552d4a 100644
--- a/drivers/net/sxe2/sxe2_ethdev.c
+++ b/drivers/net/sxe2/sxe2_ethdev.c
@@ -298,6 +298,11 @@ static int32_t sxe2_dev_infos_get(struct rte_eth_dev *dev,
if (adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_PTP)
dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_TIMESTAMP;
+ if (sxe2_ipsec_supported(adapter)) {
+ dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_SECURITY;
+ dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_SECURITY;
+ }
+
if (adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_RSS) {
dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
dev_info->flow_type_rss_offloads |= SXE2_RSS_HF_SUPPORT_ALL;
@@ -1053,6 +1058,12 @@ static int32_t sxe2_dev_init(struct rte_eth_dev *dev,
goto init_eth_err;
}
+ ret = sxe2_security_init(dev);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to initialize security, ret=%d", ret);
+ goto init_security_err;
+ }
+
ret = sxe2_rss_disable(dev);
if (ret) {
PMD_LOG_ERR(INIT, "Failed to disable rss, ret=%d", ret);
@@ -1067,6 +1078,8 @@ static int32_t sxe2_dev_init(struct rte_eth_dev *dev,
goto l_end;
+init_security_err:
+ sxe2_eth_uinit(dev);
init_sched_err:
init_rss_err:
init_eth_err:
@@ -1085,6 +1098,7 @@ static int32_t sxe2_dev_close(struct rte_eth_dev *dev)
(void)sxe2_rss_disable(dev);
(void)sxe2_sched_uinit(dev);
sxe2_vsi_uninit(dev);
+ sxe2_security_uinit(dev);
sxe2_dev_pci_map_uinit(dev);
sxe2_eth_uinit(dev);
diff --git a/drivers/net/sxe2/sxe2_ethdev.h b/drivers/net/sxe2/sxe2_ethdev.h
index 76e4cc8b33..f226d6d5f9 100644
--- a/drivers/net/sxe2/sxe2_ethdev.h
+++ b/drivers/net/sxe2/sxe2_ethdev.h
@@ -20,6 +20,8 @@
#include "sxe2_queue.h"
#include "sxe2_mac.h"
#include "sxe2_osal.h"
+#include "sxe2_security.h"
+#include "sxe2_ipsec.h"
#include "sxe2_tm.h"
#include "sxe2_filter.h"
@@ -313,6 +315,7 @@ struct sxe2_adapter {
struct sxe2_sched_hw_cap sched_ctxt;
struct sxe2_tm_context tm_ctxt;
struct sxe2_devargs devargs;
+ struct sxe2_security_ctx security_ctx;
struct sxe2_switchdev_info switchdev_info;
bool rule_started;
bool flow_isolated;
diff --git a/drivers/net/sxe2/sxe2_ipsec.c b/drivers/net/sxe2/sxe2_ipsec.c
new file mode 100644
index 0000000000..e783a51b85
--- /dev/null
+++ b/drivers/net/sxe2/sxe2_ipsec.c
@@ -0,0 +1,1565 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#include <rte_malloc.h>
+#include <rte_bitmap.h>
+
+#include "sxe2_ethdev.h"
+#include "sxe2_security.h"
+#include "sxe2_ipsec.h"
+#include "sxe2_cmd_chnl.h"
+#include "sxe2_common_log.h"
+
+bool sxe2_ipsec_supported(struct sxe2_adapter *adapter)
+{
+ uint64_t cap = adapter->cap_flags;
+
+ return !!(cap & SXE2_DEV_CAPS_OFFLOAD_IPSEC);
+}
+
+bool sxe2_ipsec_valid_tx_offloads(uint64_t offloads)
+{
+ bool ret = true;
+ uint64_t tso_features = 0;
+ uint64_t cksum_features = 0;
+
+ if (offloads & RTE_ETH_TX_OFFLOAD_SECURITY) {
+ tso_features = RTE_ETH_TX_OFFLOAD_TCP_TSO |
+ RTE_ETH_TX_OFFLOAD_UDP_TSO |
+ RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO |
+ RTE_ETH_TX_OFFLOAD_GRE_TNL_TSO |
+ RTE_ETH_TX_OFFLOAD_IPIP_TNL_TSO |
+ RTE_ETH_TX_OFFLOAD_GENEVE_TNL_TSO;
+ if (offloads & tso_features) {
+ PMD_LOG_ERR(DRV, "Security offload is not compatible with TSO offload.");
+ ret = false;
+ goto l_end;
+ }
+
+ cksum_features = RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
+ RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
+ RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
+ RTE_ETH_TX_OFFLOAD_SCTP_CKSUM |
+ RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |
+ RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM;
+ if (offloads & cksum_features) {
+ PMD_LOG_ERR(DRV, "Security offload is not compatible with checksum offload.");
+ ret = false;
+ goto l_end;
+ }
+
+ if (offloads & (RTE_ETH_TX_OFFLOAD_VLAN_INSERT | RTE_ETH_TX_OFFLOAD_QINQ_INSERT)) {
+ PMD_LOG_ERR(DRV, "Security offload is not compatible with vlan offload.");
+ ret = false;
+ goto l_end;
+ }
+ }
+
+l_end:
+ return ret;
+}
+
+bool sxe2_ipsec_valid_rx_offloads(uint64_t offloads)
+{
+ bool ret = true;
+
+ if (offloads & RTE_ETH_RX_OFFLOAD_SECURITY) {
+ if (offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO) {
+ PMD_LOG_ERR(DRV, "Security offload is not compatible with LRO offload.");
+ ret = false;
+ goto l_end;
+ }
+
+ if (offloads & RTE_ETH_RX_OFFLOAD_CHECKSUM) {
+ PMD_LOG_ERR(DRV, "Security offload is not compatible with checksum offload.");
+ ret = false;
+ goto l_end;
+ }
+
+ if (offloads & RTE_ETH_RX_OFFLOAD_KEEP_CRC) {
+ PMD_LOG_ERR(DRV, "Security offload is not compatible with keep CRC offload.");
+ ret = false;
+ goto l_end;
+ }
+
+ if (offloads & RTE_ETH_RX_OFFLOAD_VLAN) {
+ PMD_LOG_ERR(DRV, "Security offload is not compatible with vlan offload.");
+ ret = false;
+ goto l_end;
+ }
+ }
+
+l_end:
+ return ret;
+}
+
+static int32_t sxe2_ipsec_bitmap_mem_init(struct rte_bitmap **d_bmp, void **d_mem, uint32_t bits)
+{
+ struct rte_bitmap *bmp = NULL;
+ uint32_t bmp_size = 0;
+ void *mem = NULL;
+ int32_t ret = -1;
+
+ bmp_size = rte_bitmap_get_memory_footprint(bits);
+
+ mem = rte_zmalloc("ipsec bitmap", bmp_size, RTE_CACHE_LINE_SIZE);
+ if (mem == NULL) {
+ PMD_LOG_ERR(DRV, "Alloc ipsec bitmap memory failed.");
+ ret = -ENOMEM;
+ goto l_end;
+ }
+
+ bmp = rte_bitmap_init(bits, mem, bmp_size);
+ if (bmp == NULL) {
+ PMD_LOG_ERR(DRV, "Failed to init ipsec bitmap.");
+ rte_free(mem);
+ ret = -ENOMEM;
+ goto l_end;
+ }
+
+ *d_bmp = bmp;
+ *d_mem = mem;
+
+ ret = 0;
+
+l_end:
+ return ret;
+}
+
+static int32_t sxe2_ipsec_bitmap_init(struct sxe2_security_ctx *sxe2_sctx)
+{
+ int32_t ret = -1;
+
+ ret = sxe2_ipsec_bitmap_mem_init(&sxe2_sctx->ipsec_ctx.bmp.tx_sa_bmp,
+ &sxe2_sctx->ipsec_ctx.bmp.tx_sa_mem, sxe2_sctx->ipsec_ctx.max_tx_sa);
+ if (ret)
+ goto l_end;
+
+ ret = sxe2_ipsec_bitmap_mem_init(&sxe2_sctx->ipsec_ctx.bmp.rx_sa_bmp,
+ &sxe2_sctx->ipsec_ctx.bmp.rx_sa_mem, sxe2_sctx->ipsec_ctx.max_rx_sa);
+ if (ret) {
+ rte_free(sxe2_sctx->ipsec_ctx.bmp.tx_sa_mem);
+ sxe2_sctx->ipsec_ctx.bmp.tx_sa_mem = NULL;
+ goto l_end;
+ }
+
+ ret = sxe2_ipsec_bitmap_mem_init(&sxe2_sctx->ipsec_ctx.bmp.rx_tcam_bmp,
+ &sxe2_sctx->ipsec_ctx.bmp.rx_tcam_mem, sxe2_sctx->ipsec_ctx.max_tcam);
+ if (ret) {
+ rte_free(sxe2_sctx->ipsec_ctx.bmp.tx_sa_mem);
+ rte_free(sxe2_sctx->ipsec_ctx.bmp.rx_sa_mem);
+ sxe2_sctx->ipsec_ctx.bmp.tx_sa_mem = NULL;
+ sxe2_sctx->ipsec_ctx.bmp.rx_sa_mem = NULL;
+ goto l_end;
+ }
+
+ ret = sxe2_ipsec_bitmap_mem_init(&sxe2_sctx->ipsec_ctx.bmp.rx_udp_bmp,
+ &sxe2_sctx->ipsec_ctx.bmp.rx_udp_mem, sxe2_sctx->ipsec_ctx.max_udp_group);
+ if (ret) {
+ rte_free(sxe2_sctx->ipsec_ctx.bmp.tx_sa_mem);
+ rte_free(sxe2_sctx->ipsec_ctx.bmp.rx_sa_mem);
+ rte_free(sxe2_sctx->ipsec_ctx.bmp.rx_tcam_mem);
+ sxe2_sctx->ipsec_ctx.bmp.tx_sa_mem = NULL;
+ sxe2_sctx->ipsec_ctx.bmp.rx_sa_mem = NULL;
+ sxe2_sctx->ipsec_ctx.bmp.rx_tcam_mem = NULL;
+ goto l_end;
+ }
+
+l_end:
+ return ret;
+}
+
+static uint16_t sxe2_ipsec_id_alloc(struct rte_bitmap *bmp, uint16_t bits)
+{
+ uint16_t i = 0;
+ uint16_t index = 0XFFFF;
+
+ for (i = 0; i < bits; i++) {
+ if (!rte_bitmap_get(bmp, i)) {
+ index = i;
+ rte_bitmap_set(bmp, i);
+ break;
+ }
+ }
+
+ return index;
+}
+
+static void sxe2_ipsec_id_free(struct rte_bitmap *bmp, uint16_t pos)
+{
+ rte_bitmap_clear(bmp, pos);
+}
+
+static struct rte_cryptodev_symmetric_capability *
+sxe2_ipsec_cipher_cap_get(struct rte_cryptodev_capabilities *crypto_cap,
+ enum rte_crypto_cipher_algorithm algo)
+{
+ struct rte_cryptodev_symmetric_capability *capability = NULL;
+ uint8_t index = 0;
+
+ for (index = 0; index < SXE2_IPSEC_CAP_MAX; index++) {
+ if (crypto_cap[index].sym.xform_type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
+ crypto_cap[index].sym.cipher.algo == algo) {
+ capability = &crypto_cap[index].sym;
+ goto l_end;
+ }
+ }
+
+l_end:
+ return capability;
+}
+
+static struct rte_cryptodev_symmetric_capability *
+sxe2_ipsec_auth_cap_get(struct rte_cryptodev_capabilities *crypto_cap,
+ enum rte_crypto_auth_algorithm algo)
+{
+ struct rte_cryptodev_symmetric_capability *capability = NULL;
+ uint8_t index = 0;
+
+ for (index = 0; index < SXE2_IPSEC_CAP_MAX; index++) {
+ if (crypto_cap[index].sym.xform_type == RTE_CRYPTO_SYM_XFORM_AUTH &&
+ crypto_cap[index].sym.auth.algo == algo) {
+ capability = &crypto_cap[index].sym;
+ goto l_end;
+ }
+ }
+
+l_end:
+ return capability;
+}
+
+static bool sxe2_security_valid_key(uint16_t src_key, uint16_t max_key,
+ uint16_t min_key, uint16_t increment)
+{
+ bool is_valid = false;
+
+ if (src_key > SXE2_IPSEC_MAX_KEY_LEN) {
+ is_valid = false;
+ goto l_end;
+ }
+
+ if (src_key < min_key || src_key > max_key) {
+ is_valid = false;
+ goto l_end;
+ }
+
+ if (increment == 0) {
+ is_valid = true;
+ goto l_end;
+ }
+
+ if ((uint16_t)(src_key - min_key) % increment) {
+ is_valid = false;
+ goto l_end;
+ }
+
+ is_valid = true;
+
+l_end:
+ return is_valid;
+}
+
+static int32_t
+sxe2_ipsec_valid_cipher(enum rte_crypto_cipher_operation cipher_op,
+ struct rte_cryptodev_capabilities *crypto_cap,
+ struct rte_crypto_sym_xform *xform)
+{
+ const struct rte_cryptodev_symmetric_capability *capability = NULL;
+ uint16_t src_key = 0;
+ uint16_t max_key = 0;
+ uint16_t min_key = 0;
+ uint16_t increment = 0;
+ int32_t ret = -1;
+
+ if (xform->cipher.op != cipher_op) {
+ PMD_LOG_ERR(DRV, "Invalid cipher direction specified");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ capability = sxe2_ipsec_cipher_cap_get(crypto_cap, xform->cipher.algo);
+ if (!capability) {
+ PMD_LOG_ERR(DRV, "Invalid cipher algo specified");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ src_key = xform->cipher.key.length;
+ min_key = capability->cipher.key_size.min;
+ max_key = capability->cipher.key_size.max;
+ increment = capability->cipher.key_size.increment;
+ if (!sxe2_security_valid_key(src_key, max_key, min_key, increment)) {
+ PMD_LOG_ERR(DRV, "Invalid cipher key size specified");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ ret = 0;
+
+l_end:
+ return ret;
+}
+
+static int32_t
+sxe2_ipsec_valid_auth(enum rte_crypto_auth_operation auth_op,
+ struct rte_cryptodev_capabilities *crypto_cap,
+ struct rte_crypto_sym_xform *xform)
+{
+ const struct rte_cryptodev_symmetric_capability *capability = NULL;
+ uint16_t src_key = 0;
+ uint16_t max_key = 0;
+ uint16_t min_key = 0;
+ uint16_t increment = 0;
+ int32_t ret = -1;
+
+ if (xform->auth.op != auth_op) {
+ PMD_LOG_ERR(DRV, "Invalid auth direction specified");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ capability = sxe2_ipsec_auth_cap_get(crypto_cap, xform->auth.algo);
+ if (!capability) {
+ PMD_LOG_ERR(DRV, "Invalid auth algo specified");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ src_key = xform->auth.key.length;
+ min_key = capability->auth.key_size.min;
+ max_key = capability->auth.key_size.max;
+ increment = capability->auth.key_size.increment;
+ if (!sxe2_security_valid_key(src_key, max_key, min_key, increment)) {
+ PMD_LOG_ERR(DRV, "Invalid auth key size specified");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ ret = 0;
+
+l_end:
+ return ret;
+}
+
+static bool
+sxe2_ipsec_valid_algo(enum rte_crypto_auth_algorithm auth_algo,
+ enum rte_crypto_cipher_algorithm cipher_algo)
+{
+ bool ret = false;
+
+ if ((cipher_algo == SXE2_RTE_CRYPTO_CIPHER_AES_CBC &&
+ auth_algo == SXE2_RTE_CRYPTO_AUTH_SHA256_HMAC) ||
+ (cipher_algo == SXE2_RTE_RTE_CRYPTO_CIPHER_SM4_CBC &&
+ auth_algo == SXE2_RTE_CRYPTO_AUTH_SM3_HMAC)) {
+ ret = true;
+ goto l_end;
+ }
+
+l_end:
+ return ret;
+}
+
+static enum sxe2_ipsec_algorithm
+sxe2_ipsec_algo_gen(enum rte_crypto_cipher_algorithm cipher_algo)
+{
+ enum sxe2_ipsec_algorithm algo = SXE2_IPSEC_ALGO_INVALID;
+
+ if (cipher_algo == SXE2_RTE_CRYPTO_CIPHER_AES_CBC)
+ algo = SXE2_IPSEC_ALGO_AES_CBC_AND_SHA256_128_HMAC;
+ else if (cipher_algo == SXE2_RTE_RTE_CRYPTO_CIPHER_SM4_CBC)
+ algo = SXE2_IPSEC_ALGO_SM4_CBC_AND_SM3_96_HMAC;
+
+ return algo;
+}
+
+static int32_t
+ sxe2_ipsec_valid_xform(struct sxe2_security_ctx *sxe2_sctx,
+ struct rte_security_session_conf *conf)
+{
+ struct rte_crypto_sym_xform *xform = NULL;
+ struct rte_cryptodev_capabilities *crypto_cap =
+ sxe2_sctx->sxe2_capabilities[SXE2_SECURITY_PROTOCOL_IPSEC].crypto_capabilities;
+ enum rte_crypto_auth_algorithm auth_algo = RTE_CRYPTO_AUTH_NULL;
+ enum rte_crypto_cipher_algorithm cipher_algo = RTE_CRYPTO_CIPHER_NULL;
+ int32_t ret = -1;
+
+ if (conf->ipsec.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS &&
+ conf->crypto_xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
+ xform = conf->crypto_xform;
+ cipher_algo = xform->cipher.algo;
+ ret = sxe2_ipsec_valid_cipher(RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ crypto_cap, xform);
+ if (ret)
+ goto l_end;
+
+ if (conf->crypto_xform->next) {
+ if (conf->crypto_xform->next->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
+ auth_algo = conf->crypto_xform->next->auth.algo;
+ if (!sxe2_ipsec_valid_algo(auth_algo, cipher_algo)) {
+ PMD_LOG_ERR(DRV, "Invalid algo group.");
+ ret = -EINVAL;
+ goto l_end;
+ }
+ xform = conf->crypto_xform->next;
+ ret = sxe2_ipsec_valid_auth(RTE_CRYPTO_AUTH_OP_GENERATE,
+ crypto_cap, xform);
+ if (ret)
+ goto l_end;
+ } else {
+ PMD_LOG_ERR(DRV, "Encrypt direction next xform only verify.");
+ ret = -EINVAL;
+ goto l_end;
+ }
+ }
+ } else if (conf->ipsec.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS &&
+ conf->crypto_xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
+ xform = conf->crypto_xform;
+ ret = sxe2_ipsec_valid_cipher(RTE_CRYPTO_CIPHER_OP_DECRYPT,
+ crypto_cap, xform);
+ if (ret)
+ goto l_end;
+
+ } else if (conf->ipsec.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS &&
+ conf->crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
+ xform = conf->crypto_xform;
+ ret = sxe2_ipsec_valid_auth(RTE_CRYPTO_AUTH_OP_VERIFY, crypto_cap, xform);
+ if (ret)
+ goto l_end;
+
+ if (conf->crypto_xform->next &&
+ conf->crypto_xform->next->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
+ auth_algo = conf->crypto_xform->auth.algo;
+ cipher_algo = conf->crypto_xform->next->cipher.algo;
+ if (!sxe2_ipsec_valid_algo(auth_algo, cipher_algo)) {
+ PMD_LOG_ERR(DRV, "Invalid algo group.");
+ ret = -EINVAL;
+ goto l_end;
+ }
+ xform = conf->crypto_xform->next;
+ ret = sxe2_ipsec_valid_cipher(RTE_CRYPTO_CIPHER_OP_DECRYPT,
+ crypto_cap, xform);
+ if (ret)
+ goto l_end;
+ } else {
+ PMD_LOG_ERR(DRV, "Not support decrypt direction only verify, but not decrypt.");
+ ret = -EINVAL;
+ goto l_end;
+ }
+ } else {
+ PMD_LOG_ERR(DRV, "Encrypt/decrypt xform invalid.");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ ret = 0;
+
+l_end:
+ return ret;
+}
+
+static int32_t
+sxe2_ipsec_valid_udp(struct rte_security_session_conf *conf)
+{
+ int32_t ret = -1;
+ uint16_t sport = conf->ipsec.udp.sport;
+ uint16_t dport = conf->ipsec.udp.dport;
+
+ if (conf->ipsec.options.udp_encap == 0) {
+ ret = 0;
+ goto l_end;
+ }
+
+ if (sport == 0 && dport == 0) {
+ PMD_LOG_ERR(DRV, "Invalid udp port, cannot be zero.");
+ ret = -1;
+ goto l_end;
+ }
+
+ if (sport != 0 && dport != 0 && sport != dport) {
+ PMD_LOG_ERR(DRV, "Invalid udp port, if sport and dport is not zero, must be equal.");
+ ret = -1;
+ goto l_end;
+ }
+
+ ret = 0;
+
+l_end:
+ return ret;
+}
+
+static int32_t
+sxe2_ipsec_session_conf_valid(struct sxe2_security_ctx *sxe2_sctx,
+ struct rte_security_session_conf *conf)
+{
+ int32_t ret = -1;
+
+ if (sxe2_sctx == NULL) {
+ PMD_LOG_ERR(DRV, "Invalid security ctx.");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if (conf->action_type !=
+ sxe2_sctx->sxe2_capabilities[SXE2_SECURITY_PROTOCOL_IPSEC].action) {
+ PMD_LOG_ERR(DRV, "Invalid action specified");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if (conf->ipsec.mode !=
+ sxe2_sctx->sxe2_capabilities[SXE2_SECURITY_PROTOCOL_IPSEC].ipsec.mode) {
+ PMD_LOG_ERR(DRV, "Invalid IPsec mode specified");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if (conf->ipsec.proto !=
+ sxe2_sctx->sxe2_capabilities[SXE2_SECURITY_PROTOCOL_IPSEC].ipsec.proto) {
+ PMD_LOG_ERR(DRV, "Invalid IPsec protocol specified");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if (conf->ipsec.options.esn) {
+ PMD_LOG_ERR(DRV, "Not support esn.");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if (conf->ipsec.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS &&
+ conf->ipsec.spi == 0) {
+ PMD_LOG_ERR(DRV, "spi cannot be zero.");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if (conf->crypto_xform == NULL) {
+ PMD_LOG_ERR(DRV, "Invalid ipsec xform specified");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ ret = sxe2_ipsec_valid_udp(conf);
+ if (ret)
+ goto l_end;
+
+ ret = sxe2_ipsec_valid_xform(sxe2_sctx, conf);
+ if (ret)
+ goto l_end;
+
+l_end:
+ return ret;
+}
+
+static void
+sxe2_ipsec_session_save(struct sxe2_security_ctx *sxe2_sctx,
+ struct rte_security_session_conf *conf,
+ struct sxe2_security_session *sxe2_sess, uint16_t sa_id, uint16_t index)
+{
+ enum rte_crypto_cipher_algorithm cipher_algo = RTE_CRYPTO_CIPHER_NULL;
+
+ sxe2_sess->adapter = sxe2_sctx->adapter;
+ sxe2_sess->direction = conf->ipsec.direction;
+ sxe2_sess->protocol = conf->protocol;
+ sxe2_sess->mode = conf->ipsec.mode;
+ sxe2_sess->sa_proto = conf->ipsec.proto;
+ sxe2_sess->sa.spi = conf->ipsec.spi;
+ sxe2_sess->sa.hw_idx = sa_id;
+ sxe2_sess->sa.sw_idx = index;
+
+ if (conf->ipsec.options.esn) {
+ sxe2_sess->esn.enabled = true;
+ sxe2_sess->esn.value = conf->ipsec.esn.value;
+ }
+
+ if (sxe2_sess->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL)
+ sxe2_sess->type = conf->ipsec.tunnel.type;
+
+ if (conf->ipsec.options.udp_encap) {
+ sxe2_sess->udp_cap.enabled = true;
+ memcpy(&sxe2_sess->udp_cap.value, &conf->ipsec.udp,
+ sizeof(struct rte_security_ipsec_udp_param));
+ }
+
+ sxe2_sess->pkt_metadata_template.sa_idx = sa_id;
+ sxe2_sess->pkt_metadata_template.ol_flags |= SXE2_IPSEC_OL_FLAGS_IS_TUN;
+ sxe2_sess->pkt_metadata_template.ol_flags |= SXE2_IPSEC_OL_FLAGS_IS_ESP;
+
+ if (conf->ipsec.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS &&
+ conf->crypto_xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
+ cipher_algo = conf->crypto_xform->cipher.algo;
+ sxe2_sess->pkt_metadata_template.algo = sxe2_ipsec_algo_gen(cipher_algo);
+ if (conf->crypto_xform->next)
+ sxe2_sess->pkt_metadata_template.mode = SXE2_IPSEC_MODE_ENC_AND_AUTH;
+ else
+ sxe2_sess->pkt_metadata_template.mode = SXE2_IPSEC_MODE_ONLY_ENCRYPT;
+ }
+
+ PMD_LOG_INFO(DRV,
+ "Save security info to session ctx, said:%u, spi:%u, mode:%u, algo:%u",
+ sa_id, sxe2_sess->sa.spi,
+ sxe2_sess->pkt_metadata_template.mode,
+ sxe2_sess->pkt_metadata_template.algo);
+}
+
+static void
+sxe2_ipsec_tx_sa_fill(struct sxe2_ipsec_tx_sa *tx_sa,
+ struct rte_security_session_conf *conf)
+{
+ uint8_t *dst = NULL;
+ uint8_t len = 0;
+
+ memcpy(&tx_sa->xform, &conf->ipsec, sizeof(struct rte_security_ipsec_xform));
+
+ if (conf->crypto_xform->next)
+ tx_sa->mode = SXE2_IPSEC_MODE_ENC_AND_AUTH;
+ else
+ tx_sa->mode = SXE2_IPSEC_MODE_ONLY_ENCRYPT;
+
+ if (conf->crypto_xform->cipher.algo == SXE2_RTE_RTE_CRYPTO_CIPHER_SM4_CBC)
+ tx_sa->algo = SXE2_IPSEC_ALGO_SM4_CBC_AND_SM3_96_HMAC;
+ else
+ tx_sa->algo = SXE2_IPSEC_ALGO_AES_CBC_AND_SHA256_128_HMAC;
+
+ dst = tx_sa->enc_key;
+ len = conf->crypto_xform->cipher.key.length;
+ memcpy(dst, conf->crypto_xform->cipher.key.data, len);
+
+ if (conf->crypto_xform->next) {
+ dst = tx_sa->auth_key;
+ len = conf->crypto_xform->next->auth.key.length;
+ memcpy(dst, conf->crypto_xform->next->auth.key.data, len);
+ }
+}
+
+static int32_t
+sxe2_ipsec_tx_sa_add(struct sxe2_security_ctx *sxe2_sctx,
+ struct rte_security_session_conf *conf,
+ struct sxe2_security_session *sxe2_sess)
+{
+ struct sxe2_ipsec_tx_sa *tx_sa = NULL;
+ struct rte_bitmap *bmp = sxe2_sctx->ipsec_ctx.bmp.tx_sa_bmp;
+ uint16_t bits = sxe2_sctx->ipsec_ctx.max_tx_sa;
+ uint16_t index = 0xFFFF;
+ int32_t ret = -1;
+
+ rte_spinlock_lock(&sxe2_sctx->security_lock);
+ index = sxe2_ipsec_id_alloc(bmp, bits);
+ rte_spinlock_unlock(&sxe2_sctx->security_lock);
+ if (index == 0xFFFF) {
+ PMD_LOG_ERR(DRV, "Failed to allocate ipsec tx sa index.");
+ ret = -ENOMEM;
+ goto l_end;
+ }
+ tx_sa = &sxe2_sctx->ipsec_ctx.tx_sa[index];
+
+ sxe2_ipsec_tx_sa_fill(tx_sa, conf);
+
+ ret = sxe2_drv_ipsec_txsa_add(sxe2_sctx->adapter, tx_sa);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "Failed to add tx sa.");
+ ret = -EIO;
+ rte_spinlock_lock(&sxe2_sctx->security_lock);
+ sxe2_ipsec_id_free(bmp, index);
+ rte_spinlock_unlock(&sxe2_sctx->security_lock);
+ goto l_end;
+ }
+
+ sxe2_ipsec_session_save(sxe2_sctx, conf, sxe2_sess, tx_sa->hw_sa_id, tx_sa->id);
+
+ PMD_LOG_INFO(DRV, "Add tx sa success, tx sa id: %u, index: %u.",
+ tx_sa->hw_sa_id, tx_sa->id);
+
+l_end:
+ return ret;
+}
+
+static uint16_t
+sxe2_ipsec_tcam_id_find(struct sxe2_ipsec_rx_tcam *rx_tcam,
+ struct rte_security_ipsec_tunnel_param tunnel, uint16_t len)
+{
+ struct sxe2_ipsec_rx_tcam *per = NULL;
+ uint16_t tcam_id = 0XFFFF;
+ uint16_t i = 0;
+
+ for (i = 0; i < len; i++) {
+ per = &rx_tcam[i];
+ if (per->ip_addr.type == tunnel.type) {
+ if (tunnel.type == RTE_SECURITY_IPSEC_TUNNEL_IPV4 &&
+ per->ip_addr.dst_ipv4 == (uint32_t)tunnel.ipv4.dst_ip.s_addr) {
+ tcam_id = i;
+ goto l_end;
+ }
+ if (tunnel.type == RTE_SECURITY_IPSEC_TUNNEL_IPV6) {
+ if (!memcmp(&tunnel.ipv6, &per->ip_addr.dst_ipv6,
+ sizeof(tunnel.ipv6))) {
+ tcam_id = i;
+ goto l_end;
+ }
+ }
+ }
+ }
+
+l_end:
+ return tcam_id;
+}
+
+static uint16_t
+sxe2_ipsec_group_id_find(struct sxe2_ipsec_rx_udp_group *rx_udp_group,
+ uint16_t udp_port, uint8_t sport_en, uint8_t dport_en, uint16_t len)
+{
+ struct sxe2_ipsec_rx_udp_group *per = NULL;
+ uint16_t group_id = 0XFFFF;
+ uint16_t i;
+
+ for (i = 0; i < len; i++) {
+ per = &rx_udp_group[i];
+ if (per->udp_port == udp_port && per->sport_en == sport_en &&
+ per->dport_en == dport_en) {
+ group_id = i;
+ goto l_end;
+ }
+ }
+
+l_end:
+ return group_id;
+}
+
+static void
+sxe2_ipsec_rx_sa_fill(struct sxe2_ipsec_rx_sa *rx_sa,
+ struct rte_security_session_conf *conf)
+{
+ uint8_t *dst = NULL;
+ uint8_t len = 0;
+
+ memcpy(&rx_sa->xform, &conf->ipsec, sizeof(struct rte_security_ipsec_xform));
+
+ if (conf->crypto_xform->next)
+ rx_sa->mode = SXE2_IPSEC_MODE_ENC_AND_AUTH;
+ else
+ rx_sa->mode = SXE2_IPSEC_MODE_ONLY_ENCRYPT;
+
+ if (conf->crypto_xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
+ if (conf->crypto_xform->cipher.algo == SXE2_RTE_RTE_CRYPTO_CIPHER_SM4_CBC)
+ rx_sa->algo = SXE2_IPSEC_ALGO_SM4_CBC_AND_SM3_96_HMAC;
+ else
+ rx_sa->algo = SXE2_IPSEC_ALGO_AES_CBC_AND_SHA256_128_HMAC;
+ } else {
+ if (conf->crypto_xform->auth.algo == SXE2_RTE_CRYPTO_AUTH_SM3_HMAC)
+ rx_sa->algo = SXE2_IPSEC_ALGO_SM4_CBC_AND_SM3_96_HMAC;
+ else
+ rx_sa->algo = SXE2_IPSEC_ALGO_AES_CBC_AND_SHA256_128_HMAC;
+ }
+
+ if (conf->crypto_xform->next) {
+ dst = rx_sa->auth_key;
+ len = conf->crypto_xform->auth.key.length;
+ memcpy(dst, conf->crypto_xform->auth.key.data, len);
+
+ dst = rx_sa->enc_key;
+ len = conf->crypto_xform->next->cipher.key.length;
+ memcpy(dst, conf->crypto_xform->next->cipher.key.data, len);
+ } else {
+ dst = rx_sa->enc_key;
+ len = conf->crypto_xform->cipher.key.length;
+ memcpy(dst, conf->crypto_xform->cipher.key.data, len);
+ }
+
+ rx_sa->spi = conf->ipsec.spi;
+}
+
+static int32_t
+sxe2_ipsec_rx_tcam_fill(struct sxe2_security_ctx *sxe2_sctx, uint16_t *tcam_id,
+ struct rte_security_session_conf *conf)
+{
+ int32_t ret = -1;
+ uint16_t len = sxe2_sctx->ipsec_ctx.max_tcam;
+ struct sxe2_ipsec_rx_tcam *rx_tcam = NULL;
+
+ *tcam_id = sxe2_ipsec_tcam_id_find(sxe2_sctx->ipsec_ctx.rx_tcam,
+ conf->ipsec.tunnel, len);
+ if (*tcam_id == 0XFFFF) {
+ *tcam_id = sxe2_ipsec_id_alloc(sxe2_sctx->ipsec_ctx.bmp.rx_tcam_bmp, len);
+ if (*tcam_id == 0xFFFF) {
+ ret = -ENOMEM;
+ goto l_end;
+ }
+ rx_tcam = &sxe2_sctx->ipsec_ctx.rx_tcam[*tcam_id];
+
+ rx_tcam->ip_addr.type = conf->ipsec.tunnel.type;
+ if (rx_tcam->ip_addr.type == RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
+ rx_tcam->ip_addr.dst_ipv4 = (uint32_t)conf->ipsec.tunnel.ipv4.dst_ip.s_addr;
+ } else {
+ memcpy(&rx_tcam->ip_addr.dst_ipv6, &conf->ipsec.tunnel.ipv6.dst_addr,
+ sizeof(rx_tcam->ip_addr.dst_ipv6));
+ }
+ } else {
+ rx_tcam = &sxe2_sctx->ipsec_ctx.rx_tcam[*tcam_id];
+ }
+ rx_tcam->ref_cnt++;
+ ret = 0;
+
+l_end:
+ return ret;
+}
+
+static int32_t
+sxe2_ipsec_rx_udp_group_fill(struct sxe2_security_ctx *sxe2_sctx, uint16_t *udp_group_id,
+ struct rte_security_session_conf *conf)
+{
+ int32_t ret = -1;
+ uint16_t len = sxe2_sctx->ipsec_ctx.max_udp_group;
+ struct sxe2_ipsec_rx_udp_group *rx_udp_group = NULL;
+ uint8_t sport_en = 0;
+ uint8_t dport_en = 0;
+ uint16_t udp_port = 0;
+
+ if (!conf->ipsec.options.udp_encap) {
+ ret = 0;
+ goto l_end;
+ }
+
+ if (conf->ipsec.udp.sport) {
+ sport_en = 1;
+ udp_port = conf->ipsec.udp.sport;
+ } else {
+ sport_en = 0;
+ }
+ if (conf->ipsec.udp.dport) {
+ dport_en = 1;
+ udp_port = conf->ipsec.udp.dport;
+ } else {
+ dport_en = 0;
+ }
+
+ *udp_group_id = sxe2_ipsec_group_id_find(sxe2_sctx->ipsec_ctx.rx_udp_group,
+ udp_port, sport_en, dport_en, len);
+ if (*udp_group_id == 0XFFFF) {
+ *udp_group_id = sxe2_ipsec_id_alloc(sxe2_sctx->ipsec_ctx.bmp.rx_udp_bmp, len);
+ if (*udp_group_id == 0xFFFF) {
+ ret = -ENOMEM;
+ goto l_end;
+ }
+ rx_udp_group = &sxe2_sctx->ipsec_ctx.rx_udp_group[*udp_group_id];
+ rx_udp_group->sport_en = sport_en;
+ rx_udp_group->dport_en = dport_en;
+ rx_udp_group->udp_port = udp_port;
+ } else {
+ rx_udp_group = &sxe2_sctx->ipsec_ctx.rx_udp_group[*udp_group_id];
+ }
+ rx_udp_group->ref_cnt++;
+ ret = 0;
+
+l_end:
+ return ret;
+}
+
+static int32_t
+sxe2_ipsec_rx_sa_add(struct sxe2_security_ctx *sxe2_sctx,
+ struct rte_security_session_conf *conf,
+ struct sxe2_security_session *sxe2_sess)
+{
+ struct sxe2_ipsec_rx_tcam *rx_tcam = NULL;
+ struct sxe2_ipsec_rx_sa *rx_sa = NULL;
+ struct sxe2_ipsec_rx_udp_group *rx_udp_group = NULL;
+ struct rte_bitmap *rx_sa_bmp = sxe2_sctx->ipsec_ctx.bmp.rx_sa_bmp;
+ struct rte_bitmap *rx_tcam_bmp = sxe2_sctx->ipsec_ctx.bmp.rx_tcam_bmp;
+ uint16_t sa_bits = sxe2_sctx->ipsec_ctx.max_rx_sa;
+ uint16_t sa_id = 0xFFFF;
+ uint16_t tcam_id = 0xFFFF;
+ uint16_t udp_group_id = 0xFFFF;
+ int32_t ret = -1;
+
+ rte_spinlock_lock(&sxe2_sctx->security_lock);
+ sa_id = sxe2_ipsec_id_alloc(rx_sa_bmp, sa_bits);
+ if (sa_id == 0xFFFF) {
+ PMD_LOG_ERR(DRV, "Failed to allocate ipsec rx sa index.");
+ ret = -ENOMEM;
+ goto l_end;
+ }
+ rx_sa = &sxe2_sctx->ipsec_ctx.rx_sa[sa_id];
+ sxe2_ipsec_rx_sa_fill(rx_sa, conf);
+
+ ret = sxe2_ipsec_rx_tcam_fill(sxe2_sctx, &tcam_id, conf);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "Failed to allocate ipsec rx tcam index.");
+ sxe2_ipsec_id_free(rx_sa_bmp, sa_id);
+ goto l_end;
+ }
+ rx_sa->tcam_id = tcam_id;
+ rx_tcam = &sxe2_sctx->ipsec_ctx.rx_tcam[tcam_id];
+
+ ret = sxe2_ipsec_rx_udp_group_fill(sxe2_sctx, &udp_group_id, conf);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "Failed to allocate ipsec rx udp group index.");
+ sxe2_ipsec_id_free(rx_sa_bmp, sa_id);
+ sxe2_ipsec_id_free(rx_tcam_bmp, tcam_id);
+ goto l_end;
+ }
+
+ if (udp_group_id != 0XFFFF) {
+ rx_sa->udp_group_id = (uint8_t)udp_group_id;
+ rx_udp_group = &sxe2_sctx->ipsec_ctx.rx_udp_group[udp_group_id];
+ } else {
+ rx_sa->udp_group_id = 0XFF;
+ }
+
+ ret = sxe2_drv_ipsec_rxsa_add(sxe2_sctx->adapter, rx_sa, rx_tcam, rx_udp_group);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "Failed to add rx sa.");
+ sxe2_ipsec_id_free(rx_sa_bmp, sa_id);
+ rx_tcam->ref_cnt--;
+ if (rx_tcam->ref_cnt == 0)
+ sxe2_ipsec_id_free(rx_tcam_bmp, tcam_id);
+
+ if (rx_udp_group != NULL) {
+ rx_udp_group->ref_cnt--;
+ if (rx_udp_group->ref_cnt == 0)
+ sxe2_ipsec_id_free(sxe2_sctx->ipsec_ctx.bmp.rx_udp_bmp,
+ udp_group_id);
+ }
+
+ ret = -EIO;
+ goto l_end;
+ }
+
+ sxe2_ipsec_session_save(sxe2_sctx, conf, sxe2_sess, rx_sa->hw_sa_id, rx_sa->id);
+
+ PMD_LOG_INFO(DRV, "Add rx sa success, rx sa id: %u, rx ip id: %u, group id: %u, index: %u.",
+ rx_sa->hw_sa_id, rx_sa->hw_ip_id, rx_sa->udp_group_id, rx_sa->id);
+
+l_end:
+ rte_spinlock_unlock(&sxe2_sctx->security_lock);
+ return ret;
+}
+
+static int32_t
+sxe2_ipsec_hw_table_add(struct sxe2_security_ctx *sxe2_sctx,
+ struct rte_security_session_conf *conf,
+ struct sxe2_security_session *sxe2_sess)
+{
+ int32_t ret = -1;
+
+ switch (conf->ipsec.direction) {
+ case RTE_SECURITY_IPSEC_SA_DIR_EGRESS:
+ ret = sxe2_ipsec_tx_sa_add(sxe2_sctx, conf, sxe2_sess);
+ break;
+ case RTE_SECURITY_IPSEC_SA_DIR_INGRESS:
+ ret = sxe2_ipsec_rx_sa_add(sxe2_sctx, conf, sxe2_sess);
+ break;
+ default:
+ PMD_LOG_ERR(DRV, "Invalid sa direction.");
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+int sxe2_ipsec_session_create(void *device,
+ struct rte_security_session_conf *conf,
+ struct sxe2_security_session *sxe2_sess)
+{
+ struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(eth_dev);
+ struct sxe2_security_ctx *sxe2_sctx = &adapter->security_ctx;
+ int32_t ret = -1;
+
+ ret = sxe2_ipsec_session_conf_valid(sxe2_sctx, conf);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "Input ipsec session conf invalid.");
+ goto l_end;
+ }
+
+ ret = sxe2_ipsec_hw_table_add(sxe2_sctx, conf, sxe2_sess);
+ if (ret)
+ goto l_end;
+
+l_end:
+ return ret;
+}
+
+static int32_t
+sxe2_ipsec_tx_sa_delete(struct sxe2_security_ctx *sxe2_sctx,
+ struct sxe2_security_session *sxe2_sess)
+{
+ struct sxe2_ipsec_tx_sa *tx_sa = NULL;
+ uint16_t sa_id = sxe2_sess->sa.hw_idx;
+ uint16_t sw_sa_id = sxe2_sess->sa.sw_idx;
+ int32_t ret = -1;
+
+ if (sw_sa_id >= sxe2_sctx->ipsec_ctx.max_tx_sa) {
+ ret = 0;
+ PMD_LOG_WARN(DRV, "invalid sw sa id: %u.", sw_sa_id);
+ goto l_end;
+ }
+
+ if (!rte_bitmap_get(sxe2_sctx->ipsec_ctx.bmp.tx_sa_bmp, sw_sa_id)) {
+ ret = 0;
+ PMD_LOG_WARN(DRV, "bitmap not set, index: %u.", sw_sa_id);
+ goto l_end;
+ }
+
+ tx_sa = &sxe2_sctx->ipsec_ctx.tx_sa[sw_sa_id];
+
+ if (tx_sa->hw_sa_id != sa_id) {
+ ret = 0;
+ PMD_LOG_WARN(DRV, "invalid hw sa id: %u != %u.", sa_id, tx_sa->hw_sa_id);
+ goto l_end;
+ }
+
+ ret = sxe2_drv_ipsec_txsa_delete(sxe2_sctx->adapter, sa_id);
+ if (ret)
+ goto l_end;
+
+ rte_spinlock_lock(&sxe2_sctx->security_lock);
+ sxe2_ipsec_id_free(sxe2_sctx->ipsec_ctx.bmp.tx_sa_bmp, sw_sa_id);
+ rte_spinlock_unlock(&sxe2_sctx->security_lock);
+
+l_end:
+ return ret;
+}
+
+static int32_t
+sxe2_ipsec_rx_sa_delete(struct sxe2_security_ctx *sxe2_sctx,
+ struct sxe2_security_session *sxe2_sess)
+{
+ struct sxe2_ipsec_rx_udp_group *rx_udp = NULL;
+ struct sxe2_ipsec_rx_tcam *rx_tcam = NULL;
+ struct sxe2_ipsec_rx_sa *rx_sa = NULL;
+ uint16_t sa_id = sxe2_sess->sa.hw_idx;
+ uint16_t sw_sa_id = sxe2_sess->sa.sw_idx;
+ int32_t ret = -1;
+
+ if (sw_sa_id >= sxe2_sctx->ipsec_ctx.max_rx_sa) {
+ ret = 0;
+ PMD_LOG_WARN(DRV, "invalid sw sa id: %u.", sw_sa_id);
+ goto l_end;
+ }
+
+ if (!rte_bitmap_get(sxe2_sctx->ipsec_ctx.bmp.rx_sa_bmp, sw_sa_id)) {
+ ret = 0;
+ PMD_LOG_INFO(DRV, "bitmap not set, id: %u.", sw_sa_id);
+ goto l_end;
+ }
+
+ rx_sa = &sxe2_sctx->ipsec_ctx.rx_sa[sw_sa_id];
+
+ if (rx_sa->hw_sa_id != sa_id) {
+ ret = 0;
+ PMD_LOG_WARN(DRV, "invalid hw sa id: %u != %u.", sa_id, rx_sa->hw_sa_id);
+ goto l_end;
+ }
+
+ ret = sxe2_drv_ipsec_rxsa_delete(sxe2_sctx->adapter, rx_sa);
+ if (ret)
+ goto l_end;
+
+ rte_spinlock_lock(&sxe2_sctx->security_lock);
+ sxe2_ipsec_id_free(sxe2_sctx->ipsec_ctx.bmp.rx_sa_bmp, sw_sa_id);
+
+ rx_tcam = &sxe2_sctx->ipsec_ctx.rx_tcam[rx_sa->tcam_id];
+ rx_tcam->ref_cnt--;
+ if (rx_tcam->ref_cnt == 0)
+ sxe2_ipsec_id_free(sxe2_sctx->ipsec_ctx.bmp.rx_tcam_bmp, rx_sa->tcam_id);
+
+ if (rx_sa->udp_group_id == 0xFF) {
+ PMD_LOG_INFO(DRV, "Not need to release udp group resource.");
+ rte_spinlock_unlock(&sxe2_sctx->security_lock);
+ goto l_end;
+ }
+ rx_udp = &sxe2_sctx->ipsec_ctx.rx_udp_group[rx_sa->udp_group_id];
+ rx_udp->ref_cnt--;
+ if (rx_udp->ref_cnt == 0)
+ sxe2_ipsec_id_free(sxe2_sctx->ipsec_ctx.bmp.rx_udp_bmp, rx_sa->udp_group_id);
+ rte_spinlock_unlock(&sxe2_sctx->security_lock);
+
+l_end:
+ return ret;
+}
+
+static int32_t
+sxe2_ipsec_hw_table_delete(struct sxe2_security_ctx *sxe2_sctx,
+ struct sxe2_security_session *sxe2_sess)
+{
+ int32_t ret = -1;
+
+ switch (sxe2_sess->direction) {
+ case RTE_SECURITY_IPSEC_SA_DIR_EGRESS:
+ ret = sxe2_ipsec_tx_sa_delete(sxe2_sctx, sxe2_sess);
+ break;
+ case RTE_SECURITY_IPSEC_SA_DIR_INGRESS:
+ ret = sxe2_ipsec_rx_sa_delete(sxe2_sctx, sxe2_sess);
+ break;
+ default:
+ PMD_LOG_ERR(DRV, "Invalid sa direction.");
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+int sxe2_ipsec_session_destroy(void *device, struct rte_security_session *session)
+{
+ struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(eth_dev);
+ struct sxe2_security_ctx *sxe2_sctx = &adapter->security_ctx;
+ struct sxe2_security_session *sxe2_sess = NULL;
+ sxe2_sess = SECURITY_GET_SESS_PRIV(session);
+ int32_t ret = -1;
+
+ if (unlikely(sxe2_sess == NULL || sxe2_sess->adapter != adapter)) {
+ PMD_LOG_ERR(DRV, "Invalid device adapter.");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ ret = sxe2_ipsec_hw_table_delete(sxe2_sctx, sxe2_sess);
+ if (ret) {
+ ret = -EIO;
+ PMD_LOG_ERR(DRV, "Failed to delete ipsec hw tables.");
+ goto l_end;
+ }
+
+ memset(sxe2_sess, 0, sizeof(struct sxe2_security_session));
+
+ PMD_LOG_INFO(DRV, "Delete ipsec session success, sa_id: %u, spi: %u.",
+ sxe2_sess->sa.hw_idx, sxe2_sess->sa.spi);
+
+l_end:
+ return ret;
+}
+
+int sxe2_ipsec_pkt_metadata_set(void *device, struct rte_security_session *session,
+ struct rte_mbuf *m, void *params)
+{
+ struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(eth_dev);
+ struct sxe2_security_ctx *sxe2_sctx = &adapter->security_ctx;
+ struct sxe2_security_session *sxe2_sess = NULL;
+ struct sxe2_ipsec_pkt_metadata *md = NULL;
+ uint16_t offset = 0;
+ int32_t ret = -1;
+
+ sxe2_sess = SECURITY_GET_SESS_PRIV(session);
+ if (unlikely(sxe2_sess == NULL || sxe2_sess->adapter != adapter)) {
+ PMD_LOG_ERR(DRV, "Invalid parameters.");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ offset = ((struct sxe2_ipsec_metadata_params *)params)->esp_header_offset;
+ if (offset <= IPSEC_ESP_OFFSET_MIN || offset >= IPSEC_ESP_OFFSET_MAX) {
+ PMD_LOG_ERR(DRV, "Invalid esp header offset.");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ md = RTE_MBUF_DYNFIELD(m, sxe2_sctx->ipsec_ctx.md_offset, struct sxe2_ipsec_pkt_metadata *);
+
+ memcpy(md, &sxe2_sess->pkt_metadata_template, sizeof(struct sxe2_ipsec_pkt_metadata));
+ md->esp_head_offset = offset;
+
+ PMD_LOG_INFO(DRV, "ipsec metadata set, offset:%u, said:%u, mode:%u, algo:%u.", offset,
+ sxe2_sess->pkt_metadata_template.sa_idx, sxe2_sess->pkt_metadata_template.mode,
+ sxe2_sess->pkt_metadata_template.algo);
+
+ ret = 0;
+
+l_end:
+ return ret;
+}
+
+int sxe2_ipsec_pkt_md_offset_get(struct sxe2_adapter *adapter)
+{
+ return adapter->security_ctx.ipsec_ctx.md_offset;
+}
+
+static void sxe2_ipsec_enc_aes_cbc_fill(struct rte_cryptodev_capabilities *cap)
+{
+ cap->sym.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+
+ cap->sym.cipher.algo = SXE2_RTE_CRYPTO_CIPHER_AES_CBC;
+
+ cap->sym.cipher.block_size = SXE2_SECURITY_BLOCK_SIZE_16;
+
+ cap->sym.cipher.key_size.min = SXE2_IPSEC_AES_KEY_MIN;
+ cap->sym.cipher.key_size.max = SXE2_IPSEC_AES_KEY_MAX;
+ cap->sym.cipher.key_size.increment = SXE2_IPSEC_AES_KEY_INC;
+
+ cap->sym.cipher.iv_size.min = SXE2_IPSEC_AES_IV_MIN;
+ cap->sym.cipher.iv_size.max = SXE2_IPSEC_AES_IV_MAX;
+ cap->sym.cipher.iv_size.increment = SXE2_IPSEC_AES_IV_INC;
+
+ cap->sym.cipher.dataunit_set |= RTE_CRYPTO_CIPHER_DATA_UNIT_LEN_512_BYTES;
+}
+
+static void sxe2_ipsec_enc_sm4_cbc_fill(struct rte_cryptodev_capabilities *cap)
+{
+ cap->sym.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+
+ cap->sym.cipher.algo = SXE2_RTE_RTE_CRYPTO_CIPHER_SM4_CBC;
+
+ cap->sym.cipher.block_size = SXE2_SECURITY_BLOCK_SIZE_16;
+
+ cap->sym.cipher.key_size.min = SXE2_IPSEC_SM4_KEY_MIN;
+ cap->sym.cipher.key_size.max = SXE2_IPSEC_SM4_KEY_MAX;
+ cap->sym.cipher.key_size.increment = SXE2_IPSEC_SM4_KEY_INC;
+
+ cap->sym.cipher.iv_size.min = SXE2_IPSEC_SM4_IV_MIN;
+ cap->sym.cipher.iv_size.max = SXE2_IPSEC_SM4_IV_MAX;
+ cap->sym.cipher.iv_size.increment = SXE2_IPSEC_SM4_IV_INC;
+
+ cap->sym.cipher.dataunit_set |= RTE_CRYPTO_CIPHER_DATA_UNIT_LEN_512_BYTES;
+}
+
+static void sxe2_ipsec_auth_sha_hmac_fill(struct rte_cryptodev_capabilities *cap)
+{
+ cap->sym.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH;
+
+ cap->sym.auth.algo = SXE2_RTE_CRYPTO_AUTH_SHA256_HMAC;
+
+ cap->sym.auth.block_size = SXE2_SECURITY_BLOCK_SIZE_64;
+
+ cap->sym.auth.key_size.min = SXE2_IPSEC_SHA_KEY_MIN;
+ cap->sym.auth.key_size.max = SXE2_IPSEC_SHA_KEY_MAX;
+ cap->sym.auth.key_size.increment = SXE2_IPSEC_SHA_KEY_INC;
+
+ cap->sym.auth.iv_size.min = SXE2_IPSEC_SHA_IV_MIN;
+ cap->sym.auth.iv_size.max = SXE2_IPSEC_SHA_IV_MAX;
+ cap->sym.auth.iv_size.increment = SXE2_IPSEC_SHA_IV_INC;
+
+ cap->sym.auth.digest_size.min = SXE2_IPSEC_SHA_DIGEST_MIN;
+ cap->sym.auth.digest_size.max = SXE2_IPSEC_SHA_DIGEST_MAX;
+ cap->sym.auth.digest_size.increment = SXE2_IPSEC_SHA_DIGEST_INC;
+
+ cap->sym.auth.aad_size.min = SXE2_IPSEC_AAD_MIN;
+ cap->sym.auth.aad_size.max = SXE2_IPSEC_AAD_MAX;
+ cap->sym.auth.aad_size.increment = SXE2_IPSEC_AAD_INC;
+}
+
+static void sxe2_ipsec_auth_sm3_hmac_fill(struct rte_cryptodev_capabilities *cap)
+{
+ cap->sym.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH;
+
+ cap->sym.auth.algo = SXE2_RTE_CRYPTO_AUTH_SM3_HMAC;
+
+ cap->sym.auth.block_size = SXE2_SECURITY_BLOCK_SIZE_64;
+
+ cap->sym.auth.key_size.min = SXE2_IPSEC_SM3_KEY_MIN;
+ cap->sym.auth.key_size.max = SXE2_IPSEC_SM3_KEY_MAX;
+ cap->sym.auth.key_size.increment = SXE2_IPSEC_SM3_KEY_INC;
+
+ cap->sym.auth.iv_size.min = SXE2_IPSEC_SM3_IV_MIN;
+ cap->sym.auth.iv_size.max = SXE2_IPSEC_SM3_IV_MAX;
+ cap->sym.auth.iv_size.increment = SXE2_IPSEC_SM3_IV_INC;
+
+ cap->sym.auth.digest_size.min = SXE2_IPSEC_SM3_DIGEST_MIN;
+ cap->sym.auth.digest_size.max = SXE2_IPSEC_SM3_DIGEST_MAX;
+ cap->sym.auth.digest_size.increment = SXE2_IPSEC_SM3_DIGEST_INC;
+
+ cap->sym.auth.aad_size.min = SXE2_IPSEC_AAD_MIN;
+ cap->sym.auth.aad_size.max = SXE2_IPSEC_AAD_MAX;
+ cap->sym.auth.aad_size.increment = SXE2_IPSEC_AAD_INC;
+}
+
+static int32_t
+sxe2_ipsec_capabilities_init(struct sxe2_security_ctx *sxe2_sctx)
+{
+ struct rte_cryptodev_capabilities *capabilities = NULL;
+ struct sxe2_security_capabilities *sxe2_cap =
+ &sxe2_sctx->sxe2_capabilities[SXE2_SECURITY_PROTOCOL_IPSEC];
+ int32_t ret = -1;
+ uint8_t index = 0;
+
+ sxe2_cap->action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO;
+ sxe2_cap->ipsec.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP;
+ sxe2_cap->ipsec.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+ sxe2_cap->ipsec.options.stats = 1;
+
+ capabilities = rte_zmalloc("security_caps",
+ sizeof(struct rte_cryptodev_capabilities) * SXE2_IPSEC_CAP_MAX, 0);
+ if (capabilities == NULL) {
+ ret = -ENOMEM;
+ goto l_end;
+ }
+
+ for (index = 0; index < SXE2_IPSEC_CAP_MAX; index++) {
+ capabilities[index].op = RTE_CRYPTO_OP_TYPE_SYMMETRIC;
+ switch (index) {
+ case SXE2_IPSEC_CAP_ENC_AES_CBC:
+ sxe2_ipsec_enc_aes_cbc_fill(&capabilities[index]);
+ break;
+ case SXE2_IPSEC_CAP_ENC_SM4_CBC:
+ sxe2_ipsec_enc_sm4_cbc_fill(&capabilities[index]);
+ break;
+ case SXE2_IPSEC_CAP_AUTH_SHA256_HMAC:
+ sxe2_ipsec_auth_sha_hmac_fill(&capabilities[index]);
+ break;
+ case SXE2_IPSEC_CAP_AUTH_SM3_HMAC:
+ sxe2_ipsec_auth_sm3_hmac_fill(&capabilities[index]);
+ break;
+ default:
+ break;
+ }
+ }
+
+ sxe2_cap->crypto_capabilities = capabilities;
+ ret = 0;
+
+l_end:
+ return ret;
+}
+
+static void
+sxe2_ipsec_tx_sa_init(struct sxe2_ipsec_tx_sa *tx_sa, uint16_t len)
+{
+ struct sxe2_ipsec_tx_sa *per = NULL;
+ uint16_t i;
+
+ memset(tx_sa, 0, sizeof(struct sxe2_ipsec_tx_sa) * len);
+ for (i = 0; i < len; i++) {
+ per = &tx_sa[i];
+ per->id = i;
+ }
+}
+
+static void
+sxe2_ipsec_rx_sa_init(struct sxe2_ipsec_rx_sa *rx_sa, uint16_t len)
+{
+ struct sxe2_ipsec_rx_sa *per = NULL;
+ uint16_t i;
+
+ memset(rx_sa, 0, sizeof(struct sxe2_ipsec_rx_sa) * len);
+ for (i = 0; i < len; i++) {
+ per = &rx_sa[i];
+ per->id = i;
+ }
+}
+
+static void
+sxe2_ipsec_rx_tcam_init(struct sxe2_ipsec_rx_tcam *rx_tcam, uint16_t len)
+{
+ struct sxe2_ipsec_rx_tcam *per = NULL;
+ uint16_t i;
+
+ memset(rx_tcam, 0, sizeof(struct sxe2_ipsec_rx_tcam) * len);
+ for (i = 0; i < len; i++) {
+ per = &rx_tcam[i];
+ per->id = i;
+ }
+}
+
+static void
+sxe2_ipsec_rx_udp_group_init(struct sxe2_ipsec_rx_udp_group *rx_udp_group, uint16_t len)
+{
+ struct sxe2_ipsec_rx_udp_group *per = NULL;
+ uint16_t i;
+
+ memset(rx_udp_group, 0, sizeof(struct sxe2_ipsec_rx_udp_group) * len);
+ for (i = 0; i < len; i++) {
+ per = &rx_udp_group[i];
+ per->id = i;
+ }
+}
+
+static int32_t
+sxe2_ipsec_hw_table_init(struct sxe2_security_ctx *sxe2_sctx)
+{
+ struct sxe2_ipsec_tx_sa *tx_sa = NULL;
+ struct sxe2_ipsec_rx_sa *rx_sa = NULL;
+ struct sxe2_ipsec_rx_tcam *rx_tcam = NULL;
+ struct sxe2_ipsec_rx_udp_group *rx_udp_group = NULL;
+ uint16_t max_tx_sa = sxe2_sctx->ipsec_ctx.max_tx_sa;
+ uint16_t max_rx_sa = sxe2_sctx->ipsec_ctx.max_rx_sa;
+ uint16_t max_tcam = sxe2_sctx->ipsec_ctx.max_tcam;
+ uint16_t max_udp_group = sxe2_sctx->ipsec_ctx.max_udp_group;
+ int32_t ret = -1;
+
+ tx_sa = rte_zmalloc("sxe2_ipsec_tx_sa", sizeof(struct sxe2_ipsec_tx_sa) * max_tx_sa, 0);
+ if (tx_sa == NULL) {
+ ret = -ENOMEM;
+ goto l_end;
+ }
+ sxe2_ipsec_tx_sa_init(tx_sa, max_tx_sa);
+ sxe2_sctx->ipsec_ctx.tx_sa = tx_sa;
+
+ rx_sa = rte_zmalloc("sxe2_ipsec_rx_sa", sizeof(struct sxe2_ipsec_rx_sa) * max_rx_sa, 0);
+ if (rx_sa == NULL) {
+ ret = -ENOMEM;
+ goto l_end;
+ }
+ sxe2_ipsec_rx_sa_init(rx_sa, max_rx_sa);
+ sxe2_sctx->ipsec_ctx.rx_sa = rx_sa;
+
+ rx_tcam = rte_zmalloc("sxe2_ipsec_rx_tcam",
+ sizeof(struct sxe2_ipsec_rx_tcam) * max_tcam, 0);
+ if (rx_tcam == NULL) {
+ ret = -ENOMEM;
+ goto l_end;
+ }
+ sxe2_ipsec_rx_tcam_init(rx_tcam, max_tcam);
+ sxe2_sctx->ipsec_ctx.rx_tcam = rx_tcam;
+
+ rx_udp_group = rte_zmalloc("sxe2_ipsec_rx_udp_group",
+ sizeof(struct sxe2_ipsec_rx_udp_group) * max_udp_group, 0);
+ if (rx_udp_group == NULL) {
+ ret = -ENOMEM;
+ goto l_end;
+ }
+ sxe2_ipsec_rx_udp_group_init(rx_udp_group, max_udp_group);
+ sxe2_sctx->ipsec_ctx.rx_udp_group = rx_udp_group;
+
+ ret = 0;
+
+l_end:
+ if (ret) {
+ if (tx_sa != NULL) {
+ rte_free(tx_sa);
+ sxe2_sctx->ipsec_ctx.tx_sa = NULL;
+ }
+ if (rx_sa != NULL) {
+ rte_free(rx_sa);
+ sxe2_sctx->ipsec_ctx.rx_sa = NULL;
+ }
+ if (rx_tcam != NULL) {
+ rte_free(rx_tcam);
+ sxe2_sctx->ipsec_ctx.rx_tcam = NULL;
+ }
+ if (rx_udp_group != NULL) {
+ rte_free(rx_udp_group);
+ sxe2_sctx->ipsec_ctx.rx_udp_group = NULL;
+ }
+ }
+ return ret;
+}
+
+int32_t sxe2_ipsec_init(struct sxe2_adapter *adapter)
+{
+ struct sxe2_security_ctx *sxe2_sctx = &adapter->security_ctx;
+ struct sxe2_security_capabilities *sxe2_cap = NULL;
+ int32_t ret = -1;
+ struct rte_mbuf_dynfield pkt_md_dynfield = {
+ .name = "sxe2_ipsec_pkt_metadata",
+ .size = sizeof(struct sxe2_ipsec_pkt_metadata),
+ .align = alignof(struct sxe2_ipsec_pkt_metadata)
+ };
+
+ PMD_LOG_INFO(INIT, "Init ipsec.");
+
+ sxe2_sctx->ipsec_ctx.md_offset = rte_mbuf_dynfield_register(&pkt_md_dynfield);
+ if (sxe2_sctx->ipsec_ctx.md_offset < 0) {
+ PMD_LOG_ERR(INIT, "Failed to register ipsec mbuf dynamic field.");
+ ret = -EIO;
+ goto l_end;
+ }
+
+ ret = sxe2_ipsec_capabilities_init(sxe2_sctx);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to init ipsec capabilities.");
+ goto l_end;
+ }
+
+ ret = sxe2_drv_ipsec_get_capa(adapter);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to get ipsec capabilities.");
+ goto l_caps_free;
+ }
+
+ ret = sxe2_ipsec_bitmap_init(sxe2_sctx);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to init ipsec bitmap.");
+ goto l_caps_free;
+ }
+
+ ret = sxe2_ipsec_hw_table_init(sxe2_sctx);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to init ipsec hw table.");
+ goto l_bitmap_free;
+ }
+
+ goto l_end;
+
+l_bitmap_free:
+
+ if (sxe2_sctx->ipsec_ctx.bmp.tx_sa_mem != NULL) {
+ rte_free(sxe2_sctx->ipsec_ctx.bmp.tx_sa_mem);
+ sxe2_sctx->ipsec_ctx.bmp.tx_sa_mem = NULL;
+ }
+ if (sxe2_sctx->ipsec_ctx.bmp.rx_sa_mem != NULL) {
+ rte_free(sxe2_sctx->ipsec_ctx.bmp.rx_sa_mem);
+ sxe2_sctx->ipsec_ctx.bmp.rx_sa_mem = NULL;
+ }
+ if (sxe2_sctx->ipsec_ctx.bmp.rx_tcam_mem != NULL) {
+ rte_free(sxe2_sctx->ipsec_ctx.bmp.rx_tcam_mem);
+ sxe2_sctx->ipsec_ctx.bmp.rx_tcam_mem = NULL;
+ }
+ if (sxe2_sctx->ipsec_ctx.bmp.rx_udp_mem != NULL) {
+ rte_free(sxe2_sctx->ipsec_ctx.bmp.rx_udp_mem);
+ sxe2_sctx->ipsec_ctx.bmp.rx_udp_mem = NULL;
+ }
+l_caps_free:
+ sxe2_cap = &sxe2_sctx->sxe2_capabilities[SXE2_SECURITY_PROTOCOL_IPSEC];
+ if (sxe2_cap->crypto_capabilities != NULL) {
+ rte_free(sxe2_cap->crypto_capabilities);
+ sxe2_cap->crypto_capabilities = NULL;
+ }
+l_end:
+ return ret;
+}
+
+void sxe2_ipsec_uinit(struct sxe2_adapter *adapter)
+{
+ struct sxe2_security_ctx *sxe2_sctx = &adapter->security_ctx;
+ struct sxe2_security_capabilities *sxe2_cap =
+ &sxe2_sctx->sxe2_capabilities[SXE2_SECURITY_PROTOCOL_IPSEC];
+ struct sxe2_ipsec_tx_sa *tx_sa = sxe2_sctx->ipsec_ctx.tx_sa;
+ struct sxe2_ipsec_rx_sa *rx_sa = sxe2_sctx->ipsec_ctx.rx_sa;
+ struct sxe2_ipsec_rx_tcam *rx_tcam = sxe2_sctx->ipsec_ctx.rx_tcam;
+ struct sxe2_ipsec_rx_udp_group *rx_udp_group = sxe2_sctx->ipsec_ctx.rx_udp_group;
+
+ PMD_LOG_INFO(INIT, "Uinit ipsec.");
+
+ (void)sxe2_drv_ipsec_resource_clear(adapter);
+
+ if (sxe2_sctx->ipsec_ctx.bmp.tx_sa_mem != NULL) {
+ rte_free(sxe2_sctx->ipsec_ctx.bmp.tx_sa_mem);
+ sxe2_sctx->ipsec_ctx.bmp.tx_sa_mem = NULL;
+ }
+ if (sxe2_sctx->ipsec_ctx.bmp.rx_sa_mem != NULL) {
+ rte_free(sxe2_sctx->ipsec_ctx.bmp.rx_sa_mem);
+ sxe2_sctx->ipsec_ctx.bmp.rx_sa_mem = NULL;
+ }
+ if (sxe2_sctx->ipsec_ctx.bmp.rx_tcam_mem != NULL) {
+ rte_free(sxe2_sctx->ipsec_ctx.bmp.rx_tcam_mem);
+ sxe2_sctx->ipsec_ctx.bmp.rx_tcam_mem = NULL;
+ }
+ if (sxe2_sctx->ipsec_ctx.bmp.rx_udp_mem != NULL) {
+ rte_free(sxe2_sctx->ipsec_ctx.bmp.rx_udp_mem);
+ sxe2_sctx->ipsec_ctx.bmp.rx_udp_mem = NULL;
+ }
+
+ if (tx_sa != NULL) {
+ rte_free(tx_sa);
+ sxe2_sctx->ipsec_ctx.tx_sa = NULL;
+ }
+ if (rx_sa != NULL) {
+ rte_free(rx_sa);
+ sxe2_sctx->ipsec_ctx.rx_sa = NULL;
+ }
+ if (rx_tcam != NULL) {
+ rte_free(rx_tcam);
+ sxe2_sctx->ipsec_ctx.rx_tcam = NULL;
+ }
+ if (rx_udp_group != NULL) {
+ rte_free(rx_udp_group);
+ sxe2_sctx->ipsec_ctx.rx_udp_group = NULL;
+ }
+
+ if (sxe2_cap->crypto_capabilities != NULL) {
+ rte_free(sxe2_cap->crypto_capabilities);
+ sxe2_cap->crypto_capabilities = NULL;
+ }
+}
diff --git a/drivers/net/sxe2/sxe2_ipsec.h b/drivers/net/sxe2/sxe2_ipsec.h
new file mode 100644
index 0000000000..02930ddb4f
--- /dev/null
+++ b/drivers/net/sxe2/sxe2_ipsec.h
@@ -0,0 +1,254 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+#ifndef __SXE2_IPSEC_H__
+#define __SXE2_IPSEC_H__
+
+#include <rte_security.h>
+#include <rte_security_driver.h>
+
+struct sxe2_adapter;
+struct sxe2_security_session;
+
+#define SXE2_IPSEC_AES_KEY_MIN (32)
+#define SXE2_IPSEC_AES_KEY_MAX (32)
+#define SXE2_IPSEC_AES_KEY_INC (0)
+
+#define SXE2_IPSEC_SM4_KEY_MIN (16)
+#define SXE2_IPSEC_SM4_KEY_MAX (16)
+#define SXE2_IPSEC_SM4_KEY_INC (0)
+
+#define SXE2_IPSEC_SHA_KEY_MIN (32)
+#define SXE2_IPSEC_SHA_KEY_MAX (32)
+#define SXE2_IPSEC_SHA_KEY_INC (0)
+
+#define SXE2_IPSEC_SM3_KEY_MIN (32)
+#define SXE2_IPSEC_SM3_KEY_MAX (32)
+#define SXE2_IPSEC_SM3_KEY_INC (0)
+
+#define SXE2_IPSEC_AES_IV_MIN (16)
+#define SXE2_IPSEC_AES_IV_MAX (16)
+#define SXE2_IPSEC_AES_IV_INC (0)
+
+#define SXE2_IPSEC_SM4_IV_MIN (16)
+#define SXE2_IPSEC_SM4_IV_MAX (16)
+#define SXE2_IPSEC_SM4_IV_INC (0)
+
+#define SXE2_IPSEC_SHA_IV_MIN (0)
+#define SXE2_IPSEC_SHA_IV_MAX (32)
+#define SXE2_IPSEC_SHA_IV_INC (16)
+
+#define SXE2_IPSEC_SM3_IV_MIN (0)
+#define SXE2_IPSEC_SM3_IV_MAX (32)
+#define SXE2_IPSEC_SM3_IV_INC (16)
+
+#define SXE2_IPSEC_SHA_DIGEST_MIN (32)
+#define SXE2_IPSEC_SHA_DIGEST_MAX (32)
+#define SXE2_IPSEC_SHA_DIGEST_INC (0)
+
+#define SXE2_IPSEC_SM3_DIGEST_MIN (32)
+#define SXE2_IPSEC_SM3_DIGEST_MAX (32)
+#define SXE2_IPSEC_SM3_DIGEST_INC (0)
+
+#define SXE2_IPSEC_AAD_MIN (0)
+#define SXE2_IPSEC_AAD_MAX (0)
+#define SXE2_IPSEC_AAD_INC (0)
+
+#define SXE2_IPSEC_MAX_KEY_LEN (32)
+#define SXE2_IPSEC_MIN_KEY_LEN (0)
+
+#define SXE2_IPSEC_OL_FLAGS_IS_TUN (0x1 << 0)
+#define SXE2_IPSEC_OL_FLAGS_IS_ESP (0x1 << 1)
+
+#define SXE2_IPSEC_DEFAULT_SA_OFFSET (0)
+#define SXE2_IPSEC_DEFAULT_SA_LEN (1024)
+
+#define IPSEC_TX_ENCRYPT (RTE_BIT32(0))
+#define IPSEC_TX_ENGINE_SM4 (RTE_BIT32(1))
+
+#define IPSEC_RX_VALID (RTE_BIT32(0))
+#define IPSEC_RX_IPV6 (RTE_BIT32(2))
+#define IPSEC_RX_DECRYPT (RTE_BIT32(3))
+#define IPSEC_RX_ENGINE_SM4 (RTE_BIT32(4))
+
+#define IPSEC_IPV6_LEN (4)
+#define IPSEC_ESP_OFFSET_MIN (16)
+#define IPSEC_ESP_OFFSET_MAX (256)
+
+enum sxe2_ipsec_cap {
+ SXE2_IPSEC_CAP_ENC_AES_CBC = 0,
+ SXE2_IPSEC_CAP_ENC_SM4_CBC = 1,
+ SXE2_IPSEC_CAP_AUTH_SHA256_HMAC = 2,
+ SXE2_IPSEC_CAP_AUTH_SM3_HMAC = 3,
+ SXE2_IPSEC_CAP_MAX = 4,
+};
+
+enum sxe2_ipsec_icv_len {
+ SXE2_IPSEC_ICV_0_BYTES = 0,
+ SXE2_IPSEC_ICV_12_BYTES,
+ SXE2_IPSEC_ICV_16_BYTES,
+ SXE2_IPSEC_ICV_INVALID,
+};
+
+enum sxe2_ipsec_bypass_dir {
+ SXE2_IPSEC_BYPASS_DIR_RX = 0,
+ SXE2_IPSEC_BYPASS_DIR_TX,
+ SXE2_IPSEC_BYPASS_DIR_INVALID,
+};
+
+enum sxe2_ipsec_bypass_status {
+ SXE2_IPSEC_BYPASS_STATUS_DISABLE = 0,
+ SXE2_IPSEC_BYPASS_STATUS_ENABLE,
+ SXE2_IPSEC_BYPASS_STATUS_INVALID,
+};
+
+enum sxe2_ipsec_status {
+ SXE2_IPSEC_ENC_BYPASS = 0,
+ SXE2_IPSEC_ENC_ENABLE,
+ SXE2_IPSEC_ENC_INVALID,
+};
+
+enum sxe2_ipsec_mode {
+ SXE2_IPSEC_MODE_ENC_AND_AUTH = 0,
+ SXE2_IPSEC_MODE_ONLY_ENCRYPT,
+ SXE2_IPSEC_MODE_INVALID,
+};
+
+struct sxe2_ipsec_ip_param {
+ enum rte_security_ipsec_tunnel_type type;
+ union {
+ uint32_t dst_ipv4;
+ uint32_t dst_ipv6[IPSEC_IPV6_LEN];
+ };
+};
+
+enum sxe2_ipsec_algorithm {
+ SXE2_IPSEC_ALGO_AES_CBC_AND_SHA256_128_HMAC = 0,
+ SXE2_IPSEC_ALGO_SM4_CBC_AND_SM3_96_HMAC,
+ SXE2_IPSEC_ALGO_INVALID,
+};
+
+struct sxe2_ipsec_pkt_metadata {
+ uint16_t sa_idx;
+ uint16_t esp_head_offset;
+ uint8_t ol_flags;
+ uint8_t mode;
+ uint8_t algo;
+};
+
+struct sxe2_ipsec_bitmap {
+ struct rte_bitmap *tx_sa_bmp;
+ struct rte_bitmap *rx_sa_bmp;
+ struct rte_bitmap *rx_tcam_bmp;
+ struct rte_bitmap *rx_udp_bmp;
+ void *tx_sa_mem;
+ void *rx_sa_mem;
+ void *rx_tcam_mem;
+ void *rx_udp_mem;
+};
+
+struct sxe2_ipsec_security_sa {
+ uint32_t spi;
+ uint16_t hw_idx;
+ uint16_t sw_idx;
+};
+
+struct sxe2_ipsec_esn {
+ union {
+ uint64_t value;
+ struct {
+ uint32_t hi;
+ uint32_t low;
+ };
+ };
+ uint8_t enabled;
+};
+
+struct sxe2_ipsec_udp {
+ struct rte_security_ipsec_udp_param value;
+ uint8_t enabled;
+};
+
+struct sxe2_ipsec_tx_sa {
+ struct rte_security_ipsec_xform xform;
+ uint16_t id;
+ uint16_t hw_sa_id;
+ enum sxe2_ipsec_mode mode;
+ enum sxe2_ipsec_algorithm algo;
+ uint8_t enc_key[SXE2_IPSEC_MAX_KEY_LEN];
+ uint8_t auth_key[SXE2_IPSEC_MAX_KEY_LEN];
+};
+
+struct sxe2_ipsec_rx_sa {
+ struct rte_security_ipsec_xform xform;
+ uint32_t spi;
+ uint16_t id;
+ uint16_t hw_sa_id;
+ uint8_t hw_ip_id;
+ uint8_t hw_udp_group_id;
+ uint8_t tcam_id;
+ uint8_t udp_group_id;
+ uint8_t sdn_group_id;
+ enum sxe2_ipsec_mode mode;
+ enum sxe2_ipsec_algorithm algo;
+ uint8_t enc_key[SXE2_IPSEC_MAX_KEY_LEN];
+ uint8_t auth_key[SXE2_IPSEC_MAX_KEY_LEN];
+};
+
+struct sxe2_ipsec_rx_tcam {
+ struct sxe2_ipsec_ip_param ip_addr;
+ uint16_t id;
+ uint8_t hw_ip_id;
+ uint8_t ref_cnt;
+};
+
+struct sxe2_ipsec_rx_udp_group {
+ uint16_t udp_port;
+ uint8_t sport_en;
+ uint8_t dport_en;
+ uint8_t id;
+ uint8_t hw_group_id;
+ uint8_t ref_cnt;
+};
+
+struct sxe2_ipsec_ctx {
+ struct sxe2_ipsec_tx_sa *tx_sa;
+ struct sxe2_ipsec_rx_sa *rx_sa;
+ struct sxe2_ipsec_rx_tcam *rx_tcam;
+ struct sxe2_ipsec_rx_udp_group *rx_udp_group;
+ struct sxe2_ipsec_bitmap bmp;
+ int md_offset;
+ uint16_t max_tx_sa;
+ uint16_t max_rx_sa;
+ uint16_t max_tcam;
+ uint8_t max_udp_group;
+};
+
+struct sxe2_ipsec_metadata_params {
+ uint16_t esp_header_offset;
+ uint16_t reserved;
+};
+
+bool sxe2_ipsec_supported(struct sxe2_adapter *adapter);
+
+bool sxe2_ipsec_valid_tx_offloads(uint64_t offloads);
+
+bool sxe2_ipsec_valid_rx_offloads(uint64_t offloads);
+
+int sxe2_ipsec_pkt_md_offset_get(struct sxe2_adapter *adapter);
+
+int sxe2_ipsec_session_create(void *device,
+ struct rte_security_session_conf *conf,
+ struct sxe2_security_session *sxe2_sess);
+
+int sxe2_ipsec_session_destroy(void *device,
+ struct rte_security_session *session);
+
+int sxe2_ipsec_pkt_metadata_set(void *device, struct rte_security_session *session,
+ struct rte_mbuf *m, void *params);
+
+int32_t sxe2_ipsec_init(struct sxe2_adapter *adapter);
+
+void sxe2_ipsec_uinit(struct sxe2_adapter *adapter);
+
+#endif /* __SXE2_IPSEC_H__ */
diff --git a/drivers/net/sxe2/sxe2_rx.c b/drivers/net/sxe2/sxe2_rx.c
index 28832d5f71..007192c7d8 100644
--- a/drivers/net/sxe2/sxe2_rx.c
+++ b/drivers/net/sxe2/sxe2_rx.c
@@ -294,6 +294,11 @@ int32_t __rte_cold sxe2_rx_queue_setup(struct rte_eth_dev *dev,
goto l_end;
}
+ if (!sxe2_ipsec_valid_rx_offloads(offloads)) {
+ ret = -EINVAL;
+ goto l_end;
+ }
+
rxq = sxe2_rx_queue_alloc(dev, queue_idx, nb_desc, socket_id);
if (rxq == NULL) {
PMD_LOG_ERR(RX, "rx queue[%d] resource alloc failed", queue_idx);
diff --git a/drivers/net/sxe2/sxe2_security.c b/drivers/net/sxe2/sxe2_security.c
new file mode 100644
index 0000000000..bc59d1b880
--- /dev/null
+++ b/drivers/net/sxe2/sxe2_security.c
@@ -0,0 +1,335 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#include <rte_malloc.h>
+
+#include "sxe2_ethdev.h"
+#include "sxe2_security.h"
+#include "sxe2_ipsec.h"
+#include "sxe2_common_log.h"
+
+static unsigned int
+sxe2_security_session_size_get(void *device __rte_unused)
+{
+ return sizeof(struct sxe2_security_session);
+}
+
+static int
+sxe2_security_session_create(void *device,
+ struct rte_security_session_conf *conf,
+ struct rte_security_session *session)
+{
+ int32_t ret = -1;
+ struct sxe2_security_session *sxe2_sess = NULL;
+ sxe2_sess = SECURITY_GET_SESS_PRIV(session);
+
+ switch (conf->protocol) {
+ case RTE_SECURITY_PROTOCOL_IPSEC:
+ ret = sxe2_ipsec_session_create(device, conf, sxe2_sess);
+ break;
+ default:
+ PMD_LOG_ERR(DRV, "Invalid security protocol.");
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int
+sxe2_security_session_destroy(void *device, struct rte_security_session *session)
+{
+ int32_t ret = -1;
+ struct sxe2_security_session *sxe2_sess = NULL;
+ sxe2_sess = SECURITY_GET_SESS_PRIV(session);
+
+ switch (sxe2_sess->protocol) {
+ case RTE_SECURITY_PROTOCOL_IPSEC:
+ ret = sxe2_ipsec_session_destroy(device, session);
+ break;
+ default:
+ PMD_LOG_ERR(DRV, "Invalid security protocol.");
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int
+sxe2_security_pkt_metadata_set(void *device,
+ struct rte_security_session *session,
+ struct rte_mbuf *m, void *params)
+{
+ struct sxe2_security_session *sxe2_sess = NULL;
+ sxe2_sess = SECURITY_GET_SESS_PRIV(session);
+ int32_t ret = -1;
+
+ switch (sxe2_sess->protocol) {
+ case RTE_SECURITY_PROTOCOL_IPSEC:
+ ret = sxe2_ipsec_pkt_metadata_set(device, session, m, params);
+ break;
+ default:
+ PMD_LOG_ERR(DRV, "Invalid security protocol.");
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static const struct rte_security_capability *
+sxe2_security_capabilities_get(void *device __rte_unused)
+{
+ static const struct rte_cryptodev_capabilities
+ ipsec_crypto_capabilities[] = {
+ {
+ .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ {.sym = {
+ .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+ {.cipher = {
+ .algo = SXE2_RTE_CRYPTO_CIPHER_AES_CBC,
+ .block_size = SXE2_SECURITY_BLOCK_SIZE_16,
+ .key_size = {
+ .min = SXE2_IPSEC_AES_KEY_MIN,
+ .max = SXE2_IPSEC_AES_KEY_MAX,
+ .increment = SXE2_IPSEC_AES_KEY_INC
+ },
+ .iv_size = {
+ .min = SXE2_IPSEC_AES_IV_MIN,
+ .max = SXE2_IPSEC_AES_IV_MAX,
+ .increment = SXE2_IPSEC_AES_IV_INC
+ },
+ .dataunit_set = RTE_CRYPTO_CIPHER_DATA_UNIT_LEN_512_BYTES,
+ }, }
+ }, }
+ },
+ {
+ .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ {.sym = {
+ .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+ {.cipher = {
+ .algo = SXE2_RTE_RTE_CRYPTO_CIPHER_SM4_CBC,
+ .block_size = SXE2_SECURITY_BLOCK_SIZE_16,
+ .key_size = {
+ .min = SXE2_IPSEC_SM4_KEY_MIN,
+ .max = SXE2_IPSEC_SM4_KEY_MAX,
+ .increment = SXE2_IPSEC_SM4_KEY_INC
+ },
+ .iv_size = {
+ .min = SXE2_IPSEC_SM4_IV_MIN,
+ .max = SXE2_IPSEC_SM4_IV_MAX,
+ .increment = SXE2_IPSEC_SM4_IV_INC
+ },
+ .dataunit_set = RTE_CRYPTO_CIPHER_DATA_UNIT_LEN_512_BYTES,
+ }, }
+ }, }
+ },
+ {
+ .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ {.sym = {
+ .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+ {.auth = {
+ .algo = SXE2_RTE_CRYPTO_AUTH_SHA256_HMAC,
+ .block_size = SXE2_SECURITY_BLOCK_SIZE_64,
+ .key_size = {
+ .min = SXE2_IPSEC_SHA_KEY_MIN,
+ .max = SXE2_IPSEC_SHA_KEY_MAX,
+ .increment = SXE2_IPSEC_SHA_KEY_INC
+ },
+ .digest_size = {
+ .min = SXE2_IPSEC_SHA_DIGEST_MIN,
+ .max = SXE2_IPSEC_SHA_DIGEST_MAX,
+ .increment = SXE2_IPSEC_SHA_DIGEST_INC
+ },
+ .iv_size = {
+ .min = SXE2_IPSEC_SHA_IV_MIN,
+ .max = SXE2_IPSEC_SHA_IV_MAX,
+ .increment = SXE2_IPSEC_SHA_IV_INC
+ },
+ .aad_size = {
+ .min = SXE2_IPSEC_AAD_MIN,
+ .max = SXE2_IPSEC_AAD_MAX,
+ .increment = SXE2_IPSEC_AAD_INC
+ }
+ }, }
+ }, }
+ },
+ {
+ .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ {.sym = {
+ .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+ {.auth = {
+ .algo = SXE2_RTE_CRYPTO_AUTH_SM3_HMAC,
+ .block_size = SXE2_SECURITY_BLOCK_SIZE_64,
+ .key_size = {
+ .min = SXE2_IPSEC_SM3_KEY_MIN,
+ .max = SXE2_IPSEC_SM3_KEY_MAX,
+ .increment = SXE2_IPSEC_SM3_KEY_INC
+ },
+ .digest_size = {
+ .min = SXE2_IPSEC_SM3_DIGEST_MIN,
+ .max = SXE2_IPSEC_SM3_DIGEST_MAX,
+ .increment = SXE2_IPSEC_SM3_DIGEST_INC
+ },
+ .iv_size = {
+ .min = SXE2_IPSEC_SM3_IV_MIN,
+ .max = SXE2_IPSEC_SM3_IV_MAX,
+ .increment = SXE2_IPSEC_SM3_IV_INC
+ },
+ .aad_size = {
+ .min = SXE2_IPSEC_AAD_MIN,
+ .max = SXE2_IPSEC_AAD_MAX,
+ .increment = SXE2_IPSEC_AAD_INC
+ }
+ }, }
+ }, }
+ },
+ {
+ .op = RTE_CRYPTO_OP_TYPE_UNDEFINED,
+ {.sym = {
+ .xform_type = RTE_CRYPTO_SYM_XFORM_NOT_SPECIFIED
+ }, }
+ }
+ };
+
+ static const struct rte_security_capability
+ sxe2_security_capabilities[] = {
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ {.ipsec = {
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+ .direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
+ .options = {
+ .esn = 0,
+ .udp_encap = 1,
+ .copy_dscp = 0,
+ .copy_flabel = 0,
+ .copy_df = 0,
+ .dec_ttl = 0,
+ .ecn = 0,
+ .stats = 1,
+ .iv_gen_disable = 0,
+ .tunnel_hdr_verify = 1,
+ .udp_ports_verify = 1,
+ .ip_csum_enable = 0,
+ .l4_csum_enable = 0,
+ .ip_reassembly_en = 0,
+ .ingress_oop = 0
+ } } },
+ .crypto_capabilities = ipsec_crypto_capabilities,
+ .ol_flags = RTE_SECURITY_TX_OLOAD_NEED_MDATA
+ },
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ {.ipsec = {
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+ .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
+ .options = {
+ .esn = 0,
+ .udp_encap = 1,
+ .copy_dscp = 0,
+ .copy_flabel = 0,
+ .copy_df = 0,
+ .dec_ttl = 0,
+ .ecn = 0,
+ .stats = 1,
+ .iv_gen_disable = 0,
+ .tunnel_hdr_verify = 1,
+ .udp_ports_verify = 1,
+ .ip_csum_enable = 0,
+ .l4_csum_enable = 0,
+ .ip_reassembly_en = 0,
+ .ingress_oop = 0
+ } } },
+ .crypto_capabilities = ipsec_crypto_capabilities,
+ .ol_flags = 0
+ },
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_NONE
+ }
+ };
+
+ return sxe2_security_capabilities;
+}
+
+static struct rte_security_ops sxe2_security_ops = {
+ .session_get_size = sxe2_security_session_size_get,
+ .session_create = sxe2_security_session_create,
+ .session_destroy = sxe2_security_session_destroy,
+ .set_pkt_metadata = sxe2_security_pkt_metadata_set,
+ .capabilities_get = sxe2_security_capabilities_get,
+};
+
+int32_t sxe2_security_init(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct rte_security_ctx *sctx = NULL;
+ struct sxe2_security_ctx *sxe2_sctx = &adapter->security_ctx;
+ int32_t ret = -1;
+
+ if (!sxe2_ipsec_supported(adapter)) {
+ ret = 0;
+ PMD_LOG_INFO(INIT, "Not support security feature.");
+ goto l_end;
+ }
+
+ PMD_LOG_INFO(INIT, "Init security feature.");
+
+ sctx = rte_zmalloc("security_ctx", sizeof(struct rte_security_ctx), 0);
+ if (sctx == NULL) {
+ ret = -ENOMEM;
+ goto l_end;
+ }
+
+ sctx->device = dev;
+ sctx->ops = &sxe2_security_ops;
+ sctx->sess_cnt = 0;
+ sctx->flags = 0;
+ dev->security_ctx = (void *)sctx;
+
+ rte_spinlock_init(&sxe2_sctx->security_lock);
+ sxe2_sctx->adapter = adapter;
+
+ if (sxe2_ipsec_supported(adapter)) {
+ ret = sxe2_ipsec_init(adapter);
+ if (ret) {
+ rte_free(sctx);
+ sctx = NULL;
+ dev->security_ctx = NULL;
+ goto l_end;
+ }
+ }
+
+ ret = 0;
+
+l_end:
+ return ret;
+}
+
+void sxe2_security_uinit(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct rte_security_ctx *sctx = dev->security_ctx;
+
+ if (!sxe2_ipsec_supported(adapter)) {
+ PMD_LOG_INFO(INIT, "Not support security feature.");
+ goto l_end;
+ }
+
+ PMD_LOG_INFO(INIT, "Uinit security feature.");
+
+ if (sctx != NULL) {
+ rte_free(sctx);
+ sctx = NULL;
+ }
+
+ sxe2_ipsec_uinit(adapter);
+
+l_end:
+ return;
+}
diff --git a/drivers/net/sxe2/sxe2_security.h b/drivers/net/sxe2/sxe2_security.h
new file mode 100644
index 0000000000..366c0614bd
--- /dev/null
+++ b/drivers/net/sxe2/sxe2_security.h
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#ifndef __SXE2_SECURITY_H__
+#define __SXE2_SECURITY_H__
+
+#include <rte_security.h>
+#include <rte_cryptodev.h>
+#include <rte_security_driver.h>
+
+#include "sxe2_ipsec.h"
+
+#define SXE2_DEV_TO_SECURITY(eth) \
+ ((struct rte_security_ctx *)(((struct rte_eth_dev *)eth)->security_ctx))
+
+#define SXE2_RTE_CRYPTO_CIPHER_AES_CBC (RTE_CRYPTO_CIPHER_AES_CBC)
+
+#define SXE2_RTE_RTE_CRYPTO_CIPHER_SM4_CBC (RTE_CRYPTO_CIPHER_SM4_CBC)
+
+#define SXE2_RTE_CRYPTO_AUTH_SHA256_HMAC (RTE_CRYPTO_AUTH_SHA256_HMAC)
+
+#define SXE2_RTE_CRYPTO_AUTH_SM3_HMAC (RTE_CRYPTO_AUTH_SM3_HMAC)
+
+enum sxe2_security_protocol {
+ SXE2_SECURITY_PROTOCOL_IPSEC = 0,
+ SXE2_SECURITY_PROTOCOL_MAX = 1,
+};
+
+enum sxe2_security_xform {
+ SXE2_SECURITY_IPSEC_EN = 0,
+ SXE2_SECURITY_IPSEC_DE = 1,
+ SXE2_SECURITY_NUM_MAX = 2,
+};
+
+enum sxe2_security_block_size {
+ SXE2_SECURITY_BLOCK_SIZE_16 = 16,
+ SXE2_SECURITY_BLOCK_SIZE_64 = 64,
+};
+
+struct sxe2_security_ipsec_caps {
+ enum rte_security_ipsec_sa_protocol proto;
+ enum rte_security_ipsec_sa_mode mode;
+ struct rte_security_ipsec_sa_options options;
+};
+
+struct sxe2_security_capabilities {
+ struct rte_cryptodev_capabilities *crypto_capabilities;
+ enum rte_security_session_action_type action;
+ struct sxe2_security_ipsec_caps ipsec;
+};
+
+struct sxe2_security_session {
+ struct sxe2_adapter *adapter;
+ struct sxe2_ipsec_pkt_metadata pkt_metadata_template;
+ struct sxe2_ipsec_security_sa sa;
+ struct sxe2_ipsec_esn esn;
+ struct sxe2_ipsec_udp udp_cap;
+ enum rte_security_session_protocol protocol;
+ enum rte_security_ipsec_sa_direction direction;
+ enum rte_security_ipsec_sa_mode mode;
+ enum rte_security_ipsec_sa_protocol sa_proto;
+ enum rte_security_ipsec_tunnel_type type;
+};
+
+struct sxe2_security_ctx {
+ struct sxe2_adapter *adapter;
+ struct sxe2_security_capabilities sxe2_capabilities[SXE2_SECURITY_PROTOCOL_MAX];
+ struct sxe2_ipsec_ctx ipsec_ctx;
+ rte_spinlock_t security_lock;
+};
+
+int32_t sxe2_security_init(struct rte_eth_dev *dev);
+
+void sxe2_security_uinit(struct rte_eth_dev *dev);
+
+#endif /* __SXE2_SECURITY_H__ */
diff --git a/drivers/net/sxe2/sxe2_tx.c b/drivers/net/sxe2/sxe2_tx.c
index a280edc9c5..f49238ceef 100644
--- a/drivers/net/sxe2/sxe2_tx.c
+++ b/drivers/net/sxe2/sxe2_tx.c
@@ -304,6 +304,11 @@ int32_t __rte_cold sxe2_tx_queue_setup(struct rte_eth_dev *dev,
}
offloads = tx_conf->offloads | dev->data->dev_conf.txmode.offloads;
+ if (!sxe2_ipsec_valid_tx_offloads(offloads)) {
+ ret = -EINVAL;
+ goto end;
+ }
+
txq = sxe2_tx_queue_alloc(dev, queue_idx, nb_desc, socket_id);
if (txq == NULL) {
PMD_LOG_ERR(TX, "failed to alloc sxe2vf tx queue:%u resource", queue_idx);
@@ -327,6 +332,9 @@ int32_t __rte_cold sxe2_tx_queue_setup(struct rte_eth_dev *dev,
txq->ops = sxe2_tx_default_ops_get();
txq->ops.queue_reset(txq);
+ if (sxe2_ipsec_supported(adapter) && txq->offloads & RTE_ETH_TX_OFFLOAD_SECURITY)
+ txq->ipsec_pkt_md_offset = sxe2_ipsec_pkt_md_offset_get(adapter);
+
dev->data->tx_queues[queue_idx] = txq;
ret = 0;
diff --git a/drivers/net/sxe2/sxe2_txrx_poll.c b/drivers/net/sxe2/sxe2_txrx_poll.c
index 3c6fe37404..8b6e585c36 100644
--- a/drivers/net/sxe2/sxe2_txrx_poll.c
+++ b/drivers/net/sxe2/sxe2_txrx_poll.c
@@ -307,6 +307,25 @@ static __rte_always_inline void sxe2_desc_tso_fill(struct rte_mbuf *tx_pkt,
return;
}
+static __rte_always_inline void sxe2_desc_ipsec_fill(struct rte_mbuf *tx_pkt,
+ struct sxe2_tx_queue *txq, uint16_t *ipsec_offset,
+ uint64_t *desc_type_cmd_tso_mss)
+{
+ struct sxe2_ipsec_pkt_metadata *md = NULL;
+ uint16_t ipsec_pkt_md_offset = txq->ipsec_pkt_md_offset;
+
+ md = RTE_MBUF_DYNFIELD(tx_pkt, ipsec_pkt_md_offset, struct sxe2_ipsec_pkt_metadata *);
+ *ipsec_offset = md->esp_head_offset;
+ *desc_type_cmd_tso_mss |= SXE2_TX_CTXT_DESC_IPSEC_EN;
+ if (md->mode == SXE2_IPSEC_MODE_ONLY_ENCRYPT)
+ *desc_type_cmd_tso_mss |= SXE2_TX_CTXT_DESC_IPSEC_MODE;
+
+ if (md->algo == SXE2_IPSEC_ALGO_SM4_CBC_AND_SM3_96_HMAC)
+ *desc_type_cmd_tso_mss |= SXE2_TX_CTXT_DESC_IPSEC_ENGINE;
+
+ *desc_type_cmd_tso_mss |= (uint64_t)(md->sa_idx) << SXE2_TX_CTXT_DESC_IPSEC_SA_SHIFT;
+}
+
static __rte_always_inline uint64_t
sxe2_tx_data_desc_build_cobt(uint32_t cmd, uint32_t offset, uint16_t buf_size, uint16_t l2tag)
{
@@ -426,6 +445,11 @@ uint16_t sxe2_tx_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkt
else if (offloads & RTE_MBUF_F_TX_IEEE1588_TMST)
desc_type_cmd_tso_mss |= SXE2_TX_CTXT_DESC_CMD_TSYN_MASK;
+ if (offloads & RTE_MBUF_F_TX_SEC_OFFLOAD) {
+ sxe2_desc_ipsec_fill(tx_pkt, txq, &ipsec_offset,
+ &desc_type_cmd_tso_mss);
+ }
+
if (offloads & RTE_MBUF_F_TX_QINQ) {
desc_l2tag2 = tx_pkt->vlan_tci_outer;
desc_type_cmd_tso_mss |= SXE2_TX_CTXT_DESC_CMD_IL2TAG2_MASK;
@@ -786,6 +810,36 @@ static inline void sxe2_rx_desc_ptp_para_fill(struct sxe2_rx_queue *rxq,
rxq->ts_low);
}
}
+
+static inline void sxe2_rx_desc_ipsec_para_fill(struct sxe2_rx_queue *rxq __rte_unused,
+ struct rte_mbuf *mbuf, union sxe2_rx_desc *desc)
+{
+ uint32_t status_lrocnt_fdpf_id = rte_le_to_cpu_32(desc->wb.status_lrocnt_fdpf_id);
+ enum sxe2_rx_desc_ipsec_status ipsec_status;
+
+ if (status_lrocnt_fdpf_id & SXE2_RX_DESC_IPSEC_PKT_MASK) {
+ mbuf->ol_flags |= RTE_MBUF_F_RX_SEC_OFFLOAD;
+ ipsec_status = SXE2_RX_DESC_IPSEC_STATUS_VAL_GET(status_lrocnt_fdpf_id);
+ switch (ipsec_status) {
+ case SXE2_RX_DESC_IPSEC_STATUS_SUCCESS:
+ break;
+ case SXE2_RX_DESC_IPSEC_STATUS_PKG_OVER_2K:
+ case SXE2_RX_DESC_IPSEC_STATUS_SPI_IP_INVALID:
+ case SXE2_RX_DESC_IPSEC_STATUS_SA_INVALID:
+ case SXE2_RX_DESC_IPSEC_STATUS_NOT_ALIGN:
+ case SXE2_RX_DESC_IPSEC_STATUS_ICV_ERROR:
+ case SXE2_RX_DESC_IPSEC_STATUS_BY_PASSH:
+ case SXE2_RX_DESC_IPSEC_STATUS_MAC_BY_PASSH:
+ PMD_LOG_INFO(RX, "IPsec status error:%d", ipsec_status);
+ mbuf->ol_flags |= RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED;
+ break;
+ default:
+ PMD_LOG_INFO(RX, "Invalid ipsec status:%d", ipsec_status);
+ mbuf->ol_flags |= RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED;
+ break;
+ }
+ }
+}
#endif
static __rte_always_inline void
@@ -803,6 +857,7 @@ sxe2_rx_mbuf_common_fields_fill(struct sxe2_rx_queue *rxq, struct rte_mbuf *mbuf
sxe2_rx_desc_vlan_para_fill(mbuf, rxd);
sxe2_rx_desc_filter_para_fill(rxq, mbuf, rxd);
#ifndef RTE_LIBRTE_SXE2_16BYTE_RX_DESC
+ sxe2_rx_desc_ipsec_para_fill(rxq, mbuf, rxd);
sxe2_rx_desc_ptp_para_fill(rxq, mbuf, rxd);
#endif
--
2.52.0
next prev parent reply other threads:[~2026-06-02 15:56 UTC|newest]
Thread overview: 200+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-30 18:46 [PATCH v1 00/20] net/sxe2: added Linkdata sxe ethernet driver liujie5
2026-05-30 18:46 ` [PATCH v1 01/20] net/sxe2: support AVX512 vectorized path for Rx and Tx liujie5
2026-05-30 18:46 ` [PATCH v1 02/20] net/sxe2: add AVX2 vector data " liujie5
2026-05-31 22:29 ` Stephen Hemminger
2026-05-30 18:46 ` [PATCH v1 03/20] drivers: add supported packet types get callback liujie5
2026-05-30 18:46 ` [PATCH v1 04/20] net/sxe2: support L2 filtering and MAC config liujie5
2026-05-30 18:46 ` [PATCH v1 05/20] drivers: support RSS feature liujie5
2026-05-30 18:46 ` [PATCH v1 06/20] net/sxe2: support TM hierarchy and shaping liujie5
2026-05-30 18:46 ` [PATCH v1 07/20] net/sxe2: support IPsec inline protocol offload liujie5
2026-05-30 18:46 ` [PATCH v1 08/20] net/sxe2: support statistics and multi-process liujie5
2026-05-30 18:46 ` [PATCH v1 09/20] drivers: interrupt handling liujie5
2026-05-30 18:46 ` [PATCH v1 10/20] net/sxe2: add NEON vec Rx/Tx burst functions liujie5
2026-05-30 18:46 ` [PATCH v1 11/20] drivers: add support for VF representors liujie5
2026-05-30 18:46 ` [PATCH v1 12/20] net/sxe2: add support for custom UDP tunnel ports liujie5
2026-05-30 18:46 ` [PATCH v1 13/20] net/sxe2: support firmware version reading liujie5
2026-05-30 18:46 ` [PATCH v1 14/20] net/sxe2: implement get monitor address liujie5
2026-05-30 18:46 ` [PATCH v1 15/20] common/sxe2: add shared SFP module definitions liujie5
2026-05-30 18:46 ` [PATCH v1 16/20] net/sxe2: support SFP module info and EEPROM access liujie5
2026-05-30 18:46 ` [PATCH v1 17/20] net/sxe2: implement private dump info liujie5
2026-05-30 18:46 ` [PATCH v1 18/20] net/sxe2: add mbuf validation in Tx debug mode liujie5
2026-05-30 18:46 ` [PATCH v1 19/20] drivers: add testpmd commands for private features liujie5
2026-05-31 22:31 ` Stephen Hemminger
2026-05-31 22:32 ` Stephen Hemminger
2026-05-30 18:46 ` [PATCH v1 20/20] net/sxe2: update sxe2 feature matrix docs liujie5
2026-06-01 6:29 ` [PATCH v2 00/20] net/sxe2: added Linkdata sxe2 ethernet driver liujie5
2026-06-01 6:29 ` [PATCH v2 01/20] net/sxe2: support AVX512 vectorized path for Rx and Tx liujie5
2026-06-01 6:29 ` [PATCH v2 02/20] net/sxe2: add AVX2 vector data " liujie5
2026-06-01 6:29 ` [PATCH v2 03/20] drivers: add supported packet types get callback liujie5
2026-06-01 6:29 ` [PATCH v2 04/20] net/sxe2: support L2 filtering and MAC config liujie5
2026-06-01 6:29 ` [PATCH v2 05/20] drivers: support RSS feature liujie5
2026-06-01 6:29 ` [PATCH v2 06/20] net/sxe2: support TM hierarchy and shaping liujie5
2026-06-01 6:29 ` [PATCH v2 07/20] net/sxe2: support IPsec inline protocol offload liujie5
2026-06-01 6:29 ` [PATCH v2 08/20] net/sxe2: support statistics and multi-process liujie5
2026-06-01 6:29 ` [PATCH v2 09/20] drivers: interrupt handling liujie5
2026-06-01 6:29 ` [PATCH v2 10/20] net/sxe2: add NEON vec Rx/Tx burst functions liujie5
2026-06-01 6:29 ` [PATCH v2 11/20] drivers: add support for VF representors liujie5
2026-06-01 6:29 ` [PATCH v2 12/20] net/sxe2: add support for custom UDP tunnel ports liujie5
2026-06-01 6:29 ` [PATCH v2 13/20] net/sxe2: support firmware version reading liujie5
2026-06-01 6:30 ` [PATCH v2 14/20] net/sxe2: implement get monitor address liujie5
2026-06-01 6:30 ` [PATCH v2 15/20] common/sxe2: add shared SFP module definitions liujie5
2026-06-01 6:30 ` [PATCH v2 16/20] net/sxe2: support SFP module info and EEPROM access liujie5
2026-06-01 6:30 ` [PATCH v2 17/20] net/sxe2: implement private dump info liujie5
2026-06-01 6:30 ` [PATCH v2 18/20] net/sxe2: add mbuf validation in Tx debug mode liujie5
2026-06-01 6:30 ` [PATCH v2 19/20] drivers: add testpmd commands for private features liujie5
2026-06-01 6:30 ` [PATCH v2 20/20] net/sxe2: update sxe2 feature matrix docs liujie5
2026-06-01 8:49 ` [PATCH v3 00/20]net/sxe2: added Linkdata sxe2 ethernet driver liujie5
2026-06-01 8:49 ` [PATCH v3 01/20] net/sxe2: support AVX512 vectorized path for Rx and Tx liujie5
2026-06-01 8:49 ` [PATCH v3 02/20] net/sxe2: add AVX2 vector data " liujie5
2026-06-01 8:49 ` [PATCH v3 03/20] drivers: add supported packet types get callback liujie5
2026-06-01 8:49 ` [PATCH v3 04/20] net/sxe2: support L2 filtering and MAC config liujie5
2026-06-01 8:49 ` [PATCH v3 05/20] drivers: support RSS feature liujie5
2026-06-01 8:49 ` [PATCH v3 06/20] net/sxe2: support TM hierarchy and shaping liujie5
2026-06-01 8:49 ` [PATCH v3 07/20] net/sxe2: support IPsec inline protocol offload liujie5
2026-06-01 8:49 ` [PATCH v3 08/20] net/sxe2: support statistics and multi-process liujie5
2026-06-01 8:49 ` [PATCH v3 09/20] drivers: interrupt handling liujie5
2026-06-01 8:49 ` [PATCH v3 10/20] net/sxe2: add NEON vec Rx/Tx burst functions liujie5
2026-06-01 8:49 ` [PATCH v3 11/20] drivers: add support for VF representors liujie5
2026-06-01 8:49 ` [PATCH v3 12/20] net/sxe2: add support for custom UDP tunnel ports liujie5
2026-06-01 8:49 ` [PATCH v3 13/20] net/sxe2: support firmware version reading liujie5
2026-06-01 8:49 ` [PATCH v3 14/20] net/sxe2: implement get monitor address liujie5
2026-06-01 8:49 ` [PATCH v3 15/20] common/sxe2: add shared SFP module definitions liujie5
2026-06-01 8:49 ` [PATCH v3 16/20] net/sxe2: support SFP module info and EEPROM access liujie5
2026-06-01 8:49 ` [PATCH v3 17/20] net/sxe2: implement private dump info liujie5
2026-06-01 8:49 ` [PATCH v3 18/20] net/sxe2: add mbuf validation in Tx debug mode liujie5
2026-06-01 8:49 ` [PATCH v3 19/20] drivers: add testpmd commands for private features liujie5
2026-06-01 8:49 ` [PATCH v3 20/20] net/sxe2: update sxe2 feature matrix docs liujie5
2026-06-02 3:16 ` [PATCH v4 00/20] net/sxe2: added Linkdata sxe2 ethernet driver liujie5
2026-06-02 3:16 ` [PATCH v4 01/20] net/sxe2: support AVX512 vectorized path for Rx and Tx liujie5
2026-06-02 3:16 ` [PATCH v4 02/20] net/sxe2: add AVX2 vector data " liujie5
2026-06-02 3:16 ` [PATCH v4 03/20] drivers: add supported packet types get callback liujie5
2026-06-02 3:16 ` [PATCH v4 04/20] net/sxe2: support L2 filtering and MAC config liujie5
2026-06-02 3:16 ` [PATCH v4 05/20] drivers: support RSS feature liujie5
2026-06-02 3:16 ` [PATCH v4 06/20] net/sxe2: support TM hierarchy and shaping liujie5
2026-06-02 3:16 ` [PATCH v4 07/20] net/sxe2: support IPsec inline protocol offload liujie5
2026-06-02 3:16 ` [PATCH v4 08/20] net/sxe2: support statistics and multi-process liujie5
2026-06-02 3:16 ` [PATCH v4 09/20] drivers: interrupt handling liujie5
2026-06-02 3:16 ` [PATCH v4 10/20] net/sxe2: add NEON vec Rx/Tx burst functions liujie5
2026-06-02 3:16 ` [PATCH v4 11/20] drivers: add support for VF representors liujie5
2026-06-02 3:16 ` [PATCH v4 12/20] net/sxe2: add support for custom UDP tunnel ports liujie5
2026-06-02 3:16 ` [PATCH v4 13/20] net/sxe2: support firmware version reading liujie5
2026-06-02 3:17 ` [PATCH v4 14/20] net/sxe2: implement get monitor address liujie5
2026-06-02 3:17 ` [PATCH v4 15/20] common/sxe2: add shared SFP module definitions liujie5
2026-06-02 3:17 ` [PATCH v4 16/20] net/sxe2: support SFP module info and EEPROM access liujie5
2026-06-02 3:17 ` [PATCH v4 17/20] net/sxe2: implement private dump info liujie5
2026-06-02 3:17 ` [PATCH v4 18/20] net/sxe2: add mbuf validation in Tx debug mode liujie5
2026-06-02 3:17 ` [PATCH v4 19/20] drivers: add testpmd commands for private features liujie5
2026-06-02 3:17 ` [PATCH v4 20/20] net/sxe2: update sxe2 feature matrix docs liujie5
2026-06-02 5:53 ` [PATCH v5 00/20] net/sxe2: added Linkdata sxe2 ethernet driver liujie5
2026-06-02 5:53 ` [PATCH v5 01/20] net/sxe2: support AVX512 vectorized path for Rx and Tx liujie5
2026-06-02 5:53 ` [PATCH v5 02/20] net/sxe2: add AVX2 vector data " liujie5
2026-06-02 5:53 ` [PATCH v5 03/20] drivers: add supported packet types get callback liujie5
2026-06-02 5:53 ` [PATCH v5 04/20] net/sxe2: support L2 filtering and MAC config liujie5
2026-06-02 5:53 ` [PATCH v5 05/20] drivers: support RSS feature liujie5
2026-06-02 5:53 ` [PATCH v5 06/20] net/sxe2: support TM hierarchy and shaping liujie5
2026-06-02 5:54 ` [PATCH v5 07/20] net/sxe2: support IPsec inline protocol offload liujie5
2026-06-02 5:54 ` [PATCH v5 08/20] net/sxe2: support statistics and multi-process liujie5
2026-06-02 5:54 ` [PATCH v5 09/20] drivers: interrupt handling liujie5
2026-06-02 5:54 ` [PATCH v5 10/20] net/sxe2: add NEON vec Rx/Tx burst functions liujie5
2026-06-02 5:54 ` [PATCH v5 11/20] drivers: add support for VF representors liujie5
2026-06-02 5:54 ` [PATCH v5 12/20] net/sxe2: add support for custom UDP tunnel ports liujie5
2026-06-02 5:54 ` [PATCH v5 13/20] net/sxe2: support firmware version reading liujie5
2026-06-02 5:54 ` [PATCH v5 14/20] net/sxe2: implement get monitor address liujie5
2026-06-02 5:54 ` [PATCH v5 15/20] common/sxe2: add shared SFP module definitions liujie5
2026-06-02 5:54 ` [PATCH v5 16/20] net/sxe2: support SFP module info and EEPROM access liujie5
2026-06-02 5:54 ` [PATCH v5 17/20] net/sxe2: implement private dump info liujie5
2026-06-02 5:54 ` [PATCH v5 18/20] net/sxe2: add mbuf validation in Tx debug mode liujie5
2026-06-02 5:54 ` [PATCH v5 19/20] drivers: add testpmd commands for private features liujie5
2026-06-02 5:54 ` [PATCH v5 20/20] net/sxe2: update sxe2 feature matrix docs liujie5
2026-06-02 15:52 ` [PATCH v6 00/20] net/sxe2: added Linkdata sxe2 ethernet driver liujie5
2026-06-02 15:52 ` [PATCH v6 01/20] net/sxe2: support AVX512 vectorized path for Rx and Tx liujie5
2026-06-02 15:52 ` [PATCH v6 02/20] net/sxe2: add AVX2 vector data " liujie5
2026-06-02 15:52 ` [PATCH v6 03/20] drivers: add supported packet types get callback liujie5
2026-06-02 15:52 ` [PATCH v6 04/20] net/sxe2: support L2 filtering and MAC config liujie5
2026-06-02 15:52 ` [PATCH v6 05/20] drivers: support RSS feature liujie5
2026-06-02 15:52 ` [PATCH v6 06/20] net/sxe2: support TM hierarchy and shaping liujie5
2026-06-02 15:52 ` liujie5 [this message]
2026-06-02 15:52 ` [PATCH v6 08/20] net/sxe2: support statistics and multi-process liujie5
2026-06-02 15:52 ` [PATCH v6 09/20] drivers: interrupt handling liujie5
2026-06-02 15:52 ` [PATCH v6 10/20] net/sxe2: add NEON vec Rx/Tx burst functions liujie5
2026-06-02 15:52 ` [PATCH v6 11/20] drivers: add support for VF representors liujie5
2026-06-02 15:52 ` [PATCH v6 12/20] net/sxe2: add support for custom UDP tunnel ports liujie5
2026-06-02 15:52 ` [PATCH v6 13/20] net/sxe2: support firmware version reading liujie5
2026-06-02 15:52 ` [PATCH v6 14/20] net/sxe2: implement get monitor address liujie5
2026-06-02 15:52 ` [PATCH v6 15/20] common/sxe2: add shared SFP module definitions liujie5
2026-06-02 20:34 ` Stephen Hemminger
2026-06-02 15:52 ` [PATCH v6 16/20] net/sxe2: support SFP module info and EEPROM access liujie5
2026-06-02 15:52 ` [PATCH v6 17/20] net/sxe2: implement private dump info liujie5
2026-06-02 15:52 ` [PATCH v6 18/20] net/sxe2: add mbuf validation in Tx debug mode liujie5
2026-06-02 15:52 ` [PATCH v6 19/20] drivers: add testpmd commands for private features liujie5
2026-06-02 15:52 ` [PATCH v6 20/20] net/sxe2: update sxe2 feature matrix docs liujie5
2026-06-03 2:21 ` [PATCH v7 00/20]net/sxe2: added Linkdata sxe2 ethernet driver liujie5
2026-06-03 2:21 ` [PATCH v7 01/20] net/sxe2: support AVX512 vectorized path for Rx and Tx liujie5
2026-06-03 2:21 ` [PATCH v7 02/20] net/sxe2: add AVX2 vector data " liujie5
2026-06-03 2:21 ` [PATCH v7 03/20] drivers: add supported packet types get callback liujie5
2026-06-03 2:21 ` [PATCH v7 04/20] net/sxe2: support L2 filtering and MAC config liujie5
2026-06-03 2:21 ` [PATCH v7 05/20] drivers: support RSS feature liujie5
2026-06-03 2:21 ` [PATCH v7 06/20] net/sxe2: support TM hierarchy and shaping liujie5
2026-06-03 2:21 ` [PATCH v7 07/20] net/sxe2: support IPsec inline protocol offload liujie5
2026-06-03 2:21 ` [PATCH v7 08/20] net/sxe2: support statistics and multi-process liujie5
2026-06-03 2:21 ` [PATCH v7 09/20] drivers: interrupt handling liujie5
2026-06-03 2:21 ` [PATCH v7 10/20] net/sxe2: add NEON vec Rx/Tx burst functions liujie5
2026-06-03 2:21 ` [PATCH v7 11/20] drivers: add support for VF representors liujie5
2026-06-03 2:21 ` [PATCH v7 12/20] net/sxe2: add support for custom UDP tunnel ports liujie5
2026-06-03 2:21 ` [PATCH v7 13/20] net/sxe2: support firmware version reading liujie5
2026-06-03 2:21 ` [PATCH v7 14/20] net/sxe2: implement get monitor address liujie5
2026-06-03 2:21 ` [PATCH v7 15/20] common/sxe2: add shared SFP module definitions liujie5
2026-06-03 2:21 ` [PATCH v7 16/20] net/sxe2: support SFP module info and EEPROM access liujie5
2026-06-03 2:21 ` [PATCH v7 17/20] net/sxe2: implement private dump info liujie5
2026-06-03 2:21 ` [PATCH v7 18/20] net/sxe2: add mbuf validation in Tx debug mode liujie5
2026-06-03 2:21 ` [PATCH v7 19/20] drivers: add testpmd commands for private features liujie5
2026-06-03 2:21 ` [PATCH v7 20/20] net/sxe2: update sxe2 feature matrix docs liujie5
2026-06-03 6:29 ` [PATCH v8 00/20] net/sxe2: added Linkdata sxe2 ethernet driver liujie5
2026-06-03 6:29 ` [PATCH v8 01/20] net/sxe2: support AVX512 vectorized path for Rx and Tx liujie5
2026-06-03 6:29 ` [PATCH v8 02/20] net/sxe2: add AVX2 vector data " liujie5
2026-06-03 6:29 ` [PATCH v8 03/20] drivers: add supported packet types get callback liujie5
2026-06-03 6:29 ` [PATCH v8 04/20] net/sxe2: support L2 filtering and MAC config liujie5
2026-06-03 18:21 ` Stephen Hemminger
2026-06-03 6:29 ` [PATCH v8 05/20] drivers: support RSS feature liujie5
2026-06-03 6:29 ` [PATCH v8 06/20] net/sxe2: support TM hierarchy and shaping liujie5
2026-06-03 6:29 ` [PATCH v8 07/20] net/sxe2: support IPsec inline protocol offload liujie5
2026-06-03 18:17 ` Stephen Hemminger
2026-06-03 6:29 ` [PATCH v8 08/20] net/sxe2: support statistics and multi-process liujie5
2026-06-03 6:29 ` [PATCH v8 09/20] drivers: interrupt handling liujie5
2026-06-03 6:29 ` [PATCH v8 10/20] net/sxe2: add NEON vec Rx/Tx burst functions liujie5
2026-06-03 6:29 ` [PATCH v8 11/20] drivers: add support for VF representors liujie5
2026-06-03 18:22 ` Stephen Hemminger
2026-06-03 6:29 ` [PATCH v8 12/20] net/sxe2: add support for custom UDP tunnel ports liujie5
2026-06-03 6:29 ` [PATCH v8 13/20] net/sxe2: support firmware version reading liujie5
2026-06-03 6:29 ` [PATCH v8 14/20] net/sxe2: implement get monitor address liujie5
2026-06-03 6:29 ` [PATCH v8 15/20] common/sxe2: add shared SFP module definitions liujie5
2026-06-03 6:29 ` [PATCH v8 16/20] net/sxe2: support SFP module info and EEPROM access liujie5
2026-06-03 6:29 ` [PATCH v8 17/20] net/sxe2: implement private dump info liujie5
2026-06-03 6:29 ` [PATCH v8 18/20] net/sxe2: add mbuf validation in Tx debug mode liujie5
2026-06-03 6:29 ` [PATCH v8 19/20] drivers: add testpmd commands for private features liujie5
2026-06-03 18:23 ` Stephen Hemminger
2026-06-03 6:29 ` [PATCH v8 20/20] net/sxe2: update sxe2 feature matrix docs liujie5
2026-06-03 18:19 ` Stephen Hemminger
2026-06-04 1:53 ` [PATCH v9 00/20] net/sxe2: added Linkdata sxe2 ethernet driver liujie5
2026-06-04 1:53 ` [PATCH v9 01/20] net/sxe2: support AVX512 vectorized path for Rx and Tx liujie5
2026-06-04 1:53 ` [PATCH v9 02/20] net/sxe2: add AVX2 vector data " liujie5
2026-06-04 1:53 ` [PATCH v9 03/20] drivers: add supported packet types get callback liujie5
2026-06-04 1:53 ` [PATCH v9 04/20] net/sxe2: support L2 filtering and MAC config liujie5
2026-06-04 1:53 ` [PATCH v9 05/20] drivers: support RSS feature liujie5
2026-06-04 1:53 ` [PATCH v9 06/20] net/sxe2: support TM hierarchy and shaping liujie5
2026-06-04 1:53 ` [PATCH v9 07/20] net/sxe2: support IPsec inline protocol offload liujie5
2026-06-04 1:53 ` [PATCH v9 08/20] net/sxe2: support statistics and multi-process liujie5
2026-06-04 1:53 ` [PATCH v9 09/20] drivers: interrupt handling liujie5
2026-06-04 1:53 ` [PATCH v9 10/20] net/sxe2: add NEON vec Rx/Tx burst functions liujie5
2026-06-04 1:53 ` [PATCH v9 11/20] drivers: add support for VF representors liujie5
2026-06-04 1:53 ` [PATCH v9 12/20] net/sxe2: add support for custom UDP tunnel ports liujie5
2026-06-04 1:53 ` [PATCH v9 13/20] net/sxe2: support firmware version reading liujie5
2026-06-04 1:53 ` [PATCH v9 14/20] net/sxe2: implement get monitor address liujie5
2026-06-04 1:53 ` [PATCH v9 15/20] common/sxe2: add shared SFP module definitions liujie5
2026-06-04 1:54 ` [PATCH v9 16/20] net/sxe2: support SFP module info and EEPROM access liujie5
2026-06-04 1:54 ` [PATCH v9 17/20] net/sxe2: implement private dump info liujie5
2026-06-04 1:54 ` [PATCH v9 18/20] net/sxe2: add mbuf validation in Tx debug mode liujie5
2026-06-04 1:54 ` [PATCH v9 19/20] drivers: add testpmd commands for private features liujie5
2026-06-04 1:54 ` [PATCH v9 20/20] net/sxe2: update sxe2 feature matrix docs liujie5
2026-06-01 15:40 ` [PATCH v3 00/20]net/sxe2: added Linkdata sxe2 ethernet driver Stephen Hemminger
2026-05-31 22:33 ` [PATCH v1 00/20] net/sxe2: added Linkdata sxe " Stephen Hemminger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260602155240.1002602-8-liujie5@linkdatatechnology.com \
--to=liujie5@linkdatatechnology.com \
--cc=dev@dpdk.org \
--cc=stephen@networkplumber.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox