DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
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


  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