* [PATCH v2 13/20] net/sxe2: support firmware version reading
From: liujie5 @ 2026-06-14 9:23 UTC (permalink / raw)
To: stephen; +Cc: dev, Jie Liu
In-Reply-To: <20260614092328.201826-1-liujie5@linkdatatechnology.com>
From: Jie Liu <liujie5@linkdatatechnology.com>
This patch implements the logic to retrieve the firmware version and
Build ID from the hardware during device initialization.
The version is exposed to applications through the dev_info_get API.
Signed-off-by: Jie Liu <liujie5@linkdatatechnology.com>
---
drivers/net/sxe2/sxe2_ethdev.c | 35 +++++++++++++++++++++++++++++++++-
1 file changed, 34 insertions(+), 1 deletion(-)
diff --git a/drivers/net/sxe2/sxe2_ethdev.c b/drivers/net/sxe2/sxe2_ethdev.c
index 48973409d2..9a669f26f3 100644
--- a/drivers/net/sxe2/sxe2_ethdev.c
+++ b/drivers/net/sxe2/sxe2_ethdev.c
@@ -122,7 +122,8 @@ static int32_t sxe2_udp_tunnel_port_add(struct rte_eth_dev *dev,
struct rte_eth_udp_tunnel *tunnel_udp);
static int32_t sxe2_udp_tunnel_port_del(struct rte_eth_dev *dev,
struct rte_eth_udp_tunnel *tunnel_udp);
-
+static int32_t sxe2_fw_version_string_get(struct rte_eth_dev *dev,
+ char *fw_version, size_t fw_size);
static const struct eth_dev_ops sxe2_eth_dev_ops = {
.dev_configure = sxe2_dev_configure,
@@ -183,6 +184,8 @@ static const struct eth_dev_ops sxe2_eth_dev_ops = {
.xstats_reset = sxe2_stats_info_reset,
.queue_stats_mapping_set = sxe2_queue_stats_mapping_set,
+
+ .fw_version_get = sxe2_fw_version_string_get,
};
static int32_t sxe2_dev_configure(struct rte_eth_dev *dev)
@@ -1589,6 +1592,36 @@ static int32_t sxe2_eth_pmd_remove(struct sxe2_common_device *cdev)
return ret;
}
+static int32_t sxe2_fw_version_string_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size)
+{
+ struct sxe2_adapter *adapter =
+ SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_fw_info *fw_info = &adapter->dev_info.fw;
+ int32_t ret_len;
+ int32_t ret;
+
+ ret_len = snprintf(fw_version, fw_size,
+ "%u.%u.%u.%u",
+ fw_info->main_version_id,
+ fw_info->sub_version_id,
+ fw_info->fix_version_id,
+ fw_info->build_id);
+
+ if (ret_len < 0) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret_len += 1;
+ if (fw_size < (size_t)ret_len)
+ ret = -EINVAL;
+ else
+ ret = 0;
+
+out:
+ return ret;
+}
+
static uint16_t sxe2_switchdev_repr_id_encode_get(struct sxe2_switchdev_info *switchdev_info)
{
enum rte_eth_representor_type type;
--
2.52.0
^ permalink raw reply related
* [PATCH v2 10/20] net/sxe2: add NEON vec Rx/Tx burst functions
From: liujie5 @ 2026-06-14 9:23 UTC (permalink / raw)
To: stephen; +Cc: dev, Jie Liu
In-Reply-To: <20260614092328.201826-1-liujie5@linkdatatechnology.com>
From: Jie Liu <liujie5@linkdatatechnology.com>
- Implement sxe2_recv_pkts_vec_neon for bulk packet receiving.
- Implement sxe2_xmit_pkts_vec_neon for bulk packet transmission.
- Added logic to select the vectorized path based on runtime config
and CPU flags (RTE_ARCH_ARM64).
Vectorized path improves throughput for small packets by processing
multiple descriptors simultaneously using SIMD instructions.
Signed-off-by: Jie Liu <liujie5@linkdatatechnology.com>
---
drivers/net/sxe2/meson.build | 2 +
drivers/net/sxe2/sxe2_txrx.c | 39 +-
drivers/net/sxe2/sxe2_txrx_vec.h | 16 +-
drivers/net/sxe2/sxe2_txrx_vec_common.h | 1 +
drivers/net/sxe2/sxe2_txrx_vec_neon.c | 721 ++++++++++++++++++++++++
5 files changed, 774 insertions(+), 5 deletions(-)
create mode 100644 drivers/net/sxe2/sxe2_txrx_vec_neon.c
diff --git a/drivers/net/sxe2/meson.build b/drivers/net/sxe2/meson.build
index fc4466556b..4565046eae 100644
--- a/drivers/net/sxe2/meson.build
+++ b/drivers/net/sxe2/meson.build
@@ -48,6 +48,8 @@ if arch_subdir == 'x86'
include_directories: includes,
c_args: [cflags, '-mavx2'])
objs += sxe2_avx2_lib.extract_objects('sxe2_txrx_vec_avx2.c')
+elif arch_subdir == 'arm'
+ sources += files('sxe2_txrx_vec_neon.c')
endif
sources += files(
diff --git a/drivers/net/sxe2/sxe2_txrx.c b/drivers/net/sxe2/sxe2_txrx.c
index eaf95259a5..a919a84450 100644
--- a/drivers/net/sxe2/sxe2_txrx.c
+++ b/drivers/net/sxe2/sxe2_txrx.c
@@ -175,6 +175,9 @@ void sxe2_tx_mode_func_set(struct rte_eth_dev *dev)
if ((0 == (tx_mode_flags & SXE2_TX_MODE_VEC_SET_MASK)))
tx_mode_flags |= SXE2_TX_MODE_VEC_SSE;
+#elif defined(RTE_ARCH_ARM64)
+ if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_NEON) == 1)
+ tx_mode_flags |= (vec_flags | SXE2_TX_MODE_VEC_NEON);
#endif
if (tx_mode_flags & SXE2_TX_MODE_VEC_SET_MASK) {
ret = sxe2_tx_queues_vec_prepare(dev);
@@ -218,8 +221,15 @@ void sxe2_tx_mode_func_set(struct rte_eth_dev *dev)
dev->tx_pkt_burst = sxe2_tx_pkts_vec_sse_simple;
}
}
- } else {
+#elif defined(RTE_ARCH_ARM64)
+ if (tx_mode_flags & SXE2_TX_MODE_VEC_NEON) {
+ dev->tx_pkt_prepare = sxe2_tx_pkts_prepare;
+ dev->tx_pkt_burst = sxe2_tx_pkts_vec_neon;
+ } else {
+ dev->tx_pkt_burst = sxe2_tx_pkts_vec_neon_simple;
+ }
#endif
+ } else {
if (tx_mode_flags & SXE2_TX_MODE_SIMPLE_BATCH) {
dev->tx_pkt_prepare = NULL;
dev->tx_pkt_burst = sxe2_tx_pkts_simple;
@@ -227,9 +237,7 @@ void sxe2_tx_mode_func_set(struct rte_eth_dev *dev)
dev->tx_pkt_prepare = sxe2_tx_pkts_prepare;
dev->tx_pkt_burst = sxe2_tx_pkts;
}
-#ifdef RTE_ARCH_X86
}
-#endif
}
static const struct {
@@ -253,6 +261,12 @@ static const struct {
{ sxe2_tx_pkts_vec_sse_simple,
"Vector SSE Simple" },
#endif
+#ifdef RTE_ARCH_ARM64
+ { sxe2_tx_pkts_vec_neon,
+ "Vector NEON" },
+ { sxe2_tx_pkts_vec_neon_simple,
+ "Vector NEON Simple" },
+#endif
};
int32_t sxe2_tx_burst_mode_get(struct rte_eth_dev *dev,
@@ -356,6 +370,11 @@ void sxe2_rx_mode_func_set(struct rte_eth_dev *dev)
if (((rx_mode_flags & SXE2_RX_MODE_VEC_SET_MASK) == 0) &&
rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_128)
rx_mode_flags |= SXE2_RX_MODE_VEC_SSE;
+
+#elif defined(RTE_ARCH_ARM64)
+ if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_NEON) == 1) {
+ rx_mode_flags |= (vec_flags | SXE2_RX_MODE_VEC_NEON);
+ }
#endif
if ((rx_mode_flags & SXE2_RX_MODE_VEC_SET_MASK) != 0) {
ret = sxe2_rx_queues_vec_prepare(dev);
@@ -387,6 +406,14 @@ void sxe2_rx_mode_func_set(struct rte_eth_dev *dev)
}
return;
}
+#elif defined(RTE_ARCH_ARM64)
+ if (rx_mode_flags & SXE2_RX_MODE_VEC_SET_MASK) {
+ if (rx_mode_flags & SXE2_RX_MODE_VEC_OFFLOAD)
+ dev->rx_pkt_burst = sxe2_rx_pkts_scattered_vec_neon_offload;
+ else
+ dev->rx_pkt_burst = sxe2_rx_pkts_scattered_vec_neon;
+ return;
+ }
#endif
if (sxe2_rx_offload_en_check(dev, RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT))
dev->rx_pkt_burst = sxe2_rx_pkts_scattered_split;
@@ -416,6 +443,12 @@ static const struct {
{ sxe2_rx_pkts_scattered_vec_sse_offload,
"Vector SSE Scattered" },
#endif
+#ifdef RTE_ARCH_ARM64
+ { sxe2_rx_pkts_scattered_vec_neon,
+ "Vector NEON Scattered" },
+ { sxe2_rx_pkts_scattered_vec_neon_offload,
+ "Offload Vector NEON Scattered" },
+#endif
};
int32_t sxe2_rx_burst_mode_get(struct rte_eth_dev *dev,
diff --git a/drivers/net/sxe2/sxe2_txrx_vec.h b/drivers/net/sxe2/sxe2_txrx_vec.h
index 369777606f..c139aed776 100644
--- a/drivers/net/sxe2/sxe2_txrx_vec.h
+++ b/drivers/net/sxe2/sxe2_txrx_vec.h
@@ -13,19 +13,23 @@
#define SXE2_RX_MODE_VEC_SSE RTE_BIT32(2)
#define SXE2_RX_MODE_VEC_AVX2 RTE_BIT32(3)
#define SXE2_RX_MODE_VEC_AVX512 RTE_BIT32(4)
+#define SXE2_RX_MODE_VEC_NEON RTE_BIT32(5)
#define SXE2_RX_MODE_BATCH_ALLOC RTE_BIT32(10)
#define SXE2_RX_MODE_VEC_SET_MASK (SXE2_RX_MODE_VEC_SIMPLE | \
SXE2_RX_MODE_VEC_OFFLOAD | SXE2_RX_MODE_VEC_SSE | \
- SXE2_RX_MODE_VEC_AVX2 | SXE2_RX_MODE_VEC_AVX512)
+ SXE2_RX_MODE_VEC_AVX2 | SXE2_RX_MODE_VEC_AVX512 | \
+ SXE2_RX_MODE_VEC_NEON)
#define SXE2_TX_MODE_VEC_SIMPLE RTE_BIT32(0)
#define SXE2_TX_MODE_VEC_OFFLOAD RTE_BIT32(1)
#define SXE2_TX_MODE_VEC_SSE RTE_BIT32(2)
#define SXE2_TX_MODE_VEC_AVX2 RTE_BIT32(3)
#define SXE2_TX_MODE_VEC_AVX512 RTE_BIT32(4)
+#define SXE2_TX_MODE_VEC_NEON RTE_BIT32(5)
#define SXE2_TX_MODE_SIMPLE_BATCH RTE_BIT32(10)
#define SXE2_TX_MODE_VEC_SET_MASK (SXE2_TX_MODE_VEC_SIMPLE | \
SXE2_TX_MODE_VEC_OFFLOAD | SXE2_TX_MODE_VEC_SSE | \
- SXE2_TX_MODE_VEC_AVX2 | SXE2_TX_MODE_VEC_AVX512)
+ SXE2_TX_MODE_VEC_AVX2 | SXE2_TX_MODE_VEC_AVX512 | \
+ SXE2_TX_MODE_VEC_NEON)
#define SXE2_TX_VEC_NO_SUPPORT_OFFLOAD ( \
RTE_ETH_TX_OFFLOAD_MULTI_SEGS | \
RTE_ETH_TX_OFFLOAD_QINQ_INSERT | \
@@ -76,6 +80,14 @@ uint16_t sxe2_rx_pkts_scattered_vec_avx2(void *rx_queue,
struct rte_mbuf **rx_pkts, uint16_t nb_pkts);
uint16_t sxe2_rx_pkts_scattered_vec_avx2_offload(void *rx_queue,
struct rte_mbuf **rx_pkts, uint16_t nb_pkts);
+
+#elif defined(RTE_ARCH_ARM64)
+uint16_t sxe2_rx_pkts_scattered_vec_neon(void *rx_queue, struct rte_mbuf **rx_pkts,
+ uint16_t nb_pkts);
+uint16_t sxe2_rx_pkts_scattered_vec_neon_offload(void *rx_queue, struct rte_mbuf **rx_pkts,
+ uint16_t nb_pkts);
+uint16_t sxe2_tx_pkts_vec_neon_simple(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts);
+uint16_t sxe2_tx_pkts_vec_neon(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts);
#endif
int32_t __rte_cold sxe2_tx_vec_support_check(struct rte_eth_dev *dev, uint32_t *vec_flags);
int32_t __rte_cold sxe2_tx_queues_vec_prepare(struct rte_eth_dev *dev);
diff --git a/drivers/net/sxe2/sxe2_txrx_vec_common.h b/drivers/net/sxe2/sxe2_txrx_vec_common.h
index 6b1649c390..c093c3c80c 100644
--- a/drivers/net/sxe2/sxe2_txrx_vec_common.h
+++ b/drivers/net/sxe2/sxe2_txrx_vec_common.h
@@ -2,6 +2,7 @@
* Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
*/
+
#ifndef SXE2_TXRX_VEC_COMMON_H
#define SXE2_TXRX_VEC_COMMON_H
diff --git a/drivers/net/sxe2/sxe2_txrx_vec_neon.c b/drivers/net/sxe2/sxe2_txrx_vec_neon.c
new file mode 100644
index 0000000000..26d3bef21a
--- /dev/null
+++ b/drivers/net/sxe2/sxe2_txrx_vec_neon.c
@@ -0,0 +1,721 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#ifdef RTE_ARCH_ARM64
+#include <arm_neon.h>
+#include <rte_vect.h>
+
+#include "sxe2_txrx_vec_common.h"
+#include "sxe2_txrx_vec.h"
+#include "sxe2_common_log.h"
+
+#define PKTLEN_SHIFT 10
+#define SXE2_UINT16_BIT (CHAR_BIT * sizeof(uint16_t))
+
+static __rte_always_inline void
+sxe2_tx_desc_fill_one_neon(volatile union sxe2_tx_data_desc *desc,
+ struct rte_mbuf *pkt, uint64_t desc_cmd, bool with_offloads)
+{
+ uint64_t desc_qw1;
+ uint32_t desc_offset;
+
+ desc_qw1 = (SXE2_TX_DESC_DTYPE_DATA |
+ ((uint64_t)desc_cmd) << SXE2_TX_DATA_DESC_CMD_SHIFT |
+ ((uint64_t)pkt->data_len) << SXE2_TX_DATA_DESC_BUF_SZ_SHIFT);
+
+ desc_offset = SXE2_TX_DATA_DESC_MACLEN_VAL(pkt->l2_len);
+ desc_qw1 |= ((uint64_t)desc_offset) << SXE2_TX_DATA_DESC_OFFSET_SHIFT;
+ if (with_offloads)
+ sxe2_tx_desc_fill_offloads(pkt, &desc_qw1);
+
+ uint64x2_t data_desc = { rte_pktmbuf_iova(pkt), desc_qw1 };
+
+ vst1q_u64(RTE_CAST_PTR(uint64_t *, desc), data_desc);
+}
+
+static __rte_always_inline uint16_t
+sxe2_tx_pkts_vec_neon_batch(struct sxe2_tx_queue *txq, struct rte_mbuf **tx_pkts,
+ uint16_t nb_pkts, bool with_offloads)
+{
+ volatile union sxe2_tx_data_desc *desc;
+ struct sxe2_tx_buffer *buffer;
+ uint16_t next_use;
+ uint16_t res_num;
+ uint16_t tx_num;
+ uint16_t i;
+
+ if (txq->desc_free_num < txq->free_thresh)
+ (void)sxe2_tx_bufs_free_vec(txq);
+
+ nb_pkts = RTE_MIN(txq->desc_free_num, nb_pkts);
+ if (unlikely(nb_pkts == 0)) {
+ PMD_LOG_DEBUG(TX, "Tx pkts neon batch: may not enough free desc, "
+ "free_desc=%u, need_tx_pkts=%u",
+ txq->desc_free_num, nb_pkts);
+ goto l_end;
+ }
+ tx_num = nb_pkts;
+
+ next_use = txq->next_use;
+ desc = &txq->desc_ring[next_use];
+ buffer = &txq->buffer_ring[next_use];
+
+ txq->desc_free_num -= nb_pkts;
+
+ res_num = txq->ring_depth - txq->next_use;
+
+ if (tx_num >= res_num) {
+ sxe2_tx_pkts_mbuf_fill(buffer, tx_pkts, res_num);
+
+ for (i = 0; i < res_num - 1; ++i, ++tx_pkts, ++desc) {
+ sxe2_tx_desc_fill_one_neon(desc, *tx_pkts,
+ SXE2_TX_DATA_DESC_CMD_EOP, with_offloads);
+ }
+
+ sxe2_tx_desc_fill_one_neon(desc, *tx_pkts++,
+ (SXE2_TX_DATA_DESC_CMD_EOP | SXE2_TX_DATA_DESC_CMD_RS),
+ with_offloads);
+
+ tx_num -= res_num;
+
+ next_use = 0;
+ txq->next_rs = txq->rs_thresh - 1;
+ desc = &txq->desc_ring[next_use];
+ buffer = &txq->buffer_ring[next_use];
+ }
+
+ sxe2_tx_pkts_mbuf_fill(buffer, tx_pkts, tx_num);
+
+ for (i = 0; i < tx_num; ++i, ++tx_pkts, ++desc) {
+ sxe2_tx_desc_fill_one_neon(desc, *tx_pkts,
+ SXE2_TX_DATA_DESC_CMD_EOP, with_offloads);
+ }
+
+ next_use += tx_num;
+ if (next_use > txq->next_rs) {
+ txq->desc_ring[txq->next_rs].read.type_cmd_off_bsz_l2t |=
+ rte_cpu_to_le_64(SXE2_TX_DATA_DESC_CMD_RS_MASK);
+
+ txq->next_rs += txq->rs_thresh;
+ }
+ txq->next_use = next_use;
+
+ SXE2_PCI_REG_WRITE_WC(txq->tdt_reg_addr, txq->next_use);
+
+l_end:
+ return nb_pkts;
+}
+
+static __rte_always_inline uint16_t
+sxe2_tx_pkts_vec_neon_common(struct sxe2_tx_queue *txq, struct rte_mbuf **tx_pkts,
+ uint16_t nb_pkts, bool with_offloads)
+{
+ uint16_t tx_done_num = 0;
+ uint16_t tx_once_num;
+ uint16_t tx_need_num;
+
+ while (nb_pkts) {
+ tx_need_num = RTE_MIN(nb_pkts, txq->rs_thresh);
+ tx_once_num = sxe2_tx_pkts_vec_neon_batch(txq,
+ tx_pkts + tx_done_num,
+ tx_need_num, with_offloads);
+
+ nb_pkts -= tx_once_num;
+ tx_done_num += tx_once_num;
+
+ if (tx_once_num < tx_need_num)
+ break;
+ }
+
+ PMD_LOG_DEBUG(TX, "Tx pkts neon: port_id=%u, queue_id=%u, "
+ "nb_pkts=%u, tx_done_num=%u with_offloads=%u",
+ txq->port_id, txq->idx_in_func, nb_pkts, tx_done_num, with_offloads);
+
+ return tx_done_num;
+}
+
+uint16_t sxe2_tx_pkts_vec_neon_simple(void *tx_queue,
+ struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+ return sxe2_tx_pkts_vec_neon_common((struct sxe2_tx_queue *)tx_queue,
+ tx_pkts, nb_pkts, false);
+}
+
+uint16_t sxe2_tx_pkts_vec_neon(void *tx_queue,
+ struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+ return sxe2_tx_pkts_vec_neon_common((struct sxe2_tx_queue *)tx_queue,
+ tx_pkts, nb_pkts, true);
+}
+
+static __rte_always_inline void
+sxe2_rx_desc_ptype_fill_neon(uint16x8_t staterr, struct rte_mbuf **__rte_restrict rx_pkts,
+ const uint32_t *__rte_restrict ptype_tbl)
+{
+ uint16x8_t ptype_mask = {
+ 0, 0x3FFULL,
+ 0, 0x3FFULL,
+ 0, 0x3FFULL,
+ 0, 0x3FFULL,
+ };
+ uint16x8_t ptype_all;
+
+ ptype_all = vandq_u16(staterr, ptype_mask);
+
+ rx_pkts[3]->packet_type = ptype_tbl[vgetq_lane_u16(ptype_all, 3)];
+ rx_pkts[2]->packet_type = ptype_tbl[vgetq_lane_u16(ptype_all, 7)];
+ rx_pkts[1]->packet_type = ptype_tbl[vgetq_lane_u16(ptype_all, 1)];
+ rx_pkts[0]->packet_type = ptype_tbl[vgetq_lane_u16(ptype_all, 5)];
+}
+
+static __rte_always_inline uint32x4_t
+sxe2_rx_desc_fnav_flags_neon(uint64x2_t descs_arr[4])
+{
+ uint32x4_t descs_tmp1, descs_tmp2;
+ uint32x4_t descs_fnav_vld;
+ uint32x4_t v_zeros, v_ffff, v_u32_one;
+ uint32x4_t m_flags;
+
+ const uint32x4_t fdir_flags = vdupq_n_u32(RTE_MBUF_F_RX_FDIR |
+ RTE_MBUF_F_RX_FDIR_ID);
+
+ uint32x4_t d0 = vreinterpretq_u32_u64(descs_arr[0]);
+ uint32x4_t d1 = vreinterpretq_u32_u64(descs_arr[1]);
+ uint32x4_t d2 = vreinterpretq_u32_u64(descs_arr[2]);
+ uint32x4_t d3 = vreinterpretq_u32_u64(descs_arr[3]);
+
+ descs_tmp1 = vzip1q_u32(d1, d0);
+ descs_tmp2 = vzip1q_u32(d3, d2);
+
+ uint64x2_t a = vreinterpretq_u64_u32(descs_tmp1);
+ uint64x2_t b = vreinterpretq_u64_u32(descs_tmp2);
+
+ descs_fnav_vld = vreinterpretq_u32_u64(vcombine_u64(vget_low_u64(a), vget_low_u64(b)));
+
+ descs_fnav_vld = vshlq_n_u32(descs_fnav_vld, 26);
+ descs_fnav_vld = vshrq_n_u32(descs_fnav_vld, 31);
+
+ v_zeros = vdupq_n_u32(0);
+ v_ffff = vceqq_u32(v_zeros, v_zeros);
+ v_u32_one = vshrq_n_u32(v_ffff, 31);
+
+ m_flags = vceqq_u32(descs_fnav_vld, v_u32_one);
+
+ m_flags = vandq_u32(m_flags, fdir_flags);
+ return m_flags;
+}
+
+static __rte_always_inline void
+sxe2_rx_desc_offloads_para_fill_neon(struct sxe2_rx_queue *rxq,
+ volatile union sxe2_rx_desc *desc,
+ uint64x2_t descs[4], struct rte_mbuf **rx_pkts)
+{
+ uint32x4_t desc_lo, desc_hi, flags, tmp_flags;
+ const uint64x2_t mbuf_init = {rxq->mbuf_init_value, 0};
+ uint64x2_t rearm0, rearm1, rearm2, rearm3;
+
+ const uint32x4_t desc_msk = {
+ 0x00001C04, 0x00001C04, 0x00001C04, 0x00001C04};
+
+ const uint32x4_t rss_msk = {
+ 0x20000000, 0x20000000, 0x20000000, 0x20000000};
+
+ const uint32x4_t vlan_msk = {
+ RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED,
+ RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED,
+ RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED,
+ RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED
+ };
+ const uint8x16_t vlan_flags = {
+ 0, 0, 0, 0,
+ RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0
+ };
+
+ const uint8x16_t rss_flags = {
+ 0, 0, 0, 0,
+ RTE_MBUF_F_RX_RSS_HASH, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0
+ };
+
+ const uint32x4_t cksum_mask = {
+ RTE_MBUF_F_RX_IP_CKSUM_MASK | RTE_MBUF_F_RX_L4_CKSUM_MASK |
+ RTE_MBUF_F_RX_OUTER_L4_CKSUM_MASK | RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD,
+ RTE_MBUF_F_RX_IP_CKSUM_MASK | RTE_MBUF_F_RX_L4_CKSUM_MASK |
+ RTE_MBUF_F_RX_OUTER_L4_CKSUM_MASK | RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD,
+ RTE_MBUF_F_RX_IP_CKSUM_MASK | RTE_MBUF_F_RX_L4_CKSUM_MASK |
+ RTE_MBUF_F_RX_OUTER_L4_CKSUM_MASK | RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD,
+ RTE_MBUF_F_RX_IP_CKSUM_MASK | RTE_MBUF_F_RX_L4_CKSUM_MASK |
+ RTE_MBUF_F_RX_OUTER_L4_CKSUM_MASK | RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD,
+ };
+
+ const uint8x16_t cksum_flags = {
+ ((RTE_MBUF_F_RX_L4_CKSUM_GOOD | RTE_MBUF_F_RX_IP_CKSUM_GOOD) >> 1),
+ ((RTE_MBUF_F_RX_L4_CKSUM_GOOD | RTE_MBUF_F_RX_IP_CKSUM_BAD) >> 1),
+ ((RTE_MBUF_F_RX_L4_CKSUM_BAD | RTE_MBUF_F_RX_IP_CKSUM_GOOD) >> 1),
+ ((RTE_MBUF_F_RX_L4_CKSUM_BAD | RTE_MBUF_F_RX_IP_CKSUM_BAD) >> 1),
+ ((RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD | RTE_MBUF_F_RX_L4_CKSUM_GOOD |
+ RTE_MBUF_F_RX_IP_CKSUM_GOOD) >> 1),
+ ((RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD | RTE_MBUF_F_RX_L4_CKSUM_GOOD |
+ RTE_MBUF_F_RX_IP_CKSUM_BAD) >> 1),
+ ((RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD | RTE_MBUF_F_RX_L4_CKSUM_BAD |
+ RTE_MBUF_F_RX_IP_CKSUM_GOOD) >> 1),
+ ((RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD | RTE_MBUF_F_RX_L4_CKSUM_BAD |
+ RTE_MBUF_F_RX_IP_CKSUM_BAD) >> 1),
+ 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ {
+ uint32x4_t d0 = vreinterpretq_u32_u64(descs[0]);
+ uint32x4_t d1 = vreinterpretq_u32_u64(descs[1]);
+ uint32x4_t d2 = vreinterpretq_u32_u64(descs[2]);
+ uint32x4_t d3 = vreinterpretq_u32_u64(descs[3]);
+ uint64x2_t f64, t64;
+
+ flags = vzip2q_u32(d1, d0);
+ tmp_flags = vzip2q_u32(d3, d2);
+ f64 = vreinterpretq_u64_u32(flags);
+ t64 = vreinterpretq_u64_u32(tmp_flags);
+ desc_lo = vreinterpretq_u32_u64(vcombine_u64(vget_low_u64(f64),
+ vget_low_u64(t64)));
+ desc_hi = vreinterpretq_u32_u64(vcombine_u64(vget_high_u64(f64),
+ vget_high_u64(t64)));
+ }
+
+ desc_lo = vandq_u32(desc_lo, desc_msk);
+ desc_hi = vandq_u32(desc_hi, rss_msk);
+
+ tmp_flags = vreinterpretq_u32_u8(vqtbl1q_u8(vlan_flags,
+ vreinterpretq_u8_u32(desc_lo)));
+ flags = vandq_u32(tmp_flags, vlan_msk);
+
+ desc_lo = vshrq_n_u32(desc_lo, 10);
+ tmp_flags = vreinterpretq_u32_u8(vqtbl1q_u8(cksum_flags,
+ vreinterpretq_u8_u32(desc_lo)));
+ tmp_flags = vshlq_n_u32(tmp_flags, 1);
+ tmp_flags = vandq_u32(tmp_flags, cksum_mask);
+ flags = vorrq_u32(flags, tmp_flags);
+
+ desc_hi = vshrq_n_u32(desc_hi, 27);
+ tmp_flags = vreinterpretq_u32_u8(vqtbl1q_u8(rss_flags,
+ vreinterpretq_u8_u32(desc_hi)));
+ flags = vorrq_u32(flags, tmp_flags);
+
+#ifndef RTE_LIBRTE_SXE2_16BYTE_RX_DESC
+ if (rxq->fnav_enable) {
+ uint32x4_t tmp_fnav_flags = sxe2_rx_desc_fnav_flags_neon(descs);
+ flags = vorrq_u32(flags, tmp_fnav_flags);
+
+ rx_pkts[0]->hash.fdir.hi = desc[0].wb.fd_filter_id;
+ rx_pkts[1]->hash.fdir.hi = desc[1].wb.fd_filter_id;
+ rx_pkts[2]->hash.fdir.hi = desc[2].wb.fd_filter_id;
+ rx_pkts[3]->hash.fdir.hi = desc[3].wb.fd_filter_id;
+ }
+#endif
+
+ rearm0 = vsetq_lane_u64(vgetq_lane_u32(flags, 0), mbuf_init, 1);
+ rearm1 = vsetq_lane_u64(vgetq_lane_u32(flags, 1), mbuf_init, 1);
+ rearm2 = vsetq_lane_u64(vgetq_lane_u32(flags, 2), mbuf_init, 1);
+ rearm3 = vsetq_lane_u64(vgetq_lane_u32(flags, 3), mbuf_init, 1);
+
+ vst1q_u64((uint64_t *)&rx_pkts[0]->rearm_data, rearm0);
+ vst1q_u64((uint64_t *)&rx_pkts[1]->rearm_data, rearm1);
+ vst1q_u64((uint64_t *)&rx_pkts[2]->rearm_data, rearm2);
+ vst1q_u64((uint64_t *)&rx_pkts[3]->rearm_data, rearm3);
+}
+
+static inline void sxe2_rx_queue_rearm_neon(struct sxe2_rx_queue *rxq)
+{
+ volatile union sxe2_rx_desc *desc;
+ struct rte_mbuf **buffer;
+ struct rte_mbuf *mbuf0, *mbuf1;
+ uint64x2_t dma_addr0, dma_addr1;
+ uint64x2_t zero = vdupq_n_u64(0);
+ uint64x2_t virt_addr0, virt_addr1;
+ uint64x2_t hdr_room = vdupq_n_u64(RTE_PKTMBUF_HEADROOM);
+ int32_t ret;
+ uint16_t i;
+ uint16_t new_tail;
+
+ buffer = &rxq->buffer_ring[rxq->realloc_start];
+ desc = &rxq->desc_ring[rxq->realloc_start];
+
+ ret = rte_mempool_get_bulk(rxq->mb_pool, (void *)buffer,
+ SXE2_RX_REARM_THRESH_VEC);
+ if (ret != 0) {
+ PMD_LOG_INFO(RX, "Rx mbuf vec alloc failed port_id=%u "
+ "queue_id=%u", rxq->port_id, rxq->idx_in_func);
+
+ if ((rxq->realloc_num + SXE2_RX_REARM_THRESH_VEC) >= rxq->ring_depth) {
+ for (i = 0; i < SXE2_RX_NUM_PER_LOOP_NEON; ++i) {
+ buffer[i] = &rxq->fake_mbuf;
+ vst1q_u64(RTE_CAST_PTR(uint64_t *, &desc[i].read), zero);
+ }
+ }
+
+ rxq->vsi->adapter->dev_info.dev_data->rx_mbuf_alloc_failed +=
+ SXE2_RX_REARM_THRESH_VEC;
+ goto l_end;
+ }
+
+ for (i = 0; i < SXE2_RX_REARM_THRESH_VEC; i += 2, buffer += 2) {
+ mbuf0 = buffer[0];
+ mbuf1 = buffer[1];
+#if RTE_IOVA_IN_MBUF
+ RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, buf_iova) !=
+ offsetof(struct rte_mbuf, buf_addr) + 8);
+#endif
+ virt_addr0 = vld1q_u64((uint64_t *)&mbuf0->buf_addr);
+ virt_addr1 = vld1q_u64((uint64_t *)&mbuf1->buf_addr);
+
+#if RTE_IOVA_IN_MBUF
+ dma_addr0 = vdupq_n_u64((uint64_t)vget_high_u64(virt_addr0));
+ dma_addr1 = vdupq_n_u64((uint64_t)vget_high_u64(virt_addr1));
+#else
+ dma_addr0 = vdupq_n_u64((uint64_t)vget_low_u64(virt_addr0));
+ dma_addr1 = vdupq_n_u64((uint64_t)vget_low_u64(virt_addr1));
+#endif
+ dma_addr0 = vaddq_u64(dma_addr0, hdr_room);
+ dma_addr1 = vaddq_u64(dma_addr1, hdr_room);
+
+ vst1q_u64(RTE_CAST_PTR(uint64_t *, &desc++->read), dma_addr0);
+ vst1q_u64(RTE_CAST_PTR(uint64_t *, &desc++->read), dma_addr1);
+ }
+
+ rxq->realloc_start += SXE2_RX_REARM_THRESH_VEC;
+ if (rxq->realloc_start >= rxq->ring_depth)
+ rxq->realloc_start = 0;
+ rxq->realloc_num -= SXE2_RX_REARM_THRESH_VEC;
+
+ new_tail = (rxq->realloc_start == 0) ?
+ (rxq->ring_depth - 1) : (rxq->realloc_start - 1);
+
+ SXE2_PCI_REG_WRITE_WC(rxq->rdt_reg_addr, new_tail);
+
+l_end:
+ return;
+}
+
+static __rte_always_inline uint16_t
+sxe2_rx_pkts_common_vec_neon(struct sxe2_rx_queue *rxq, struct rte_mbuf **rx_pkts,
+ uint16_t nb_pkts, uint8_t *split_rxe_flags, uint8_t *umbcast_flags,
+ bool do_offload)
+{
+ volatile union sxe2_rx_desc *desc;
+ struct rte_mbuf **buffer;
+ uint32_t i;
+ uint16_t done_num = 0;
+ const uint32_t *ptype_tbl = rxq->vsi->adapter->ptype_tbl;
+
+ uint8x16_t rvp_shuf_mask = {
+ 0xFF, 0xFF, 0xFF, 0xFF,
+ 12, 13, 0xFF, 0xFF,
+ 12, 13,
+ 2, 3,
+ 4, 5, 6, 7
+ };
+
+ uint16x8_t crc_adjust = {
+ 0, 0,
+ rxq->crc_len,
+ 0, rxq->crc_len,
+ 0, 0, 0
+ };
+
+ desc = &rxq->desc_ring[rxq->processing_idx];
+ rte_prefetch0(desc);
+
+ nb_pkts = RTE_ALIGN_FLOOR(nb_pkts, SXE2_RX_NUM_PER_LOOP_NEON);
+
+ if (rxq->realloc_num > SXE2_RX_REARM_THRESH_VEC)
+ sxe2_rx_queue_rearm_neon(rxq);
+
+ if ((rte_le_to_cpu_64(desc->wb.status_err_ptype_len) &
+ SXE2_RX_DESC_STATUS_DD_MASK) == 0) {
+ goto l_end;
+ }
+
+ buffer = &rxq->buffer_ring[rxq->processing_idx];
+ for (i = 0; i < nb_pkts; i += SXE2_RX_NUM_PER_LOOP_NEON,
+ desc += SXE2_RX_NUM_PER_LOOP_NEON) {
+ uint64x2_t descs[SXE2_RX_NUM_PER_LOOP_NEON];
+ uint8x16_t pkt_mb1, pkt_mb2, pkt_mb3, pkt_mb4;
+ uint64x2_t mbp1, mbp2;
+ uint16x8_t staterr;
+ uint16x8_t tmp;
+ uint16_t bit_num;
+
+ descs[3] = vld1q_u64(RTE_CAST_PTR(uint64_t *, desc + 3));
+ rte_atomic_thread_fence(rte_memory_order_acquire);
+ descs[2] = vld1q_u64(RTE_CAST_PTR(uint64_t *, desc + 2));
+ rte_atomic_thread_fence(rte_memory_order_acquire);
+ descs[1] = vld1q_u64(RTE_CAST_PTR(uint64_t *, desc + 1));
+ rte_atomic_thread_fence(rte_memory_order_acquire);
+ descs[0] = vld1q_u64(RTE_CAST_PTR(uint64_t *, desc));
+
+ rte_atomic_thread_fence(rte_memory_order_acquire);
+
+ descs[3] = vld1q_lane_u64(RTE_CAST_PTR(uint64_t *, desc + 3), descs[3], 0);
+ descs[2] = vld1q_lane_u64(RTE_CAST_PTR(uint64_t *, desc + 2), descs[2], 0);
+ descs[1] = vld1q_lane_u64(RTE_CAST_PTR(uint64_t *, desc + 1), descs[1], 0);
+ descs[0] = vld1q_lane_u64(RTE_CAST_PTR(uint64_t *, desc), descs[0], 0);
+
+ mbp1 = vld1q_u64((uint64_t *)&buffer[i]);
+ mbp2 = vld1q_u64((uint64_t *)&buffer[i + 2]);
+
+ vst1q_u64((uint64_t *)&rx_pkts[i], mbp1);
+ vst1q_u64((uint64_t *)&rx_pkts[i + 2], mbp2);
+
+ if (split_rxe_flags) {
+ rte_mbuf_prefetch_part2(rx_pkts[i]);
+ rte_mbuf_prefetch_part2(rx_pkts[i + 1]);
+ rte_mbuf_prefetch_part2(rx_pkts[i + 2]);
+ rte_mbuf_prefetch_part2(rx_pkts[i + 3]);
+ }
+
+ pkt_mb4 = vqtbl1q_u8(vreinterpretq_u8_u64(descs[3]), rvp_shuf_mask);
+ pkt_mb3 = vqtbl1q_u8(vreinterpretq_u8_u64(descs[2]), rvp_shuf_mask);
+ pkt_mb2 = vqtbl1q_u8(vreinterpretq_u8_u64(descs[1]), rvp_shuf_mask);
+ pkt_mb1 = vqtbl1q_u8(vreinterpretq_u8_u64(descs[0]), rvp_shuf_mask);
+
+ if (do_offload) {
+ sxe2_rx_desc_offloads_para_fill_neon(rxq, desc, descs, &rx_pkts[i]);
+ } else {
+ const uint64x2_t mbuf_init = {
+ rxq->mbuf_init_value,
+ 0,
+ };
+
+ vst1q_u64((uint64_t *)&rx_pkts[i]->rearm_data, mbuf_init);
+ vst1q_u64((uint64_t *)&rx_pkts[i + 1]->rearm_data, mbuf_init);
+ vst1q_u64((uint64_t *)&rx_pkts[i + 2]->rearm_data, mbuf_init);
+ vst1q_u64((uint64_t *)&rx_pkts[i + 3]->rearm_data, mbuf_init);
+ }
+
+ tmp = vsubq_u16(vreinterpretq_u16_u8(pkt_mb4), crc_adjust);
+ pkt_mb4 = vreinterpretq_u8_u16(tmp);
+ tmp = vsubq_u16(vreinterpretq_u16_u8(pkt_mb3), crc_adjust);
+ pkt_mb3 = vreinterpretq_u8_u16(tmp);
+ tmp = vsubq_u16(vreinterpretq_u16_u8(pkt_mb2), crc_adjust);
+ pkt_mb2 = vreinterpretq_u8_u16(tmp);
+ tmp = vsubq_u16(vreinterpretq_u16_u8(pkt_mb1), crc_adjust);
+ pkt_mb1 = vreinterpretq_u8_u16(tmp);
+
+ vst1q_u8((void *)&rx_pkts[i + 3]->rx_descriptor_fields1,
+ pkt_mb4);
+ vst1q_u8((void *)&rx_pkts[i + 2]->rx_descriptor_fields1,
+ pkt_mb3);
+ vst1q_u8((void *)&rx_pkts[i + 1]->rx_descriptor_fields1,
+ pkt_mb2);
+ vst1q_u8((void *)&rx_pkts[i]->rx_descriptor_fields1,
+ pkt_mb1);
+
+ if (likely(i + SXE2_RX_NUM_PER_LOOP_NEON < nb_pkts))
+ rte_prefetch_non_temporal(desc + SXE2_RX_NUM_PER_LOOP_NEON);
+
+ {
+ uint32x4_t d0 = vreinterpretq_u32_u64(descs[0]);
+ uint32x4_t d1 = vreinterpretq_u32_u64(descs[1]);
+ uint32x4_t d2 = vreinterpretq_u32_u64(descs[2]);
+ uint32x4_t d3 = vreinterpretq_u32_u64(descs[3]);
+ uint32x4_t sterr_tmp1 = vzip2q_u32(d1, d0);
+ uint32x4_t sterr_tmp2 = vzip2q_u32(d3, d2);
+ uint32x4_t sterr_u32 = vzip1q_u32(sterr_tmp1, sterr_tmp2);
+
+ staterr = vreinterpretq_u16_u32(sterr_u32);
+ }
+
+ sxe2_rx_desc_ptype_fill_neon(staterr, &rx_pkts[i], ptype_tbl);
+
+ if (umbcast_flags != NULL) {
+ uint32x4_t umbcast_mask = {
+ SXE2_RX_DESC_STATUS_UMBCAST_MASK, SXE2_RX_DESC_STATUS_UMBCAST_MASK,
+ SXE2_RX_DESC_STATUS_UMBCAST_MASK, SXE2_RX_DESC_STATUS_UMBCAST_MASK,
+ };
+
+ uint8x16_t umbcast_shuf_mask = {
+ 0x0B, 0x03, 0x0F, 0x07,
+ 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF,
+ };
+ uint8x16_t umbcast_bits =
+ vreinterpretq_u8_u32(vandq_u32(vreinterpretq_u32_u16(staterr),
+ umbcast_mask));
+
+ umbcast_bits = vqtbl1q_u8(umbcast_bits, umbcast_shuf_mask);
+ vst1q_lane_u32((uint32_t *)umbcast_flags,
+ vreinterpretq_u32_u8(umbcast_bits), 0);
+ umbcast_flags += SXE2_RX_NUM_PER_LOOP_NEON;
+ }
+
+ if (split_rxe_flags) {
+ uint8x16_t eop_shuf_mask = {
+ 0x08, 0x00, 0x0C, 0x04,
+ 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF};
+ uint8x16_t eop_bits;
+ uint32x4_t rxe_mask = {
+ 0x2080, 0x2080, 0x2080, 0x2080
+ };
+ uint32x4_t rxe_bits;
+ uint32x4_t eop_mask;
+
+ eop_mask = vshlq_n_u32(vdupq_n_u32(1), SXE2_RX_DESC_STATUS_EOP_SHIFT);
+ eop_bits = vandq_u8(vmvnq_u8(vreinterpretq_u8_u16(staterr)),
+ vreinterpretq_u8_u32(eop_mask));
+
+ rxe_bits = vandq_u32(vreinterpretq_u32_u16(staterr), rxe_mask);
+ rxe_bits = vshrq_n_u32(rxe_bits, 7);
+
+ eop_bits = vorrq_u8(eop_bits, vreinterpretq_u8_u32(rxe_bits));
+
+ eop_bits = vqtbl1q_u8(eop_bits, eop_shuf_mask);
+
+ vst1q_lane_u32((uint32_t *)split_rxe_flags,
+ vreinterpretq_u32_u8(eop_bits), 0);
+ split_rxe_flags += SXE2_RX_NUM_PER_LOOP_NEON;
+
+#ifdef RTE_IOVA_IN_MBUF
+ rx_pkts[i]->next = NULL;
+ rx_pkts[i + 1]->next = NULL;
+ rx_pkts[i + 2]->next = NULL;
+ rx_pkts[i + 3]->next = NULL;
+#endif
+ }
+
+ {
+ uint32x4_t dd_mask = vdupq_n_u32(1);
+ uint32x4_t sterr_dd = vandq_u32(vreinterpretq_u32_u16(staterr), dd_mask);
+ uint16x4_t packed_lo = vmovn_u32(sterr_dd);
+ uint64_t dd64 = vget_lane_u64(vreinterpret_u64_u16(packed_lo), 0);
+
+ bit_num = (uint16_t)rte_popcount64(dd64);
+ }
+ done_num += bit_num;
+ if (likely(bit_num != SXE2_RX_NUM_PER_LOOP_NEON))
+ break;
+ }
+
+ rxq->processing_idx += done_num;
+ rxq->processing_idx &= (rxq->ring_depth - 1);
+ rxq->realloc_num += done_num;
+
+l_end:
+ return done_num;
+}
+
+static __rte_always_inline uint16_t
+sxe2_rx_pkts_scattered_batch_vec_neon(struct sxe2_rx_queue *rxq,
+ struct rte_mbuf **rx_pkts, uint16_t nb_pkts, bool do_offload)
+{
+ const uint64_t *split_flags64;
+ uint8_t split_rxe_flags[SXE2_RX_PKTS_BURST_BATCH_NUM_VEC] = {0};
+ uint8_t umbcast_flags[SXE2_RX_PKTS_BURST_BATCH_NUM_VEC] = {0};
+ uint16_t rx_done_num;
+ uint16_t rx_pkt_done_num;
+
+ rx_pkt_done_num = 0;
+
+ if (rxq->vsi->adapter->devargs.sw_stats_en) {
+ rx_done_num = sxe2_rx_pkts_common_vec_neon((struct sxe2_rx_queue *)rxq,
+ rx_pkts, nb_pkts, split_rxe_flags, umbcast_flags,
+ do_offload);
+ } else {
+ rx_done_num = sxe2_rx_pkts_common_vec_neon((struct sxe2_rx_queue *)rxq,
+ rx_pkts, nb_pkts, split_rxe_flags, NULL,
+ do_offload);
+ }
+
+ if (rx_done_num == 0)
+ goto l_end;
+
+ if (!rxq->vsi->adapter->devargs.sw_stats_en) {
+ split_flags64 = (uint64_t *)split_rxe_flags;
+
+ if (rxq->pkt_first_seg == NULL &&
+ split_flags64[0] == 0 && split_flags64[1] == 0 &&
+ split_flags64[2] == 0 && split_flags64[3] == 0) {
+ rx_pkt_done_num = rx_done_num;
+ goto l_end;
+ }
+
+ if (rxq->pkt_first_seg == NULL) {
+ while (rx_pkt_done_num < rx_done_num &&
+ split_rxe_flags[rx_pkt_done_num] == 0) {
+ rx_pkt_done_num++;
+ }
+
+ if (rx_pkt_done_num == rx_done_num)
+ goto l_end;
+
+ rxq->pkt_first_seg = rx_pkts[rx_pkt_done_num];
+ }
+ }
+
+ rx_pkt_done_num += sxe2_rx_pkts_refactor(rxq, &rx_pkts[rx_pkt_done_num],
+ rx_done_num - rx_pkt_done_num, &split_rxe_flags[rx_pkt_done_num],
+ &umbcast_flags[rx_pkt_done_num]);
+
+l_end:
+ return rx_pkt_done_num;
+}
+
+uint16_t sxe2_rx_pkts_scattered_vec_neon_offload(void *rx_queue,
+ struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
+{
+ uint16_t done_num = 0;
+ uint16_t once_num;
+
+ while (nb_pkts > SXE2_RX_PKTS_BURST_BATCH_NUM_VEC) {
+ once_num = sxe2_rx_pkts_scattered_batch_vec_neon((struct sxe2_rx_queue *)rx_queue,
+ rx_pkts + done_num,
+ SXE2_RX_PKTS_BURST_BATCH_NUM_VEC,
+ true);
+
+ done_num += once_num;
+ nb_pkts -= once_num;
+
+ if (once_num < SXE2_RX_PKTS_BURST_BATCH_NUM_VEC)
+ goto l_end;
+ }
+
+ done_num += sxe2_rx_pkts_scattered_batch_vec_neon((struct sxe2_rx_queue *)rx_queue,
+ rx_pkts + done_num,
+ nb_pkts,
+ true);
+l_end:
+ return done_num;
+}
+
+uint16_t sxe2_rx_pkts_scattered_vec_neon(void *rx_queue,
+ struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
+{
+ uint16_t done_num = 0;
+ uint16_t once_num;
+
+ while (nb_pkts > SXE2_RX_PKTS_BURST_BATCH_NUM_VEC) {
+ once_num = sxe2_rx_pkts_scattered_batch_vec_neon((struct sxe2_rx_queue *)rx_queue,
+ rx_pkts + done_num,
+ SXE2_RX_PKTS_BURST_BATCH_NUM_VEC,
+ false);
+
+ done_num += once_num;
+ nb_pkts -= once_num;
+
+ if (once_num < SXE2_RX_PKTS_BURST_BATCH_NUM_VEC)
+ goto l_end;
+ }
+
+ done_num += sxe2_rx_pkts_scattered_batch_vec_neon((struct sxe2_rx_queue *)rx_queue,
+ rx_pkts + done_num,
+ nb_pkts,
+ false);
+l_end:
+ return done_num;
+}
+#endif
--
2.52.0
^ permalink raw reply related
* [PATCH v2 14/20] net/sxe2: implement get monitor address
From: liujie5 @ 2026-06-14 9:23 UTC (permalink / raw)
To: stephen; +Cc: dev, Jie Liu
In-Reply-To: <20260614092328.201826-1-liujie5@linkdatatechnology.com>
From: Jie Liu <liujie5@linkdatatechnology.com>
This patch implements the 'get_monitor_addr' ethdev ops in the sxe2
PMD. This interface allows the Ethernet device to provide the
address of the next expected Rx descriptor to the power management
library.
The implementation calculates the address of the next Rx descriptor
based on the receive queue's current hardware ring position and
descriptor size. Applications can then use this address with
rte_power_monitor() to put the CPU into a low-power state until
new packets are written to the descriptor by the hardware.
Signed-off-by: Jie Liu <liujie5@linkdatatechnology.com>
---
drivers/net/sxe2/sxe2_ethdev.c | 2 ++
drivers/net/sxe2/sxe2_rx.c | 21 +++++++++++++++++++++
drivers/net/sxe2/sxe2_rx.h | 2 ++
3 files changed, 25 insertions(+)
diff --git a/drivers/net/sxe2/sxe2_ethdev.c b/drivers/net/sxe2/sxe2_ethdev.c
index 9a669f26f3..e94d10210a 100644
--- a/drivers/net/sxe2/sxe2_ethdev.c
+++ b/drivers/net/sxe2/sxe2_ethdev.c
@@ -186,6 +186,8 @@ static const struct eth_dev_ops sxe2_eth_dev_ops = {
.queue_stats_mapping_set = sxe2_queue_stats_mapping_set,
.fw_version_get = sxe2_fw_version_string_get,
+
+ .get_monitor_addr = sxe2_get_monitor_addr,
};
static int32_t sxe2_dev_configure(struct rte_eth_dev *dev)
diff --git a/drivers/net/sxe2/sxe2_rx.c b/drivers/net/sxe2/sxe2_rx.c
index 007192c7d8..79e65cfbf1 100644
--- a/drivers/net/sxe2/sxe2_rx.c
+++ b/drivers/net/sxe2/sxe2_rx.c
@@ -557,3 +557,24 @@ void __rte_cold sxe2_rxqs_all_stop(struct rte_eth_dev *dev)
}
}
}
+
+static int32_t sxe2_monitor_callback(const uint64_t value,
+ const uint64_t arg[RTE_POWER_MONITOR_OPAQUE_SZ] __rte_unused)
+{
+ const uint64_t dd_state = rte_cpu_to_le_64(SXE2_RX_DESC_STATUS_DD_MASK);
+ return (value & dd_state) == dd_state ? -1 : 0;
+}
+
+int32_t sxe2_get_monitor_addr(void *rx_queue, struct rte_power_monitor_cond *pmc)
+{
+ volatile union sxe2_rx_desc *rxdp;
+ struct sxe2_rx_queue *rxq = (struct sxe2_rx_queue *)rx_queue;
+
+ rxdp = &rxq->desc_ring[rxq->processing_idx];
+
+ pmc->addr = &rxdp->wb.status_err_ptype_len;
+ pmc->fn = sxe2_monitor_callback;
+ pmc->size = sizeof(uint16_t);
+
+ return 0;
+}
diff --git a/drivers/net/sxe2/sxe2_rx.h b/drivers/net/sxe2/sxe2_rx.h
index 295d9005e0..c2582bc571 100644
--- a/drivers/net/sxe2/sxe2_rx.h
+++ b/drivers/net/sxe2/sxe2_rx.h
@@ -29,4 +29,6 @@ int32_t __rte_cold sxe2_rxqs_all_start(struct rte_eth_dev *dev);
void __rte_cold sxe2_rxqs_all_stop(struct rte_eth_dev *dev);
+int32_t sxe2_get_monitor_addr(void *rx_queue, struct rte_power_monitor_cond *pmc);
+
#endif /* SXE2_RX_H */
--
2.52.0
^ permalink raw reply related
* [PATCH v2 12/20] net/sxe2: add support for custom UDP tunnel ports
From: liujie5 @ 2026-06-14 9:23 UTC (permalink / raw)
To: stephen; +Cc: dev, Jie Liu
In-Reply-To: <20260614092328.201826-1-liujie5@linkdatatechnology.com>
From: Jie Liu <liujie5@linkdatatechnology.com>
This patch enables the configuration of custom UDP port numbers for
tunneling protocols in the SXE2 PMD.
The change includes:
- Adding a new entry in the tunnel port lookup table.
- Updating the hardware profile to recognize
the custom UDP port as a tunnel type.
- Enabling inner header parsing for packets arriving on these ports.
This allows the Switch module to correctly apply recipes based on
inner packet fields (e.g., inner MAC or IP).
Signed-off-by: Jie Liu <liujie5@linkdatatechnology.com>
---
drivers/net/sxe2/sxe2_cmd_chnl.c | 96 ++++++++++
drivers/net/sxe2/sxe2_cmd_chnl.h | 17 ++
drivers/net/sxe2/sxe2_drv_cmd.h | 16 ++
drivers/net/sxe2/sxe2_ethdev.c | 200 ++++++++++++++++++++-
drivers/net/sxe2/sxe2_ethdev.h | 9 +
drivers/net/sxe2/sxe2_flow.c | 54 ++++++
drivers/net/sxe2/sxe2_flow.h | 3 +-
drivers/net/sxe2/sxe2_flow_define.h | 1 +
drivers/net/sxe2/sxe2_flow_parse_pattern.c | 113 ++++++++++++
drivers/net/sxe2/sxe2_flow_parse_pattern.h | 6 +
drivers/net/sxe2/sxe2_txrx_poll.c | 46 ++++-
11 files changed, 557 insertions(+), 4 deletions(-)
diff --git a/drivers/net/sxe2/sxe2_cmd_chnl.c b/drivers/net/sxe2/sxe2_cmd_chnl.c
index 6e2dd139a5..926eaee062 100644
--- a/drivers/net/sxe2/sxe2_cmd_chnl.c
+++ b/drivers/net/sxe2/sxe2_cmd_chnl.c
@@ -1455,6 +1455,102 @@ int32_t sxe2_drv_ipsec_txsa_delete(struct sxe2_adapter *adapter,
return ret;
}
+int32_t sxe2_drv_udp_tunnel_add(struct sxe2_adapter *adapter,
+ enum sxe2_udp_tunnel_protocol tunnel_proto,
+ uint16_t udp_port)
+{
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_udp_tunnel_req req = {};
+ struct sxe2_drv_cmd_params cmd = {};
+ int32_t ret = -1;
+
+ req.type = tunnel_proto;
+ req.port = udp_port;
+ sxe2_drv_cmd_params_fill(adapter, &cmd, SXE2_DRV_CMD_UDPTUNNEL_ADD,
+ &req, sizeof(req),
+ NULL, 0);
+ ret = sxe2_drv_cmd_exec(cdev, &cmd);
+ if (ret)
+ PMD_LOG_ERR(DRV, "Failed to add udp proto %d port %d, ret=%d",
+ tunnel_proto, udp_port, ret);
+
+ return ret;
+}
+
+int32_t sxe2_drv_udp_tunnel_del(struct sxe2_adapter *adapter,
+ enum sxe2_udp_tunnel_protocol tunnel_proto,
+ uint16_t udp_port)
+{
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_udp_tunnel_req req = {};
+ struct sxe2_drv_cmd_params cmd = {};
+ int32_t ret = -1;
+
+ req.type = tunnel_proto;
+ req.port = udp_port;
+ sxe2_drv_cmd_params_fill(adapter, &cmd, SXE2_DRV_CMD_UDPTUNNEL_DEL,
+ &req, sizeof(req),
+ NULL, 0);
+ ret = sxe2_drv_cmd_exec(cdev, &cmd);
+ if (ret)
+ PMD_LOG_ERR(DRV, "Failed to del udp proto %d port %d, ret=%d",
+ tunnel_proto, udp_port, ret);
+
+ return ret;
+}
+
+int32_t sxe2_drv_get_udp_tunnel_port(struct sxe2_adapter *adapter,
+ enum sxe2_flow_udp_tunnel_protocol proto,
+ uint16_t *port)
+{
+ int32_t ret = 0;
+ static const uint16_t flow_proto_to_udp_tunnel_proto[SXE2_FLOW_UDP_TUNNEL_MAX] = {
+ [SXE2_FLOW_UDP_TUNNEL_PROTOCOL_VXLAN] = SXE2_UDP_TUNNEL_PROTOCOL_VXLAN,
+ [SXE2_FLOW_UDP_TUNNEL_PROTOCOL_VXLAN_GPE] = SXE2_UDP_TUNNEL_PROTOCOL_VXLAN_GPE,
+ [SXE2_FLOW_UDP_TUNNEL_PROTOCOL_GENEVE] = SXE2_UDP_TUNNEL_PROTOCOL_GENEVE,
+ [SXE2_FLOW_UDP_TUNNEL_PROTOCOL_GTP_U] = SXE2_UDP_TUNNEL_PROTOCOL_GTP_U,
+ [SXE2_FLOW_UDP_TUNNEL_PROTOCOL_NVGRE] = SXE2_UDP_TUNNEL_PROTOCOL_NVGRE,
+ };
+ struct sxe2_udp_tunnel_cfg tunnel_config = {};
+
+ tunnel_config.protocol = flow_proto_to_udp_tunnel_proto[proto];
+ ret = sxe2_drv_udp_tunnel_get(adapter, &tunnel_config);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to get udp tunnel port, ret=%d", ret);
+ goto l_end;
+ }
+
+ *port = tunnel_config.fw_port;
+l_end:
+ return ret;
+}
+
+int32_t sxe2_drv_udp_tunnel_get(struct sxe2_adapter *adapter,
+ struct sxe2_udp_tunnel_cfg *tunnel_config)
+{
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_udp_tunnel_req req = {};
+ struct sxe2_drv_udp_tunnel_resp resp = {};
+ struct sxe2_drv_cmd_params cmd = {};
+ int32_t ret = -1;
+
+ req.type = tunnel_config->protocol;
+ sxe2_drv_cmd_params_fill(adapter, &cmd, SXE2_DRV_CMD_UDPTUNNEL_GET,
+ &req, sizeof(req),
+ &resp, sizeof(resp));
+ ret = sxe2_drv_cmd_exec(cdev, &cmd);
+ if (ret)
+ PMD_LOG_ERR(DRV, "Failed to get udp proto %d port, ret=%d", req.type, ret);
+
+ tunnel_config->fw_port = resp.port;
+ tunnel_config->fw_status = resp.enable;
+ tunnel_config->fw_dst_en = resp.dst;
+ tunnel_config->fw_src_en = resp.src;
+ tunnel_config->fw_used = resp.fw_used;
+
+ return ret;
+}
+
int32_t sxe2_drv_queue_info_get_update(struct sxe2_adapter *adapter, struct eth_queue_stats *qstats)
{
struct sxe2_drv_cmd_params param = {0};
diff --git a/drivers/net/sxe2/sxe2_cmd_chnl.h b/drivers/net/sxe2/sxe2_cmd_chnl.h
index 52cd9922ad..97007c7cfa 100644
--- a/drivers/net/sxe2/sxe2_cmd_chnl.h
+++ b/drivers/net/sxe2/sxe2_cmd_chnl.h
@@ -67,6 +67,23 @@ int32_t sxe2_drv_ipsec_txsa_delete(struct sxe2_adapter *adapter,
int32_t sxe2_drv_promisc_config(struct sxe2_adapter *adapter, bool set);
+int32_t sxe2_drv_udp_tunnel_add(struct sxe2_adapter *adapter,
+ enum sxe2_udp_tunnel_protocol tunnel_proto,
+ uint16_t udp_port);
+
+int32_t sxe2_drv_udp_tunnel_del(struct sxe2_adapter *adapter,
+ enum sxe2_udp_tunnel_protocol tunnel_proto,
+ uint16_t udp_port);
+
+int32_t sxe2_drv_udp_tunnel_get(struct sxe2_adapter *adapter,
+ struct sxe2_udp_tunnel_cfg *tunnel_config);
+
+int32_t sxe2_drv_get_udp_tunnel_port(struct sxe2_adapter *adapter,
+ enum sxe2_flow_udp_tunnel_protocol proto,
+ uint16_t *port);
+
+int32_t sxe2_drv_vsi_info_get(struct sxe2_adapter *adapter, struct sxe2_vsi *vsi);
+
int32_t sxe2_drv_vsi_info_get(struct sxe2_adapter *adapter, struct sxe2_vsi *vsi);
int32_t sxe2_drv_mac_link_status_get(struct sxe2_adapter *adapter);
diff --git a/drivers/net/sxe2/sxe2_drv_cmd.h b/drivers/net/sxe2/sxe2_drv_cmd.h
index 38eb2d5cac..f7acd20642 100644
--- a/drivers/net/sxe2/sxe2_drv_cmd.h
+++ b/drivers/net/sxe2/sxe2_drv_cmd.h
@@ -617,6 +617,22 @@ struct __rte_aligned(4) __rte_packed_begin sxe2_drv_flow_fnav_query_stat_resp {
uint64_t stat_bytes;
} __rte_packed_end;
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_udp_tunnel_req {
+ uint8_t type;
+ uint8_t rsv;
+ uint16_t port;
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_udp_tunnel_resp {
+ uint8_t type;
+ uint8_t enable;
+ uint8_t dst;
+ uint8_t src;
+ uint16_t port;
+ uint8_t fw_used;
+ uint8_t rsv;
+} __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 3f892345bb..48973409d2 100644
--- a/drivers/net/sxe2/sxe2_ethdev.c
+++ b/drivers/net/sxe2/sxe2_ethdev.c
@@ -40,10 +40,11 @@
#include "sxe2_ioctl_chnl_func.h"
#include "sxe2_ethdev_repr.h"
#include "sxe2vf_regs.h"
+#include "sxe2_switchdev.h"
#define SXE2_PCI_VENDOR_ID_1 0x1ff2
#define SXE2_PCI_DEVICE_ID_PF_1 0x10b1
-#define SXE2_PCI_DEVICE_ID_VF_1 0x10b2
+#define SXE2_PCI_DEVICE_ID_VF_1 0x10b
#define SXE2_PCI_VENDOR_ID_2 0x1d94
#define SXE2_PCI_DEVICE_ID_PF_2 0x1260
@@ -117,6 +118,11 @@ static int32_t sxe2_dev_close(struct rte_eth_dev *dev);
static int32_t sxe2_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info);
static const uint32_t *sxe2_buffer_split_supported_hdr_ptypes_get(struct rte_eth_dev *dev
__rte_unused, size_t *no_of_elements __rte_unused);
+static int32_t sxe2_udp_tunnel_port_add(struct rte_eth_dev *dev,
+ struct rte_eth_udp_tunnel *tunnel_udp);
+static int32_t sxe2_udp_tunnel_port_del(struct rte_eth_dev *dev,
+ struct rte_eth_udp_tunnel *tunnel_udp);
+
static const struct eth_dev_ops sxe2_eth_dev_ops = {
.dev_configure = sxe2_dev_configure,
@@ -164,6 +170,9 @@ static const struct eth_dev_ops sxe2_eth_dev_ops = {
.rss_hash_update = sxe2_dev_rss_hash_update,
.rss_hash_conf_get = sxe2_dev_rss_hash_conf_get,
+ .udp_tunnel_port_add = sxe2_udp_tunnel_port_add,
+ .udp_tunnel_port_del = sxe2_udp_tunnel_port_del,
+
.flow_ops_get = sxe2_flow_ops_get,
.tm_ops_get = sxe2_tm_ops_get,
@@ -228,6 +237,12 @@ static int32_t sxe2_dev_start(struct rte_eth_dev *dev)
struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
PMD_INIT_FUNC_TRACE();
+ ret = sxe2_flow_init_udp_tunnel_port(dev);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "Failed to init udp tunnel port, ret: %d.", ret);
+ goto l_end;
+ }
+
ret = sxe2_queues_init(dev);
if (ret) {
PMD_LOG_ERR(INIT, "Failed to init queues.");
@@ -273,6 +288,182 @@ static int32_t sxe2_dev_start(struct rte_eth_dev *dev)
return ret;
}
+static enum sxe2_udp_tunnel_protocol
+sxe2_udp_tunnel_type_rte_to_sxe2(enum rte_eth_tunnel_type rte_type)
+{
+ static enum sxe2_udp_tunnel_protocol sxe2_udp_proto_map[RTE_ETH_TUNNEL_TYPE_MAX] = {
+ [RTE_ETH_TUNNEL_TYPE_NONE] = SXE2_UDP_TUNNEL_MAX,
+ [RTE_ETH_TUNNEL_TYPE_VXLAN] = SXE2_UDP_TUNNEL_PROTOCOL_VXLAN,
+ [RTE_ETH_TUNNEL_TYPE_GENEVE] = SXE2_UDP_TUNNEL_PROTOCOL_GENEVE,
+ [RTE_ETH_TUNNEL_TYPE_TEREDO] = SXE2_UDP_TUNNEL_PROTOCOL_TEREDO,
+ [RTE_ETH_TUNNEL_TYPE_NVGRE] = SXE2_UDP_TUNNEL_PROTOCOL_NVGRE,
+ [RTE_ETH_TUNNEL_TYPE_IP_IN_GRE] = SXE2_UDP_TUNNEL_MAX,
+ [RTE_ETH_L2_TUNNEL_TYPE_E_TAG] = SXE2_UDP_TUNNEL_MAX,
+ [RTE_ETH_TUNNEL_TYPE_VXLAN_GPE] = SXE2_UDP_TUNNEL_PROTOCOL_VXLAN_GPE,
+ [RTE_ETH_TUNNEL_TYPE_ECPRI] = SXE2_UDP_TUNNEL_PROTOCOL_ECPRI
+ };
+
+ if (rte_type >= RTE_ETH_TUNNEL_TYPE_MAX) {
+ PMD_LOG_ERR(DRV, "Invalid rte_eth_tunnel_type %d!", rte_type);
+ rte_type = RTE_ETH_TUNNEL_TYPE_NONE;
+ }
+
+ return sxe2_udp_proto_map[rte_type];
+}
+
+int32_t sxe2_udp_tunnel_port_add_common(struct sxe2_adapter *ad,
+ enum sxe2_udp_tunnel_protocol tunnel_proto,
+ uint16_t udp_port)
+{
+ struct sxe2_udp_tunnel_cfg *tunnel_config;
+ int32_t ret = -1;
+
+ rte_spinlock_lock(&ad->udp_tunnel_ctx.lock);
+
+ tunnel_config = &ad->udp_tunnel_ctx.tunnel_conf[tunnel_proto];
+
+ if (tunnel_config->dev_status == SXE2_UDP_TUNNEL_ENABLE) {
+ if (udp_port == tunnel_config->dev_port &&
+ tunnel_config->dev_ref_cnt < 0xFFFFU) {
+ tunnel_config->dev_ref_cnt++;
+ ret = 0;
+ goto l_unlock_end;
+ } else {
+ PMD_LOG_ERR(DRV, "Adding multiple ports to the same protocol "
+ "is not supported!");
+ ret = -EINVAL;
+ goto l_unlock_end;
+ }
+ } else {
+ ret = sxe2_drv_udp_tunnel_add(ad, tunnel_proto, udp_port);
+ if (ret != 0)
+ goto l_unlock_end;
+
+ tunnel_config->protocol = tunnel_proto;
+ tunnel_config->dev_port = udp_port;
+ tunnel_config->dev_status = SXE2_UDP_TUNNEL_ENABLE;
+ tunnel_config->dev_ref_cnt++;
+ }
+
+l_unlock_end:
+ rte_spinlock_unlock(&ad->udp_tunnel_ctx.lock);
+ return ret;
+}
+
+int32_t sxe2_udp_tunnel_port_del_common(struct sxe2_adapter *ad,
+ enum sxe2_udp_tunnel_protocol tunnel_proto,
+ uint16_t udp_port)
+{
+ struct sxe2_udp_tunnel_cfg *tunnel_config;
+ int32_t ret = -1;
+
+ rte_spinlock_lock(&ad->udp_tunnel_ctx.lock);
+ tunnel_config = &ad->udp_tunnel_ctx.tunnel_conf[tunnel_proto];
+
+ if (tunnel_config->dev_status == SXE2_UDP_TUNNEL_ENABLE &&
+ udp_port == tunnel_config->dev_port) {
+ if (tunnel_config->dev_ref_cnt > 1) {
+ tunnel_config->dev_ref_cnt--;
+ ret = 0;
+ goto l_unlock_end;
+ } else {
+ ret = sxe2_drv_udp_tunnel_del(ad, tunnel_proto, udp_port);
+ if (ret != 0)
+ goto l_unlock_end;
+
+ tunnel_config->dev_status = SXE2_UDP_TUNNEL_DISABLE;
+ tunnel_config->dev_ref_cnt = 0;
+ }
+ goto l_unlock_end;
+ }
+
+ ret = -EINVAL;
+
+l_unlock_end:
+ rte_spinlock_unlock(&ad->udp_tunnel_ctx.lock);
+ return ret;
+}
+
+static int32_t sxe2_udp_tunnel_port_clear(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *ad = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_udp_tunnel_cfg *tunnel_config;
+ int32_t ret = 0;
+ uint16_t tunnel_proto = 0;
+
+ rte_spinlock_lock(&ad->udp_tunnel_ctx.lock);
+
+ for (tunnel_proto = 0; tunnel_proto < SXE2_UDP_TUNNEL_MAX; tunnel_proto++) {
+ tunnel_config = &ad->udp_tunnel_ctx.tunnel_conf[tunnel_proto];
+ if (tunnel_config->dev_status == SXE2_UDP_TUNNEL_ENABLE) {
+ ret = sxe2_drv_udp_tunnel_del(ad, tunnel_config->protocol,
+ tunnel_config->dev_port);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "Failed to delete udp tunnel port %d, proto %d",
+ tunnel_config->dev_port, tunnel_config->protocol);
+ goto l_unlock_end;
+ }
+
+ tunnel_config->dev_status = SXE2_UDP_TUNNEL_DISABLE;
+ tunnel_config->dev_ref_cnt = 0;
+ }
+ }
+l_unlock_end:
+ rte_spinlock_unlock(&ad->udp_tunnel_ctx.lock);
+ return ret;
+}
+
+static int32_t sxe2_udp_tunnel_port_add(struct rte_eth_dev *dev,
+ struct rte_eth_udp_tunnel *tunnel_udp)
+{
+ int32_t ret = 0;
+ enum sxe2_udp_tunnel_protocol tunnel_proto;
+ struct sxe2_adapter *ad = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+
+ if (tunnel_udp->udp_port == 0) {
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ tunnel_proto = sxe2_udp_tunnel_type_rte_to_sxe2(tunnel_udp->prot_type);
+ if (tunnel_proto >= SXE2_UDP_TUNNEL_MAX) {
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ ret = sxe2_udp_tunnel_port_add_common(ad, tunnel_proto, tunnel_udp->udp_port);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "Add tunnel port failed, ret = %d", ret);
+ goto l_end;
+ }
+
+l_end:
+ return ret;
+}
+
+static int32_t sxe2_udp_tunnel_port_del(struct rte_eth_dev *dev,
+ struct rte_eth_udp_tunnel *tunnel_udp)
+{
+ int32_t ret = 0;
+ enum sxe2_udp_tunnel_protocol tunnel_proto;
+ struct sxe2_adapter *ad = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+
+ tunnel_proto = sxe2_udp_tunnel_type_rte_to_sxe2(tunnel_udp->prot_type);
+ if (tunnel_proto >= SXE2_UDP_TUNNEL_MAX) {
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ ret = sxe2_udp_tunnel_port_del_common(ad, tunnel_proto, tunnel_udp->udp_port);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "Delete tunnel port failed, ret = %d", ret);
+ goto l_end;
+ }
+
+l_end:
+ return ret;
+}
+
static int32_t sxe2_dev_infos_get(struct rte_eth_dev *dev,
struct rte_eth_dev_info *dev_info)
{
@@ -1320,15 +1511,20 @@ static int32_t sxe2_dev_close(struct rte_eth_dev *dev)
(void)sxe2_dev_stop(dev);
(void)sxe2_queues_release(dev);
sxe2_mp_uninit(dev);
- (void)sxe2_rss_disable(dev);
(void)sxe2_sched_uinit(dev);
+ (void)sxe2_rss_disable(dev);
+ (void)sxe2_flow_uninit(dev);
+ (void)sxe2_udp_tunnel_port_clear(dev);
sxe2_vsi_uninit(dev);
sxe2_security_uinit(dev);
sxe2_intr_uninit(dev);
(void)sxe2_switchdev_uninit(dev);
sxe2_sw_uninit(dev);
+ (void)sxe2_switchdev_uninit(dev);
+ sxe2_dev_pci_map_uinit(dev);
sxe2_eth_uinit(dev);
sxe2_dev_pci_map_uinit(dev);
+ sxe2_free_repr_info(dev);
l_end:
return 0;
diff --git a/drivers/net/sxe2/sxe2_ethdev.h b/drivers/net/sxe2/sxe2_ethdev.h
index 756924ca0a..76cd3bc9e0 100644
--- a/drivers/net/sxe2/sxe2_ethdev.h
+++ b/drivers/net/sxe2/sxe2_ethdev.h
@@ -319,6 +319,7 @@ struct sxe2_adapter {
struct sxe2_sched_hw_cap sched_ctxt;
struct sxe2_tm_context tm_ctxt;
struct sxe2_devargs devargs;
+ struct sxe2_udp_tunnel_ctx udp_tunnel_ctx;
struct sxe2_security_ctx security_ctx;
struct sxe2_repr_context repr_ctxt;
struct sxe2_switchdev_info switchdev_info;
@@ -371,6 +372,14 @@ void sxe2_dev_pci_seg_unmap(struct sxe2_adapter *adapter, uint32_t res_type);
int32_t sxe2_dev_pci_map_init(struct rte_eth_dev *dev);
+void sxe2_dev_pci_seg_unmap(struct sxe2_adapter *adapter, uint32_t res_type);
+
+int32_t sxe2_udp_tunnel_port_del_common(struct sxe2_adapter *ad,
+ enum sxe2_udp_tunnel_protocol tunnel_proto, uint16_t udp_port);
+
+int32_t sxe2_udp_tunnel_port_add_common(struct sxe2_adapter *ad,
+ enum sxe2_udp_tunnel_protocol tunnel_proto, uint16_t udp_port);
+
void sxe2_dev_pci_map_uinit(struct rte_eth_dev *dev);
void sxe2_eth_uinit(struct rte_eth_dev *dev);
diff --git a/drivers/net/sxe2/sxe2_flow.c b/drivers/net/sxe2/sxe2_flow.c
index 6999cb0725..63cfc36968 100644
--- a/drivers/net/sxe2/sxe2_flow.c
+++ b/drivers/net/sxe2/sxe2_flow.c
@@ -523,6 +523,51 @@ static int32_t sxe2_flow_adjust_action(struct rte_eth_dev *dev __rte_unused,
return ret;
}
+int32_t sxe2_flow_init_udp_tunnel_port(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret = 0;
+ uint16_t i = 0;
+ uint16_t *flow_udp_tunnel_port = NULL;
+
+ memset(adapter->flow_ctxt.tunnel_port_list, 0,
+ sizeof(adapter->flow_ctxt.tunnel_port_list));
+
+ flow_udp_tunnel_port = adapter->flow_ctxt.tunnel_port_list;
+ for (i = 0; i < SXE2_FLOW_UDP_TUNNEL_MAX; i++) {
+ if (flow_udp_tunnel_port[i] == 0) {
+ ret = sxe2_drv_get_udp_tunnel_port(adapter, i,
+ &flow_udp_tunnel_port[i]);
+ if (ret != 0) {
+ PMD_LOG_ERR(DRV, "Failed to get udp tunnel port, proto: %d,"
+ "ret: %d", i, ret);
+ goto l_end;
+ }
+ }
+ }
+
+l_end:
+ return ret;
+}
+
+static int32_t sxe2_flowlist_add_tunnel_port(struct rte_eth_dev *dev,
+ struct rte_flow *flow_list,
+ struct rte_flow_error *error)
+{
+ struct sxe2_flow_list_t *sxe2_flow_list = &flow_list->sxe2_flow_list;
+ struct sxe2_flow *flow = TAILQ_FIRST(sxe2_flow_list);
+ enum sxe2_flow_tunnel_type tunnel_type = flow->meta.tunnel_type;
+ DECLARE_BITMAP(flow_type, SXE2_EXPANSION_MAX);
+ sxe2_bitmap_zero(flow_type, SXE2_EXPANSION_MAX);
+ sxe2_bitmap_copy(flow_type, flow->flow_type, SXE2_EXPANSION_MAX);
+ int32_t ret = 0;
+
+ if (flow->engine_type == SXE2_FLOW_ENGINE_FNAV)
+ return sxe2_flow_add_tunnel_port(dev, error, flow, flow_type, tunnel_type);
+
+ return ret;
+}
+
static int32_t sxe2_flow_check_item_empty(uint8_t *item, uint16_t size)
{
uint16_t i = 0;
@@ -679,6 +724,10 @@ static int32_t sxe2_flow_post_proc(struct rte_eth_dev *dev,
{
int32_t ret = 0;
+ ret = sxe2_flowlist_add_tunnel_port(dev, flow_list, error);
+ if (ret)
+ goto l_end;
+
ret = sxe2_flowlist_add_proto_type(dev, flow_list, error);
if (ret)
goto l_end;
@@ -1308,6 +1357,11 @@ int32_t sxe2_flow_init(struct rte_eth_dev *dev)
adapter->flow_ctxt.fnav_inited = 1;
rte_spinlock_init(&adapter->flow_ctxt.flow_list_lock);
+
+ ret = sxe2_flow_init_udp_tunnel_port(dev);
+ if (ret)
+ PMD_LOG_ERR(DRV, "Failed to init udp tunnel port, ret: %d.", ret);
+
return ret;
}
diff --git a/drivers/net/sxe2/sxe2_flow.h b/drivers/net/sxe2/sxe2_flow.h
index 9970fddcf0..daaeedd4dc 100644
--- a/drivers/net/sxe2/sxe2_flow.h
+++ b/drivers/net/sxe2/sxe2_flow.h
@@ -8,7 +8,6 @@
#include "sxe2_osal.h"
#include "sxe2_common.h"
-
int32_t sxe2_flow_ops_get(struct rte_eth_dev *dev, const struct rte_flow_ops **ops);
int32_t sxe2_flow_init(struct rte_eth_dev *dev);
@@ -26,4 +25,6 @@ int32_t sxe2_flow_query_mgr(struct sxe2_adapter *adapter,
struct sxe2_flow *flow,
struct sxe2_fnav_cid_mgr **mgr_ptr,
struct rte_flow_error *error);
+
+int32_t sxe2_flow_init_udp_tunnel_port(struct rte_eth_dev *dev);
#endif /* __SXE2_FLOW_H__ */
diff --git a/drivers/net/sxe2/sxe2_flow_define.h b/drivers/net/sxe2/sxe2_flow_define.h
index d2f6000efa..263a573f04 100644
--- a/drivers/net/sxe2/sxe2_flow_define.h
+++ b/drivers/net/sxe2/sxe2_flow_define.h
@@ -119,6 +119,7 @@ struct sxe2_flow_context {
struct rte_flow_list_t rte_flow_list;
rte_spinlock_t flow_list_lock;
struct sxe2_fnav_count_resource hw_res;
+ uint16_t tunnel_port_list[SXE2_FLOW_UDP_TUNNEL_MAX];
uint32_t fnav_inited;
};
#define SXE2_INVALID_RSS_ATTR \
diff --git a/drivers/net/sxe2/sxe2_flow_parse_pattern.c b/drivers/net/sxe2/sxe2_flow_parse_pattern.c
index 189abb1a33..f5bf8922c6 100644
--- a/drivers/net/sxe2/sxe2_flow_parse_pattern.c
+++ b/drivers/net/sxe2/sxe2_flow_parse_pattern.c
@@ -1637,6 +1637,119 @@ static int32_t sxe2_flow_parse_pattern_vxlan_gpe(const struct rte_flow_item *ite
return ret;
}
+static int32_t sxe2_flow_parse_pattern_ipip(struct sxe2_flow *flow, BITMAP_TYPE *flow_type)
+{
+ sxe2_set_bit(SXE2_EXPANSION_IPIP, flow_type);
+ if (sxe2_test_bit(SXE2_EXPANSION_OUTER_IPV4, flow_type)) {
+ sxe2_set_bit(SXE2_FLOW_FLD_ID_IPV4_PROT, flow->pattern_outer.map_spec);
+ if (sxe2_test_bit(SXE2_EXPANSION_IPV4, flow_type))
+ flow->pattern_outer.item_spec.ipv4.protocol = SXE2_FLOW_IP_PROTOCOL_IPV4;
+ if (sxe2_test_bit(SXE2_EXPANSION_IPV6, flow_type))
+ flow->pattern_outer.item_spec.ipv4.protocol = SXE2_FLOW_IP_PROTOCOL_IPV6;
+ }
+ if (sxe2_test_bit(SXE2_EXPANSION_OUTER_IPV6, flow_type)) {
+ sxe2_set_bit(SXE2_FLOW_FLD_ID_IPV6_PROT, flow->pattern_outer.map_spec);
+ if (sxe2_test_bit(SXE2_EXPANSION_ETH, flow_type)) {
+ flow->pattern_outer.item_spec.ipv6.nexthdr = SXE2_FLOW_IP_PROTOCOL_ETH;
+ } else {
+ if (sxe2_test_bit(SXE2_EXPANSION_IPV4, flow_type))
+ flow->pattern_outer.item_spec.ipv6.nexthdr =
+ SXE2_FLOW_IP_PROTOCOL_IPV4;
+ if (sxe2_test_bit(SXE2_EXPANSION_IPV6, flow_type))
+ flow->pattern_outer.item_spec.ipv6.nexthdr =
+ SXE2_FLOW_IP_PROTOCOL_IPV6;
+ }
+ }
+ return 0;
+}
+
+static int32_t sxe2_flow_add_udp_tunnel_port(struct sxe2_adapter *adapter,
+ enum sxe2_flow_udp_tunnel_protocol proto,
+ struct sxe2_flow *flow,
+ BITMAP_TYPE *flow_type)
+{
+ int32_t ret = 0;
+ uint16_t tun_port;
+
+ tun_port = adapter->flow_ctxt.tunnel_port_list[proto];
+ if (tun_port == 0xffff || tun_port == 0) {
+ ret = -EINVAL;
+ PMD_LOG_ERR(DRV, "UDP tunnel port not initialized, proto: %d", proto);
+ goto l_end;
+ }
+ if (!sxe2_test_bit(SXE2_EXPANSION_OUTER_UDP, flow_type)) {
+ ret = -EINVAL;
+ PMD_LOG_ERR(DRV, "UDP must be over tunnel");
+ goto l_end;
+ }
+ sxe2_set_bit(SXE2_FLOW_FLD_ID_UDP_DST_PORT, flow->pattern_outer.map_spec);
+ flow->pattern_outer.item_spec.udp.dest = rte_cpu_to_be_16(tun_port);
+l_end:
+ return ret;
+}
+
+int32_t sxe2_flow_add_tunnel_port(struct rte_eth_dev *dev,
+ struct rte_flow_error *error,
+ struct sxe2_flow *flow, BITMAP_TYPE *flow_type,
+ enum sxe2_flow_tunnel_type tunnel_type)
+{
+ int32_t ret = 0;
+ enum sxe2_flow_udp_tunnel_protocol proto = SXE2_FLOW_UDP_TUNNEL_MAX;
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_flow_pattern *pattern = &flow->pattern_outer;
+ switch (tunnel_type) {
+ case SXE2_FLOW_TUNNEL_TYPE_VXLAN:
+ if (sxe2_test_bit(SXE2_EXPANSION_ETH, flow_type)) {
+ proto = SXE2_FLOW_UDP_TUNNEL_PROTOCOL_VXLAN;
+ } else if (sxe2_test_bit(SXE2_EXPANSION_IPV4, flow_type) ||
+ sxe2_test_bit(SXE2_EXPANSION_IPV6, flow_type)) {
+ proto = SXE2_FLOW_UDP_TUNNEL_PROTOCOL_VXLAN_GPE;
+ }
+ break;
+ case SXE2_FLOW_TUNNEL_TYPE_GTPU:
+ proto = SXE2_FLOW_UDP_TUNNEL_PROTOCOL_GTP_U;
+ break;
+ case SXE2_FLOW_TUNNEL_TYPE_GENEVE:
+ proto = SXE2_FLOW_UDP_TUNNEL_PROTOCOL_GENEVE;
+ break;
+ case SXE2_FLOW_TUNNEL_TYPE_GRE:
+ if (sxe2_test_bit(SXE2_EXPANSION_OUTER_UDP, flow_type)) {
+ proto = SXE2_FLOW_UDP_TUNNEL_PROTOCOL_NVGRE;
+ } else {
+ if (sxe2_test_bit(SXE2_EXPANSION_OUTER_IPV4, flow_type)) {
+ pattern->item_spec.ipv4.protocol = SXE2_FLOW_IP_PROTOCOL_GRE;
+ sxe2_set_bit(SXE2_FLOW_FLD_ID_IPV4_PROT, pattern->map_spec);
+ }
+ if (sxe2_test_bit(SXE2_EXPANSION_OUTER_IPV6, flow_type)) {
+ pattern->item_spec.ipv6.nexthdr = SXE2_FLOW_IP_PROTOCOL_GRE;
+ sxe2_set_bit(SXE2_FLOW_FLD_ID_IPV6_PROT, pattern->map_spec);
+ }
+ }
+ break;
+ case SXE2_FLOW_TUNNEL_TYPE_IPIP:
+ ret = sxe2_flow_parse_pattern_ipip(flow, flow_type);
+ break;
+ default:
+ break;
+ }
+ if (proto != SXE2_FLOW_UDP_TUNNEL_MAX) {
+ ret = sxe2_flow_add_udp_tunnel_port(adapter, proto, flow, flow_type);
+ if (ret != 0) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ NULL, "Failed to add udp port for tunnel.");
+ PMD_LOG_ERR(DRV, "Failed to add udp port for tunnel, ret %d.", ret);
+ goto l_end;
+ }
+ }
+ if (tunnel_type != SXE2_FLOW_TUNNEL_TYPE_NONE) {
+ if (!sxe2_test_bit(SXE2_EXPANSION_OUTER_UDP, flow_type))
+ sxe2_set_bit(SXE2_FLOW_HDR_IPV_OTHER, pattern->hdrs);
+ }
+l_end:
+ return ret;
+}
+
struct sxe2_flow_parse_pattern_ops sxe2_flow_parse_pattern_list[] = {
[SXE2_EXPANSION_OUTER_ETH] = {
.is_inner = false,
diff --git a/drivers/net/sxe2/sxe2_flow_parse_pattern.h b/drivers/net/sxe2/sxe2_flow_parse_pattern.h
index 69d83a6ea6..8442c35cae 100644
--- a/drivers/net/sxe2/sxe2_flow_parse_pattern.h
+++ b/drivers/net/sxe2/sxe2_flow_parse_pattern.h
@@ -37,4 +37,10 @@ int32_t sxe2_flow_parse_pattern(struct rte_eth_dev *dev,
struct rte_flow_error *error,
struct sxe2_flow *flow);
+int32_t sxe2_flow_add_tunnel_port(struct rte_eth_dev *dev,
+ struct rte_flow_error *error,
+ struct sxe2_flow *flow,
+ BITMAP_TYPE *flow_type,
+ enum sxe2_flow_tunnel_type tunnel_type);
+
#endif /* SXE2_FLOW_PARSE_PATTERN_H_ */
diff --git a/drivers/net/sxe2/sxe2_txrx_poll.c b/drivers/net/sxe2/sxe2_txrx_poll.c
index f3c4fa0d91..746f9cc2d5 100644
--- a/drivers/net/sxe2/sxe2_txrx_poll.c
+++ b/drivers/net/sxe2/sxe2_txrx_poll.c
@@ -234,6 +234,44 @@ sxe2_tx_pkt_data_desc_count(struct rte_mbuf *tx_pkt)
return count;
}
+static __rte_always_inline void sxe2_tx_desc_tunneling_params_fill(uint64_t offloads,
+ union sxe2_tx_offload_info ol_info,
+ uint32_t *desc_tunneling_params)
+{
+ if (offloads & RTE_MBUF_F_TX_OUTER_IP_CKSUM)
+ *desc_tunneling_params |= SXE2_TX_CTXT_DESC_EIPT_IPV4;
+ else if (offloads & RTE_MBUF_F_TX_OUTER_IPV4)
+ *desc_tunneling_params |= SXE2_TX_CTXT_DESC_EIPT_IPV4_NO_CSUM;
+ else if (offloads & RTE_MBUF_F_TX_OUTER_IPV6)
+ *desc_tunneling_params |= SXE2_TX_CTXT_DESC_EIPT_IPV6;
+
+ *desc_tunneling_params |=
+ SXE2_TX_CTXT_DESC_EIPLEN_VAL(ol_info.outer_l3_len);
+ switch (offloads & RTE_MBUF_F_TX_TUNNEL_MASK) {
+ case RTE_MBUF_F_TX_TUNNEL_IPIP:
+ break;
+ case RTE_MBUF_F_TX_TUNNEL_VXLAN:
+ case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE:
+ case RTE_MBUF_F_TX_TUNNEL_GTP:
+ case RTE_MBUF_F_TX_TUNNEL_GENEVE:
+ *desc_tunneling_params |= SXE2_TX_CTXT_DESC_UDP_TUNNE;
+ break;
+ case RTE_MBUF_F_TX_TUNNEL_GRE:
+ *desc_tunneling_params |= SXE2_TX_CTXT_DESC_GRE_TUNNE;
+ break;
+ default:
+ PMD_LOG_ERR(TX, "Tunnel type [0x%" PRIx64 "] is not supported.",
+ (uint64_t)(offloads & RTE_MBUF_F_TX_TUNNEL_MASK));
+ return;
+ }
+ *desc_tunneling_params |= SXE2_TX_CTXT_DESC_NATLEN_VAL(ol_info.l2_len);
+ if (!(*desc_tunneling_params & SXE2_TX_CTXT_DESC_EIPT_NONE) &&
+ (*desc_tunneling_params & SXE2_TX_CTXT_DESC_UDP_TUNNE) &&
+ (offloads & RTE_MBUF_F_TX_OUTER_UDP_CKSUM)) {
+ *desc_tunneling_params |= SXE2_TX_CTXT_DESC_L4T_CS_MASK;
+ }
+}
+
static __rte_always_inline void
sxe2_tx_desc_checksum_fill(uint64_t offloads, uint32_t *desc_cmd, uint32_t *desc_offset,
union sxe2_tx_offload_info ol_info)
@@ -414,7 +452,13 @@ uint16_t sxe2_tx_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkt
}
}
- desc_offset |= SXE2_TX_DATA_DESC_MACLEN_VAL(ol_info.l2_len);
+ if ((offloads & RTE_MBUF_F_TX_TUNNEL_MASK) && ctxt_desc_num) {
+ desc_offset |= SXE2_TX_DATA_DESC_MACLEN_VAL(ol_info.outer_l2_len);
+ sxe2_tx_desc_tunneling_params_fill(offloads, ol_info,
+ &desc_tunneling_params);
+ } else {
+ desc_offset |= SXE2_TX_DATA_DESC_MACLEN_VAL(ol_info.l2_len);
+ }
if (offloads & SXE2_TX_OFFLOAD_CKSUM_MASK) {
sxe2_tx_desc_checksum_fill(offloads, &desc_cmd,
--
2.52.0
^ permalink raw reply related
* [PATCH v2 09/20] drivers: interrupt handling
From: liujie5 @ 2026-06-14 9:23 UTC (permalink / raw)
To: stephen; +Cc: dev, Jie Liu
In-Reply-To: <20260614092328.201826-1-liujie5@linkdatatechnology.com>
From: Jie Liu <liujie5@linkdatatechnology.com>
This patch includes:
- MSI-X vector allocation and mapping logic.
- Support for rx_queue_intr_enable and rx_queue_intr_disable ops.
- Interrupt handler to process admin and queue events.
- Integration with EAL interrupt framework.
RX queue interrupts allow applications to use rte_eth_dev_rx_intr_wait()
for power-efficient packet processing.
Signed-off-by: Jie Liu <liujie5@linkdatatechnology.com>
---
drivers/common/sxe2/sxe2_ioctl_chnl.c | 176 +++-
drivers/common/sxe2/sxe2_ioctl_chnl_func.h | 18 +
drivers/net/sxe2/meson.build | 1 +
drivers/net/sxe2/sxe2_cmd_chnl.c | 42 +
drivers/net/sxe2/sxe2_cmd_chnl.h | 4 +
drivers/net/sxe2/sxe2_drv_cmd.h | 8 +
drivers/net/sxe2/sxe2_ethdev.c | 93 +-
drivers/net/sxe2/sxe2_ethdev.h | 6 +
drivers/net/sxe2/sxe2_irq.c | 942 +++++++++++++++++++++
drivers/net/sxe2/sxe2_irq.h | 21 +
drivers/net/sxe2/sxe2vf_regs.h | 85 ++
11 files changed, 1393 insertions(+), 3 deletions(-)
create mode 100644 drivers/net/sxe2/sxe2_irq.c
create mode 100644 drivers/net/sxe2/sxe2vf_regs.h
diff --git a/drivers/common/sxe2/sxe2_ioctl_chnl.c b/drivers/common/sxe2/sxe2_ioctl_chnl.c
index 51aea327e5..173d8d57ae 100644
--- a/drivers/common/sxe2/sxe2_ioctl_chnl.c
+++ b/drivers/common/sxe2/sxe2_ioctl_chnl.c
@@ -67,6 +67,7 @@ sxe2_drv_cmd_exec(struct sxe2_common_device *cdev,
return ret;
}
+
RTE_EXPORT_INTERNAL_SYMBOL(sxe2_drv_dev_open)
int32_t
sxe2_drv_dev_open(struct sxe2_common_device *cdev, struct rte_pci_device *pci_dev)
@@ -87,7 +88,7 @@ sxe2_drv_dev_open(struct sxe2_common_device *cdev, struct rte_pci_device *pci_de
if (fd < 0) {
ret = -EBADF;
PMD_LOG_ERR(COM, "Fail to open device:%s, ret=%d, err:%s",
- drv_name, ret, strerror(errno));
+ drv_name, ret, strerror(errno));
goto l_end;
}
@@ -159,6 +160,177 @@ sxe2_drv_dev_handshake(struct sxe2_common_device *cdev)
return ret;
}
+RTE_EXPORT_INTERNAL_SYMBOL(sxe2_drv_dev_rxq_irq_set)
+int32_t
+sxe2_drv_dev_rxq_irq_set(struct sxe2_common_device *cdev,
+ uint16_t base_irq, int32_t *efd, uint16_t nb_irq)
+{
+ struct sxe2_ioctl_irq_set cmd_params;
+ int32_t ret = 0;
+ int32_t cmd_fd = 0;
+
+ if (cdev->config.kernel_reset) {
+ ret = -EPERM;
+ PMD_LOG_WARN(COM, "kernel reset, need restart app.");
+ goto l_end;
+ }
+
+ cmd_fd = SXE2_CDEV_TO_CMD_FD(cdev);
+ if (cmd_fd < 0) {
+ ret = -EBADF;
+ PMD_LOG_ERR(COM, "Failed to exec cmd, fd=%d", cmd_fd);
+ goto l_end;
+ }
+
+ PMD_LOG_DEBUG(COM, "Open fd=%d to set rxq irq, base_queue=%d, efds=%p, nb_irq=%d",
+ cmd_fd, base_irq, efd, nb_irq);
+
+ memset(&cmd_params, 0, sizeof(struct sxe2_ioctl_irq_set));
+ cmd_params.base_irq_in_com = base_irq;
+ cmd_params.cnt = nb_irq;
+ cmd_params.event_fd = efd;
+
+ pthread_mutex_lock(&cdev->config.lock);
+ ret = ioctl(cmd_fd, SXE2_COM_CMD_IO_IRQS_REQ, &cmd_params);
+ if (ret < 0) {
+ PMD_LOG_ERR(COM, "Failed to set io irqs, fd=%d, ret=%d, err:%s",
+ cmd_fd, ret, strerror(errno));
+ pthread_mutex_unlock(&cdev->config.lock);
+ goto l_end;
+ }
+ pthread_mutex_unlock(&cdev->config.lock);
+
+l_end:
+ return ret;
+}
+
+RTE_EXPORT_INTERNAL_SYMBOL(sxe2_drv_dev_other_irq_set)
+int32_t
+sxe2_drv_dev_other_irq_set(struct sxe2_common_device *cdev,
+ int32_t efd, uint64_t event)
+{
+ int32_t ret = 0;
+ int32_t cmd_fd = 0;
+ struct sxe2_ioctl_other_evt_set cmd_params;
+
+ if (cdev->config.kernel_reset) {
+ ret = -EPERM;
+ PMD_LOG_WARN(COM, "kernel reset, need restart app.");
+ goto l_end;
+ }
+
+ cmd_fd = SXE2_CDEV_TO_CMD_FD(cdev);
+ if (cmd_fd < 0) {
+ ret = -EBADF;
+ PMD_LOG_ERR(COM, "Failed to exec cmd, fd=%d", cmd_fd);
+ goto l_end;
+ }
+
+ PMD_LOG_DEBUG(COM, "Open fd=%d to set other irq, efd=%d, event=%"PRIu64"",
+ cmd_fd, efd, event);
+
+ memset(&cmd_params, 0, sizeof(struct sxe2_ioctl_other_evt_set));
+ cmd_params.eventfd = efd;
+ cmd_params.filter_table = event;
+
+ pthread_mutex_lock(&cdev->config.lock);
+ ret = ioctl(cmd_fd, SXE2_COM_CMD_EVT_IRQ_REQ, &cmd_params);
+ if (ret < 0) {
+ PMD_LOG_ERR(COM, "Failed to set others evt, fd=%d, ret=%d, err:%s",
+ cmd_fd, ret, strerror(errno));
+ ret = -EIO;
+ pthread_mutex_unlock(&cdev->config.lock);
+ goto l_end;
+ }
+ pthread_mutex_unlock(&cdev->config.lock);
+
+l_end:
+ return ret;
+}
+
+RTE_EXPORT_INTERNAL_SYMBOL(sxe2_drv_dev_other_irq_get)
+int32_t
+sxe2_drv_dev_other_irq_get(struct sxe2_common_device *cdev, uint64_t *event)
+{
+ int32_t ret = 0;
+ int32_t cmd_fd = 0;
+ struct sxe2_ioctl_other_evt_get cmd_params;
+
+ if (cdev->config.kernel_reset) {
+ ret = -EPERM;
+ PMD_LOG_WARN(COM, "kernel reset, need restart app.");
+ goto l_end;
+ }
+
+ cmd_fd = SXE2_CDEV_TO_CMD_FD(cdev);
+ if (cmd_fd < 0) {
+ ret = -EBADF;
+ PMD_LOG_ERR(COM, "Failed to exec cmd, fd=%d", cmd_fd);
+ goto l_end;
+ }
+
+ PMD_LOG_DEBUG(COM, "Open fd=%d to get other irq", cmd_fd);
+
+ memset(&cmd_params, 0, sizeof(struct sxe2_ioctl_other_evt_get));
+
+ pthread_mutex_lock(&cdev->config.lock);
+ ret = ioctl(cmd_fd, SXE2_COM_CMD_EVT_CAUSE_GET, &cmd_params);
+ if (ret < 0) {
+ PMD_LOG_ERR(COM, "Failed to set others evt, fd=%d, ret=%d, err:%s",
+ cmd_fd, ret, strerror(errno));
+ ret = -EIO;
+ pthread_mutex_unlock(&cdev->config.lock);
+ goto l_end;
+ }
+ pthread_mutex_unlock(&cdev->config.lock);
+ *event = cmd_params.evt_cause;
+
+l_end:
+ return ret;
+}
+
+RTE_EXPORT_INTERNAL_SYMBOL(sxe2_drv_dev_reset_irq_set)
+int32_t
+sxe2_drv_dev_reset_irq_set(struct sxe2_common_device *cdev, int32_t efd)
+{
+ int32_t ret = 0;
+ int32_t cmd_fd = 0;
+ struct sxe2_ioctl_reset_sub_set cmd_params;
+
+ if (cdev->config.kernel_reset) {
+ ret = -EPERM;
+ PMD_LOG_WARN(COM, "kernel reset, need restart app.");
+ goto l_end;
+ }
+
+ cmd_fd = SXE2_CDEV_TO_CMD_FD(cdev);
+ if (cmd_fd < 0) {
+ ret = -EBADF;
+ PMD_LOG_ERR(COM, "Failed to exec cmd, fd=%d", cmd_fd);
+ goto l_end;
+ }
+
+ PMD_LOG_DEBUG(COM, "Open fd=%d to set reset irq, efd=%d",
+ cmd_fd, efd);
+
+ memset(&cmd_params, 0, sizeof(struct sxe2_ioctl_reset_sub_set));
+ cmd_params.eventfd = efd;
+
+ pthread_mutex_lock(&cdev->config.lock);
+ ret = ioctl(cmd_fd, SXE2_COM_CMD_RST_IRQ_REQ, &cmd_params);
+ if (ret < 0) {
+ PMD_LOG_ERR(COM, "Failed to set reset irqs, fd=%d, ret=%d, err:%s",
+ cmd_fd, ret, strerror(errno));
+ ret = -EIO;
+ pthread_mutex_unlock(&cdev->config.lock);
+ goto l_end;
+ }
+ pthread_mutex_unlock(&cdev->config.lock);
+
+l_end:
+ return ret;
+}
+
RTE_EXPORT_INTERNAL_SYMBOL(sxe2_drv_dev_mmap)
void
*sxe2_drv_dev_mmap(struct sxe2_common_device *cdev, uint8_t bar_idx, uint64_t len, uint64_t offset)
@@ -223,7 +395,7 @@ sxe2_drv_dev_munmap(struct sxe2_common_device *cdev, void *virt, uint64_t len)
RTE_EXPORT_INTERNAL_SYMBOL(sxe2_drv_dev_dma_map)
int32_t
sxe2_drv_dev_dma_map(struct sxe2_common_device *cdev, uint64_t vaddr,
- uint64_t iova, uint64_t size)
+ uint64_t iova, uint64_t size)
{
struct sxe2_ioctl_iommu_dma_map cmd_params;
enum rte_iova_mode iova_mode;
diff --git a/drivers/common/sxe2/sxe2_ioctl_chnl_func.h b/drivers/common/sxe2/sxe2_ioctl_chnl_func.h
index e5d8cad1e0..368be16d4f 100644
--- a/drivers/common/sxe2/sxe2_ioctl_chnl_func.h
+++ b/drivers/common/sxe2/sxe2_ioctl_chnl_func.h
@@ -29,6 +29,7 @@ int32_t
sxe2_drv_dev_open(struct sxe2_common_device *cdev,
struct rte_pci_device *pci_dev);
+
__rte_internal
void
sxe2_drv_dev_close(struct sxe2_common_device *cdev);
@@ -37,6 +38,23 @@ __rte_internal
int32_t
sxe2_drv_dev_handshake(struct sxe2_common_device *cdev);
+__rte_internal
+int32_t
+sxe2_drv_dev_rxq_irq_set(struct sxe2_common_device *cdev, uint16_t base_irq,
+ int32_t *efd, uint16_t nb_irq);
+
+__rte_internal
+int32_t
+sxe2_drv_dev_other_irq_set(struct sxe2_common_device *cdev, int32_t efd, uint64_t event);
+
+__rte_internal
+int32_t
+sxe2_drv_dev_other_irq_get(struct sxe2_common_device *cdev, uint64_t *event);
+
+__rte_internal
+int32_t
+sxe2_drv_dev_reset_irq_set(struct sxe2_common_device *cdev, int32_t fd);
+
__rte_internal
void
*sxe2_drv_dev_mmap(struct sxe2_common_device *cdev, uint8_t bar_idx,
diff --git a/drivers/net/sxe2/meson.build b/drivers/net/sxe2/meson.build
index 8c8f16863e..fc4466556b 100644
--- a/drivers/net/sxe2/meson.build
+++ b/drivers/net/sxe2/meson.build
@@ -68,4 +68,5 @@ sources += files(
'sxe2_security.c',
'sxe2_mp.c',
'sxe2_stats.c',
+ 'sxe2_irq.c',
)
diff --git a/drivers/net/sxe2/sxe2_cmd_chnl.c b/drivers/net/sxe2/sxe2_cmd_chnl.c
index a1fc8a50e3..d1f15084ed 100644
--- a/drivers/net/sxe2/sxe2_cmd_chnl.c
+++ b/drivers/net/sxe2/sxe2_cmd_chnl.c
@@ -348,6 +348,48 @@ int32_t sxe2_drv_mac_link_status_get(struct sxe2_adapter *adapter)
return ret;
}
+int32_t sxe2_drv_rxq_bind_irq(struct sxe2_adapter *adapter, uint16_t rxq_idx, uint16_t msix_idx)
+{
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_drv_queue_irq_bind_req req = {0};
+ int32_t ret = 0;
+
+ req.msix_idx = msix_idx;
+ req.q_idx = rxq_idx;
+ req.itr_idx = 0;
+ req.bind = true;
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_EVT_IRQ_BAND_RXQ,
+ &req, sizeof(req),
+ NULL, 0);
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret)
+ PMD_DEV_LOG_ERR(adapter, DRV, "rxq bind irq failed, ret=%d", ret);
+
+ return ret;
+}
+
+int32_t sxe2_drv_rxq_unbind_irq(struct sxe2_adapter *adapter, uint16_t rxq_idx)
+{
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_drv_queue_irq_bind_req req = {0};
+ int32_t ret = 0;
+
+ req.bind = false;
+ req.q_idx = rxq_idx;
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_EVT_IRQ_BAND_RXQ,
+ &req, sizeof(req),
+ NULL, 0);
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret)
+ PMD_DEV_LOG_ERR(adapter, DRV, "rxq unbind irq failed, ret=%d", ret);
+
+ return ret;
+}
+
int32_t sxe2_drv_get_mac_stats(struct sxe2_adapter *adapter)
{
int32_t ret = 0;
diff --git a/drivers/net/sxe2/sxe2_cmd_chnl.h b/drivers/net/sxe2/sxe2_cmd_chnl.h
index 80ad10ac00..3eb30078e1 100644
--- a/drivers/net/sxe2/sxe2_cmd_chnl.h
+++ b/drivers/net/sxe2/sxe2_cmd_chnl.h
@@ -118,4 +118,8 @@ int32_t sxe2_drv_rss_hf_clear(struct sxe2_adapter *adapter);
int32_t sxe2_drv_ptp_gettime(struct sxe2_adapter *adapter, struct sxe2_rx_queue *rxq);
+int32_t sxe2_drv_rxq_bind_irq(struct sxe2_adapter *adapter, uint16_t rxq_idx, uint16_t msix_idx);
+
+int32_t sxe2_drv_rxq_unbind_irq(struct sxe2_adapter *adapter, uint16_t rxq_idx);
+
#endif /* SXE2_CMD_CHNL_H */
diff --git a/drivers/net/sxe2/sxe2_drv_cmd.h b/drivers/net/sxe2/sxe2_drv_cmd.h
index 7935a28dc1..807edfc4d6 100644
--- a/drivers/net/sxe2/sxe2_drv_cmd.h
+++ b/drivers/net/sxe2/sxe2_drv_cmd.h
@@ -556,6 +556,14 @@ struct __rte_aligned(4) __rte_packed_begin sxe2_drv_tx_map_req {
uint8_t pool_idx;
} __rte_packed_end;
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_queue_irq_bind_req {
+ uint16_t q_idx;
+ uint16_t msix_idx;
+ uint8_t itr_idx;
+ uint8_t bind;
+ uint8_t rsv[2];
+} __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 46c6c993bf..07d67321c9 100644
--- a/drivers/net/sxe2/sxe2_ethdev.c
+++ b/drivers/net/sxe2/sxe2_ethdev.c
@@ -22,6 +22,7 @@
#include <rte_eal_paging.h>
#include "sxe2_ethdev.h"
+#include "sxe2_irq.h"
#include "sxe2_drv_cmd.h"
#include "sxe2_cmd_chnl.h"
#include "sxe2_tx.h"
@@ -107,6 +108,9 @@ static const struct eth_dev_ops sxe2_eth_dev_ops = {
.rx_queue_release = sxe2_rx_queue_release,
.tx_queue_setup = sxe2_tx_queue_setup,
.tx_queue_release = sxe2_tx_queue_release,
+ .rx_queue_intr_enable = sxe2_rx_queue_intr_enable,
+ .rx_queue_intr_disable = sxe2_rx_queue_intr_disable,
+
.rxq_info_get = sxe2_rx_queue_info_get,
.txq_info_get = sxe2_tx_queue_info_get,
.rx_burst_mode_get = sxe2_rx_burst_mode_get,
@@ -177,6 +181,8 @@ static int32_t sxe2_dev_stop(struct rte_eth_dev *dev)
if (adapter->started == 0)
goto l_end;
+ sxe2_rxq_intr_disable(dev);
+
sxe2_txqs_all_stop(dev);
sxe2_rxqs_all_stop(dev);
@@ -215,6 +221,12 @@ static int32_t sxe2_dev_start(struct rte_eth_dev *dev)
goto l_end;
}
+ ret = sxe2_rxq_intr_enable(dev);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to enable rx queue intr");
+ goto l_rxq_intr_err;
+ }
+
ret = sxe2_queues_start(dev);
if (ret) {
PMD_LOG_ERR(INIT, "enable queues failed");
@@ -224,7 +236,10 @@ static int32_t sxe2_dev_start(struct rte_eth_dev *dev)
dev->data->dev_started = 1;
adapter->started = 1;
goto l_end;
+
l_start_queues_err:
+ (void)sxe2_rxq_intr_disable(dev);
+l_rxq_intr_err:
(void)sxe2_filter_rule_stop(dev);
l_end:
return ret;
@@ -615,6 +630,8 @@ static int32_t sxe2_func_caps_get(struct sxe2_adapter *adapter)
sxe2_sw_queue_ctx_hw_cap_set(adapter, &dev_caps.queue_caps);
+ sxe2_sw_irq_ctx_hw_cap_set(adapter, &dev_caps.msix_caps);
+
sxe2_sw_rss_ctx_hw_cap_set(adapter, &dev_caps.rss_hash_caps);
sxe2_sw_vsi_ctx_hw_cap_set(adapter, &dev_caps.vsi_caps);
@@ -636,6 +653,41 @@ static int32_t sxe2_dev_caps_get(struct sxe2_adapter *adapter)
return ret;
}
+uint32_t sxe2_pci_map_read_reg(struct sxe2_adapter *adapter,
+ enum sxe2_pci_map_resource res_type, uint16_t idx_in_func)
+{
+ void *reg_addr;
+ uint32_t value;
+
+ reg_addr = sxe2_pci_map_addr_get(adapter, res_type, idx_in_func);
+ if (unlikely(reg_addr == NULL)) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "reg addr:0x%p is error.", reg_addr);
+ value = SXE2_PCI_MAP_INVALID_VAL;
+ goto l_ret;
+ }
+
+ value = SXE2_PCI_REG_READ(reg_addr);
+
+l_ret:
+ return value;
+}
+
+void sxe2_pci_map_write_reg(struct sxe2_adapter *adapter,
+ enum sxe2_pci_map_resource res_type, uint16_t idx_in_func, uint32_t value)
+{
+ void *reg_addr;
+
+ reg_addr = sxe2_pci_map_addr_get(adapter, res_type, idx_in_func);
+ if (unlikely(reg_addr == NULL)) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "reg addr:0x%p is error.", reg_addr);
+ goto l_ret;
+ }
+
+ SXE2_PCI_REG_WRITE_WC(reg_addr, value);
+l_ret:
+ return;
+}
+
int32_t sxe2_dev_pci_seg_map(struct sxe2_adapter *adapter,
enum sxe2_pci_map_resource res_type,
uint64_t org_len,
@@ -715,6 +767,27 @@ static int32_t sxe2_hw_init(struct rte_eth_dev *dev)
return ret;
}
+static int32_t sxe2_sw_init(struct rte_eth_dev *dev)
+{
+ int32_t ret = -1;
+
+ PMD_INIT_FUNC_TRACE();
+
+ ret = sxe2_sw_irq_ctxt_init(dev);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to sw irq ctxt init, ret=[%d]", ret);
+ goto l_end;
+ }
+
+l_end:
+ return ret;
+}
+
+static void sxe2_sw_uninit(struct rte_eth_dev *dev)
+{
+ sxe2_sw_irq_ctxt_uninit(dev);
+}
+
int32_t sxe2_dev_pci_res_seg_map(struct sxe2_adapter *adapter,
uint32_t res_type,
uint32_t item_cnt,
@@ -1065,6 +1138,18 @@ static int32_t sxe2_dev_init(struct rte_eth_dev *dev,
goto init_dev_info_err;
}
+ ret = sxe2_sw_init(dev);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to initialize sw parameters, ret=[%d]", ret);
+ goto init_sw_err;
+ }
+
+ ret = sxe2_intr_init(dev);
+ if (ret != 0) {
+ PMD_LOG_ERR(INIT, "Failed to initialize interrupt, ret:%d", ret);
+ goto init_irq_err;
+ }
+
ret = sxe2_eth_init(dev);
if (ret) {
PMD_LOG_ERR(INIT, "Failed to initialize eth parameters, ret=%d", ret);
@@ -1109,6 +1194,10 @@ static int32_t sxe2_dev_init(struct rte_eth_dev *dev,
init_rss_err:
sxe2_security_uinit(dev);
init_security_err:
+ sxe2_intr_uninit(dev);
+init_irq_err:
+ sxe2_sw_uninit(dev);
+init_sw_err:
sxe2_eth_uinit(dev);
init_eth_err:
init_dev_info_err:
@@ -1132,8 +1221,10 @@ static int32_t sxe2_dev_close(struct rte_eth_dev *dev)
(void)sxe2_sched_uinit(dev);
sxe2_vsi_uninit(dev);
sxe2_security_uinit(dev);
- sxe2_dev_pci_map_uinit(dev);
+ sxe2_intr_uninit(dev);
+ sxe2_sw_uninit(dev);
sxe2_eth_uinit(dev);
+ sxe2_dev_pci_map_uinit(dev);
l_end:
return 0;
diff --git a/drivers/net/sxe2/sxe2_ethdev.h b/drivers/net/sxe2/sxe2_ethdev.h
index fed8ce37d9..263d407587 100644
--- a/drivers/net/sxe2/sxe2_ethdev.h
+++ b/drivers/net/sxe2/sxe2_ethdev.h
@@ -352,6 +352,12 @@ int32_t sxe2_dev_pci_res_seg_map(struct sxe2_adapter *adapter,
uint32_t item_cnt,
uint32_t item_base);
+void sxe2_pci_map_write_reg(struct sxe2_adapter *adapter,
+ enum sxe2_pci_map_resource res_type, uint16_t idx_in_func, uint32_t value);
+
+uint32_t sxe2_pci_map_read_reg(struct sxe2_adapter *adapter,
+ enum sxe2_pci_map_resource res_type, uint16_t idx_in_func);
+
void sxe2_dev_pci_seg_unmap(struct sxe2_adapter *adapter, uint32_t res_type);
int32_t sxe2_dev_pci_map_init(struct rte_eth_dev *dev);
diff --git a/drivers/net/sxe2/sxe2_irq.c b/drivers/net/sxe2/sxe2_irq.c
new file mode 100644
index 0000000000..6dab2f8cd8
--- /dev/null
+++ b/drivers/net/sxe2/sxe2_irq.c
@@ -0,0 +1,942 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#include <stdint.h>
+#include <sys/eventfd.h>
+#include <unistd.h>
+#include <ethdev_pci.h>
+#include <ethdev_driver.h>
+#include <rte_alarm.h>
+#include <fcntl.h>
+#include <rte_stdatomic.h>
+
+#include "sxe2_ethdev.h"
+#include "sxe2_irq.h"
+#include "sxe2_common_log.h"
+#include "sxe2_queue.h"
+#include "sxe2_drv_cmd.h"
+#include "sxe2_ioctl_chnl_func.h"
+#include "sxe2vf_regs.h"
+#include "sxe2_host_regs.h"
+#include "sxe2_cmd_chnl.h"
+
+#define SXE2_INT_EVENT_OICR_ALL (SXE2_PF_INT_OICR_SWINT | \
+ SXE2_PF_INT_OICR_LAN_TX_ERR | \
+ SXE2_PF_INT_OICR_LAN_RX_ERR | \
+ SXE2_PF_INT_OICR_FW)
+
+#define MAX_EVENT_PENDING (16)
+
+struct sxe2_event_element {
+ TAILQ_ENTRY(sxe2_event_element) next;
+ struct rte_eth_dev *dev;
+};
+
+struct sxe2_event_handler {
+ RTE_ATOMIC(uint16_t)ndev;
+ rte_thread_t tid;
+ int32_t fd[2];
+ rte_spinlock_t lock;
+ TAILQ_HEAD(event_list, sxe2_event_element) pending;
+};
+static struct sxe2_event_handler event_handler = {
+ .fd = {-1, -1},
+};
+
+static RTE_ATOMIC(uint32_t)event_thread_run;
+
+
+static void sxe2_event_irq_common_handler(struct sxe2_adapter *adapter, uint64_t oicr)
+{
+ struct rte_eth_dev *dev = &rte_eth_devices[adapter->dev_info.dev_data->port_id];
+
+ if (oicr & RTE_BIT32(SXE2_COM_EC_LINK_CHG)) {
+ PMD_DEV_LOG_INFO(adapter, DRV, "OICR=%" PRIu64, oicr);
+ (void)sxe2_drv_mac_link_status_get(adapter);
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+ rte_eth_dev_callback_process(dev,
+ RTE_ETH_EVENT_INTR_LSC,
+ NULL);
+ }
+}
+
+static uint32_t sxe2_event_intr_handle(void *param __rte_unused)
+{
+ struct sxe2_event_handler *handler = &event_handler;
+ struct sxe2_adapter *adapter;
+ struct sxe2_event_element *pos;
+ struct sxe2_event_element *tmp;
+ int32_t ret = 0;
+ uint64_t oicr = 0;
+ TAILQ_HEAD(event_list, sxe2_event_element) pending;
+ int8_t unused[MAX_EVENT_PENDING];
+ ssize_t nr;
+
+ while (rte_atomic_load_explicit(&event_thread_run, rte_memory_order_relaxed)) {
+ nr = read(handler->fd[0], &unused, sizeof(unused));
+ if (nr <= 0)
+ break;
+
+ rte_spinlock_lock(&handler->lock);
+ TAILQ_INIT(&pending);
+ TAILQ_CONCAT(&pending, &handler->pending, next);
+ rte_spinlock_unlock(&handler->lock);
+
+ TAILQ_FOREACH_SAFE(pos, &pending, next, tmp) {
+ TAILQ_REMOVE(&pending, pos, next);
+ adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(pos->dev);
+
+ ret = sxe2_drv_dev_other_irq_get(adapter->cdev, &oicr);
+ sxe2_event_irq_common_handler(adapter, oicr);
+
+ rte_free(pos);
+ }
+ }
+
+ return ret;
+}
+
+static int32_t sxe2_event_intr_handler_init(void)
+{
+ struct sxe2_event_handler *handler = &event_handler;
+ int32_t ret = 0;
+ int err = 0;
+
+ PMD_INIT_FUNC_TRACE();
+ if (rte_atomic_fetch_add_explicit(&handler->ndev, 1, rte_memory_order_acq_rel) >= 1) {
+ ret = 0;
+ PMD_LOG_DEBUG(INIT, "%s: ndev > 1", __func__);
+ goto l_end;
+ }
+
+#if defined(RTE_EXEC_ENV_IS_WINDOWS) && RTE_EXEC_ENV_IS_WINDOWS != 0
+ err = _pipe(handler->fd, MAX_EVENT_PENDING, O_BINARY);
+#else
+ err = pipe(handler->fd);
+#endif
+ if (err != 0) {
+ ret = -ECHILD;
+ rte_atomic_fetch_sub_explicit(&handler->ndev, 1, rte_memory_order_release);
+ PMD_LOG_ERR(INIT, "%s: pipe failed", __func__);
+ goto l_end;
+ }
+
+ rte_atomic_store_explicit(&event_thread_run, 1, rte_memory_order_relaxed);
+
+ TAILQ_INIT(&handler->pending);
+ rte_spinlock_init(&handler->lock);
+
+ if (rte_thread_create_internal_control(&handler->tid, "sxe2-event",
+ sxe2_event_intr_handle, NULL)) {
+ PMD_LOG_ERR(INIT, "%s: thread create failed", __func__);
+ rte_atomic_fetch_sub_explicit(&handler->ndev, 1, rte_memory_order_release);
+ ret = -ECHILD;
+ goto l_end;
+ }
+ ret = 0;
+l_end:
+ return ret;
+}
+
+static void sxe2_event_intr_handler_uinit(void)
+{
+ struct sxe2_event_handler *handler = &event_handler;
+ struct sxe2_event_element *pos;
+ struct sxe2_event_element *tmp;
+ ssize_t nw = 0;
+ int8_t notify_byte = 0;
+
+ PMD_INIT_FUNC_TRACE();
+ if (rte_atomic_fetch_sub_explicit(&handler->ndev, 1, rte_memory_order_acq_rel) > 1) {
+ PMD_LOG_DEBUG(INIT, "event handler uinit, ndev > 0");
+ return;
+ }
+
+ rte_atomic_store_explicit(&event_thread_run, 0, rte_memory_order_relaxed);
+ nw = write(handler->fd[1], ¬ify_byte, 1);
+ RTE_SET_USED(nw);
+
+ (void)rte_thread_join(handler->tid, NULL);
+
+ if (handler->fd[0] != -1) {
+ close(handler->fd[0]);
+ handler->fd[0] = -1;
+ }
+ if (handler->fd[1] != -1) {
+ close(handler->fd[1]);
+ handler->fd[1] = -1;
+ }
+
+ rte_spinlock_lock(&handler->lock);
+ TAILQ_FOREACH_SAFE(pos, &handler->pending, next, tmp) {
+ TAILQ_REMOVE(&handler->pending, pos, next);
+ rte_free(pos);
+ }
+ rte_spinlock_unlock(&handler->lock);
+}
+
+static void sxe2_event_intr_post(struct rte_eth_dev *dev)
+{
+ struct sxe2_event_handler *handler = &event_handler;
+ struct sxe2_event_element *elem = rte_malloc(NULL, sizeof(struct sxe2_event_element), 0);
+ int8_t notify_byte = 0;
+ ssize_t nw = 0;
+
+ if (!elem)
+ goto l_end;
+
+ elem->dev = dev;
+
+ rte_spinlock_lock(&handler->lock);
+ TAILQ_INSERT_TAIL(&handler->pending, elem, next);
+ rte_spinlock_unlock(&handler->lock);
+
+ nw = write(handler->fd[1], ¬ify_byte, 1);
+ RTE_SET_USED(nw);
+
+l_end:
+ return;
+}
+
+static void sxe2_interrupt_handler_other(void *arg)
+{
+ struct rte_eth_dev *dev = (struct rte_eth_dev *)arg;
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t eventfd = adapter->irq_ctxt.other_event_fd;
+ int32_t ret = 0;
+ uint64_t buf = 0;
+
+ ret = read(eventfd, &buf, sizeof(buf));
+ if (ret != sizeof(buf)) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "read eventfd[%d] failed, ret:%d, errno:%d.",
+ eventfd, ret, errno);
+ }
+
+ sxe2_event_intr_post(dev);
+}
+
+static void sxe2_interrupt_handler_reset(void *arg)
+{
+ struct rte_eth_dev *dev = (struct rte_eth_dev *)arg;
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t resetfd = adapter->irq_ctxt.reset_event_fd;
+ int32_t ret = 0;
+ uint64_t buf = 0;
+
+ ret = read(resetfd, &buf, sizeof(buf));
+ if (ret != sizeof(buf)) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "read resetfd[%d] failed, ret:%d, errno:%d.",
+ resetfd, ret, errno);
+ }
+
+ sxe2_drv_cmd_close(adapter->cdev);
+
+ rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RMV, NULL);
+}
+
+int32_t sxe2_sw_irq_ctxt_init(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_irq_context *irq_ctxt = &adapter->irq_ctxt;
+ int32_t ret = 0;
+
+ irq_ctxt->rxq_avail_cnt = irq_ctxt->max_cnt_hw;
+ irq_ctxt->rxq_base_idx_in_pf = irq_ctxt->base_idx_in_func;
+ irq_ctxt->reset_event_fd = -1;
+ irq_ctxt->other_event_fd = -1;
+
+ return ret;
+}
+
+void sxe2_sw_irq_ctxt_uninit(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+
+ memset(&adapter->irq_ctxt, 0, sizeof(adapter->irq_ctxt));
+ adapter->irq_ctxt.reset_event_fd = -1;
+ adapter->irq_ctxt.other_event_fd = -1;
+}
+
+void sxe2_sw_irq_ctx_hw_cap_set(struct sxe2_adapter *adapter,
+ struct sxe2_drv_msix_caps *msix_caps)
+{
+ adapter->irq_ctxt.max_cnt_hw = msix_caps->msix_vectors_cnt;
+ adapter->irq_ctxt.base_idx_in_func = msix_caps->base_idx_in_func;
+}
+
+static int32_t sxe2_intr_handler_cfg(struct rte_intr_handle *handle,
+ int32_t fd, rte_intr_callback_fn cb, void *cb_arg)
+{
+ int32_t ret = 0;
+
+ ret = rte_intr_fd_set(handle, fd);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to set intr_handle->fd, error %i (%s)",
+ errno, strerror(errno));
+ goto err;
+ }
+
+ ret = rte_intr_type_set(handle, RTE_INTR_HANDLE_EXT);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to set intr_handle->type, error %i (%s)",
+ errno, strerror(errno));
+ goto err;
+ }
+
+ ret = rte_intr_callback_register(handle, cb, cb_arg);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to initialize register intr callback, ret=%d", ret);
+ goto err;
+ }
+err:
+ return ret;
+}
+
+static struct rte_intr_handle *
+sxe2_intr_handler_create(int32_t fd, rte_intr_callback_fn cb, void *cb_arg)
+{
+ struct rte_intr_handle *tmp_intr_handle = NULL;
+ int32_t ret = 0;
+
+ tmp_intr_handle = rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_PRIVATE);
+ if (!tmp_intr_handle) {
+ PMD_LOG_ERR(INIT, "Failed to alloc memory for intr_handler, error %i (%s)",
+ errno, strerror(errno));
+ goto err;
+ }
+
+ ret = rte_intr_fd_set(tmp_intr_handle, fd);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to set intr_handle->fd, error %i (%s)",
+ errno, strerror(errno));
+ goto err;
+ }
+
+ ret = rte_intr_type_set(tmp_intr_handle, RTE_INTR_HANDLE_EXT);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to set intr_handle->type, error %i (%s)",
+ errno, strerror(errno));
+ goto err;
+ }
+
+ ret = rte_intr_callback_register(tmp_intr_handle, cb, cb_arg);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to initialize register intr callback, ret=%d", ret);
+ goto err;
+ }
+
+ return tmp_intr_handle;
+err:
+ rte_intr_instance_free(tmp_intr_handle);
+ return NULL;
+}
+
+static void sxe2_intr_handler_destroy(struct rte_intr_handle *intr_handle,
+ rte_intr_callback_fn cb, void *cb_arg)
+{
+ if (!intr_handle)
+ return;
+
+ if (rte_intr_fd_get(intr_handle) >= 0)
+ (void)rte_intr_callback_unregister(intr_handle, cb, cb_arg);
+ rte_intr_instance_free(intr_handle);
+}
+
+static int32_t sxe2_event_intr_fd_create(void)
+{
+ int32_t fd = 0;
+
+ fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
+ if (fd < 0) {
+ PMD_LOG_ERR(INIT, "Can't setup eventfd, error %i (%s)",
+ errno, strerror(errno));
+ goto err;
+ }
+
+ return fd;
+err:
+ return -EBADF;
+}
+
+static void sxe2_event_intr_fd_destroy(int32_t fd)
+{
+ if (fd >= 0)
+ close(fd);
+}
+
+static int32_t sxe2_other_intr_register(struct rte_eth_dev *dev, int32_t fd)
+{
+ struct sxe2_adapter *adapter =
+ SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret = 0;
+ uint64_t event = RTE_BIT32(SXE2_COM_EC_LINK_CHG) |
+ RTE_BIT32(SXE2_COM_SW_MODE_LEGACY) |
+ RTE_BIT32(SXE2_COM_SW_MODE_SWITCHDEV) |
+ RTE_BIT32(SXE2_COM_FC_ST_CHANGE);
+
+ ret = sxe2_drv_dev_other_irq_set(adapter->cdev, fd, event);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to set other irq, ret=%d", ret);
+ goto l_end;
+ }
+
+l_end:
+ return ret;
+}
+
+static void sxe2_other_intr_unregister(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter =
+ SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret = 0;
+
+ ret = sxe2_drv_dev_other_irq_set(adapter->cdev, -1, 0);
+ if (ret)
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to set other irq, ret=%d", ret);
+}
+
+static int32_t sxe2_reset_intr_register(struct rte_eth_dev *dev, int32_t fd)
+{
+ struct sxe2_adapter *adapter =
+ SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret = 0;
+
+ ret = sxe2_drv_dev_reset_irq_set(adapter->cdev, fd);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to set reset irq, ret=%d", ret);
+ goto l_end;
+ }
+
+l_end:
+ return ret;
+}
+
+static void sxe2_reset_intr_unregister(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter =
+ SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret = 0;
+
+ ret = sxe2_drv_dev_reset_irq_set(adapter->cdev, -1);
+ if (ret)
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to set reset irq, ret=%d", ret);
+}
+
+int32_t sxe2_intr_init(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter =
+ SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct rte_pci_device *pci_dev = container_of(dev->device, struct rte_pci_device, device);
+ struct rte_intr_handle *reset_handle = NULL;
+ int32_t ofd = -1;
+ int32_t rfd = -1;
+ int32_t ret = 0;
+
+ PMD_INIT_FUNC_TRACE();
+
+ ofd = sxe2_event_intr_fd_create();
+ if (ofd < 0) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to create event intr fd");
+ ret = -EBADF;
+ goto l_end;
+ }
+
+ ret = sxe2_intr_handler_cfg(pci_dev->intr_handle,
+ ofd, sxe2_interrupt_handler_other, dev);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to create intr handler");
+ goto l_err_create_other_handler;
+ }
+
+ ret = sxe2_event_intr_handler_init();
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Event handler init failed, ret=%d", ret);
+ goto l_err_event_intr_handler_init;
+ }
+
+ ret = sxe2_other_intr_register(dev, ofd);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to register other intr, ret=%d", ret);
+ goto l_err_register_other_intr;
+ }
+ adapter->irq_ctxt.other_event_fd = ofd;
+
+ rfd = sxe2_event_intr_fd_create();
+ if (rfd < 0) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to create event intr fd");
+ ret = -EBADF;
+ goto l_err_create_reset_fd;
+ }
+
+ reset_handle = sxe2_intr_handler_create(rfd, sxe2_interrupt_handler_reset, dev);
+ if (!reset_handle) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to create intr handler");
+ ret = -ENOMEM;
+ goto l_err_create_reset_handler;
+ }
+ adapter->irq_ctxt.reset_handle = reset_handle;
+
+ ret = sxe2_reset_intr_register(dev, rfd);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to register reset intr, ret=%d", ret);
+ goto l_err_register_reset_intr;
+ }
+ adapter->irq_ctxt.reset_event_fd = rfd;
+
+ goto l_end;
+l_err_register_reset_intr:
+ sxe2_intr_handler_destroy(reset_handle, sxe2_interrupt_handler_reset, dev);
+ adapter->irq_ctxt.reset_handle = NULL;
+l_err_create_reset_handler:
+ sxe2_event_intr_fd_destroy(rfd);
+l_err_create_reset_fd:
+ sxe2_other_intr_unregister(dev);
+ adapter->irq_ctxt.other_event_fd = -1;
+l_err_register_other_intr:
+ sxe2_event_intr_handler_uinit();
+l_err_event_intr_handler_init:
+ sxe2_intr_handler_destroy(pci_dev->intr_handle,
+ sxe2_interrupt_handler_other, dev);
+ pci_dev->intr_handle = NULL;
+l_err_create_other_handler:
+ sxe2_event_intr_fd_destroy(ofd);
+l_end:
+ return ret;
+}
+
+void sxe2_intr_uninit(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter =
+ SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct rte_pci_device *pci_dev = container_of(dev->device, struct rte_pci_device, device);
+
+ sxe2_reset_intr_unregister(dev);
+ sxe2_intr_handler_destroy(adapter->irq_ctxt.reset_handle,
+ sxe2_interrupt_handler_reset, dev);
+ sxe2_event_intr_fd_destroy(adapter->irq_ctxt.reset_event_fd);
+ sxe2_other_intr_unregister(dev);
+ sxe2_event_intr_handler_uinit();
+ sxe2_intr_handler_destroy(pci_dev->intr_handle,
+ sxe2_interrupt_handler_other, dev);
+ sxe2_event_intr_fd_destroy(adapter->irq_ctxt.other_event_fd);
+
+ adapter->irq_ctxt.other_event_fd = -1;
+ adapter->irq_ctxt.reset_event_fd = -1;
+ pci_dev->intr_handle = NULL;
+ adapter->irq_ctxt.reset_handle = NULL;
+}
+
+static int32_t sxe2_rxq_intr_efd_alloc(struct rte_eth_dev *dev, int32_t *efd)
+{
+ struct sxe2_adapter *adapter =
+ SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret = 0;
+ int32_t fd = 0;
+
+ fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
+ if (fd < 0) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Can't setup eventfd, error %i (%s)",
+ errno, strerror(errno));
+ ret = -EBADF;
+ goto l_end;
+ }
+
+ *efd = fd;
+
+l_end:
+ return ret;
+}
+
+static void sxe2_rxq_intr_efd_free(int32_t efd)
+{
+ close(efd);
+}
+
+static void sxe2_pci_hw_int_itr_set(struct sxe2_adapter *adapter, uint16_t msix_idx, uint16_t itr)
+{
+ sxe2_pci_map_write_reg(adapter, SXE2_PCI_MAP_RES_IRQ_ITR, msix_idx, itr);
+}
+
+static void sxe2_pci_hw_irq_disable(struct sxe2_adapter *adapter, uint16_t irq_idx)
+{
+ uint32_t value = (SXE2_ITR_IDX_NONE << SXE2_VF_DYN_CTL_ITR_IDX_S);
+
+ sxe2_pci_map_write_reg(adapter, SXE2_PCI_MAP_RES_IRQ_DYN, irq_idx, value);
+}
+
+static void sxe2_pci_hw_irq_enable(struct sxe2_adapter *adapter, uint16_t irq_idx)
+{
+ uint32_t value = SXE2_VF_DYN_CTL_INTENABLE |
+ SXE2_VF_DYN_CTL_CLEARPBA |
+ (SXE2_ITR_IDX_NONE << SXE2_VF_DYN_CTL_ITR_IDX_S);
+
+ sxe2_pci_map_write_reg(adapter, SXE2_PCI_MAP_RES_IRQ_DYN, irq_idx, value);
+}
+
+static uint32_t sxe2_pci_hw_irq_dyn_ctl_read(struct sxe2_adapter *adapter, uint16_t irq_idx)
+{
+ return sxe2_pci_map_read_reg(adapter, SXE2_PCI_MAP_RES_IRQ_DYN, irq_idx);
+}
+
+static void sxe2_pci_hw_msix_disable(struct sxe2_adapter *adapter, uint16_t irq_idx)
+{
+ sxe2_pci_map_write_reg(adapter, SXE2_PCI_MAP_RES_IRQ_MSIX,
+ irq_idx, SXE2VF_BAR4_MSIX_DISABLE);
+}
+
+static void sxe2_pci_hw_msix_enable(struct sxe2_adapter *adapter, uint16_t irq_idx)
+{
+ sxe2_pci_map_write_reg(adapter, SXE2_PCI_MAP_RES_IRQ_MSIX,
+ irq_idx, SXE2VF_BAR4_MSIX_ENABLE);
+}
+
+static void sxe2_pci_hw_irq_trigger(struct sxe2_adapter *adapter, uint16_t irq_idx)
+{
+ sxe2_pci_map_write_reg(adapter, SXE2_PCI_MAP_RES_IRQ_DYN, irq_idx,
+ (SXE2VF_ITR_IDX_NONE << SXE2VF_DYN_CTL_ITR_IDX_SHIFT) |
+ SXE2VF_DYN_CTL_SWINT_TRIG | SXE2VF_DYN_CTL_INTENABLE_MSK);
+}
+
+static void sxe2_pci_hw_irq_clear_pba(struct sxe2_adapter *adapter, uint16_t irq_idx)
+{
+ sxe2_pci_map_write_reg(adapter, SXE2_PCI_MAP_RES_IRQ_DYN, irq_idx,
+ (SXE2VF_ITR_IDX_NONE << SXE2VF_DYN_CTL_ITR_IDX_SHIFT) |
+ SXE2VF_DYN_CTL_CLEARPBA | SXE2VF_DYN_CTL_INTENABLE_MSK);
+}
+
+static void sxe2_rxq_msix_cfg_unmap(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter =
+ SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_irq_context *irq_ctxt = &adapter->irq_ctxt;
+ uint16_t rxq_cnt = adapter->q_ctxt.qp_cnt_assign;
+ uint16_t i = 0;
+
+ for (i = 0; i < irq_ctxt->rxq_irq_cnt; i++)
+ sxe2_pci_hw_irq_disable(adapter, irq_ctxt->rxq_msix_idx[i]);
+
+ for (i = 0; i < rxq_cnt; i++)
+ (void)sxe2_drv_rxq_unbind_irq(adapter, i);
+}
+
+static int32_t sxe2_rxq_msix_cfg_map(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter =
+ SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_irq_context *irq_ctxt = &adapter->irq_ctxt;
+ int32_t ret = 0;
+ uint32_t val;
+ uint16_t rxq_cnt = dev->data->nb_rx_queues;
+ uint16_t i = 0;
+ uint8_t rx_low_latency = adapter->devargs.rx_low_latency;
+
+ for (i = 0; i < irq_ctxt->rxq_irq_cnt; i++) {
+ sxe2_pci_hw_irq_disable(adapter, irq_ctxt->rxq_msix_idx[i]);
+ if (rx_low_latency) {
+ sxe2_pci_hw_int_itr_set(adapter, irq_ctxt->rxq_msix_idx[i],
+ SXE2_ITR_INTERVAL_LOW);
+ } else {
+ sxe2_pci_hw_int_itr_set(adapter, irq_ctxt->rxq_msix_idx[i],
+ SXE2_ITR_INTERVAL_NORMAL);
+ }
+ }
+
+ for (i = 0; i < rxq_cnt; i++) {
+ ret = sxe2_drv_rxq_bind_irq(adapter, i, irq_ctxt->rxq_msix_idx[i]);
+ if (ret != 0) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "RXQ[%u] bind IRQ[%u] failed.",
+ i, irq_ctxt->rxq_msix_idx[i]);
+ goto l_end;
+ }
+ }
+
+ for (i = 0; i < irq_ctxt->rxq_irq_cnt; i++)
+ sxe2_pci_hw_irq_enable(adapter, irq_ctxt->rxq_msix_idx[i]);
+
+ for (i = 0; i < irq_ctxt->rxq_irq_cnt; i++) {
+ val = sxe2_pci_hw_irq_dyn_ctl_read(adapter, i);
+ if ((val & SXE2VF_DYN_CTL_INTENABLE) == 0)
+ continue;
+
+ sxe2_pci_hw_msix_disable(adapter, i);
+ sxe2_pci_hw_irq_trigger(adapter, i);
+ val = sxe2_pci_hw_irq_dyn_ctl_read(adapter, i);
+ sxe2_pci_hw_irq_clear_pba(adapter, i);
+ val = sxe2_pci_hw_irq_dyn_ctl_read(adapter, i);
+ sxe2_pci_hw_msix_enable(adapter, i);
+ }
+
+l_end:
+ if (ret != 0)
+ sxe2_rxq_msix_cfg_unmap(dev);
+ return ret;
+}
+
+static int32_t sxe2_rxq_map_msix_intr(struct rte_eth_dev *dev,
+ uint16_t msix_base __rte_unused, uint16_t nb_msix,
+ uint16_t base_queue, uint16_t nb_queue)
+{
+ struct sxe2_adapter *adapter =
+ SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_irq_context *irq_ctxt = &adapter->irq_ctxt;
+ uint32_t *msix_tbl = NULL;
+ int32_t ret = 0;
+ uint16_t i;
+
+ if (!nb_queue || !nb_msix || nb_queue < nb_msix) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Queue num[%u] or msix num[%u] is invalid.",
+ nb_queue, nb_msix);
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ msix_tbl = rte_zmalloc(NULL, sizeof(uint32_t) * nb_queue, 0);
+ if (!msix_tbl) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to alloc msix_tbl memory.");
+ ret = -ENOMEM;
+ goto l_end;
+ }
+ for (i = 0; i < nb_queue; i++) {
+ msix_tbl[i] = i % nb_msix;
+ PMD_DEV_LOG_INFO(adapter, INIT, "Queue %u is binding to vect %u",
+ base_queue + i, msix_tbl[i]);
+ }
+
+ irq_ctxt->rxq_irq_cnt = nb_msix;
+ irq_ctxt->rxq_msix_idx = msix_tbl;
+
+l_end:
+ return ret;
+}
+
+static void sxe2_rxq_unmap_msix_intr(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter =
+ SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_irq_context *irq_ctxt = &adapter->irq_ctxt;
+
+ rte_free(irq_ctxt->rxq_msix_idx);
+ irq_ctxt->rxq_msix_idx = NULL;
+ irq_ctxt->rxq_irq_cnt = 0;
+}
+
+static int32_t sxe2_rxq_intr_register(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter =
+ SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_irq_context *irq_ctxt = &adapter->irq_ctxt;
+ struct rte_intr_handle *intr_handle = dev->intr_handle;
+ int32_t *efd_tbl = NULL;
+ uint16_t rxq_cnt = dev->data->nb_rx_queues;
+ uint16_t nb_msix = irq_ctxt->rxq_irq_cnt;
+ uint16_t i;
+ int32_t ret = 0;
+
+ if (rte_intr_type_set(intr_handle, RTE_INTR_HANDLE_EXT)) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to set intr_handle->type, error %i (%s)",
+ errno, strerror(errno));
+ ret = -EPERM;
+ goto l_end;
+ }
+
+ efd_tbl = rte_zmalloc(NULL, sizeof(int32_t) * nb_msix, 0);
+ if (!efd_tbl) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to alloc efd_tbl memory.");
+ ret = -ENOMEM;
+ goto l_end;
+ }
+
+ for (i = 0; i < nb_msix; i++) {
+ ret = sxe2_rxq_intr_efd_alloc(dev, &efd_tbl[i]);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to alloc efd_tbl, ret=%d", ret);
+ goto l_free_efd_tbl;
+ }
+ }
+
+ if (rte_intr_vec_list_alloc(intr_handle, "sxe2 rxq int", rxq_cnt)) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to allocate %d rx_queues intr_vec",
+ rxq_cnt);
+ ret = -ENOMEM;
+ goto l_free_efd_tbl;
+ }
+
+ for (i = 0; i < rxq_cnt; i++) {
+ ret = rte_intr_vec_list_index_set(intr_handle, i,
+ irq_ctxt->rxq_msix_idx[i] + RTE_INTR_VEC_RXTX_OFFSET);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to set msix_tbl, ret=%d", ret);
+ goto l_free_efd_tbl;
+ }
+ }
+
+ for (i = 0; i < irq_ctxt->rxq_irq_cnt; i++) {
+ ret = rte_intr_efds_index_set(intr_handle, i, efd_tbl[i]);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to set efd_tbl, ret=%d", ret);
+ goto l_free_efd_tbl;
+ }
+ }
+
+ if (rte_intr_nb_efd_set(intr_handle, rxq_cnt)) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Set intr nb efd failed, error %i (%s)",
+ errno, strerror(errno));
+ ret = -EPERM;
+ goto l_free_efd_tbl;
+ }
+
+ ret = sxe2_drv_dev_rxq_irq_set(adapter->cdev, 0, efd_tbl, nb_msix);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to set rxq irq, ret=%d", ret);
+ goto l_free_efd_tbl;
+ }
+ irq_ctxt->rxq_event_fd = efd_tbl;
+
+ goto l_end;
+
+l_free_efd_tbl:
+ if (efd_tbl) {
+ for (i = 0; i < nb_msix; i++)
+ if (efd_tbl[i] >= 0)
+ sxe2_rxq_intr_efd_free(efd_tbl[i]);
+ rte_free(efd_tbl);
+ }
+ irq_ctxt->rxq_event_fd = NULL;
+
+ rte_intr_vec_list_free(intr_handle);
+l_end:
+ return ret;
+}
+
+static void sxe2_rxq_intr_unregister(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter =
+ SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_irq_context *irq_ctxt = &adapter->irq_ctxt;
+ struct rte_intr_handle *intr_handle = dev->intr_handle;
+ int32_t efd = -1;
+ uint16_t msix_cnt = irq_ctxt->rxq_irq_cnt;
+ uint16_t i;
+
+ if (irq_ctxt->rxq_event_fd) {
+ for (i = 0; i < msix_cnt; i++) {
+ (void)sxe2_drv_dev_rxq_irq_set(adapter->cdev, i, &efd, 1);
+ sxe2_rxq_intr_efd_free(irq_ctxt->rxq_event_fd[i]);
+ }
+ }
+ rte_free(irq_ctxt->rxq_event_fd);
+ irq_ctxt->rxq_event_fd = NULL;
+
+ rte_intr_vec_list_free(intr_handle);
+
+ rte_intr_nb_efd_set(intr_handle, 0);
+ rte_intr_max_intr_set(intr_handle, 0);
+}
+
+int32_t sxe2_rxq_intr_enable(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter =
+ SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ uint16_t msix_vect = adapter->irq_ctxt.rxq_base_idx_in_pf;
+ uint16_t msix_cnt = adapter->irq_ctxt.rxq_avail_cnt;
+ uint16_t rxq_cnt = dev->data->nb_rx_queues;
+ uint16_t rxq_base = adapter->q_ctxt.base_idx_in_pf;
+ int32_t ret = 0;
+
+ if (!rxq_cnt)
+ goto l_end;
+
+ msix_cnt = RTE_MIN(msix_cnt, rxq_cnt);
+
+ ret = sxe2_rxq_map_msix_intr(dev, msix_vect, msix_cnt, rxq_base, rxq_cnt);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to rxq[%d] map msix[%d] intr, cnt=%d, ret=%d",
+ rxq_base, msix_vect, rxq_cnt, ret);
+ goto l_end;
+ }
+
+ if (dev->data->dev_conf.intr_conf.rxq) {
+ ret = sxe2_rxq_intr_register(dev);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to register rxq[%d] intr, ret=%d",
+ rxq_base, ret);
+ goto l_err_unmap;
+ }
+ }
+
+ ret = sxe2_rxq_msix_cfg_map(dev);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to rxq[%d] map msix[%d] intr, ret=%d",
+ rxq_base, msix_vect, ret);
+ goto l_err_unregister;
+ }
+
+ goto l_end;
+l_err_unregister:
+ if (dev->data->dev_conf.intr_conf.rxq)
+ sxe2_rxq_intr_unregister(dev);
+l_err_unmap:
+ sxe2_rxq_unmap_msix_intr(dev);
+l_end:
+ return ret;
+}
+
+void sxe2_rxq_intr_disable(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter =
+ SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_irq_context *irq_ctxt = &adapter->irq_ctxt;
+
+ if (!irq_ctxt->rxq_irq_cnt)
+ goto l_end;
+
+ sxe2_rxq_msix_cfg_unmap(dev);
+
+ if (dev->data->dev_conf.intr_conf.rxq)
+ sxe2_rxq_intr_unregister(dev);
+
+ sxe2_rxq_unmap_msix_intr(dev);
+
+l_end:
+ return;
+}
+
+int32_t sxe2_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+ struct sxe2_adapter *adapter =
+ SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_irq_context *irq_ctxt = &adapter->irq_ctxt;
+ uint64_t buf;
+ uint16_t irq_idx = irq_ctxt->rxq_msix_idx[queue_id];
+ size_t read_ret;
+
+ read_ret = read(irq_ctxt->rxq_event_fd[irq_idx], &buf, sizeof(buf));
+ (void)read_ret;
+ sxe2_pci_hw_irq_enable(adapter, irq_idx);
+ return 0;
+}
+
+int32_t sxe2_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+ struct sxe2_adapter *adapter =
+ SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ uint32_t val;
+ int32_t ret = 0;
+ uint16_t irq_idx = adapter->irq_ctxt.rxq_msix_idx[queue_id];
+
+ val = sxe2_pci_hw_irq_dyn_ctl_read(adapter, irq_idx);
+ if ((val & SXE2VF_DYN_CTL_INTENABLE) == 0) {
+ PMD_DEV_LOG_DEBUG(adapter, INIT, "rxq [%d] interrupt is disabled.", queue_id);
+ goto l_end;
+ }
+
+ sxe2_pci_hw_msix_disable(adapter, irq_idx);
+ sxe2_pci_hw_irq_trigger(adapter, irq_idx);
+ val = sxe2_pci_hw_irq_dyn_ctl_read(adapter, irq_idx);
+ sxe2_pci_hw_irq_clear_pba(adapter, irq_idx);
+ val = sxe2_pci_hw_irq_dyn_ctl_read(adapter, irq_idx);
+ sxe2_pci_hw_msix_enable(adapter, irq_idx);
+l_end:
+ return ret;
+}
diff --git a/drivers/net/sxe2/sxe2_irq.h b/drivers/net/sxe2/sxe2_irq.h
index 4ca2118b92..31216240e6 100644
--- a/drivers/net/sxe2/sxe2_irq.h
+++ b/drivers/net/sxe2/sxe2_irq.h
@@ -45,4 +45,25 @@ struct sxe2_irq_context {
int32_t *rxq_event_fd;
};
+uint32_t sxe2_drv_dev_other_cause_get(struct sxe2_adapter *adapter);
+
+int32_t sxe2_intr_init(struct rte_eth_dev *dev);
+
+void sxe2_intr_uninit(struct rte_eth_dev *dev);
+
+int32_t sxe2_sw_irq_ctxt_init(struct rte_eth_dev *dev);
+
+void sxe2_sw_irq_ctxt_uninit(struct rte_eth_dev *dev);
+
+void sxe2_sw_irq_ctx_hw_cap_set(struct sxe2_adapter *adapter,
+ struct sxe2_drv_msix_caps *msix_caps);
+
+int32_t sxe2_rxq_intr_enable(struct rte_eth_dev *dev);
+
+void sxe2_rxq_intr_disable(struct rte_eth_dev *dev);
+
+int32_t sxe2_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id);
+
+int32_t sxe2_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id);
+
#endif /* SXE2_IRQ_H */
diff --git a/drivers/net/sxe2/sxe2vf_regs.h b/drivers/net/sxe2/sxe2vf_regs.h
new file mode 100644
index 0000000000..854f1d3ae8
--- /dev/null
+++ b/drivers/net/sxe2/sxe2vf_regs.h
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#ifndef __SXE2VF_REGS_H__
+#define __SXE2VF_REGS_H__
+
+#define SXE2VF_MBX_Q_LEN_M 0x3FF
+#define SXE2VF_MBX_Q_LEN_VFE_M RTE_BIT32(28)
+
+#define SXE2VF_MBX_Q_LEN_OVFL_M RTE_BIT32(29)
+#define SXE2VF_MBX_Q_LEN_CRIT_M RTE_BIT32(30)
+#define SXE2VF_MBX_Q_LEN_ENA_M RTE_BIT32(31)
+
+#define SXE2VF_MBX_RQ_HEAD (0x00008000)
+#define SXE2VF_MBX_RQ_TAIL (0x00008400)
+#define SXE2VF_MBX_RQ_LEN (0x00007C00)
+#define SXE2VF_MBX_RQ_BAH (0x00007800)
+#define SXE2VF_MBX_RQ_BAL (0x00007400)
+
+#define SXE2VF_MBX_TQ_HEAD (0x00006C00)
+#define SXE2VF_MBX_TQ_TAIL (0x00007000)
+#define SXE2VF_MBX_TQ_LEN (0x00006800)
+#define SXE2VF_MBX_TQ_BAH (0x00006400)
+#define SXE2VF_MBX_TQ_BAL (0x00006000)
+
+#define SXE2VF_RXQ_TAIL(_QRX) (0x2000 + ((_QRX) * 4))
+#define SXE2VF_TXQ_TAIL(_QRX) (0x1000 + ((_QRX) * 4))
+
+#define SXE2VF_INT_BASE 0x00002800
+
+#define SXE2VF_DYN_CTL0 (SXE2VF_INT_BASE + 0x0)
+
+#define SXE2VF_DYN_CTL(_idx) (SXE2VF_INT_BASE + 0x4 + ((_idx) * 4))
+#define SXE2VF_VF_DYN_CTL(_idx) (SXE2VF_INT_BASE + ((_idx) * 4))
+
+#define SXE2VF_BAR4_MSIX_BASE 0
+#define SXE2VF_BAR4_MSIX_CTL(_idx) (SXE2VF_BAR4_MSIX_BASE + 0xC + ((_idx) * 0x10))
+#define SXE2VF_BAR4_MSIX_ENABLE 0
+#define SXE2VF_BAR4_MSIX_DISABLE 1
+
+#define SXE2VF_DYN_CTL_INTENABLE RTE_BIT32(0)
+#define SXE2VF_DYN_CTL_CLEARPBA RTE_BIT32(1)
+#define SXE2VF_DYN_CTL_SWINT_TRIG RTE_BIT32(2)
+#define SXE2VF_DYN_CTL_SW_ITR_IDX_ENABLE RTE_BIT32(24)
+
+#define SXE2VF_DYN_CTL_INTENABLE_MSK \
+ RTE_BIT32(31)
+
+#define SXE2VF_DYN_CTL_ITR_IDX_SHIFT 3
+
+enum sxe2vf_itr_idx {
+ SXE2VF_ITR_IDX_0 = 0,
+ SXE2VF_ITR_IDX_1,
+ SXE2VF_ITR_IDX_2,
+ SXE2VF_ITR_IDX_NONE,
+};
+
+#define SXE2VF_INT_ITR0 (0x00002800 + 65 * 0x4)
+#define SXE2VF_INT_ITR(_i, _irq_idx) (SXE2VF_INT_ITR0 + \
+ 0x4 + (_i) * 0x104 + ((_irq_idx) * 4))
+#define SXE2VF_VF_INT_ITR(_itr_idx, _irq_idx) (0x00002800 + \
+ (0x104 * (_itr_idx)) + ((_irq_idx) * 4))
+#define SXE2VF_PFG_INT_CTL_ITR_GRAN_0 (2)
+
+#define SXE2VF_PCIE_SYS_READY 0x38c
+#define SXE2VF_PCIE_SYS_READY_CORER_ASSERT RTE_BIT32(0)
+#define SXE2VF_PCIE_SYS_READY_STOP_DROP_DONE RTE_BIT32(2)
+#define SXE2VF_PCIE_SYS_READY_R5 RTE_BIT32(3)
+#define SXE2VF_PCIE_SYS_READY_STOP_DROP RTE_BIT32(16)
+
+#define SXE2VF_PCIE_DEV_CTRL_DEV_STATUS 0x78
+#define SXE2VF_PCIE_DEV_CTRL_DEV_STATUS_TRANS_PENDING RTE_BIT32(21)
+
+#define SXE2VF_VF_VRC_VFGEN_RSTAT (0x5800)
+#define SXE2VF_VF_VRC_VFGEN_VFRSTAT GENMASK(1, 0)
+#define SXE2VF_VF_VRC_VFGEN_VFRSTAT_VFR (0)
+#define SXE2VF_VF_VRC_VFGEN_VFRSTAT_COMPLETE (RTE_BIT32(0))
+#define SXE2VF_VF_VRC_VFGEN_VFRSTAT_VF_ACTIVE (RTE_BIT32(1))
+
+#define SXE2VF_VF_VRC_VFGEN_VFRSTAT_FORVF_VFR (1)
+#define SXE2VF_VF_VRC_VFGEN_VFRSTAT_FORVF_MASK \
+ (RTE_BIT32(10))
+
+#endif /* SXE2VF_VF_INT_ITR */
--
2.52.0
^ permalink raw reply related
* [PATCH v2 05/20] drivers: support RSS feature
From: liujie5 @ 2026-06-14 9:23 UTC (permalink / raw)
To: stephen; +Cc: dev, Jie Liu
In-Reply-To: <20260614092328.201826-1-liujie5@linkdatatechnology.com>
From: Jie Liu <liujie5@linkdatatechnology.com>
Add support for Receive Side Scaling (RSS) to distribute incoming
traffic across multiple receive queues.
- Implement rss_hash_update and rss_hash_conf_get.
- Implement reta_update and reta_query.
- Support RSS hash configuration for IPv4, IPv6, TCP and UDP.
- Default hash key is initialized during port start.
Signed-off-by: Jie Liu <liujie5@linkdatatechnology.com>
---
drivers/common/sxe2/sxe2_flow_public.h | 633 +++++++++++++++++++++++++
drivers/net/sxe2/meson.build | 1 +
drivers/net/sxe2/sxe2_cmd_chnl.c | 173 +++++++
drivers/net/sxe2/sxe2_cmd_chnl.h | 16 +
drivers/net/sxe2/sxe2_drv_cmd.h | 29 ++
drivers/net/sxe2/sxe2_ethdev.c | 37 ++
drivers/net/sxe2/sxe2_ethdev.h | 8 +
drivers/net/sxe2/sxe2_flow_define.h | 143 ++++++
drivers/net/sxe2/sxe2_queue.c | 11 +
| 584 +++++++++++++++++++++++
| 81 ++++
drivers/net/sxe2/sxe2_txrx.h | 4 +
drivers/net/sxe2/sxe2_txrx_poll.c | 85 +++-
13 files changed, 1804 insertions(+), 1 deletion(-)
create mode 100644 drivers/common/sxe2/sxe2_flow_public.h
create mode 100644 drivers/net/sxe2/sxe2_flow_define.h
create mode 100644 drivers/net/sxe2/sxe2_rss.c
create mode 100644 drivers/net/sxe2/sxe2_rss.h
diff --git a/drivers/common/sxe2/sxe2_flow_public.h b/drivers/common/sxe2/sxe2_flow_public.h
new file mode 100644
index 0000000000..32ab2a9713
--- /dev/null
+++ b/drivers/common/sxe2/sxe2_flow_public.h
@@ -0,0 +1,633 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#ifndef __SXE2_FLOW_PUBLIC_H__
+#define __SXE2_FLOW_PUBLIC_H__
+#include "sxe2_osal.h"
+
+enum sxe2_flow_type {
+ SXE2_FLOW_TYPE_NONE = 0,
+ SXE2_FLOW_MAC_PAY = 1,
+ SXE2_FLOW_MAC_IPV4_FRAG_PAY = 22,
+ SXE2_FLOW_MAC_IPV4_PAY = 23,
+ SXE2_FLOW_MAC_IPV4_UDP_PAY = 24,
+ SXE2_FLOW_MAC_IPV4_TCP_PAY = 26,
+ SXE2_FLOW_MAC_IPV4_SCTP_PAY = 27,
+ SXE2_FLOW_MAC_IPV4_IPV4_FRAG_PAY = 29,
+ SXE2_FLOW_MAC_IPV4_IPV4_PAY = 30,
+ SXE2_FLOW_MAC_IPV4_IPV4_UDP_PAY = 31,
+ SXE2_FLOW_MAC_IPV4_IPV4_TCP_PAY = 33,
+ SXE2_FLOW_MAC_IPV4_IPV4_SCTP_PAY = 34,
+ SXE2_FLOW_MAC_IPV4_IPV6_FRAG_PAY = 36,
+ SXE2_FLOW_MAC_IPV4_IPV6_PAY = 37,
+ SXE2_FLOW_MAC_IPV4_IPV6_UDP_PAY = 38,
+ SXE2_FLOW_MAC_IPV4_IPV6_TCP_PAY = 40,
+ SXE2_FLOW_MAC_IPV4_IPV6_SCTP_PAY = 41,
+ SXE2_FLOW_MAC_IPV4_GRE_PAY = 43,
+ SXE2_FLOW_MAC_IPV4_GRE_IPV4_FRAG_PAY = 44,
+ SXE2_FLOW_MAC_IPV4_GRE_IPV4_PAY = 45,
+ SXE2_FLOW_MAC_IPV4_GRE_IPV4_UDP_PAY = 46,
+ SXE2_FLOW_MAC_IPV4_GRE_IPV4_TCP_PAY = 48,
+ SXE2_FLOW_MAC_IPV4_GRE_IPV4_SCTP_PAY = 49,
+ SXE2_FLOW_MAC_IPV4_GRE_IPV6_FRAG_PAY = 51,
+ SXE2_FLOW_MAC_IPV4_GRE_IPV6_PAY = 52,
+ SXE2_FLOW_MAC_IPV4_GRE_IPV6_UDP_PAY = 53,
+ SXE2_FLOW_MAC_IPV4_GRE_IPV6_TCP_PAY = 55,
+ SXE2_FLOW_MAC_IPV4_GRE_IPV6_SCTP_PAY = 56,
+ SXE2_FLOW_MAC_IPV4_GRE_MAC_PAY = 58,
+ SXE2_FLOW_MAC_IPV4_GRE_MAC_IPV4_FRAG_PAY = 59,
+ SXE2_FLOW_MAC_IPV4_GRE_MAC_IPV4_PAY = 60,
+ SXE2_FLOW_MAC_IPV4_GRE_MAC_IPV4_UDP_PAY = 61,
+ SXE2_FLOW_MAC_IPV4_GRE_MAC_IPV4_TCP_PAY = 63,
+ SXE2_FLOW_MAC_IPV4_GRE_MAC_IPV4_SCTP_PAY = 64,
+ SXE2_FLOW_MAC_IPV4_GRE_MAC_IPV6_FRAG_PAY = 66,
+ SXE2_FLOW_MAC_IPV4_GRE_MAC_IPV6_PAY = 67,
+ SXE2_FLOW_MAC_IPV4_GRE_MAC_IPV6_UDP_PAY = 68,
+ SXE2_FLOW_MAC_IPV4_GRE_MAC_IPV6_TCP_PAY = 70,
+ SXE2_FLOW_MAC_IPV4_GRE_MAC_IPV6_SCTP_PAY = 71,
+ SXE2_FLOW_MAC_IPV4_GRE_MAC_VLAN_PAY = 73,
+ SXE2_FLOW_MAC_IPV4_GRE_MAC_VLAN_IPV4_FRAG_PAY = 74,
+ SXE2_FLOW_MAC_IPV4_GRE_MAC_VLAN_IPV4_PAY = 75,
+ SXE2_FLOW_MAC_IPV4_GRE_MAC_VLAN_IPV4_UDP_PAY = 76,
+ SXE2_FLOW_MAC_IPV4_GRE_MAC_VLAN_IPV4_TCP_PAY = 78,
+ SXE2_FLOW_MAC_IPV4_GRE_MAC_VLAN_IPV4_SCTP_PAY = 79,
+ SXE2_FLOW_MAC_IPV4_GRE_MAC_VLAN_IPV6_FRAG_PAY = 81,
+ SXE2_FLOW_MAC_IPV4_GRE_MAC_VLAN_IPV6_PAY = 82,
+ SXE2_FLOW_MAC_IPV4_GRE_MAC_VLAN_IPV6_UDP_PAY = 83,
+ SXE2_FLOW_MAC_IPV4_GRE_MAC_VLAN_IPV6_TCP_PAY = 85,
+ SXE2_FLOW_MAC_IPV4_GRE_MAC_VLAN_IPV6_SCTP_PAY = 86,
+ SXE2_FLOW_MAC_IPV6_FRAG_PAY = 88,
+ SXE2_FLOW_MAC_IPV6_PAY = 89,
+ SXE2_FLOW_MAC_IPV6_UDP_PAY = 90,
+ SXE2_FLOW_MAC_IPV6_TCP_PAY = 92,
+ SXE2_FLOW_MAC_IPV6_SCTP_PAY = 93,
+ SXE2_FLOW_MAC_IPV6_IPV4_FRAG_PAY = 95,
+ SXE2_FLOW_MAC_IPV6_IPV4_PAY = 96,
+ SXE2_FLOW_MAC_IPV6_IPV4_UDP_PAY = 97,
+ SXE2_FLOW_MAC_IPV6_IPV4_TCP_PAY = 99,
+ SXE2_FLOW_MAC_IPV6_IPV4_SCTP_PAY = 100,
+ SXE2_FLOW_MAC_IPV6_IPV6_FRAG_PAY = 102,
+ SXE2_FLOW_MAC_IPV6_IPV6_PAY = 103,
+ SXE2_FLOW_MAC_IPV6_IPV6_UDP_PAY = 104,
+ SXE2_FLOW_MAC_IPV6_IPV6_TCP_PAY = 106,
+ SXE2_FLOW_MAC_IPV6_IPV6_SCTP_PAY = 107,
+ SXE2_FLOW_MAC_IPV6_GRE_PAY = 109,
+ SXE2_FLOW_MAC_IPV6_GRE_IPV4_FRAG_PAY = 110,
+ SXE2_FLOW_MAC_IPV6_GRE_IPV4_PAY = 111,
+ SXE2_FLOW_MAC_IPV6_GRE_IPV4_UDP_PAY = 112,
+ SXE2_FLOW_MAC_IPV6_GRE_IPV4_TCP_PAY = 114,
+ SXE2_FLOW_MAC_IPV6_GRE_IPV4_SCTP_PAY = 115,
+ SXE2_FLOW_MAC_IPV6_GRE_IPV6_FRAG_PAY = 117,
+ SXE2_FLOW_MAC_IPV6_GRE_IPV6_PAY = 118,
+ SXE2_FLOW_MAC_IPV6_GRE_IPV6_UDP_PAY = 119,
+ SXE2_FLOW_MAC_IPV6_GRE_IPV6_TCP_PAY = 121,
+ SXE2_FLOW_MAC_IPV6_GRE_IPV6_SCTP_PAY = 122,
+ SXE2_FLOW_MAC_IPV6_GRE_MAC_PAY = 124,
+ SXE2_FLOW_MAC_IPV6_GRE_MAC_IPV4_FRAG_PAY = 125,
+ SXE2_FLOW_MAC_IPV6_GRE_MAC_IPV4_PAY = 126,
+ SXE2_FLOW_MAC_IPV6_GRE_MAC_IPV4_UDP_PAY = 127,
+ SXE2_FLOW_MAC_IPV6_GRE_MAC_IPV4_TCP_PAY = 129,
+ SXE2_FLOW_MAC_IPV6_GRE_MAC_IPV4_SCTP_PAY = 130,
+ SXE2_FLOW_MAC_IPV6_GRE_MAC_IPV6_FRAG_PAY = 132,
+ SXE2_FLOW_MAC_IPV6_GRE_MAC_IPV6_PAY = 133,
+ SXE2_FLOW_MAC_IPV6_GRE_MAC_IPV6_UDP_PAY = 134,
+ SXE2_FLOW_MAC_IPV6_GRE_MAC_IPV6_TCP_PAY = 136,
+ SXE2_FLOW_MAC_IPV6_GRE_MAC_IPV6_SCTP_PAY = 137,
+ SXE2_FLOW_MAC_IPV6_GRE_MAC_VLAN_PAY = 139,
+ SXE2_FLOW_MAC_IPV6_GRE_MAC_VLAN_IPV4_FRAG_PAY = 140,
+ SXE2_FLOW_MAC_IPV6_GRE_MAC_VLAN_IPV4_PAY = 141,
+ SXE2_FLOW_MAC_IPV6_GRE_MAC_VLAN_IPV4_UDP_PAY = 142,
+ SXE2_FLOW_MAC_IPV6_GRE_MAC_VLAN_IPV4_TCP_PAY = 144,
+ SXE2_FLOW_MAC_IPV6_GRE_MAC_VLAN_IPV4_SCTP_PAY = 145,
+ SXE2_FLOW_MAC_IPV6_GRE_MAC_VLAN_IPV6_FRAG_PAY = 147,
+ SXE2_FLOW_MAC_IPV6_GRE_MAC_VLAN_IPV6_PAY = 148,
+ SXE2_FLOW_MAC_IPV6_GRE_MAC_VLAN_IPV6_UDP_PAY = 149,
+ SXE2_FLOW_MAC_IPV6_GRE_MAC_VLAN_IPV6_TCP_PAY = 151,
+ SXE2_FLOW_MAC_IPV6_GRE_MAC_VLAN_IPV6_SCTP_PAY = 152,
+ SXE2_FLOW_MAC_IPV4_UDP_GTPU_PAY = 329,
+ SXE2_FLOW_MAC_IPV6_UDP_GTPU_PAY = 330,
+ SXE2_FLOW_MAC_IPV4_UDP_GTPU_IPV4_FRAG_PAY = 331,
+ SXE2_FLOW_MAC_IPV4_UDP_GTPU_IPV4_PAY = 332,
+ SXE2_FLOW_MAC_IPV4_UDP_GTPU_IPV4_UDP_PAY = 333,
+ SXE2_FLOW_MAC_IPV4_UDP_GTPU_IPV4_TCP_PAY = 334,
+ SXE2_FLOW_MAC_IPV4_UDP_GTPU_IPV4_SCTP_PAY = 335,
+ SXE2_FLOW_MAC_IPV6_UDP_GTPU_IPV4_FRAG_PAY = 336,
+ SXE2_FLOW_MAC_IPV6_UDP_GTPU_IPV4_PAY = 337,
+ SXE2_FLOW_MAC_IPV6_UDP_GTPU_IPV4_UDP_PAY = 338,
+ SXE2_FLOW_MAC_IPV6_UDP_GTPU_IPV4_TCP_PAY = 339,
+ SXE2_FLOW_MAC_IPV6_UDP_GTPU_IPV4_SCTP_PAY = 340,
+ SXE2_FLOW_MAC_IPV4_UDP_GTPU_IPV6_FRAG_PAY = 341,
+ SXE2_FLOW_MAC_IPV4_UDP_GTPU_IPV6_PAY = 342,
+ SXE2_FLOW_MAC_IPV4_UDP_GTPU_IPV6_UDP_PAY = 343,
+ SXE2_FLOW_MAC_IPV4_UDP_GTPU_IPV6_TCP_PAY = 344,
+ SXE2_FLOW_MAC_IPV4_UDP_GTPU_IPV6_SCTP_PAY = 345,
+ SXE2_FLOW_MAC_IPV6_UDP_GTPU_IPV6_FRAG_PAY = 346,
+ SXE2_FLOW_MAC_IPV6_UDP_GTPU_IPV6_PAY = 347,
+ SXE2_FLOW_MAC_IPV6_UDP_GTPU_IPV6_UDP_PAY = 348,
+ SXE2_FLOW_MAC_IPV6_UDP_GTPU_IPV6_TCP_PAY = 349,
+ SXE2_FLOW_MAC_IPV6_UDP_GTPU_IPV6_SCTP_PAY = 350,
+ SXE2_FLOW_MAC_IPV6_MAC_PAY = 820,
+ SXE2_FLOW_MAC_IPV6_MAC_IPV4_FRAG_PAY = 821,
+ SXE2_FLOW_MAC_IPV6_MAC_IPV4_PAY = 822,
+ SXE2_FLOW_MAC_IPV6_MAC_IPV4_UDP_PAY = 823,
+ SXE2_FLOW_MAC_IPV6_MAC_IPV4_TCP_PAY = 824,
+ SXE2_FLOW_MAC_IPV6_MAC_IPV4_SCTP_PAY = 825,
+ SXE2_FLOW_MAC_IPV6_MAC_IPV6_FRAG_PAY = 827,
+ SXE2_FLOW_MAC_IPV6_MAC_IPV6_PAY = 828,
+ SXE2_FLOW_MAC_IPV6_MAC_IPV6_UDP_PAY = 829,
+ SXE2_FLOW_MAC_IPV6_MAC_IPV6_TCP_PAY = 830,
+ SXE2_FLOW_MAC_IPV6_MAC_IPV6_SCTP_PAY = 831,
+ SXE2_FLOW_MAC_IPV6_MAC_VLAN_PAY = 835,
+ SXE2_FLOW_MAC_IPV6_MAC_VLAN_IPV4_FRAG_PAY = 836,
+ SXE2_FLOW_MAC_IPV6_MAC_VLAN_IPV4_PAY = 837,
+ SXE2_FLOW_MAC_IPV6_MAC_VLAN_IPV4_UDP_PAY = 838,
+ SXE2_FLOW_MAC_IPV6_MAC_VLAN_IPV4_TCP_PAY = 839,
+ SXE2_FLOW_MAC_IPV6_MAC_VLAN_IPV4_SCTP_PAY = 840,
+ SXE2_FLOW_MAC_IPV6_MAC_VLAN_IPV6_FRAG_PAY = 842,
+ SXE2_FLOW_MAC_IPV6_MAC_VLAN_IPV6_PAY = 843,
+ SXE2_FLOW_MAC_IPV6_MAC_VLAN_IPV6_UDP_PAY = 844,
+ SXE2_FLOW_MAC_IPV6_MAC_VLAN_IPV6_TCP_PAY = 845,
+ SXE2_FLOW_MAC_IPV6_MAC_VLAN_IPV6_SCTP_PAY = 846,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_PAY = 878,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_IPV4_FRAG_PAY = 877,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_IPV4_PAY = 876,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_IPV4_UDP_PAY = 879,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_IPV4_TCP_PAY = 880,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_IPV4_SCTP_PAY = 875,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_IPV6_FRAG_PAY = 871,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_IPV6_PAY = 870,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_IPV6_UDP_PAY = 872,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_IPV6_TCP_PAY = 873,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_IPV6_SCTP_PAY = 869,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_PAY = 891,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_IPV4_FRAG_PAY = 890,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_IPV4_PAY = 889,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_IPV4_UDP_PAY = 892,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_IPV4_TCP_PAY = 893,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_IPV4_SCTP_PAY = 888,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_IPV6_FRAG_PAY = 884,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_IPV6_PAY = 883,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_IPV6_UDP_PAY = 885,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_IPV6_TCP_PAY = 886,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_IPV6_SCTP_PAY = 882,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_PAY = 904,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_IPV4_FRAG_PAY = 903,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_IPV4_PAY = 902,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_IPV4_UDP_PAY = 905,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_IPV4_TCP_PAY = 906,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_IPV4_SCTP_PAY = 901,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_IPV6_FRAG_PAY = 897,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_IPV6_PAY = 896,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_IPV6_UDP_PAY = 898,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_IPV6_TCP_PAY = 899,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_IPV6_SCTP_PAY = 895,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_PAY = 917,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_IPV4_FRAG_PAY = 916,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_IPV4_PAY = 915,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_IPV4_UDP_PAY = 918,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_IPV4_TCP_PAY = 919,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_IPV4_SCTP_PAY = 914,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_IPV6_FRAG_PAY = 910,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_IPV6_PAY = 909,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_IPV6_UDP_PAY = 911,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_IPV6_TCP_PAY = 912,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_IPV6_SCTP_PAY = 908,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_MAC_VLAN_PAY = 930,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_MAC_VLAN_IPV4_FRAG_PAY = 929,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_MAC_VLAN_IPV4_PAY = 928,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_MAC_VLAN_IPV4_UDP_PAY = 931,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_MAC_VLAN_IPV4_TCP_PAY = 932,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_MAC_VLAN_IPV4_SCTP_PAY = 927,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_MAC_VLAN_IPV6_FRAG_PAY = 923,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_MAC_VLAN_IPV6_PAY = 922,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_MAC_VLAN_IPV6_UDP_PAY = 924,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_MAC_VLAN_IPV6_TCP_PAY = 925,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_MAC_VLAN_IPV6_SCTP_PAY = 921,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_MAC_VLAN_PAY = 943,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_MAC_VLAN_IPV4_FRAG_PAY = 942,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_MAC_VLAN_IPV4_PAY = 941,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_MAC_VLAN_IPV4_UDP_PAY = 944,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_MAC_VLAN_IPV4_TCP_PAY = 945,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_MAC_VLAN_IPV4_SCTP_PAY = 940,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_MAC_VLAN_IPV6_FRAG_PAY = 936,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_MAC_VLAN_IPV6_PAY = 935,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_MAC_VLAN_IPV6_UDP_PAY = 937,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_MAC_VLAN_IPV6_TCP_PAY = 938,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_MAC_VLAN_IPV6_SCTP_PAY = 934,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_MAC_VLAN_PAY = 956,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_MAC_VLAN_IPV4_FRAG_PAY = 955,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_MAC_VLAN_IPV4_PAY = 954,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_MAC_VLAN_IPV4_UDP_PAY = 957,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_MAC_VLAN_IPV4_TCP_PAY = 958,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_MAC_VLAN_IPV4_SCTP_PAY = 953,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_MAC_VLAN_IPV6_FRAG_PAY = 949,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_MAC_VLAN_IPV6_PAY = 948,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_MAC_VLAN_IPV6_UDP_PAY = 950,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_MAC_VLAN_IPV6_TCP_PAY = 951,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_MAC_VLAN_IPV6_SCTP_PAY = 947,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_MAC_VLAN_PAY = 969,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_MAC_VLAN_IPV4_FRAG_PAY = 968,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_MAC_VLAN_IPV4_PAY = 967,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_MAC_VLAN_IPV4_UDP_PAY = 970,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_MAC_VLAN_IPV4_TCP_PAY = 971,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_MAC_VLAN_IPV4_SCTP_PAY = 966,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_MAC_VLAN_IPV6_FRAG_PAY = 962,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_MAC_VLAN_IPV6_PAY = 961,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_MAC_VLAN_IPV6_UDP_PAY = 963,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_MAC_VLAN_IPV6_TCP_PAY = 964,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_MAC_VLAN_IPV6_SCTP_PAY = 960,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_MAC_PAY = 982,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_MAC_IPV4_FRAG_PAY = 981,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_MAC_IPV4_PAY = 980,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_MAC_IPV4_UDP_PAY = 983,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_MAC_IPV4_TCP_PAY = 984,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_MAC_IPV4_SCTP_PAY = 979,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_MAC_IPV6_FRAG_PAY = 975,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_MAC_IPV6_PAY = 974,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_MAC_IPV6_UDP_PAY = 976,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_MAC_IPV6_TCP_PAY = 977,
+ SXE2_FLOW_MAC_IPV6_UDP_VXGEN_MAC_IPV6_SCTP_PAY = 973,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_MAC_PAY = 995,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_MAC_IPV4_FRAG_PAY = 994,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_MAC_IPV4_PAY = 993,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_MAC_IPV4_UDP_PAY = 996,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_MAC_IPV4_TCP_PAY = 997,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_MAC_IPV4_SCTP_PAY = 992,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_MAC_IPV6_FRAG_PAY = 988,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_MAC_IPV6_PAY = 987,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_MAC_IPV6_UDP_PAY = 989,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_MAC_IPV6_TCP_PAY = 990,
+ SXE2_FLOW_MAC_IPV4_UDP_VXGEN_MAC_IPV6_SCTP_PAY = 986,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_MAC_PAY = 1008,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_MAC_IPV4_FRAG_PAY = 1007,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_MAC_IPV4_PAY = 1006,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_MAC_IPV4_UDP_PAY = 1009,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_MAC_IPV4_TCP_PAY = 1010,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_MAC_IPV4_SCTP_PAY = 1005,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_MAC_IPV6_FRAG_PAY = 1001,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_MAC_IPV6_PAY = 1000,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_MAC_IPV6_UDP_PAY = 1002,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_MAC_IPV6_TCP_PAY = 1003,
+ SXE2_FLOW_MAC_IPV6_UDP_GRE_MAC_IPV6_SCTP_PAY = 999,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_MAC_PAY = 1021,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_MAC_IPV4_FRAG_PAY = 1020,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_MAC_IPV4_PAY = 1019,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_MAC_IPV4_UDP_PAY = 1022,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_MAC_IPV4_TCP_PAY = 1023,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_MAC_IPV4_SCTP_PAY = 1018,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_MAC_IPV6_FRAG_PAY = 1014,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_MAC_IPV6_PAY = 1013,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_MAC_IPV6_UDP_PAY = 1015,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_MAC_IPV6_TCP_PAY = 1016,
+ SXE2_FLOW_MAC_IPV4_UDP_GRE_MAC_IPV6_SCTP_PAY = 1012,
+ SXE2_FLOW_TYPE_MAX = 2048,
+};
+
+enum sxe2_rss_cfg_hdr_type {
+ SXE2_RSS_OUTER_HEADERS,
+ SXE2_RSS_INNER_HEADERS,
+
+ SXE2_RSS_INNER_HEADERS_WITH_OUTER_IPV4,
+
+ SXE2_RSS_INNER_HEADERS_WITH_OUTER_IPV6,
+
+ SXE2_RSS_INNER_HEADERS_WITH_OUTER_IPV4_GRE,
+
+ SXE2_RSS_INNER_HEADERS_WITH_OUTER_IPV6_GRE,
+
+ SXE2_RSS_INNER_HEADERS_WITH_OUTER_IPV4_UDP_GRE,
+
+ SXE2_RSS_INNER_HEADERS_WITH_OUTER_IPV6_UDP_GRE,
+
+ SXE2_RSS_INNER_HEADERS_WITH_OUTER_IPV4_UDP_VXLAN,
+
+ SXE2_RSS_INNER_HEADERS_WITH_OUTER_IPV6_UDP_VXLAN,
+
+ SXE2_RSS_INNER_HEADERS_WITH_OUTER_IPV4_UDP_GENEVE,
+
+ SXE2_RSS_INNER_HEADERS_WITH_OUTER_IPV6_UDP_GENEVE,
+
+ SXE2_RSS_INNER_HEADERS_WITH_OUTER_IPV4_UDP_GTPU,
+
+ SXE2_RSS_INNER_HEADERS_WITH_OUTER_IPV6_UDP_GTPU,
+ SXE2_RSS_ANY_HEADERS
+};
+
+enum sxe2_flow_hdr {
+ SXE2_FLOW_HDR_ETH = 0,
+ SXE2_FLOW_HDR_VLAN,
+ SXE2_FLOW_HDR_QINQ,
+ SXE2_FLOW_HDR_IPV4,
+ SXE2_FLOW_HDR_IPV6,
+ SXE2_FLOW_HDR_ICMP = 5,
+ SXE2_FLOW_HDR_TCP,
+ SXE2_FLOW_HDR_UDP,
+ SXE2_FLOW_HDR_SCTP,
+ SXE2_FLOW_HDR_GRE,
+ SXE2_FLOW_HDR_VXLAN = 10,
+ SXE2_FLOW_HDR_GENEVE,
+ SXE2_FLOW_HDR_GTPU,
+
+ SXE2_FLOW_HDR_IPV_FRAG,
+
+ SXE2_FLOW_HDR_IPV_OTHER,
+
+ SXE2_FLOW_HDR_ETH_NON_IP = 15,
+ SXE2_FLOW_HDR_MAX = 128,
+};
+
+enum sxe2_flow_fld_id {
+ SXE2_FLOW_FLD_ID_ETH_DA = 0,
+ SXE2_FLOW_FLD_ID_ETH_SA,
+ SXE2_FLOW_FLD_ID_S_TCI,
+ SXE2_FLOW_FLD_ID_C_TCI,
+ SXE2_FLOW_FLD_ID_S_TPID,
+ SXE2_FLOW_FLD_ID_C_TPID = 5,
+ SXE2_FLOW_FLD_ID_S_VID,
+ SXE2_FLOW_FLD_ID_C_VID,
+ SXE2_FLOW_FLD_ID_ETH_TYPE,
+
+ SXE2_FLOW_FLD_ID_IPV4_TOS,
+ SXE2_FLOW_FLD_ID_IPV6_DSCP = 10,
+ SXE2_FLOW_FLD_ID_IPV4_TTL,
+ SXE2_FLOW_FLD_ID_IPV4_PROT,
+ SXE2_FLOW_FLD_ID_IPV6_TTL,
+ SXE2_FLOW_FLD_ID_IPV6_PROT,
+ SXE2_FLOW_FLD_ID_IPV4_SA = 15,
+ SXE2_FLOW_FLD_ID_IPV4_DA,
+ SXE2_FLOW_FLD_ID_IPV6_SA,
+ SXE2_FLOW_FLD_ID_IPV6_DA,
+ SXE2_FLOW_FLD_ID_IPV4_CHKSUM,
+ SXE2_FLOW_FLD_ID_IPV4_ID = 20,
+ SXE2_FLOW_FLD_ID_IPV6_ID,
+ SXE2_FLOW_FLD_ID_IPV6_PRE32_SA,
+ SXE2_FLOW_FLD_ID_IPV6_PRE32_DA,
+ SXE2_FLOW_FLD_ID_IPV6_PRE48_SA,
+ SXE2_FLOW_FLD_ID_IPV6_PRE48_DA = 25,
+ SXE2_FLOW_FLD_ID_IPV6_PRE64_SA,
+ SXE2_FLOW_FLD_ID_IPV6_PRE64_DA,
+
+ SXE2_FLOW_FLD_ID_TCP_SRC_PORT,
+ SXE2_FLOW_FLD_ID_TCP_DST_PORT,
+ SXE2_FLOW_FLD_ID_UDP_SRC_PORT = 30,
+ SXE2_FLOW_FLD_ID_UDP_DST_PORT,
+ SXE2_FLOW_FLD_ID_SCTP_SRC_PORT,
+ SXE2_FLOW_FLD_ID_SCTP_DST_PORT,
+ SXE2_FLOW_FLD_ID_TCP_FLAGS,
+ SXE2_FLOW_FLD_ID_TCP_CHKSUM = 35,
+ SXE2_FLOW_FLD_ID_UDP_CHKSUM,
+ SXE2_FLOW_FLD_ID_SCTP_CHKSUM,
+
+ SXE2_FLOW_FLD_ID_VXLAN_VNI,
+
+ SXE2_FLOW_FLD_ID_GENEVE_VNI,
+
+ SXE2_FLOW_FLD_ID_GTPU_TEID = 40,
+
+ SXE2_FLOW_FLD_ID_NVGRE_TNI,
+
+ SXE2_FLOW_FLD_ID_MAX = 128,
+};
+
+struct sxe2_ether_hdr {
+ uint8_t dst_addr[SXE2_ETH_ALEN];
+ uint8_t src_addr[SXE2_ETH_ALEN];
+ uint16_t ether_type;
+};
+
+struct sxe2_vlan_hdr {
+ uint16_t type;
+ uint16_t vlan;
+};
+
+struct sxe2_ipv4_hdr {
+ uint8_t ver_ihl;
+ uint8_t tos;
+ uint16_t tot_len;
+ uint16_t id;
+ uint16_t frag_off;
+ uint8_t ttl;
+ uint8_t protocol;
+ uint16_t check;
+ uint32_t saddr;
+ uint32_t daddr;
+};
+#define SXE2_IPV6_ADDR_LENGTH (16)
+#define SXE2_IPV6_TC_SHIFT (20)
+#define SXE2_IPV6_TC_MASK (0xFF)
+
+struct sxe2_ipv6_hdr {
+ uint32_t pri_ver_flow;
+ uint16_t payload_len;
+ uint8_t nexthdr;
+ uint8_t hop_limit;
+ union {
+ uint8_t saddr[16];
+ uint16_t saddr16[8];
+ uint32_t saddr32[4];
+ };
+ union {
+ uint8_t daddr[16];
+ uint16_t daddr16[8];
+ uint32_t daddr32[4];
+ };
+};
+
+struct sxe2_tcp_hdr {
+ uint16_t source;
+ uint16_t dest;
+ uint32_t seq;
+ uint32_t ack_seq;
+ uint16_t flag;
+ uint16_t window;
+ uint16_t check;
+ uint16_t urg_ptr;
+};
+
+struct sxe2_udp_hdr {
+ uint16_t source;
+ uint16_t dest;
+ uint16_t len;
+ uint16_t check;
+};
+
+struct sxe2_sctp_hdr {
+ uint16_t src_port;
+ uint16_t dst_port;
+};
+
+struct sxe2_nvgre_hdr {
+ uint16_t flags;
+ uint16_t protocol;
+ uint32_t tni;
+};
+struct sxe2_geneve_hdr {
+ uint16_t flags;
+ uint16_t protocol;
+ uint32_t vni;
+};
+struct sxe2_gtpu_hdr {
+ uint8_t flag;
+ uint8_t msg_type;
+ uint16_t msg_len;
+ uint32_t teid;
+};
+struct sxe2_vxlan_hdr {
+ uint8_t flag;
+ uint8_t resvd0;
+ uint8_t resvd1;
+ uint8_t protocol;
+ uint32_t vni;
+};
+
+enum sxe2_flow_act_type {
+ SXE2_FLOW_ACTION_DROP = 0,
+ SXE2_FLOW_ACTION_TC_REDIRECT,
+ SXE2_FLOW_ACTION_TO_VSI,
+ SXE2_FLOW_ACTION_TO_VSI_LIST,
+ SXE2_FLOW_ACTION_PASSTHRU,
+ SXE2_FLOW_ACTION_QUEUE,
+ SXE2_FLOW_ACTION_Q_REGION,
+ SXE2_FLOW_ACTION_MARK,
+ SXE2_FLOW_ACTION_COUNT,
+ SXE2_FLOW_ACTION_RSS,
+ SXE2_FLOW_ACTION_MAX = 32,
+};
+
+enum sxe2_rss_hash_key_func {
+ SXE2_RSS_HASH_FUNC_TOEPLITZ = 0,
+ SXE2_RSS_HASH_FUNC_SYM_TOEPLITZ = 1,
+ SXE2_RSS_HASH_FUNC_XOR = 2,
+ SXE2_RSS_HASH_FUNC_JEKINS = 3
+};
+
+struct sxe2_flow_action_rss {
+ DECLARE_BITMAP(hdr_out, SXE2_FLOW_HDR_MAX);
+ DECLARE_BITMAP(hdr_in, SXE2_FLOW_HDR_MAX);
+ DECLARE_BITMAP(fld, SXE2_FLOW_FLD_ID_MAX);
+ uint8_t is_inner;
+ uint8_t func;
+ uint8_t hdr_type;
+};
+
+struct sxe2_flow_action_queue {
+ uint16_t vsi_index;
+ uint16_t q_index;
+};
+
+struct sxe2_flow_action_queue_region {
+ uint16_t vsi_index;
+ uint16_t q_index;
+ uint8_t region;
+};
+
+struct sxe2_flow_action_passthru {
+ uint16_t vsi_index;
+};
+
+struct sxe2_flow_action_mark {
+ uint32_t mark_id;
+};
+
+#define SXE2_VSI_MAX (2048)
+struct sxe2_flow_action_vsi {
+ uint16_t vsi_index;
+};
+
+struct sxe2_flow_action_vsi_list {
+ DECLARE_BITMAP(vsi_list_map, SXE2_VSI_MAX);
+ uint16_t vsi_cnt;
+};
+
+enum sxe2_fnav_stat_ctrl_type {
+ SXE2_FNAV_STAT_ENA_NONE = 0,
+ SXE2_FNAV_STAT_ENA_PKTS,
+ SXE2_FNAV_STAT_ENA_BYTES,
+ SXE2_FNAV_STAT_ENA_ALL,
+};
+
+struct sxe2_flow_action_count {
+ uint32_t user_id;
+ uint32_t driver_id;
+ uint32_t stat_index;
+ uint32_t stat_ctrl;
+};
+
+enum sxe2_flow_engine_type {
+ SXE2_FLOW_ENGINE_ACL,
+ SXE2_FLOW_ENGINE_SWITCH,
+ SXE2_FLOW_ENGINE_FNAV,
+ SXE2_FLOW_ENGINE_RSS,
+ SXE2_FLOW_ENGINE_MAX,
+};
+
+struct sxe2_flow_item {
+ struct sxe2_ether_hdr eth;
+ struct sxe2_vlan_hdr vlan;
+ struct sxe2_vlan_hdr qinq;
+ struct sxe2_ipv4_hdr ipv4;
+ struct sxe2_ipv6_hdr ipv6;
+ struct sxe2_udp_hdr udp;
+ struct sxe2_tcp_hdr tcp;
+ struct sxe2_sctp_hdr sctp;
+ struct sxe2_gtpu_hdr gtpu;
+ struct sxe2_vxlan_hdr vxlan;
+ struct sxe2_nvgre_hdr nvgre;
+ struct sxe2_geneve_hdr geneve;
+};
+
+enum sxe2_flow_sw_direct_type {
+ SXE2_FLOW_SW_DIRECT_TX,
+ SXE2_FLOW_SW_DIRECT_RX,
+ SXE2_FLOW_SW_DIRECT_MAX,
+};
+enum sxe2_flow_sw_pattern_type {
+ SXE2_FLOW_SW_PATTERN_ONLY,
+ SXE2_FLOW_SW_PATTERN_LAST,
+ SXE2_FLOW_SW_PATTERN_FIRST,
+ SXE2_FLOW_SW_PATTERN_MAX,
+};
+
+enum sxe2_flow_tunnel_type {
+ SXE2_FLOW_TUNNEL_TYPE_NONE,
+ SXE2_FLOW_TUNNEL_TYPE_PARENT,
+ SXE2_FLOW_TUNNEL_TYPE_VXLAN,
+ SXE2_FLOW_TUNNEL_TYPE_GTPU,
+ SXE2_FLOW_TUNNEL_TYPE_GENEVE,
+ SXE2_FLOW_TUNNEL_TYPE_GRE,
+ SXE2_FLOW_TUNNEL_TYPE_IPIP,
+};
+
+struct sxe2_flow_meta {
+ uint8_t switch_pattern_dup_allow;
+ uint8_t switch_src_direct;
+ uint16_t flow_src_vsi;
+ uint16_t flow_rule_vsi;
+ uint32_t flow_prio;
+ uint16_t flow_type;
+ uint8_t tunnel_type;
+ uint8_t rsv;
+};
+
+struct sxe2_flow_pattern {
+ DECLARE_BITMAP(hdrs, SXE2_FLOW_HDR_MAX);
+ DECLARE_BITMAP(map_spec, SXE2_FLOW_FLD_ID_MAX);
+ DECLARE_BITMAP(map_mask, SXE2_FLOW_FLD_ID_MAX);
+ struct sxe2_flow_item item_spec;
+ struct sxe2_flow_item item_mask;
+ uint64_t rss_type_allow;
+};
+
+struct sxe2_flow_action {
+ DECLARE_BITMAP(act_types, SXE2_FLOW_ACTION_MAX);
+ struct sxe2_flow_action_rss rss;
+ struct sxe2_flow_action_queue queue;
+ struct sxe2_flow_action_queue_region q_region;
+ struct sxe2_flow_action_passthru passthru;
+ struct sxe2_flow_action_vsi vsi;
+ struct sxe2_flow_action_vsi_list vsi_list;
+ struct sxe2_flow_action_mark mark;
+ struct sxe2_flow_action_count count;
+};
+#endif /* __SXE2_FLOW_PUBLIC_H__ */
diff --git a/drivers/net/sxe2/meson.build b/drivers/net/sxe2/meson.build
index b661e3cbf4..da7a690063 100644
--- a/drivers/net/sxe2/meson.build
+++ b/drivers/net/sxe2/meson.build
@@ -62,4 +62,5 @@ sources += files(
'sxe2_txrx_vec.c',
'sxe2_mac.c',
'sxe2_filter.c',
+ 'sxe2_rss.c',
)
diff --git a/drivers/net/sxe2/sxe2_cmd_chnl.c b/drivers/net/sxe2/sxe2_cmd_chnl.c
index 1fa9ad718e..b997e7b044 100644
--- a/drivers/net/sxe2/sxe2_cmd_chnl.c
+++ b/drivers/net/sxe2/sxe2_cmd_chnl.c
@@ -541,3 +541,176 @@ int32_t sxe2_drv_vlan_filter_switch(struct sxe2_adapter *adapter, bool on)
return ret;
}
+
+int32_t sxe2_drv_rss_key_set(struct sxe2_adapter *adapter, uint8_t *key, uint16_t key_size)
+{
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_rss_key_req *req = NULL;
+ int32_t ret = 0;
+ uint16_t buf_size = sizeof(*req) + key_size;
+
+ req = rte_zmalloc("drv_cmd_rss_key", buf_size, 0);
+ if (!req) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to alloc rss key");
+ ret = -ENOMEM;
+ goto l_end;
+ }
+
+ req->vsi_id = rte_cpu_to_le_16(adapter->vsi_ctxt.dpdk_vsi_id);
+ req->key_size = rte_cpu_to_le_16(key_size);
+ rte_memcpy(req->key, key, key_size);
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_RSS_KEY_SET,
+ req, buf_size, NULL, 0);
+
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to cmd set rss key, ret=%d", ret);
+ goto l_end;
+ }
+
+l_end:
+ if (req) {
+ rte_free(req);
+ req = NULL;
+ }
+ return ret;
+}
+
+int32_t sxe2_drv_rss_lut_set(struct sxe2_adapter *adapter, uint8_t *lut, uint16_t lut_size)
+{
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_rss_lut_req *req = NULL;
+ int32_t ret = 0;
+ uint16_t buf_size = sizeof(struct sxe2_rss_lut_req) + lut_size;
+
+ req = rte_zmalloc("drv_cmd_rss_lut", buf_size, 0);
+ if (!req) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to alloc rss lut");
+ ret = -ENOMEM;
+ goto l_end;
+ }
+
+ req->vsi_id = rte_cpu_to_le_16(adapter->vsi_ctxt.dpdk_vsi_id);
+ req->lut_size = rte_cpu_to_le_16(lut_size);
+ rte_memcpy(req->lut, lut, lut_size);
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_RSS_LUT_SET,
+ req, buf_size, NULL, 0);
+
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to cmd set rss lut, ret=%d", ret);
+ goto l_end;
+ }
+
+l_end:
+ if (req) {
+ rte_free(req);
+ req = NULL;
+ }
+ return ret;
+}
+
+int32_t sxe2_drv_rss_hash_ctrl_func(struct sxe2_adapter *adapter, enum sxe2_rss_hash_key_func func)
+{
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_rss_func_req req = {0};
+ int32_t ret = 0;
+
+ req.vsi_id = rte_cpu_to_le_16(adapter->vsi_ctxt.dpdk_vsi_id);
+ req.func = func;
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_RSS_FUNC_SET,
+ &req, sizeof(req), NULL, 0);
+
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret)
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to cmd set rss func, ret=%d", ret);
+ return ret;
+}
+
+static void sxe2_drv_flow_bitmap_fill(uint32_t *bitmap, uint16_t *list)
+{
+ uint16_t index = 0;
+ uint16_t i = 0;
+ uint16_t map_size = sizeof(*bitmap) * SXE2_BITS_PER_BYTE;
+
+ while (list[i] != SXE2_FLOW_END) {
+ index = list[i] / map_size;
+ bitmap[index] |= (1UL << (list[i] % map_size));
+ i++;
+ }
+}
+
+int32_t sxe2_drv_rss_hf_add(struct sxe2_adapter *adapter,
+ struct sxe2_rss_hf_config *rss_conf)
+{
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_rss_hf_req req = {0};
+ int32_t ret = 0;
+
+ req.vsi_id = rte_cpu_to_le_16(adapter->vsi_ctxt.dpdk_vsi_id);
+ req.symm = rss_conf->symm;
+ req.hdr_type = rte_cpu_to_le_32(SXE2_RSS_OUTER_HEADERS);
+ sxe2_drv_flow_bitmap_fill(req.headers, rss_conf->hdrs);
+ sxe2_drv_flow_bitmap_fill(req.hash_flds, rss_conf->flds);
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_RSS_HF_ADD,
+ &req, sizeof(req), NULL, 0);
+
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret)
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to cmd add rss hf, ret=%d", ret);
+ return ret;
+}
+
+int32_t sxe2_drv_rss_hf_del(struct sxe2_adapter *adapter,
+ struct sxe2_rss_hf_config *rss_conf)
+{
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_rss_hf_req req = {0};
+ int32_t ret = 0;
+
+ req.vsi_id = rte_cpu_to_le_16(adapter->vsi_ctxt.dpdk_vsi_id);
+ req.symm = rss_conf->symm;
+ req.hdr_type = rte_cpu_to_le_32(SXE2_RSS_OUTER_HEADERS);
+ sxe2_drv_flow_bitmap_fill(req.headers, rss_conf->hdrs);
+ sxe2_drv_flow_bitmap_fill(req.hash_flds, rss_conf->flds);
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_RSS_HF_DEL,
+ &req, sizeof(req), NULL, 0);
+
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret)
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to cmd del rss hf, ret=%d", ret);
+ return ret;
+}
+
+int32_t sxe2_drv_rss_hf_clear(struct sxe2_adapter *adapter)
+{
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_cmd_params param = {0};
+ int32_t ret = 0;
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_RSS_HF_CLEAR,
+ NULL, 0, NULL, 0);
+
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret)
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to cmd clear rss hf, ret=%d", ret);
+
+ return ret;
+}
+
+int32_t sxe2_drv_ptp_gettime(struct sxe2_adapter *adapter, struct sxe2_rx_queue *rxq)
+{
+ (void)adapter;
+ (void)rxq;
+ return 0;
+}
diff --git a/drivers/net/sxe2/sxe2_cmd_chnl.h b/drivers/net/sxe2/sxe2_cmd_chnl.h
index c93bc2b0c9..2546c65a6c 100644
--- a/drivers/net/sxe2/sxe2_cmd_chnl.h
+++ b/drivers/net/sxe2/sxe2_cmd_chnl.h
@@ -53,4 +53,20 @@ int32_t sxe2_drv_vlan_insert_strip_cfg(struct sxe2_adapter *adapter);
int32_t sxe2_drv_vlan_filter_switch(struct sxe2_adapter *adapter, bool on);
+int32_t sxe2_drv_rss_key_set(struct sxe2_adapter *adapter, uint8_t *key, uint16_t key_size);
+
+int32_t sxe2_drv_rss_lut_set(struct sxe2_adapter *adapter, uint8_t *lut, uint16_t lut_size);
+
+int32_t sxe2_drv_rss_hash_ctrl_func(struct sxe2_adapter *adapter, enum sxe2_rss_hash_key_func func);
+
+int32_t sxe2_drv_rss_hf_add(struct sxe2_adapter *adapter,
+ struct sxe2_rss_hf_config *rss_conf);
+
+int32_t sxe2_drv_rss_hf_del(struct sxe2_adapter *adapter,
+ struct sxe2_rss_hf_config *rss_conf);
+
+int32_t sxe2_drv_rss_hf_clear(struct sxe2_adapter *adapter);
+
+int32_t sxe2_drv_ptp_gettime(struct sxe2_adapter *adapter, struct sxe2_rx_queue *rxq);
+
#endif /* SXE2_CMD_CHNL_H */
diff --git a/drivers/net/sxe2/sxe2_drv_cmd.h b/drivers/net/sxe2/sxe2_drv_cmd.h
index d69d650148..9998f241f0 100644
--- a/drivers/net/sxe2/sxe2_drv_cmd.h
+++ b/drivers/net/sxe2/sxe2_drv_cmd.h
@@ -6,6 +6,7 @@
#define SXE2_DRV_CMD_H
#include "sxe2_osal.h"
+#include "sxe2_flow_public.h"
#define SXE2_DRV_CMD_MODULE_S (16)
#define SXE2_MK_DRV_CMD(module, cmd) (((module) << SXE2_DRV_CMD_MODULE_S) | ((cmd) & 0xFFFF))
@@ -320,6 +321,34 @@ struct __rte_aligned(4) __rte_packed_begin sxe2_vlan_filter_switch_req {
uint8_t rsv;
} __rte_packed_end;
+struct __rte_aligned(4) __rte_packed_begin sxe2_rss_key_req {
+ uint16_t vsi_id;
+ uint16_t key_size;
+ uint8_t key[];
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_rss_lut_req {
+ uint16_t vsi_id;
+ uint16_t lut_size;
+ uint8_t lut[];
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_rss_func_req {
+ uint16_t vsi_id;
+ uint8_t func;
+ uint8_t rsv[1];
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_rss_hf_req {
+ uint16_t vsi_id;
+ uint8_t rsv[2];
+ uint32_t headers[BITS_TO_U32(SXE2_FLOW_HDR_MAX)];
+ uint32_t hash_flds[BITS_TO_U32(SXE2_FLOW_FLD_ID_MAX)];
+ uint32_t hdr_type;
+ uint8_t symm;
+ uint8_t rsv1[3];
+} __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 4ffe32d353..77a2b5b1dc 100644
--- a/drivers/net/sxe2/sxe2_ethdev.c
+++ b/drivers/net/sxe2/sxe2_ethdev.c
@@ -125,6 +125,11 @@ static const struct eth_dev_ops sxe2_eth_dev_ops = {
.vlan_filter_set = sxe2_dev_vlan_filter_set,
.vlan_offload_set = sxe2_dev_vlan_offload_set,
+
+ .reta_update = sxe2_dev_rss_reta_update,
+ .reta_query = sxe2_dev_rss_reta_query,
+ .rss_hash_update = sxe2_dev_rss_hash_update,
+ .rss_hash_conf_get = sxe2_dev_rss_hash_conf_get,
};
static int32_t sxe2_dev_configure(struct rte_eth_dev *dev)
@@ -141,6 +146,12 @@ static int32_t sxe2_dev_configure(struct rte_eth_dev *dev)
goto end;
}
+ ret = sxe2_rss_init(dev);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to init rss, ret=%d", ret);
+ goto end;
+ }
+
end:
return ret;
}
@@ -281,6 +292,22 @@ static int32_t sxe2_dev_infos_get(struct rte_eth_dev *dev,
RTE_ETH_TX_OFFLOAD_IPIP_TNL_TSO |
RTE_ETH_TX_OFFLOAD_GENEVE_TNL_TSO;
+
+ if (adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_PTP)
+ dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_TIMESTAMP;
+
+ 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;
+ dev_info->reta_size = adapter->rss_ctxt.rss_lut_size;
+ dev_info->hash_key_size = adapter->rss_ctxt.rss_key_size;
+ dev_info->rss_algo_capa =
+ RTE_ETH_HASH_ALGO_TO_CAPA(RTE_ETH_HASH_FUNCTION_DEFAULT) |
+ RTE_ETH_HASH_ALGO_TO_CAPA(RTE_ETH_HASH_FUNCTION_TOEPLITZ) |
+ RTE_ETH_HASH_ALGO_TO_CAPA(RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ) |
+ RTE_ETH_HASH_ALGO_TO_CAPA(RTE_ETH_HASH_FUNCTION_SIMPLE_XOR);
+ }
+
dev_info->default_rxconf = (struct rte_eth_rxconf) {
.rx_thresh = {
.pthresh = SXE2_DEFAULT_RX_PTHRESH,
@@ -563,6 +590,8 @@ static int32_t sxe2_func_caps_get(struct sxe2_adapter *adapter)
sxe2_sw_queue_ctx_hw_cap_set(adapter, &dev_caps.queue_caps);
+ sxe2_sw_rss_ctx_hw_cap_set(adapter, &dev_caps.rss_hash_caps);
+
sxe2_sw_vsi_ctx_hw_cap_set(adapter, &dev_caps.vsi_caps);
l_end:
@@ -950,8 +979,15 @@ static int32_t sxe2_dev_init(struct rte_eth_dev *dev,
goto init_eth_err;
}
+ ret = sxe2_rss_disable(dev);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to disable rss, ret=%d", ret);
+ goto init_rss_err;
+ }
+
goto l_end;
+init_rss_err:
init_eth_err:
init_dev_info_err:
sxe2_vsi_uninit(dev);
@@ -965,6 +1001,7 @@ static int32_t sxe2_dev_close(struct rte_eth_dev *dev)
{
(void)sxe2_dev_stop(dev);
(void)sxe2_queues_release(dev);
+ (void)sxe2_rss_disable(dev);
sxe2_vsi_uninit(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 fa3c69d360..3aa3799b79 100644
--- a/drivers/net/sxe2/sxe2_ethdev.h
+++ b/drivers/net/sxe2/sxe2_ethdev.h
@@ -15,6 +15,7 @@
#include "sxe2_common.h"
#include "sxe2_vsi.h"
+#include "sxe2_rss.h"
#include "sxe2_irq.h"
#include "sxe2_queue.h"
#include "sxe2_mac.h"
@@ -122,6 +123,11 @@ enum {
SXE2_FLAGS_NBITS
};
+struct sxe2_ptp_context {
+ uint64_t mbuf_rx_ts_flag;
+ int32_t mbuf_rx_ts_offset;
+};
+
struct sxe2_devargs {
uint8_t flow_dup_pattern_mode;
uint8_t func_flow_direct_en;
@@ -300,7 +306,9 @@ struct sxe2_adapter {
struct sxe2_queue_context q_ctxt;
struct sxe2_vsi_context vsi_ctxt;
struct sxe2_filter_context filter_ctxt;
+ struct sxe2_rss_context rss_ctxt;
struct sxe2_link_context link_ctxt;
+ struct sxe2_ptp_context ptp_ctxt;
struct sxe2_devargs devargs;
struct sxe2_switchdev_info switchdev_info;
bool rule_started;
diff --git a/drivers/net/sxe2/sxe2_flow_define.h b/drivers/net/sxe2/sxe2_flow_define.h
new file mode 100644
index 0000000000..d2f6000efa
--- /dev/null
+++ b/drivers/net/sxe2/sxe2_flow_define.h
@@ -0,0 +1,143 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#ifndef __SXE2_FLOW_DEFINE_H__
+#define __SXE2_FLOW_DEFINE_H__
+#include <rte_tailq.h>
+#include <rte_eal.h>
+#include <rte_flow_driver.h>
+
+#include "sxe2_osal.h"
+#include "sxe2_flow_public.h"
+
+#define SXE2_FLOW_ETH_TYPE_MIN (1500)
+
+enum sxe2_expansion {
+ SXE2_EXPANSION_ERROR = 0,
+ SXE2_EXPANSION_OUTER_ETH,
+ SXE2_EXPANSION_OUTER_VLAN,
+ SXE2_EXPANSION_OUTER_QINQ,
+ SXE2_EXPANSION_OUTER_IPV4,
+ SXE2_EXPANSION_OUTER_IPV4_FRAG_EXT,
+ SXE2_EXPANSION_OUTER_IPV6,
+ SXE2_EXPANSION_OUTER_IPV6_FRAG_EXT,
+ SXE2_EXPANSION_OUTER_UDP,
+ SXE2_EXPANSION_OUTER_TCP,
+ SXE2_EXPANSION_OUTER_SCTP,
+
+ SXE2_EXPANSION_VXLAN,
+ SXE2_EXPANSION_VXLAN_GPE,
+ SXE2_EXPANSION_GRE,
+ SXE2_EXPANSION_NVGRE,
+ SXE2_EXPANSION_GENEVE,
+ SXE2_EXPANSION_GTPU,
+ SXE2_EXPANSION_IPIP,
+ SXE2_EXPANSION_OUTER_END,
+
+ SXE2_EXPANSION_ETH,
+ SXE2_EXPANSION_VLAN,
+ SXE2_EXPANSION_IPV4,
+ SXE2_EXPANSION_IPV4_FRAG_EXT,
+ SXE2_EXPANSION_IPV6,
+ SXE2_EXPANSION_IPV6_FRAG_EXT,
+ SXE2_EXPANSION_UDP,
+ SXE2_EXPANSION_TCP,
+ SXE2_EXPANSION_SCTP,
+
+ SXE2_EXPANSION_END,
+ SXE2_EXPANSION_MAX,
+};
+
+enum sxe2_flow_udp_tunnel_protocol {
+ SXE2_FLOW_UDP_TUNNEL_PROTOCOL_VXLAN,
+ SXE2_FLOW_UDP_TUNNEL_PROTOCOL_VXLAN_GPE,
+ SXE2_FLOW_UDP_TUNNEL_PROTOCOL_GENEVE,
+ SXE2_FLOW_UDP_TUNNEL_PROTOCOL_GTP_U,
+ SXE2_FLOW_UDP_TUNNEL_PROTOCOL_NVGRE,
+ SXE2_FLOW_UDP_TUNNEL_MAX,
+};
+
+enum {
+ SXE2_FLOW_ETH_TYPE_IPV4 = 0x0800,
+ SXE2_FLOW_ETH_TYPE_IPV6 = 0x86DD,
+ SXE2_FLOW_IP_PROTOCOL_GRE = 0x2F,
+ SXE2_FLOW_IP_PROTOCOL_IPV4 = 0x04,
+ SXE2_FLOW_IP_PROTOCOL_IPV6 = 0x29,
+ SXE2_FLOW_IP_PROTOCOL_ETH = 0x3B,
+ SXE2_FLOW_IP_PROTOCOL_UDP = 0x11,
+ SXE2_FLOW_IP_PROTOCOL_TCP = 0x06,
+ SXE2_FLOW_IP_PROTOCOL_SCTP = 0x84,
+};
+
+union sxe2_flow_item_raw {
+ struct sxe2_flow_item item;
+ uint8_t raw[sizeof(struct sxe2_flow_item)];
+};
+
+struct sxe2_flow {
+ TAILQ_ENTRY(sxe2_flow) next;
+ enum sxe2_flow_engine_type engine_type;
+ struct sxe2_flow_pattern pattern_outer;
+ struct sxe2_flow_pattern pattern_inner;
+ uint8_t has_mask;
+ uint8_t has_spec;
+ uint8_t has_hdr;
+ struct sxe2_flow_meta meta;
+ struct sxe2_flow_action action;
+ uint32_t flow_id;
+ int32_t create_err;
+ DECLARE_BITMAP(flow_type, SXE2_EXPANSION_MAX);
+};
+
+TAILQ_HEAD(sxe2_flow_list_t, sxe2_flow);
+
+struct rte_flow {
+ TAILQ_ENTRY(rte_flow) next;
+ struct sxe2_flow_list_t sxe2_flow_list;
+};
+TAILQ_HEAD(rte_flow_list_t, rte_flow);
+
+struct sxe2_fnav_cid_mgr {
+ TAILQ_ENTRY(sxe2_fnav_cid_mgr) next;
+ uint16_t stat_index;
+ uint32_t user_id;
+ uint32_t driver_id;
+ uint32_t count_type;
+ uint64_t hits;
+ uint64_t bytes;
+};
+TAILQ_HEAD(sxe2_fnav_cid_mgr_list_t, sxe2_fnav_cid_mgr);
+
+struct sxe2_fnav_count_resource {
+ uint32_t count_type;
+ uint32_t global_index;
+ struct sxe2_fnav_cid_mgr_list_t fnav_cid_mgr_list;
+};
+
+struct sxe2_flow_context {
+ struct rte_flow_list_t rte_flow_list;
+ rte_spinlock_t flow_list_lock;
+ struct sxe2_fnav_count_resource hw_res;
+ uint32_t fnav_inited;
+};
+#define SXE2_INVALID_RSS_ATTR \
+ (RTE_ETH_RSS_L3_PRE40 | RTE_ETH_RSS_L3_PRE56 | RTE_ETH_RSS_L3_PRE96)
+#define SXE2_VALID_RSS_IPV4_L4 \
+ (RTE_ETH_RSS_NONFRAG_IPV4_UDP | RTE_ETH_RSS_NONFRAG_IPV4_TCP | \
+ RTE_ETH_RSS_NONFRAG_IPV4_SCTP)
+
+#define SXE2_VALID_RSS_IPV6_L4 \
+ (RTE_ETH_RSS_NONFRAG_IPV6_UDP | RTE_ETH_RSS_NONFRAG_IPV6_TCP | \
+ RTE_ETH_RSS_NONFRAG_IPV6_SCTP)
+#define SXE2_VALID_RSS_IPV4 \
+ (RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4 | \
+ RTE_ETH_RSS_NONFRAG_IPV4_OTHER | SXE2_VALID_RSS_IPV4_L4)
+#define SXE2_VALID_RSS_IPV6 \
+ (RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6 | \
+ RTE_ETH_RSS_NONFRAG_IPV6_OTHER | SXE2_VALID_RSS_IPV6_L4)
+
+#define SXE2_VALID_RSS_L3 (SXE2_VALID_RSS_IPV4 | SXE2_VALID_RSS_IPV6)
+#define SXE2_VALID_RSS_L4 (SXE2_VALID_RSS_IPV4_L4 | SXE2_VALID_RSS_IPV6_L4)
+
+#endif /* __SXE2_FLOW_DEFINE_H__ */
diff --git a/drivers/net/sxe2/sxe2_queue.c b/drivers/net/sxe2/sxe2_queue.c
index 1786d6ea4f..220cab6fce 100644
--- a/drivers/net/sxe2/sxe2_queue.c
+++ b/drivers/net/sxe2/sxe2_queue.c
@@ -17,6 +17,7 @@ void sxe2_sw_queue_ctx_hw_cap_set(struct sxe2_adapter *adapter,
int32_t sxe2_queues_init(struct rte_eth_dev *dev)
{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
int32_t ret = 0;
uint16_t buf_size;
uint16_t frame_size;
@@ -36,6 +37,16 @@ int32_t sxe2_queues_init(struct rte_eth_dev *dev)
dev->data->scattered_rx = 1;
}
+ adapter->ptp_ctxt.mbuf_rx_ts_offset = -1;
+ adapter->ptp_ctxt.mbuf_rx_ts_flag = 0;
+ if (dev->data->dev_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP) {
+ ret = rte_mbuf_dyn_rx_timestamp_register
+ (&adapter->ptp_ctxt.mbuf_rx_ts_offset,
+ (uint64_t *)&adapter->ptp_ctxt.mbuf_rx_ts_flag);
+ if (ret)
+ PMD_LOG_ERR(INIT, "Failed to enable timestamp offloads, ret=%d", ret);
+ }
+
return ret;
}
--git a/drivers/net/sxe2/sxe2_rss.c b/drivers/net/sxe2/sxe2_rss.c
new file mode 100644
index 0000000000..1d56613043
--- /dev/null
+++ b/drivers/net/sxe2/sxe2_rss.c
@@ -0,0 +1,584 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#include "sxe2_rss.h"
+#include "sxe2_common_log.h"
+#include "sxe2_ethdev.h"
+#include "sxe2_cmd_chnl.h"
+
+void sxe2_sw_rss_ctx_hw_cap_set(struct sxe2_adapter *adapter,
+ struct sxe2_drv_rss_hash_caps *rss_caps)
+{
+ adapter->rss_ctxt.rss_key_size = rss_caps->hash_key_size;
+ adapter->rss_ctxt.rss_lut_size = rss_caps->lut_key_size;
+}
+
+int32_t sxe2_rss_hash_key_init(struct rte_eth_dev *dev)
+{
+ struct rte_eth_rss_conf *rss_conf = &dev->data->dev_conf.rx_adv_conf.rss_conf;
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_rss_context *rss_ctxt = &adapter->rss_ctxt;
+ int32_t ret = 0;
+ uint16_t i = 0;
+
+ if (rss_ctxt->rss_key == NULL) {
+ rss_ctxt->rss_key = (uint8_t *)rte_zmalloc("rss_key", rss_ctxt->rss_key_size, 0);
+ if (rss_ctxt->rss_key == NULL) {
+ PMD_LOG_ERR(INIT, "Failed to allocate rss key");
+ ret = -ENOMEM;
+ goto l_end;
+ }
+ }
+
+ if (!rss_conf->rss_key) {
+ for (i = 0; i < rss_ctxt->rss_key_size; i++)
+ rss_ctxt->rss_key[i] = (uint8_t)rte_rand();
+ } else {
+ rte_memcpy(rss_ctxt->rss_key, rss_conf->rss_key,
+ RTE_MIN(rss_conf->rss_key_len, rss_ctxt->rss_key_size));
+ }
+
+ ret = sxe2_drv_rss_key_set(adapter, rss_ctxt->rss_key,
+ rss_ctxt->rss_key_size);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to set rss key, ret:%d", ret);
+ rte_free(rss_ctxt->rss_key);
+ rss_ctxt->rss_key = NULL;
+ goto l_end;
+ }
+
+l_end:
+ return ret;
+}
+
+void sxe2_rss_hash_key_uninit(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_rss_context *rss_ctxt = &adapter->rss_ctxt;
+
+ if (rss_ctxt->rss_key) {
+ rte_free(rss_ctxt->rss_key);
+ rss_ctxt->rss_key = NULL;
+ }
+}
+
+int32_t sxe2_rss_lut_init(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_rss_context *rss_ctxt = &adapter->rss_ctxt;
+ int32_t ret = 0;
+ uint16_t i;
+
+ if (rss_ctxt->rss_lut == NULL) {
+ rss_ctxt->rss_lut = (uint8_t *)rte_zmalloc("rss_lut", rss_ctxt->rss_lut_size, 0);
+ if (rss_ctxt->rss_lut == NULL) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to allocate rss lut");
+ ret = -ENOMEM;
+ goto l_end;
+ }
+ }
+
+ for (i = 0; i < rss_ctxt->rss_lut_size; i++)
+ rss_ctxt->rss_lut[i] = (uint8_t)(i % dev->data->nb_rx_queues);
+
+ ret = sxe2_drv_rss_lut_set(adapter, rss_ctxt->rss_lut, rss_ctxt->rss_lut_size);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to set rss lut, ret:%d", ret);
+ rte_free(rss_ctxt->rss_lut);
+ rss_ctxt->rss_lut = NULL;
+ goto l_end;
+ }
+
+l_end:
+ return ret;
+}
+
+void sxe2_rss_lut_uninit(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_rss_context *rss_ctxt = &adapter->rss_ctxt;
+
+ if (rss_ctxt->rss_lut) {
+ rte_free(rss_ctxt->rss_lut);
+ rss_ctxt->rss_lut = NULL;
+ }
+}
+
+static struct sxe2_rss_hf_config sxe2_rss_default_hf_config[] = {
+ {
+ .rss_hf = RTE_ETH_RSS_L2_PAYLOAD,
+ .hdrs = {SXE2_FLOW_HDR_ETH,
+ SXE2_FLOW_END},
+ .flds = {SXE2_FLOW_FLD_ID_ETH_TYPE,
+ SXE2_FLOW_END},
+ },
+ {
+ .rss_hf = RTE_ETH_RSS_IPV4,
+ .hdrs = {SXE2_FLOW_HDR_IPV4,
+ SXE2_FLOW_END},
+ .flds = {SXE2_FLOW_FLD_ID_IPV4_SA,
+ SXE2_FLOW_FLD_ID_IPV4_DA,
+ SXE2_FLOW_END},
+ },
+ {
+ .rss_hf = RTE_ETH_RSS_IPV6,
+ .hdrs = {SXE2_FLOW_HDR_IPV6,
+ SXE2_FLOW_END},
+ .flds = {SXE2_FLOW_FLD_ID_IPV6_SA,
+ SXE2_FLOW_FLD_ID_IPV6_DA,
+ SXE2_FLOW_END},
+ },
+ {
+ .rss_hf = RTE_ETH_RSS_FRAG_IPV4,
+ .hdrs = {SXE2_FLOW_HDR_IPV4,
+ SXE2_FLOW_HDR_IPV_FRAG,
+ SXE2_FLOW_END},
+ .flds = {SXE2_FLOW_FLD_ID_IPV4_SA,
+ SXE2_FLOW_FLD_ID_IPV4_DA,
+ SXE2_FLOW_END},
+ },
+ {
+ .rss_hf = RTE_ETH_RSS_FRAG_IPV6,
+ .hdrs = {SXE2_FLOW_HDR_IPV6,
+ SXE2_FLOW_HDR_IPV_FRAG,
+ SXE2_FLOW_END},
+ .flds = {SXE2_FLOW_FLD_ID_IPV6_SA,
+ SXE2_FLOW_FLD_ID_IPV6_DA,
+ SXE2_FLOW_END},
+ },
+ {
+ .rss_hf = RTE_ETH_RSS_NONFRAG_IPV4_OTHER,
+ .hdrs = {SXE2_FLOW_HDR_IPV4,
+ SXE2_FLOW_HDR_IPV_OTHER,
+ SXE2_FLOW_END},
+ .flds = {SXE2_FLOW_FLD_ID_IPV4_SA,
+ SXE2_FLOW_FLD_ID_IPV4_DA,
+ SXE2_FLOW_END},
+ },
+ {
+ .rss_hf = RTE_ETH_RSS_NONFRAG_IPV6_OTHER,
+ .hdrs = {SXE2_FLOW_HDR_IPV6,
+ SXE2_FLOW_HDR_IPV_OTHER,
+ SXE2_FLOW_END},
+ .flds = {SXE2_FLOW_FLD_ID_IPV6_SA,
+ SXE2_FLOW_FLD_ID_IPV6_DA,
+ SXE2_FLOW_END},
+ },
+ {
+ .rss_hf = RTE_ETH_RSS_NONFRAG_IPV4_UDP,
+ .hdrs = {SXE2_FLOW_HDR_IPV4,
+ SXE2_FLOW_HDR_UDP,
+ SXE2_FLOW_END},
+ .flds = {SXE2_FLOW_FLD_ID_IPV4_SA,
+ SXE2_FLOW_FLD_ID_IPV4_DA,
+ SXE2_FLOW_FLD_ID_UDP_SRC_PORT,
+ SXE2_FLOW_FLD_ID_UDP_DST_PORT,
+ SXE2_FLOW_END},
+ },
+ {
+ .rss_hf = RTE_ETH_RSS_NONFRAG_IPV6_UDP,
+ .hdrs = {SXE2_FLOW_HDR_IPV6,
+ SXE2_FLOW_HDR_UDP,
+ SXE2_FLOW_END},
+ .flds = {SXE2_FLOW_FLD_ID_IPV6_SA,
+ SXE2_FLOW_FLD_ID_IPV6_DA,
+ SXE2_FLOW_FLD_ID_UDP_SRC_PORT,
+ SXE2_FLOW_FLD_ID_UDP_DST_PORT,
+ SXE2_FLOW_END},
+ },
+ {
+ .rss_hf = RTE_ETH_RSS_NONFRAG_IPV4_TCP,
+ .hdrs = {SXE2_FLOW_HDR_IPV4,
+ SXE2_FLOW_HDR_TCP,
+ SXE2_FLOW_END},
+ .flds = {SXE2_FLOW_FLD_ID_IPV4_SA,
+ SXE2_FLOW_FLD_ID_IPV4_DA,
+ SXE2_FLOW_FLD_ID_TCP_SRC_PORT,
+ SXE2_FLOW_FLD_ID_TCP_DST_PORT,
+ SXE2_FLOW_END},
+ },
+ {
+ .rss_hf = RTE_ETH_RSS_NONFRAG_IPV6_TCP,
+ .hdrs = {SXE2_FLOW_HDR_IPV6,
+ SXE2_FLOW_HDR_TCP,
+ SXE2_FLOW_END},
+ .flds = {SXE2_FLOW_FLD_ID_IPV6_SA,
+ SXE2_FLOW_FLD_ID_IPV6_DA,
+ SXE2_FLOW_FLD_ID_TCP_SRC_PORT,
+ SXE2_FLOW_FLD_ID_TCP_DST_PORT,
+ SXE2_FLOW_END},
+ },
+ {
+ .rss_hf = RTE_ETH_RSS_NONFRAG_IPV4_SCTP,
+ .hdrs = {SXE2_FLOW_HDR_IPV4,
+ SXE2_FLOW_HDR_SCTP,
+ SXE2_FLOW_END},
+ .flds = {SXE2_FLOW_FLD_ID_IPV4_SA,
+ SXE2_FLOW_FLD_ID_IPV4_DA,
+ SXE2_FLOW_FLD_ID_SCTP_SRC_PORT,
+ SXE2_FLOW_FLD_ID_SCTP_DST_PORT,
+ SXE2_FLOW_END},
+ },
+ {
+ .rss_hf = RTE_ETH_RSS_NONFRAG_IPV6_SCTP,
+ .hdrs = {SXE2_FLOW_HDR_IPV6,
+ SXE2_FLOW_HDR_SCTP,
+ SXE2_FLOW_END},
+ .flds = {SXE2_FLOW_FLD_ID_IPV6_SA,
+ SXE2_FLOW_FLD_ID_IPV6_DA,
+ SXE2_FLOW_FLD_ID_SCTP_SRC_PORT,
+ SXE2_FLOW_FLD_ID_SCTP_DST_PORT,
+ SXE2_FLOW_END},
+ },
+};
+
+int32_t sxe2_rss_hf_type_set(struct rte_eth_dev *dev, uint64_t rss_hf)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_rss_context *rss_ctxt = &adapter->rss_ctxt;
+ int32_t ret = 0;
+ uint32_t i;
+ uint8_t symm = 0;
+
+ if (0 == (rss_hf & SXE2_RSS_HF_SUPPORT_ALL) && rss_hf != 0) {
+ PMD_DEV_LOG_ERR(adapter, DRV,
+ "Failed to set unsupported rss_hf:0x%016" PRIx64,
+ rss_hf);
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ for (i = 0; i < RTE_DIM(sxe2_rss_default_hf_config); i++) {
+ if (rss_ctxt->rss_hf & sxe2_rss_default_hf_config[i].rss_hf) {
+ sxe2_rss_default_hf_config[i].symm = rss_ctxt->symm;
+ ret = sxe2_drv_rss_hf_del(adapter, &sxe2_rss_default_hf_config[i]);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT,
+ "Failed to del rss hf cfg[%d], ret:%d", i, ret);
+ goto l_end;
+ }
+ }
+ }
+
+ if (rss_ctxt->hash_func == RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ)
+ symm = 1;
+
+ for (i = 0; i < RTE_DIM(sxe2_rss_default_hf_config); i++) {
+ if (rss_hf & sxe2_rss_default_hf_config[i].rss_hf) {
+ sxe2_rss_default_hf_config[i].symm = symm;
+ ret = sxe2_drv_rss_hf_add(adapter, &sxe2_rss_default_hf_config[i]);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT,
+ "Failed to add rss hf cfg[%d], ret:%d", i, ret);
+ goto l_end;
+ }
+ }
+ }
+
+ rss_ctxt->rss_hf = rss_hf & SXE2_RSS_HF_SUPPORT_ALL;
+ rss_ctxt->symm = symm;
+l_end:
+ return ret;
+}
+
+int32_t sxe2_rss_hash_function_set(struct rte_eth_dev *dev, enum rte_eth_hash_function func)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ enum sxe2_rss_hash_key_func hash_func = SXE2_RSS_HASH_FUNC_SYM_TOEPLITZ;
+ int32_t ret = 0;
+
+ switch (func) {
+ case RTE_ETH_HASH_FUNCTION_DEFAULT:
+ case RTE_ETH_HASH_FUNCTION_TOEPLITZ:
+ case RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ:
+ hash_func = SXE2_RSS_HASH_FUNC_SYM_TOEPLITZ;
+ break;
+ case RTE_ETH_HASH_FUNCTION_SIMPLE_XOR:
+ hash_func = SXE2_RSS_HASH_FUNC_XOR;
+ break;
+ default:
+ PMD_DEV_LOG_ERR(adapter, DRV, "RSS hash function[%d] not support.", func);
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ ret = sxe2_drv_rss_hash_ctrl_func(adapter, hash_func);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to set rss hash function, ret=[%d]", ret);
+ goto l_end;
+ }
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_rss_init(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct rte_eth_rss_conf *rss_conf = &dev->data->dev_conf.rx_adv_conf.rss_conf;
+ enum rte_eth_hash_function rss_func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
+ int32_t ret = 0;
+
+ adapter->rss_ctxt.inited = false;
+
+ if (dev->data->nb_rx_queues <= 1) {
+ PMD_DEV_LOG_DEBUG(adapter, INIT, "No need to init rss, rx queues %d.",
+ dev->data->nb_rx_queues);
+ goto l_end;
+ }
+
+ if ((adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_RSS) == 0) {
+ PMD_DEV_LOG_WARN(adapter, INIT, "RSS not supported");
+ goto l_end;
+ }
+
+ ret = sxe2_rss_hash_key_init(dev);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to init rss key");
+ goto l_end;
+ }
+
+ ret = sxe2_rss_lut_init(dev);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to init rss lut");
+ goto l_err_key;
+ }
+
+ rss_func = rss_conf->algorithm;
+ ret = sxe2_rss_hash_function_set(dev, rss_func);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to init rss hash function");
+ goto l_err_lut;
+ }
+ ret = sxe2_rss_hf_type_set(dev, rss_conf->rss_hf);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to set rss hf type");
+ goto l_err_lut;
+ }
+ adapter->rss_ctxt.inited = true;
+ goto l_end;
+
+l_err_lut:
+ sxe2_rss_lut_uninit(dev);
+l_err_key:
+ sxe2_rss_hash_key_uninit(dev);
+l_end:
+ return ret;
+}
+
+int32_t sxe2_rss_disable(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret = 0;
+
+ PMD_INIT_FUNC_TRACE();
+
+ if ((adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_RSS) == 0)
+ goto l_end;
+
+ ret = sxe2_drv_rss_hf_clear(adapter);
+ if (ret)
+ PMD_LOG_ERR(INIT, "Failed to clear rss hf");
+
+ sxe2_rss_hash_key_uninit(dev);
+
+ sxe2_rss_lut_uninit(dev);
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_dev_rss_reta_update(struct rte_eth_dev *dev,
+ struct rte_eth_rss_reta_entry64 *reta_conf,
+ uint16_t reta_size)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_rss_context *rss_ctxt = &adapter->rss_ctxt;
+ uint8_t *lut_tmp = NULL;
+ int32_t ret = 0;
+ uint16_t i;
+ uint16_t shift;
+ uint16_t idx;
+
+ if (!adapter->rss_ctxt.inited) {
+ PMD_DEV_LOG_INFO(adapter, DRV, "RSS not inited.");
+ ret = -ENOTSUP;
+ goto l_end;
+ }
+
+ if (reta_size != rss_ctxt->rss_lut_size) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "The size of hash lookup table configured "
+ "(%d) doesn't match the number of hardware can "
+ "support (%d)", reta_size, rss_ctxt->rss_lut_size);
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ lut_tmp = rte_zmalloc("rss_lut_temp", reta_size, 0);
+ if (!lut_tmp) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "No memory can be allocated");
+ ret = -ENOMEM;
+ goto l_end;
+ }
+ rte_memcpy(lut_tmp, rss_ctxt->rss_lut, reta_size);
+
+ for (i = 0; i < reta_size; i++) {
+ idx = i / RTE_ETH_RETA_GROUP_SIZE;
+ shift = i % RTE_ETH_RETA_GROUP_SIZE;
+ if (reta_conf[idx].mask & (1ULL << shift))
+ lut_tmp[i] = reta_conf[idx].reta[shift];
+ }
+
+ ret = sxe2_drv_rss_lut_set(adapter, lut_tmp, reta_size);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to set rss lut");
+ goto l_end;
+ }
+
+ rte_memcpy(rss_ctxt->rss_lut, lut_tmp, reta_size);
+
+l_end:
+ if (lut_tmp)
+ rte_free(lut_tmp);
+ return ret;
+}
+
+int32_t sxe2_dev_rss_reta_query(struct rte_eth_dev *dev,
+ struct rte_eth_rss_reta_entry64 *reta_conf,
+ uint16_t reta_size)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_rss_context *rss_ctxt = &adapter->rss_ctxt;
+ int32_t ret = 0;
+ uint16_t i;
+ uint16_t shift;
+ uint16_t idx;
+
+ if (!adapter->rss_ctxt.inited) {
+ PMD_DEV_LOG_INFO(adapter, DRV, "RSS not inited.");
+ ret = -ENOTSUP;
+ goto l_end;
+ }
+
+ if (reta_size != rss_ctxt->rss_lut_size) {
+ PMD_LOG_ERR(INIT, "The size of hash lookup table configured "
+ "(%d) doesn't match the number of hardware can "
+ "support (%d)", reta_size, rss_ctxt->rss_lut_size);
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ for (i = 0; i < reta_size; i++) {
+ idx = i / RTE_ETH_RETA_GROUP_SIZE;
+ shift = i % RTE_ETH_RETA_GROUP_SIZE;
+ if (reta_conf[idx].mask & (1ULL << shift))
+ reta_conf[idx].reta[shift] = rss_ctxt->rss_lut[i];
+ }
+
+l_end:
+ return ret;
+}
+
+static int32_t sxe2_rss_hash_key_update(struct rte_eth_dev *dev,
+ struct rte_eth_rss_conf *rss_conf)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_rss_context *rss_ctxt = &adapter->rss_ctxt;
+ int32_t ret = 0;
+ uint16_t i;
+
+ if (rss_conf->rss_key_len == 0 || rss_conf->rss_key == NULL)
+ goto l_end;
+
+ if (rss_conf->rss_key_len != rss_ctxt->rss_key_size) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "The size of hash key configured "
+ "(%d) doesn't match the size of hardware can "
+ "support (%d)", rss_conf->rss_key_len,
+ rss_ctxt->rss_key_size);
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ for (i = 0; i < rss_conf->rss_key_len; i++) {
+ if (rss_conf->rss_key[i] != rss_ctxt->rss_key[i])
+ break;
+ }
+ if (i == rss_conf->rss_key_len)
+ goto l_end;
+
+ ret = sxe2_drv_rss_key_set(adapter, rss_conf->rss_key,
+ rss_conf->rss_key_len);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to set rss key");
+ goto l_end;
+ }
+
+ rte_memcpy(rss_ctxt->rss_key, rss_conf->rss_key, rss_conf->rss_key_len);
+l_end:
+ return ret;
+}
+
+int32_t sxe2_dev_rss_hash_update(struct rte_eth_dev *dev,
+ struct rte_eth_rss_conf *rss_conf)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_rss_context *rss_ctxt = &adapter->rss_ctxt;
+ int32_t ret = -1;
+
+ if (!adapter->rss_ctxt.inited) {
+ PMD_DEV_LOG_INFO(adapter, DRV, "RSS not inited.");
+ ret = -ENOTSUP;
+ goto l_end;
+ }
+
+ ret = sxe2_rss_hash_key_update(dev, rss_conf);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to set rss hash key");
+ goto l_end;
+ }
+
+ if (rss_conf->algorithm != rss_ctxt->hash_func) {
+ ret = sxe2_rss_hash_function_set(dev, rss_conf->algorithm);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to set rss hash function");
+ goto l_end;
+ }
+ rss_ctxt->hash_func = rss_conf->algorithm;
+ }
+
+ if ((rss_conf->rss_hf & SXE2_RSS_HF_SUPPORT_ALL)
+ != rss_ctxt->rss_hf) {
+ ret = sxe2_rss_hf_type_set(dev, rss_conf->rss_hf);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to set rss hf type");
+ goto l_end;
+ }
+ }
+ ret = 0;
+l_end:
+ return ret;
+}
+
+int32_t sxe2_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
+ struct rte_eth_rss_conf *rss_conf)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_rss_context *rss_ctxt = &adapter->rss_ctxt;
+ int32_t ret = 0;
+
+ if (adapter->rss_ctxt.inited == 0) {
+ PMD_DEV_LOG_INFO(adapter, DRV, "RSS not inited.");
+ ret = -ENOTSUP;
+ goto l_end;
+ }
+
+ if (rss_conf->rss_key) {
+ rss_conf->rss_key_len = rss_ctxt->rss_key_size;
+ rte_memcpy(rss_conf->rss_key, rss_ctxt->rss_key, rss_ctxt->rss_key_size);
+ }
+ rss_conf->rss_hf = rss_ctxt->rss_hf;
+ rss_conf->algorithm = rss_ctxt->hash_func;
+l_end:
+ return ret;
+}
--git a/drivers/net/sxe2/sxe2_rss.h b/drivers/net/sxe2/sxe2_rss.h
new file mode 100644
index 0000000000..2a454ac1b3
--- /dev/null
+++ b/drivers/net/sxe2/sxe2_rss.h
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#ifndef __SXE2_RSS_H__
+#define __SXE2_RSS_H__
+#include <ethdev_driver.h>
+#include "sxe2_osal.h"
+#include "sxe2_drv_cmd.h"
+#include "sxe2_flow_define.h"
+
+#define SXE2_FLOW_END (0xFFFF)
+
+struct sxe2_rss_context {
+ enum rte_eth_hash_function hash_func;
+ uint16_t rss_key_size;
+ uint16_t rss_lut_size;
+ uint8_t *rss_key;
+ uint8_t *rss_lut;
+ uint64_t rss_hf;
+ uint8_t symm;
+ bool inited;
+};
+
+struct sxe2_rss_hf_config {
+ uint64_t rss_hf;
+ uint16_t hdrs[SXE2_FLOW_HDR_MAX];
+ uint16_t flds[SXE2_FLOW_FLD_ID_MAX];
+ uint8_t symm;
+};
+
+#define SXE2_RSS_HF_SUPPORT_ALL ( \
+ RTE_ETH_RSS_IPV4 | \
+ RTE_ETH_RSS_FRAG_IPV4 | \
+ RTE_ETH_RSS_NONFRAG_IPV4_TCP | \
+ RTE_ETH_RSS_NONFRAG_IPV4_UDP | \
+ RTE_ETH_RSS_NONFRAG_IPV4_SCTP | \
+ RTE_ETH_RSS_NONFRAG_IPV4_OTHER | \
+ RTE_ETH_RSS_IPV6 | \
+ RTE_ETH_RSS_FRAG_IPV6 | \
+ RTE_ETH_RSS_NONFRAG_IPV6_TCP | \
+ RTE_ETH_RSS_NONFRAG_IPV6_UDP | \
+ RTE_ETH_RSS_NONFRAG_IPV6_SCTP | \
+ RTE_ETH_RSS_NONFRAG_IPV6_OTHER | \
+ RTE_ETH_RSS_L2_PAYLOAD)
+
+struct sxe2_adapter;
+
+void sxe2_sw_rss_ctx_hw_cap_set(struct sxe2_adapter *adapter,
+ struct sxe2_drv_rss_hash_caps *rss_caps);
+
+int32_t sxe2_rss_hash_key_init(struct rte_eth_dev *dev);
+
+void sxe2_rss_hash_key_uninit(struct rte_eth_dev *dev);
+
+int32_t sxe2_rss_lut_init(struct rte_eth_dev *dev);
+
+void sxe2_rss_lut_uninit(struct rte_eth_dev *dev);
+
+int32_t sxe2_rss_init(struct rte_eth_dev *dev);
+
+int32_t sxe2_rss_hash_function_set(struct rte_eth_dev *dev, enum rte_eth_hash_function func);
+
+int32_t sxe2_rss_hf_type_set(struct rte_eth_dev *dev, uint64_t rss_hf);
+
+int32_t sxe2_rss_disable(struct rte_eth_dev *dev);
+
+int32_t sxe2_dev_rss_reta_update(struct rte_eth_dev *dev,
+ struct rte_eth_rss_reta_entry64 *reta_conf,
+ uint16_t reta_size);
+
+int32_t sxe2_dev_rss_reta_query(struct rte_eth_dev *dev,
+ struct rte_eth_rss_reta_entry64 *reta_conf,
+ uint16_t reta_size);
+
+int32_t sxe2_dev_rss_hash_update(struct rte_eth_dev *dev,
+ struct rte_eth_rss_conf *rss_conf);
+
+int32_t sxe2_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
+ struct rte_eth_rss_conf *rss_conf);
+#endif /* __SXE2_RSS_H__ */
diff --git a/drivers/net/sxe2/sxe2_txrx.h b/drivers/net/sxe2/sxe2_txrx.h
index 6f6ff3e3d1..2ff5fee7c7 100644
--- a/drivers/net/sxe2/sxe2_txrx.h
+++ b/drivers/net/sxe2/sxe2_txrx.h
@@ -23,4 +23,8 @@ int32_t sxe2_tx_burst_mode_get(struct rte_eth_dev *dev,
int32_t sxe2_rx_burst_mode_get(struct rte_eth_dev *dev,
__rte_unused uint16_t queue_id, struct rte_eth_burst_mode *mode);
+#ifndef RTE_LIBRTE_SXE2_16BYTE_RX_DESC
+int32_t sxe2_rx_update_ptp_time(struct sxe2_rx_queue *rxq);
+#endif
+
#endif /* SXE2_TXRX_H */
diff --git a/drivers/net/sxe2/sxe2_txrx_poll.c b/drivers/net/sxe2/sxe2_txrx_poll.c
index 21d5c38725..3c6fe37404 100644
--- a/drivers/net/sxe2/sxe2_txrx_poll.c
+++ b/drivers/net/sxe2/sxe2_txrx_poll.c
@@ -17,6 +17,7 @@
#include "sxe2_queue.h"
#include "sxe2_ethdev.h"
#include "sxe2_common_log.h"
+#include "sxe2_cmd_chnl.h"
static __rte_always_inline int32_t
sxe2_tx_bufs_free(struct sxe2_tx_queue *txq)
@@ -282,6 +283,30 @@ sxe2_tx_desc_checksum_fill(uint64_t offloads, uint32_t *desc_cmd, uint32_t *desc
return;
}
+static __rte_always_inline void sxe2_desc_tso_fill(struct rte_mbuf *tx_pkt,
+ uint64_t *desc_type_cmd_tso_mss,
+ union sxe2_tx_offload_info ol_info)
+{
+ uint32_t hdr_len;
+ uint32_t tso_len;
+
+ if (!ol_info.l4_len) {
+ PMD_LOG_DEBUG(TX, "TSO ERROR: L4 length is 0");
+ goto l_end;
+ }
+ hdr_len = ol_info.l2_len + ol_info.l3_len + ol_info.l4_len;
+ if (tx_pkt->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK)
+ hdr_len += ol_info.outer_l2_len + ol_info.outer_l3_len;
+
+ tso_len = tx_pkt->pkt_len - hdr_len;
+ *desc_type_cmd_tso_mss |=
+ ((uint64_t)SXE2_TX_CTXT_DESC_CMD_TSO << SXE2_TX_CTXT_DESC_CMD_SHIFT) |
+ ((uint64_t)tso_len << SXE2_TX_CTXT_DESC_TSO_LEN_SHIFT) |
+ ((uint64_t)tx_pkt->tso_segsz << SXE2_TX_CTXT_DESC_MSS_SHIFT);
+l_end:
+ return;
+}
+
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)
{
@@ -395,6 +420,11 @@ uint16_t sxe2_tx_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkt
rte_pktmbuf_free_seg(buffer->mbuf);
buffer->mbuf = NULL;
}
+ if (offloads & (RTE_MBUF_F_TX_TCP_SEG | RTE_MBUF_F_TX_UDP_SEG))
+ sxe2_desc_tso_fill(tx_pkt,
+ &desc_type_cmd_tso_mss, ol_info);
+ 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_QINQ) {
desc_l2tag2 = tx_pkt->vlan_tci_outer;
@@ -707,6 +737,57 @@ sxe2_rx_desc_filter_para_fill(struct sxe2_rx_queue *rxq __rte_unused,
#endif
}
+#ifndef RTE_LIBRTE_SXE2_16BYTE_RX_DESC
+int32_t sxe2_rx_update_ptp_time(struct sxe2_rx_queue *rxq)
+{
+ struct sxe2_adapter *adapter;
+ uint64_t cur_time_ms;
+ int32_t ret = 0;
+ cur_time_ms = rte_get_timer_cycles() / (rte_get_timer_hz() / 1000);
+
+ if (likely((cur_time_ms - rxq->update_time) < SXE2_RX_PKTS_TS_TIMEOUT_VAL))
+ goto l_end;
+ rxq->update_time = cur_time_ms;
+ adapter = rxq->vsi->adapter;
+ rxq->ts_need_update = true;
+ ret = sxe2_drv_ptp_gettime(adapter, rxq);
+ if (rxq->desc_ts < rxq->ts_low)
+ rxq->ts_need_update = false;
+
+ PMD_LOG_INFO(RX, "rxq update time ret=%d, cur time=%" PRIu64 ", rxqh=%" PRIu64 ", rxql=%d",
+ ret, cur_time_ms, rxq->ts_high, rxq->ts_low);
+l_end:
+ return ret;
+}
+
+static inline void sxe2_rx_desc_ptp_para_fill(struct sxe2_rx_queue *rxq,
+ struct rte_mbuf *mbuf,
+ union sxe2_rx_desc *desc)
+{
+ struct sxe2_adapter *adapter = rxq->vsi->adapter;
+ uint64_t ts_ns;
+
+ if (adapter->ptp_ctxt.mbuf_rx_ts_flag != 0 &&
+ (rxq->offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP) &&
+ SXE2_RX_DESC_RXDID_VAL_GET(desc->wb.rxdid_src) == SXE2_RX_DESC_RXDID_1588) {
+ rxq->desc_ts = rte_le_to_cpu_32(desc->wb_ts.ts_h);
+ (void)sxe2_rx_update_ptp_time(rxq);
+ if (rxq->ts_need_update && rxq->desc_ts < rxq->ts_low)
+ rxq->ts_high += 1;
+
+ rxq->ts_need_update = true;
+ rxq->ts_low = rxq->desc_ts;
+ rxq->update_time = rte_get_timer_cycles() /
+ (rte_get_timer_hz() / 1000);
+ ts_ns = rxq->ts_high * NSEC_PER_SEC + rxq->ts_low;
+ *RTE_MBUF_DYNFIELD(mbuf, adapter->ptp_ctxt.mbuf_rx_ts_offset, uint64_t *) = ts_ns;
+ mbuf->ol_flags |= adapter->ptp_ctxt.mbuf_rx_ts_flag;
+ PMD_LOG_INFO(RX, "receive ptp pkt,ts_s=%" PRIu64 ", ts_ns=%d", rxq->ts_high,
+ rxq->ts_low);
+ }
+}
+#endif
+
static __rte_always_inline void
sxe2_rx_mbuf_common_fields_fill(struct sxe2_rx_queue *rxq, struct rte_mbuf *mbuf,
union sxe2_rx_desc *rxd)
@@ -718,10 +799,12 @@ sxe2_rx_mbuf_common_fields_fill(struct sxe2_rx_queue *rxq, struct rte_mbuf *mbuf
mbuf->ol_flags = 0;
mbuf->packet_type = ptype_tbl[SXE2_RX_DESC_PTYPE_VAL_GET(qword1)];
-
pkt_flags = sxe2_rx_desc_error_para(rxq, rxd);
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_ptp_para_fill(rxq, mbuf, rxd);
+#endif
mbuf->ol_flags |= pkt_flags;
}
--
2.52.0
^ permalink raw reply related
* [PATCH v2 08/20] net/sxe2: support statistics and multi-process
From: liujie5 @ 2026-06-14 9:23 UTC (permalink / raw)
To: stephen; +Cc: dev, Jie Liu
In-Reply-To: <20260614092328.201826-1-liujie5@linkdatatechnology.com>
From: Jie Liu <liujie5@linkdatatechnology.com>
- The statistics support includes:
- Basic statistics (ipackets, opackets, ibytes, obytes, etc.)
- Extended statistics (xstats) for detailed hardware counters.
- Per-queue statistics for both RX and TX.
The multi-process support allows secondary processes to retrieve
statistics. Since secondary processes cannot access hardware registers
directly, an IPC mechanism is implemented using the DPDK MP API.
Atomic operations are used when reading 64-bit counters to ensure
data consistency between processes.
Signed-off-by: Jie Liu <liujie5@linkdatatechnology.com>
---
drivers/net/sxe2/meson.build | 2 +
drivers/net/sxe2/sxe2_cmd_chnl.c | 340 +++++++++++++++++-
drivers/net/sxe2/sxe2_cmd_chnl.h | 23 ++
drivers/net/sxe2/sxe2_drv_cmd.h | 120 +++++++
drivers/net/sxe2/sxe2_ethdev.c | 38 +-
drivers/net/sxe2/sxe2_mp.c | 414 ++++++++++++++++++++++
drivers/net/sxe2/sxe2_mp.h | 67 ++++
drivers/net/sxe2/sxe2_stats.c | 586 +++++++++++++++++++++++++++++++
drivers/net/sxe2/sxe2_stats.h | 39 ++
9 files changed, 1616 insertions(+), 13 deletions(-)
create mode 100644 drivers/net/sxe2/sxe2_mp.c
create mode 100644 drivers/net/sxe2/sxe2_mp.h
create mode 100644 drivers/net/sxe2/sxe2_stats.c
create mode 100644 drivers/net/sxe2/sxe2_stats.h
diff --git a/drivers/net/sxe2/meson.build b/drivers/net/sxe2/meson.build
index 86973edc99..8c8f16863e 100644
--- a/drivers/net/sxe2/meson.build
+++ b/drivers/net/sxe2/meson.build
@@ -66,4 +66,6 @@ sources += files(
'sxe2_tm.c',
'sxe2_ipsec.c',
'sxe2_security.c',
+ 'sxe2_mp.c',
+ 'sxe2_stats.c',
)
diff --git a/drivers/net/sxe2/sxe2_cmd_chnl.c b/drivers/net/sxe2/sxe2_cmd_chnl.c
index 7711e8e57d..a1fc8a50e3 100644
--- a/drivers/net/sxe2/sxe2_cmd_chnl.c
+++ b/drivers/net/sxe2/sxe2_cmd_chnl.c
@@ -348,6 +348,184 @@ int32_t sxe2_drv_mac_link_status_get(struct sxe2_adapter *adapter)
return ret;
}
+int32_t sxe2_drv_get_mac_stats(struct sxe2_adapter *adapter)
+{
+ int32_t ret = 0;
+ uint8_t i = 0;
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_vsi *vsi = adapter->vsi_ctxt.main_vsi;
+ struct sxe2_stats *stats = &vsi->vsi_stats.vsi_hw_stats;
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_drv_mac_stats_resp resp = {0};
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_MAC_STATS_GET,
+ NULL, 0,
+ &resp, sizeof(resp));
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "vsi stats get failed, ret=%d", ret);
+ goto l_end;
+ }
+
+ stats->rx_out_of_buffer = rte_le_to_cpu_64(resp.rx_out_of_buffer);
+ stats->rx_qblock_drop = rte_le_to_cpu_64(resp.rx_qblock_drop);
+ stats->tx_frame_good = rte_le_to_cpu_64(resp.tx_frame_good);
+ stats->rx_frame_good = rte_le_to_cpu_64(resp.rx_frame_good);
+ stats->rx_crc_errors = rte_le_to_cpu_64(resp.rx_crc_errors);
+ stats->tx_bytes_good = rte_le_to_cpu_64(resp.tx_bytes_good);
+ stats->rx_bytes_good = rte_le_to_cpu_64(resp.rx_bytes_good);
+ stats->tx_multicast_good = rte_le_to_cpu_64(resp.tx_multicast_good);
+ stats->tx_broadcast_good = rte_le_to_cpu_64(resp.tx_broadcast_good);
+ stats->rx_multicast_good = rte_le_to_cpu_64(resp.rx_multicast_good);
+ stats->rx_broadcast_good = rte_le_to_cpu_64(resp.rx_broadcast_good);
+ stats->rx_len_errors = rte_le_to_cpu_64(resp.rx_len_errors);
+ stats->rx_out_of_range_errors = rte_le_to_cpu_64(resp.rx_out_of_range_errors);
+ stats->rx_oversize_pkts_phy = rte_le_to_cpu_64(resp.rx_oversize_pkts_phy);
+ stats->rx_symbol_err = rte_le_to_cpu_64(resp.rx_symbol_err);
+ stats->rx_pause_frame = rte_le_to_cpu_64(resp.rx_pause_frame);
+ stats->tx_pause_frame = rte_le_to_cpu_64(resp.tx_pause_frame);
+ stats->rx_discards_phy = rte_le_to_cpu_64(resp.rx_discards_phy);
+ stats->rx_discards_ips_phy = rte_le_to_cpu_64(resp.rx_discards_ips_phy);
+ stats->tx_dropped_link_down = rte_le_to_cpu_64(resp.tx_dropped_link_down);
+ stats->rx_undersize_good = rte_le_to_cpu_64(resp.rx_undersize_good);
+ stats->rx_runt_error = rte_le_to_cpu_64(resp.rx_runt_error);
+ stats->tx_bytes_good_bad = rte_le_to_cpu_64(resp.tx_bytes_good_bad);
+ stats->tx_frame_good_bad = rte_le_to_cpu_64(resp.tx_frame_good_bad);
+ stats->rx_jabbers = rte_le_to_cpu_64(resp.rx_jabbers);
+ stats->rx_size_64 = rte_le_to_cpu_64(resp.rx_size_64);
+ stats->rx_size_65_127 = rte_le_to_cpu_64(resp.rx_size_65_127);
+ stats->rx_size_128_255 = rte_le_to_cpu_64(resp.rx_size_128_255);
+ stats->rx_size_256_511 = rte_le_to_cpu_64(resp.rx_size_256_511);
+ stats->rx_size_512_1023 = rte_le_to_cpu_64(resp.rx_size_512_1023);
+ stats->rx_size_1024_1522 = rte_le_to_cpu_64(resp.rx_size_1024_1522);
+ stats->rx_size_1523_max = rte_le_to_cpu_64(resp.rx_size_1523_max);
+ stats->rx_pcs_symbol_err_phy = rte_le_to_cpu_64(resp.rx_pcs_symbol_err_phy);
+ stats->rx_corrected_bits_phy = rte_le_to_cpu_64(resp.rx_corrected_bits_phy);
+ stats->rx_err_lane_0_phy = rte_le_to_cpu_64(resp.rx_err_lane_0_phy);
+ stats->rx_err_lane_1_phy = rte_le_to_cpu_64(resp.rx_err_lane_1_phy);
+ stats->rx_err_lane_2_phy = rte_le_to_cpu_64(resp.rx_err_lane_2_phy);
+ stats->rx_err_lane_3_phy = rte_le_to_cpu_64(resp.rx_err_lane_3_phy);
+ stats->rx_illegal_bytes = rte_le_to_cpu_64(resp.rx_illegal_bytes);
+ stats->rx_oversize_good = rte_le_to_cpu_64(resp.rx_oversize_good);
+ stats->tx_unicast = rte_le_to_cpu_64(resp.tx_unicast);
+ stats->tx_broadcast = rte_le_to_cpu_64(resp.tx_broadcast);
+ stats->tx_multicast = rte_le_to_cpu_64(resp.tx_multicast);
+ stats->tx_vlan_packet_good = rte_le_to_cpu_64(resp.tx_vlan_packet_good);
+ stats->tx_size_64 = rte_le_to_cpu_64(resp.tx_size_64);
+ stats->tx_size_65_127 = rte_le_to_cpu_64(resp.tx_size_65_127);
+ stats->tx_size_128_255 = rte_le_to_cpu_64(resp.tx_size_128_255);
+ stats->tx_size_256_511 = rte_le_to_cpu_64(resp.tx_size_256_511);
+ stats->tx_size_512_1023 = rte_le_to_cpu_64(resp.tx_size_512_1023);
+ stats->tx_size_1024_1522 = rte_le_to_cpu_64(resp.tx_size_1024_1522);
+ stats->tx_size_1523_max = rte_le_to_cpu_64(resp.tx_size_1523_max);
+ stats->tx_underflow_error = rte_le_to_cpu_64(resp.tx_underflow_error);
+ stats->rx_byte_good_bad = rte_le_to_cpu_64(resp.rx_byte_good_bad);
+ stats->rx_frame_good_bad = rte_le_to_cpu_64(resp.rx_frame_good_bad);
+ stats->rx_unicast_good = rte_le_to_cpu_64(resp.rx_unicast_good);
+ stats->rx_vlan_packets = rte_le_to_cpu_64(resp.rx_vlan_packets);
+
+ for (i = 0; i < SXE2_MAX_USER_PRIORITY; i++) {
+ stats->rx_prio_buf_discard[i] =
+ rte_le_to_cpu_64(resp.rx_prio_buf_discard[i]);
+ stats->prio_xoff_rx[i] =
+ rte_le_to_cpu_64(resp.prio_xoff_rx[i]);
+ stats->prio_xoff_tx[i] =
+ rte_le_to_cpu_64(resp.prio_xoff_tx[i]);
+ stats->prio_xon_rx[i] =
+ rte_le_to_cpu_64(resp.prio_xon_rx[i]);
+ stats->prio_xon_tx[i] =
+ rte_le_to_cpu_64(resp.prio_xon_tx[i]);
+ stats->prio_xon_2_xoff[i] =
+ rte_le_to_cpu_64(resp.prio_xon_2_xoff[i]);
+ }
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_drv_mac_stats_reset(struct sxe2_adapter *adapter)
+{
+ int32_t ret = 0;
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_cmd_params param = {0};
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_MAC_STATS_CLEAR,
+ NULL, 0,
+ NULL, 0);
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "mac stats reset failed, ret=%d", ret);
+ goto l_end;
+ }
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_drv_get_vsi_stats(struct sxe2_adapter *adapter)
+{
+ int32_t ret = 0;
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_vsi *vsi = adapter->vsi_ctxt.main_vsi;
+ struct sxe2_stats *new_stats = &vsi->vsi_stats.vsi_hw_stats;
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_drv_vsi_stats_req req = {0};
+ struct sxe2_drv_vsi_stats_resp resp = {0};
+
+ req.vsi_id = rte_cpu_to_le_16(vsi->vsi_id);
+ req.sw_stats.rx_bytes = rte_cpu_to_le_64(vsi->vsi_stats.stats.ibytes);
+ req.sw_stats.rx_packets = rte_cpu_to_le_64(vsi->vsi_stats.stats.ipackets);
+ req.sw_stats.tx_bytes = rte_cpu_to_le_64(vsi->vsi_stats.stats.obytes);
+ req.sw_stats.tx_packets = rte_cpu_to_le_64(vsi->vsi_stats.stats.opackets);
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_VSI_STATS_GET,
+ &req, sizeof(req),
+ &resp, sizeof(resp));
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "vsi stats get failed, ret=%d", ret);
+ goto l_end;
+ }
+
+ new_stats->rx_vsi_unicast_packets = rte_le_to_cpu_64(resp.rx_vsi_unicast_packets);
+ new_stats->rx_vsi_bytes = rte_le_to_cpu_64(resp.rx_vsi_bytes);
+ new_stats->tx_vsi_unicast_packets = rte_le_to_cpu_64(resp.tx_vsi_unicast_packets);
+ new_stats->tx_vsi_bytes = rte_le_to_cpu_64(resp.tx_vsi_bytes);
+ new_stats->rx_vsi_multicast_packets = rte_le_to_cpu_64(resp.rx_vsi_multicast_packets);
+ new_stats->tx_vsi_multicast_packets = rte_le_to_cpu_64(resp.tx_vsi_multicast_packets);
+ new_stats->rx_vsi_broadcast_packets = rte_le_to_cpu_64(resp.rx_vsi_broadcast_packets);
+ new_stats->tx_vsi_broadcast_packets = rte_le_to_cpu_64(resp.tx_vsi_broadcast_packets);
+ new_stats->opackets = new_stats->tx_vsi_unicast_packets +
+ new_stats->tx_vsi_multicast_packets +
+ new_stats->tx_vsi_broadcast_packets;
+ new_stats->obytes = new_stats->tx_vsi_bytes;
+ new_stats->ipackets = new_stats->rx_vsi_unicast_packets +
+ new_stats->rx_vsi_multicast_packets +
+ new_stats->rx_vsi_broadcast_packets;
+ new_stats->ibytes = new_stats->rx_vsi_bytes;
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_drv_vsi_stats_reset(struct sxe2_adapter *adapter)
+{
+ int32_t ret = 0;
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_cmd_params param = {0};
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_VSI_STATS_CLEAR,
+ NULL, 0, NULL, 0);
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "vsi stats reset failed, ret=%d", ret);
+ goto l_end;
+ }
+
+l_end:
+ return ret;
+}
+
int32_t sxe2_drv_promisc_config(struct sxe2_adapter *adapter, bool set)
{
int32_t ret = 0;
@@ -409,8 +587,9 @@ int32_t sxe2_drv_uc_config(struct sxe2_adapter *adapter, struct rte_ether_addr *
mac_filter_cfg_req.type = SXE2_MAC_FILTER_TYPE_UC;
sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_MAC_ADDR_UC,
- &mac_filter_cfg_req, sizeof(mac_filter_cfg_req),
- NULL, 0);
+ &mac_filter_cfg_req,
+ sizeof(mac_filter_cfg_req),
+ NULL, 0);
ret = sxe2_drv_cmd_exec(cdev, ¶m);
if (ret)
@@ -435,8 +614,8 @@ int32_t sxe2_drv_mc_config(struct sxe2_adapter *adapter, struct rte_ether_addr *
mac_filter_cfg_req.type = SXE2_MAC_FILTER_TYPE_MC;
sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_MAC_ADDR_MC,
- &mac_filter_cfg_req, sizeof(mac_filter_cfg_req),
- NULL, 0);
+ &mac_filter_cfg_req, sizeof(mac_filter_cfg_req),
+ NULL, 0);
ret = sxe2_drv_cmd_exec(cdev, ¶m);
if (ret)
@@ -455,7 +634,7 @@ int32_t sxe2_drv_vlan_config_query(struct sxe2_adapter *adapter)
sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_VLAN_CFG_QUERY,
NULL, 0,
&vlan_cfg_query_resp,
- sizeof(vlan_cfg_query_resp));
+ sizeof(vlan_cfg_query_resp));
ret = sxe2_drv_cmd_exec(cdev, ¶m);
if (ret)
@@ -566,7 +745,8 @@ int32_t sxe2_drv_rss_key_set(struct sxe2_adapter *adapter, uint8_t *key, uint16_
rte_memcpy(req->key, key, key_size);
sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_RSS_KEY_SET,
- req, buf_size, NULL, 0);
+ req, buf_size,
+ NULL, 0);
ret = sxe2_drv_cmd_exec(cdev, ¶m);
if (ret) {
@@ -602,7 +782,8 @@ int32_t sxe2_drv_rss_lut_set(struct sxe2_adapter *adapter, uint8_t *lut, uint16_
rte_memcpy(req->lut, lut, lut_size);
sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_RSS_LUT_SET,
- req, buf_size, NULL, 0);
+ req, buf_size,
+ NULL, 0);
ret = sxe2_drv_cmd_exec(cdev, ¶m);
if (ret) {
@@ -629,7 +810,8 @@ int32_t sxe2_drv_rss_hash_ctrl_func(struct sxe2_adapter *adapter, enum sxe2_rss_
req.func = func;
sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_RSS_FUNC_SET,
- &req, sizeof(req), NULL, 0);
+ &req, sizeof(req),
+ NULL, 0);
ret = sxe2_drv_cmd_exec(cdev, ¶m);
if (ret)
@@ -665,7 +847,8 @@ int32_t sxe2_drv_rss_hf_add(struct sxe2_adapter *adapter,
sxe2_drv_flow_bitmap_fill(req.hash_flds, rss_conf->flds);
sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_RSS_HF_ADD,
- &req, sizeof(req), NULL, 0);
+ &req, sizeof(req),
+ NULL, 0);
ret = sxe2_drv_cmd_exec(cdev, ¶m);
if (ret)
@@ -703,7 +886,8 @@ int32_t sxe2_drv_rss_hf_clear(struct sxe2_adapter *adapter)
int32_t ret = 0;
sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_RSS_HF_CLEAR,
- NULL, 0, NULL, 0);
+ NULL, 0,
+ NULL, 0);
ret = sxe2_drv_cmd_exec(cdev, ¶m);
if (ret)
@@ -878,7 +1062,6 @@ int32_t sxe2_drv_tm_commit(struct sxe2_adapter *adapter)
return ret;
}
-
int32_t sxe2_drv_ipsec_get_capa(struct sxe2_adapter *adapter)
{
int32_t ret = -1;
@@ -1074,3 +1257,138 @@ int32_t sxe2_drv_ipsec_txsa_delete(struct sxe2_adapter *adapter,
return ret;
}
+int32_t sxe2_drv_queue_info_get_update(struct sxe2_adapter *adapter, struct eth_queue_stats *qstats)
+{
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_queue_map_info resp = {0};
+ struct sxe2_common_device *cdev = adapter->cdev;
+ uint8_t pool_idx;
+ uint8_t index;
+ int32_t ret;
+
+ if (!(adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_Q_MAP)) {
+ ret = 0;
+ goto l_end;
+ }
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_TX_RX_MAP_GET,
+ NULL, 0,
+ &resp, sizeof(resp));
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "get queue info map failed, ret=%d", ret);
+ goto l_end;
+ }
+
+ for (pool_idx = 0; pool_idx < SXE2_RXQ_STATS_MAP_MAX_NUM; pool_idx++) {
+ qstats->q_ipackets[pool_idx] = resp.rxq_stats_map_info[pool_idx].rxq_lan_in_pkt_cnt;
+ qstats->q_ibytes[pool_idx] = resp.rxq_stats_map_info[pool_idx].rxq_lan_in_byte_cnt;
+ }
+
+ for (index = 0; index < SXE2_TXQ_STATS_MAP_MAX_NUM; index++) {
+ qstats->q_opackets[index] = resp.txq_stats_map_info[index].txq_lan_pkt_cnt;
+ qstats->q_obytes[index] = resp.txq_stats_map_info[index].txq_lan_byte_cnt;
+ }
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_drv_rxq_mapping_set(struct rte_eth_dev *eth_dev, uint16_t queue_id, uint8_t pool_idx)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(eth_dev);
+ int32_t ret = 0;
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_drv_rx_map_req req = {0};
+ struct sxe2_rx_queue *rxq = NULL;
+
+ rxq = eth_dev->data->rx_queues[queue_id];
+ if (rxq == NULL) {
+ PMD_LOG_ERR(DRV, "Rx queue %u is not available or setup",
+ queue_id);
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ req.queue_id = rxq->queue_id;
+ req.pool_idx = pool_idx;
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_RX_MAP_SET,
+ &req, sizeof(req),
+ NULL, 0);
+
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret)
+ PMD_LOG_ERR(DRV, "get dev caps failed, ret=%d", ret);
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_drv_txq_mapping_set(struct rte_eth_dev *eth_dev, uint16_t queue_id, uint8_t pool_idx)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(eth_dev);
+ int32_t ret = 0;
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_drv_tx_map_req req = {0};
+ struct sxe2_tx_queue *txq = NULL;
+
+ txq = eth_dev->data->tx_queues[queue_id];
+ if (txq == NULL) {
+ PMD_LOG_ERR(DRV, "Rx queue %u is not available or setup", queue_id);
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ req.queue_id = txq->queue_id;
+ req.pool_idx = pool_idx;
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_TX_MAP_SET,
+ &req, sizeof(req),
+ NULL, 0);
+
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret)
+ PMD_LOG_ERR(DRV, "get dev caps failed, ret=%d", ret);
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_drv_mapping_reset(struct rte_eth_dev *eth_dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(eth_dev);
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_common_device *cdev = adapter->cdev;
+ int32_t ret;
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_TX_RX_MAP_RESET,
+ NULL, 0,
+ NULL, 0);
+
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret)
+ PMD_LOG_ERR(DRV, "Reset queue mapping failed, ret=%d", ret);
+
+ return ret;
+}
+
+int32_t sxe2_drv_mapping_stats_info_clear(struct rte_eth_dev *eth_dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(eth_dev);
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_common_device *cdev = adapter->cdev;
+ int32_t ret;
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_TX_RX_MAP_INFO_CLEAR,
+ NULL, 0,
+ NULL, 0);
+
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret)
+ PMD_LOG_ERR(DRV, "Clear map stats info failed, ret=%d", ret);
+
+ return ret;
+}
diff --git a/drivers/net/sxe2/sxe2_cmd_chnl.h b/drivers/net/sxe2/sxe2_cmd_chnl.h
index dac487fe7d..80ad10ac00 100644
--- a/drivers/net/sxe2/sxe2_cmd_chnl.h
+++ b/drivers/net/sxe2/sxe2_cmd_chnl.h
@@ -64,6 +64,29 @@ int32_t sxe2_drv_ipsec_txsa_delete(struct sxe2_adapter *adapter,
int32_t sxe2_drv_promisc_config(struct sxe2_adapter *adapter, bool set);
+int32_t sxe2_drv_mac_link_status_get(struct sxe2_adapter *adapter);
+
+int32_t sxe2_drv_get_mac_stats(struct sxe2_adapter *adapter);
+
+int32_t sxe2_drv_mac_stats_reset(struct sxe2_adapter *adapter);
+
+int32_t sxe2_drv_get_vsi_stats(struct sxe2_adapter *adapter);
+
+int32_t sxe2_drv_vsi_stats_reset(struct sxe2_adapter *adapter);
+
+int32_t sxe2_drv_queue_info_get_update(struct sxe2_adapter *adapter,
+ struct eth_queue_stats *qstats);
+
+int32_t sxe2_drv_rxq_mapping_set(struct rte_eth_dev *eth_dev, uint16_t queue_id, uint8_t pool_idx);
+
+int32_t sxe2_drv_txq_mapping_set(struct rte_eth_dev *eth_dev, uint16_t queue_id, uint8_t pool_idx);
+
+int32_t sxe2_drv_mapping_reset(struct rte_eth_dev *eth_dev);
+
+int32_t sxe2_drv_mapping_stats_info_clear(struct rte_eth_dev *eth_dev);
+
+int32_t sxe2_drv_rxq_mapping_set(struct rte_eth_dev *eth_dev, uint16_t queue_id, uint8_t pool_idx);
+
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 39a108d76a..7935a28dc1 100644
--- a/drivers/net/sxe2/sxe2_drv_cmd.h
+++ b/drivers/net/sxe2/sxe2_drv_cmd.h
@@ -436,6 +436,126 @@ struct __rte_aligned(4) __rte_packed_begin sxe2_drv_ipsec_rxsa_del_req {
uint8_t drv_id;
} __rte_packed_end;
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_vsi_sw_stats {
+ uint64_t rx_packets;
+ uint64_t rx_bytes;
+ uint64_t tx_packets;
+ uint64_t tx_bytes;
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_vsi_stats_req {
+ uint16_t vsi_id;
+ uint8_t rsv[2];
+ struct sxe2_drv_vsi_sw_stats sw_stats;
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_vsi_stats_resp {
+ uint64_t rx_vsi_unicast_packets;
+ uint64_t rx_vsi_bytes;
+ uint64_t tx_vsi_unicast_packets;
+ uint64_t tx_vsi_bytes;
+ uint64_t rx_vsi_multicast_packets;
+ uint64_t tx_vsi_multicast_packets;
+ uint64_t rx_vsi_broadcast_packets;
+ uint64_t tx_vsi_broadcast_packets;
+} __rte_packed_end;
+
+#define SXE2_MAX_USER_PRIORITY (8)
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_mac_stats_resp {
+ uint64_t rx_out_of_buffer;
+ uint64_t rx_qblock_drop;
+ uint64_t tx_frame_good;
+ uint64_t rx_frame_good;
+ uint64_t rx_crc_errors;
+ uint64_t tx_bytes_good;
+ uint64_t rx_bytes_good;
+ uint64_t tx_multicast_good;
+ uint64_t tx_broadcast_good;
+ uint64_t rx_multicast_good;
+ uint64_t rx_broadcast_good;
+ uint64_t rx_len_errors;
+ uint64_t rx_out_of_range_errors;
+ uint64_t rx_oversize_pkts_phy;
+ uint64_t rx_symbol_err;
+ uint64_t rx_pause_frame;
+ uint64_t tx_pause_frame;
+ uint64_t rx_discards_phy;
+ uint64_t rx_discards_ips_phy;
+ uint64_t tx_dropped_link_down;
+ uint64_t rx_undersize_good;
+ uint64_t rx_runt_error;
+ uint64_t tx_bytes_good_bad;
+ uint64_t tx_frame_good_bad;
+ uint64_t rx_jabbers;
+ uint64_t rx_size_64;
+ uint64_t rx_size_65_127;
+ uint64_t rx_size_128_255;
+ uint64_t rx_size_256_511;
+ uint64_t rx_size_512_1023;
+ uint64_t rx_size_1024_1522;
+ uint64_t rx_size_1523_max;
+ uint64_t rx_pcs_symbol_err_phy;
+ uint64_t rx_corrected_bits_phy;
+ uint64_t rx_err_lane_0_phy;
+ uint64_t rx_err_lane_1_phy;
+ uint64_t rx_err_lane_2_phy;
+ uint64_t rx_err_lane_3_phy;
+ uint64_t rx_prio_buf_discard[SXE2_MAX_USER_PRIORITY];
+ uint64_t rx_illegal_bytes;
+ uint64_t rx_oversize_good;
+ uint64_t tx_unicast;
+ uint64_t tx_broadcast;
+ uint64_t tx_multicast;
+ uint64_t tx_vlan_packet_good;
+ uint64_t tx_size_64;
+ uint64_t tx_size_65_127;
+ uint64_t tx_size_128_255;
+ uint64_t tx_size_256_511;
+ uint64_t tx_size_512_1023;
+ uint64_t tx_size_1024_1522;
+ uint64_t tx_size_1523_max;
+ uint64_t tx_underflow_error;
+ uint64_t rx_byte_good_bad;
+ uint64_t rx_frame_good_bad;
+ uint64_t rx_unicast_good;
+ uint64_t rx_vlan_packets;
+ uint64_t prio_xoff_rx[SXE2_MAX_USER_PRIORITY];
+ uint64_t prio_xon_rx[SXE2_MAX_USER_PRIORITY];
+ uint64_t prio_xon_tx[SXE2_MAX_USER_PRIORITY];
+ uint64_t prio_xoff_tx[SXE2_MAX_USER_PRIORITY];
+ uint64_t prio_xon_2_xoff[SXE2_MAX_USER_PRIORITY];
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_txq_map_info {
+ uint32_t txq_lan_pkt_cnt;
+ uint32_t txq_lan_byte_cnt;
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_rxq_map_info {
+ uint64_t rxq_lan_in_pkt_cnt;
+ uint64_t rxq_lan_in_byte_cnt;
+ uint64_t rxq_fd_in_pkt_cnt;
+ uint64_t rxq_mng_in_pkt_cnt;
+ uint64_t rxq_mng_in_byte_cnt;
+ uint64_t rxq_mng_out_pkt_cnt;
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_queue_map_info {
+ struct sxe2_rxq_map_info rxq_stats_map_info[SXE2_RXQ_STATS_MAP_MAX_NUM];
+ struct sxe2_txq_map_info txq_stats_map_info[SXE2_TXQ_STATS_MAP_MAX_NUM];
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_rx_map_req {
+ uint16_t queue_id;
+ uint8_t pool_idx;
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_tx_map_req {
+ uint16_t queue_id;
+ uint8_t pool_idx;
+} __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 9c9d98782b..46c6c993bf 100644
--- a/drivers/net/sxe2/sxe2_ethdev.c
+++ b/drivers/net/sxe2/sxe2_ethdev.c
@@ -31,6 +31,8 @@
#include "sxe2_common.h"
#include "sxe2_ptype.h"
#include "sxe2_common_log.h"
+#include "sxe2_mp.h"
+#include "sxe2_stats.h"
#include "sxe2_host_regs.h"
#include "sxe2_ioctl_chnl_func.h"
@@ -132,6 +134,14 @@ static const struct eth_dev_ops sxe2_eth_dev_ops = {
.rss_hash_conf_get = sxe2_dev_rss_hash_conf_get,
.tm_ops_get = sxe2_tm_ops_get,
+
+ .stats_get = sxe2_stats_info_get,
+ .stats_reset = sxe2_stats_info_reset,
+ .xstats_get = sxe2_xstats_info_get,
+ .xstats_get_names = sxe2_xstats_names_get,
+ .xstats_reset = sxe2_stats_info_reset,
+
+ .queue_stats_mapping_set = sxe2_queue_stats_mapping_set,
};
static int32_t sxe2_dev_configure(struct rte_eth_dev *dev)
@@ -1023,6 +1033,9 @@ static int32_t sxe2_dev_init(struct rte_eth_dev *dev,
if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
sxe2_rx_mode_func_set(dev);
sxe2_tx_mode_func_set(dev);
+ ret = sxe2_mp_init(dev);
+ if (ret != 0)
+ PMD_LOG_ERR(INIT, "Failed to mp init (secondary), ret=%d", ret);
goto l_end;
}
@@ -1076,12 +1089,27 @@ static int32_t sxe2_dev_init(struct rte_eth_dev *dev,
goto init_sched_err;
}
+ ret = sxe2_stats_init(dev);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to stats init, ret=%d", ret);
+ goto init_xstats_err;
+ }
+
+ ret = sxe2_mp_init(dev);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to mp init, ret=%d", ret);
+ goto init_xstats_err;
+ }
+
goto l_end;
-init_security_err:
- sxe2_eth_uinit(dev);
+init_xstats_err:
+ (void)sxe2_sched_uinit(dev);
init_sched_err:
init_rss_err:
+ sxe2_security_uinit(dev);
+init_security_err:
+ sxe2_eth_uinit(dev);
init_eth_err:
init_dev_info_err:
sxe2_vsi_uninit(dev);
@@ -1093,8 +1121,13 @@ static int32_t sxe2_dev_init(struct rte_eth_dev *dev,
static int32_t sxe2_dev_close(struct rte_eth_dev *dev)
{
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
+ sxe2_mp_uninit(dev);
+ goto l_end;
+ }
(void)sxe2_dev_stop(dev);
(void)sxe2_queues_release(dev);
+ sxe2_mp_uninit(dev);
(void)sxe2_rss_disable(dev);
(void)sxe2_sched_uinit(dev);
sxe2_vsi_uninit(dev);
@@ -1102,6 +1135,7 @@ static int32_t sxe2_dev_close(struct rte_eth_dev *dev)
sxe2_dev_pci_map_uinit(dev);
sxe2_eth_uinit(dev);
+l_end:
return 0;
}
diff --git a/drivers/net/sxe2/sxe2_mp.c b/drivers/net/sxe2/sxe2_mp.c
new file mode 100644
index 0000000000..a4a5c76495
--- /dev/null
+++ b/drivers/net/sxe2/sxe2_mp.c
@@ -0,0 +1,414 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+ #include <stdlib.h>
+#include <rte_eal.h>
+#include <rte_ethdev.h>
+#include <ethdev_driver.h>
+#include <rte_log.h>
+#include <rte_malloc.h>
+#include <rte_memzone.h>
+#include <rte_string_fns.h>
+
+#include "sxe2_mp.h"
+#include "sxe2_stats.h"
+#include "sxe2_common_log.h"
+
+static RTE_ATOMIC(uint16_t)primary_ethdev_cnt;
+static RTE_ATOMIC(uint16_t)secondary_ethdev_cnt;
+static const struct rte_memzone *sxe2_mp_mz;
+
+static int32_t sxe2_mp_acquire_token(void);
+static void sxe2_mp_release_token(void);
+
+static int32_t sxe2_mp_primary_handle(const struct rte_mp_msg *mp_msg,
+ const void *peer);
+
+static int32_t sxe2_mp_secondary_handle(const struct rte_mp_msg *mp_msg,
+ const void *peer);
+
+static int32_t
+sxe2_mp_primary_handle(const struct rte_mp_msg *mp_msg, const void *peer)
+{
+ struct rte_mp_msg reply;
+ const struct sxe2_mp_param *param =
+ (const struct sxe2_mp_param *)mp_msg->param;
+ struct sxe2_mp_param *reply_param = (struct sxe2_mp_param *)reply.param;
+ struct rte_eth_dev *dev;
+ int32_t ret = 0;
+ struct sxe2_mp_shared_data *mz_data;
+ int32_t send_reply = 0;
+ int32_t cnt = 0;
+
+ if (!rte_eth_dev_is_valid_port(param->port_id)) {
+ PMD_LOG_ERR(DRV, "primary process: invalid port_id %u",
+ param->port_id);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ dev = &rte_eth_devices[param->port_id];
+ sxe2_mp_mz = rte_memzone_lookup(SXE2_MP_MZ_NAME);
+ if (sxe2_mp_mz == NULL) {
+ PMD_LOG_ERR(DRV, "Failed to lookup memzone %s", SXE2_MP_MZ_NAME);
+ ret = -ENOENT;
+ goto out;
+ }
+
+ mz_data = (struct sxe2_mp_shared_data *)sxe2_mp_mz->addr;
+ send_reply = 1;
+
+ memset(&reply, 0, sizeof(reply));
+ (void)strlcpy(reply.name, SXE2_MP_NAME, sizeof(reply.name));
+ reply.len_param = sizeof(*reply_param);
+
+ switch (param->type) {
+ case SXE2_MP_REQ_GET_STATS:
+ ret = sxe2_stats_info_get(dev,
+ &mz_data->payload.stats_blk.stats,
+ &mz_data->payload.stats_blk.qstats);
+ break;
+ case SXE2_MP_REQ_GET_XSTATS:
+ cnt = sxe2_xstats_info_get(dev,
+ mz_data->payload.xstats_blk.xstats,
+ SXE2_MP_MAX_XSTATS);
+
+ if (cnt >= 0) {
+ mz_data->payload.xstats_blk.xstats_num = (uint32_t)cnt;
+ ret = 0;
+ } else {
+ mz_data->payload.xstats_blk.xstats_num = 0;
+ ret = cnt;
+ }
+ break;
+ case SXE2_MP_REQ_RESET_STATS:
+ ret = sxe2_stats_hw_reset(dev);
+ break;
+ default:
+ PMD_LOG_ERR(DRV, "primary process: unrecognized msg type: %d",
+ param->type);
+ send_reply = false;
+ ret = -EINVAL;
+ goto out;
+ }
+out:
+ if (!send_reply)
+ return ret;
+
+ reply_param->result = ret;
+ reply_param->type = param->type;
+ reply_param->port_id = param->port_id;
+
+ return rte_mp_reply(&reply, peer);
+}
+
+static int32_t
+sxe2_mp_secondary_handle(const struct rte_mp_msg *mp_msg __rte_unused,
+ const void *peer __rte_unused)
+{
+ PMD_LOG_WARN(DRV, "the secondary process handler should not be called");
+ return 0;
+}
+
+static int32_t
+sxe2_mp_init_primary(__rte_unused struct rte_eth_dev *dev)
+{
+ int32_t ret;
+
+ if (sxe2_mp_mz == NULL) {
+ sxe2_mp_mz = rte_memzone_reserve(SXE2_MP_MZ_NAME,
+ sizeof(struct sxe2_mp_shared_data),
+ rte_socket_id(), 0);
+ if (sxe2_mp_mz == NULL && rte_errno != EEXIST) {
+ PMD_LOG_ERR(DRV, "Failed to reserve memzone %s, error: %d",
+ SXE2_MP_MZ_NAME, -rte_errno);
+ ret = -rte_errno;
+ goto out;
+ }
+
+ sxe2_mp_mz = rte_memzone_lookup(SXE2_MP_MZ_NAME);
+ if (sxe2_mp_mz == NULL) {
+ PMD_LOG_ERR(DRV, "Failed to lookup memzone %s", SXE2_MP_MZ_NAME);
+ ret = -ENOENT;
+ goto out;
+ }
+
+ struct sxe2_mp_shared_data *mz =
+ (struct sxe2_mp_shared_data *)sxe2_mp_mz->addr;
+ rte_atomic_store_explicit(&mz->in_use, 0, rte_memory_order_release);
+ }
+
+ ret = rte_mp_action_register(SXE2_MP_NAME, sxe2_mp_primary_handle);
+ if (ret && rte_errno == ENOTSUP) {
+ PMD_LOG_INFO(DRV, "Primary not support IPC.");
+ ret = 0;
+ goto out;
+ } else if (ret && rte_errno != EEXIST) {
+ PMD_LOG_ERR(DRV, "Failed to register MP primary handle, error: %d",
+ -rte_errno);
+ goto out;
+ }
+
+ rte_atomic_fetch_add_explicit(&primary_ethdev_cnt, 1, rte_memory_order_relaxed);
+
+ ret = 0;
+out:
+ return ret;
+}
+
+static int32_t
+sxe2_mp_init_secondary(__rte_unused struct rte_eth_dev *dev)
+{
+ int32_t ret;
+
+ sxe2_mp_mz = rte_memzone_lookup(SXE2_MP_MZ_NAME);
+ if (sxe2_mp_mz == NULL) {
+ PMD_LOG_ERR(DRV, "Failed to lookup memzone %s", SXE2_MP_MZ_NAME);
+ ret = -ENOENT;
+ goto out;
+ }
+
+ ret = rte_mp_action_register(SXE2_MP_NAME, sxe2_mp_secondary_handle);
+ if (ret && rte_errno != EEXIST) {
+ PMD_LOG_ERR(DRV, "Failed to register MP secondary handle, error: %d",
+ -rte_errno);
+ goto out;
+ }
+
+ rte_atomic_fetch_add_explicit(&secondary_ethdev_cnt, 1, rte_memory_order_relaxed);
+
+ ret = 0;
+out:
+ return ret;
+}
+
+int32_t
+sxe2_mp_init(struct rte_eth_dev *dev)
+{
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+ return sxe2_mp_init_primary(dev);
+ else
+ return sxe2_mp_init_secondary(dev);
+}
+
+void
+sxe2_mp_uninit(__rte_unused struct rte_eth_dev *dev)
+{
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+ if (rte_atomic_fetch_sub_explicit(&primary_ethdev_cnt, 1,
+ rte_memory_order_acq_rel) == 1) {
+ rte_mp_action_unregister(SXE2_MP_NAME);
+ if (sxe2_mp_mz != NULL) {
+ rte_memzone_free(sxe2_mp_mz);
+ sxe2_mp_mz = NULL;
+ }
+ }
+ } else {
+ if (rte_atomic_fetch_sub_explicit(&secondary_ethdev_cnt, 1,
+ rte_memory_order_acq_rel) == 1)
+ rte_mp_action_unregister(SXE2_MP_NAME);
+ }
+}
+
+static int32_t sxe2_mp_acquire_token(void)
+{
+ struct sxe2_mp_shared_data *mz;
+ uint16_t expected;
+
+ if (sxe2_mp_mz == NULL)
+ return -EINVAL;
+
+ mz = (struct sxe2_mp_shared_data *)sxe2_mp_mz->addr;
+
+ for (int32_t i = 0; i < SXE2_MP_MAX_SPIN; i++) {
+ expected = 0;
+ if (rte_atomic_compare_exchange_strong_explicit(&mz->in_use, &expected, 1,
+ rte_memory_order_acquire, rte_memory_order_relaxed))
+ return 0;
+
+ rte_pause();
+ }
+ return -EBUSY;
+}
+
+static void sxe2_mp_release_token(void)
+{
+ struct sxe2_mp_shared_data *mz;
+
+ if (sxe2_mp_mz == NULL)
+ return;
+
+ mz = (struct sxe2_mp_shared_data *)sxe2_mp_mz->addr;
+ rte_atomic_store_explicit(&mz->in_use, 0, rte_memory_order_release);
+}
+
+int32_t sxe2_mp_request_simple(struct rte_eth_dev *dev,
+ enum sxe2_mp_req_type type,
+ int32_t *result_out)
+{
+ struct rte_mp_msg msg;
+ struct rte_mp_reply reply = { 0 };
+ struct timespec ts = { .tv_sec = SXE2_MP_MSG_TIMEOUT, .tv_nsec = 0 };
+ struct sxe2_mp_param *param = (struct sxe2_mp_param *)msg.param;
+ struct sxe2_mp_shared_data *mz_data;
+ int32_t ret = 0;
+
+ mz_data = (struct sxe2_mp_shared_data *)sxe2_mp_mz->addr;
+
+ memset(&mz_data->payload, 0, sizeof(mz_data->payload));
+ memset(&msg, 0, sizeof(msg));
+ (void)strlcpy(msg.name, SXE2_MP_NAME, sizeof(msg.name));
+ msg.len_param = sizeof(*param);
+ param->type = type;
+ param->port_id = dev->data->port_id;
+
+ ret = rte_mp_request_sync(&msg, &reply, &ts);
+ if (ret != 0) {
+ PMD_LOG_ERR(DRV,
+ "IPC request(type=%d) failed for port %u: %s",
+ type, dev->data->port_id, rte_strerror(rte_errno));
+ ret = -rte_errno;
+ goto out;
+ }
+
+ if (reply.nb_received == 0) {
+ PMD_LOG_ERR(DRV, "No response received from primary for type=%d, port %u",
+ type, dev->data->port_id);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ *result_out = ((struct sxe2_mp_param *)reply.msgs[0].param)->result;
+
+out:
+ if (reply.msgs != NULL)
+ free(reply.msgs);
+
+ return ret;
+}
+
+int32_t sxe2_mp_req_get_stats(struct rte_eth_dev *dev,
+ struct rte_eth_stats *stats,
+ struct eth_queue_stats *qstats)
+{
+ struct sxe2_mp_shared_data *mz_data;
+ int32_t mp_ret;
+ int32_t ret;
+ int32_t token_acquired = 0;
+
+ if (sxe2_mp_mz == NULL)
+ return -EINVAL;
+
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+ PMD_LOG_WARN(DRV, "Primary process direct execution for port %u",
+ dev->data->port_id);
+ return sxe2_stats_info_get(dev, stats, qstats);
+ }
+
+ int32_t token_ret = sxe2_mp_acquire_token();
+ if (token_ret != 0)
+ return token_ret;
+ token_acquired = 1;
+
+ mp_ret = sxe2_mp_request_simple(dev, SXE2_MP_REQ_GET_STATS, &ret);
+ if (mp_ret != 0) {
+ ret = mp_ret;
+ goto out;
+ }
+
+ if (ret != 0) {
+ PMD_LOG_ERR(DRV, "Primary failed to exec request (type=%d), result: %d for port %u",
+ SXE2_MP_REQ_GET_STATS, ret, dev->data->port_id);
+ goto out;
+ }
+
+ mz_data = (struct sxe2_mp_shared_data *)sxe2_mp_mz->addr;
+ memcpy(stats, &mz_data->payload.stats_blk.stats, sizeof(*stats));
+ memcpy(qstats, &mz_data->payload.stats_blk.qstats, sizeof(*qstats));
+ PMD_LOG_DEBUG(DRV, "sxe2_mp: stats received via IPC for port %u",
+ dev->data->port_id);
+ ret = 0;
+out:
+ if (token_acquired)
+ sxe2_mp_release_token();
+ return ret;
+}
+
+int32_t sxe2_mp_req_get_xstats(struct rte_eth_dev *dev,
+ struct rte_eth_xstat *xstats, uint32_t usr_cnt)
+{
+ struct sxe2_mp_shared_data *mz_data;
+ int32_t ret;
+ int32_t mp_ret;
+ int32_t token_acquired = 0;
+
+ if (sxe2_mp_mz == NULL)
+ return -EINVAL;
+
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+ PMD_LOG_WARN(DRV, "Primary process direct execution for port %u",
+ dev->data->port_id);
+ return sxe2_xstats_info_get(dev, xstats, usr_cnt);
+ }
+
+ int32_t token_ret = sxe2_mp_acquire_token();
+ if (token_ret != 0)
+ return token_ret;
+ token_acquired = 1;
+
+ mp_ret = sxe2_mp_request_simple(dev, SXE2_MP_REQ_GET_XSTATS, &ret);
+ if (mp_ret != 0) {
+ ret = mp_ret;
+ goto out;
+ }
+
+ if (ret != 0) {
+ PMD_LOG_ERR(DRV, "Primary failed to exec request (type=%d), result: %d for port %u",
+ SXE2_MP_REQ_GET_XSTATS, ret, dev->data->port_id);
+ goto out;
+ }
+
+ mz_data = (struct sxe2_mp_shared_data *)sxe2_mp_mz->addr;
+ if (usr_cnt < mz_data->payload.xstats_blk.xstats_num) {
+ PMD_LOG_ERR(DRV, "user usr_cnt:%u less than xstats cnt:%u.",
+ usr_cnt, mz_data->payload.xstats_blk.xstats_num);
+ ret = (int32_t)mz_data->payload.xstats_blk.xstats_num;
+ goto out;
+ }
+
+ memcpy(xstats, mz_data->payload.xstats_blk.xstats,
+ mz_data->payload.xstats_blk.xstats_num *
+ sizeof(struct rte_eth_xstat));
+ ret = (int32_t)mz_data->payload.xstats_blk.xstats_num;
+
+ PMD_LOG_DEBUG(DRV,
+ "xstats received via IPC for port %u (cnt=%d)",
+ dev->data->port_id, ret);
+out:
+ if (token_acquired)
+ sxe2_mp_release_token();
+ return ret;
+}
+
+int32_t
+sxe2_mp_req_reset_stats(struct rte_eth_dev *dev)
+{
+ int32_t mp_ret;
+ int32_t ret = 0;
+
+ if (sxe2_mp_mz == NULL)
+ return -EINVAL;
+
+ mp_ret = sxe2_mp_request_simple(dev, SXE2_MP_REQ_RESET_STATS, &ret);
+ if (mp_ret != 0)
+ return mp_ret;
+
+ if (ret != 0) {
+ PMD_LOG_ERR(DRV,
+ "Primary failed SXE2_MP_REQ_RESET_STATS, result: %d for port %u",
+ ret, dev->data->port_id);
+ return ret;
+ }
+ return 0;
+}
diff --git a/drivers/net/sxe2/sxe2_mp.h b/drivers/net/sxe2/sxe2_mp.h
new file mode 100644
index 0000000000..da9cc91d8d
--- /dev/null
+++ b/drivers/net/sxe2/sxe2_mp.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#ifndef SXE2_MP_H
+#define SXE2_MP_H
+
+#include <rte_eal.h>
+#include <rte_ethdev.h>
+#include <rte_memzone.h>
+#include <rte_stdatomic.h>
+
+#define SXE2_MP_NAME "sxe2_mp_msg"
+#define SXE2_MP_MZ_NAME "sxe2_stats_mz"
+
+#define SXE2_MP_MSG_TIMEOUT 30
+
+#define SXE2_MP_MAX_XSTATS 128
+
+#define SXE2_MP_MAX_SPIN 100000
+
+enum sxe2_mp_req_type {
+ SXE2_MP_REQ_GET_STATS = 1,
+ SXE2_MP_REQ_GET_XSTATS,
+ SXE2_MP_REQ_RESET_STATS,
+};
+
+struct sxe2_mp_param {
+ enum sxe2_mp_req_type type;
+ uint32_t port_id;
+ int result;
+};
+
+union sxe2_mp_shared_payload {
+ struct {
+ struct rte_eth_stats stats;
+ struct eth_queue_stats qstats;
+ } stats_blk;
+ struct {
+ struct rte_eth_xstat xstats[SXE2_MP_MAX_XSTATS];
+ uint32_t xstats_num;
+ } xstats_blk;
+};
+
+struct sxe2_mp_shared_data {
+ RTE_ATOMIC(uint16_t)in_use;
+ union sxe2_mp_shared_payload payload;
+};
+
+int sxe2_mp_init(struct rte_eth_dev *dev);
+
+void sxe2_mp_uninit(struct rte_eth_dev *dev);
+
+int sxe2_mp_request_simple(struct rte_eth_dev *dev,
+ enum sxe2_mp_req_type type,
+ int *result_out);
+
+int sxe2_mp_req_get_stats(struct rte_eth_dev *dev,
+ struct rte_eth_stats *stats,
+ struct eth_queue_stats *qstats);
+
+int sxe2_mp_req_get_xstats(struct rte_eth_dev *dev,
+ struct rte_eth_xstat *xstats, uint32_t usr_cnt);
+
+int sxe2_mp_req_reset_stats(struct rte_eth_dev *dev);
+
+#endif
diff --git a/drivers/net/sxe2/sxe2_stats.c b/drivers/net/sxe2/sxe2_stats.c
new file mode 100644
index 0000000000..7ea2815fa3
--- /dev/null
+++ b/drivers/net/sxe2/sxe2_stats.c
@@ -0,0 +1,586 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#include <rte_eal.h>
+
+#include "sxe2_ethdev.h"
+#include "sxe2_vsi.h"
+#include "sxe2_common_log.h"
+#include "sxe2_stats.h"
+#include "sxe2_queue.h"
+#include "sxe2_cmd_chnl.h"
+#include "sxe2_mp.h"
+
+#define SXE2_XSTAT_CNT_PF RTE_DIM(sxe2_xstats_field_pf)
+#define SXE2_XSTAT_CNT_VF RTE_DIM(sxe2_xstats_field_vf)
+
+static struct sxe2_stats_field sxe2_xstats_field_pf[] = {
+ {"rx_qblock_drop", offsetof(struct sxe2_stats, rx_qblock_drop)},
+ {"rx_out_of_buffer", offsetof(struct sxe2_stats, rx_out_of_buffer)},
+ {"tx_packets_phy", offsetof(struct sxe2_stats, tx_frame_good)},
+ {"rx_packets_phy", offsetof(struct sxe2_stats, rx_frame_good)},
+ {"rx_crc_errors_phy", offsetof(struct sxe2_stats, rx_crc_errors)},
+ {"tx_bytes_phy", offsetof(struct sxe2_stats, tx_bytes_good)},
+ {"rx_bytes_phy", offsetof(struct sxe2_stats, rx_bytes_good)},
+ {"tx_multicast_phy", offsetof(struct sxe2_stats, tx_multicast_good)},
+ {"tx_broadcast_phy", offsetof(struct sxe2_stats, tx_broadcast_good)},
+ {"rx_multicast_phy", offsetof(struct sxe2_stats, rx_multicast_good)},
+ {"rx_broadcast_phy", offsetof(struct sxe2_stats, rx_broadcast_good)},
+ {"rx_in_range_len_errs_phy", offsetof(struct sxe2_stats, rx_len_errors)},
+ {"rx_out_of_range_len_phy", offsetof(struct sxe2_stats, rx_out_of_range_errors)},
+ {"rx_oversize_pkts_phy", offsetof(struct sxe2_stats, rx_oversize_pkts_phy)},
+ {"rx_symbol_err_phy", offsetof(struct sxe2_stats, rx_symbol_err)},
+ {"rx_pause_ctrl_phy", offsetof(struct sxe2_stats, rx_pause_frame)},
+ {"tx_pause_ctrl_phy", offsetof(struct sxe2_stats, tx_pause_frame)},
+ {"rx_discards_phy", offsetof(struct sxe2_stats, rx_discards_phy)},
+ {"rx_discards_ips_phy", offsetof(struct sxe2_stats, rx_discards_ips_phy)},
+ {"tx_dropped_link_down_phy", offsetof(struct sxe2_stats, tx_dropped_link_down)},
+ {"rx_undersize_pkts_phy", offsetof(struct sxe2_stats, rx_undersize_good)},
+ {"rx_fragments_phy", offsetof(struct sxe2_stats, rx_runt_error)},
+ {"tx_bytes_all_phy", offsetof(struct sxe2_stats, tx_bytes_good_bad)},
+ {"tx_packets_all_phy", offsetof(struct sxe2_stats, tx_frame_good_bad)},
+ {"rx_jabbers_phy", offsetof(struct sxe2_stats, rx_jabbers)},
+ {"rx_64_bytes_phy", offsetof(struct sxe2_stats, rx_size_64)},
+ {"rx_65_to_127_bytes_phy", offsetof(struct sxe2_stats, rx_size_65_127)},
+ {"rx_128_to_255_bytes_phy", offsetof(struct sxe2_stats, rx_size_128_255)},
+ {"rx_256_to_511_bytes_phy", offsetof(struct sxe2_stats, rx_size_256_511)},
+ {"rx_512_to_1023_bytes_phy", offsetof(struct sxe2_stats, rx_size_512_1023)},
+ {"rx_1024_to_1522_bytes_phy", offsetof(struct sxe2_stats, rx_size_1024_1522)},
+ {"rx_1523_to_max_bytes_phy", offsetof(struct sxe2_stats, rx_size_1523_max)},
+ {"rx_pcs_symbol_err_phy", offsetof(struct sxe2_stats, rx_pcs_symbol_err_phy)},
+ {"rx_corrected_bits_phy", offsetof(struct sxe2_stats, rx_corrected_bits_phy)},
+ {"rx_err_lane_0_phy", offsetof(struct sxe2_stats, rx_err_lane_0_phy)},
+ {"rx_err_lane_1_phy", offsetof(struct sxe2_stats, rx_err_lane_1_phy)},
+ {"rx_err_lane_2_phy", offsetof(struct sxe2_stats, rx_err_lane_2_phy)},
+ {"rx_err_lane_3_phy", offsetof(struct sxe2_stats, rx_err_lane_3_phy)},
+ {"rx_illegal_bytes_phy", offsetof(struct sxe2_stats, rx_illegal_bytes)},
+ {"rx_oversize_good_phy", offsetof(struct sxe2_stats, rx_oversize_good)},
+ {"tx_unicast_all_phy", offsetof(struct sxe2_stats, tx_unicast)},
+ {"tx_broadcast_all_phy", offsetof(struct sxe2_stats, tx_broadcast)},
+ {"tx_multicast_all_phy", offsetof(struct sxe2_stats, tx_multicast)},
+ {"tx_vlan_packets_good_phy", offsetof(struct sxe2_stats, tx_vlan_packet_good)},
+ {"tx_64_bytes_phy", offsetof(struct sxe2_stats, tx_size_64)},
+ {"tx_65_to_127_bytes_phy", offsetof(struct sxe2_stats, tx_size_65_127)},
+ {"tx_128_to_255_bytes_phy", offsetof(struct sxe2_stats, tx_size_128_255)},
+ {"tx_256_to_511_bytes_phy", offsetof(struct sxe2_stats, tx_size_256_511)},
+ {"tx_512_to_1023_bytes_phy", offsetof(struct sxe2_stats, tx_size_512_1023)},
+ {"tx_1024_to_1522_bytes_phy", offsetof(struct sxe2_stats, tx_size_1024_1522)},
+ {"tx_1523_to_max_bytes_phy", offsetof(struct sxe2_stats, tx_size_1523_max)},
+ {"tx_underflow_error_phy", offsetof(struct sxe2_stats, tx_underflow_error)},
+ {"rx_bytes_all_phy", offsetof(struct sxe2_stats, rx_byte_good_bad)},
+ {"rx_packets_all_phy", offsetof(struct sxe2_stats, rx_frame_good_bad)},
+ {"rx_unicast_phy", offsetof(struct sxe2_stats, rx_unicast_good)},
+ {"rx_vlan_packets_phy", offsetof(struct sxe2_stats, rx_vlan_packets)},
+
+ {"rx_vport_bytes", offsetof(struct sxe2_stats, rx_vsi_bytes)},
+ {"rx_vport_unicast_packets", offsetof(struct sxe2_stats, rx_vsi_unicast_packets)},
+ {"rx_vport_broadcast_packets", offsetof(struct sxe2_stats, rx_vsi_broadcast_packets)},
+ {"rx_vport_multicast_packets", offsetof(struct sxe2_stats, rx_vsi_multicast_packets)},
+ {"rx_sw_unicast_packets", offsetof(struct sxe2_stats, rx_sw_unicast_packets)},
+ {"rx_sw_broadcast_packets", offsetof(struct sxe2_stats, rx_sw_broadcast_packets)},
+ {"rx_sw_multicast_packets", offsetof(struct sxe2_stats, rx_sw_multicast_packets)},
+ {"rx_sw_drop_packets", offsetof(struct sxe2_stats, rx_sw_drop_packets)},
+ {"rx_sw_drop_bytes", offsetof(struct sxe2_stats, rx_sw_drop_bytes)},
+
+ {"tx_vport_bytes", offsetof(struct sxe2_stats, tx_vsi_bytes)},
+ {"tx_vport_unicast_packets", offsetof(struct sxe2_stats, tx_vsi_unicast_packets)},
+ {"tx_vport_broadcast_packets", offsetof(struct sxe2_stats, tx_vsi_broadcast_packets)},
+ {"tx_vport_multicast_packets", offsetof(struct sxe2_stats, tx_vsi_multicast_packets)},
+};
+
+static struct sxe2_stats_field sxe2_xstats_field_vf[] = {
+ {"rx_vport_bytes", offsetof(struct sxe2_stats, rx_vsi_bytes)},
+ {"rx_vport_unicast_packets", offsetof(struct sxe2_stats, rx_vsi_unicast_packets)},
+ {"rx_vport_broadcast_packets", offsetof(struct sxe2_stats, rx_vsi_broadcast_packets)},
+ {"rx_vport_multicast_packets", offsetof(struct sxe2_stats, rx_vsi_multicast_packets)},
+ {"rx_sw_unicast_packets", offsetof(struct sxe2_stats, rx_sw_unicast_packets)},
+ {"rx_sw_broadcast_packets", offsetof(struct sxe2_stats, rx_sw_broadcast_packets)},
+ {"rx_sw_multicast_packets", offsetof(struct sxe2_stats, rx_sw_multicast_packets)},
+ {"rx_sw_drop_packets", offsetof(struct sxe2_stats, rx_sw_drop_packets)},
+ {"rx_sw_drop_bytes", offsetof(struct sxe2_stats, rx_sw_drop_bytes)},
+
+ {"tx_vport_bytes", offsetof(struct sxe2_stats, tx_vsi_bytes)},
+ {"tx_vport_unicast_packets", offsetof(struct sxe2_stats, tx_vsi_unicast_packets)},
+ {"tx_vport_broadcast_packets", offsetof(struct sxe2_stats, tx_vsi_broadcast_packets)},
+ {"tx_vport_multicast_packets", offsetof(struct sxe2_stats, tx_vsi_multicast_packets)},
+};
+
+static int32_t sxe2_xstat_pf_offset_get(uint32_t id, uint32_t *offset)
+{
+ int32_t ret = 0;
+ uint32_t size = SXE2_XSTAT_CNT_PF;
+
+ if (id < size) {
+ *offset = sxe2_xstats_field_pf[id].offset;
+ } else {
+ ret = -EINVAL;
+ PMD_LOG_ERR(DRV, "invalid id:%u exceed stats size cnt:%u", id, size);
+ }
+ return ret;
+}
+
+static int32_t sxe2_xstat_vf_offset_get(uint32_t id, uint32_t *offset)
+{
+ int32_t ret = 0;
+ uint32_t size = SXE2_XSTAT_CNT_VF;
+
+ if (id < size) {
+ *offset = sxe2_xstats_field_vf[id].offset;
+ } else {
+ ret = -EINVAL;
+ PMD_LOG_ERR(DRV, "invalid id:%u exceed stats size cnt:%u", id, size);
+ }
+ return ret;
+}
+
+static int32_t sxe2_mac_hw_stats_get_update(struct sxe2_adapter *adapter)
+{
+ int32_t ret = 0;
+
+ ret = sxe2_drv_get_mac_stats(adapter);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "get mac stats failed, ret:%d.", ret);
+ goto l_end;
+ }
+
+l_end:
+ return ret;
+}
+
+static int32_t sxe2_vsi_hw_stats_get_update(struct sxe2_adapter *adapter)
+{
+ int32_t ret = 0;
+
+ ret = sxe2_drv_get_vsi_stats(adapter);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "get vsi stats failed, ret:%d.", ret);
+ goto l_end;
+ }
+
+l_end:
+ return ret;
+}
+
+static int32_t sxe2_vsi_sw_stats_get_update(struct sxe2_adapter *adapter)
+{
+ int32_t ret = 0;
+ struct sxe2_vsi *vsi = adapter->vsi_ctxt.main_vsi;
+ struct sxe2_stats *sw_stats = &vsi->vsi_stats.vsi_sw_stats;
+ struct sxe2_rx_queue *rxq;
+ uint32_t rx_queue_id;
+ memset(sw_stats, 0, sizeof(struct sxe2_stats));
+
+ for (rx_queue_id = 0; rx_queue_id < adapter->dev_info.dev_data->nb_rx_queues;
+ rx_queue_id++) {
+ rxq = adapter->dev_info.dev_data->rx_queues[rx_queue_id];
+ if (rxq) {
+ sw_stats->ipackets += rxq->sw_stats.pkts;
+ sw_stats->ierrors += rxq->sw_stats.drop_pkts;
+ sw_stats->ibytes += rxq->sw_stats.bytes;
+
+ sw_stats->rx_sw_unicast_packets += rxq->sw_stats.unicast_pkts;
+ sw_stats->rx_sw_broadcast_packets += rxq->sw_stats.broadcast_pkts;
+ sw_stats->rx_sw_multicast_packets += rxq->sw_stats.multicast_pkts;
+ sw_stats->rx_sw_drop_packets += rxq->sw_stats.drop_pkts;
+ sw_stats->rx_sw_drop_bytes += rxq->sw_stats.drop_bytes;
+ }
+ }
+
+ return ret;
+}
+
+static void sxe2_stats_update(struct sxe2_adapter *adapter)
+{
+ struct sxe2_vsi *vsi = adapter->vsi_ctxt.main_vsi;
+ struct sxe2_stats *stats = &vsi->vsi_stats.stats;
+ struct sxe2_stats *hw_stats = &vsi->vsi_stats.vsi_hw_stats;
+ struct sxe2_stats *sw_stats = &vsi->vsi_stats.vsi_sw_stats;
+ struct sxe2_stats *sw_stats_prev = &vsi->vsi_stats.vsi_sw_stats_prev;
+ uint8_t i = 0;
+
+ memset(stats, 0, sizeof(struct sxe2_stats));
+
+ stats->opackets = hw_stats->opackets;
+ stats->obytes = hw_stats->tx_vsi_bytes;
+ stats->tx_vsi_bytes = hw_stats->tx_vsi_bytes;
+ stats->tx_vsi_unicast_packets = hw_stats->tx_vsi_unicast_packets;
+ stats->tx_vsi_broadcast_packets = hw_stats->tx_vsi_broadcast_packets;
+ stats->tx_vsi_multicast_packets = hw_stats->tx_vsi_multicast_packets;
+
+ stats->ierrors = sw_stats->ierrors + sw_stats_prev->ierrors;
+ if (adapter->devargs.sw_stats_en) {
+ stats->ipackets = sw_stats->ipackets + sw_stats_prev->ipackets;
+ stats->ibytes = sw_stats->ibytes + sw_stats_prev->ibytes;
+ } else {
+ stats->ipackets = hw_stats->ipackets;
+ stats->ibytes = hw_stats->rx_vsi_bytes;
+ }
+ stats->rx_vsi_bytes = hw_stats->rx_vsi_bytes;
+ stats->rx_vsi_unicast_packets = hw_stats->rx_vsi_unicast_packets;
+ stats->rx_vsi_broadcast_packets = hw_stats->rx_vsi_broadcast_packets;
+ stats->rx_vsi_multicast_packets = hw_stats->rx_vsi_multicast_packets;
+ stats->rx_sw_unicast_packets = sw_stats->rx_sw_unicast_packets +
+ sw_stats_prev->rx_sw_unicast_packets;
+ stats->rx_sw_broadcast_packets = sw_stats->rx_sw_broadcast_packets +
+ sw_stats_prev->rx_sw_broadcast_packets;
+ stats->rx_sw_multicast_packets = sw_stats->rx_sw_multicast_packets +
+ sw_stats_prev->rx_sw_multicast_packets;
+ stats->rx_sw_drop_packets = sw_stats->rx_sw_drop_packets +
+ sw_stats_prev->rx_sw_drop_packets;
+ stats->rx_sw_drop_bytes = sw_stats->rx_sw_drop_bytes +
+ sw_stats_prev->rx_sw_drop_bytes;
+
+ if (adapter->dev_type != SXE2_DEV_T_VF) {
+ stats->rx_out_of_buffer = hw_stats->rx_out_of_buffer;
+ stats->rx_qblock_drop = hw_stats->rx_qblock_drop;
+ stats->tx_frame_good = hw_stats->tx_frame_good;
+ stats->rx_frame_good = hw_stats->rx_frame_good;
+ stats->rx_crc_errors = hw_stats->rx_crc_errors;
+ stats->tx_bytes_good = hw_stats->tx_bytes_good;
+ stats->rx_bytes_good = hw_stats->rx_bytes_good;
+ stats->tx_multicast_good = hw_stats->tx_multicast_good;
+ stats->tx_broadcast_good = hw_stats->tx_broadcast_good;
+ stats->rx_multicast_good = hw_stats->rx_multicast_good;
+ stats->rx_broadcast_good = hw_stats->rx_broadcast_good;
+ stats->rx_len_errors = hw_stats->rx_len_errors;
+ stats->rx_out_of_range_errors = hw_stats->rx_out_of_range_errors;
+ stats->rx_oversize_pkts_phy = hw_stats->rx_oversize_pkts_phy;
+ stats->rx_symbol_err = hw_stats->rx_symbol_err;
+ stats->rx_pause_frame = hw_stats->rx_pause_frame;
+ stats->tx_pause_frame = hw_stats->tx_pause_frame;
+ stats->rx_discards_phy = hw_stats->rx_discards_phy;
+ stats->rx_discards_ips_phy = hw_stats->rx_discards_ips_phy;
+ stats->tx_dropped_link_down = hw_stats->tx_dropped_link_down;
+ stats->rx_undersize_good = hw_stats->rx_undersize_good;
+ stats->rx_runt_error = hw_stats->rx_runt_error;
+ stats->tx_bytes_good_bad = hw_stats->tx_bytes_good_bad;
+ stats->tx_frame_good_bad = hw_stats->tx_frame_good_bad;
+ stats->rx_jabbers = hw_stats->rx_jabbers;
+ stats->rx_size_64 = hw_stats->rx_size_64;
+ stats->rx_size_65_127 = hw_stats->rx_size_65_127;
+ stats->rx_size_128_255 = hw_stats->rx_size_128_255;
+ stats->rx_size_256_511 = hw_stats->rx_size_256_511;
+ stats->rx_size_512_1023 = hw_stats->rx_size_512_1023;
+ stats->rx_size_1024_1522 = hw_stats->rx_size_1024_1522;
+ stats->rx_size_1523_max = hw_stats->rx_size_1523_max;
+ stats->rx_pcs_symbol_err_phy = hw_stats->rx_pcs_symbol_err_phy;
+ stats->rx_corrected_bits_phy = hw_stats->rx_corrected_bits_phy;
+ stats->rx_err_lane_0_phy = hw_stats->rx_err_lane_0_phy;
+ stats->rx_err_lane_1_phy = hw_stats->rx_err_lane_1_phy;
+ stats->rx_err_lane_2_phy = hw_stats->rx_err_lane_2_phy;
+ stats->rx_err_lane_3_phy = hw_stats->rx_err_lane_3_phy;
+ stats->rx_illegal_bytes = hw_stats->rx_illegal_bytes;
+ stats->rx_oversize_good = hw_stats->rx_oversize_good;
+ stats->tx_unicast = hw_stats->tx_unicast;
+ stats->tx_broadcast = hw_stats->tx_broadcast;
+ stats->tx_multicast = hw_stats->tx_multicast;
+ stats->tx_vlan_packet_good = hw_stats->tx_vlan_packet_good;
+ stats->tx_size_64 = hw_stats->tx_size_64;
+ stats->tx_size_65_127 = hw_stats->tx_size_65_127;
+ stats->tx_size_128_255 = hw_stats->tx_size_128_255;
+ stats->tx_size_256_511 = hw_stats->tx_size_256_511;
+ stats->tx_size_512_1023 = hw_stats->tx_size_512_1023;
+ stats->tx_size_1024_1522 = hw_stats->tx_size_1024_1522;
+ stats->tx_size_1523_max = hw_stats->tx_size_1523_max;
+ stats->tx_underflow_error = hw_stats->tx_underflow_error;
+ stats->rx_byte_good_bad = hw_stats->rx_byte_good_bad;
+ stats->rx_frame_good_bad = hw_stats->rx_frame_good_bad;
+ stats->rx_unicast_good = hw_stats->rx_unicast_good;
+ stats->rx_vlan_packets = hw_stats->rx_vlan_packets;
+ rte_memcpy(stats->rx_prio_buf_discard, hw_stats->rx_prio_buf_discard,
+ sizeof(hw_stats->rx_prio_buf_discard));
+ rte_memcpy(stats->prio_xoff_rx, hw_stats->prio_xoff_rx,
+ sizeof(hw_stats->prio_xoff_rx));
+ rte_memcpy(stats->prio_xon_rx, hw_stats->prio_xon_rx,
+ sizeof(hw_stats->prio_xon_rx));
+ rte_memcpy(stats->prio_xon_tx, hw_stats->prio_xon_tx,
+ sizeof(hw_stats->prio_xon_tx));
+ rte_memcpy(stats->prio_xoff_tx, hw_stats->prio_xoff_tx,
+ sizeof(hw_stats->prio_xoff_tx));
+ rte_memcpy(stats->prio_xon_2_xoff, hw_stats->prio_xon_2_xoff,
+ sizeof(hw_stats->prio_xon_2_xoff));
+
+ stats->imissed = hw_stats->rx_out_of_buffer +
+ hw_stats->rx_qblock_drop;
+ for (i = 0; i < SXE2_MAX_USER_PRIORITY; i++)
+ stats->imissed += hw_stats->rx_prio_buf_discard[i];
+ }
+}
+
+int32_t sxe2_stats_info_get(struct rte_eth_dev *dev,
+ struct rte_eth_stats *stats,
+ struct eth_queue_stats *qstats)
+{
+ int32_t ret = 0;
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_vsi *vsi = adapter->vsi_ctxt.main_vsi;
+ struct sxe2_stats *stats_out = &vsi->vsi_stats.stats;
+
+ if (rte_eal_process_type() == RTE_PROC_SECONDARY)
+ return sxe2_mp_req_get_stats(dev, stats, qstats);
+
+ ret = sxe2_vsi_hw_stats_get_update(adapter);
+ if (ret)
+ goto end;
+
+ ret = sxe2_vsi_sw_stats_get_update(adapter);
+ if (ret)
+ goto end;
+
+ ret = sxe2_drv_queue_info_get_update(adapter, qstats);
+ if (ret)
+ goto end;
+
+ sxe2_stats_update(adapter);
+
+ stats->ipackets = stats_out->ipackets;
+ stats->ibytes = stats_out->ibytes;
+ stats->ierrors = stats_out->ierrors;
+ stats->imissed = stats_out->imissed;
+ stats->rx_nombuf = dev->data->rx_mbuf_alloc_failed;
+
+ stats->opackets = stats_out->opackets;
+ stats->obytes = stats_out->obytes;
+
+ ret = 0;
+
+end:
+ return ret;
+}
+
+int32_t sxe2_xstats_info_get(struct rte_eth_dev *dev,
+ struct rte_eth_xstat *xstats, uint32_t usr_cnt)
+{
+ uint32_t i = 0;
+ uint32_t cnt = 0;
+ int32_t ret = 0;
+ uint32_t offset = 0;
+ uint32_t xstats_cnt = 0;
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_vsi *vsi = adapter->vsi_ctxt.main_vsi;
+ struct sxe2_vsi_stats *xstats_out = &vsi->vsi_stats;
+
+ if (rte_eal_process_type() == RTE_PROC_SECONDARY)
+ return sxe2_mp_req_get_xstats(dev, xstats, usr_cnt);
+
+ if (adapter->dev_type == SXE2_DEV_T_VF)
+ xstats_cnt = SXE2_XSTAT_CNT_VF;
+ else
+ xstats_cnt = SXE2_XSTAT_CNT_PF;
+
+ if (usr_cnt < xstats_cnt) {
+ ret = xstats_cnt;
+ PMD_LOG_ERR(DRV, "user usr_cnt:%u less than stats cnt:%u", usr_cnt, ret);
+ goto end;
+ }
+
+ ret = sxe2_vsi_hw_stats_get_update(adapter);
+ if (ret) {
+ ret = xstats_cnt;
+ goto end;
+ }
+
+ ret = sxe2_vsi_sw_stats_get_update(adapter);
+ if (ret) {
+ ret = xstats_cnt;
+ goto end;
+ }
+
+ if (adapter->dev_type == SXE2_DEV_T_VF) {
+ sxe2_stats_update(adapter);
+ for (i = 0; i < xstats_cnt; i++) {
+ (void)sxe2_xstat_vf_offset_get(i, &offset);
+ xstats[cnt].value = *(uint64_t *)(((int8_t *)(&xstats_out->stats)) +
+ offset);
+ xstats[cnt].id = cnt;
+ cnt++;
+ }
+ } else {
+ ret = sxe2_mac_hw_stats_get_update(adapter);
+ if (ret) {
+ ret = xstats_cnt;
+ goto end;
+ }
+
+ sxe2_stats_update(adapter);
+
+ for (i = 0; i < xstats_cnt; i++) {
+ (void)sxe2_xstat_pf_offset_get(i, &offset);
+ xstats[cnt].value = *(uint64_t *)(((int8_t *)(&xstats_out->stats)) +
+ offset);
+ xstats[cnt].id = cnt;
+ cnt++;
+ }
+ }
+ ret = cnt;
+ PMD_LOG_DEBUG(DRV, "usr_cnt:%u stats cnt:%u stats done", usr_cnt, cnt);
+
+end:
+ return ret;
+}
+
+int32_t sxe2_xstats_names_get(__rte_unused struct rte_eth_dev *dev,
+ struct rte_eth_xstat_name *xstats_names,
+ __rte_unused unsigned int usr_cnt)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_stats_field *field = NULL;
+ uint32_t i = 0;
+ uint32_t cnt = 0;
+ int32_t ret = -1;
+ uint32_t xstats_cnt = 0;
+
+ if (adapter->dev_type == SXE2_DEV_T_VF) {
+ field = sxe2_xstats_field_vf;
+ xstats_cnt = SXE2_XSTAT_CNT_VF;
+ } else {
+ field = sxe2_xstats_field_pf;
+ xstats_cnt = SXE2_XSTAT_CNT_PF;
+ }
+
+ if (!xstats_names) {
+ ret = xstats_cnt;
+ PMD_LOG_DEBUG(DRV, "xstats field size:%u", ret);
+ goto l_out;
+ }
+
+ if (usr_cnt < xstats_cnt) {
+ ret = -EINVAL;
+ PMD_LOG_ERR(DRV, "max:%d usr_cnt:%u invalid (err:%d)", xstats_cnt, usr_cnt, ret);
+ goto l_out;
+ }
+
+ for (i = 0; i < xstats_cnt; i++) {
+ (void)strlcpy(xstats_names[cnt].name, field[i].name,
+ sizeof(xstats_names[cnt].name));
+ cnt++;
+ }
+
+ ret = cnt;
+
+l_out:
+ return ret;
+}
+
+int32_t sxe2_stats_hw_reset(struct rte_eth_dev *dev)
+{
+ int32_t ret = 0;
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_vsi *vsi = adapter->vsi_ctxt.main_vsi;
+ struct sxe2_rx_queue *rxq;
+ uint32_t rx_queue_id;
+
+ ret = sxe2_drv_vsi_stats_reset(adapter);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "reset vsi stats failed, ret:%d.", ret);
+ goto l_end;
+ }
+ if (adapter->dev_type != SXE2_DEV_T_VF) {
+ ret = sxe2_drv_mac_stats_reset(adapter);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "reset mac stats failed, ret:%d.", ret);
+ goto l_end;
+ }
+ }
+
+ memset(&vsi->vsi_stats, 0, sizeof(vsi->vsi_stats));
+ for (rx_queue_id = 0; rx_queue_id < dev->data->nb_rx_queues; rx_queue_id++) {
+ rxq = dev->data->rx_queues[rx_queue_id];
+ if (rxq)
+ memset(&rxq->sw_stats, 0, sizeof(rxq->sw_stats));
+ }
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_stats_info_reset(struct rte_eth_dev *dev)
+{
+ int32_t ret;
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+
+ if (rte_eal_process_type() == RTE_PROC_SECONDARY)
+ return sxe2_mp_req_reset_stats(dev);
+
+ if (adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_Q_MAP) {
+ ret = sxe2_drv_mapping_stats_info_clear(dev);
+ if (ret)
+ goto l_end;
+ }
+
+ ret = sxe2_stats_hw_reset(dev);
+ if (ret)
+ goto l_end;
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_stats_init(struct rte_eth_dev *dev)
+{
+ PMD_INIT_FUNC_TRACE();
+ int32_t ret;
+
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+ return 0;
+
+ ret = sxe2_queue_stats_map_init(dev);
+ if (ret)
+ goto l_end;
+
+ ret = sxe2_stats_hw_reset(dev);
+ if (ret)
+ goto l_end;
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_queue_stats_mapping_set(struct rte_eth_dev *eth_dev,
+ uint16_t queue_id, uint8_t pool_idx, uint8_t is_rx)
+{
+ int32_t ret = -1;
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(eth_dev);
+
+ if (!(adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_Q_MAP)) {
+ PMD_LOG_ERR(DRV, "VF does not support queue mapping! ");
+ goto l_end;
+ }
+
+ if (is_rx)
+ ret = sxe2_drv_rxq_mapping_set(eth_dev, queue_id, pool_idx);
+ else
+ ret = sxe2_drv_txq_mapping_set(eth_dev, queue_id, pool_idx);
+
+ if (ret) {
+ PMD_LOG_ERR(DRV, "Queue stats mapping failed ! "
+ "queue_id:%u pool_idx:%u", queue_id, pool_idx);
+ goto l_end;
+ }
+
+ PMD_LOG_DEBUG(DRV, "port %u %s queue_id %d stat map to pool[%u] ",
+ (uint16_t)(eth_dev->data->port_id), is_rx ? "RX" : "TX",
+ queue_id, pool_idx);
+l_end:
+ return ret;
+}
+
+int32_t sxe2_queue_stats_map_init(struct rte_eth_dev *dev)
+{
+ int32_t ret = 0;
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+
+ if (adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_Q_MAP) {
+ dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
+
+ ret = sxe2_drv_mapping_reset(dev);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "Queue stats mapping init failed !");
+ goto l_end;
+ }
+ }
+
+l_end:
+ return ret;
+}
diff --git a/drivers/net/sxe2/sxe2_stats.h b/drivers/net/sxe2/sxe2_stats.h
new file mode 100644
index 0000000000..64ac2bb11d
--- /dev/null
+++ b/drivers/net/sxe2/sxe2_stats.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#ifndef __SXE2_STATS_H__
+#define __SXE2_STATS_H__
+
+#define SXE2_STATS_FIELD_NAME_SIZE 50
+
+struct sxe2_stats_field {
+ char name[SXE2_STATS_FIELD_NAME_SIZE];
+ uint32_t offset;
+};
+
+struct sxe2_adapter;
+
+int32_t sxe2_stats_info_get(struct rte_eth_dev *dev,
+ struct rte_eth_stats *stats,
+ struct eth_queue_stats *qstats);
+
+int32_t sxe2_xstats_info_get(struct rte_eth_dev *dev,
+ struct rte_eth_xstat *xstats, uint32_t usr_cnt);
+
+int32_t sxe2_xstats_names_get(__rte_unused struct rte_eth_dev *dev,
+ struct rte_eth_xstat_name *xstats_names,
+ __rte_unused unsigned int usr_cnt);
+
+int32_t sxe2_stats_hw_reset(struct rte_eth_dev *dev);
+
+int32_t sxe2_stats_info_reset(struct rte_eth_dev *dev);
+
+int32_t sxe2_stats_init(struct rte_eth_dev *dev);
+
+int32_t sxe2_queue_stats_mapping_set(struct rte_eth_dev *eth_dev,
+ uint16_t queue_id, uint8_t pool_idx, uint8_t is_rx);
+
+int32_t sxe2_queue_stats_map_init(struct rte_eth_dev *dev);
+
+#endif
--
2.52.0
^ permalink raw reply related
* [PATCH v2 03/20] drivers: add supported packet types get callback
From: liujie5 @ 2026-06-14 9:23 UTC (permalink / raw)
To: stephen; +Cc: dev, Jie Liu
In-Reply-To: <20260614092328.201826-1-liujie5@linkdatatechnology.com>
From: Jie Liu <liujie5@linkdatatechnology.com>
Implement dev_supported_ptypes_get ethdev callback for sxe2 PMD.
This allows applications to query the packet types the driver
is capable of identifying, such as L2, L3 (IPv4/IPv6), and
L4 (TCP/UDP/SCTP) layers.
Signed-off-by: Jie Liu <liujie5@linkdatatechnology.com>
---
drivers/common/sxe2/sxe2_ptype.h | 1793 ++++++++++++++++++++++++++++++
drivers/net/sxe2/meson.build | 1 +
drivers/net/sxe2/sxe2_cmd_chnl.c | 22 +
drivers/net/sxe2/sxe2_cmd_chnl.h | 2 +
drivers/net/sxe2/sxe2_drv_cmd.h | 6 +
drivers/net/sxe2/sxe2_ethdev.c | 169 ++-
drivers/net/sxe2/sxe2_ethdev.h | 19 +-
drivers/net/sxe2/sxe2_mac.c | 103 ++
drivers/net/sxe2/sxe2_mac.h | 50 +
9 files changed, 2126 insertions(+), 39 deletions(-)
create mode 100644 drivers/common/sxe2/sxe2_ptype.h
create mode 100644 drivers/net/sxe2/sxe2_mac.c
create mode 100644 drivers/net/sxe2/sxe2_mac.h
diff --git a/drivers/common/sxe2/sxe2_ptype.h b/drivers/common/sxe2/sxe2_ptype.h
new file mode 100644
index 0000000000..9c19570979
--- /dev/null
+++ b/drivers/common/sxe2/sxe2_ptype.h
@@ -0,0 +1,1793 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#ifndef _SXE2_PTYPE_H_
+#define _SXE2_PTYPE_H_
+#include <rte_ethdev.h>
+
+static inline const uint32_t *
+sxe2_dev_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements)
+{
+ const uint32_t *ret = NULL;
+
+ static const uint32_t ptypes[] = {
+ RTE_PTYPE_L2_ETHER,
+ RTE_PTYPE_L2_ETHER_TIMESYNC,
+ RTE_PTYPE_L2_ETHER_LLDP,
+ RTE_PTYPE_L2_ETHER_ARP,
+ RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
+ RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
+ RTE_PTYPE_L4_FRAG,
+ RTE_PTYPE_L4_ICMP,
+ RTE_PTYPE_L4_NONFRAG,
+ RTE_PTYPE_L4_SCTP,
+ RTE_PTYPE_L4_TCP,
+ RTE_PTYPE_L4_UDP,
+ RTE_PTYPE_TUNNEL_GRENAT,
+ RTE_PTYPE_TUNNEL_IP,
+ RTE_PTYPE_INNER_L2_ETHER,
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN,
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN,
+ RTE_PTYPE_INNER_L4_FRAG,
+ RTE_PTYPE_INNER_L4_ICMP,
+ RTE_PTYPE_INNER_L4_NONFRAG,
+ RTE_PTYPE_INNER_L4_SCTP,
+ RTE_PTYPE_INNER_L4_TCP,
+ RTE_PTYPE_INNER_L4_UDP,
+ RTE_PTYPE_UNKNOWN
+ };
+
+ if (dev->rx_pkt_burst != NULL) {
+ *no_of_elements = RTE_DIM(ptypes);
+ ret = ptypes;
+ } else {
+ ret = NULL;
+ }
+
+ return ret;
+}
+
+static inline void sxe2_init_ptype_list(uint32_t *ptype)
+{
+ /* ptype[0] reserved */
+ ptype[1] = RTE_PTYPE_L2_ETHER;
+ ptype[2] = RTE_PTYPE_L2_ETHER_TIMESYNC;
+ /* ptype[3] - ptype[5] reserved */
+ ptype[6] = RTE_PTYPE_L2_ETHER_LLDP;
+ /* ECP */
+ ptype[7] = RTE_PTYPE_UNKNOWN;
+ /* ptype[8] - ptype[9] reserved */
+ /* EAPol */
+ ptype[10] = RTE_PTYPE_UNKNOWN;
+ ptype[11] = RTE_PTYPE_L2_ETHER_ARP;
+ /* ptype[12] - ptype[21] reserved */
+
+ /* Non tunneled IPv4 */
+ ptype[22] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_FRAG;
+ ptype[23] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ ptype[24] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP;
+ /* ptype[25] reserved */
+ ptype[26] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_TCP;
+ ptype[27] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_SCTP;
+ ptype[28] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_ICMP;
+
+ /* IPv4 --> IPv4 */
+ ptype[29] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[30] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[31] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ /* ptype[32] reserved */
+ ptype[33] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[34] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[35] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv4 --> IPv6 */
+ ptype[36] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[37] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[38] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ /* ptype[39] reserved */
+ ptype[40] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[41] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[42] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv4 --> GRE/GENEVE/VXLAN */
+ ptype[43] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT;
+
+ /* IPv4 --> GRE/GENEVE/VXLAN --> IPv4 */
+ ptype[44] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[45] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[46] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ /* ptype[47] reserved */
+ ptype[48] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[49] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[50] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv4 --> GRE/GENEVE/VXLAN --> IPv6 */
+ ptype[51] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[52] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[53] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ /* ptype[54] reserved */
+ ptype[55] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[56] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[57] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv4 --> GRE/GENEVE/VXLAN --> MAC */
+ ptype[58] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER;
+
+ /* IPv4 --> GRE/GENEVE/VXLAN --> MAC --> IPv4 */
+ ptype[59] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[60] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[61] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ /* ptype[62] reserved */
+ ptype[63] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[64] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[65] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv4 --> GRE/GENEVE/VXLAN --> MAC --> IPv6 */
+ ptype[66] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[67] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[68] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ /* ptype[69] reserved */
+ ptype[70] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[71] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[72] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+ /* IPv4 --> GRE/GENEVE/VXLAN --> MAC/VLAN */
+ ptype[73] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN;
+ /* IPv4 --> GRE/GENEVE/VXLAN --> MAC/VLAN --> IPv4 */
+ ptype[74] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[75] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[76] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_UDP;
+ /* ptype[77] reserved */
+ ptype[78] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_TCP;
+ ptype[79] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_SCTP;
+ ptype[80] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_ICMP;
+ /* IPv4 --> GRE/GENEVE/VXLAN --> MAC/VLAN --> IPv6 */
+ ptype[81] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_FRAG;
+ ptype[82] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[83] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_UDP;
+ /* ptype[64] reserved */
+ ptype[85] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_TCP;
+ ptype[86] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_SCTP;
+ ptype[87] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_ICMP;
+ /* Non tunneled IPv6 */
+ ptype[88] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_FRAG;
+ ptype[89] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ ptype[90] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP;
+ /* ptype[91] reserved */
+ ptype[92] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_TCP;
+ ptype[93] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_SCTP;
+ ptype[94] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_ICMP;
+
+ /* IPv6 --> IPv4 */
+ ptype[95] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[96] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[97] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ /* ptype[98] reserved */
+ ptype[99] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[100] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[101] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv6 --> IPv6 */
+ ptype[102] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[103] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[104] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ /* ptype[105] reserved */
+ ptype[106] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[107] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[108] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv6 --> GRE/GENEVE/VXLAN */
+ ptype[109] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT;
+
+ /* IPv6 --> GRE/GENEVE/VXLAN --> IPv4 */
+ ptype[110] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[111] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[112] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ /* ptype[113] reserved */
+ ptype[114] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[115] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[116] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv6 --> GRE/GENEVE/VXLAN --> IPv6 */
+ ptype[117] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[118] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[119] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ /* ptype[120] reserved */
+ ptype[121] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[122] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[123] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv6 --> GRE/GENEVE/VXLAN --> MAC */
+ ptype[124] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER;
+
+ /* IPv6 --> GRE/GENEVE/VXLAN --> MAC --> IPv4 */
+ ptype[125] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[126] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[127] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ /* ptype[128] reserved */
+ ptype[129] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[130] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[131] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv6 --> GRE/GENEVE/VXLAN --> MAC --> IPv6 */
+ ptype[132] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[133] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[134] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ /* ptype[135] reserved */
+ ptype[136] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[137] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[138] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv6 --> GRE/GENEVE/VXLAN --> MAC/VLAN */
+ ptype[139] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN;
+
+ /* IPv6 --> GRE/GENEVE/VXLAN --> MAC/VLAN --> IPv4 */
+ ptype[140] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[141] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[142] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_UDP;
+ /* ptype[143] reserved */
+ ptype[144] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_TCP;
+ ptype[145] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_SCTP;
+ ptype[146] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv6 --> GRE/GENEVE/VXLAN --> MAC/VLAN --> IPv6 */
+ ptype[147] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[148] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[149] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_UDP;
+ /* ptype[150] reserved */
+ ptype[151] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_TCP;
+ ptype[152] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_SCTP;
+ ptype[153] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_ICMP;
+ /* ptype[154] - ptype[159] reserved */
+ /* IPSec */
+ ptype[160] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_ESP;
+ ptype[161] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_ESP;
+ /* AH */
+ ptype[162] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ ptype[163] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ /* NAT-T-ESP */
+ ptype[164] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_ESP;
+ ptype[165] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_ESP;
+ /* SDN-ESP */
+ ptype[166] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_ESP;
+ ptype[167] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_ESP;
+ /* ptype[168] - ptype[271] reserved */
+ /* IPV4 --> VRRP */
+ ptype[272] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ /* IPV4 --> OSPF */
+ ptype[273] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ /* IPV6 --> VRRP */
+ ptype[274] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ /* IPV6 --> VRRP */
+ ptype[275] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ /* ATAoE */
+ ptype[276] = RTE_PTYPE_UNKNOWN;
+ /* Control */
+ ptype[278] = RTE_PTYPE_UNKNOWN;
+ /* ptype[279] - ptype[324] reserved */
+ /* GTP */
+ ptype[325] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPC;
+ ptype[326] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPC;
+ ptype[327] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPC;
+ ptype[328] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPC;
+ ptype[329] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPU;
+ ptype[330] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPU;
+ ptype[331] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPU |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[332] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPU |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[333] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPU |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[334] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPU |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[335] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPU |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+ ptype[336] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPU |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[337] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPU |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[338] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPU |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[339] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPU |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[340] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPU |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+ ptype[341] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPU |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[342] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPU |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[343] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPU |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[344] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPU |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[345] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPU |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+ ptype[346] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPU |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[347] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPU |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[348] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPU |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[349] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPU |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[350] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPU |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+ /* PFCP */
+ ptype[351] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP;
+ ptype[352] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP;
+ ptype[353] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP;
+ ptype[354] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP;
+ /* ptype[355] - ptype[359] reserved */
+ /* L2TPv3 */
+ ptype[360] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_L2TP;
+ ptype[361] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_L2TP;
+ /* ptype[362] - ptype[370] reserved */
+ /* eCPRI */
+ ptype[371] = RTE_PTYPE_UNKNOWN;
+ ptype[381] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP;
+ ptype[391] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP;
+ ptype[396] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv6, UDP, TUN, MAC, IPv4, IGMP */
+ ptype[397] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv4, UDP, TUN, MAC, IPv4, EIGRP */
+ ptype[398] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv6, UDP, TUN, MAC, IPv4, EIGRP */
+ ptype[399] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv4, UDP, TUN, MAC, IPv4, PIM */
+ ptype[400] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv6, UDP, TUN, MAC, IPv4, PIM */
+ ptype[401] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv4, UDP, TUN, MAC, IPv6, IGMP */
+ ptype[402] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv6, UDP, TUN, MAC, IPv6, IGMP */
+ ptype[403] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv4, UDP, TUN, MAC, IPv6, EIGRP */
+ ptype[404] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv6, UDP, TUN, MAC, IPv6, EIGRP */
+ ptype[405] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv4, UDP, TUN, MAC, IPv6, PIM */
+ ptype[406] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv6, UDP, TUN, MAC, IPv6, PIM */
+ ptype[407] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv4, UDP, TUN, MAC, IPv4, VRRP */
+ ptype[408] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv6, UDP, TUN, MAC, IPv4, VRRP */
+ ptype[409] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv4, UDP, TUN, MAC, IPv6, VRRP */
+ ptype[410] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv6, UDP, TUN, MAC, IPv6, VRRP */
+ ptype[411] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv4, UDP, TUN, MAC, IPv4, OSPF */
+ ptype[412] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv6, UDP, TUN, MAC, IPv4, OSPF */
+ ptype[413] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv4, UDP, TUN, MAC, IPv6, OSPF */
+ ptype[414] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv6, UDP, TUN, MAC, IPv6, OSPF */
+ ptype[415] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv4, UDP, TUN, MAC, IPv4, L2_TP_V3 */
+ ptype[416] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv6, UDP, TUN, MAC, IPv4, L2_TP_V3 */
+ ptype[417] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv4, UDP, TUN, MAC, IPv6, L2_TP_V3 */
+ ptype[418] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv6, UDP, TUN, MAC, IPv6, L2_TP_V3 */
+ ptype[419] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv4, UDP, TUN, MAC, IPv4, AH */
+ ptype[420] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv6, UDP, TUN, MAC, IPv4, AH */
+ ptype[421] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv4, UDP, TUN, MAC, IPv6, AH */
+ ptype[422] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv6, UDP, TUN, MAC, IPv6, AH */
+ ptype[423] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv4, UDP, TUN, MAC, IPv4, ESP */
+ ptype[424] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv6, UDP, TUN, MAC, IPv4, ESP */
+ ptype[425] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv4, UDP, TUN, MAC, IPv6, ESP */
+ ptype[426] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* MAC, IPv6, UDP, TUN, MAC, IPv6, ESP */
+ ptype[427] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ /* TP-TUN GTPU */
+ ptype[450] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[451] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[452] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[453] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[454] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[455] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[456] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[457] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[458] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[459] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[460] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[461] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[462] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[463] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[464] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[465] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[466] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[467] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[468] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[469] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[470] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[471] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[472] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[473] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[474] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[475] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[476] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[477] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[478] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[479] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[480] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[481] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[482] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[483] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[484] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[485] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[486] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[487] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[488] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[489] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[490] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[491] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[492] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[493] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[494] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[495] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[496] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[497] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ /* ptype[498] - ptype[767] reserved */
+ /* L2(NETWORK CPU) */
+ /* ISIS */
+ ptype[768] = RTE_PTYPE_UNKNOWN;
+ /* SDF */
+ ptype[769] = RTE_PTYPE_UNKNOWN;
+ /* PPoE_NEGO */
+ ptype[770] = RTE_PTYPE_L2_ETHER_PPPOE;
+ /* PPoE_PROTOCOL */
+ ptype[771] = RTE_PTYPE_L2_ETHER_PPPOE;
+ ptype[772] = RTE_PTYPE_L2_ETHER_PPPOE;
+ /* LACP */
+ ptype[773] = RTE_PTYPE_UNKNOWN;
+ /* ptype[774] - ptype[775] reserved */
+ /* IPv4 L3(NETWORK CPU) */
+ ptype[776] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_IGMP;
+ /* EIGRP */
+ ptype[777] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ /* PIM */
+ ptype[778] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ ptype[779] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_L2TP;
+ ptype[780] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_L2TP;
+ ptype[781] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_L2TP;
+ /* ptype[782] - ptype[783] reserved */
+ /* IPv6 L3(NETWORK CPU) */
+ ptype[784] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_IGMP;
+ /* EIGRP */
+ ptype[785] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ /* PIM */
+ ptype[786] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ ptype[787] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_L2TP;
+ ptype[788] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_L2TP;
+ ptype[789] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_L2TP;
+ /* ptype[790] - ptype[791] reserved */
+ /* IPv4 L4(NETWORK CPU) */
+ ptype[792] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_TCP;
+ ptype[793] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_TCP;
+ ptype[794] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP;
+ ptype[795] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP;
+ ptype[796] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP;
+ ptype[797] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP;
+ ptype[798] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP;
+ ptype[799] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP;
+ ptype[800] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP;
+ ptype[801] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP;
+ /* ptype[802] - ptype[807] reserved */
+ /* IPv6 L4(NETWORK CPU) */
+ ptype[808] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_TCP;
+ ptype[809] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_TCP;
+ ptype[810] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP;
+ ptype[811] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP;
+ ptype[812] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP;
+ ptype[813] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP;
+ ptype[814] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP;
+ ptype[815] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP;
+ ptype[816] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP;
+ ptype[817] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_UDP;
+ /* ptype[818] - ptype[819] reserved */
+ /* IPv6 -> MAC */
+ ptype[820] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ /* IPv6 -> MAC -> IPv4*/
+ ptype[821] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ ptype[822] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ ptype[823] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ ptype[824] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ ptype[825] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ ptype[826] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ /* IPv6 -> MAC -> IPv4*/
+ ptype[827] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ ptype[828] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ ptype[829] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ ptype[830] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ ptype[831] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ ptype[832] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ /* ptype[833] - ptype[834] reserved */
+ /* IPv6 -> MAC/VLAN */
+ ptype[835] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ /* IPv6 -> MAC/VLAN -> IPv4 */
+ ptype[836] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ ptype[837] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ ptype[838] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ ptype[839] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ ptype[840] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ ptype[841] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ /* IPv6 -> MAC/VLAN -> IPv6 */
+ ptype[842] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ ptype[843] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ ptype[844] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ ptype[845] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ ptype[846] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+ ptype[847] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_L4_NONFRAG;
+
+ /* IPv6 -> UDP -> VXLAN/GENEVE -> PAY */
+ ptype[878] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT;
+
+ /* IPv6 -> UDP -> VXLAN/GENEVE -> IPv4 */
+ ptype[877] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[876] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[879] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[880] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[875] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[874] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv6 -> UDP -> VXLAN/GENEVE -> IPv6 */
+ ptype[871] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[870] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[872] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[873] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[869] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[868] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv4 -> UDP -> VXLAN/GENEVE -> PAY */
+ ptype[891] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT;
+ /* IPv4 -> UDP -> VXLAN/GENEVE -> IPv4 */
+ ptype[890] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[889] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[892] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[893] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[888] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[887] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+ /* IPv4 -> UDP -> VXLAN/GENEVE -> IPv6 */
+ ptype[884] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[883] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[885] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[886] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[882] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[881] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv6 -> UDP -> GRE -> PAY */
+ ptype[904] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT;
+ /* IPv6 -> UDP -> GRE -> IPv4 */
+ ptype[903] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[902] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[905] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[906] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[901] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[900] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+ /* IPv6 -> UDP -> GRE -> IPv6 */
+ ptype[897] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[896] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[898] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[899] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[895] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[894] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv4 -> UDP -> GRE -> PAY */
+ ptype[917] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT;
+ /* IPv4 -> UDP -> GRE -> IPv4 */
+ ptype[916] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[915] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[918] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[919] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[914] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[913] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+ /* IPv4 -> UDP -> GRE -> IPv6 */
+ ptype[910] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[909] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[911] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[912] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[908] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[907] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv6 -> UDP -> VXLAN/GENEVE -> MACVLAN -> PAY */
+ ptype[930] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN;
+
+ /* IPv6 -> UDP -> VXLAN/GENEVE -> MACVLAN -> IPv4 */
+ ptype[929] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[928] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[931] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[932] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[927] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[926] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv6 -> UDP -> VXLAN/GENEVE -> MACVLAN -> IPv6 */
+ ptype[923] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[922] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[924] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[925] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[921] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[920] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv4 -> UDP -> VXLAN/GENEVE -> MACVLAN -> PAY */
+ ptype[943] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN;
+ /* IPv4 -> UDP -> VXLAN/GENEVE -> MACVLAN -> IPv4 */
+ ptype[942] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[941] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[944] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[945] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[940] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[939] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+ /* IPv4 -> UDP -> VXLAN/GENEVE -> MACVLAN -> IPv6 */
+ ptype[936] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[935] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[937] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[938] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[934] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[933] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv6 > UDP -> GRE -> MACVLAN -> PAY */
+ ptype[956] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN;
+ /* IPv6 -> UDP -> GRE -> MACVLAN -> IPv4 */
+ ptype[955] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[954] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[957] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[958] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[953] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[952] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+ /* IPv6 -> UDP -> GRE -> MACVLAN -> IPv6 */
+ ptype[949] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[948] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[950] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[951] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[947] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[946] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv4 -> UDP -> GRE -> MACVLAN -> PAY */
+ ptype[969] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN;
+ /* IPv4 -> UDP -> GRE -> MACVLAN -> IPv4 */
+ ptype[968] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[967] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[970] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[971] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[966] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[965] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+ /* IPv4 -> UDP -> GRE -> MACVLAN -> IPv6 */
+ ptype[962] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[961] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[963] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[964] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[960] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[959] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv6 -> UDP -> VXLAN/GENEVE -> MAC -> PAY */
+ ptype[982] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER;
+
+ /* IPv6 -> UDP -> VXLAN/GENEVE -> MAC -> IPv4 */
+ ptype[981] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[980] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[983] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[984] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[979] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[978] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv6 -> UDP -> VXLAN/GENEVE -> MAC -> IPv6 */
+ ptype[975] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[974] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[976] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[977] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[973] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[972] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv4 -> UDP -> VXLAN/GENEVE -> MAC -> PAY */
+ ptype[995] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER;
+ /* IPv4 -> UDP -> VXLAN/GENEVE -> MAC -> IPv4 */
+ ptype[994] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[993] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[996] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[997] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[992] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[991] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+ /* IPv4 -> UDP -> VXLAN/GENEVE -> MAC -> IPv6 */
+ ptype[988] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[987] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[989] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[990] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[986] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[985] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv6 > UDP -> GRE -> MAC -> PAY */
+ ptype[1008] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER;
+ /* IPv6 -> UDP -> GRE -> MAC -> IPv4 */
+ ptype[1007] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[1006] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[1009] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[1010] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[1005] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[1004] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+ /* IPv6 -> UDP -> GRE -> MAC -> IPv6 */
+ ptype[1001] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[1000] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[1002] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[1003] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[999] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[998] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+
+ /* IPv4 -> UDP -> GRE -> MAC -> PAY */
+ ptype[1021] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER;
+ /* IPv4 -> UDP -> GRE -> MAC -> IPv4 */
+ ptype[1020] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[1019] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[1022] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[1023] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[1018] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[1017] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+ /* IPv4 -> UDP -> GRE -> MAC -> IPv6 */
+ ptype[1014] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_FRAG;
+ ptype[1013] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_NONFRAG;
+ ptype[1015] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_UDP;
+ ptype[1016] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_TCP;
+ ptype[1012] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_SCTP;
+ ptype[1011] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
+ RTE_PTYPE_INNER_L4_ICMP;
+}
+
+#endif /* _RTE_PTYPE_TUNNEL_GRENAT_H_ */
diff --git a/drivers/net/sxe2/meson.build b/drivers/net/sxe2/meson.build
index c225dd7cd8..b14b5120c1 100644
--- a/drivers/net/sxe2/meson.build
+++ b/drivers/net/sxe2/meson.build
@@ -60,4 +60,5 @@ sources += files(
'sxe2_txrx_poll.c',
'sxe2_txrx.c',
'sxe2_txrx_vec.c',
+ 'sxe2_mac.c',
)
diff --git a/drivers/net/sxe2/sxe2_cmd_chnl.c b/drivers/net/sxe2/sxe2_cmd_chnl.c
index d16b6528d0..07eeb7f38c 100644
--- a/drivers/net/sxe2/sxe2_cmd_chnl.c
+++ b/drivers/net/sxe2/sxe2_cmd_chnl.c
@@ -321,3 +321,25 @@ int32_t sxe2_drv_txq_switch(struct sxe2_adapter *adapter, struct sxe2_tx_queue *
return ret;
}
+
+int32_t sxe2_drv_mac_link_status_get(struct sxe2_adapter *adapter)
+{
+ int32_t ret = 0;
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_drv_link_info_resp resp = {0};
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_LINK_STATUS_GET,
+ NULL, 0,
+ &resp, sizeof(resp));
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "link status get failed, ret=%d", ret);
+ goto l_end;
+ }
+ adapter->link_ctxt.speed = resp.speed;
+ adapter->link_ctxt.link_up = resp.status;
+
+l_end:
+ return ret;
+}
diff --git a/drivers/net/sxe2/sxe2_cmd_chnl.h b/drivers/net/sxe2/sxe2_cmd_chnl.h
index ed5e842346..cda676ed97 100644
--- a/drivers/net/sxe2/sxe2_cmd_chnl.h
+++ b/drivers/net/sxe2/sxe2_cmd_chnl.h
@@ -34,4 +34,6 @@ int32_t sxe2_drv_txq_ctxt_cfg(struct sxe2_adapter *adapter,
struct sxe2_tx_queue *txq,
uint16_t txq_cnt);
+int32_t sxe2_drv_mac_link_status_get(struct sxe2_adapter *adapter);
+
#endif /* SXE2_CMD_CHNL_H */
diff --git a/drivers/net/sxe2/sxe2_drv_cmd.h b/drivers/net/sxe2/sxe2_drv_cmd.h
index ccc9c20ef4..a0f08b5184 100644
--- a/drivers/net/sxe2/sxe2_drv_cmd.h
+++ b/drivers/net/sxe2/sxe2_drv_cmd.h
@@ -227,6 +227,12 @@ struct __rte_aligned(4) __rte_packed_begin sxe2_drv_vsi_info_get_resp {
struct sxe2_drv_msix_caps used_msix;
} __rte_packed_end;
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_link_info_resp {
+ uint32_t speed;
+ uint8_t status;
+ uint8_t rsv[3];
+} __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 066e1faf7e..80881595d6 100644
--- a/drivers/net/sxe2/sxe2_ethdev.c
+++ b/drivers/net/sxe2/sxe2_ethdev.c
@@ -27,7 +27,9 @@
#include "sxe2_tx.h"
#include "sxe2_rx.h"
#include "sxe2_txrx.h"
+#include "sxe2_mac.h"
#include "sxe2_common.h"
+#include "sxe2_ptype.h"
#include "sxe2_common_log.h"
#include "sxe2_host_regs.h"
#include "sxe2_ioctl_chnl_func.h"
@@ -78,6 +80,41 @@ static struct sxe2_pci_map_addr_info sxe2_net_map_addr_info_pf[SXE2_PCI_MAP_RES_
.reg_width = 10},
};
+static int32_t sxe2_dev_configure(struct rte_eth_dev *dev);
+static int32_t sxe2_dev_start(struct rte_eth_dev *dev);
+static int32_t sxe2_dev_stop(struct rte_eth_dev *dev);
+static int32_t sxe2_dev_close(struct rte_eth_dev *dev);
+static int32_t sxe2_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info);
+static const uint32_t *sxe2_buffer_split_supported_hdr_ptypes_get(struct rte_eth_dev *dev
+ __rte_unused, size_t *no_of_elements __rte_unused);
+
+static const struct eth_dev_ops sxe2_eth_dev_ops = {
+ .dev_configure = sxe2_dev_configure,
+ .dev_start = sxe2_dev_start,
+ .dev_stop = sxe2_dev_stop,
+ .dev_close = sxe2_dev_close,
+ .dev_infos_get = sxe2_dev_infos_get,
+ .dev_supported_ptypes_get = sxe2_dev_supported_ptypes_get,
+ .link_update = sxe2_link_update,
+
+ .rx_queue_start = sxe2_rx_queue_start,
+ .rx_queue_stop = sxe2_rx_queue_stop,
+ .tx_queue_start = sxe2_tx_queue_start,
+ .tx_queue_stop = sxe2_tx_queue_stop,
+ .rx_queue_setup = sxe2_rx_queue_setup,
+ .rx_queue_release = sxe2_rx_queue_release,
+ .tx_queue_setup = sxe2_tx_queue_setup,
+ .tx_queue_release = sxe2_tx_queue_release,
+ .rxq_info_get = sxe2_rx_queue_info_get,
+ .txq_info_get = sxe2_tx_queue_info_get,
+ .rx_burst_mode_get = sxe2_rx_burst_mode_get,
+ .tx_burst_mode_get = sxe2_tx_burst_mode_get,
+ .tx_done_cleanup = sxe2_tx_done_cleanup,
+
+ .mtu_set = sxe2_mtu_set,
+ .buffer_split_supported_hdr_ptypes_get = sxe2_buffer_split_supported_hdr_ptypes_get,
+};
+
static int32_t sxe2_dev_configure(struct rte_eth_dev *dev)
{
int32_t ret = 0;
@@ -122,6 +159,12 @@ static int32_t sxe2_dev_start(struct rte_eth_dev *dev)
sxe2_rx_mode_func_set(dev);
sxe2_tx_mode_func_set(dev);
+ ret = sxe2_link_update_init(dev);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to initialize link update, ret:%d", ret);
+ goto l_end;
+ }
+
ret = sxe2_queues_start(dev);
if (ret) {
PMD_LOG_ERR(INIT, "enable queues failed");
@@ -136,16 +179,6 @@ static int32_t sxe2_dev_start(struct rte_eth_dev *dev)
return ret;
}
-static int32_t sxe2_dev_close(struct rte_eth_dev *dev)
-{
- (void)sxe2_dev_stop(dev);
- (void)sxe2_queues_release(dev);
- sxe2_vsi_uninit(dev);
- sxe2_dev_pci_map_uinit(dev);
-
- return 0;
-}
-
static int32_t sxe2_dev_infos_get(struct rte_eth_dev *dev,
struct rte_eth_dev_info *dev_info)
{
@@ -270,28 +303,59 @@ static int32_t sxe2_dev_infos_get(struct rte_eth_dev *dev,
return 0;
}
-static const struct eth_dev_ops sxe2_eth_dev_ops = {
- .dev_configure = sxe2_dev_configure,
- .dev_start = sxe2_dev_start,
- .dev_stop = sxe2_dev_stop,
- .dev_close = sxe2_dev_close,
- .dev_infos_get = sxe2_dev_infos_get,
+static const uint32_t *
+sxe2_buffer_split_supported_hdr_ptypes_get(struct rte_eth_dev *dev __rte_unused,
+ size_t *no_of_elements __rte_unused)
+{
+ static const uint32_t ptypes[] = {
+ RTE_PTYPE_L2_ETHER,
+ RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
+ RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_UDP,
+ RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_TCP,
+ RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_SCTP,
+ RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
+ RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_L4_UDP,
+ RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_L4_TCP,
+ RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_L4_SCTP,
+
+ RTE_PTYPE_TUNNEL_GRENAT,
+
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER,
+
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN,
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN,
+
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_UDP,
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_TCP,
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_SCTP,
+
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_UDP,
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_TCP,
+ RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER |
+ RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_SCTP,
+
+ RTE_PTYPE_UNKNOWN
+ };
- .rx_queue_start = sxe2_rx_queue_start,
- .rx_queue_stop = sxe2_rx_queue_stop,
- .tx_queue_start = sxe2_tx_queue_start,
- .tx_queue_stop = sxe2_tx_queue_stop,
- .rx_queue_setup = sxe2_rx_queue_setup,
- .rx_queue_release = sxe2_rx_queue_release,
- .tx_queue_setup = sxe2_tx_queue_setup,
- .tx_queue_release = sxe2_tx_queue_release,
+ return ptypes;
+}
- .rxq_info_get = sxe2_rx_queue_info_get,
- .txq_info_get = sxe2_tx_queue_info_get,
- .rx_burst_mode_get = sxe2_rx_burst_mode_get,
- .tx_burst_mode_get = sxe2_tx_burst_mode_get,
- .tx_done_cleanup = sxe2_tx_done_cleanup,
-};
+static inline void sxe2_init_ptype_tbl(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ uint32_t *ptype = adapter->ptype_tbl;
+
+ PMD_INIT_FUNC_TRACE();
+
+ sxe2_init_ptype_list(ptype);
+}
struct sxe2_pci_map_bar_info *sxe2_dev_get_bar_info(struct sxe2_adapter *adapter,
enum sxe2_pci_map_resource res_type)
@@ -360,6 +424,29 @@ void *sxe2_pci_map_addr_get(struct sxe2_adapter *adapter,
return addr;
}
+static int32_t sxe2_eth_init(struct rte_eth_dev *dev)
+{
+ int32_t ret = 0;
+
+ ret = sxe2_link_update_init(dev);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to initialize link update, ret:%d", ret);
+ goto l_end;
+ }
+
+ ret = sxe2_mtu_set(dev, dev->data->mtu);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to set mtu, ret=%d", ret);
+ goto l_end;
+ }
+l_end:
+ return ret;
+}
+
+static void sxe2_eth_uinit(struct rte_eth_dev *dev __rte_unused)
+{
+}
+
static void sxe2_drv_dev_caps_set(struct sxe2_adapter *adapter,
struct sxe2_drv_dev_caps_resp *dev_caps)
{
@@ -765,6 +852,8 @@ static int32_t sxe2_dev_init(struct rte_eth_dev *dev,
goto l_end;
}
+ sxe2_init_ptype_tbl(dev);
+
ret = sxe2_hw_init(dev);
if (ret) {
PMD_LOG_ERR(INIT, "Failed to initialize hw, ret=[%d]", ret);
@@ -789,18 +878,38 @@ static int32_t sxe2_dev_init(struct rte_eth_dev *dev,
goto init_dev_info_err;
}
+ ret = sxe2_eth_init(dev);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to initialize eth parameters, ret=%d", ret);
+ goto init_eth_err;
+ }
+
goto l_end;
+init_eth_err:
init_dev_info_err:
sxe2_vsi_uninit(dev);
init_vsi_err:
+ sxe2_dev_pci_map_uinit(dev);
l_end:
return ret;
}
+static int32_t sxe2_dev_close(struct rte_eth_dev *dev)
+{
+ (void)sxe2_dev_stop(dev);
+ (void)sxe2_queues_release(dev);
+ sxe2_vsi_uninit(dev);
+ sxe2_dev_pci_map_uinit(dev);
+ sxe2_eth_uinit(dev);
+
+ return 0;
+}
+
static int32_t sxe2_dev_uninit(struct rte_eth_dev *dev)
{
int32_t ret = 0;
+
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
goto l_end;
diff --git a/drivers/net/sxe2/sxe2_ethdev.h b/drivers/net/sxe2/sxe2_ethdev.h
index a3706945e8..9de47d8338 100644
--- a/drivers/net/sxe2/sxe2_ethdev.h
+++ b/drivers/net/sxe2/sxe2_ethdev.h
@@ -120,12 +120,6 @@ enum {
SXE2_FLAGS_NBITS
};
-struct sxe2_link_context {
- rte_spinlock_t link_lock;
- bool link_up;
- uint32_t speed;
-};
-
struct sxe2_devargs {
uint8_t flow_dup_pattern_mode;
uint8_t func_flow_direct_en;
@@ -267,6 +261,12 @@ struct sxe2_sched_hw_cap {
uint8_t adj_lvl;
};
+struct sxe2_link_context {
+ rte_spinlock_t link_lock;
+ bool link_up;
+ uint32_t speed;
+};
+
struct sxe2_adapter {
struct sxe2_common_device *cdev;
struct sxe2_dev_info dev_info;
@@ -276,9 +276,10 @@ struct sxe2_adapter {
struct sxe2_irq_context irq_ctxt;
struct sxe2_queue_context q_ctxt;
struct sxe2_vsi_context vsi_ctxt;
- struct sxe2_devargs devargs;
- uint16_t dev_port_id;
- uint64_t cap_flags;
+ struct sxe2_link_context link_ctxt;
+ struct sxe2_devargs devargs;
+ uint16_t dev_port_id;
+ uint64_t cap_flags;
enum sxe2_dev_type dev_type;
uint32_t ptype_tbl[SXE2_MAX_PTYPE_NUM];
struct rte_ether_addr mac_addr;
diff --git a/drivers/net/sxe2/sxe2_mac.c b/drivers/net/sxe2/sxe2_mac.c
new file mode 100644
index 0000000000..3c2f909002
--- /dev/null
+++ b/drivers/net/sxe2/sxe2_mac.c
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#include <rte_os.h>
+#include "sxe2_osal.h"
+#include "sxe2_mac.h"
+#include "sxe2_common_log.h"
+#include "sxe2_ethdev.h"
+#include "sxe2_cmd_chnl.h"
+#include "sxe2_host_regs.h"
+
+int32_t sxe2_link_update_init(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret;
+
+ PMD_INIT_FUNC_TRACE();
+
+ rte_spinlock_init(&adapter->link_ctxt.link_lock);
+
+ ret = sxe2_drv_mac_link_status_get(adapter);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to get link status, ret=%d", ret);
+ goto l_end;
+ }
+
+ (void)sxe2_link_update(dev, 0);
+
+l_end:
+ return ret;
+}
+int32_t sxe2_link_update(struct rte_eth_dev *dev, __rte_unused int32_t wait_to_complete)
+{
+ struct rte_eth_link new_link;
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+
+ memset(&new_link, 0, sizeof(new_link));
+
+ switch (adapter->link_ctxt.speed) {
+ case 0:
+ new_link.link_speed = RTE_ETH_SPEED_NUM_NONE;
+ break;
+ case 10:
+ new_link.link_speed = RTE_ETH_SPEED_NUM_10M;
+ break;
+ case 100:
+ new_link.link_speed = RTE_ETH_SPEED_NUM_100M;
+ break;
+ case 1000:
+ new_link.link_speed = RTE_ETH_SPEED_NUM_1G;
+ break;
+ case 10000:
+ new_link.link_speed = RTE_ETH_SPEED_NUM_10G;
+ break;
+ case 20000:
+ new_link.link_speed = RTE_ETH_SPEED_NUM_20G;
+ break;
+ case 25000:
+ new_link.link_speed = RTE_ETH_SPEED_NUM_25G;
+ break;
+ case 40000:
+ new_link.link_speed = RTE_ETH_SPEED_NUM_40G;
+ break;
+ case 50000:
+ new_link.link_speed = RTE_ETH_SPEED_NUM_50G;
+ break;
+ case 100000:
+ new_link.link_speed = RTE_ETH_SPEED_NUM_100G;
+ break;
+ default:
+ new_link.link_speed = RTE_ETH_SPEED_NUM_NONE;
+ break;
+ }
+
+ new_link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
+ new_link.link_status = adapter->link_ctxt.link_up ? RTE_ETH_LINK_UP :
+ RTE_ETH_LINK_DOWN;
+ new_link.link_autoneg = !(dev->data->dev_conf.link_speeds &
+ RTE_ETH_LINK_SPEED_FIXED);
+
+ return rte_eth_linkstatus_set(dev, &new_link);
+}
+
+int32_t sxe2_mtu_set(struct rte_eth_dev *dev, uint16_t mtu __rte_unused)
+{
+ int32_t ret = -1;
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+
+ PMD_INIT_FUNC_TRACE();
+
+ if (dev->data->dev_started != 0) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "port %d must be stopped before configuration",
+ dev->data->port_id);
+ ret = -1;
+ goto l_end;
+ }
+
+ ret = 0;
+
+l_end:
+ return ret;
+}
diff --git a/drivers/net/sxe2/sxe2_mac.h b/drivers/net/sxe2/sxe2_mac.h
new file mode 100644
index 0000000000..f2f3edaeff
--- /dev/null
+++ b/drivers/net/sxe2/sxe2_mac.h
@@ -0,0 +1,50 @@
+
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#ifndef __SXE2_MAC_H__
+#define __SXE2_MAC_H__
+#include <ethdev_driver.h>
+#include "sxe2_host_regs.h"
+
+#define SXE2_NUM_MACADDR_MAX 64
+
+#define SXE2_DPDK_OFFLOAD_OUTER_INSERT_8021Q SXE2_VSI_L2TAGSTXVALID_ID_OUT_VLAN1
+#define SXE2_DPDK_OFFLOAD_OUTER_INSERT_8021AD SXE2_VSI_L2TAGSTXVALID_ID_STAG
+#define SXE2_DPDK_OFFLOAD_OUTER_INSERT_QINQ1 SXE2_VSI_L2TAGSTXVALID_ID_OUT_VLAN2
+#define SXE2_DPDK_OFFLOAD_OUTER_INSERT_VLAN SXE2_VSI_L2TAGSTXVALID_ID_VLAN
+
+#define SXE2_DPDK_OFFLOAD_OUTER_INSERT_ENABLE SXE2_VSI_L2TAGSTXVALID_L2TAG1_VALID
+
+#define SXE2_DPDK_OFFLOAD_OUTER_STRIP_8021Q SXE2_VSI_TSR_ID_OUT_VLAN1
+#define SXE2_DPDK_OFFLOAD_OUTER_STRIP_8021AD SXE2_VSI_TSR_ID_STAG
+#define SXE2_DPDK_OFFLOAD_OUTER_STRIP_QINQ1 SXE2_VSI_TSR_ID_OUT_VLAN2
+
+#define SXE2_DPDK_OFFLOAD_INNER_INSERT_QINQ1 SXE2_VSI_L2TAGSTXVALID_ID_VLAN
+#define SXE2_DPDK_OFFLOAD_INNER_INSERT_ENABLE SXE2_VSI_L2TAGSTXVALID_L2TAG2_VALID
+
+#define SXE2_DPDK_OFFLOAD_INNER_STRIP_QINQ1 SXE2_VSI_TSR_ID_VLAN
+
+#define SXE2_DPDK_OFFLOAD_FIELD (0X0F)
+#define SXE2_DPDK_OFFLOAD_TAGID_FIELD (0X07)
+
+#define SXE2_DPDK_OFFLOAD_OUTER_STRIP_MASK (SXE2_DPDK_OFFLOAD_OUTER_STRIP_8021Q | \
+ SXE2_DPDK_OFFLOAD_OUTER_STRIP_8021AD | \
+ SXE2_DPDK_OFFLOAD_OUTER_STRIP_QINQ1)
+#define SXE2_DPDK_OFFLOAD_STRIP_OFFSET SXE2_VSI_TSR_SHOW_TAG_S
+
+#define SXE2_DPDK_OFFLOAD_INSERT_ENABLE (RTE_BIT32(3))
+
+struct sxe2_mac_mc_list {
+ uint32_t count;
+ struct rte_ether_addr addr[SXE2_NUM_MACADDR_MAX];
+};
+
+int32_t sxe2_link_update_init(struct rte_eth_dev *dev);
+
+int32_t sxe2_link_update(struct rte_eth_dev *dev, __rte_unused int32_t wait_to_complete);
+
+int32_t sxe2_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
+
+#endif /* __SXE2_MAC_H__ */
--
2.52.0
^ permalink raw reply related
* [PATCH v2 06/20] net/sxe2: support TM hierarchy and shaping
From: liujie5 @ 2026-06-14 9:23 UTC (permalink / raw)
To: stephen; +Cc: dev, Jie Liu
In-Reply-To: <20260614092328.201826-1-liujie5@linkdatatechnology.com>
From: Jie Liu <liujie5@linkdatatechnology.com>
This patch implements the traffic management ops for example PMD.
It supports a 4-level hierarchy: port, vsi, queue group and queue.
- Support node add/delete and hierarchy commit.
- Support private shaper and rate limiting on each node.
The hardware requires all nodes to be configured before the hierarchy
is committed to the global registers.
Signed-off-by: Jie Liu <liujie5@linkdatatechnology.com>
---
drivers/net/sxe2/meson.build | 1 +
drivers/net/sxe2/sxe2_cmd_chnl.c | 163 +++++
drivers/net/sxe2/sxe2_cmd_chnl.h | 6 +
drivers/net/sxe2/sxe2_drv_cmd.h | 26 +
drivers/net/sxe2/sxe2_ethdev.c | 82 +++
drivers/net/sxe2/sxe2_ethdev.h | 5 +
drivers/net/sxe2/sxe2_tm.c | 1151 ++++++++++++++++++++++++++++++
drivers/net/sxe2/sxe2_tm.h | 76 ++
drivers/net/sxe2/sxe2_tx.c | 1 -
9 files changed, 1510 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/sxe2/sxe2_tm.c
create mode 100644 drivers/net/sxe2/sxe2_tm.h
diff --git a/drivers/net/sxe2/meson.build b/drivers/net/sxe2/meson.build
index da7a690063..f03ea15356 100644
--- a/drivers/net/sxe2/meson.build
+++ b/drivers/net/sxe2/meson.build
@@ -63,4 +63,5 @@ sources += files(
'sxe2_mac.c',
'sxe2_filter.c',
'sxe2_rss.c',
+ 'sxe2_tm.c',
)
diff --git a/drivers/net/sxe2/sxe2_cmd_chnl.c b/drivers/net/sxe2/sxe2_cmd_chnl.c
index b997e7b044..19323ffcc4 100644
--- a/drivers/net/sxe2/sxe2_cmd_chnl.c
+++ b/drivers/net/sxe2/sxe2_cmd_chnl.c
@@ -230,6 +230,7 @@ static void sxe2_txq_ctxt_cfg_fill(struct sxe2_tx_queue *txq,
struct sxe2_drv_txq_cfg_req *req,
uint16_t txq_cnt)
{
+ struct sxe2_adapter *adapter = txq->vsi->adapter;
struct sxe2_drv_txq_ctxt *ctxt = req->cfg;
uint16_t q_idx = 0;
@@ -241,6 +242,8 @@ static void sxe2_txq_ctxt_cfg_fill(struct sxe2_tx_queue *txq,
ctxt->depth = txq[q_idx].ring_depth;
ctxt->dma_addr = txq[q_idx].base_addr;
ctxt->queue_id = txq[q_idx].queue_id;
+
+ ctxt->sched_mode = sxe2_sched_mode_get(adapter);
}
}
@@ -310,6 +313,7 @@ int32_t sxe2_drv_txq_switch(struct sxe2_adapter *adapter, struct sxe2_tx_queue *
req.q_idx = txq->queue_id;
req.is_enable = (uint8_t)enable;
+ req.sched_mode = sxe2_sched_mode_get(adapter);
sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_TXQ_DISABLE,
&req, sizeof(req), NULL, 0);
@@ -714,3 +718,162 @@ int32_t sxe2_drv_ptp_gettime(struct sxe2_adapter *adapter, struct sxe2_rx_queue
(void)rxq;
return 0;
}
+
+int32_t sxe2_drv_root_tree_alloc(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_tm_context *tm_ctxt = &adapter->tm_ctxt;
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_tm_res tm_resp;
+ int32_t ret;
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_SCHED_ROOT_TREE_ALLOC,
+ NULL, 0,
+ &tm_resp, sizeof(tm_resp));
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "add sched root failed, ret:%d", ret);
+ goto l_end;
+ }
+
+ tm_ctxt->root_teid = tm_resp.teid;
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_drv_root_tree_release(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_tm_res tm_res = {0};
+ int32_t ret;
+
+ tm_res.teid = adapter->tm_ctxt.root_teid;
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_SCHED_ROOT_TREE_RELEASE,
+ &tm_res, sizeof(tm_res),
+ NULL, 0);
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "release sched root failed, ret:%d", ret);
+ goto l_end;
+ }
+
+l_end:
+ return ret;
+}
+
+static void sxe2_drv_tm_node_to_info(struct sxe2_adapter *adapter,
+ struct sxe2_tm_node *node, struct sxe2_tm_info *info)
+{
+ uint32_t rate = 0;
+
+ if (node->shaper_profile->profile.committed.rate == UINT64_MAX)
+ rate = UINT32_MAX;
+ else
+ rate = (uint32_t)(node->shaper_profile->profile.committed.rate * 8 / 1000);
+
+ info->committed = rte_cpu_to_le_32(rate);
+
+ if (node->shaper_profile->profile.peak.rate == UINT64_MAX)
+ rate = UINT32_MAX;
+ else
+ rate = (uint32_t)(node->shaper_profile->profile.peak.rate * 8 / 1000);
+
+ info->peak = rte_cpu_to_le_32(rate);
+
+ info->priority = (adapter->tm_ctxt.prio_max - 1 - node->priority);
+
+ info->weight = rte_cpu_to_le_16(node->hw_weight);
+}
+
+static int32_t sxe2_drv_tm_commit_node(struct sxe2_adapter *adapter,
+ struct sxe2_tm_node *tm_node)
+{
+ struct sxe2_drv_cmd_params cmd = { 0 };
+ struct sxe2_tm_add_mid_msg msg_mid = {0};
+ struct sxe2_tm_add_queue_msg msg_queue = {0};
+ struct sxe2_tm_res res = {0};
+ struct sxe2_common_device *cdev = adapter->cdev;
+ int32_t ret;
+ uint32_t i;
+
+ if (tm_node->type == SXE2_TM_NODE_TYPE_VSIG) {
+ goto l_add;
+ } else if (tm_node->type == SXE2_TM_NODE_TYPE_MID) {
+ sxe2_drv_tm_node_to_info(adapter, tm_node, &msg_mid.info);
+ msg_mid.parent_teid = rte_cpu_to_le_16(tm_node->parent->teid);
+ msg_mid.adj_lvl = adapter->sched_ctxt.adj_lvl;
+
+ sxe2_drv_cmd_params_fill(adapter, &cmd,
+ SXE2_DRV_CMD_SCHED_TM_ADD_MID_NODE,
+ &msg_mid, sizeof(msg_mid),
+ &res, sizeof(res));
+ ret = sxe2_drv_cmd_exec(cdev, &cmd);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "add tm mid node failed, ret:%d", ret);
+ goto l_end;
+ }
+ } else if (tm_node->type == SXE2_TM_NODE_TYPE_QUEUE) {
+ sxe2_drv_tm_node_to_info(adapter, tm_node, &msg_queue.info);
+ msg_queue.parent_teid = rte_cpu_to_le_16(tm_node->parent->teid);
+ msg_queue.queue_id = rte_cpu_to_le_16(tm_node->id);
+ msg_queue.adj_lvl = adapter->sched_ctxt.adj_lvl;
+
+ sxe2_drv_cmd_params_fill(adapter, &cmd,
+ SXE2_DRV_CMD_SCHED_TM_ADD_QUEUE_NODE,
+ &msg_queue, sizeof(msg_queue),
+ &res, sizeof(res));
+ ret = sxe2_drv_cmd_exec(cdev, &cmd);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "add tm queue failed, ret:%d", ret);
+ goto l_end;
+ }
+ } else {
+ PMD_LOG_ERR(DRV, "commit tm node failed, type:%d", tm_node->type);
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ tm_node->teid = rte_le_to_cpu_16(res.teid);
+
+l_add:
+ for (i = 0; i < tm_node->child_cnt; i++) {
+ ret = sxe2_drv_tm_commit_node(adapter, tm_node->children[i]);
+ if (ret)
+ goto l_end;
+ }
+l_end:
+ return ret;
+}
+
+int32_t sxe2_drv_tm_commit(struct sxe2_adapter *adapter)
+{
+ struct sxe2_drv_cmd_params cmd = { 0 };
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_tm_res tm_res = {0};
+ int32_t ret;
+
+ tm_res.teid = adapter->tm_ctxt.root_teid;
+ sxe2_drv_cmd_params_fill(adapter, &cmd, SXE2_DRV_CMD_SCHED_ROOT_CHILDREN_DELETE,
+ &tm_res, sizeof(tm_res),
+ NULL, 0);
+ ret = sxe2_drv_cmd_exec(cdev, &cmd);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "del tm root failed, ret:%d", ret);
+ goto l_end;
+ }
+
+ ret = sxe2_drv_tm_commit_node(adapter, adapter->tm_ctxt.root);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "commit tm node failed, ret:%d", ret);
+ goto l_end;
+ }
+
+ PMD_LOG_DEBUG(DRV, "commit tm success");
+l_end:
+ return ret;
+}
diff --git a/drivers/net/sxe2/sxe2_cmd_chnl.h b/drivers/net/sxe2/sxe2_cmd_chnl.h
index 2546c65a6c..77e689abcd 100644
--- a/drivers/net/sxe2/sxe2_cmd_chnl.h
+++ b/drivers/net/sxe2/sxe2_cmd_chnl.h
@@ -38,6 +38,12 @@ int32_t sxe2_drv_mac_link_status_get(struct sxe2_adapter *adapter);
int32_t sxe2_drv_promisc_config(struct sxe2_adapter *adapter, bool set);
+int32_t sxe2_drv_root_tree_release(struct rte_eth_dev *dev);
+
+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_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 9998f241f0..67c6885cae 100644
--- a/drivers/net/sxe2/sxe2_drv_cmd.h
+++ b/drivers/net/sxe2/sxe2_drv_cmd.h
@@ -349,6 +349,32 @@ struct __rte_aligned(4) __rte_packed_begin sxe2_rss_hf_req {
uint8_t rsv1[3];
} __rte_packed_end;
+struct __rte_aligned(4) __rte_packed_begin sxe2_tm_res {
+ uint16_t teid;
+ uint8_t rsv[2];
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_tm_info {
+ uint32_t committed;
+ uint32_t peak;
+ uint8_t priority;
+ uint8_t reserve;
+ uint16_t weight;
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_tm_add_mid_msg {
+ uint16_t parent_teid;
+ uint8_t adj_lvl;
+ struct sxe2_tm_info info;
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_tm_add_queue_msg {
+ uint16_t parent_teid;
+ uint16_t queue_id;
+ uint8_t adj_lvl;
+ struct sxe2_tm_info info;
+} __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 77a2b5b1dc..f98cf367f1 100644
--- a/drivers/net/sxe2/sxe2_ethdev.c
+++ b/drivers/net/sxe2/sxe2_ethdev.c
@@ -130,6 +130,8 @@ static const struct eth_dev_ops sxe2_eth_dev_ops = {
.reta_query = sxe2_dev_rss_reta_query,
.rss_hash_update = sxe2_dev_rss_hash_update,
.rss_hash_conf_get = sxe2_dev_rss_hash_conf_get,
+
+ .tm_ops_get = sxe2_tm_ops_get,
};
static int32_t sxe2_dev_configure(struct rte_eth_dev *dev)
@@ -575,6 +577,14 @@ static void sxe2_drv_dev_caps_set(struct sxe2_adapter *adapter,
adapter->cap_flags |= SXE2_DEV_CAPS_OFFLOAD_FC_STATE;
}
+static void sxe2_sw_sched_hw_cap_set(struct sxe2_adapter *adapter,
+ struct sxe2_txsch_caps *txsch_caps)
+{
+ adapter->sched_ctxt.tm_layers = txsch_caps->layer_cap;
+ adapter->sched_ctxt.root_max_children = txsch_caps->tm_mid_node_num;
+ adapter->sched_ctxt.prio_max = txsch_caps->prio_num;
+}
+
static int32_t sxe2_func_caps_get(struct sxe2_adapter *adapter)
{
int32_t ret = -1;
@@ -594,6 +604,8 @@ static int32_t sxe2_func_caps_get(struct sxe2_adapter *adapter)
sxe2_sw_vsi_ctx_hw_cap_set(adapter, &dev_caps.vsi_caps);
+ sxe2_sw_sched_hw_cap_set(adapter, &dev_caps.txsch_caps);
+
l_end:
return ret;
}
@@ -930,6 +942,68 @@ void sxe2_dev_pci_map_uinit(struct rte_eth_dev *dev)
adapter->dev_info.dev_data = NULL;
}
+uint32_t sxe2_sched_mode_get(struct sxe2_adapter *adapter)
+{
+ uint32_t ret_mode = SXE2_SCHED_MODE_INVALID;
+ struct sxe2_tm_context *tm_ctxt = &adapter->tm_ctxt;
+
+ if (adapter->devargs.high_performance_mode)
+ ret_mode = SXE2_SCHED_MODE_HIGH_PERFORMANCE;
+ else if (tm_ctxt->committed)
+ ret_mode = SXE2_SCHED_MODE_TM;
+ else
+ ret_mode = SXE2_SCHED_MODE_DEFAULT;
+
+ return ret_mode;
+}
+
+static int32_t sxe2_sched_init(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret = 0;
+
+ adapter->sched_ctxt.adj_lvl = adapter->devargs.sched_layer_mode;
+
+ if (adapter->devargs.high_performance_mode) {
+ PMD_LOG_DEBUG(DRV, "TM feature will be disabled in high-performance mode.");
+ adapter->cap_flags &= ~(SXE2_DEV_CAPS_OFFLOAD_TM);
+ } else {
+ ret = sxe2_tm_init(dev);
+ if (ret)
+ goto l_end;
+
+ ret = sxe2_drv_root_tree_alloc(dev);
+ if (ret)
+ goto l_end;
+ }
+
+l_end:
+ return ret;
+}
+
+static int32_t sxe2_sched_uinit(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret = 0;
+
+ if (adapter->devargs.high_performance_mode == 0) {
+ ret = sxe2_tm_uninit(dev);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to uninit tm, ret=%d", ret);
+ goto l_end;
+ }
+
+ ret = sxe2_drv_root_tree_release(dev);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to release root tree, ret=%d", ret);
+ goto l_end;
+ }
+ }
+
+l_end:
+ return ret;
+}
+
static int32_t sxe2_dev_init(struct rte_eth_dev *dev,
struct sxe2_dev_kvargs_info *kvargs __rte_unused)
{
@@ -985,8 +1059,15 @@ static int32_t sxe2_dev_init(struct rte_eth_dev *dev,
goto init_rss_err;
}
+ ret = sxe2_sched_init(dev);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to init sched, ret=%d", ret);
+ goto init_sched_err;
+ }
+
goto l_end;
+init_sched_err:
init_rss_err:
init_eth_err:
init_dev_info_err:
@@ -1002,6 +1083,7 @@ static int32_t sxe2_dev_close(struct rte_eth_dev *dev)
(void)sxe2_dev_stop(dev);
(void)sxe2_queues_release(dev);
(void)sxe2_rss_disable(dev);
+ (void)sxe2_sched_uinit(dev);
sxe2_vsi_uninit(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 3aa3799b79..95594fcbde 100644
--- a/drivers/net/sxe2/sxe2_ethdev.h
+++ b/drivers/net/sxe2/sxe2_ethdev.h
@@ -20,6 +20,7 @@
#include "sxe2_queue.h"
#include "sxe2_mac.h"
#include "sxe2_osal.h"
+#include "sxe2_tm.h"
#include "sxe2_filter.h"
struct sxe2_link_msg {
@@ -309,6 +310,8 @@ struct sxe2_adapter {
struct sxe2_rss_context rss_ctxt;
struct sxe2_link_context link_ctxt;
struct sxe2_ptp_context ptp_ctxt;
+ struct sxe2_sched_hw_cap sched_ctxt;
+ struct sxe2_tm_context tm_ctxt;
struct sxe2_devargs devargs;
struct sxe2_switchdev_info switchdev_info;
bool rule_started;
@@ -332,6 +335,8 @@ void *sxe2_pci_map_addr_get(struct sxe2_adapter *adapter,
enum sxe2_pci_map_resource res_type,
uint16_t idx_in_func);
+uint32_t sxe2_sched_mode_get(struct sxe2_adapter *adapter);
+
struct sxe2_pci_map_bar_info *sxe2_dev_get_bar_info(struct sxe2_adapter *adapter,
enum sxe2_pci_map_resource res_type);
diff --git a/drivers/net/sxe2/sxe2_tm.c b/drivers/net/sxe2/sxe2_tm.c
new file mode 100644
index 0000000000..4c4f793cd5
--- /dev/null
+++ b/drivers/net/sxe2/sxe2_tm.c
@@ -0,0 +1,1151 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#include <rte_ethdev.h>
+#include <rte_tm_driver.h>
+
+#include "sxe2_tm.h"
+#include "sxe2_ethdev.h"
+#include "sxe2_common_log.h"
+#include "sxe2_cmd_chnl.h"
+
+static uint16_t sxe2_tm_level_node_num_get(uint8_t level)
+{
+ uint16_t node_num = 0;
+
+ switch (level) {
+ case 0:
+ node_num = SXE2_TM_1L_NODE_NUM_MAX;
+ break;
+ case 1:
+ node_num = SXE2_TM_2L_NODE_NUM_MAX;
+ break;
+ case 2:
+ node_num = SXE2_TM_3L_NODE_NUM_MAX;
+ break;
+ case 3:
+ node_num = SXE2_TM_4L_NODE_NUM_MAX;
+ break;
+ }
+ return node_num;
+}
+
+static int32_t sxe2_tm_capabilities_get(struct rte_eth_dev *dev,
+ struct rte_tm_capabilities *cap,
+ struct rte_tm_error *error)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret = 0;
+ uint32_t i;
+
+ if (!cap || !error) {
+ PMD_LOG_ERR(DRV, "sxe2 get tm cap failed, cap or error is NULL.");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if ((adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_TM) == 0) {
+ PMD_LOG_ERR(DRV, "The TM capability is not supported.");
+ error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
+ error->message = "The TM capability is not supported.";
+ ret = ENOTSUP;
+ goto l_end;
+ }
+
+ error->type = RTE_TM_ERROR_TYPE_NONE;
+ memset(cap, 0, sizeof(struct rte_tm_capabilities));
+
+ for (i = 0; i < adapter->tm_ctxt.tm_layers; i++)
+ cap->n_nodes_max += sxe2_tm_level_node_num_get(i);
+
+ cap->n_levels_max = adapter->tm_ctxt.tm_layers;
+
+ cap->non_leaf_nodes_identical = 1;
+
+ cap->leaf_nodes_identical = 1;
+
+ cap->shaper_n_max = cap->n_nodes_max;
+
+ cap->shaper_private_n_max = cap->n_nodes_max;
+
+ cap->shaper_private_dual_rate_n_max = cap->n_nodes_max;
+
+ cap->shaper_private_rate_min = 0;
+
+ cap->shaper_private_rate_max = 12500000000ull;
+
+ cap->shaper_private_packet_mode_supported = 0;
+ cap->shaper_private_byte_mode_supported = 1;
+
+ cap->shaper_pkt_length_adjust_min = RTE_TM_ETH_FRAMING_OVERHEAD;
+
+ cap->shaper_pkt_length_adjust_max = RTE_TM_ETH_FRAMING_OVERHEAD_FCS;
+
+ cap->shaper_shared_n_max = 0;
+ cap->shaper_shared_n_nodes_per_shaper_max = 0;
+ cap->shaper_shared_n_shapers_per_node_max = 0;
+ cap->shaper_shared_dual_rate_n_max = 0;
+ cap->shaper_shared_rate_min = 0;
+ cap->shaper_shared_rate_max = 0;
+ cap->shaper_shared_packet_mode_supported = 0;
+ cap->shaper_shared_byte_mode_supported = 0;
+
+ cap->sched_n_children_max = dev->data->nb_tx_queues;
+
+ cap->sched_sp_n_priorities_max = 7;
+
+ cap->sched_wfq_n_children_per_group_max = 1;
+ cap->sched_wfq_n_groups_max = 0;
+ cap->sched_wfq_weight_max = 0;
+ cap->sched_wfq_packet_mode_supported = 0;
+ cap->sched_wfq_byte_mode_supported = 0;
+
+ cap->cman_wred_packet_mode_supported = 0;
+ cap->cman_wred_byte_mode_supported = 0;
+ cap->cman_head_drop_supported = 0;
+ cap->cman_wred_context_n_max = 0;
+ cap->cman_wred_context_private_n_max = 0;
+ cap->cman_wred_context_shared_n_max = 0;
+ cap->cman_wred_context_shared_n_nodes_per_context_max = 0;
+ cap->cman_wred_context_shared_n_contexts_per_node_max = 0;
+
+ cap->dynamic_update_mask = 0;
+
+ cap->stats_mask = 0;
+l_end:
+ return ret;
+}
+
+static int32_t sxe2_level_capabilities_get(struct rte_eth_dev *dev,
+ uint32_t level_id, struct rte_tm_level_capabilities *cap,
+ struct rte_tm_error *error)
+{
+ int32_t ret = 0;
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+
+ if (!cap || !error) {
+ PMD_LOG_ERR(DRV, "sxe2 get tm cap failed, cap or error is NULL.");
+ ret = -EINVAL;
+ goto l_end;
+ }
+ if ((adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_TM) == 0) {
+ PMD_LOG_ERR(DRV, "The TM capability is not supported.");
+ error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
+ error->message = "The TM capability is not supported.";
+ ret = ENOTSUP;
+ goto l_end;
+ }
+
+ if (level_id >= adapter->tm_ctxt.tm_layers) {
+ ret = -EINVAL;
+ error->type = RTE_TM_ERROR_TYPE_LEVEL_ID;
+ error->message = "too deep level";
+ goto l_end;
+ }
+
+ cap->n_nodes_max = sxe2_tm_level_node_num_get(level_id);
+
+ cap->non_leaf_nodes_identical = true;
+
+ cap->leaf_nodes_identical = true;
+
+ if (level_id != adapter->tm_ctxt.tm_layers - 1) {
+ cap->n_nodes_nonleaf_max = cap->n_nodes_max;
+ cap->n_nodes_leaf_max = 0;
+
+ cap->nonleaf.shaper_private_supported = true;
+ cap->nonleaf.shaper_private_dual_rate_supported = true;
+ cap->nonleaf.shaper_private_rate_min = 0;
+
+ cap->nonleaf.shaper_private_rate_max = 12500000000ull;
+ cap->nonleaf.shaper_private_packet_mode_supported = 0;
+ cap->nonleaf.shaper_private_byte_mode_supported = 1;
+
+ cap->nonleaf.shaper_shared_n_max = 0;
+ cap->nonleaf.shaper_shared_packet_mode_supported = 0;
+ cap->nonleaf.shaper_shared_byte_mode_supported = 0;
+
+ cap->nonleaf.sched_n_children_max = SXE2_TM_MAX_CHILDREN_COUNT;
+ cap->nonleaf.sched_sp_n_priorities_max = 7;
+
+ cap->nonleaf.sched_wfq_n_children_per_group_max = 0;
+ cap->nonleaf.sched_wfq_n_groups_max = 0;
+ cap->nonleaf.sched_wfq_weight_max = 0;
+ cap->nonleaf.sched_wfq_packet_mode_supported = 0;
+ cap->nonleaf.sched_wfq_byte_mode_supported = 0;
+
+ cap->nonleaf.stats_mask = 0;
+ } else {
+ cap->n_nodes_nonleaf_max = 0;
+ cap->n_nodes_leaf_max = cap->n_nodes_max;
+
+ cap->leaf.shaper_private_supported = true;
+ cap->leaf.shaper_private_dual_rate_supported = true;
+ cap->leaf.shaper_private_rate_min = 0;
+ cap->leaf.shaper_private_rate_max = 12500000000ull;
+ cap->leaf.shaper_private_packet_mode_supported = 0;
+ cap->leaf.shaper_private_byte_mode_supported = 1;
+
+ cap->leaf.shaper_shared_n_max = 0;
+ cap->leaf.shaper_shared_packet_mode_supported = 0;
+ cap->leaf.shaper_shared_byte_mode_supported = 0;
+
+ cap->leaf.cman_head_drop_supported = false;
+ cap->leaf.cman_wred_context_private_supported = false;
+ cap->leaf.cman_wred_context_shared_n_max = 0;
+
+ cap->leaf.stats_mask = 0;
+ }
+
+l_end:
+ return ret;
+}
+
+static struct sxe2_tm_node *sxe2_tm_find_node(struct sxe2_tm_node *parent, uint32_t id)
+{
+ struct sxe2_tm_node *node = NULL;
+ uint32_t i;
+
+ if (parent == NULL || parent->id == id) {
+ node = parent;
+ goto l_end;
+ }
+
+ for (i = 0; i < parent->child_cnt; i++) {
+ node = sxe2_tm_find_node(parent->children[i], id);
+ if (node)
+ goto l_end;
+ }
+
+l_end:
+ return node;
+}
+
+static int32_t sxe2_node_capabilities_get(struct rte_eth_dev *dev, uint32_t node_id,
+ struct rte_tm_node_capabilities *cap,
+ struct rte_tm_error *error)
+{
+ int32_t ret = -EINVAL;
+ struct sxe2_tm_node *tm_node;
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+
+ if (!cap || !error) {
+ PMD_LOG_ERR(DRV, "sxe2 get tm cap failed, cap or error is NULL.");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if ((adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_TM) == 0) {
+ PMD_LOG_ERR(DRV, "The TM capability is not supported.");
+ error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
+ error->message = "The TM capability is not supported.";
+ ret = ENOTSUP;
+ goto l_end;
+ }
+
+ if (node_id == RTE_TM_NODE_ID_NULL) {
+ PMD_LOG_ERR(DRV, "invalid node id");
+ error->type = RTE_TM_ERROR_TYPE_NODE_ID;
+ error->message = "invalid node id";
+ goto l_end;
+ }
+
+ tm_node = sxe2_tm_find_node(adapter->tm_ctxt.root, node_id);
+ if (!tm_node) {
+ PMD_LOG_ERR(DRV, "no such node");
+ error->type = RTE_TM_ERROR_TYPE_NODE_ID;
+ error->message = "no such node";
+ goto l_end;
+ }
+
+ cap->shaper_private_supported = true;
+ cap->shaper_private_dual_rate_supported = true;
+ cap->shaper_private_rate_min = 0;
+ cap->shaper_private_rate_max = 12500000000ull;
+ cap->shaper_private_packet_mode_supported = 0;
+ cap->shaper_private_byte_mode_supported = 1;
+
+ cap->shaper_shared_n_max = 0;
+ cap->shaper_shared_packet_mode_supported = 0;
+ cap->shaper_shared_byte_mode_supported = 0;
+
+ if (tm_node->level == adapter->tm_ctxt.tm_layers - 1) {
+ cap->leaf.cman_head_drop_supported = false;
+ cap->leaf.cman_wred_context_private_supported = false;
+ cap->leaf.cman_wred_context_shared_n_max = 0;
+ } else {
+ cap->nonleaf.sched_n_children_max = SXE2_TM_MAX_CHILDREN_COUNT;
+ cap->nonleaf.sched_sp_n_priorities_max = 7;
+ cap->nonleaf.sched_wfq_n_children_per_group_max = 0;
+ cap->nonleaf.sched_wfq_n_groups_max = 0;
+ cap->nonleaf.sched_wfq_weight_max = 0;
+ cap->nonleaf.sched_wfq_packet_mode_supported = 0;
+ cap->nonleaf.sched_wfq_byte_mode_supported = 0;
+ }
+ cap->stats_mask = 0;
+
+ ret = 0;
+l_end:
+ return ret;
+}
+
+static int32_t sxe2_tm_shaper_profile_param_check(const struct rte_tm_shaper_params *profile,
+ struct rte_tm_error *error)
+{
+ int32_t ret = 0;
+
+ if (profile->committed.size) {
+ PMD_LOG_ERR(DRV, "committed bucket size not supported.");
+ error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_SIZE;
+ error->message = "committed bucket size not supported";
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if (profile->peak.size) {
+ PMD_LOG_ERR(DRV, "peak bucket size not supported.");
+ error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE;
+ error->message = "peak bucket size not supported";
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if (profile->pkt_length_adjust) {
+ PMD_LOG_ERR(DRV, "packet length adjustment not supported.");
+ error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PKT_ADJUST_LEN;
+ error->message = "packet length adjustment not supported";
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if (profile->committed.rate > SXE2_HW_RATE_MAX ||
+ profile->committed.rate < SXE2_HW_RATE_MIN) {
+ PMD_LOG_ERR(DRV, "The committed rate limit value is required to be in "
+ "the range [%" PRIu64 ", %" PRIu64 "].",
+ (uint64_t)SXE2_HW_RATE_MIN, (uint64_t)SXE2_HW_RATE_MAX);
+ error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_RATE;
+ error->message = "invalid rate limit: value out of range.";
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if (profile->peak.rate > SXE2_HW_RATE_MAX ||
+ profile->peak.rate < SXE2_HW_RATE_MIN) {
+ PMD_LOG_ERR(DRV, "The peak rate limit value is required to be in "
+ "the range [%" PRIu64 ", %" PRIu64 "].",
+ (uint64_t)SXE2_HW_RATE_MIN, (uint64_t)SXE2_HW_RATE_MAX);
+ error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE;
+ error->message = "invalid rate limit: value out of range.";
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if (profile->committed.rate > profile->peak.rate) {
+ PMD_LOG_ERR(DRV, "committed rate can't be greater than peak rate.");
+ error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_RATE;
+ error->message = "committed rate can't be greater than peak rate.";
+ ret = -EINVAL;
+ goto l_end;
+ }
+l_end:
+ return ret;
+}
+
+static inline struct sxe2_tm_shaper_profile *
+sxe2_tm_shaper_profile_search(struct rte_eth_dev *dev, uint32_t id)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_shaper_profile_list *shaper_profile_list =
+ &adapter->tm_ctxt.profile_list;
+ struct sxe2_tm_shaper_profile *shaper_profile = NULL;
+
+ TAILQ_FOREACH(shaper_profile, shaper_profile_list, node) {
+ if (id == shaper_profile->id)
+ goto l_end;
+ }
+
+ shaper_profile = NULL;
+
+l_end:
+ return shaper_profile;
+}
+
+static int32_t sxe2_tm_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id,
+ const struct rte_tm_shaper_params *profile,
+ struct rte_tm_error *error)
+{
+ int32_t ret = -EINVAL;
+ struct sxe2_tm_shaper_profile *shaper_profile = NULL;
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+
+ if (!profile || !error) {
+ PMD_LOG_ERR(DRV, "Invalid input: profile:0x%p or error:0x%p is null.",
+ profile, error);
+ if (error) {
+ error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
+ error->message = "Invalid input: profile or error is null.";
+ }
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if ((adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_TM) == 0) {
+ PMD_LOG_ERR(DRV, "The TM capability is not supported.");
+ error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
+ error->message = "The TM capability is not supported.";
+ ret = ENOTSUP;
+ goto l_end;
+ }
+
+ ret = sxe2_tm_shaper_profile_param_check(profile, error);
+ if (ret)
+ goto l_end;
+
+ shaper_profile = sxe2_tm_shaper_profile_search(dev, shaper_profile_id);
+ if (shaper_profile) {
+ PMD_LOG_ERR(DRV, "profile ID exist.");
+ error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID;
+ error->message = "profile ID exist";
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ shaper_profile = rte_zmalloc("sxe2_tm_shaper_profile",
+ sizeof(struct sxe2_tm_shaper_profile), 0);
+ if (!shaper_profile) {
+ PMD_LOG_ERR(DRV, "Alloc shaper_profile memory failed.");
+ error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
+ error->message = "Alloc shaper_profile memory failed";
+ ret = -ENOMEM;
+ goto l_end;
+ }
+
+ rte_memcpy(&shaper_profile->profile, profile,
+ sizeof(struct rte_tm_shaper_params));
+ shaper_profile->id = shaper_profile_id;
+
+ TAILQ_INSERT_TAIL(&adapter->tm_ctxt.profile_list, shaper_profile, node);
+l_end:
+ return ret;
+}
+
+static int32_t sxe2_tm_shaper_profile_del(struct rte_eth_dev *dev,
+ uint32_t id, struct rte_tm_error *error)
+{
+ int32_t ret = -EINVAL;
+ struct sxe2_tm_shaper_profile *shaper_profile = NULL;
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+
+ if (!error) {
+ PMD_LOG_ERR(DRV, "Error param is null.");
+ goto l_end;
+ }
+
+ if ((adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_TM) == 0) {
+ PMD_LOG_ERR(DRV, "The TM capability is not supported.");
+ error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
+ error->message = "The TM capability is not supported.";
+ ret = ENOTSUP;
+ goto l_end;
+ }
+
+ shaper_profile = sxe2_tm_shaper_profile_search(dev, id);
+ if (!shaper_profile) {
+ PMD_LOG_ERR(DRV, "profile ID not exist.");
+ error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID;
+ error->message = "profile ID not exist";
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if (shaper_profile->ref_cnt) {
+ PMD_LOG_ERR(DRV, "profile in use.");
+ error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE;
+ error->message = "profile in use";
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ TAILQ_REMOVE(&adapter->tm_ctxt.profile_list, shaper_profile, node);
+ rte_free(shaper_profile);
+
+ ret = 0;
+l_end:
+ return ret;
+}
+
+static int32_t sxe2_tm_node_param_check(struct rte_eth_dev *dev,
+ uint32_t parent_node_type,
+ uint32_t node_id, uint32_t priority, uint32_t weight,
+ const struct rte_tm_node_params *params,
+ bool is_leaf, struct rte_tm_error *error)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_tm_context *tm_ctxt = &adapter->tm_ctxt;
+ int32_t ret = -EINVAL;
+
+ if (node_id == RTE_TM_NODE_ID_NULL) {
+ PMD_LOG_ERR(DRV, "Invalid node id.");
+ error->type = RTE_TM_ERROR_TYPE_NODE_ID;
+ error->message = "invalid node id";
+ goto l_end;
+ }
+
+ if (parent_node_type == SXE2_TM_NODE_TYPE_VSIG &&
+ priority >= tm_ctxt->prio_max) {
+ PMD_LOG_ERR(DRV, "Priority should be less than %u.", tm_ctxt->prio_max);
+ error->type = RTE_TM_ERROR_TYPE_NODE_PRIORITY;
+ error->message = "The priority is too high.";
+ goto l_end;
+ }
+
+ if (priority > SXE2_TM_PRIO_MAX) {
+ PMD_LOG_ERR(DRV, "Priority should be less than %u.", SXE2_TM_PRIO_MAX);
+ error->type = RTE_TM_ERROR_TYPE_NODE_PRIORITY;
+ error->message = "The priority is too high.";
+ goto l_end;
+ }
+
+ if (weight > SXE2_TM_WEIGHT_MAX || weight < SXE2_TM_WEIGHT_MIN) {
+ PMD_LOG_ERR(DRV, "Weight must be between 1 and 200.");
+ error->type = RTE_TM_ERROR_TYPE_NODE_WEIGHT;
+ error->message = "weight must be between 1 and 200";
+ goto l_end;
+ }
+
+ if (params->shared_shaper_id) {
+ PMD_LOG_ERR(DRV, "Shared shaper not supported.");
+ error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_SHAPER_ID;
+ error->message = "shared shaper not supported";
+ goto l_end;
+ }
+ if (params->n_shared_shapers) {
+ PMD_LOG_ERR(DRV, "Shared shaper not supported..");
+ error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS;
+ error->message = "shared shaper not supported";
+ goto l_end;
+ }
+
+ if (!is_leaf) {
+ if (node_id <= dev->data->nb_tx_queues) {
+ PMD_LOG_ERR(DRV, "no leaf node id must bigger than queue id.");
+ error->type = RTE_TM_ERROR_TYPE_NODE_ID;
+ error->message = "no leaf node id must bigger than queue id.";
+ goto l_end;
+ }
+
+ if (params->nonleaf.wfq_weight_mode) {
+ PMD_LOG_ERR(DRV, "WFQ not supported.");
+ error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE;
+ error->message = "WFQ not supported";
+ goto l_end;
+ }
+
+ if (params->nonleaf.n_sp_priorities != 1) {
+ PMD_LOG_ERR(DRV, "SP priority not supported.");
+ error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES;
+ error->message = "SP priority not supported";
+ goto l_end;
+ }
+ } else {
+ if (node_id >= dev->data->nb_tx_queues) {
+ PMD_LOG_ERR(DRV, "leaf node id must be queue id.");
+ error->type = RTE_TM_ERROR_TYPE_NODE_ID;
+ error->message = "leaf node id must be queue id.";
+ goto l_end;
+ }
+
+ if (params->leaf.cman) {
+ PMD_LOG_ERR(DRV, "Congestion management not supported.");
+ error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_CMAN;
+ error->message = "Congestion management not supported";
+ goto l_end;
+ }
+ if (params->leaf.wred.wred_profile_id != RTE_TM_WRED_PROFILE_ID_NONE) {
+ PMD_LOG_ERR(DRV, "WRED not supported.");
+ error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_WRED_PROFILE_ID;
+ error->message = "WRED not supported";
+ goto l_end;
+ }
+ if (params->leaf.wred.shared_wred_context_id) {
+ PMD_LOG_ERR(DRV, "WRED not supported.");
+ error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_WRED_CONTEXT_ID;
+ error->message = "WRED not supported";
+ goto l_end;
+ }
+ if (params->leaf.wred.n_shared_wred_contexts) {
+ PMD_LOG_ERR(DRV, "WRED not supported.");
+ error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_WRED_CONTEXTS;
+ error->message = "WRED not supported";
+ goto l_end;
+ }
+ }
+ ret = 0;
+l_end:
+ return ret;
+}
+
+static int32_t sxe2_tm_add_child(struct sxe2_tm_node *parent,
+ struct sxe2_tm_node *child)
+{
+ int32_t ret = -1;
+ uint32_t i;
+ for (i = 0; i < SXE2_TM_MAX_CHILDREN_COUNT; i++) {
+ if (parent->children[i] == NULL) {
+ parent->children[i] = child;
+ child->index_in_parent = i;
+ parent->child_cnt++;
+ ret = 0;
+ break;
+ }
+ }
+ return ret;
+}
+
+static int32_t sxe2_tm_node_add(struct rte_eth_dev *dev, uint32_t node_id, uint32_t parent_node_id,
+ uint32_t priority, uint32_t weight, uint32_t level_id,
+ const struct rte_tm_node_params *params,
+ struct rte_tm_error *error)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_tm_shaper_profile *shaper_profile = NULL;
+ struct sxe2_tm_context *tm_ctxt = &adapter->tm_ctxt;
+ struct sxe2_tm_node *tm_node = NULL;
+ struct sxe2_tm_node *parent_node = NULL;
+ int32_t ret = -EINVAL;
+ bool is_leaf;
+
+ if (!params || !error) {
+ PMD_LOG_ERR(DRV, "Invalid input: params:0x%p or error:0x%p is null.",
+ params, error);
+ if (error) {
+ error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
+ error->message = "Invalid input: params or error is null.";
+ }
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if ((adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_TM) == 0) {
+ PMD_LOG_ERR(DRV, "The TM capability is not supported.");
+ error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
+ error->message = "The TM capability is not supported.";
+ ret = ENOTSUP;
+ goto l_end;
+ }
+
+ shaper_profile = sxe2_tm_shaper_profile_search(dev, params->shaper_profile_id);
+ if (!shaper_profile) {
+ PMD_LOG_ERR(DRV, "Shaper profile does not exist.");
+ error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID;
+ error->message = "shaper profile does not exist";
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if (parent_node_id == RTE_TM_NODE_ID_NULL) {
+ if (level_id != 0) {
+ PMD_LOG_ERR(DRV, "Wrong level, root node (NULL parent) must be at level 0.");
+ error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
+ error->message = "Wrong level, root node (NULL parent) must be at level 0";
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if (tm_ctxt->root) {
+ PMD_LOG_ERR(DRV, "Already have a root.");
+ error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
+ error->message = "already have a root";
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ ret = sxe2_tm_node_param_check(dev, SXE2_TM_NODE_TYPE_INVALID, node_id, priority,
+ weight, params, false, error);
+ if (ret)
+ goto l_end;
+
+ tm_node = rte_zmalloc("tm_node_root", sizeof(struct sxe2_tm_node), 0);
+ if (!tm_node) {
+ PMD_LOG_ERR(DRV, "Alloc tm_node memory failed.");
+ error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
+ error->message = "Alloc tm_node memory failed";
+ ret = -ENOMEM;
+ goto l_end;
+ }
+
+ tm_node->id = node_id;
+ tm_node->level = 0;
+ tm_node->parent = NULL;
+ tm_node->child_cnt = 0;
+ tm_node->weight = weight;
+ tm_node->hw_weight = SXE2_TM_WEIGHT_SUM;
+ tm_node->type = SXE2_TM_NODE_TYPE_VSIG;
+ tm_node->priority = priority;
+ tm_node->shaper_profile = shaper_profile;
+
+ tm_node->teid = tm_ctxt->root_teid;
+
+ shaper_profile->ref_cnt++;
+ tm_ctxt->root = tm_node;
+ ret = 0;
+ goto l_end;
+ }
+
+ parent_node = sxe2_tm_find_node(tm_ctxt->root, parent_node_id);
+ if (!parent_node) {
+ PMD_LOG_ERR(DRV, "Parent not exist.");
+ error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
+ error->message = "parent not exist";
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if (parent_node->child_cnt >= SXE2_TM_MAX_CHILDREN_COUNT ||
+ (parent_node->type == SXE2_TM_NODE_TYPE_VSIG &&
+ parent_node->child_cnt >= tm_ctxt->root_max_children)) {
+ PMD_LOG_ERR(DRV, "Parent node is full.");
+ error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
+ error->message = "parent node is full";
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if (level_id == RTE_TM_NODE_LEVEL_ID_ANY) {
+ level_id = parent_node->level + 1;
+ } else if (level_id != parent_node->level + 1) {
+ PMD_LOG_ERR(DRV, "Wrong level.");
+ error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
+ error->message = "Wrong level";
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if (level_id >= tm_ctxt->tm_layers) {
+ PMD_LOG_ERR(DRV, "The maximum number of TM configuration levels is %d",
+ tm_ctxt->tm_layers);
+ error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
+ error->message = "TM level exceeds supported hardware limit";
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if (level_id + 1 == tm_ctxt->tm_layers)
+ is_leaf = true;
+ else
+ is_leaf = false;
+
+ ret = sxe2_tm_node_param_check(dev, parent_node->type, node_id, priority, weight,
+ params, is_leaf, error);
+ if (ret)
+ goto l_end;
+
+ if (sxe2_tm_find_node(tm_ctxt->root, node_id)) {
+ PMD_LOG_ERR(DRV, "Node id already used.");
+ error->type = RTE_TM_ERROR_TYPE_NODE_ID;
+ error->message = "node id already used";
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ tm_node = rte_zmalloc("tm_node_no_root", sizeof(struct sxe2_tm_node), 0);
+ if (!tm_node) {
+ PMD_LOG_ERR(DRV, "Alloc tm_node memory failed.");
+ error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
+ error->message = "Alloc tm_node memory failed";
+ ret = -ENOMEM;
+ goto l_end;
+ }
+
+ if (level_id + 1 != tm_ctxt->tm_layers)
+ tm_node->type = SXE2_TM_NODE_TYPE_MID;
+ else
+ tm_node->type = SXE2_TM_NODE_TYPE_QUEUE;
+ tm_node->id = node_id;
+ tm_node->level = level_id;
+ tm_node->parent = parent_node;
+ tm_node->child_cnt = 0;
+ tm_node->weight = weight;
+ tm_node->priority = priority;
+ tm_node->shaper_profile = shaper_profile;
+ shaper_profile->ref_cnt++;
+
+ ret = sxe2_tm_add_child(parent_node, tm_node);
+ if (ret) {
+ shaper_profile->ref_cnt--;
+ rte_free(tm_node);
+ }
+l_end:
+ return ret;
+}
+
+static int32_t sxe2_tm_tree_delete(struct sxe2_tm_node *tm_node)
+{
+ int32_t ret = 0;
+ uint32_t i, j;
+ struct sxe2_tm_node *parent = NULL;
+
+ if (!tm_node)
+ goto l_end;
+
+ parent = tm_node->parent;
+
+ if (tm_node->child_cnt != 0) {
+ for (i = SXE2_TM_MAX_CHILDREN_COUNT; i > 0; i--) {
+ if (tm_node->children[i - 1])
+ ret = sxe2_tm_tree_delete(tm_node->children[i - 1]);
+ }
+ }
+
+ if (tm_node->shaper_profile)
+ tm_node->shaper_profile->ref_cnt--;
+
+ if (tm_node->type != SXE2_TM_NODE_TYPE_VSIG && parent) {
+ for (i = 0; i < parent->child_cnt; i++) {
+ if (parent->children[i] == tm_node)
+ break;
+ }
+ for (j = i; j < parent->child_cnt - 1; j++)
+ parent->children[j] = parent->children[j + 1];
+
+ parent->children[parent->child_cnt - 1] = NULL;
+ parent->child_cnt--;
+ }
+ rte_free(tm_node);
+ tm_node = NULL;
+l_end:
+ return ret;
+}
+
+static int32_t sxe2_tm_node_delete(struct rte_eth_dev *dev, uint32_t node_id,
+ struct rte_tm_error *error)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_tm_context *tm_ctxt = &adapter->tm_ctxt;
+ struct sxe2_tm_node *tm_node = NULL;
+ int32_t ret = -EINVAL;
+
+ if (!error) {
+ PMD_LOG_ERR(DRV, "Invalid input: error is null.");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if ((adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_TM) == 0) {
+ PMD_LOG_ERR(DRV, "The TM capability is not supported.");
+ error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
+ error->message = "The TM capability is not supported.";
+ ret = ENOTSUP;
+ goto l_end;
+ }
+
+ if (node_id == RTE_TM_NODE_ID_NULL) {
+ PMD_LOG_ERR(DRV, "Invalid node id. node_id = %u", node_id);
+ error->type = RTE_TM_ERROR_TYPE_NODE_ID;
+ error->message = "invalid node id";
+ goto l_end;
+ }
+
+ tm_node = sxe2_tm_find_node(tm_ctxt->root, node_id);
+ if (!tm_node) {
+ PMD_LOG_ERR(DRV, "No such node.");
+ error->type = RTE_TM_ERROR_TYPE_NODE_ID;
+ error->message = "no such node";
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ ret = sxe2_tm_tree_delete(tm_node);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "Delete node failed.");
+ error->type = RTE_TM_ERROR_TYPE_NODE_ID;
+ error->message = "Delete node failed";
+ goto l_end;
+ }
+
+ if (tm_node == tm_ctxt->root)
+ tm_ctxt->root = NULL;
+
+l_end:
+ return ret;
+}
+
+static int32_t sxe2_tm_node_type_get(struct rte_eth_dev *dev, uint32_t node_id,
+ int32_t *is_leaf, struct rte_tm_error *error)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_tm_context *tm_ctxt = &adapter->tm_ctxt;
+ struct sxe2_tm_node *tm_node = NULL;
+ int32_t ret = -EINVAL;
+
+ if (!is_leaf || !error) {
+ PMD_LOG_ERR(DRV, "Invalid input: is_leaf:0x%p or error:0x%p is null.",
+ is_leaf, error);
+ if (error) {
+ error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
+ error->message = "Invalid input: is_leaf or error is null";
+ }
+ goto l_end;
+ }
+
+ if ((adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_TM) == 0) {
+ PMD_LOG_ERR(DRV, "The TM capability is not supported.");
+ error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
+ error->message = "The TM capability is not supported.";
+ ret = ENOTSUP;
+ goto l_end;
+ }
+
+ if (node_id == RTE_TM_NODE_ID_NULL) {
+ PMD_LOG_ERR(DRV, "Invalid node id.");
+ error->type = RTE_TM_ERROR_TYPE_NODE_ID;
+ error->message = "invalid node id";
+ goto l_end;
+ }
+
+ tm_node = sxe2_tm_find_node(tm_ctxt->root, node_id);
+ if (!tm_node) {
+ PMD_LOG_ERR(DRV, "No such node.");
+ error->type = RTE_TM_ERROR_TYPE_NODE_ID;
+ error->message = "no such node";
+ goto l_end;
+ }
+
+ if (tm_node->level + 1 == tm_ctxt->tm_layers)
+ *is_leaf = true;
+ else
+ *is_leaf = false;
+ ret = 0;
+l_end:
+ return ret;
+}
+
+int32_t sxe2_tm_uninit(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_tm_context *tm_ctxt = &adapter->tm_ctxt;
+ struct sxe2_tm_shaper_profile *shaper_profile = NULL;
+ int32_t ret = 0;
+
+ if ((adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_TM) == 0) {
+ ret = 0;
+ goto l_end;
+ }
+
+ tm_ctxt->tm_layers = 0;
+ tm_ctxt->root_max_children = 0;
+ tm_ctxt->committed = false;
+
+ (void)sxe2_tm_tree_delete(tm_ctxt->root);
+
+ while ((shaper_profile = TAILQ_FIRST(&tm_ctxt->profile_list))) {
+ TAILQ_REMOVE(&tm_ctxt->profile_list, shaper_profile, node);
+ rte_free(shaper_profile);
+ }
+l_end:
+ return ret;
+}
+
+int32_t sxe2_tm_init(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_sched_hw_cap *sched_ctxt = &adapter->sched_ctxt;
+ struct sxe2_tm_context *tm_ctxt = &adapter->tm_ctxt;
+ int32_t ret = 0;
+ struct sxe2_tm_shaper_profile *shaper_profile = NULL;
+
+ if ((adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_TM) == 0)
+ goto l_end;
+
+ tm_ctxt->tm_layers = sched_ctxt->tm_layers;
+ tm_ctxt->root_max_children = sched_ctxt->root_max_children;
+ tm_ctxt->prio_max = sched_ctxt->prio_max;
+ tm_ctxt->committed = false;
+ TAILQ_INIT(&tm_ctxt->profile_list);
+ tm_ctxt->root = NULL;
+
+ shaper_profile = rte_zmalloc("sxe2_tm_shaper_profile",
+ sizeof(struct sxe2_tm_shaper_profile), 0);
+ if (!shaper_profile) {
+ PMD_LOG_ERR(DRV, "Alloc shaper_profile memory failed.");
+ ret = -ENOMEM;
+ goto l_end;
+ }
+ shaper_profile->id = RTE_TM_SHAPER_PROFILE_ID_NONE;
+ shaper_profile->ref_cnt = 1;
+ shaper_profile->profile.committed.rate = UINT64_MAX;
+ shaper_profile->profile.peak.rate = UINT64_MAX;
+ TAILQ_INSERT_TAIL(&tm_ctxt->profile_list, shaper_profile, node);
+
+l_end:
+ return ret;
+}
+
+static int32_t sxe2_tm_chk_all_leaf(struct rte_eth_dev *dev)
+{
+ int32_t ret = 0;
+ uint32_t i = 0;
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ for (i = 0; i < dev->data->nb_tx_queues; i++) {
+ if (!sxe2_tm_find_node(adapter->tm_ctxt.root, i)) {
+ ret = -1;
+ break;
+ }
+ }
+ return ret;
+}
+
+static int32_t sxe2_tm_weight_calc(struct sxe2_tm_node *tm_node)
+{
+ int32_t ret = 0;
+ int32_t total_weight = 0;
+ int32_t total_weight2 = 0;
+ uint32_t i = 0;
+ uint32_t j = 0;
+ uint32_t k = 0;
+ uint32_t maxindex = 0;
+ uint32_t maxweight = 0;
+ struct sxe2_tm_node *cacl_node[SXE2_TM_MAX_CHILDREN_COUNT] = {NULL};
+
+ if (!tm_node) {
+ PMD_LOG_ERR(DRV, "Invalid input: tm_node is null.");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if (tm_node->child_cnt == 0)
+ goto l_end;
+
+ for (j = SXE2_TM_PRIO_MIN; j <= SXE2_TM_PRIO_MAX; j++) {
+ k = 0;
+ total_weight = 0;
+ total_weight2 = 0;
+ maxindex = 0;
+ maxweight = 0;
+
+ for (i = 0; i < tm_node->child_cnt; i++) {
+ if (tm_node->children[i]->priority == j)
+ cacl_node[k++] = tm_node->children[i];
+ }
+ if (k == 0)
+ continue;
+
+ for (i = 0; i < k; i++)
+ total_weight += cacl_node[i]->weight;
+
+ for (i = 0; i < k; i++) {
+ cacl_node[i]->hw_weight = cacl_node[i]->weight *
+ SXE2_TM_WEIGHT_SUM / total_weight;
+ total_weight2 += cacl_node[i]->hw_weight;
+ if (cacl_node[i]->hw_weight > maxweight) {
+ maxweight = cacl_node[i]->hw_weight;
+ maxindex = i;
+ }
+ }
+
+ cacl_node[maxindex]->hw_weight += SXE2_TM_WEIGHT_SUM - total_weight2;
+ }
+
+ for (i = 0; i < tm_node->child_cnt; i++) {
+ ret = sxe2_tm_weight_calc(tm_node->children[i]);
+ if (ret)
+ goto l_end;
+ }
+
+l_end:
+ return ret;
+}
+
+static int32_t sxe2_tm_hierarchy_commit(struct rte_eth_dev *dev,
+ int32_t clear_on_fail, struct rte_tm_error *error)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret = -EINVAL;
+
+ if (!error) {
+ PMD_LOG_ERR(DRV, "Invalid input: error is null.");
+ ret = -EINVAL;
+ goto l_clear_on_fail;
+ }
+
+ if ((adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_TM) == 0) {
+ PMD_LOG_ERR(DRV, "The TM capability is not supported.");
+ error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
+ error->message = "The TM capability is not supported.";
+ ret = ENOTSUP;
+ goto l_clear_on_fail;
+ }
+
+ if (dev->data->dev_started) {
+ PMD_LOG_ERR(DRV, "Device failed to Stop.");
+ error->message = "Device failed to Stop";
+ error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
+ ret = -EPERM;
+ goto l_clear_on_fail;
+ }
+
+ ret = sxe2_tm_chk_all_leaf(dev);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "All tx queues need config.");
+ error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
+ error->message = "All tx queues need config.";
+ goto l_clear_on_fail;
+ }
+
+ ret = sxe2_tm_weight_calc(adapter->tm_ctxt.root);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "The weight in tree is wrong.");
+ error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
+ error->message = "The weight in tree is wrong.";
+ goto l_clear_on_fail;
+ }
+
+ ret = sxe2_drv_tm_commit(adapter);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "Commit tree to fw failed.");
+ error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
+ error->message = "Commit tree to fw failed.";
+ goto l_clear_on_fail;
+ }
+
+ adapter->tm_ctxt.committed = true;
+ ret = 0;
+ goto l_end;
+
+l_clear_on_fail:
+ if (clear_on_fail) {
+ (void)sxe2_tm_uninit(dev);
+ (void)sxe2_tm_init(dev);
+ }
+
+l_end:
+ return ret;
+}
+
+static const struct rte_tm_ops sxe2_tm_ops = {
+ .capabilities_get = sxe2_tm_capabilities_get,
+ .level_capabilities_get = sxe2_level_capabilities_get,
+ .node_capabilities_get = sxe2_node_capabilities_get,
+ .shaper_profile_add = sxe2_tm_shaper_profile_add,
+ .shaper_profile_delete = sxe2_tm_shaper_profile_del,
+ .node_add = sxe2_tm_node_add,
+ .node_delete = sxe2_tm_node_delete,
+ .node_type_get = sxe2_tm_node_type_get,
+
+ .hierarchy_commit = sxe2_tm_hierarchy_commit,
+};
+
+int32_t sxe2_tm_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
+{
+ int32_t ret = 0;
+
+ if (!arg) {
+ ret = -EINVAL;
+ PMD_LOG_ERR(DRV, "%s failed because arg is NULL", __func__);
+ goto l_end;
+ }
+ *(const void **)arg = &sxe2_tm_ops;
+l_end:
+ return ret;
+}
diff --git a/drivers/net/sxe2/sxe2_tm.h b/drivers/net/sxe2/sxe2_tm.h
new file mode 100644
index 0000000000..c4f8da6a8e
--- /dev/null
+++ b/drivers/net/sxe2/sxe2_tm.h
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#ifndef __SXE2_TM_H__
+#define __SXE2_TM_H__
+#include <ethdev_driver.h>
+#include <rte_flow_driver.h>
+#include "sxe2_osal.h"
+
+#define SXE2_TM_MAX_LEVEL 7
+#define SXE2_TM_1L_NODE_NUM_MAX 1
+#define SXE2_TM_2L_NODE_NUM_MAX 8
+#define SXE2_TM_3L_NODE_NUM_MAX 64
+#define SXE2_TM_4L_NODE_NUM_MAX 256
+
+#define SXE2_TM_MAX_CHILDREN_COUNT 8
+
+#define SXE2_TM_WEIGHT_MAX (200)
+#define SXE2_TM_WEIGHT_MIN (1)
+#define SXE2_TM_WEIGHT_SUM (32768)
+
+#define SXE2_HW_RATE_MIN 62500ull
+#define SXE2_HW_RATE_MAX 12500000000ull
+
+#define SXE2_TM_PRIO_MAX (7)
+#define SXE2_TM_PRIO_MIN (0)
+
+enum sxe2_tm_node_type {
+ SXE2_TM_NODE_TYPE_VSIG = 0,
+ SXE2_TM_NODE_TYPE_MID,
+ SXE2_TM_NODE_TYPE_QUEUE,
+ SXE2_TM_NODE_TYPE_INVALID,
+};
+
+struct sxe2_tm_shaper_profile {
+ TAILQ_ENTRY(sxe2_tm_shaper_profile) node;
+ uint32_t id;
+ uint32_t ref_cnt;
+ struct rte_tm_shaper_params profile;
+};
+
+TAILQ_HEAD(sxe2_shaper_profile_list, sxe2_tm_shaper_profile);
+
+struct sxe2_tm_node {
+ uint16_t id;
+ uint16_t teid;
+ uint32_t level;
+ uint32_t child_cnt;
+ uint32_t type;
+ uint16_t hw_weight;
+ uint16_t weight;
+ uint8_t priority;
+ struct sxe2_tm_node *parent;
+ uint8_t index_in_parent;
+ struct sxe2_tm_node *children[SXE2_TM_MAX_CHILDREN_COUNT];
+ struct sxe2_tm_shaper_profile *shaper_profile;
+};
+
+struct sxe2_tm_context {
+ uint32_t tm_layers;
+ uint16_t root_teid;
+ uint8_t root_max_children;
+ uint8_t prio_max;
+ bool committed;
+ struct sxe2_tm_node *root;
+ struct sxe2_shaper_profile_list profile_list;
+};
+
+int32_t sxe2_tm_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg);
+
+int32_t sxe2_tm_init(struct rte_eth_dev *dev);
+
+int32_t sxe2_tm_uninit(struct rte_eth_dev *dev);
+
+#endif /* __SXE2_TM_H__ */
diff --git a/drivers/net/sxe2/sxe2_tx.c b/drivers/net/sxe2/sxe2_tx.c
index a05beb8c7a..a280edc9c5 100644
--- a/drivers/net/sxe2/sxe2_tx.c
+++ b/drivers/net/sxe2/sxe2_tx.c
@@ -304,7 +304,6 @@ int32_t __rte_cold sxe2_tx_queue_setup(struct rte_eth_dev *dev,
}
offloads = tx_conf->offloads | dev->data->dev_conf.txmode.offloads;
-
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);
--
2.52.0
^ permalink raw reply related
* [PATCH v2 02/20] net/sxe2: add AVX2 vector data path for Rx and Tx
From: liujie5 @ 2026-06-14 9:23 UTC (permalink / raw)
To: stephen; +Cc: dev, Jie Liu
In-Reply-To: <20260614092328.201826-1-liujie5@linkdatatechnology.com>
From: Jie Liu <liujie5@linkdatatechnology.com>
Added AVX256 vectorized versions of Rx and Tx data path functions to
improve packet processing performance.
The vector path uses AVX2 SIMD instructions to process multiple
descriptors per loop, significantly reducing the per-packet overhead.
Signed-off-by: Jie Liu <liujie5@linkdatatechnology.com>
net/sxe2: support AVX512 vectorized path for Rx and Tx
---
drivers/net/sxe2/meson.build | 9 +
drivers/net/sxe2/sxe2_txrx.c | 38 +-
drivers/net/sxe2/sxe2_txrx_vec.h | 12 +-
drivers/net/sxe2/sxe2_txrx_vec_avx2.c | 776 ++++++++++++++++++++++++++
4 files changed, 830 insertions(+), 5 deletions(-)
create mode 100644 drivers/net/sxe2/sxe2_txrx_vec_avx2.c
diff --git a/drivers/net/sxe2/meson.build b/drivers/net/sxe2/meson.build
index 7bd0d8120c..c225dd7cd8 100644
--- a/drivers/net/sxe2/meson.build
+++ b/drivers/net/sxe2/meson.build
@@ -39,6 +39,15 @@ if arch_subdir == 'x86'
c_args: avx512_args)
objs += sxe2_avx512_lib.extract_objects('sxe2_txrx_vec_avx512.c')
endif
+ sxe2_avx2_lib = static_library('sxe2_avx2_lib',
+ 'sxe2_txrx_vec_avx2.c',
+ dependencies: [static_rte_ethdev,
+ static_rte_kvargs, static_rte_hash,
+ static_rte_security, static_rte_cryptodev,
+ static_rte_bus_pci],
+ include_directories: includes,
+ c_args: [cflags, '-mavx2'])
+ objs += sxe2_avx2_lib.extract_objects('sxe2_txrx_vec_avx2.c')
endif
sources += files(
diff --git a/drivers/net/sxe2/sxe2_txrx.c b/drivers/net/sxe2/sxe2_txrx.c
index aa1c474088..eaf95259a5 100644
--- a/drivers/net/sxe2/sxe2_txrx.c
+++ b/drivers/net/sxe2/sxe2_txrx.c
@@ -167,8 +167,14 @@ void sxe2_tx_mode_func_set(struct rte_eth_dev *dev)
PMD_LOG_INFO(TX, "AVX512 is not supported in build env.");
#endif
}
- if ((tx_mode_flags & SXE2_TX_MODE_VEC_SET_MASK) == 0)
- tx_mode_flags |= SXE2_TX_MODE_VEC_SSE;
+ if (((tx_mode_flags & SXE2_TX_MODE_VEC_SET_MASK) == 0) &&
+ ((rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX2) == 1) ||
+ (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512F) == 1)) &&
+ (rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_256))
+ tx_mode_flags |= SXE2_TX_MODE_VEC_AVX2;
+
+ if ((0 == (tx_mode_flags & SXE2_TX_MODE_VEC_SET_MASK)))
+ tx_mode_flags |= SXE2_TX_MODE_VEC_SSE;
#endif
if (tx_mode_flags & SXE2_TX_MODE_VEC_SET_MASK) {
ret = sxe2_tx_queues_vec_prepare(dev);
@@ -197,6 +203,13 @@ void sxe2_tx_mode_func_set(struct rte_eth_dev *dev)
dev->tx_pkt_burst = sxe2_tx_pkts_vec_avx512_simple;
}
#endif
+ } else if (tx_mode_flags & SXE2_TX_MODE_VEC_AVX2) {
+ if (tx_mode_flags & SXE2_TX_MODE_VEC_OFFLOAD) {
+ dev->tx_pkt_prepare = sxe2_tx_pkts_prepare;
+ dev->tx_pkt_burst = sxe2_tx_pkts_vec_avx2;
+ } else {
+ dev->tx_pkt_burst = sxe2_tx_pkts_vec_avx2_simple;
+ }
} else {
if (tx_mode_flags & SXE2_TX_MODE_VEC_OFFLOAD) {
dev->tx_pkt_prepare = sxe2_tx_pkts_prepare;
@@ -231,6 +244,10 @@ static const struct {
{ sxe2_tx_pkts_vec_avx512_simple,
"Vector AVX512 Simple" },
#endif
+ { sxe2_tx_pkts_vec_avx2,
+ "Vector AVX2" },
+ { sxe2_tx_pkts_vec_avx2_simple,
+ "Vector AVX2 Simple" },
{ sxe2_tx_pkts_vec_sse,
"Vector SSE" },
{ sxe2_tx_pkts_vec_sse_simple,
@@ -330,7 +347,13 @@ void sxe2_rx_mode_func_set(struct rte_eth_dev *dev)
PMD_LOG_INFO(RX, "AVX512 support detected but not enabled");
#endif
}
- if ((rx_mode_flags & SXE2_RX_MODE_VEC_SET_MASK) == 0 &&
+ if (((rx_mode_flags & SXE2_RX_MODE_VEC_SET_MASK) == 0) &&
+ ((rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX2) == 1) ||
+ (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512F) == 1)) &&
+ (rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_256))
+ rx_mode_flags |= SXE2_RX_MODE_VEC_AVX2;
+
+ if (((rx_mode_flags & SXE2_RX_MODE_VEC_SET_MASK) == 0) &&
rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_128)
rx_mode_flags |= SXE2_RX_MODE_VEC_SSE;
#endif
@@ -354,6 +377,11 @@ void sxe2_rx_mode_func_set(struct rte_eth_dev *dev)
else
dev->rx_pkt_burst = sxe2_rx_pkts_scattered_vec_avx512;
#endif
+ } else if (rx_mode_flags & SXE2_RX_MODE_VEC_AVX2) {
+ if (rx_mode_flags & SXE2_RX_MODE_VEC_OFFLOAD)
+ dev->rx_pkt_burst = sxe2_rx_pkts_scattered_vec_avx2_offload;
+ else
+ dev->rx_pkt_burst = sxe2_rx_pkts_scattered_vec_avx2;
} else {
dev->rx_pkt_burst = sxe2_rx_pkts_scattered_vec_sse_offload;
}
@@ -381,6 +409,10 @@ static const struct {
{ sxe2_rx_pkts_scattered_vec_avx512_offload,
"Offload Vector AVX512 Scattered" },
#endif
+ { sxe2_rx_pkts_scattered_vec_avx2,
+ "Vector AVX2 Scattered" },
+ { sxe2_rx_pkts_scattered_vec_avx2_offload,
+ "Offload Vector AVX2 Scattered" },
{ sxe2_rx_pkts_scattered_vec_sse_offload,
"Vector SSE Scattered" },
#endif
diff --git a/drivers/net/sxe2/sxe2_txrx_vec.h b/drivers/net/sxe2/sxe2_txrx_vec.h
index af7c8d12b2..369777606f 100644
--- a/drivers/net/sxe2/sxe2_txrx_vec.h
+++ b/drivers/net/sxe2/sxe2_txrx_vec.h
@@ -11,19 +11,21 @@
#define SXE2_RX_MODE_VEC_SIMPLE RTE_BIT32(0)
#define SXE2_RX_MODE_VEC_OFFLOAD RTE_BIT32(1)
#define SXE2_RX_MODE_VEC_SSE RTE_BIT32(2)
+#define SXE2_RX_MODE_VEC_AVX2 RTE_BIT32(3)
#define SXE2_RX_MODE_VEC_AVX512 RTE_BIT32(4)
#define SXE2_RX_MODE_BATCH_ALLOC RTE_BIT32(10)
#define SXE2_RX_MODE_VEC_SET_MASK (SXE2_RX_MODE_VEC_SIMPLE | \
SXE2_RX_MODE_VEC_OFFLOAD | SXE2_RX_MODE_VEC_SSE | \
- SXE2_RX_MODE_VEC_AVX512)
+ SXE2_RX_MODE_VEC_AVX2 | SXE2_RX_MODE_VEC_AVX512)
#define SXE2_TX_MODE_VEC_SIMPLE RTE_BIT32(0)
#define SXE2_TX_MODE_VEC_OFFLOAD RTE_BIT32(1)
#define SXE2_TX_MODE_VEC_SSE RTE_BIT32(2)
+#define SXE2_TX_MODE_VEC_AVX2 RTE_BIT32(3)
#define SXE2_TX_MODE_VEC_AVX512 RTE_BIT32(4)
#define SXE2_TX_MODE_SIMPLE_BATCH RTE_BIT32(10)
#define SXE2_TX_MODE_VEC_SET_MASK (SXE2_TX_MODE_VEC_SIMPLE | \
SXE2_TX_MODE_VEC_OFFLOAD | SXE2_TX_MODE_VEC_SSE | \
- SXE2_TX_MODE_VEC_AVX512)
+ SXE2_TX_MODE_VEC_AVX2 | SXE2_TX_MODE_VEC_AVX512)
#define SXE2_TX_VEC_NO_SUPPORT_OFFLOAD ( \
RTE_ETH_TX_OFFLOAD_MULTI_SEGS | \
RTE_ETH_TX_OFFLOAD_QINQ_INSERT | \
@@ -68,6 +70,12 @@ uint16_t sxe2_rx_pkts_scattered_vec_avx512(void *rx_queue,
struct rte_mbuf **rx_pkts, uint16_t nb_pkts);
uint16_t sxe2_rx_pkts_scattered_vec_avx512_offload(void *rx_queue,
struct rte_mbuf **rx_pkts, uint16_t nb_pkts);
+uint16_t sxe2_tx_pkts_vec_avx2_simple(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts);
+uint16_t sxe2_tx_pkts_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts);
+uint16_t sxe2_rx_pkts_scattered_vec_avx2(void *rx_queue,
+ struct rte_mbuf **rx_pkts, uint16_t nb_pkts);
+uint16_t sxe2_rx_pkts_scattered_vec_avx2_offload(void *rx_queue,
+ struct rte_mbuf **rx_pkts, uint16_t nb_pkts);
#endif
int32_t __rte_cold sxe2_tx_vec_support_check(struct rte_eth_dev *dev, uint32_t *vec_flags);
int32_t __rte_cold sxe2_tx_queues_vec_prepare(struct rte_eth_dev *dev);
diff --git a/drivers/net/sxe2/sxe2_txrx_vec_avx2.c b/drivers/net/sxe2/sxe2_txrx_vec_avx2.c
new file mode 100644
index 0000000000..72b09850b6
--- /dev/null
+++ b/drivers/net/sxe2/sxe2_txrx_vec_avx2.c
@@ -0,0 +1,776 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#include <rte_vect.h>
+
+#include "sxe2_ethdev.h"
+#include "sxe2_common_log.h"
+#include "sxe2_queue.h"
+#include "sxe2_txrx_vec.h"
+#include "sxe2_txrx_vec_common.h"
+#include "sxe2_vsi.h"
+
+static inline void
+sxe2_tx_desc_fill_one_avx2(volatile union sxe2_tx_data_desc *desc, struct rte_mbuf *pkt,
+ uint64_t desc_cmd, bool with_offloads)
+{
+ __m128i data_desc;
+ uint64_t desc_qw1;
+ uint32_t desc_offset;
+
+ desc_qw1 = (SXE2_TX_DESC_DTYPE_DATA |
+ ((uint64_t)desc_cmd) << SXE2_TX_DATA_DESC_CMD_SHIFT |
+ ((uint64_t)pkt->data_len) << SXE2_TX_DATA_DESC_BUF_SZ_SHIFT);
+
+ desc_offset = SXE2_TX_DATA_DESC_MACLEN_VAL(pkt->l2_len);
+ desc_qw1 |= ((uint64_t)desc_offset) << SXE2_TX_DATA_DESC_OFFSET_SHIFT;
+ if (with_offloads)
+ sxe2_tx_desc_fill_offloads(pkt, &desc_qw1);
+
+ data_desc = _mm_set_epi64x(desc_qw1, rte_pktmbuf_iova(pkt));
+ _mm_store_si128(RTE_CAST_PTR(__m128i *, desc), data_desc);
+}
+
+static __rte_always_inline void
+sxe2_tx_desc_fill_avx2(volatile union sxe2_tx_data_desc *desc, struct rte_mbuf **pkts,
+ uint16_t pkts_num, uint64_t desc_cmd, bool with_offloads)
+{
+ __m256i desc_group0;
+ __m256i desc_group1;
+ uint64_t desc0_qw1;
+ uint64_t desc1_qw1;
+ uint64_t desc2_qw1;
+ uint64_t desc3_qw1;
+
+ const uint64_t desc_qw1_com = (SXE2_TX_DESC_DTYPE_DATA |
+ ((uint64_t)desc_cmd) << SXE2_TX_DATA_DESC_CMD_SHIFT);
+ uint32_t desc_offset[4] = {0};
+
+ if (((uint64_t)desc & 0x1F) != 0 && pkts_num != 0) {
+ sxe2_tx_desc_fill_one_avx2(desc, *pkts, desc_cmd, with_offloads);
+ pkts_num--;
+ desc++;
+ pkts++;
+ }
+
+ while (pkts_num > 3) {
+ desc3_qw1 = (desc_qw1_com |
+ ((uint64_t)pkts[3]->data_len)
+ << SXE2_TX_DATA_DESC_BUF_SZ_SHIFT);
+
+ desc_offset[3] = SXE2_TX_DATA_DESC_MACLEN_VAL(pkts[3]->l2_len);
+ desc3_qw1 |= ((uint64_t)desc_offset[3]) << SXE2_TX_DATA_DESC_OFFSET_SHIFT;
+ if (with_offloads)
+ sxe2_tx_desc_fill_offloads(pkts[3], &desc3_qw1);
+
+ desc2_qw1 = (desc_qw1_com |
+ ((uint64_t)pkts[2]->data_len)
+ << SXE2_TX_DATA_DESC_BUF_SZ_SHIFT);
+ desc_offset[2] = SXE2_TX_DATA_DESC_MACLEN_VAL(pkts[2]->l2_len);
+ desc2_qw1 |= ((uint64_t)desc_offset[2]) << SXE2_TX_DATA_DESC_OFFSET_SHIFT;
+ if (with_offloads)
+ sxe2_tx_desc_fill_offloads(pkts[2], &desc2_qw1);
+
+ desc1_qw1 = (desc_qw1_com |
+ ((uint64_t)pkts[1]->data_len)
+ << SXE2_TX_DATA_DESC_BUF_SZ_SHIFT);
+ desc_offset[1] = SXE2_TX_DATA_DESC_MACLEN_VAL(pkts[1]->l2_len);
+ desc1_qw1 |= ((uint64_t)desc_offset[1]) << SXE2_TX_DATA_DESC_OFFSET_SHIFT;
+ if (with_offloads)
+ sxe2_tx_desc_fill_offloads(pkts[1], &desc1_qw1);
+
+ desc0_qw1 = (desc_qw1_com |
+ ((uint64_t)pkts[0]->data_len)
+ << SXE2_TX_DATA_DESC_BUF_SZ_SHIFT);
+ desc_offset[0] = SXE2_TX_DATA_DESC_MACLEN_VAL(pkts[0]->l2_len);
+ desc0_qw1 |= ((uint64_t)desc_offset[0]) << SXE2_TX_DATA_DESC_OFFSET_SHIFT;
+ if (with_offloads)
+ sxe2_tx_desc_fill_offloads(pkts[0], &desc0_qw1);
+
+ desc_group1 = _mm256_set_epi64x(desc3_qw1, rte_pktmbuf_iova(pkts[3]),
+ desc2_qw1, rte_pktmbuf_iova(pkts[2]));
+
+ desc_group0 = _mm256_set_epi64x(desc1_qw1, rte_pktmbuf_iova(pkts[1]),
+ desc0_qw1, rte_pktmbuf_iova(pkts[0]));
+
+ _mm256_store_si256(RTE_CAST_PTR(__m256i *, desc + 2), desc_group1);
+ _mm256_store_si256(RTE_CAST_PTR(__m256i *, desc), desc_group0);
+
+ pkts_num -= 4;
+ desc += 4;
+ pkts += 4;
+ }
+
+ while (pkts_num) {
+ sxe2_tx_desc_fill_one_avx2(desc, *pkts, desc_cmd, with_offloads);
+ pkts_num--;
+ desc++;
+ pkts++;
+ }
+}
+
+static __rte_always_inline uint16_t
+sxe2_tx_pkts_vec_avx2_batch(struct sxe2_tx_queue *txq, struct rte_mbuf **tx_pkts,
+ uint16_t nb_pkts, bool with_offloads)
+{
+ volatile union sxe2_tx_data_desc *desc;
+ struct sxe2_tx_buffer *buffer;
+ uint16_t next_use;
+ uint16_t res_num;
+ uint16_t tx_num;
+
+ if (txq->desc_free_num < txq->free_thresh)
+ (void)sxe2_tx_bufs_free_vec(txq);
+
+ nb_pkts = RTE_MIN(txq->desc_free_num, nb_pkts);
+ if (unlikely(nb_pkts == 0)) {
+ PMD_LOG_DEBUG(TX, "Tx pkts avx2 batch: may not enough free desc, "
+ "free_desc=%u, need_tx_pkts=%u",
+ txq->desc_free_num, nb_pkts);
+ goto l_end;
+ }
+ tx_num = nb_pkts;
+
+ next_use = txq->next_use;
+ desc = &txq->desc_ring[next_use];
+ buffer = &txq->buffer_ring[next_use];
+
+ txq->desc_free_num -= nb_pkts;
+
+ res_num = txq->ring_depth - txq->next_use;
+
+ if (tx_num >= res_num) {
+ sxe2_tx_pkts_mbuf_fill(buffer, tx_pkts, res_num);
+
+ sxe2_tx_desc_fill_avx2(desc, tx_pkts, res_num,
+ SXE2_TX_DATA_DESC_CMD_EOP, with_offloads);
+ tx_pkts += (res_num - 1);
+ desc += (res_num - 1);
+
+ sxe2_tx_desc_fill_one_avx2(desc, *tx_pkts++,
+ (SXE2_TX_DATA_DESC_CMD_EOP | SXE2_TX_DATA_DESC_CMD_RS),
+ with_offloads);
+
+ tx_num -= res_num;
+
+ next_use = 0;
+ txq->next_rs = txq->rs_thresh - 1;
+ desc = &txq->desc_ring[next_use];
+ buffer = &txq->buffer_ring[next_use];
+ }
+
+ sxe2_tx_pkts_mbuf_fill(buffer, tx_pkts, tx_num);
+
+ sxe2_tx_desc_fill_avx2(desc, tx_pkts, tx_num,
+ SXE2_TX_DATA_DESC_CMD_EOP, with_offloads);
+
+ next_use += tx_num;
+ if (next_use > txq->next_rs) {
+ txq->desc_ring[txq->next_rs].read.type_cmd_off_bsz_l2t |=
+ rte_cpu_to_le_64(SXE2_TX_DATA_DESC_CMD_RS_MASK);
+
+ txq->next_rs += txq->rs_thresh;
+ }
+ txq->next_use = next_use;
+ SXE2_PCI_REG_WRITE_WC(txq->tdt_reg_addr, next_use);
+ PMD_LOG_DEBUG(TX, "port_id=%u queue_id=%u next_use=%u send_pkts=%u",
+ txq->port_id, txq->queue_id, next_use, nb_pkts);
+l_end:
+ return nb_pkts;
+}
+
+static __rte_always_inline uint16_t
+sxe2_tx_pkts_vec_avx2_common(struct sxe2_tx_queue *txq, struct rte_mbuf **tx_pkts,
+ uint16_t nb_pkts, bool with_offloads)
+{
+ uint16_t tx_done_num = 0;
+ uint16_t tx_once_num;
+ uint16_t tx_need_num;
+
+ while (nb_pkts) {
+ tx_need_num = RTE_MIN(nb_pkts, txq->rs_thresh);
+ tx_once_num = sxe2_tx_pkts_vec_avx2_batch(txq,
+ tx_pkts + tx_done_num, tx_need_num, with_offloads);
+
+ nb_pkts -= tx_once_num;
+ tx_done_num += tx_once_num;
+
+ if (tx_once_num < tx_need_num)
+ break;
+ }
+ return tx_done_num;
+}
+
+uint16_t sxe2_tx_pkts_vec_avx2_simple(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+ return sxe2_tx_pkts_vec_avx2_common(tx_queue, tx_pkts, nb_pkts, false);
+}
+
+uint16_t sxe2_tx_pkts_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+ return sxe2_tx_pkts_vec_avx2_common(tx_queue, tx_pkts, nb_pkts, true);
+}
+
+static inline void sxe2_rx_queue_rearm_avx2(struct sxe2_rx_queue *rxq)
+{
+ volatile union sxe2_rx_desc *desc;
+ struct rte_mbuf **buffer;
+ struct rte_mbuf *mbuf0, *mbuf1;
+ __m128i dma_addr0, dma_addr1;
+ __m128i virt_addr0, virt_addr1;
+ __m128i hdr_room = _mm_set_epi64x(RTE_PKTMBUF_HEADROOM, RTE_PKTMBUF_HEADROOM);
+ int32_t ret;
+ uint16_t i;
+ uint16_t new_tail;
+
+ buffer = &rxq->buffer_ring[rxq->realloc_start];
+ desc = &rxq->desc_ring[rxq->realloc_start];
+
+ ret = rte_mempool_get_bulk(rxq->mb_pool, (void *)buffer, SXE2_RX_REARM_THRESH_VEC);
+ if (ret != 0) {
+ if ((rxq->realloc_num + SXE2_RX_REARM_THRESH_VEC) >= rxq->ring_depth) {
+ dma_addr0 = _mm_setzero_si128();
+ for (i = 0; i < SXE2_RX_NUM_PER_LOOP_AVX; ++i) {
+ buffer[i] = &rxq->fake_mbuf;
+ _mm_store_si128(RTE_CAST_PTR(__m128i *, &desc[i].read), dma_addr0);
+ }
+ }
+
+ rxq->vsi->adapter->dev_info.dev_data->rx_mbuf_alloc_failed +=
+ SXE2_RX_REARM_THRESH_VEC;
+ return;
+ }
+
+ for (i = 0; i < SXE2_RX_REARM_THRESH_VEC; i += 2, buffer += 2) {
+ mbuf0 = buffer[0];
+ mbuf1 = buffer[1];
+#if RTE_IOVA_IN_MBUF
+
+ RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, buf_iova) !=
+ offsetof(struct rte_mbuf, buf_addr) + 8);
+#endif
+ virt_addr0 = _mm_loadu_si128((__m128i *)&mbuf0->buf_addr);
+ virt_addr1 = _mm_loadu_si128((__m128i *)&mbuf1->buf_addr);
+
+#if RTE_IOVA_IN_MBUF
+
+ dma_addr0 = _mm_unpackhi_epi64(virt_addr0, virt_addr0);
+ dma_addr1 = _mm_unpackhi_epi64(virt_addr1, virt_addr1);
+#else
+
+ dma_addr0 = _mm_unpacklo_epi64(virt_addr0, virt_addr0);
+ dma_addr1 = _mm_unpacklo_epi64(virt_addr1, virt_addr1);
+#endif
+
+ dma_addr0 = _mm_add_epi64(dma_addr0, hdr_room);
+ dma_addr1 = _mm_add_epi64(dma_addr1, hdr_room);
+
+ _mm_store_si128(RTE_CAST_PTR(__m128i *, &desc++->read), dma_addr0);
+ _mm_store_si128(RTE_CAST_PTR(__m128i *, &desc++->read), dma_addr1);
+ }
+
+ rxq->realloc_start += SXE2_RX_REARM_THRESH_VEC;
+ if (rxq->realloc_start >= rxq->ring_depth)
+ rxq->realloc_start = 0;
+ rxq->realloc_num -= SXE2_RX_REARM_THRESH_VEC;
+
+ new_tail = (rxq->realloc_start == 0) ?
+ (rxq->ring_depth - 1) : (rxq->realloc_start - 1);
+ SXE2_PCI_REG_WRITE_WC(rxq->rdt_reg_addr, new_tail);
+}
+
+static __rte_always_inline uint16_t
+sxe2_rx_pkts_common_vec_avx2(struct sxe2_rx_queue *rxq,
+ struct rte_mbuf **rx_pkts, uint16_t nb_pkts, uint8_t *split_rxe_flags,
+ uint8_t *umbcast_flags, bool do_offload)
+{
+ const uint32_t *ptype_tbl = rxq->vsi->adapter->ptype_tbl;
+ const __m256i mbuf_init = _mm256_set_epi64x(0, 0, 0, rxq->mbuf_init_value);
+ struct rte_mbuf **buffer;
+ volatile union sxe2_rx_desc *desc;
+ __m256i mbufs6_7, mbufs4_5, mbufs2_3, mbufs0_1;
+ uint32_t bit_num;
+ uint16_t done_num;
+ uint16_t i = 0;
+ uint16_t j = 0;
+
+ buffer = &rxq->buffer_ring[rxq->processing_idx];
+ desc = &rxq->desc_ring[rxq->processing_idx];
+ done_num = 0;
+
+ rte_prefetch0(desc);
+
+ nb_pkts = RTE_ALIGN_FLOOR(nb_pkts, SXE2_RX_NUM_PER_LOOP_AVX);
+
+ if (rxq->realloc_num > SXE2_RX_REARM_THRESH_VEC)
+ sxe2_rx_queue_rearm_avx2(rxq);
+
+ if (0 == (rte_le_to_cpu_64(desc->wb.status_err_ptype_len) &
+ SXE2_RX_DESC_STATUS_DD_MASK))
+ goto l_end;
+
+ const __m256i crc_adjust =
+ _mm256_set_epi16(0, 0, 0, -rxq->crc_len,
+ 0, -rxq->crc_len, 0,
+ 0, 0, 0, 0,
+ -rxq->crc_len, 0, -rxq->crc_len, 0, 0);
+
+ const __m256i dd_mask = _mm256_set1_epi32(1);
+ const __m256i rvp_shuf_mask =
+ _mm256_set_epi8(7, 6, 5, 4,
+ 3, 2, 13, 12,
+ 0xFF, 0xFF, 13, 12,
+ 0xFF, 0xFF, 0xFF, 0xFF,
+ 7, 6, 5, 4,
+ 3, 2, 13, 12,
+ 0xFF, 0xFF, 13, 12,
+ 0xFF, 0xFF, 0xFF, 0xFF);
+
+ const __m128i eop_shuf_mask =
+ _mm_set_epi8(0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF,
+ 8, 0, 10, 2,
+ 12, 4, 14, 6);
+
+ RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, pkt_len) !=
+ offsetof(struct rte_mbuf, rx_descriptor_fields1) + 4);
+ RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, data_len) !=
+ offsetof(struct rte_mbuf, rx_descriptor_fields1) + 8);
+ RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, vlan_tci) !=
+ offsetof(struct rte_mbuf, rx_descriptor_fields1) + 10);
+ RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, hash) !=
+ offsetof(struct rte_mbuf, rx_descriptor_fields1) + 12);
+
+ for (i = 0; i < nb_pkts; i += SXE2_RX_NUM_PER_LOOP_AVX,
+ desc += SXE2_RX_NUM_PER_LOOP_AVX) {
+ _mm256_storeu_si256((void *)&rx_pkts[i],
+ _mm256_loadu_si256((void *)&buffer[i]));
+#ifdef RTE_ARCH_X86_64
+ _mm256_storeu_si256((void *)&rx_pkts[i + 4],
+ _mm256_loadu_si256((void *)&buffer[i + 4]));
+#endif
+
+ const __m128i desc7 = _mm_loadu_si128(RTE_CAST_PTR(const __m128i *, desc + 7));
+ rte_compiler_barrier();
+ const __m128i desc6 = _mm_loadu_si128(RTE_CAST_PTR(const __m128i *, desc + 6));
+ rte_compiler_barrier();
+ const __m128i desc5 = _mm_loadu_si128(RTE_CAST_PTR(const __m128i *, desc + 5));
+ rte_compiler_barrier();
+ const __m128i desc4 = _mm_loadu_si128(RTE_CAST_PTR(const __m128i *, desc + 4));
+ rte_compiler_barrier();
+ const __m128i desc3 = _mm_loadu_si128(RTE_CAST_PTR(const __m128i *, desc + 3));
+ rte_compiler_barrier();
+ const __m128i desc2 = _mm_loadu_si128(RTE_CAST_PTR(const __m128i *, desc + 2));
+ rte_compiler_barrier();
+ const __m128i desc1 = _mm_loadu_si128(RTE_CAST_PTR(const __m128i *, desc + 1));
+ rte_compiler_barrier();
+ const __m128i desc0 = _mm_loadu_si128(RTE_CAST_PTR(const __m128i *, desc + 0));
+
+ const __m256i descs6_7 =
+ _mm256_inserti128_si256(_mm256_castsi128_si256(desc6), desc7, 1);
+ const __m256i descs4_5 =
+ _mm256_inserti128_si256(_mm256_castsi128_si256(desc4), desc5, 1);
+ const __m256i descs2_3 =
+ _mm256_inserti128_si256(_mm256_castsi128_si256(desc2), desc3, 1);
+ const __m256i descs0_1 =
+ _mm256_inserti128_si256(_mm256_castsi128_si256(desc0), desc1, 1);
+
+ if (split_rxe_flags) {
+ for (j = 0; j < SXE2_RX_NUM_PER_LOOP_AVX; j++)
+ rte_mbuf_prefetch_part2(rx_pkts[i + j]);
+ }
+
+ mbufs6_7 = _mm256_shuffle_epi8(descs6_7, rvp_shuf_mask);
+ mbufs4_5 = _mm256_shuffle_epi8(descs4_5, rvp_shuf_mask);
+
+ mbufs6_7 = _mm256_add_epi16(mbufs6_7, crc_adjust);
+ mbufs4_5 = _mm256_add_epi16(mbufs4_5, crc_adjust);
+
+ const __m256i ptype_mask = _mm256_set1_epi32(SXE2_RX_DESC_PTYPE_MASK);
+
+ const __m256i staterrs4_7 = _mm256_unpackhi_epi32(descs6_7, descs4_5);
+
+ __m256i ptypes4_7 = _mm256_and_si256(staterrs4_7, ptype_mask);
+
+ const uint16_t ptype7 = _mm256_extract_epi16(ptypes4_7, 9);
+ const uint16_t ptype6 = _mm256_extract_epi16(ptypes4_7, 1);
+ const uint16_t ptype5 = _mm256_extract_epi16(ptypes4_7, 11);
+ const uint16_t ptype4 = _mm256_extract_epi16(ptypes4_7, 3);
+
+ mbufs6_7 = _mm256_insert_epi32(mbufs6_7, ptype_tbl[ptype7], 4);
+ mbufs6_7 = _mm256_insert_epi32(mbufs6_7, ptype_tbl[ptype6], 0);
+ mbufs4_5 = _mm256_insert_epi32(mbufs4_5, ptype_tbl[ptype5], 4);
+ mbufs4_5 = _mm256_insert_epi32(mbufs4_5, ptype_tbl[ptype4], 0);
+
+ mbufs2_3 = _mm256_shuffle_epi8(descs2_3, rvp_shuf_mask);
+ mbufs0_1 = _mm256_shuffle_epi8(descs0_1, rvp_shuf_mask);
+
+ mbufs2_3 = _mm256_add_epi16(mbufs2_3, crc_adjust);
+ mbufs0_1 = _mm256_add_epi16(mbufs0_1, crc_adjust);
+
+ const __m256i staterrs0_3 = _mm256_unpackhi_epi32(descs2_3, descs0_1);
+
+ __m256i ptypes0_3 = _mm256_and_si256(staterrs0_3, ptype_mask);
+
+ const uint16_t ptype3 = _mm256_extract_epi16(ptypes0_3, 9);
+ const uint16_t ptype2 = _mm256_extract_epi16(ptypes0_3, 1);
+ const uint16_t ptype1 = _mm256_extract_epi16(ptypes0_3, 11);
+ const uint16_t ptype0 = _mm256_extract_epi16(ptypes0_3, 3);
+
+ mbufs2_3 = _mm256_insert_epi32(mbufs2_3, ptype_tbl[ptype3], 4);
+ mbufs2_3 = _mm256_insert_epi32(mbufs2_3, ptype_tbl[ptype2], 0);
+ mbufs0_1 = _mm256_insert_epi32(mbufs0_1, ptype_tbl[ptype1], 4);
+ mbufs0_1 = _mm256_insert_epi32(mbufs0_1, ptype_tbl[ptype0], 0);
+
+ __m256i staterrs0_7 = _mm256_unpacklo_epi64(staterrs4_7, staterrs0_3);
+
+ __m256i stu_len0_7 = _mm256_unpackhi_epi64(staterrs4_7, staterrs0_3);
+ __m256i mbuf_flags = _mm256_setzero_si256();
+
+ if (do_offload) {
+ const __m256i desc_flags_mask = _mm256_set1_epi32(0x00001C04);
+ const __m256i desc_flags_rss_mask = _mm256_set1_epi32(0x20000000);
+ const __m256i vlan_flags =
+ _mm256_set_epi8
+ (0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,
+ RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,
+ RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED,
+ 0, 0, 0, 0);
+
+ const __m256i rss_flags =
+ _mm256_set_epi8
+ (0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, RTE_MBUF_F_RX_RSS_HASH, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, RTE_MBUF_F_RX_RSS_HASH, 0, 0, 0, 0);
+
+ const __m256i cksum_flags =
+ _mm256_set_epi8
+ (0, 0, 0, 0, 0, 0, 0, 0,
+ ((RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD |
+ RTE_MBUF_F_RX_L4_CKSUM_BAD |
+ RTE_MBUF_F_RX_IP_CKSUM_BAD) >> 1),
+ ((RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD |
+ RTE_MBUF_F_RX_L4_CKSUM_BAD |
+ RTE_MBUF_F_RX_IP_CKSUM_GOOD) >> 1),
+ ((RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD |
+ RTE_MBUF_F_RX_L4_CKSUM_GOOD |
+ RTE_MBUF_F_RX_IP_CKSUM_BAD) >> 1),
+ ((RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD |
+ RTE_MBUF_F_RX_L4_CKSUM_GOOD |
+ RTE_MBUF_F_RX_IP_CKSUM_GOOD) >> 1),
+ ((RTE_MBUF_F_RX_L4_CKSUM_BAD |
+ RTE_MBUF_F_RX_IP_CKSUM_BAD) >> 1),
+ ((RTE_MBUF_F_RX_L4_CKSUM_BAD |
+ RTE_MBUF_F_RX_IP_CKSUM_GOOD) >> 1),
+ ((RTE_MBUF_F_RX_L4_CKSUM_GOOD |
+ RTE_MBUF_F_RX_IP_CKSUM_BAD) >> 1),
+ ((RTE_MBUF_F_RX_L4_CKSUM_GOOD |
+ RTE_MBUF_F_RX_IP_CKSUM_GOOD) >> 1),
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ ((RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD |
+ RTE_MBUF_F_RX_L4_CKSUM_BAD |
+ RTE_MBUF_F_RX_IP_CKSUM_BAD) >> 1),
+ ((RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD |
+ RTE_MBUF_F_RX_L4_CKSUM_BAD |
+ RTE_MBUF_F_RX_IP_CKSUM_GOOD) >> 1),
+ ((RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD |
+ RTE_MBUF_F_RX_L4_CKSUM_GOOD |
+ RTE_MBUF_F_RX_IP_CKSUM_BAD) >> 1),
+ ((RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD |
+ RTE_MBUF_F_RX_L4_CKSUM_GOOD |
+ RTE_MBUF_F_RX_IP_CKSUM_GOOD) >> 1),
+ ((RTE_MBUF_F_RX_L4_CKSUM_BAD |
+ RTE_MBUF_F_RX_IP_CKSUM_BAD) >> 1),
+ ((RTE_MBUF_F_RX_L4_CKSUM_BAD |
+ RTE_MBUF_F_RX_IP_CKSUM_GOOD) >> 1),
+ ((RTE_MBUF_F_RX_L4_CKSUM_GOOD |
+ RTE_MBUF_F_RX_IP_CKSUM_BAD) >> 1),
+ ((RTE_MBUF_F_RX_L4_CKSUM_GOOD |
+ RTE_MBUF_F_RX_IP_CKSUM_GOOD) >> 1));
+
+ const __m256i cksum_mask =
+ _mm256_set1_epi32
+ (RTE_MBUF_F_RX_IP_CKSUM_MASK |
+ RTE_MBUF_F_RX_L4_CKSUM_MASK |
+ RTE_MBUF_F_RX_OUTER_L4_CKSUM_MASK |
+ RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD);
+ const __m256i vlan_mask =
+ _mm256_set1_epi32
+ (RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED);
+
+ __m256i tmp_flags;
+ __m256i descs_flags = _mm256_and_si256(staterrs0_7, desc_flags_mask);
+ stu_len0_7 = _mm256_and_si256(stu_len0_7, desc_flags_rss_mask);
+
+ tmp_flags = _mm256_shuffle_epi8(vlan_flags, descs_flags);
+ mbuf_flags = _mm256_and_si256(tmp_flags, vlan_mask);
+
+ descs_flags = _mm256_srli_epi32(descs_flags, 10);
+ tmp_flags = _mm256_shuffle_epi8(cksum_flags, descs_flags);
+ tmp_flags = _mm256_slli_epi32(tmp_flags, 1);
+ tmp_flags = _mm256_and_si256(tmp_flags, cksum_mask);
+ mbuf_flags = _mm256_or_si256(mbuf_flags, tmp_flags);
+
+ descs_flags = _mm256_srli_epi32(stu_len0_7, 27);
+ tmp_flags = _mm256_shuffle_epi8(rss_flags, descs_flags);
+ mbuf_flags = _mm256_or_si256(mbuf_flags, tmp_flags);
+
+#ifndef RTE_LIBRTE_SXE2_16BYTE_RX_DESC
+
+ if (rxq->fnav_enable) {
+ __m256i fnav_vld0_3, fnav_vld4_7;
+ __m256i fnav_vld0_7;
+ __m256i v_zeros, v_ffff, v_u32_one;
+ const __m256i fdir_flags =
+ _mm256_set1_epi32
+ (RTE_MBUF_F_RX_FDIR | RTE_MBUF_F_RX_FDIR_ID);
+ fnav_vld0_3 = _mm256_unpacklo_epi32(descs2_3, descs0_1);
+ fnav_vld4_7 = _mm256_unpacklo_epi32(descs6_7, descs4_5);
+
+ fnav_vld0_7 = _mm256_unpacklo_epi64(fnav_vld4_7, fnav_vld0_3);
+
+ fnav_vld0_7 = _mm256_slli_epi32(fnav_vld0_7, 26);
+ fnav_vld0_7 = _mm256_srli_epi32(fnav_vld0_7, 31);
+
+ v_zeros = _mm256_setzero_si256();
+ v_ffff = _mm256_cmpeq_epi32(v_zeros, v_zeros);
+ v_u32_one = _mm256_srli_epi32(v_ffff, 31);
+
+ tmp_flags = _mm256_cmpeq_epi32(fnav_vld0_7, v_u32_one);
+
+ tmp_flags = _mm256_and_si256(tmp_flags, fdir_flags);
+
+ mbuf_flags = _mm256_or_si256(mbuf_flags, tmp_flags);
+
+ rx_pkts[i + 0]->hash.fdir.hi = desc[0].wb.fd_filter_id;
+ rx_pkts[i + 1]->hash.fdir.hi = desc[1].wb.fd_filter_id;
+ rx_pkts[i + 2]->hash.fdir.hi = desc[2].wb.fd_filter_id;
+ rx_pkts[i + 3]->hash.fdir.hi = desc[3].wb.fd_filter_id;
+ rx_pkts[i + 4]->hash.fdir.hi = desc[4].wb.fd_filter_id;
+ rx_pkts[i + 5]->hash.fdir.hi = desc[5].wb.fd_filter_id;
+ rx_pkts[i + 6]->hash.fdir.hi = desc[6].wb.fd_filter_id;
+ rx_pkts[i + 7]->hash.fdir.hi = desc[7].wb.fd_filter_id;
+ }
+#endif
+ }
+
+ RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, ol_flags) !=
+ offsetof(struct rte_mbuf, rearm_data) + 8);
+ RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, rx_descriptor_fields1) !=
+ offsetof(struct rte_mbuf, rearm_data) + 16);
+ RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, rearm_data) !=
+ RTE_ALIGN(offsetof(struct rte_mbuf, rearm_data), 16));
+
+ __m256i rearm_arr[8];
+
+ rearm_arr[6] = _mm256_blend_epi32(mbuf_init, _mm256_slli_si256(mbuf_flags, 8), 4);
+ rearm_arr[4] = _mm256_blend_epi32(mbuf_init, _mm256_slli_si256(mbuf_flags, 4), 4);
+ rearm_arr[2] = _mm256_blend_epi32(mbuf_init, mbuf_flags, 4);
+ rearm_arr[0] = _mm256_blend_epi32(mbuf_init, _mm256_srli_si256(mbuf_flags, 4), 4);
+
+ rearm_arr[6] = _mm256_permute2f128_si256(rearm_arr[6], mbufs6_7, 0x20);
+ rearm_arr[4] = _mm256_permute2f128_si256(rearm_arr[4], mbufs4_5, 0x20);
+ rearm_arr[2] = _mm256_permute2f128_si256(rearm_arr[2], mbufs2_3, 0x20);
+ rearm_arr[0] = _mm256_permute2f128_si256(rearm_arr[0], mbufs0_1, 0x20);
+
+ _mm256_storeu_si256((__m256i *)&rx_pkts[i + 6]->rearm_data, rearm_arr[6]);
+ _mm256_storeu_si256((__m256i *)&rx_pkts[i + 4]->rearm_data, rearm_arr[4]);
+ _mm256_storeu_si256((__m256i *)&rx_pkts[i + 2]->rearm_data, rearm_arr[2]);
+ _mm256_storeu_si256((__m256i *)&rx_pkts[i + 0]->rearm_data, rearm_arr[0]);
+
+ const __m256i tmp_mbuf_flags =
+ _mm256_castsi128_si256(_mm256_extracti128_si256(mbuf_flags, 1));
+
+ rearm_arr[7] =
+ _mm256_blend_epi32(mbuf_init, _mm256_slli_si256(tmp_mbuf_flags, 8), 4);
+ rearm_arr[5] =
+ _mm256_blend_epi32(mbuf_init, _mm256_slli_si256(tmp_mbuf_flags, 4), 4);
+ rearm_arr[3] =
+ _mm256_blend_epi32(mbuf_init, tmp_mbuf_flags, 4);
+ rearm_arr[1] =
+ _mm256_blend_epi32(mbuf_init, _mm256_srli_si256(tmp_mbuf_flags, 4), 4);
+
+ rearm_arr[7] = _mm256_blend_epi32(rearm_arr[7], mbufs6_7, 0XF0);
+ rearm_arr[5] = _mm256_blend_epi32(rearm_arr[5], mbufs4_5, 0XF0);
+ rearm_arr[3] = _mm256_blend_epi32(rearm_arr[3], mbufs2_3, 0XF0);
+ rearm_arr[1] = _mm256_blend_epi32(rearm_arr[1], mbufs0_1, 0XF0);
+
+ _mm256_storeu_si256((__m256i *)&rx_pkts[i + 7]->rearm_data, rearm_arr[7]);
+ _mm256_storeu_si256((__m256i *)&rx_pkts[i + 5]->rearm_data, rearm_arr[5]);
+ _mm256_storeu_si256((__m256i *)&rx_pkts[i + 3]->rearm_data, rearm_arr[3]);
+ _mm256_storeu_si256((__m256i *)&rx_pkts[i + 1]->rearm_data, rearm_arr[1]);
+
+ if (umbcast_flags != NULL) {
+ const __m256i umbcast_mask =
+ _mm256_set1_epi32(SXE2_RX_DESC_STATUS_UMBCAST_MASK);
+ __m256i umbcast_bits_256 = _mm256_and_si256(staterrs0_7,
+ umbcast_mask);
+
+ umbcast_bits_256 = _mm256_srli_epi32(umbcast_bits_256, 24);
+
+ __m128i umbcast_bits_128 = _mm_packs_epi32
+ (_mm256_castsi256_si128(umbcast_bits_256),
+ _mm256_extractf128_si256
+ (umbcast_bits_256, 1));
+
+ umbcast_bits_128 = _mm_shuffle_epi8(umbcast_bits_128, eop_shuf_mask);
+
+ *(uint64_t *)umbcast_flags = _mm_cvtsi128_si64(umbcast_bits_128);
+ umbcast_flags += SXE2_RX_NUM_PER_LOOP_AVX;
+ }
+
+ if (split_rxe_flags != NULL) {
+ const __m256i eop_rxe_mask = _mm256_set1_epi32
+ (SXE2_RX_DESC_STATUS_EOP_MASK |
+ SXE2_RX_DESC_ERROR_RXE_MASK |
+ SXE2_RX_DESC_ERROR_OVERSIZE_MASK);
+
+ const __m128i eop_mask_128 = _mm_set1_epi16(SXE2_RX_DESC_STATUS_EOP_MASK);
+ const __m128i rxe_mask_128 = _mm_set1_epi16(SXE2_RX_DESC_ERROR_RXE_MASK |
+ SXE2_RX_DESC_ERROR_OVERSIZE_MASK);
+
+ const __m256i tmp_stats = _mm256_and_si256(staterrs0_7, eop_rxe_mask);
+
+ const __m128i eop_rxe_bits = _mm_packs_epi32
+ (_mm256_castsi256_si128(tmp_stats),
+ _mm256_extractf128_si256(tmp_stats, 1));
+
+ __m128i not_eop_bits = _mm_andnot_si128(eop_rxe_bits, eop_mask_128);
+
+ not_eop_bits = _mm_or_si128
+ (not_eop_bits,
+ _mm_srli_epi16
+ (_mm_and_si128(eop_rxe_bits, rxe_mask_128),
+ 7));
+
+ not_eop_bits = _mm_shuffle_epi8(not_eop_bits, eop_shuf_mask);
+
+ *(uint64_t *)split_rxe_flags = _mm_cvtsi128_si64(not_eop_bits);
+ split_rxe_flags += SXE2_RX_NUM_PER_LOOP_AVX;
+ }
+
+ staterrs0_7 = _mm256_and_si256(staterrs0_7, dd_mask);
+
+ staterrs0_7 = _mm256_packs_epi32(staterrs0_7, _mm256_setzero_si256());
+ bit_num = rte_popcount64
+ (_mm_cvtsi128_si64(_mm256_extracti128_si256(staterrs0_7, 1)));
+ bit_num += rte_popcount64
+ (_mm_cvtsi128_si64(_mm256_castsi256_si128(staterrs0_7)));
+
+ done_num += bit_num;
+
+ if (bit_num != SXE2_RX_NUM_PER_LOOP_AVX)
+ break;
+ }
+
+ rxq->processing_idx += done_num;
+ rxq->processing_idx &= (rxq->ring_depth - 1);
+ if ((1 == (rxq->processing_idx & 1)) && done_num > 1) {
+ rxq->processing_idx--;
+ done_num--;
+ }
+ rxq->realloc_num += done_num;
+
+l_end:
+ PMD_LOG_DEBUG(RX, "port_id=%u queue_id=%u last_id=%u recv_pkts=%d",
+ rxq->port_id, rxq->queue_id, rxq->processing_idx, done_num);
+ return done_num;
+}
+
+static __rte_always_inline uint16_t
+sxe2_rx_pkts_scattered_batch_vec_avx2(struct sxe2_rx_queue *rxq, struct rte_mbuf **rx_pkts,
+ uint16_t nb_pkts, bool do_offload)
+{
+ const uint64_t *split_rxe_flags64;
+ uint8_t split_rxe_flags[SXE2_RX_PKTS_BURST_BATCH_NUM_VEC] = {0};
+ uint8_t umbcast_flags[SXE2_RX_PKTS_BURST_BATCH_NUM_VEC] = {0};
+ uint16_t rx_done_num;
+ uint16_t rx_pkt_done_num;
+
+ rx_pkt_done_num = 0;
+
+ if (rxq->vsi->adapter->devargs.sw_stats_en) {
+ rx_done_num = sxe2_rx_pkts_common_vec_avx2(rxq, rx_pkts, nb_pkts,
+ split_rxe_flags, umbcast_flags, do_offload);
+ } else {
+ rx_done_num = sxe2_rx_pkts_common_vec_avx2(rxq, rx_pkts, nb_pkts,
+ split_rxe_flags, NULL, do_offload);
+ }
+ if (rx_done_num == 0)
+ goto l_end;
+
+ if (!rxq->vsi->adapter->devargs.sw_stats_en) {
+ split_rxe_flags64 = (uint64_t *)split_rxe_flags;
+
+ if (rxq->pkt_first_seg == NULL &&
+ split_rxe_flags64[0] == 0 && split_rxe_flags64[1] == 0 &&
+ split_rxe_flags64[2] == 0 && split_rxe_flags64[3] == 0) {
+ rx_pkt_done_num = rx_done_num;
+ goto l_end;
+ }
+
+ if (rxq->pkt_first_seg == NULL) {
+ while (rx_pkt_done_num < rx_done_num &&
+ split_rxe_flags[rx_pkt_done_num] == 0)
+ rx_pkt_done_num++;
+
+ if (rx_pkt_done_num == rx_done_num)
+ goto l_end;
+
+ rxq->pkt_first_seg = rx_pkts[rx_pkt_done_num];
+ }
+ }
+
+ rx_pkt_done_num += sxe2_rx_pkts_refactor(rxq, &rx_pkts[rx_pkt_done_num],
+ rx_done_num - rx_pkt_done_num, &split_rxe_flags[rx_pkt_done_num],
+ &umbcast_flags[rx_pkt_done_num]);
+
+l_end:
+ return rx_pkt_done_num;
+}
+
+static __rte_always_inline uint16_t
+sxe2_rx_pkts_scattered_common_vec_avx2(struct sxe2_rx_queue *rxq, struct rte_mbuf **rx_pkts,
+ uint16_t nb_pkts, bool do_offload)
+{
+ uint16_t done_num = 0;
+ uint16_t once_num;
+
+ while (nb_pkts > SXE2_RX_PKTS_BURST_BATCH_NUM) {
+ once_num =
+ sxe2_rx_pkts_scattered_batch_vec_avx2(rxq,
+ rx_pkts + done_num,
+ SXE2_RX_PKTS_BURST_BATCH_NUM,
+ do_offload);
+ done_num += once_num;
+ nb_pkts -= once_num;
+ if (once_num < SXE2_RX_PKTS_BURST_BATCH_NUM)
+ goto l_end;
+ }
+
+ done_num += sxe2_rx_pkts_scattered_batch_vec_avx2(rxq,
+ rx_pkts + done_num, nb_pkts, do_offload);
+l_end:
+ return done_num;
+}
+
+uint16_t sxe2_rx_pkts_scattered_vec_avx2(void *rx_queue,
+ struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
+{
+ return sxe2_rx_pkts_scattered_common_vec_avx2(rx_queue,
+ rx_pkts, nb_pkts, false);
+}
+
+uint16_t sxe2_rx_pkts_scattered_vec_avx2_offload(void *rx_queue,
+ struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
+{
+ return sxe2_rx_pkts_scattered_common_vec_avx2(rx_queue,
+ rx_pkts, nb_pkts, true);
+}
--
2.52.0
^ permalink raw reply related
* [PATCH v2 04/20] net/sxe2: support L2 filtering and MAC config
From: liujie5 @ 2026-06-14 9:23 UTC (permalink / raw)
To: stephen; +Cc: dev, Jie Liu
In-Reply-To: <20260614092328.201826-1-liujie5@linkdatatechnology.com>
From: Jie Liu <liujie5@linkdatatechnology.com>
- Support primary/secondary MAC address setup.
- Enable L2 broadcast/multicast filter bits.
- Add multicast address update logic.
Signed-off-by: Jie Liu <liujie5@linkdatatechnology.com>
---
drivers/net/sxe2/meson.build | 1 +
drivers/net/sxe2/sxe2_cmd_chnl.c | 198 ++++++++
drivers/net/sxe2/sxe2_cmd_chnl.h | 17 +
drivers/net/sxe2/sxe2_drv_cmd.h | 87 ++++
drivers/net/sxe2/sxe2_ethdev.c | 70 ++-
drivers/net/sxe2/sxe2_ethdev.h | 43 +-
drivers/net/sxe2/sxe2_filter.c | 782 ++++++++++++++++++++++++++++++
drivers/net/sxe2/sxe2_filter.h | 98 ++++
drivers/net/sxe2/sxe2_mac.c | 432 +++++++++++++++++
drivers/net/sxe2/sxe2_mac.h | 34 ++
drivers/net/sxe2/sxe2_txrx_poll.c | 49 ++
11 files changed, 1805 insertions(+), 6 deletions(-)
create mode 100644 drivers/net/sxe2/sxe2_filter.c
create mode 100644 drivers/net/sxe2/sxe2_filter.h
diff --git a/drivers/net/sxe2/meson.build b/drivers/net/sxe2/meson.build
index b14b5120c1..b661e3cbf4 100644
--- a/drivers/net/sxe2/meson.build
+++ b/drivers/net/sxe2/meson.build
@@ -61,4 +61,5 @@ sources += files(
'sxe2_txrx.c',
'sxe2_txrx_vec.c',
'sxe2_mac.c',
+ 'sxe2_filter.c',
)
diff --git a/drivers/net/sxe2/sxe2_cmd_chnl.c b/drivers/net/sxe2/sxe2_cmd_chnl.c
index 07eeb7f38c..1fa9ad718e 100644
--- a/drivers/net/sxe2/sxe2_cmd_chnl.c
+++ b/drivers/net/sxe2/sxe2_cmd_chnl.c
@@ -343,3 +343,201 @@ int32_t sxe2_drv_mac_link_status_get(struct sxe2_adapter *adapter)
l_end:
return ret;
}
+
+int32_t sxe2_drv_promisc_config(struct sxe2_adapter *adapter, bool set)
+{
+ int32_t ret = 0;
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_promisc_filter_cfg_req promisc_filter_cfg_req = {0};
+
+ promisc_filter_cfg_req.vsi_id = adapter->vsi_ctxt.dpdk_vsi_id;
+ promisc_filter_cfg_req.is_add = set;
+ promisc_filter_cfg_req.type = SXE2_PROMISC_FILTER_TYPE_PROMISC;
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_PROMISC_CFG,
+ &promisc_filter_cfg_req,
+ sizeof(promisc_filter_cfg_req),
+ NULL, 0);
+
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret)
+ PMD_DEV_LOG_WARN(adapter, DRV, "promic config failed, ret=%d", ret);
+
+ return ret;
+}
+
+int32_t sxe2_drv_allmulti_config(struct sxe2_adapter *adapter, bool set)
+{
+ int32_t ret = 0;
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_promisc_filter_cfg_req promisc_filter_cfg_req = {0};
+
+ promisc_filter_cfg_req.vsi_id = adapter->vsi_ctxt.dpdk_vsi_id;
+ promisc_filter_cfg_req.is_add = set;
+ promisc_filter_cfg_req.type = SXE2_PROMISC_FILTER_TYPE_ALLMULTI;
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_ALLMULTI_CFG,
+ &promisc_filter_cfg_req,
+ sizeof(promisc_filter_cfg_req),
+ NULL, 0);
+
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret)
+ PMD_DEV_LOG_WARN(adapter, DRV, "allmulti config failed, ret=%d", ret);
+
+ return ret;
+}
+
+int32_t sxe2_drv_uc_config(struct sxe2_adapter *adapter, struct rte_ether_addr *addr, bool add)
+{
+ int32_t ret = 0;
+ int32_t i;
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_mac_filter_cfg_req mac_filter_cfg_req = {0};
+
+ mac_filter_cfg_req.vsi_id = adapter->vsi_ctxt.dpdk_vsi_id;
+ for (i = 0; i < SXE2_ETH_ALEN; i++)
+ mac_filter_cfg_req.addr[i] = addr->addr_bytes[i];
+ mac_filter_cfg_req.is_add = add;
+ mac_filter_cfg_req.type = SXE2_MAC_FILTER_TYPE_UC;
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_MAC_ADDR_UC,
+ &mac_filter_cfg_req, sizeof(mac_filter_cfg_req),
+ NULL, 0);
+
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret)
+ PMD_DEV_LOG_WARN(adapter, DRV, "uc config query failed, ret=%d", ret);
+
+ return ret;
+}
+
+int32_t sxe2_drv_mc_config(struct sxe2_adapter *adapter, struct rte_ether_addr *addr, bool add)
+{
+ int32_t ret = 0;
+ int32_t i;
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_mac_filter_cfg_req mac_filter_cfg_req = {0};
+
+ mac_filter_cfg_req.vsi_id = adapter->vsi_ctxt.dpdk_vsi_id;
+ for (i = 0; i < SXE2_ETH_ALEN; i++)
+ mac_filter_cfg_req.addr[i] = addr->addr_bytes[i];
+
+ mac_filter_cfg_req.is_add = add;
+ mac_filter_cfg_req.type = SXE2_MAC_FILTER_TYPE_MC;
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_MAC_ADDR_MC,
+ &mac_filter_cfg_req, sizeof(mac_filter_cfg_req),
+ NULL, 0);
+
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret)
+ PMD_DEV_LOG_WARN(adapter, DRV, "mac config query failed, ret=%d", ret);
+
+ return ret;
+}
+
+int32_t sxe2_drv_vlan_config_query(struct sxe2_adapter *adapter)
+{
+ int32_t ret = 0;
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_drv_vlan_cfg_query_resp vlan_cfg_query_resp = {0};
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_VLAN_CFG_QUERY,
+ NULL, 0,
+ &vlan_cfg_query_resp,
+ sizeof(vlan_cfg_query_resp));
+
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret)
+ PMD_DEV_LOG_WARN(adapter, DRV, "vlan config query failed, ret=%d", ret);
+
+ adapter->filter_ctxt.vlan_info.port_vlan_exist = vlan_cfg_query_resp.port_vlan_exist;
+ adapter->filter_ctxt.vlan_info.is_switchdev = vlan_cfg_query_resp.is_switchdev;
+
+
+ adapter->filter_ctxt.vlan_info.tpid = vlan_cfg_query_resp.tpid;
+ adapter->filter_ctxt.vlan_info.vid = vlan_cfg_query_resp.vid;
+
+ adapter->filter_ctxt.vlan_info.outer_insert = vlan_cfg_query_resp.outer_insert;
+ adapter->filter_ctxt.vlan_info.outer_strip = vlan_cfg_query_resp.outer_strip;
+ adapter->filter_ctxt.vlan_info.inner_insert = vlan_cfg_query_resp.inner_insert;
+ adapter->filter_ctxt.vlan_info.inner_strip = vlan_cfg_query_resp.inner_strip;
+
+ return ret;
+}
+
+int32_t sxe2_drv_vlan_filter_id_config(struct sxe2_adapter *adapter,
+ struct sxe2_vlan *vlan, bool on)
+{
+ int32_t ret = 0;
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_vlan_filter_cfg_req vlan_filter_cfg_req = {0};
+
+ vlan_filter_cfg_req.vsi_id = adapter->vsi_ctxt.dpdk_vsi_id;
+ vlan_filter_cfg_req.tpid_id = vlan->tpid;
+ vlan_filter_cfg_req.vlan_id = vlan->vid;
+ vlan_filter_cfg_req.prio = vlan->prio;
+ vlan_filter_cfg_req.is_add = on;
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_VLAN_FILTER_ADD_DEL,
+ &vlan_filter_cfg_req, sizeof(vlan_filter_cfg_req),
+ NULL, 0);
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret)
+ PMD_DEV_LOG_WARN(adapter, DRV, "vlan config failed, ret=%d", ret);
+
+ return ret;
+}
+
+int32_t sxe2_drv_vlan_insert_strip_cfg(struct sxe2_adapter *adapter)
+{
+ int32_t ret = 0;
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_drv_vlan_offload_cfg_req vlan_offload_cfg_req = {0};
+
+ vlan_offload_cfg_req.vsi_id = adapter->vsi_ctxt.dpdk_vsi_id;
+ vlan_offload_cfg_req.tpid = adapter->filter_ctxt.vlan_info.tpid;
+ vlan_offload_cfg_req.outer_insert = adapter->filter_ctxt.vlan_info.outer_insert;
+ vlan_offload_cfg_req.outer_strip = adapter->filter_ctxt.vlan_info.outer_strip;
+ vlan_offload_cfg_req.inner_insert = adapter->filter_ctxt.vlan_info.inner_insert;
+ vlan_offload_cfg_req.inner_strip = adapter->filter_ctxt.vlan_info.inner_strip;
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_VLAN_OFFLOAD_CFG,
+ &vlan_offload_cfg_req,
+ sizeof(vlan_offload_cfg_req),
+ NULL, 0);
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret)
+ PMD_DEV_LOG_WARN(adapter, DRV, "vlan config query failed, ret=%d", ret);
+
+ return ret;
+}
+
+int32_t sxe2_drv_vlan_filter_switch(struct sxe2_adapter *adapter, bool on)
+{
+ int32_t ret = 0;
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_vlan_filter_switch_req vlan_filter_switch_req = {0};
+
+ vlan_filter_switch_req.vsi_id = adapter->vsi_ctxt.dpdk_vsi_id;
+ vlan_filter_switch_req.is_oper_enable = on;
+
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_VLAN_FILTER_SWITCH,
+ &vlan_filter_switch_req,
+ sizeof(vlan_filter_switch_req),
+ NULL, 0);
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret)
+ PMD_DEV_LOG_WARN(adapter, DRV, "vlan config filter failed, ret=%d", ret);
+
+ return ret;
+}
diff --git a/drivers/net/sxe2/sxe2_cmd_chnl.h b/drivers/net/sxe2/sxe2_cmd_chnl.h
index cda676ed97..c93bc2b0c9 100644
--- a/drivers/net/sxe2/sxe2_cmd_chnl.h
+++ b/drivers/net/sxe2/sxe2_cmd_chnl.h
@@ -36,4 +36,21 @@ int32_t sxe2_drv_txq_ctxt_cfg(struct sxe2_adapter *adapter,
int32_t sxe2_drv_mac_link_status_get(struct sxe2_adapter *adapter);
+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);
+
+int32_t sxe2_drv_mc_config(struct sxe2_adapter *adapter, struct rte_ether_addr *addr, bool add);
+
+int32_t sxe2_drv_vlan_config_query(struct sxe2_adapter *adapter);
+
+int32_t sxe2_drv_vlan_filter_id_config(struct sxe2_adapter *adapter,
+ struct sxe2_vlan *vlan, bool on);
+
+int32_t sxe2_drv_vlan_insert_strip_cfg(struct sxe2_adapter *adapter);
+
+int32_t sxe2_drv_vlan_filter_switch(struct sxe2_adapter *adapter, bool on);
+
#endif /* SXE2_CMD_CHNL_H */
diff --git a/drivers/net/sxe2/sxe2_drv_cmd.h b/drivers/net/sxe2/sxe2_drv_cmd.h
index a0f08b5184..d69d650148 100644
--- a/drivers/net/sxe2/sxe2_drv_cmd.h
+++ b/drivers/net/sxe2/sxe2_drv_cmd.h
@@ -233,6 +233,93 @@ struct __rte_aligned(4) __rte_packed_begin sxe2_drv_link_info_resp {
uint8_t rsv[3];
} __rte_packed_end;
+struct __rte_aligned(4) __rte_packed_begin sxe2_switchdev_info {
+ uint8_t is_switchdev;
+ uint8_t primary;
+ uint8_t representor;
+ uint8_t port_name_type;
+ uint32_t ctrl_num;
+ uint32_t pf_num;
+ uint32_t vf_num;
+ uint32_t mpesw_owner;
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_vlan_cfg_query_resp {
+ uint16_t vsi_id;
+ uint8_t port_vlan_exist;
+ uint8_t is_switchdev;
+ uint16_t tpid;
+ uint16_t vid;
+ uint8_t outer_insert;
+ uint8_t outer_strip;
+ uint8_t inner_insert;
+ uint8_t inner_strip;
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_vlan_offload_cfg_req {
+ uint16_t vsi_id;
+ uint16_t tpid;
+ uint8_t outer_insert;
+ uint8_t outer_strip;
+ uint8_t inner_insert;
+ uint8_t inner_strip;
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_port_vlan_cfg_req {
+ uint16_t vsi_id;
+ uint16_t tpid;
+ uint16_t vid;
+ uint8_t prio;
+ uint8_t rsv;
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_mac_filter_cfg_req {
+ uint16_t vsi_id;
+ uint8_t addr[SXE2_ETH_ALEN];
+ uint8_t type;
+ uint8_t is_add;
+ uint8_t rsv[2];
+} __rte_packed_end;
+
+enum sxe2_promisc_filter_type {
+ SXE2_PROMISC_FILTER_TYPE_PROMISC = 0,
+ SXE2_PROMISC_FILTER_TYPE_ALLMULTI,
+ SXE2_PROMISC_FILTER_TYPE_MAX,
+};
+
+enum sxe2_mac_filter_type {
+ SXE2_MAC_FILTER_TYPE_UC = 0,
+ SXE2_MAC_FILTER_TYPE_MC,
+ SXE2_MAC_FILTER_TYPE_MAX,
+};
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_promisc_filter_cfg_req {
+ uint16_t vsi_id;
+ uint8_t type;
+ uint8_t is_add;
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_srcvsi_ext_cfg_req {
+ uint16_t vsi_id;
+ uint16_t srcvsi_list[SXE2_SRCVSI_PRUNE_MAX_NUM];
+ uint8_t srcvsi_cnt;
+ uint8_t is_add;
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_vlan_filter_cfg_req {
+ uint16_t vsi_id;
+ uint16_t vlan_id;
+ uint16_t tpid_id;
+ uint8_t prio;
+ uint8_t is_add;
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_vlan_filter_switch_req {
+ uint16_t vsi_id;
+ uint8_t is_oper_enable;
+ uint8_t rsv;
+} __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 80881595d6..4ffe32d353 100644
--- a/drivers/net/sxe2/sxe2_ethdev.c
+++ b/drivers/net/sxe2/sxe2_ethdev.c
@@ -111,8 +111,20 @@ static const struct eth_dev_ops sxe2_eth_dev_ops = {
.tx_burst_mode_get = sxe2_tx_burst_mode_get,
.tx_done_cleanup = sxe2_tx_done_cleanup,
+ .promiscuous_enable = sxe2_promisc_enable,
+ .promiscuous_disable = sxe2_promisc_disable,
+ .allmulticast_enable = sxe2_allmulti_enable,
+ .allmulticast_disable = sxe2_allmulti_disable,
+
+ .mac_addr_add = sxe2_mac_addr_add,
+ .mac_addr_remove = sxe2_mac_addr_del,
+ .mac_addr_set = sxe2_mac_addr_set,
+ .set_mc_addr_list = sxe2_set_mc_addr_list,
.mtu_set = sxe2_mtu_set,
.buffer_split_supported_hdr_ptypes_get = sxe2_buffer_split_supported_hdr_ptypes_get,
+
+ .vlan_filter_set = sxe2_dev_vlan_filter_set,
+ .vlan_offload_set = sxe2_dev_vlan_offload_set,
};
static int32_t sxe2_dev_configure(struct rte_eth_dev *dev)
@@ -123,6 +135,13 @@ static int32_t sxe2_dev_configure(struct rte_eth_dev *dev)
if (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG)
dev->data->dev_conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
+ ret = sxe2_vlan_default_cfg(dev);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to init vlan, ret=%d", ret);
+ goto end;
+ }
+
+end:
return ret;
}
@@ -138,6 +157,8 @@ static int32_t sxe2_dev_stop(struct rte_eth_dev *dev)
sxe2_txqs_all_stop(dev);
sxe2_rxqs_all_stop(dev);
+ (void)sxe2_filter_rule_stop(dev);
+
dev->data->dev_started = 0;
adapter->started = 0;
l_end:
@@ -165,16 +186,23 @@ static int32_t sxe2_dev_start(struct rte_eth_dev *dev)
goto l_end;
}
+ ret = sxe2_filter_rule_start(dev);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to add all mc addr to fw.");
+ goto l_end;
+ }
+
ret = sxe2_queues_start(dev);
if (ret) {
PMD_LOG_ERR(INIT, "enable queues failed");
- goto l_end;
+ goto l_start_queues_err;
}
dev->data->dev_started = 1;
adapter->started = 1;
goto l_end;
-
+l_start_queues_err:
+ (void)sxe2_filter_rule_stop(dev);
l_end:
return ret;
}
@@ -194,6 +222,7 @@ static int32_t sxe2_dev_infos_get(struct rte_eth_dev *dev,
dev_info->min_mtu = RTE_ETHER_MIN_MTU;
dev_info->rx_offload_capa =
+ RTE_ETH_RX_OFFLOAD_VLAN_STRIP |
RTE_ETH_RX_OFFLOAD_KEEP_CRC |
RTE_ETH_RX_OFFLOAD_SCATTER |
RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
@@ -202,9 +231,15 @@ static int32_t sxe2_dev_infos_get(struct rte_eth_dev *dev,
RTE_ETH_RX_OFFLOAD_SCTP_CKSUM |
RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM |
RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT |
+#ifndef RTE_LIBRTE_SXE2_16BYTE_RX_DESC
+ RTE_ETH_RX_OFFLOAD_QINQ_STRIP |
+#endif
+ RTE_ETH_RX_OFFLOAD_VLAN_EXTEND |
RTE_ETH_RX_OFFLOAD_TCP_LRO;
dev_info->tx_offload_capa =
+ RTE_ETH_TX_OFFLOAD_VLAN_INSERT |
+ RTE_ETH_TX_OFFLOAD_QINQ_INSERT |
RTE_ETH_TX_OFFLOAD_MULTI_SEGS |
RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE |
RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
@@ -428,6 +463,12 @@ static int32_t sxe2_eth_init(struct rte_eth_dev *dev)
{
int32_t ret = 0;
+ ret = sxe2_filter_init(dev);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to initialize l2 filter, ret:%d", ret);
+ goto l_end;
+ }
+
ret = sxe2_link_update_init(dev);
if (ret) {
PMD_LOG_ERR(INIT, "Failed to initialize link update, ret:%d", ret);
@@ -439,12 +480,37 @@ static int32_t sxe2_eth_init(struct rte_eth_dev *dev)
PMD_LOG_ERR(INIT, "Failed to set mtu, ret=%d", ret);
goto l_end;
}
+
+ ret = sxe2_mac_addr_init(dev);
+ if (ret != 0) {
+ PMD_LOG_ERR(INIT, "Failed to initialize mac address, ret:%d", ret);
+ goto l_end;
+ }
+
+ ret = sxe2_mac_default_cfg(dev);
+ if (ret != 0) {
+ PMD_LOG_ERR(INIT, "Failed to configure default mac address, ret:%d", ret);
+ goto l_err;
+ }
+
+ ret = sxe2_vlan_cfg_init(dev);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to initialize vlan config, ret:%d", ret);
+ goto l_err;
+ }
+ goto l_end;
+
+l_err:
+ sxe2_mac_addr_uinit(dev);
+ (void)sxe2_filter_uinit(dev);
l_end:
return ret;
}
static void sxe2_eth_uinit(struct rte_eth_dev *dev __rte_unused)
{
+ sxe2_mac_addr_uinit(dev);
+ (void)sxe2_filter_uinit(dev);
}
static void sxe2_drv_dev_caps_set(struct sxe2_adapter *adapter,
diff --git a/drivers/net/sxe2/sxe2_ethdev.h b/drivers/net/sxe2/sxe2_ethdev.h
index 9de47d8338..fa3c69d360 100644
--- a/drivers/net/sxe2/sxe2_ethdev.h
+++ b/drivers/net/sxe2/sxe2_ethdev.h
@@ -15,9 +15,11 @@
#include "sxe2_common.h"
#include "sxe2_vsi.h"
-#include "sxe2_queue.h"
#include "sxe2_irq.h"
+#include "sxe2_queue.h"
+#include "sxe2_mac.h"
#include "sxe2_osal.h"
+#include "sxe2_filter.h"
struct sxe2_link_msg {
uint32_t speed;
@@ -35,7 +37,7 @@ enum sxe2_fnav_tunnel_flag_type {
#define SXE2_FRAME_SIZE_MAX 9832
#define SXE2_VLAN_TAG_SIZE 4
#define SXE2_ETH_OVERHEAD \
- (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN + SXE2_VLAN_TAG_SIZE)
+ (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN + 2 * SXE2_VLAN_TAG_SIZE)
#define SXE2_ETH_MAX_LEN (RTE_ETHER_MTU + SXE2_ETH_OVERHEAD)
#ifdef SXE2_TEST
@@ -267,6 +269,27 @@ struct sxe2_link_context {
uint32_t speed;
};
+struct sxe2_filter_context {
+ rte_spinlock_t filter_lock;
+ struct sxe2_vlan_info vlan_info;
+ struct sxe2_uc_filter_list_head uc_list;
+ struct sxe2_mc_filter_list_head mc_list;
+ struct sxe2_vlan_filter_list_head vlan_list;
+ uint8_t uc_num;
+ uint8_t mc_num;
+ uint8_t vlan_num;
+ uint8_t rsv;
+ uint32_t hw_promisc_flags;
+ uint32_t cur_promisc_flags;
+
+ bool hw_uplink_config;
+ bool cur_uplink_config;
+ bool hw_repr_config;
+ bool cur_repr_config;
+ bool hw_l2_config;
+ bool cur_l2_config;
+};
+
struct sxe2_adapter {
struct sxe2_common_device *cdev;
struct sxe2_dev_info dev_info;
@@ -276,10 +299,14 @@ struct sxe2_adapter {
struct sxe2_irq_context irq_ctxt;
struct sxe2_queue_context q_ctxt;
struct sxe2_vsi_context vsi_ctxt;
+ struct sxe2_filter_context filter_ctxt;
struct sxe2_link_context link_ctxt;
struct sxe2_devargs devargs;
- uint16_t dev_port_id;
- uint64_t cap_flags;
+ struct sxe2_switchdev_info switchdev_info;
+ bool rule_started;
+ bool flow_isolated;
+ uint16_t dev_port_id;
+ uint64_t cap_flags;
enum sxe2_dev_type dev_type;
uint32_t ptype_tbl[SXE2_MAX_PTYPE_NUM];
struct rte_ether_addr mac_addr;
@@ -315,4 +342,12 @@ int32_t sxe2_dev_pci_map_init(struct rte_eth_dev *dev);
void sxe2_dev_pci_map_uinit(struct rte_eth_dev *dev);
+static inline bool
+sxe2_dev_port_vlan_check(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *ad = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+
+ return ad->filter_ctxt.vlan_info.port_vlan_exist;
+}
+
#endif /* SXE2_ETHDEV_H */
diff --git a/drivers/net/sxe2/sxe2_filter.c b/drivers/net/sxe2/sxe2_filter.c
new file mode 100644
index 0000000000..b2a726f77e
--- /dev/null
+++ b/drivers/net/sxe2/sxe2_filter.c
@@ -0,0 +1,782 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#include <rte_os.h>
+#include <rte_tailq.h>
+#include "sxe2_osal.h"
+#include "sxe2_mac.h"
+#include "sxe2_common_log.h"
+#include "sxe2_ethdev.h"
+#include "sxe2_cmd_chnl.h"
+
+static struct sxe2_mac_filter *sxe2_uc_filter_find(struct sxe2_adapter *adapter,
+ struct rte_ether_addr *macaddr)
+{
+ struct sxe2_mac_filter *filter = NULL;
+ struct sxe2_mac_filter *entry = NULL;
+ struct sxe2_mac_filter *next_entry = NULL;
+
+ rte_spinlock_lock(&adapter->filter_ctxt.filter_lock);
+ RTE_TAILQ_FOREACH_SAFE(entry, &adapter->filter_ctxt.uc_list, next, next_entry) {
+ if (rte_is_same_ether_addr(macaddr, &entry->mac_addr)) {
+ filter = entry;
+ break;
+ }
+ }
+ rte_spinlock_unlock(&adapter->filter_ctxt.filter_lock);
+
+ return filter;
+}
+
+int32_t sxe2_uc_filter_add(struct sxe2_adapter *adapter,
+ struct rte_ether_addr *mac_addr, bool default_config)
+{
+ struct sxe2_mac_filter *filter = NULL;
+ bool hw_config = false;
+ int32_t ret = 0;
+
+ filter = sxe2_uc_filter_find(adapter, mac_addr);
+ if (filter) {
+ if (default_config && !filter->default_config)
+ filter->default_config = true;
+ PMD_DEV_LOG_INFO(adapter, DRV, "This MAC filter already exists.");
+ goto l_end;
+ }
+
+ if (!adapter->rule_started) {
+ PMD_DEV_LOG_DEBUG(adapter, DRV, "cannot add hw uc addr in port stop status");
+ } else if (adapter->flow_isolated) {
+ PMD_DEV_LOG_WARN(adapter, DRV, "cannot add hw uc addr in flow isolation mode");
+ } else if (adapter->switchdev_info.is_switchdev) {
+ PMD_DEV_LOG_WARN(adapter, DRV, "cannot add hw uc addr in switchdev mode");
+ } else {
+ ret = sxe2_drv_uc_config(adapter, mac_addr, true);
+ if (ret && ret != -EEXIST) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to add uc rule");
+ ret = -EINVAL;
+ goto l_end;
+ }
+ hw_config = true;
+ }
+
+ filter = rte_zmalloc("sxe2_uc_filter",
+ sizeof(struct sxe2_mac_filter), 0);
+ if (!filter) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to allocate memory");
+ ret = -ENOMEM;
+ goto l_end;
+ }
+ filter->hw_config = hw_config;
+ filter->default_config = default_config;
+ rte_ether_addr_copy(mac_addr, &filter->mac_addr);
+ rte_spinlock_lock(&adapter->filter_ctxt.filter_lock);
+ TAILQ_INSERT_TAIL(&adapter->filter_ctxt.uc_list, filter, next);
+ adapter->filter_ctxt.uc_num++;
+ rte_spinlock_unlock(&adapter->filter_ctxt.filter_lock);
+
+ PMD_DEV_LOG_INFO(adapter, DRV, "add mac rule, mac num %u.", adapter->filter_ctxt.uc_num);
+ ret = 0;
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_uc_filter_del(struct sxe2_adapter *adapter,
+ struct rte_ether_addr *mac_addr)
+{
+ struct sxe2_mac_filter *filter = NULL;
+ int32_t ret = -1;
+
+ filter = sxe2_uc_filter_find(adapter, mac_addr);
+ if (!filter) {
+ PMD_DEV_LOG_INFO(adapter, DRV, "This MAC filter not exists.");
+ ret = 0;
+ goto l_end;
+ }
+ if (filter->hw_config) {
+ ret = sxe2_drv_uc_config(adapter, mac_addr, false);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to delete mac rule");
+ if (ret == -EPERM)
+ goto l_free;
+ ret = -EINVAL;
+ goto l_end;
+ }
+ }
+ PMD_DEV_LOG_INFO(adapter, DRV, "remove mac rule, uc num %u.", adapter->filter_ctxt.uc_num);
+ ret = 0;
+
+l_free:
+
+ rte_spinlock_lock(&adapter->filter_ctxt.filter_lock);
+ TAILQ_REMOVE(&adapter->filter_ctxt.uc_list, filter, next);
+ adapter->filter_ctxt.uc_num--;
+ rte_spinlock_unlock(&adapter->filter_ctxt.filter_lock);
+ rte_free(filter);
+ filter = NULL;
+l_end:
+ return ret;
+}
+
+void sxe2_uc_filter_clear(struct sxe2_adapter *adapter, bool default_config)
+{
+ struct sxe2_mac_filter *entry;
+ struct sxe2_mac_filter *next_entry;
+
+ RTE_TAILQ_FOREACH_SAFE(entry, &adapter->filter_ctxt.uc_list, next, next_entry) {
+ if (entry->default_config && !default_config)
+ continue;
+
+ if (sxe2_uc_filter_del(adapter, &entry->mac_addr))
+ PMD_DEV_LOG_ERR(adapter, DRV, "This MAC filter delete fail.");
+ }
+}
+
+static struct sxe2_mac_filter *sxe2_mc_filter_find(struct sxe2_adapter *adapter,
+ struct rte_ether_addr *macaddr)
+{
+ struct sxe2_mac_filter *filter = NULL;
+ struct sxe2_mac_filter *entry = NULL;
+ struct sxe2_mac_filter *next_entry = NULL;
+
+ rte_spinlock_lock(&adapter->filter_ctxt.filter_lock);
+ RTE_TAILQ_FOREACH_SAFE(entry, &adapter->filter_ctxt.mc_list, next, next_entry) {
+ if (rte_is_same_ether_addr(macaddr, &entry->mac_addr)) {
+ filter = entry;
+ break;
+ }
+ }
+ rte_spinlock_unlock(&adapter->filter_ctxt.filter_lock);
+
+ return filter;
+}
+
+int32_t sxe2_mc_filter_add(struct sxe2_adapter *adapter,
+ struct rte_ether_addr *mac_addr, bool default_config)
+{
+ struct sxe2_mac_filter *filter = NULL;
+ bool hw_config = false;
+ int32_t ret = 0;
+
+ filter = sxe2_mc_filter_find(adapter, mac_addr);
+ if (filter) {
+ if (default_config && !filter->default_config)
+ filter->default_config = true;
+ PMD_DEV_LOG_INFO(adapter, DRV, "This MAC filter already exists.");
+ goto l_end;
+ }
+
+ if (!adapter->rule_started) {
+ PMD_DEV_LOG_DEBUG(adapter, DRV, "cannot add hw mc addr in port stop status");
+ } else if (adapter->flow_isolated) {
+ PMD_DEV_LOG_WARN(adapter, DRV, "cannot add hw mc addr in flow isolation mode");
+ } else if (adapter->switchdev_info.is_switchdev) {
+ PMD_DEV_LOG_WARN(adapter, DRV, "cannot add hw mc addr in switchdev mode");
+ } else {
+ ret = sxe2_drv_mc_config(adapter, mac_addr, true);
+ if (ret && ret != -EEXIST) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to add mac rule");
+ ret = -EINVAL;
+ goto l_end;
+ }
+ hw_config = true;
+ }
+
+ filter = rte_zmalloc("sxe2_mc_filter",
+ sizeof(struct sxe2_mac_filter), 0);
+ if (!filter) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to allocate memory");
+ ret = -ENOMEM;
+ goto l_end;
+ }
+ filter->hw_config = hw_config;
+ filter->default_config = default_config;
+ rte_ether_addr_copy(mac_addr, &filter->mac_addr);
+ rte_spinlock_lock(&adapter->filter_ctxt.filter_lock);
+ TAILQ_INSERT_TAIL(&adapter->filter_ctxt.mc_list, filter, next);
+ adapter->filter_ctxt.mc_num++;
+ rte_spinlock_unlock(&adapter->filter_ctxt.filter_lock);
+
+ PMD_DEV_LOG_INFO(adapter, DRV, "add mc rule, mc num %u.", adapter->filter_ctxt.mc_num);
+ ret = 0;
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_mc_filter_del(struct sxe2_adapter *adapter,
+ struct rte_ether_addr *mac_addr)
+{
+ struct sxe2_mac_filter *filter = NULL;
+ int32_t ret = -1;
+
+ filter = sxe2_mc_filter_find(adapter, mac_addr);
+ if (!filter) {
+ PMD_DEV_LOG_INFO(adapter, DRV, "This MAC filter not exists.");
+ ret = 0;
+ goto l_end;
+ }
+
+ if (filter->hw_config) {
+ ret = sxe2_drv_mc_config(adapter, mac_addr, false);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to delete mc rule");
+ if (ret == -EPERM)
+ goto l_free;
+ ret = -EINVAL;
+ goto l_end;
+ }
+ }
+ PMD_DEV_LOG_INFO(adapter, DRV, "remove mc rule, mc num %u.", adapter->filter_ctxt.mc_num);
+ ret = 0;
+
+l_free:
+
+ rte_spinlock_lock(&adapter->filter_ctxt.filter_lock);
+ TAILQ_REMOVE(&adapter->filter_ctxt.mc_list, filter, next);
+ adapter->filter_ctxt.mc_num--;
+ rte_spinlock_unlock(&adapter->filter_ctxt.filter_lock);
+ rte_free(filter);
+ filter = NULL;
+l_end:
+ return ret;
+}
+
+void sxe2_mc_filter_clear(struct sxe2_adapter *adapter, bool default_config)
+{
+ struct sxe2_mac_filter *entry;
+ struct sxe2_mac_filter *next_entry;
+
+ RTE_TAILQ_FOREACH_SAFE(entry, &adapter->filter_ctxt.mc_list, next, next_entry) {
+ if (entry->default_config && !default_config)
+ continue;
+ if (sxe2_mc_filter_del(adapter, &entry->mac_addr))
+ PMD_DEV_LOG_ERR(adapter, DRV, "This MAC filter delete fail.");
+ }
+}
+
+static struct sxe2_vlan_filter *sxe2_vlan_filter_find(struct sxe2_adapter *adapter,
+ struct sxe2_vlan *vlan)
+{
+ struct sxe2_vlan_filter *f;
+ struct sxe2_vlan_filter *save_f = NULL;
+
+ rte_spinlock_lock(&adapter->filter_ctxt.filter_lock);
+ TAILQ_FOREACH(f, &adapter->filter_ctxt.vlan_list, next)
+ {
+ if (vlan->tpid == f->vlan_info.tpid &&
+ vlan->vid == f->vlan_info.vid) {
+ save_f = f;
+ break;
+ }
+ }
+ rte_spinlock_unlock(&adapter->filter_ctxt.filter_lock);
+
+ return save_f;
+}
+
+int32_t sxe2_vlan_filter_add(struct sxe2_adapter *adapter,
+ struct sxe2_vlan *vlan, bool default_config)
+{
+ struct sxe2_vlan_filter *filter = NULL;
+ bool hw_config = false;
+ int32_t ret = 0;
+
+ if (!vlan || vlan->vid > RTE_ETHER_MAX_VLAN_ID) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "This vlan filter is invalid.");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ filter = sxe2_vlan_filter_find(adapter, vlan);
+ if (filter) {
+ PMD_DEV_LOG_INFO(adapter, DRV, "This vlan filter already exists.");
+ ret = 0;
+ goto l_end;
+ }
+ if (!adapter->rule_started) {
+ PMD_DEV_LOG_DEBUG(adapter, DRV, "cannot add vlan in port stop status");
+ } else if (adapter->flow_isolated) {
+ PMD_DEV_LOG_WARN(adapter, DRV, "cannot add vlan in flow isolation mode");
+ } else if (adapter->switchdev_info.is_switchdev) {
+ PMD_DEV_LOG_WARN(adapter, DRV, "cannot add vlan in switchdev mode");
+ } else {
+ ret = sxe2_drv_vlan_filter_id_config(adapter, vlan, true);
+ if (ret && ret != -EEXIST) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to add vlan rule");
+ ret = -EINVAL;
+ goto l_end;
+ }
+ hw_config = true;
+ }
+
+ filter = rte_zmalloc("sxe2_vlan_filter", sizeof(*filter), 0);
+ if (!filter) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to allocate memory");
+ ret = -ENOMEM;
+ goto l_end;
+ }
+
+ filter->hw_config = hw_config;
+ filter->default_config = default_config;
+
+ filter->vlan_info.tpid = vlan->tpid;
+ filter->vlan_info.vid = vlan->vid;
+ filter->vlan_info.prio = vlan->prio;
+
+ rte_spinlock_lock(&adapter->filter_ctxt.filter_lock);
+ TAILQ_INSERT_TAIL(&adapter->filter_ctxt.vlan_list, filter, next);
+ adapter->filter_ctxt.vlan_num++;
+ rte_spinlock_unlock(&adapter->filter_ctxt.filter_lock);
+
+ ret = 0;
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_vlan_filter_del(struct sxe2_adapter *adapter, struct sxe2_vlan *vlan)
+{
+ struct sxe2_vlan_filter *filter = NULL;
+ int32_t ret = -1;
+
+ if (!vlan || vlan->vid > RTE_ETHER_MAX_VLAN_ID) {
+ PMD_DEV_LOG_INFO(adapter, DRV, "This vlan filter is invalid.");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ filter = sxe2_vlan_filter_find(adapter, vlan);
+ if (!filter) {
+ PMD_DEV_LOG_INFO(adapter, DRV, "This vlan filter not exists.");
+ ret = 0;
+ goto l_end;
+ }
+
+ if (filter->hw_config) {
+ ret = sxe2_drv_vlan_filter_id_config(adapter, vlan, false);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to delete vlan rule");
+ if (ret == -EPERM)
+ goto l_free;
+ ret = -EINVAL;
+ goto l_end;
+ }
+ }
+ ret = 0;
+
+l_free:
+
+ rte_spinlock_lock(&adapter->filter_ctxt.filter_lock);
+ TAILQ_REMOVE(&adapter->filter_ctxt.vlan_list, filter, next);
+ adapter->filter_ctxt.vlan_num--;
+ rte_spinlock_unlock(&adapter->filter_ctxt.filter_lock);
+ rte_free(filter);
+ filter = NULL;
+l_end:
+ return ret;
+}
+
+void sxe2_vlan_filters_clear(struct sxe2_adapter *adapter, bool default_config)
+{
+ int32_t ret = 0;
+ struct sxe2_vlan_filter *v_f;
+ void *temp;
+
+ if (adapter->filter_ctxt.vlan_num == 0)
+ return;
+
+ RTE_TAILQ_FOREACH_SAFE(v_f, &adapter->filter_ctxt.vlan_list, next, temp)
+ {
+ if (v_f->default_config && !default_config)
+ continue;
+ ret = sxe2_vlan_filter_del(adapter, &v_f->vlan_info);
+ if (ret)
+ PMD_DEV_LOG_ERR(adapter, DRV, "This vlan filter delete fail.");
+ }
+}
+
+int32_t sxe2_vlan_filter_ctrl(struct sxe2_adapter *adapter, bool flag)
+{
+ struct sxe2_vlan_info *vlan_info = &adapter->filter_ctxt.vlan_info;
+ int32_t ret = 0;
+
+ if (vlan_info->filter_on == flag)
+ goto l_end;
+ if (!adapter->rule_started) {
+ PMD_DEV_LOG_DEBUG(adapter, DRV, "cannot add vlan filter ctrl in port stop status");
+ } else if (adapter->flow_isolated) {
+ PMD_DEV_LOG_WARN(adapter, DRV, "cannot add vlan filter ctrl in flow isolation mode");
+ } else if (adapter->switchdev_info.is_switchdev) {
+ PMD_DEV_LOG_WARN(adapter, DRV, "cannot add vlan filter ctrl in switchdev mode");
+ } else {
+ ret = sxe2_drv_vlan_filter_switch(adapter, flag);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to add vlan filter ctrl");
+ goto l_end;
+ }
+ vlan_info->hw_filter_on = flag;
+ }
+ vlan_info->filter_on = flag;
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_promisc_add(struct sxe2_adapter *adapter)
+{
+ int32_t ret = 0;
+
+ if (!adapter->rule_started) {
+ PMD_DEV_LOG_DEBUG(adapter, DRV, "cannot enable promiscuous in port stop status");
+ } else if (adapter->flow_isolated) {
+ PMD_DEV_LOG_WARN(adapter, DRV, "cannot enable promiscuous in flow isolation mode");
+ } else if (adapter->switchdev_info.is_switchdev) {
+ PMD_DEV_LOG_WARN(adapter, DRV, "cannot enable promiscuous in switchdev mode");
+ } else if (!(adapter->filter_ctxt.hw_promisc_flags & SXE2_PROMISC)) {
+ ret = sxe2_drv_promisc_config(adapter, true);
+ if (ret && ret != -EEXIST) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "failed to cfg promiscuous, ret:%d", ret);
+ goto l_end;
+ }
+ adapter->filter_ctxt.hw_promisc_flags |= SXE2_PROMISC;
+ }
+ adapter->filter_ctxt.cur_promisc_flags |= SXE2_PROMISC;
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_promisc_del(struct sxe2_adapter *adapter)
+{
+ int32_t ret = 0;
+
+ if (!adapter->flow_isolated &&
+ (adapter->filter_ctxt.hw_promisc_flags & SXE2_PROMISC)) {
+ ret = sxe2_drv_promisc_config(adapter, false);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "failed to cfg promiscuous, ret:%d", ret);
+ goto l_end;
+ }
+ adapter->filter_ctxt.hw_promisc_flags &= ~SXE2_PROMISC;
+ }
+
+ adapter->filter_ctxt.cur_promisc_flags &= ~SXE2_PROMISC;
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_allmulti_add(struct sxe2_adapter *adapter)
+{
+ int32_t ret = 0;
+
+ if (!adapter->rule_started) {
+ PMD_DEV_LOG_DEBUG(adapter, DRV, "cannot enable allmulticast in port stop status");
+ } else if (adapter->flow_isolated) {
+ PMD_DEV_LOG_WARN(adapter, DRV, "cannot enable allmulticast in flow isolation mode");
+ } else if (adapter->switchdev_info.is_switchdev) {
+ PMD_DEV_LOG_WARN(adapter, DRV, "cannot enable allmulticast in switchdev mode");
+ } else if (!(adapter->filter_ctxt.hw_promisc_flags & SXE2_PROMISC_MULTICAST)) {
+ ret = sxe2_drv_allmulti_config(adapter, true);
+ if (ret && ret != -EEXIST) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "failed to cfg allmulticast, ret:%d", ret);
+ goto l_end;
+ }
+ adapter->filter_ctxt.hw_promisc_flags |= SXE2_PROMISC_MULTICAST;
+ }
+ adapter->filter_ctxt.cur_promisc_flags |= SXE2_PROMISC_MULTICAST;
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_allmulti_del(struct sxe2_adapter *adapter)
+{
+ int32_t ret = 0;
+
+ if (!adapter->flow_isolated &&
+ (adapter->filter_ctxt.hw_promisc_flags & SXE2_PROMISC_MULTICAST)) {
+ ret = sxe2_drv_allmulti_config(adapter, false);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "failed to cfg allmulticast, ret:%d", ret);
+ goto l_end;
+ }
+ adapter->filter_ctxt.hw_promisc_flags &= ~SXE2_PROMISC_MULTICAST;
+ }
+
+ adapter->filter_ctxt.cur_promisc_flags &= ~SXE2_PROMISC_MULTICAST;
+l_end:
+ return ret;
+}
+
+static int32_t sxe2_all_filter_hw_clear(struct sxe2_adapter *adapter)
+{
+ int32_t ret = 0;
+ struct sxe2_mac_filter *mac_entry;
+ struct sxe2_mac_filter *next_mac_entry;
+ struct sxe2_vlan_filter *vlan_entry;
+ struct sxe2_vlan_filter *next_vlan_entry;
+
+ if (adapter->filter_ctxt.uc_num > 0) {
+ RTE_TAILQ_FOREACH_SAFE(mac_entry, &adapter->filter_ctxt.uc_list, next,
+ next_mac_entry) {
+ if (mac_entry->hw_config) {
+ ret = sxe2_drv_uc_config(adapter, &mac_entry->mac_addr, false);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to delete mac rule");
+ ret = -EINVAL;
+ goto l_end;
+ }
+ mac_entry->hw_config = false;
+ }
+ }
+ }
+
+ if (adapter->filter_ctxt.mc_num > 0) {
+ RTE_TAILQ_FOREACH_SAFE(mac_entry, &adapter->filter_ctxt.mc_list, next,
+ next_mac_entry) {
+ if (mac_entry->hw_config) {
+ ret = sxe2_drv_mc_config(adapter, &mac_entry->mac_addr, false);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to delete mc rule");
+ ret = -EINVAL;
+ goto l_end;
+ }
+ mac_entry->hw_config = false;
+ }
+ }
+ }
+
+ if (adapter->filter_ctxt.vlan_num > 0) {
+ RTE_TAILQ_FOREACH_SAFE(vlan_entry, &adapter->filter_ctxt.vlan_list, next,
+ next_vlan_entry) {
+ if (vlan_entry->hw_config) {
+ ret = sxe2_drv_vlan_filter_id_config(adapter,
+ &vlan_entry->vlan_info, false);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to delete vlan rule");
+ ret = -EINVAL;
+ goto l_end;
+ }
+ vlan_entry->hw_config = false;
+ }
+ }
+ }
+
+ if (adapter->filter_ctxt.vlan_info.hw_filter_on) {
+ ret = sxe2_drv_vlan_filter_switch(adapter, false);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to delete vlan rule");
+ ret = -EINVAL;
+ goto l_end;
+ }
+ adapter->filter_ctxt.vlan_info.hw_filter_on = false;
+ }
+
+ if (adapter->filter_ctxt.hw_promisc_flags & SXE2_PROMISC) {
+ ret = sxe2_drv_promisc_config(adapter, false);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "failed to cfg promiscuous, ret:%d", ret);
+ goto l_end;
+ }
+ adapter->filter_ctxt.hw_promisc_flags &= ~SXE2_PROMISC;
+ }
+
+ if (adapter->filter_ctxt.hw_promisc_flags & SXE2_PROMISC_MULTICAST) {
+ ret = sxe2_drv_allmulti_config(adapter, false);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "failed to cfg allmulticast, ret:%d", ret);
+ goto l_end;
+ }
+ adapter->filter_ctxt.hw_promisc_flags &= ~SXE2_PROMISC_MULTICAST;
+ }
+l_end:
+ return ret;
+}
+
+static int32_t sxe2_all_filter_hw_set(struct sxe2_adapter *adapter)
+{
+ int32_t ret = 0;
+ struct sxe2_mac_filter *mac_entry;
+ struct sxe2_mac_filter *next_mac_entry;
+ struct sxe2_vlan_filter *vlan_entry;
+ struct sxe2_vlan_filter *next_vlan_entry;
+
+ if (adapter->filter_ctxt.uc_num > 0) {
+ RTE_TAILQ_FOREACH_SAFE(mac_entry, &adapter->filter_ctxt.uc_list, next,
+ next_mac_entry) {
+ if (!mac_entry->hw_config) {
+ ret = sxe2_drv_uc_config(adapter, &mac_entry->mac_addr,
+ true);
+ if (ret && ret != -EEXIST) {
+ PMD_DEV_LOG_ERR(adapter, DRV,
+ "Failed to add uc rule, ret:%d", ret);
+ ret = -EINVAL;
+ goto l_end;
+ }
+ mac_entry->hw_config = true;
+ ret = 0;
+ }
+ }
+ }
+
+ if (adapter->filter_ctxt.mc_num > 0) {
+ RTE_TAILQ_FOREACH_SAFE(mac_entry, &adapter->filter_ctxt.mc_list, next,
+ next_mac_entry) {
+ if (!mac_entry->hw_config) {
+ ret = sxe2_drv_mc_config(adapter, &mac_entry->mac_addr, true);
+ if (ret && ret != -EEXIST) {
+ PMD_DEV_LOG_ERR(adapter, DRV,
+ "Failed to add mc rule, ret:%d", ret);
+ ret = -EINVAL;
+ goto l_end;
+ }
+ mac_entry->hw_config = true;
+ ret = 0;
+ }
+ }
+ }
+
+ if (adapter->filter_ctxt.vlan_num > 0) {
+ RTE_TAILQ_FOREACH_SAFE(vlan_entry, &adapter->filter_ctxt.vlan_list, next,
+ next_vlan_entry) {
+ if (!vlan_entry->hw_config) {
+ ret = sxe2_drv_vlan_filter_id_config(adapter,
+ &vlan_entry->vlan_info, true);
+ if (ret && ret != -EEXIST) {
+ PMD_DEV_LOG_ERR(adapter, DRV,
+ "Failed to add vlan rule, ret:%d", ret);
+ ret = -EINVAL;
+ goto l_end;
+ }
+ vlan_entry->hw_config = true;
+ ret = 0;
+ }
+ }
+ }
+
+ if (adapter->filter_ctxt.vlan_info.filter_on) {
+ if (!(adapter->filter_ctxt.vlan_info.hw_filter_on)) {
+ ret = sxe2_drv_vlan_filter_switch(adapter, true);
+ if (ret && ret != -EEXIST) {
+ PMD_DEV_LOG_ERR(adapter, DRV,
+ "Failed to add vlan ctrl, ret:%d", ret);
+ ret = -EINVAL;
+ goto l_end;
+ }
+ adapter->filter_ctxt.vlan_info.hw_filter_on = true;
+ ret = 0;
+ }
+ }
+
+ if ((adapter->filter_ctxt.cur_promisc_flags & SXE2_PROMISC) &&
+ (!(adapter->filter_ctxt.hw_promisc_flags & SXE2_PROMISC))) {
+ ret = sxe2_drv_promisc_config(adapter, true);
+ if (ret && ret != -EEXIST) {
+ PMD_DEV_LOG_ERR(adapter, DRV,
+ "Failed to set promisc, ret:%d", ret);
+ goto l_end;
+ }
+ adapter->filter_ctxt.hw_promisc_flags |= SXE2_PROMISC;
+ ret = 0;
+ }
+
+ if ((adapter->filter_ctxt.cur_promisc_flags & SXE2_PROMISC_MULTICAST) &&
+ (!(adapter->filter_ctxt.hw_promisc_flags & SXE2_PROMISC_MULTICAST))) {
+ ret = sxe2_drv_allmulti_config(adapter, true);
+ if (ret && ret != -EEXIST) {
+ PMD_DEV_LOG_ERR(adapter, DRV,
+ "Failed to set allmulti, ret:%d", ret);
+ goto l_end;
+ }
+ adapter->filter_ctxt.hw_promisc_flags |= SXE2_PROMISC_MULTICAST;
+ ret = 0;
+ }
+l_end:
+ return ret;
+}
+
+int32_t sxe2_l2_rule_update(struct sxe2_adapter *adapter)
+{
+ int32_t ret = 0;
+
+ if (!adapter->flow_isolated && !adapter->switchdev_info.is_switchdev &&
+ adapter->rule_started) {
+ adapter->filter_ctxt.cur_l2_config = true;
+ } else {
+ adapter->filter_ctxt.cur_l2_config = false;
+ }
+
+ if (adapter->filter_ctxt.cur_l2_config !=
+ adapter->filter_ctxt.hw_l2_config) {
+ if (adapter->filter_ctxt.cur_l2_config) {
+ ret = sxe2_all_filter_hw_set(adapter);
+ if (!ret)
+ adapter->filter_ctxt.hw_l2_config = true;
+ } else {
+ ret = sxe2_all_filter_hw_clear(adapter);
+ if (!ret)
+ adapter->filter_ctxt.hw_l2_config = false;
+ }
+ }
+ return ret;
+}
+
+int32_t sxe2_filter_rule_stop(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret = 0;
+ adapter->rule_started = 0;
+
+ ret = sxe2_l2_rule_update(adapter);
+ if (ret != 0)
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to update l2 rule");
+
+ return ret;
+}
+
+int32_t sxe2_filter_rule_start(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret = 0;
+ adapter->rule_started = 1;
+
+ ret = sxe2_l2_rule_update(adapter);
+ if (ret != 0)
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to update l2 rule");
+
+ return ret;
+}
+
+int32_t sxe2_filter_init(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+
+ rte_spinlock_init(&adapter->filter_ctxt.filter_lock);
+
+ TAILQ_INIT(&adapter->filter_ctxt.uc_list);
+ adapter->filter_ctxt.uc_num = 0;
+
+ TAILQ_INIT(&adapter->filter_ctxt.mc_list);
+ adapter->filter_ctxt.mc_num = 0;
+
+ TAILQ_INIT(&adapter->filter_ctxt.vlan_list);
+ adapter->filter_ctxt.vlan_num = 0;
+ return 0;
+}
+
+int32_t sxe2_filter_uinit(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ sxe2_uc_filter_clear(adapter, true);
+ adapter->filter_ctxt.uc_num = 0;
+
+ sxe2_mc_filter_clear(adapter, true);
+ adapter->filter_ctxt.mc_num = 0;
+
+ sxe2_vlan_filters_clear(adapter, true);
+ adapter->filter_ctxt.vlan_num = 0;
+ return 0;
+}
diff --git a/drivers/net/sxe2/sxe2_filter.h b/drivers/net/sxe2/sxe2_filter.h
new file mode 100644
index 0000000000..6262e8c845
--- /dev/null
+++ b/drivers/net/sxe2/sxe2_filter.h
@@ -0,0 +1,98 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#ifndef __SXE2_FILTER_H__
+#define __SXE2_FILTER_H__
+#include <ethdev_driver.h>
+
+#define SXE2_PROMISC (1UL << 0UL)
+#define SXE2_PROMISC_MULTICAST (1UL << 1UL)
+
+struct sxe2_vlan_info {
+ uint8_t port_vlan_exist;
+ uint8_t is_switchdev;
+ uint16_t max_cnt;
+ uint16_t cnt;
+
+ bool filter_on;
+ bool hw_filter_on;
+
+ uint16_t tpid;
+ uint16_t vid;
+
+ uint8_t outer_insert;
+ uint8_t outer_strip;
+ uint8_t inner_insert;
+ uint8_t inner_strip;
+};
+
+struct sxe2_vlan {
+ uint16_t tpid;
+ uint16_t vid;
+ uint8_t prio;
+};
+
+struct sxe2_vlan_filter {
+ TAILQ_ENTRY(sxe2_vlan_filter) next;
+ bool hw_config;
+ bool default_config;
+ struct sxe2_vlan vlan_info;
+};
+
+TAILQ_HEAD(sxe2_vlan_filter_list_head, sxe2_vlan_filter);
+
+struct sxe2_mac_filter {
+ TAILQ_ENTRY(sxe2_mac_filter) next;
+ bool hw_config;
+ bool default_config;
+ struct rte_ether_addr mac_addr;
+};
+
+TAILQ_HEAD(sxe2_uc_filter_list_head, sxe2_mac_filter);
+TAILQ_HEAD(sxe2_mc_filter_list_head, sxe2_mac_filter);
+
+int32_t sxe2_uc_filter_add(struct sxe2_adapter *adapter,
+ struct rte_ether_addr *mac_addr, bool default_config);
+
+int32_t sxe2_uc_filter_del(struct sxe2_adapter *adapter,
+ struct rte_ether_addr *mac_addr);
+
+void sxe2_uc_filter_clear(struct sxe2_adapter *adapter, bool default_config);
+
+int32_t sxe2_mc_filter_add(struct sxe2_adapter *adapter,
+ struct rte_ether_addr *mac_addr, bool default_config);
+
+int32_t sxe2_mc_filter_del(struct sxe2_adapter *adapter,
+ struct rte_ether_addr *mac_addr);
+
+void sxe2_mc_filter_clear(struct sxe2_adapter *adapter, bool default_config);
+
+int32_t sxe2_vlan_filter_add(struct sxe2_adapter *adapter,
+ struct sxe2_vlan *vlan, bool default_config);
+
+int32_t sxe2_vlan_filter_del(struct sxe2_adapter *adapter, struct sxe2_vlan *vlan);
+
+void sxe2_vlan_filters_clear(struct sxe2_adapter *adapter, bool default_config);
+
+int32_t sxe2_vlan_filter_ctrl(struct sxe2_adapter *adapter, bool flag);
+
+int32_t sxe2_promisc_add(struct sxe2_adapter *adapter);
+
+int32_t sxe2_promisc_del(struct sxe2_adapter *adapter);
+
+int32_t sxe2_allmulti_add(struct sxe2_adapter *adapter);
+
+int32_t sxe2_allmulti_del(struct sxe2_adapter *adapter);
+
+int32_t sxe2_l2_rule_update(struct sxe2_adapter *adapter);
+
+int32_t sxe2_filter_rule_stop(struct rte_eth_dev *dev);
+
+int32_t sxe2_filter_rule_start(struct rte_eth_dev *dev);
+
+int32_t sxe2_filter_init(struct rte_eth_dev *dev);
+
+int32_t sxe2_filter_uinit(struct rte_eth_dev *dev);
+
+#endif /* __SXE2_FILTER_H__ */
diff --git a/drivers/net/sxe2/sxe2_mac.c b/drivers/net/sxe2/sxe2_mac.c
index 3c2f909002..d94936a742 100644
--- a/drivers/net/sxe2/sxe2_mac.c
+++ b/drivers/net/sxe2/sxe2_mac.c
@@ -10,6 +10,438 @@
#include "sxe2_cmd_chnl.h"
#include "sxe2_host_regs.h"
+int32_t sxe2_mac_default_cfg(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret;
+ struct rte_ether_addr broadcast = {
+ .addr_bytes = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} };
+ struct rte_ether_addr mac_addr;
+
+ rte_ether_addr_copy((struct rte_ether_addr *)
+ adapter->dev_info.mac.perm_addr, &mac_addr);
+ ret = sxe2_uc_filter_add(adapter, &mac_addr, true);
+ if (ret != 0) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to add default MAC filter");
+ goto l_end;
+ }
+
+ rte_ether_addr_copy(&broadcast, &mac_addr);
+ ret = sxe2_mc_filter_add(adapter, &mac_addr, true);
+ if (ret != 0) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to add broadcast MAC filter");
+ goto l_end;
+ }
+
+ ret = 0;
+l_end:
+ return ret;
+}
+
+int32_t sxe2_mac_addr_init(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret = -1;
+ PMD_INIT_FUNC_TRACE();
+
+ if (!rte_is_unicast_ether_addr
+ ((struct rte_ether_addr *)adapter->dev_info.mac.perm_addr)) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Invalid MAC address");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ dev->data->mac_addrs = rte_zmalloc("sxe2_mac_adds",
+ sizeof(struct rte_ether_addr) * SXE2_NUM_MACADDR_MAX, 0);
+ if (!dev->data->mac_addrs) {
+ PMD_LOG_ERR(DRV, "Failed to allocate memory to store mac address");
+ ret = -ENOMEM;
+ goto l_end;
+ }
+
+ rte_ether_addr_copy((struct rte_ether_addr *)adapter->dev_info.mac.perm_addr,
+ &dev->data->mac_addrs[0]);
+
+ ret = 0;
+
+l_end:
+ return ret;
+}
+
+void sxe2_mac_addr_uinit(struct rte_eth_dev *dev)
+{
+ PMD_INIT_FUNC_TRACE();
+ if (dev != NULL && dev->data->mac_addrs != NULL) {
+ rte_free(dev->data->mac_addrs);
+ dev->data->mac_addrs = NULL;
+ }
+}
+
+int32_t sxe2_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,
+ __rte_unused uint32_t index, __rte_unused uint32_t pool)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret = -1;
+
+ if (rte_is_zero_ether_addr(mac_addr)) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Invalid MAC Address");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if (rte_is_multicast_ether_addr(mac_addr))
+ ret = sxe2_mc_filter_add(adapter, mac_addr, true);
+ else
+ ret = sxe2_uc_filter_add(adapter, mac_addr, false);
+
+ if (ret)
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to add MAC filter");
+
+l_end:
+ return ret;
+}
+
+void sxe2_mac_addr_del(struct rte_eth_dev *dev, uint32_t index)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct rte_ether_addr *mac_addr = &dev->data->mac_addrs[index];
+ int32_t ret = -1;
+
+ if (rte_is_multicast_ether_addr(mac_addr))
+ ret = sxe2_mc_filter_del(adapter, mac_addr);
+ else
+ ret = sxe2_uc_filter_del(adapter, mac_addr);
+
+ if (ret)
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to remove MAC filter");
+}
+
+int32_t sxe2_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret = 0;
+ struct rte_ether_addr *old_addr = (struct rte_ether_addr *)&adapter->dev_info.mac.perm_addr;
+ struct rte_ether_addr temp_addr;
+
+ if (rte_is_same_ether_addr(old_addr, mac_addr))
+ goto l_end;
+
+ if (rte_is_multicast_ether_addr(mac_addr)) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to set multicast addr");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ ret = sxe2_uc_filter_del(adapter, old_addr);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to remove MAC filter");
+ goto l_end;
+ }
+
+ rte_ether_addr_copy(old_addr, &temp_addr);
+
+ rte_ether_addr_copy(mac_addr, old_addr);
+
+ ret = sxe2_uc_filter_add(adapter, mac_addr, true);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to add MAC filter");
+ rte_ether_addr_copy(&temp_addr, old_addr);
+ (void)sxe2_uc_filter_add(adapter, old_addr, true);
+ goto l_end;
+ }
+l_end:
+ return ret;
+}
+
+int32_t sxe2_set_mc_addr_list(struct rte_eth_dev *dev,
+ struct rte_ether_addr *mc_addrs,
+ uint32_t mc_addrs_num)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret = 0;
+ uint32_t i;
+ const uint8_t *mac;
+
+ if (mc_addrs_num > SXE2_NUM_MACADDR_MAX) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Too many multicast MAC addresses, ");
+ ret = -1;
+ goto l_end;
+ }
+
+ sxe2_mc_filter_clear(adapter, false);
+
+ for (i = 0; i < mc_addrs_num; i++) {
+ if (!rte_is_multicast_ether_addr(&mc_addrs[i])) {
+ mac = mc_addrs[i].addr_bytes;
+ PMD_DEV_LOG_ERR(adapter, DRV,
+ "Invalid mac: %02x:%02x:%02x:%02x:%02x:%02x",
+ mac[0], mac[1], mac[2], mac[3], mac[4],
+ mac[5]);
+ ret = -EINVAL;
+ goto add_err;
+ }
+
+ ret = sxe2_mc_filter_add(adapter, &mc_addrs[i], false);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV,
+ "Failed to remove old multicast MAC filter list");
+ goto add_err;
+ }
+ }
+ goto l_end;
+add_err:
+ sxe2_mc_filter_clear(adapter, false);
+l_end:
+ return ret;
+}
+
+int32_t sxe2_dev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int32_t on)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_vlan vlan = {
+ .tpid = RTE_ETHER_TYPE_VLAN,
+ .vid = vlan_id,
+ .prio = 0
+ };
+ int32_t ret = 0;
+
+ if (sxe2_dev_port_vlan_check(dev)) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Filter not supported with Port VLAN");
+ ret = -ENOTSUP;
+ goto l_end;
+ }
+
+ if (vlan_id == 0)
+ goto l_end;
+
+ if (on) {
+ ret = sxe2_vlan_filter_add(adapter, &vlan, false);
+ if (ret < 0) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to add vlan filter");
+ goto l_end;
+ }
+ } else {
+ ret = sxe2_vlan_filter_del(adapter, &vlan);
+ if (ret < 0) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to remove vlan filter");
+ goto l_end;
+ }
+ }
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_dev_vlan_offload_set(struct rte_eth_dev *dev, int32_t mask)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret = 0;
+ struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
+ struct rte_eth_txmode *txmode = &dev->data->dev_conf.txmode;
+ struct sxe2_vlan_info new_info = adapter->filter_ctxt.vlan_info;
+ bool port_vlan = new_info.port_vlan_exist;
+
+ uint8_t out_strip_mask = SXE2_DPDK_OFFLOAD_OUTER_STRIP_8021Q |
+ SXE2_DPDK_OFFLOAD_OUTER_STRIP_8021AD |
+ SXE2_DPDK_OFFLOAD_OUTER_STRIP_QINQ1;
+
+ if (txmode->offloads & RTE_ETH_TX_OFFLOAD_QINQ_INSERT) {
+ if (!(txmode->offloads & RTE_ETH_TX_OFFLOAD_VLAN_INSERT)) {
+ PMD_DEV_LOG_ERR(adapter, DRV,
+ "VLAN INSERT must be enabled when QinQ INSERT is enabled");
+ return -EINVAL;
+ }
+ if (port_vlan) {
+ PMD_DEV_LOG_ERR(adapter, DRV,
+ "QINQ INSERT not supported with Port VLAN");
+ return -EINVAL;
+ }
+ }
+
+ if (mask & RTE_ETH_QINQ_STRIP_MASK) {
+ if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_QINQ_STRIP) {
+ if (port_vlan) {
+ PMD_DEV_LOG_ERR(adapter, DRV,
+ "QinQ strip not supported with Port VLAN");
+ return -EINVAL;
+ }
+ new_info.inner_strip = SXE2_VSI_TSR_ID_VLAN;
+ } else {
+ new_info.inner_strip = 0;
+ }
+ }
+
+ if (mask & RTE_ETH_VLAN_STRIP_MASK) {
+ if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) {
+ new_info.outer_strip =
+ port_vlan ? 0 : out_strip_mask;
+ new_info.inner_strip =
+ port_vlan ? new_info.inner_strip : new_info.inner_strip;
+ } else {
+ if (new_info.inner_strip != 0) {
+ PMD_DEV_LOG_ERR(adapter, DRV,
+ "Must disable QinQ strip before disabling VLAN strip");
+ return -EINVAL;
+ }
+ new_info.outer_strip = 0;
+ }
+ }
+
+ if (mask & (RTE_ETH_VLAN_STRIP_MASK | RTE_ETH_QINQ_STRIP_MASK)) {
+ struct sxe2_vlan_info old_info = adapter->filter_ctxt.vlan_info;
+ adapter->filter_ctxt.vlan_info = new_info;
+
+ ret = sxe2_drv_vlan_insert_strip_cfg(adapter);
+ if (ret) {
+ adapter->filter_ctxt.vlan_info = old_info;
+ return ret;
+ }
+ }
+ if (mask & RTE_ETH_VLAN_FILTER_MASK) {
+ if (adapter->filter_ctxt.vlan_info.port_vlan_exist) {
+ ret = 0;
+ PMD_DEV_LOG_INFO(adapter, INIT, "vlan filter is not support when port vlan is enabled");
+ goto l_end;
+ }
+
+ ret = sxe2_vlan_filter_ctrl(adapter,
+ !!(rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_FILTER));
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV,
+ "sxe2_drv_vlan_filter_switch failed ret:%d", ret);
+ goto l_end;
+ }
+ }
+
+ PMD_DEV_LOG_DEBUG(adapter, DRV,
+ "mask:0x%x rx mode offload:0x%" PRIx64 " vlan offload set done",
+ mask, rxmode->offloads);
+l_end:
+ return ret;
+}
+
+static int32_t sxe2_vlan_filter_zero(struct sxe2_adapter *adapter)
+{
+ struct sxe2_vlan vlan;
+ int32_t ret;
+ uint16_t tpids[] = {RTE_ETHER_TYPE_VLAN, RTE_ETHER_TYPE_QINQ, RTE_ETHER_TYPE_QINQ1};
+ uint8_t i;
+
+ vlan = (struct sxe2_vlan){0, 0, 0};
+ ret = sxe2_vlan_filter_add(adapter, &vlan, true);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to add VLAN ID 0");
+ goto l_end;
+ }
+
+ for (i = 0; i < RTE_DIM(tpids); i++) {
+ vlan = (struct sxe2_vlan){tpids[i], 0, 0};
+ ret = sxe2_vlan_filter_add(adapter, &vlan, true);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to add VLAN ID 0 when tpid:0x%x",
+ tpids[i]);
+ goto l_end;
+ }
+ }
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_vlan_cfg_init(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret = 0;
+
+ ret = sxe2_drv_vlan_config_query(adapter);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to query vlan config, ret=%d", ret);
+ goto l_end;
+ }
+
+ if (!sxe2_dev_port_vlan_check(dev))
+ adapter->filter_ctxt.vlan_info.outer_insert =
+ SXE2_DPDK_OFFLOAD_OUTER_INSERT_8021Q |
+ SXE2_DPDK_OFFLOAD_INSERT_ENABLE;
+ else
+ adapter->filter_ctxt.vlan_info.outer_insert = 0;
+
+ adapter->filter_ctxt.vlan_info.inner_insert =
+ SXE2_DPDK_OFFLOAD_INNER_INSERT_QINQ1 | SXE2_DPDK_OFFLOAD_INSERT_ENABLE;
+
+ if (!sxe2_dev_port_vlan_check(dev)) {
+ ret = sxe2_vlan_filter_zero(adapter);
+ if (ret != 0)
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to add vlan filter switch:0 "
+ "for port:%d", adapter->port_idx);
+ }
+
+l_end:
+ return ret;
+}
+
+int32_t sxe2_vlan_default_cfg(struct rte_eth_dev *dev)
+{
+ int32_t ret = 0;
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+
+ ret = sxe2_dev_vlan_offload_set(dev, RTE_ETH_VLAN_STRIP_MASK |
+ RTE_ETH_QINQ_STRIP_MASK |
+ RTE_ETH_VLAN_FILTER_MASK);
+ if (ret)
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to cfg vlan offload, ret:%d", ret);
+
+ return ret;
+}
+
+int32_t sxe2_promisc_enable(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret = 0;
+
+ ret = sxe2_promisc_add(adapter);
+ if (ret)
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to enable promisc, ret:%d", ret);
+
+ return ret;
+}
+
+int32_t sxe2_promisc_disable(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret = 0;
+
+ ret = sxe2_promisc_del(adapter);
+ if (ret)
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to disable promisc, ret:%d", ret);
+
+ return ret;
+}
+
+int32_t sxe2_allmulti_enable(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret = 0;
+
+ ret = sxe2_allmulti_add(adapter);
+ if (ret)
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to enable allmulti, ret:%d", ret);
+
+ return ret;
+}
+
+int32_t sxe2_allmulti_disable(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret = 0;
+
+ ret = sxe2_allmulti_del(adapter);
+ if (ret)
+ PMD_DEV_LOG_ERR(adapter, DRV, "Failed to disable allmulti, ret:%d", ret);
+
+ return ret;
+}
+
int32_t sxe2_link_update_init(struct rte_eth_dev *dev)
{
struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
diff --git a/drivers/net/sxe2/sxe2_mac.h b/drivers/net/sxe2/sxe2_mac.h
index f2f3edaeff..55fd1829a0 100644
--- a/drivers/net/sxe2/sxe2_mac.h
+++ b/drivers/net/sxe2/sxe2_mac.h
@@ -43,6 +43,40 @@ struct sxe2_mac_mc_list {
int32_t sxe2_link_update_init(struct rte_eth_dev *dev);
+int32_t sxe2_mac_default_cfg(struct rte_eth_dev *dev);
+
+int32_t sxe2_vlan_cfg_init(struct rte_eth_dev *dev);
+
+int32_t sxe2_mac_addr_init(struct rte_eth_dev *dev);
+
+void sxe2_mac_addr_uinit(struct rte_eth_dev *dev);
+
+int32_t sxe2_mac_addr_add(struct rte_eth_dev *dev,
+ struct rte_ether_addr *mac_addr,
+ __rte_unused uint32_t index, __rte_unused uint32_t pool);
+
+void sxe2_mac_addr_del(struct rte_eth_dev *dev, uint32_t index);
+
+int32_t sxe2_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr);
+
+int32_t sxe2_set_mc_addr_list(struct rte_eth_dev *dev,
+ struct rte_ether_addr *mc_addrs,
+ uint32_t mc_addrs_num);
+
+int32_t sxe2_promisc_enable(struct rte_eth_dev *dev);
+
+int32_t sxe2_promisc_disable(struct rte_eth_dev *dev);
+
+int32_t sxe2_allmulti_enable(struct rte_eth_dev *dev);
+
+int32_t sxe2_allmulti_disable(struct rte_eth_dev *dev);
+
+int32_t sxe2_dev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int32_t on);
+
+int32_t sxe2_dev_vlan_offload_set(struct rte_eth_dev *dev, int32_t mask);
+
+int32_t sxe2_vlan_default_cfg(struct rte_eth_dev *dev);
+
int32_t sxe2_link_update(struct rte_eth_dev *dev, __rte_unused int32_t wait_to_complete);
int32_t sxe2_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
diff --git a/drivers/net/sxe2/sxe2_txrx_poll.c b/drivers/net/sxe2/sxe2_txrx_poll.c
index b9d34afb31..21d5c38725 100644
--- a/drivers/net/sxe2/sxe2_txrx_poll.c
+++ b/drivers/net/sxe2/sxe2_txrx_poll.c
@@ -660,6 +660,53 @@ sxe2_rx_desc_error_para(__rte_unused struct sxe2_rx_queue *rxq,
return flags;
}
+static inline void sxe2_rx_desc_vlan_para_fill(struct rte_mbuf *mbuf,
+ union sxe2_rx_desc *desc)
+{
+ if (0 == (rte_le_to_cpu_64(desc->wb.status_err_ptype_len) &
+ SXE2_RX_DESC_STATUS_L2TAG1_P_MASK)) {
+ mbuf->vlan_tci = 0;
+ } else {
+ mbuf->ol_flags |= (RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED);
+ mbuf->vlan_tci = rte_le_to_cpu_16(desc->wb.l2tag1);
+ PMD_LOG_DEBUG(RX, "Rx desc mbuf vlan, vlan_tci:%u",
+ mbuf->vlan_tci);
+ }
+#ifndef RTE_LIBRTE_SXE2_16BYTE_RX_DESC
+ if (0 == (rte_le_to_cpu_32(desc->wb.status_lrocnt_fdpf_id) &
+ SXE2_RX_DESC_EXT_STATUS_L2TAG2P_MASK)) {
+ mbuf->vlan_tci_outer = 0;
+ } else {
+ mbuf->ol_flags |= RTE_MBUF_F_RX_QINQ_STRIPPED | RTE_MBUF_F_RX_QINQ |
+ RTE_MBUF_F_RX_VLAN_STRIPPED | RTE_MBUF_F_RX_VLAN;
+ mbuf->vlan_tci_outer = mbuf->vlan_tci;
+ mbuf->vlan_tci = rte_le_to_cpu_16(desc->wb.l2tag2_2nd);
+ PMD_LOG_DEBUG(RX, "Rx desc out vlan, l2tag2_1st:%u l2tag2_2nd:%u.",
+ rte_le_to_cpu_16(desc->wb.l2tag2_1st),
+ rte_le_to_cpu_16(desc->wb.l2tag2_2nd));
+ }
+#endif
+}
+
+static inline void
+sxe2_rx_desc_filter_para_fill(struct sxe2_rx_queue *rxq __rte_unused,
+ struct rte_mbuf *mbuf, union sxe2_rx_desc *desc)
+{
+ if (SXE2_RX_DESC_STATUS_RSS_VLD_MASK &
+ rte_le_to_cpu_64(desc->wb.status_err_ptype_len)) {
+ mbuf->ol_flags |= RTE_MBUF_F_RX_RSS_HASH;
+ mbuf->hash.rss = rte_le_to_cpu_32(desc->wb.filter_status);
+ PMD_LOG_DEBUG(RX, "rss id:%u", mbuf->hash.rss);
+ }
+#ifndef RTE_LIBRTE_SXE2_16BYTE_RX_DESC
+ if (SXE2_RX_DESC_FD_VLD_MASK & desc->wb.rxdid_src) {
+ mbuf->ol_flags |= (RTE_MBUF_F_RX_FDIR | RTE_MBUF_F_RX_FDIR_ID);
+ mbuf->hash.fdir.hi = rte_le_to_cpu_32(desc->wb.fd_filter_id);
+ PMD_LOG_DEBUG(RX, "fdir id:%u", mbuf->hash.fdir.hi);
+ }
+#endif
+}
+
static __rte_always_inline void
sxe2_rx_mbuf_common_fields_fill(struct sxe2_rx_queue *rxq, struct rte_mbuf *mbuf,
union sxe2_rx_desc *rxd)
@@ -673,6 +720,8 @@ sxe2_rx_mbuf_common_fields_fill(struct sxe2_rx_queue *rxq, struct rte_mbuf *mbuf
mbuf->packet_type = ptype_tbl[SXE2_RX_DESC_PTYPE_VAL_GET(qword1)];
pkt_flags = sxe2_rx_desc_error_para(rxq, rxd);
+ sxe2_rx_desc_vlan_para_fill(mbuf, rxd);
+ sxe2_rx_desc_filter_para_fill(rxq, mbuf, rxd);
mbuf->ol_flags |= pkt_flags;
}
--
2.52.0
^ permalink raw reply related
* [PATCH v2 01/20] net/sxe2: support AVX512 vectorized path for Rx and Tx
From: liujie5 @ 2026-06-14 9:23 UTC (permalink / raw)
To: stephen; +Cc: dev, Jie Liu
In-Reply-To: <20260614092328.201826-1-liujie5@linkdatatechnology.com>
From: Jie Liu <liujie5@linkdatatechnology.com>
Add AVX512 vector data path for Rx and Tx burst functions.
The decision to use AVX512 is based on:
1. CPU hardware flags (AVX512F, AVX512BW).
2. Compiler support (CC_AVX512_SUPPORT).
3. Max SIMD bitwidth configuration.
Performance shows approximately X% improvement in small packet
forwarding scenarios.
Signed-off-by: Jie Liu <liujie5@linkdatatechnology.com>
---
drivers/net/sxe2/meson.build | 24 +
drivers/net/sxe2/sxe2_drv_cmd.h | 80 +--
drivers/net/sxe2/sxe2_ethdev.c | 2 +-
drivers/net/sxe2/sxe2_txrx.c | 92 ++-
drivers/net/sxe2/sxe2_txrx_vec.c | 46 +-
drivers/net/sxe2/sxe2_txrx_vec.h | 18 +-
drivers/net/sxe2/sxe2_txrx_vec_avx512.c | 897 ++++++++++++++++++++++++
7 files changed, 1099 insertions(+), 60 deletions(-)
create mode 100644 drivers/net/sxe2/sxe2_txrx_vec_avx512.c
diff --git a/drivers/net/sxe2/meson.build b/drivers/net/sxe2/meson.build
index 6b2eb75b0e..7bd0d8120c 100644
--- a/drivers/net/sxe2/meson.build
+++ b/drivers/net/sxe2/meson.build
@@ -15,6 +15,30 @@ includes += include_directories('../../common/sxe2')
if arch_subdir == 'x86'
sources += files('sxe2_txrx_vec_sse.c')
+
+ sxe2_avx512_cpu_support =(
+ cc.get_define('__AVX512F__', args: machine_args) != '' and
+ cc.get_define('__AVX512BW__', args: machine_args) != '')
+
+ sxe2_avx512_cc_support = (
+ not machine_args.contains('-mno-avx512f') and
+ cc.has_argument('-mavx512f') and
+ cc.has_argument('-mavx512bw'))
+
+ if sxe2_avx512_cpu_support == true or sxe2_avx512_cc_support == true
+ cflags += ['-DCC_AVX512_SUPPORT']
+ avx512_args = [cflags, '-mavx512f', '-mavx512bw']
+ if cc.has_argument('-march=skylake-avx512')
+ avx512_args += '-march=skylake-avx512'
+ endif
+ sxe2_avx512_lib = static_library('sxe2_avx512_lib', 'sxe2_txrx_vec_avx512.c',
+ dependencies: [static_rte_ethdev,
+ static_rte_kvargs, static_rte_hash,
+ static_rte_security, static_rte_cryptodev, static_rte_bus_pci],
+ include_directories: includes,
+ c_args: avx512_args)
+ objs += sxe2_avx512_lib.extract_objects('sxe2_txrx_vec_avx512.c')
+ endif
endif
sources += files(
diff --git a/drivers/net/sxe2/sxe2_drv_cmd.h b/drivers/net/sxe2/sxe2_drv_cmd.h
index bba6476c2e..ccc9c20ef4 100644
--- a/drivers/net/sxe2/sxe2_drv_cmd.h
+++ b/drivers/net/sxe2/sxe2_drv_cmd.h
@@ -67,20 +67,20 @@ enum sxe2_dev_type {
SXE2_DEV_T_MAX,
};
-struct sxe2_drv_queue_caps {
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_queue_caps {
uint16_t queues_cnt;
uint16_t base_idx_in_pf;
-};
+} __rte_packed_end;
-struct sxe2_drv_msix_caps {
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_msix_caps {
uint16_t msix_vectors_cnt;
uint16_t base_idx_in_func;
-};
+} __rte_packed_end;
-struct sxe2_drv_rss_hash_caps {
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_rss_hash_caps {
uint16_t hash_key_size;
uint16_t lut_key_size;
-};
+} __rte_packed_end;
enum sxe2_vf_vsi_valid {
SXE2_VF_VSI_BOTH = 0,
@@ -89,18 +89,18 @@ enum sxe2_vf_vsi_valid {
SXE2_VF_VSI_MAX,
};
-struct sxe2_drv_vsi_caps {
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_vsi_caps {
uint16_t func_id;
uint16_t dpdk_vsi_id;
uint16_t kernel_vsi_id;
uint16_t vsi_type;
-};
+} __rte_packed_end;
-struct sxe2_drv_representor_caps {
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_representor_caps {
uint16_t cnt_repr_vf;
uint8_t rsv[2];
struct sxe2_drv_vsi_caps repr_vf_id[256];
-};
+} __rte_packed_end;
enum sxe2_phys_port_name_type {
SXE2_PHYS_PORT_NAME_TYPE_NOTSET = 0,
@@ -111,25 +111,25 @@ enum sxe2_phys_port_name_type {
SXE2_PHYS_PORT_NAME_TYPE_UNKNOWN,
};
-struct sxe2_switchdev_mode_info {
+struct __rte_aligned(4) __rte_packed_begin sxe2_switchdev_mode_info {
uint8_t pf_id;
uint8_t is_switchdev;
uint8_t rsv[2];
-};
+} __rte_packed_end;
-struct sxe2_switchdev_cpvsi_info {
+struct __rte_aligned(4) __rte_packed_begin sxe2_switchdev_cpvsi_info {
uint16_t cp_vsi_id;
uint8_t rsv[2];
-};
+} __rte_packed_end;
-struct sxe2_txsch_caps {
+struct __rte_aligned(4) __rte_packed_begin sxe2_txsch_caps {
uint8_t layer_cap;
uint8_t tm_mid_node_num;
uint8_t prio_num;
uint8_t rev;
-};
+} __rte_packed_end;
-struct sxe2_drv_dev_caps_resp {
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_dev_caps_resp {
struct sxe2_drv_queue_caps queue_caps;
struct sxe2_drv_msix_caps msix_caps;
struct sxe2_drv_rss_hash_caps rss_hash_caps;
@@ -141,24 +141,24 @@ struct sxe2_drv_dev_caps_resp {
uint8_t dev_type;
uint8_t rev;
uint32_t cap_flags;
-};
+} __rte_packed_end;
-struct sxe2_drv_dev_info_resp {
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_dev_info_resp {
uint64_t dsn;
uint16_t vsi_id;
uint8_t rsv[2];
uint8_t mac_addr[SXE2_ETH_ALEN];
uint8_t rsv2[2];
-};
+} __rte_packed_end;
-struct sxe2_drv_dev_fw_info_resp {
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_dev_fw_info_resp {
uint8_t main_version_id;
uint8_t sub_version_id;
uint8_t fix_version_id;
uint8_t build_id;
-};
+} __rte_packed_end;
-struct sxe2_drv_rxq_ctxt {
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_rxq_ctxt {
uint64_t dma_addr;
uint32_t max_lro_size;
uint32_t split_type_mask;
@@ -170,62 +170,62 @@ struct sxe2_drv_rxq_ctxt {
uint8_t keep_crc_en;
uint8_t split_en;
uint8_t desc_size;
-};
+} __rte_packed_end;
-struct sxe2_drv_rxq_cfg_req {
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_rxq_cfg_req {
uint16_t q_cnt;
uint16_t vsi_id;
uint16_t max_frame_size;
uint8_t rsv[2];
struct sxe2_drv_rxq_ctxt cfg[];
-};
+} __rte_packed_end;
-struct sxe2_drv_txq_ctxt {
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_txq_ctxt {
uint64_t dma_addr;
uint32_t sched_mode;
uint16_t queue_id;
uint16_t depth;
uint16_t vsi_id;
uint8_t rsv[2];
-};
+} __rte_packed_end;
-struct sxe2_drv_txq_cfg_req {
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_txq_cfg_req {
uint16_t q_cnt;
uint16_t vsi_id;
struct sxe2_drv_txq_ctxt cfg[];
-};
+} __rte_packed_end;
-struct sxe2_drv_q_switch_req {
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_q_switch_req {
uint16_t q_idx;
uint16_t vsi_id;
uint8_t is_enable;
uint8_t sched_mode;
uint8_t rsv[2];
-};
+} __rte_packed_end;
-struct sxe2_drv_vsi_create_req_resp {
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_vsi_create_req_resp {
uint16_t vsi_id;
uint16_t vsi_type;
struct sxe2_drv_queue_caps used_queues;
struct sxe2_drv_msix_caps used_msix;
-};
+} __rte_packed_end;
-struct sxe2_drv_vsi_free_req {
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_vsi_free_req {
uint16_t vsi_id;
uint8_t rsv[2];
-};
+} __rte_packed_end;
-struct sxe2_drv_vsi_info_get_req {
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_vsi_info_get_req {
uint16_t vsi_id;
uint8_t rsv[2];
-};
+} __rte_packed_end;
-struct sxe2_drv_vsi_info_get_resp {
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_vsi_info_get_resp {
uint16_t vsi_id;
uint16_t vsi_type;
struct sxe2_drv_queue_caps used_queues;
struct sxe2_drv_msix_caps used_msix;
-};
+} __rte_packed_end;
enum sxe2_drv_cmd_module {
SXE2_DRV_CMD_MODULE_HANDSHAKE = 0,
diff --git a/drivers/net/sxe2/sxe2_ethdev.c b/drivers/net/sxe2/sxe2_ethdev.c
index b6cc8703a7..066e1faf7e 100644
--- a/drivers/net/sxe2/sxe2_ethdev.c
+++ b/drivers/net/sxe2/sxe2_ethdev.c
@@ -891,7 +891,7 @@ static int32_t sxe2_eth_pmd_probe_pf(struct sxe2_common_device *cdev,
static int32_t sxe2_parse_eth_devargs(struct rte_device *dev,
struct rte_eth_devargs *eth_da)
{
- int ret = 0;
+ int32_t ret = 0;
if (dev->devargs == NULL)
return 0;
diff --git a/drivers/net/sxe2/sxe2_txrx.c b/drivers/net/sxe2/sxe2_txrx.c
index 8d17535301..aa1c474088 100644
--- a/drivers/net/sxe2/sxe2_txrx.c
+++ b/drivers/net/sxe2/sxe2_txrx.c
@@ -157,6 +157,19 @@ void sxe2_tx_mode_func_set(struct rte_eth_dev *dev)
if (ret == 0 &&
rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_128) {
tx_mode_flags = vec_flags;
+#ifdef RTE_ARCH_X86
+ if ((rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_512) &&
+ (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512F) == 1) &&
+ (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512BW) == 1)) {
+#ifdef CC_AVX512_SUPPORT
+ tx_mode_flags |= SXE2_TX_MODE_VEC_AVX512;
+#else
+ PMD_LOG_INFO(TX, "AVX512 is not supported in build env.");
+#endif
+ }
+ if ((tx_mode_flags & SXE2_TX_MODE_VEC_SET_MASK) == 0)
+ tx_mode_flags |= SXE2_TX_MODE_VEC_SSE;
+#endif
if (tx_mode_flags & SXE2_TX_MODE_VEC_SET_MASK) {
ret = sxe2_tx_queues_vec_prepare(dev);
if (ret != 0)
@@ -172,14 +185,25 @@ void sxe2_tx_mode_func_set(struct rte_eth_dev *dev)
tx_mode_flags = adapter->q_ctxt.tx_mode_flags;
}
-#ifdef RTE_ARCH_X86
if (tx_mode_flags & SXE2_TX_MODE_VEC_SET_MASK) {
- if (tx_mode_flags & SXE2_TX_MODE_VEC_OFFLOAD) {
- dev->tx_pkt_prepare = sxe2_tx_pkts_prepare;
- dev->tx_pkt_burst = sxe2_tx_pkts_vec_sse;
+ dev->tx_pkt_prepare = NULL;
+#ifdef RTE_ARCH_X86
+ if (tx_mode_flags & SXE2_TX_MODE_VEC_AVX512) {
+#ifdef CC_AVX512_SUPPORT
+ if (tx_mode_flags & SXE2_TX_MODE_VEC_OFFLOAD) {
+ dev->tx_pkt_prepare = sxe2_tx_pkts_prepare;
+ dev->tx_pkt_burst = sxe2_tx_pkts_vec_avx512;
+ } else {
+ dev->tx_pkt_burst = sxe2_tx_pkts_vec_avx512_simple;
+ }
+#endif
} else {
- dev->tx_pkt_prepare = NULL;
- dev->tx_pkt_burst = sxe2_tx_pkts_vec_sse_simple;
+ if (tx_mode_flags & SXE2_TX_MODE_VEC_OFFLOAD) {
+ dev->tx_pkt_prepare = sxe2_tx_pkts_prepare;
+ dev->tx_pkt_burst = sxe2_tx_pkts_vec_sse;
+ } else {
+ dev->tx_pkt_burst = sxe2_tx_pkts_vec_sse_simple;
+ }
}
} else {
#endif
@@ -201,8 +225,16 @@ static const struct {
} sxe2_tx_burst_infos[] = {
{ sxe2_tx_pkts, "Scalar" },
#ifdef RTE_ARCH_X86
- { sxe2_tx_pkts_vec_sse, "Vector SSE" },
- { sxe2_tx_pkts_vec_sse_simple, "Vector SSE Simple" },
+#ifdef CC_AVX512_SUPPORT
+ { sxe2_tx_pkts_vec_avx512,
+ "Vector AVX512" },
+ { sxe2_tx_pkts_vec_avx512_simple,
+ "Vector AVX512 Simple" },
+#endif
+ { sxe2_tx_pkts_vec_sse,
+ "Vector SSE" },
+ { sxe2_tx_pkts_vec_sse_simple,
+ "Vector SSE Simple" },
#endif
};
@@ -288,6 +320,20 @@ void sxe2_rx_mode_func_set(struct rte_eth_dev *dev)
if (ret == 0 &&
rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_128) {
rx_mode_flags = vec_flags;
+#ifdef RTE_ARCH_X86
+ if ((rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_512) &&
+ (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512F) == 1) &&
+ (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512BW) == 1)) {
+#ifdef CC_AVX512_SUPPORT
+ rx_mode_flags |= SXE2_RX_MODE_VEC_AVX512;
+#else
+ PMD_LOG_INFO(RX, "AVX512 support detected but not enabled");
+#endif
+ }
+ if ((rx_mode_flags & SXE2_RX_MODE_VEC_SET_MASK) == 0 &&
+ rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_128)
+ rx_mode_flags |= SXE2_RX_MODE_VEC_SSE;
+#endif
if ((rx_mode_flags & SXE2_RX_MODE_VEC_SET_MASK) != 0) {
ret = sxe2_rx_queues_vec_prepare(dev);
if (ret != 0)
@@ -301,7 +347,16 @@ void sxe2_rx_mode_func_set(struct rte_eth_dev *dev)
#ifdef RTE_ARCH_X86
if (rx_mode_flags & SXE2_RX_MODE_VEC_SET_MASK) {
- dev->rx_pkt_burst = sxe2_rx_pkts_scattered_vec_sse_offload;
+ if (rx_mode_flags & SXE2_RX_MODE_VEC_AVX512) {
+#ifdef CC_AVX512_SUPPORT
+ if (rx_mode_flags & SXE2_RX_MODE_VEC_OFFLOAD)
+ dev->rx_pkt_burst = sxe2_rx_pkts_scattered_vec_avx512_offload;
+ else
+ dev->rx_pkt_burst = sxe2_rx_pkts_scattered_vec_avx512;
+#endif
+ } else {
+ dev->rx_pkt_burst = sxe2_rx_pkts_scattered_vec_sse_offload;
+ }
return;
}
#endif
@@ -315,19 +370,30 @@ static const struct {
eth_rx_burst_t rx_burst;
const char *info;
} sxe2_rx_burst_infos[] = {
- { sxe2_rx_pkts_scattered, "Scalar Scattered" },
- { sxe2_rx_pkts_scattered_split, "Scalar Scattered split" },
+ { sxe2_rx_pkts_scattered,
+ "Scalar Scattered" },
+ { sxe2_rx_pkts_scattered_split,
+ "Scalar Scattered split" },
#ifdef RTE_ARCH_X86
- { sxe2_rx_pkts_scattered_vec_sse_offload, "Vector SSE Scattered" },
+#ifdef CC_AVX512_SUPPORT
+ { sxe2_rx_pkts_scattered_vec_avx512,
+ "Vector AVX512 Scattered" },
+ { sxe2_rx_pkts_scattered_vec_avx512_offload,
+ "Offload Vector AVX512 Scattered" },
+#endif
+ { sxe2_rx_pkts_scattered_vec_sse_offload,
+ "Vector SSE Scattered" },
#endif
};
int32_t sxe2_rx_burst_mode_get(struct rte_eth_dev *dev,
- __rte_unused uint16_t queue_id, struct rte_eth_burst_mode *mode)
+ __rte_unused uint16_t queue_id,
+ struct rte_eth_burst_mode *mode)
{
eth_rx_burst_t pkt_burst = dev->rx_pkt_burst;
int32_t ret = -EINVAL;
uint32_t i, size;
+
size = RTE_DIM(sxe2_rx_burst_infos);
for (i = 0; i < size; ++i) {
if (pkt_burst == sxe2_rx_burst_infos[i].rx_burst) {
diff --git a/drivers/net/sxe2/sxe2_txrx_vec.c b/drivers/net/sxe2/sxe2_txrx_vec.c
index 8df4954d86..cf004f5eb2 100644
--- a/drivers/net/sxe2/sxe2_txrx_vec.c
+++ b/drivers/net/sxe2/sxe2_txrx_vec.c
@@ -165,16 +165,54 @@ static void sxe2_tx_queue_mbufs_release_vec(struct sxe2_tx_queue *txq)
return;
}
i = txq->next_dd - (txq->rs_thresh - 1);
- buffer = txq->buffer_ring;
- if (txq->next_use < i) {
- for ( ; i < txq->ring_depth; ++i) {
+#ifdef CC_AVX512_SUPPORT
+ struct rte_eth_dev *dev;
+ struct sxe2_tx_buffer_vec *buffer_vec;
+
+ dev = &rte_eth_devices[txq->port_id];
+
+ if (dev->tx_pkt_burst == sxe2_tx_pkts_vec_avx512 ||
+ dev->tx_pkt_burst == sxe2_tx_pkts_vec_avx512_simple) {
+ buffer_vec = (struct sxe2_tx_buffer_vec *)txq->buffer_ring;
+
+ if (txq->next_use < i) {
+ for ( ; i < txq->ring_depth; ++i) {
+ if (buffer_vec[i].mbuf != NULL) {
+ rte_pktmbuf_free_seg(buffer_vec[i].mbuf);
+ buffer_vec[i].mbuf = NULL;
+ }
+ }
+ i = 0;
+ }
+ for ( ; i < txq->next_use; ++i) {
+ if (buffer_vec[i].mbuf != NULL) {
+ rte_pktmbuf_free_seg(buffer_vec[i].mbuf);
+ buffer_vec[i].mbuf = NULL;
+ }
+ }
+ } else {
+#endif
+ buffer = txq->buffer_ring;
+ buffer = txq->buffer_ring;
+ if (txq->next_use < i) {
+ for ( ; i < txq->ring_depth; ++i) {
+ if (buffer[i].mbuf != NULL) {
+ rte_pktmbuf_free_seg(buffer[i].mbuf);
+ buffer[i].mbuf = NULL;
+ }
+ }
+ i = 0;
+ }
+ for (; i < txq->next_use; ++i) {
if (buffer[i].mbuf != NULL) {
rte_pktmbuf_free_seg(buffer[i].mbuf);
buffer[i].mbuf = NULL;
}
}
- i = 0;
+#ifdef CC_AVX512_SUPPORT
}
+#endif
+
for (; i < txq->next_use; ++i) {
if (buffer[i].mbuf != NULL) {
rte_pktmbuf_free_seg(buffer[i].mbuf);
diff --git a/drivers/net/sxe2/sxe2_txrx_vec.h b/drivers/net/sxe2/sxe2_txrx_vec.h
index 04ff4d96a5..af7c8d12b2 100644
--- a/drivers/net/sxe2/sxe2_txrx_vec.h
+++ b/drivers/net/sxe2/sxe2_txrx_vec.h
@@ -11,15 +11,19 @@
#define SXE2_RX_MODE_VEC_SIMPLE RTE_BIT32(0)
#define SXE2_RX_MODE_VEC_OFFLOAD RTE_BIT32(1)
#define SXE2_RX_MODE_VEC_SSE RTE_BIT32(2)
+#define SXE2_RX_MODE_VEC_AVX512 RTE_BIT32(4)
#define SXE2_RX_MODE_BATCH_ALLOC RTE_BIT32(10)
#define SXE2_RX_MODE_VEC_SET_MASK (SXE2_RX_MODE_VEC_SIMPLE | \
- SXE2_RX_MODE_VEC_OFFLOAD | SXE2_RX_MODE_VEC_SSE)
+ SXE2_RX_MODE_VEC_OFFLOAD | SXE2_RX_MODE_VEC_SSE | \
+ SXE2_RX_MODE_VEC_AVX512)
#define SXE2_TX_MODE_VEC_SIMPLE RTE_BIT32(0)
#define SXE2_TX_MODE_VEC_OFFLOAD RTE_BIT32(1)
#define SXE2_TX_MODE_VEC_SSE RTE_BIT32(2)
+#define SXE2_TX_MODE_VEC_AVX512 RTE_BIT32(4)
#define SXE2_TX_MODE_SIMPLE_BATCH RTE_BIT32(10)
#define SXE2_TX_MODE_VEC_SET_MASK (SXE2_TX_MODE_VEC_SIMPLE | \
- SXE2_TX_MODE_VEC_OFFLOAD | SXE2_TX_MODE_VEC_SSE)
+ SXE2_TX_MODE_VEC_OFFLOAD | SXE2_TX_MODE_VEC_SSE | \
+ SXE2_TX_MODE_VEC_AVX512)
#define SXE2_TX_VEC_NO_SUPPORT_OFFLOAD ( \
RTE_ETH_TX_OFFLOAD_MULTI_SEGS | \
RTE_ETH_TX_OFFLOAD_QINQ_INSERT | \
@@ -54,6 +58,16 @@ uint16_t sxe2_tx_pkts_vec_sse(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_
uint16_t sxe2_tx_pkts_vec_sse_simple(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts);
uint16_t sxe2_rx_pkts_scattered_vec_sse_offload(void *rx_queue,
struct rte_mbuf **rx_pkts, uint16_t nb_pkts);
+uint16_t sxe2_tx_pkts_vec_avx512_simple(void *tx_queue,
+ struct rte_mbuf **tx_pkts, uint16_t nb_pkts);
+uint16_t sxe2_tx_pkts_vec_avx512(void *tx_queue,
+ struct rte_mbuf **tx_pkts, uint16_t nb_pkts);
+uint16_t sxe2_tx_pkts_vec_avx512_ctx_offload(void *tx_queue,
+ struct rte_mbuf **tx_pkts, uint16_t nb_pkts);
+uint16_t sxe2_rx_pkts_scattered_vec_avx512(void *rx_queue,
+ struct rte_mbuf **rx_pkts, uint16_t nb_pkts);
+uint16_t sxe2_rx_pkts_scattered_vec_avx512_offload(void *rx_queue,
+ struct rte_mbuf **rx_pkts, uint16_t nb_pkts);
#endif
int32_t __rte_cold sxe2_tx_vec_support_check(struct rte_eth_dev *dev, uint32_t *vec_flags);
int32_t __rte_cold sxe2_tx_queues_vec_prepare(struct rte_eth_dev *dev);
diff --git a/drivers/net/sxe2/sxe2_txrx_vec_avx512.c b/drivers/net/sxe2/sxe2_txrx_vec_avx512.c
new file mode 100644
index 0000000000..2aec8037dd
--- /dev/null
+++ b/drivers/net/sxe2/sxe2_txrx_vec_avx512.c
@@ -0,0 +1,897 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#ifndef SXE2_TEST
+#include <rte_vect.h>
+
+#include "sxe2_ethdev.h"
+#include "sxe2_common_log.h"
+#include "sxe2_queue.h"
+#include "sxe2_txrx_vec.h"
+#include "sxe2_txrx_vec_common.h"
+#include "sxe2_vsi.h"
+
+static __rte_always_inline int32_t sxe2_tx_bufs_free_vec_avx512(struct sxe2_tx_queue *txq)
+{
+ struct sxe2_tx_buffer_vec *buffer;
+ struct rte_mbuf *mbuf;
+ struct rte_mbuf *mbuf_free_arr[SXE2_TX_FREE_BUFFER_SIZE_MAX_VEC];
+ struct rte_mempool *mp;
+ struct rte_mempool_cache *cache;
+ void **cache_objs;
+ uint32_t copied;
+ uint32_t i;
+ int32_t ret;
+ uint16_t rs_thresh;
+ uint16_t free_num;
+
+ if (rte_cpu_to_le_64(SXE2_TX_DESC_DTYPE_DESC_DONE) !=
+ (txq->desc_ring[txq->next_dd].wb.dd &
+ rte_cpu_to_le_64(SXE2_TX_DESC_DTYPE_MASK))) {
+ ret = 0;
+ goto l_end;
+ }
+
+ rs_thresh = txq->rs_thresh;
+
+ buffer = (struct sxe2_tx_buffer_vec *)txq->buffer_ring;
+ buffer += txq->next_dd - (rs_thresh - 1);
+
+ if ((txq->offloads & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE) &&
+ (rs_thresh & 31) == 0) {
+ mp = buffer[0].mbuf->pool;
+ cache = rte_mempool_default_cache(mp, rte_lcore_id());
+
+ if (cache == NULL || cache->len)
+ goto normal;
+
+ if (rs_thresh > RTE_MEMPOOL_CACHE_MAX_SIZE) {
+ (void)rte_mempool_ops_enqueue_bulk(mp, (void *)buffer, rs_thresh);
+ goto done;
+ }
+ cache_objs = &cache->objs[cache->len];
+
+ copied = 0;
+ while (copied < rs_thresh) {
+ const __m512i objs0 = _mm512_loadu_si512(&buffer[copied]);
+ const __m512i objs1 = _mm512_loadu_si512(&buffer[copied + 8]);
+ const __m512i objs2 = _mm512_loadu_si512(&buffer[copied + 16]);
+ const __m512i objs3 = _mm512_loadu_si512(&buffer[copied + 24]);
+
+ _mm512_storeu_si512(&cache_objs[copied], objs0);
+ _mm512_storeu_si512(&cache_objs[copied + 8], objs1);
+ _mm512_storeu_si512(&cache_objs[copied + 16], objs2);
+ _mm512_storeu_si512(&cache_objs[copied + 24], objs3);
+ copied += 32;
+ }
+ cache->len += rs_thresh;
+
+ if (cache->len >= cache->flushthresh) {
+ (void)rte_mempool_ops_enqueue_bulk(mp,
+ &cache->objs[cache->size], cache->len - cache->size);
+ cache->len = cache->size;
+ }
+ goto done;
+ }
+
+normal:
+ mbuf = rte_pktmbuf_prefree_seg(buffer[0].mbuf);
+
+ if (likely(mbuf)) {
+ mbuf_free_arr[0] = mbuf;
+ free_num = 1;
+
+ for (i = 1; i < rs_thresh; ++i) {
+ mbuf = rte_pktmbuf_prefree_seg(buffer[i].mbuf);
+
+ if (likely(mbuf)) {
+ if (likely(mbuf->pool == mbuf_free_arr[0]->pool)) {
+ mbuf_free_arr[free_num] = mbuf;
+ free_num++;
+ } else {
+ rte_mempool_put_bulk(mbuf_free_arr[0]->pool,
+ (void *)mbuf_free_arr, free_num);
+
+ mbuf_free_arr[0] = mbuf;
+ free_num = 1;
+ }
+ }
+ }
+
+ rte_mempool_put_bulk(mbuf_free_arr[0]->pool,
+ (void *)mbuf_free_arr, free_num);
+ } else {
+ for (i = 1; i < rs_thresh; ++i) {
+ mbuf = rte_pktmbuf_prefree_seg(buffer[i].mbuf);
+ if (mbuf != NULL)
+ rte_mempool_put(mbuf->pool, mbuf);
+ }
+ }
+
+done:
+ txq->desc_free_num += txq->rs_thresh;
+ txq->next_dd += txq->rs_thresh;
+ if (txq->next_dd >= txq->ring_depth)
+ txq->next_dd = txq->rs_thresh - 1;
+ ret = rs_thresh;
+
+l_end:
+ return ret;
+}
+
+static __rte_always_inline void
+sxe2_tx_desc_fill_one_avx512(volatile union sxe2_tx_data_desc *desc, struct rte_mbuf *pkt,
+ uint64_t desc_cmd, bool with_offloads)
+{
+ __m128i data_desc;
+ uint64_t desc_qw1;
+ uint32_t desc_offset;
+
+ desc_qw1 = (SXE2_TX_DESC_DTYPE_DATA |
+ ((uint64_t)desc_cmd) << SXE2_TX_DATA_DESC_CMD_SHIFT |
+ ((uint64_t)pkt->data_len) << SXE2_TX_DATA_DESC_BUF_SZ_SHIFT);
+ desc_offset = SXE2_TX_DATA_DESC_MACLEN_VAL(pkt->l2_len);
+ desc_qw1 |= ((uint64_t)desc_offset) << SXE2_TX_DATA_DESC_OFFSET_SHIFT;
+ if (with_offloads)
+ sxe2_tx_desc_fill_offloads(pkt, &desc_qw1);
+
+ data_desc = _mm_set_epi64x(desc_qw1, rte_pktmbuf_iova(pkt));
+
+ _mm_store_si128(RTE_CAST_PTR(__m128i *, desc), data_desc);
+}
+
+static __rte_always_inline
+void sxe2_tx_desc_fill_avx512(volatile union sxe2_tx_data_desc *desc, struct rte_mbuf **pkts,
+ uint16_t pkts_num, uint64_t desc_cmd, bool with_offloads)
+{
+ __m512i desc_group;
+ uint64_t desc0_qw1;
+ uint64_t desc1_qw1;
+ uint64_t desc2_qw1;
+ uint64_t desc3_qw1;
+
+ const uint64_t desc_qw1_com = (SXE2_TX_DESC_DTYPE_DATA |
+ ((uint64_t)desc_cmd) << SXE2_TX_DATA_DESC_CMD_SHIFT);
+ uint32_t desc_offset[4] = {0};
+
+ while (pkts_num > 3) {
+ desc3_qw1 = desc_qw1_com |
+ ((uint64_t)pkts[3]->data_len) << SXE2_TX_DATA_DESC_BUF_SZ_SHIFT;
+
+ desc_offset[3] = SXE2_TX_DATA_DESC_MACLEN_VAL(pkts[3]->l2_len);
+ desc3_qw1 |= ((uint64_t)desc_offset[3]) << SXE2_TX_DATA_DESC_OFFSET_SHIFT;
+ if (with_offloads)
+ sxe2_tx_desc_fill_offloads(pkts[3], &desc3_qw1);
+
+ desc2_qw1 = desc_qw1_com |
+ ((uint64_t)pkts[2]->data_len) << SXE2_TX_DATA_DESC_BUF_SZ_SHIFT;
+ desc_offset[2] = SXE2_TX_DATA_DESC_MACLEN_VAL(pkts[2]->l2_len);
+ desc2_qw1 |= ((uint64_t)desc_offset[2]) << SXE2_TX_DATA_DESC_OFFSET_SHIFT;
+ if (with_offloads)
+ sxe2_tx_desc_fill_offloads(pkts[2], &desc2_qw1);
+
+ desc1_qw1 = (desc_qw1_com |
+ ((uint64_t)pkts[1]->data_len) << SXE2_TX_DATA_DESC_BUF_SZ_SHIFT);
+ desc_offset[1] = SXE2_TX_DATA_DESC_MACLEN_VAL(pkts[1]->l2_len);
+ desc1_qw1 |= ((uint64_t)desc_offset[1]) << SXE2_TX_DATA_DESC_OFFSET_SHIFT;
+ if (with_offloads)
+ sxe2_tx_desc_fill_offloads(pkts[1], &desc1_qw1);
+
+ desc0_qw1 = (desc_qw1_com |
+ ((uint64_t)pkts[0]->data_len) << SXE2_TX_DATA_DESC_BUF_SZ_SHIFT);
+ desc_offset[0] = SXE2_TX_DATA_DESC_MACLEN_VAL(pkts[0]->l2_len);
+ desc0_qw1 |= ((uint64_t)desc_offset[0]) << SXE2_TX_DATA_DESC_OFFSET_SHIFT;
+ if (with_offloads)
+ sxe2_tx_desc_fill_offloads(pkts[0], &desc0_qw1);
+
+ desc_group =
+ _mm512_set_epi64(desc3_qw1, rte_pktmbuf_iova(pkts[3]),
+ desc2_qw1, rte_pktmbuf_iova(pkts[2]),
+ desc1_qw1, rte_pktmbuf_iova(pkts[1]),
+ desc0_qw1, rte_pktmbuf_iova(pkts[0]));
+
+ _mm512_storeu_si512(RTE_CAST_PTR(void *, desc), desc_group);
+
+ pkts_num -= 4;
+ desc += 4;
+ pkts += 4;
+ }
+
+ while (pkts_num) {
+ sxe2_tx_desc_fill_one_avx512(desc, *pkts, desc_cmd, with_offloads);
+
+ pkts_num--;
+ desc++;
+ pkts++;
+ }
+}
+
+static __rte_always_inline void
+sxe2_tx_pkts_mbuf_fill_avx512(struct sxe2_tx_buffer_vec *buffer,
+ struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+ uint16_t i;
+
+ for (i = 0; i < nb_pkts; ++i)
+ buffer[i].mbuf = tx_pkts[i];
+}
+
+static __rte_always_inline uint16_t
+sxe2_tx_pkts_vec_avx512_batch(struct sxe2_tx_queue *txq, struct rte_mbuf **tx_pkts,
+ uint16_t nb_pkts, bool with_offloads)
+{
+ volatile union sxe2_tx_data_desc *desc;
+ struct sxe2_tx_buffer_vec *buffer;
+ uint16_t next_use;
+ uint16_t res_num;
+ uint16_t tx_num;
+
+ if (txq->desc_free_num < txq->free_thresh)
+ (void)sxe2_tx_bufs_free_vec_avx512(txq);
+
+ nb_pkts = RTE_MIN(txq->desc_free_num, nb_pkts);
+ if (unlikely(nb_pkts == 0)) {
+ PMD_LOG_DEBUG(TX, "Tx pkts avx512 batch: may not enough free desc, "
+ "free_desc=%u, need_tx_pkts=%u",
+ txq->desc_free_num, nb_pkts);
+ goto l_end;
+ }
+ tx_num = nb_pkts;
+
+ next_use = txq->next_use;
+ desc = &txq->desc_ring[next_use];
+ buffer = (struct sxe2_tx_buffer_vec *)txq->buffer_ring;
+ buffer += next_use;
+
+ txq->desc_free_num -= nb_pkts;
+
+ res_num = txq->ring_depth - txq->next_use;
+
+ if (tx_num >= res_num) {
+ sxe2_tx_pkts_mbuf_fill_avx512(buffer, tx_pkts, res_num);
+
+ sxe2_tx_desc_fill_avx512(desc, tx_pkts, res_num,
+ SXE2_TX_DATA_DESC_CMD_EOP, with_offloads);
+ tx_pkts += (res_num - 1);
+ desc += (res_num - 1);
+
+ sxe2_tx_desc_fill_one_avx512(desc, *tx_pkts++,
+ (SXE2_TX_DATA_DESC_CMD_EOP | SXE2_TX_DATA_DESC_CMD_RS),
+ with_offloads);
+
+ tx_num -= res_num;
+
+ next_use = 0;
+ txq->next_rs = txq->rs_thresh - 1;
+ desc = txq->desc_ring;
+ buffer = (struct sxe2_tx_buffer_vec *)txq->buffer_ring;
+ }
+
+ sxe2_tx_pkts_mbuf_fill_avx512(buffer, tx_pkts, tx_num);
+
+ sxe2_tx_desc_fill_avx512(desc, tx_pkts, tx_num,
+ SXE2_TX_DATA_DESC_CMD_EOP, with_offloads);
+
+ next_use += tx_num;
+ if (next_use > txq->next_rs) {
+ txq->desc_ring[txq->next_rs].read.type_cmd_off_bsz_l2t |=
+ rte_cpu_to_le_64(SXE2_TX_DATA_DESC_CMD_RS_MASK);
+
+ txq->next_rs += txq->rs_thresh;
+ }
+ txq->next_use = next_use;
+
+ SXE2_PCI_REG_WRITE_WC(txq->tdt_reg_addr, next_use);
+ PMD_LOG_DEBUG(TX, "port_id=%u queue_id=%u next_use=%u send_pkts=%u",
+ txq->port_id, txq->queue_id, next_use, nb_pkts);
+l_end:
+ return nb_pkts;
+}
+
+static __rte_always_inline uint16_t
+sxe2_tx_pkts_vec_avx512_common(struct sxe2_tx_queue *txq, struct rte_mbuf **tx_pkts,
+ uint16_t nb_pkts, bool with_offloads)
+{
+ uint16_t tx_done_num = 0;
+ uint16_t tx_once_num;
+ uint16_t tx_need_num;
+
+ while (nb_pkts) {
+ tx_need_num = RTE_MIN(nb_pkts, txq->rs_thresh);
+ tx_once_num =
+ sxe2_tx_pkts_vec_avx512_batch(txq, tx_pkts + tx_done_num,
+ tx_need_num, with_offloads);
+ nb_pkts -= tx_once_num;
+ tx_done_num += tx_once_num;
+ if (tx_once_num < tx_need_num)
+ break;
+ }
+
+ return tx_done_num;
+}
+
+uint16_t sxe2_tx_pkts_vec_avx512_simple(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+ return sxe2_tx_pkts_vec_avx512_common((struct sxe2_tx_queue *)tx_queue,
+ tx_pkts, nb_pkts, false);
+}
+
+uint16_t sxe2_tx_pkts_vec_avx512(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+ return sxe2_tx_pkts_vec_avx512_common((struct sxe2_tx_queue *)tx_queue,
+ tx_pkts, nb_pkts, true);
+}
+
+static inline void sxe2_rx_queue_rearm_avx512(struct sxe2_rx_queue *rxq)
+{
+ volatile union sxe2_rx_desc *desc;
+ struct rte_mbuf **buffer;
+ struct rte_mbuf *mbuf0, *mbuf1;
+ __m128i dma_addr0, dma_addr1;
+ __m128i virt_addr0, virt_addr1;
+ __m128i hdr_room = _mm_set_epi64x(RTE_PKTMBUF_HEADROOM, RTE_PKTMBUF_HEADROOM);
+ int32_t ret;
+ uint16_t i;
+ uint16_t new_tail;
+
+ buffer = &rxq->buffer_ring[rxq->realloc_start];
+ desc = &rxq->desc_ring[rxq->realloc_start];
+
+ ret = rte_mempool_get_bulk(rxq->mb_pool, (void *)buffer, SXE2_RX_REARM_THRESH_VEC);
+ if (ret != 0) {
+ if ((rxq->realloc_num + SXE2_RX_REARM_THRESH_VEC) >= rxq->ring_depth) {
+ dma_addr0 = _mm_setzero_si128();
+ for (i = 0; i < SXE2_RX_NUM_PER_LOOP_AVX; ++i) {
+ buffer[i] = &rxq->fake_mbuf;
+ _mm_store_si128(RTE_CAST_PTR(__m128i *, &desc[i].read),
+ dma_addr0);
+ }
+ }
+
+ rxq->vsi->adapter->dev_info.dev_data->rx_mbuf_alloc_failed +=
+ SXE2_RX_REARM_THRESH_VEC;
+ goto l_end;
+ }
+
+ for (i = 0; i < SXE2_RX_REARM_THRESH_VEC; i += 2, buffer += 2) {
+ mbuf0 = buffer[0];
+ mbuf1 = buffer[1];
+
+#if RTE_IOVA_IN_MBUF
+
+ RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, buf_iova) !=
+ offsetof(struct rte_mbuf, buf_addr) + 8);
+#endif
+ virt_addr0 = _mm_loadu_si128((__m128i *)&mbuf0->buf_addr);
+ virt_addr1 = _mm_loadu_si128((__m128i *)&mbuf1->buf_addr);
+
+#if RTE_IOVA_IN_MBUF
+
+ dma_addr0 = _mm_unpackhi_epi64(virt_addr0, virt_addr0);
+ dma_addr1 = _mm_unpackhi_epi64(virt_addr1, virt_addr1);
+#else
+
+ dma_addr0 = _mm_unpacklo_epi64(virt_addr0, virt_addr0);
+ dma_addr1 = _mm_unpacklo_epi64(virt_addr1, virt_addr1);
+#endif
+
+ dma_addr0 = _mm_add_epi64(dma_addr0, hdr_room);
+ dma_addr1 = _mm_add_epi64(dma_addr1, hdr_room);
+
+ _mm_store_si128(RTE_CAST_PTR(__m128i *, &desc++->read), dma_addr0);
+ _mm_store_si128(RTE_CAST_PTR(__m128i *, &desc++->read), dma_addr1);
+ }
+
+ rxq->realloc_start += SXE2_RX_REARM_THRESH_VEC;
+ if (rxq->realloc_start >= rxq->ring_depth)
+ rxq->realloc_start = 0;
+ rxq->realloc_num -= SXE2_RX_REARM_THRESH_VEC;
+
+ new_tail = (rxq->realloc_start == 0) ? (rxq->ring_depth - 1) :
+ (rxq->realloc_start - 1);
+
+ SXE2_PCI_REG_WRITE_WC(rxq->rdt_reg_addr, new_tail);
+
+l_end:
+ return;
+}
+
+static __rte_always_inline uint16_t
+sxe2_rx_pkts_common_vec_avx512(struct sxe2_rx_queue *rxq, struct rte_mbuf **rx_pkts,
+ uint16_t nb_pkts, uint8_t *split_rxe_flags,
+ uint8_t *umbcast_flags, bool do_offload)
+{
+ const uint32_t *ptype_tbl = rxq->vsi->adapter->ptype_tbl;
+ const __m256i mbuf_init = _mm256_set_epi64x(0, 0, 0, rxq->mbuf_init_value);
+ struct rte_mbuf **buffer;
+ volatile union sxe2_rx_desc *desc;
+ __m512i mbufs4_7;
+ __m512i mbufs0_3;
+ __m256i mbufs6_7;
+ __m256i mbufs4_5;
+ __m256i mbufs2_3;
+ __m256i mbufs0_1;
+ uint32_t bit_num = 0;
+ uint16_t done_num = 0;
+ uint16_t i = 0;
+ uint16_t j = 0;
+
+ buffer = &rxq->buffer_ring[rxq->processing_idx];
+ desc = &rxq->desc_ring[rxq->processing_idx];
+
+ rte_prefetch0(desc);
+
+ nb_pkts = RTE_ALIGN_FLOOR(nb_pkts, SXE2_RX_NUM_PER_LOOP_AVX);
+
+ if (rxq->realloc_num > SXE2_RX_REARM_THRESH_VEC)
+ sxe2_rx_queue_rearm_avx512(rxq);
+
+ if (0 == (rte_le_to_cpu_64(desc->wb.status_err_ptype_len) & SXE2_RX_DESC_STATUS_DD_MASK))
+ goto l_end;
+
+ const __m512i crc_adjust =
+ _mm512_set4_epi32(0, -rxq->crc_len, -rxq->crc_len, 0);
+
+ const __m256i dd_mask = _mm256_set1_epi32(1);
+
+ const __m512i rvp_shuf_mask =
+ _mm512_set4_epi32((7 << 24) | (6 << 16) | (5 << 8) | 4,
+ (3 << 24) | (2 << 16) | (13 << 8) | 12,
+ (0xFFU << 24) | (0xFF << 16) | (13 << 8) | 12,
+ 0xFFFFFFFF);
+
+ const __m128i eop_shuf_mask =
+ _mm_set_epi8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 8, 0, 10, 2, 12, 4, 14, 6);
+
+ RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, pkt_len) !=
+ offsetof(struct rte_mbuf, rx_descriptor_fields1) + 4);
+ RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, data_len) !=
+ offsetof(struct rte_mbuf, rx_descriptor_fields1) + 8);
+ RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, vlan_tci) !=
+ offsetof(struct rte_mbuf, rx_descriptor_fields1) + 10);
+ RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, hash) !=
+ offsetof(struct rte_mbuf, rx_descriptor_fields1) + 12);
+
+ for (i = 0; i < nb_pkts; i += SXE2_RX_NUM_PER_LOOP_AVX,
+ desc += SXE2_RX_NUM_PER_LOOP_AVX) {
+ _mm256_storeu_si256((void *)&rx_pkts[i],
+ _mm256_loadu_si256((void *)&buffer[i]));
+#ifdef RTE_ARCH_X86_64
+ _mm256_storeu_si256((void *)&rx_pkts[i + 4],
+ _mm256_loadu_si256((void *)&buffer[i + 4]));
+#endif
+
+ const __m128i desc7 = _mm_loadu_si128(RTE_CAST_PTR(const __m128i *, desc + 7));
+ rte_compiler_barrier();
+ const __m128i desc6 = _mm_loadu_si128(RTE_CAST_PTR(const __m128i *, desc + 6));
+ rte_compiler_barrier();
+ const __m128i desc5 = _mm_loadu_si128(RTE_CAST_PTR(const __m128i *, desc + 5));
+ rte_compiler_barrier();
+ const __m128i desc4 = _mm_loadu_si128(RTE_CAST_PTR(const __m128i *, desc + 4));
+ rte_compiler_barrier();
+ const __m128i desc3 = _mm_loadu_si128(RTE_CAST_PTR(const __m128i *, desc + 3));
+ rte_compiler_barrier();
+ const __m128i desc2 = _mm_loadu_si128(RTE_CAST_PTR(const __m128i *, desc + 2));
+ rte_compiler_barrier();
+ const __m128i desc1 = _mm_loadu_si128(RTE_CAST_PTR(const __m128i *, desc + 1));
+ rte_compiler_barrier();
+ const __m128i desc0 = _mm_loadu_si128(RTE_CAST_PTR(const __m128i *, desc + 0));
+
+ const __m256i descs6_7 =
+ _mm256_inserti128_si256(_mm256_castsi128_si256(desc6), desc7, 1);
+ const __m256i descs4_5 =
+ _mm256_inserti128_si256(_mm256_castsi128_si256(desc4), desc5, 1);
+ const __m256i descs2_3 =
+ _mm256_inserti128_si256(_mm256_castsi128_si256(desc2), desc3, 1);
+ const __m256i descs0_1 =
+ _mm256_inserti128_si256(_mm256_castsi128_si256(desc0), desc1, 1);
+
+ const __m512i descs4_7 =
+ _mm512_inserti64x4(_mm512_castsi256_si512(descs4_5), descs6_7, 1);
+ const __m512i descs0_3 =
+ _mm512_inserti64x4(_mm512_castsi256_si512(descs0_1), descs2_3, 1);
+
+ if (split_rxe_flags != NULL) {
+ for (j = 0; j < SXE2_RX_NUM_PER_LOOP_AVX; j++)
+ rte_mbuf_prefetch_part2(rx_pkts[i + j]);
+ }
+
+ mbufs4_7 = _mm512_shuffle_epi8(descs4_7, rvp_shuf_mask);
+ mbufs0_3 = _mm512_shuffle_epi8(descs0_3, rvp_shuf_mask);
+
+ mbufs4_7 = _mm512_add_epi32(mbufs4_7, crc_adjust);
+ mbufs0_3 = _mm512_add_epi32(mbufs0_3, crc_adjust);
+
+ const __m512i ptype_mask = _mm512_set1_epi64(SXE2_RX_FLEX_DESC_PTYPE_M <<
+ SXE2_RX_FLEX_DESC_PTYPE_S);
+
+ __m512i ptypes4_7 = _mm512_and_si512(descs4_7, ptype_mask);
+ __m512i ptypes0_3 = _mm512_and_si512(descs0_3, ptype_mask);
+
+ const __m256i ptypes6_7 = _mm512_extracti64x4_epi64(ptypes4_7, 1);
+ const __m256i ptypes4_5 = _mm512_extracti64x4_epi64(ptypes4_7, 0);
+ const __m256i ptypes2_3 = _mm512_extracti64x4_epi64(ptypes0_3, 1);
+ const __m256i ptypes0_1 = _mm512_extracti64x4_epi64(ptypes0_3, 0);
+
+ const uint16_t ptype7 = _mm256_extract_epi16(ptypes6_7, 13);
+ const uint16_t ptype6 = _mm256_extract_epi16(ptypes6_7, 5);
+ const uint16_t ptype5 = _mm256_extract_epi16(ptypes4_5, 13);
+ const uint16_t ptype4 = _mm256_extract_epi16(ptypes4_5, 5);
+ const uint16_t ptype3 = _mm256_extract_epi16(ptypes2_3, 13);
+ const uint16_t ptype2 = _mm256_extract_epi16(ptypes2_3, 5);
+ const uint16_t ptype1 = _mm256_extract_epi16(ptypes0_1, 13);
+ const uint16_t ptype0 = _mm256_extract_epi16(ptypes0_1, 5);
+
+ const __m512i ptype_mask4_7 =
+ _mm512_set_epi32(0, 0, 0, ptype_tbl[ptype7],
+ 0, 0, 0, ptype_tbl[ptype6],
+ 0, 0, 0, ptype_tbl[ptype5],
+ 0, 0, 0, ptype_tbl[ptype4]);
+ const __m512i ptype_mask0_3 =
+ _mm512_set_epi32(0, 0, 0, ptype_tbl[ptype3],
+ 0, 0, 0, ptype_tbl[ptype2],
+ 0, 0, 0, ptype_tbl[ptype1],
+ 0, 0, 0, ptype_tbl[ptype0]);
+
+ mbufs4_7 = _mm512_or_si512(mbufs4_7, ptype_mask4_7);
+ mbufs0_3 = _mm512_or_si512(mbufs0_3, ptype_mask0_3);
+
+ mbufs6_7 = _mm512_extracti64x4_epi64(mbufs4_7, 1);
+ mbufs4_5 = _mm512_extracti64x4_epi64(mbufs4_7, 0);
+ mbufs2_3 = _mm512_extracti64x4_epi64(mbufs0_3, 1);
+ mbufs0_1 = _mm512_extracti64x4_epi64(mbufs0_3, 0);
+
+ const __m512i staterr_per_mask =
+ _mm512_set_epi32(0x17, 0x1F, 0x07, 0x0F,
+ 0x13, 0x1B, 0x03, 0x0B,
+ 0x16, 0x1E, 0x06, 0x0E,
+ 0x12, 0x1A, 0x02, 0x0A);
+ __m512i qw1_0_7 = _mm512_permutex2var_epi32(descs4_7,
+ staterr_per_mask,
+ descs0_3);
+
+ __m256i staterrs0_7 = _mm512_extracti64x4_epi64(qw1_0_7, 0);
+
+ __m256i stu_len0_7 = _mm512_extracti64x4_epi64(qw1_0_7, 1);
+ __m256i mbuf_flags = _mm256_setzero_si256();
+
+ if (do_offload) {
+ const __m256i desc_flags_mask = _mm256_set1_epi32(0xC0001C04);
+ const __m256i desc_flags_rss_mask = _mm256_set1_epi32(0x20000000);
+ const __m256i vlan_flags =
+ _mm256_set_epi8(0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, RTE_MBUF_F_RX_VLAN |
+ RTE_MBUF_F_RX_VLAN_STRIPPED,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, RTE_MBUF_F_RX_VLAN |
+ RTE_MBUF_F_RX_VLAN_STRIPPED,
+ 0, 0, 0, 0);
+
+ const __m256i rss_flags =
+ _mm256_set_epi8(0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, RTE_MBUF_F_RX_RSS_HASH,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, RTE_MBUF_F_RX_RSS_HASH,
+ 0, 0, 0, 0);
+
+ const __m256i cksum_flags =
+ _mm256_set_epi8(0, 0, 0, 0, 0, 0, 0,
+ 0,
+ ((RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD | RTE_MBUF_F_RX_L4_CKSUM_BAD |
+ RTE_MBUF_F_RX_IP_CKSUM_BAD) >> 1),
+ ((RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD | RTE_MBUF_F_RX_L4_CKSUM_BAD |
+ RTE_MBUF_F_RX_IP_CKSUM_GOOD) >> 1),
+ ((RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD | RTE_MBUF_F_RX_L4_CKSUM_GOOD |
+ RTE_MBUF_F_RX_IP_CKSUM_BAD) >> 1),
+ ((RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD | RTE_MBUF_F_RX_L4_CKSUM_GOOD |
+ RTE_MBUF_F_RX_IP_CKSUM_GOOD) >> 1),
+ ((RTE_MBUF_F_RX_L4_CKSUM_BAD | RTE_MBUF_F_RX_IP_CKSUM_BAD) >> 1),
+ ((RTE_MBUF_F_RX_L4_CKSUM_BAD | RTE_MBUF_F_RX_IP_CKSUM_GOOD) >> 1),
+ ((RTE_MBUF_F_RX_L4_CKSUM_GOOD | RTE_MBUF_F_RX_IP_CKSUM_BAD) >> 1),
+ ((RTE_MBUF_F_RX_L4_CKSUM_GOOD | RTE_MBUF_F_RX_IP_CKSUM_GOOD) >> 1),
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ ((RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD | RTE_MBUF_F_RX_L4_CKSUM_BAD |
+ RTE_MBUF_F_RX_IP_CKSUM_BAD) >> 1),
+ ((RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD | RTE_MBUF_F_RX_L4_CKSUM_BAD |
+ RTE_MBUF_F_RX_IP_CKSUM_GOOD) >> 1),
+ ((RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD | RTE_MBUF_F_RX_L4_CKSUM_GOOD |
+ RTE_MBUF_F_RX_IP_CKSUM_BAD) >> 1),
+ ((RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD | RTE_MBUF_F_RX_L4_CKSUM_GOOD |
+ RTE_MBUF_F_RX_IP_CKSUM_GOOD) >> 1),
+ ((RTE_MBUF_F_RX_L4_CKSUM_BAD | RTE_MBUF_F_RX_IP_CKSUM_BAD) >> 1),
+ ((RTE_MBUF_F_RX_L4_CKSUM_BAD | RTE_MBUF_F_RX_IP_CKSUM_GOOD) >> 1),
+ ((RTE_MBUF_F_RX_L4_CKSUM_GOOD | RTE_MBUF_F_RX_IP_CKSUM_BAD) >> 1),
+ ((RTE_MBUF_F_RX_L4_CKSUM_GOOD | RTE_MBUF_F_RX_IP_CKSUM_GOOD) >> 1));
+
+ const __m256i cksum_mask =
+ _mm256_set1_epi32(RTE_MBUF_F_RX_IP_CKSUM_MASK |
+ RTE_MBUF_F_RX_L4_CKSUM_MASK |
+ RTE_MBUF_F_RX_OUTER_L4_CKSUM_MASK |
+ RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD);
+
+ const __m256i vlan_mask =
+ _mm256_set1_epi32(RTE_MBUF_F_RX_VLAN |
+ RTE_MBUF_F_RX_VLAN_STRIPPED);
+
+ __m256i tmp_flags;
+ __m256i descs_flags = _mm256_and_si256(staterrs0_7, desc_flags_mask);
+ stu_len0_7 = _mm256_and_si256(stu_len0_7, desc_flags_rss_mask);
+
+ tmp_flags = _mm256_shuffle_epi8(vlan_flags, descs_flags);
+ mbuf_flags = _mm256_and_si256(tmp_flags, vlan_mask);
+
+ descs_flags = _mm256_srli_epi32(descs_flags, 10);
+ tmp_flags = _mm256_shuffle_epi8(cksum_flags, descs_flags);
+ tmp_flags = _mm256_slli_epi32(tmp_flags, 1);
+ tmp_flags = _mm256_and_si256(tmp_flags, cksum_mask);
+ mbuf_flags = _mm256_or_si256(mbuf_flags, tmp_flags);
+
+ descs_flags = _mm256_srli_epi32(stu_len0_7, 27);
+ tmp_flags = _mm256_shuffle_epi8(rss_flags, descs_flags);
+ mbuf_flags = _mm256_or_si256(mbuf_flags, tmp_flags);
+
+#ifndef RTE_LIBRTE_SXE2_16BYTE_RX_DESC
+ if (rxq->fnav_enable) {
+ __m256i fnav_vld0_3, fnav_vld4_7;
+ __m256i fnav_vld0_7;
+ __m256i v_zeros, v_ffff, v_u32_one;
+ const __m256i fdir_flags =
+ _mm256_set1_epi32(RTE_MBUF_F_RX_FDIR |
+ RTE_MBUF_F_RX_FDIR_ID);
+ fnav_vld0_3 = _mm256_unpacklo_epi32(descs2_3, descs0_1);
+ fnav_vld4_7 = _mm256_unpacklo_epi32(descs6_7, descs4_5);
+
+ fnav_vld0_7 = _mm256_unpacklo_epi64(fnav_vld4_7, fnav_vld0_3);
+
+ fnav_vld0_7 = _mm256_slli_epi32(fnav_vld0_7, 26);
+ fnav_vld0_7 = _mm256_srli_epi32(fnav_vld0_7, 31);
+
+ v_zeros = _mm256_setzero_si256();
+ v_ffff = _mm256_cmpeq_epi32(v_zeros, v_zeros);
+ v_u32_one = _mm256_srli_epi32(v_ffff, 31);
+
+ tmp_flags = _mm256_cmpeq_epi32(fnav_vld0_7, v_u32_one);
+
+ tmp_flags = _mm256_and_si256(tmp_flags, fdir_flags);
+
+ mbuf_flags = _mm256_or_si256(mbuf_flags, tmp_flags);
+
+ rx_pkts[i + 0]->hash.fdir.hi = desc[0].wb.fd_filter_id;
+ rx_pkts[i + 1]->hash.fdir.hi = desc[1].wb.fd_filter_id;
+ rx_pkts[i + 2]->hash.fdir.hi = desc[2].wb.fd_filter_id;
+ rx_pkts[i + 3]->hash.fdir.hi = desc[3].wb.fd_filter_id;
+ rx_pkts[i + 4]->hash.fdir.hi = desc[4].wb.fd_filter_id;
+ rx_pkts[i + 5]->hash.fdir.hi = desc[5].wb.fd_filter_id;
+ rx_pkts[i + 6]->hash.fdir.hi = desc[6].wb.fd_filter_id;
+ rx_pkts[i + 7]->hash.fdir.hi = desc[7].wb.fd_filter_id;
+ }
+#endif
+ }
+
+ RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, ol_flags) !=
+ offsetof(struct rte_mbuf, rearm_data) + 8);
+ RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, rx_descriptor_fields1) !=
+ offsetof(struct rte_mbuf, rearm_data) + 16);
+ RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, rearm_data) !=
+ RTE_ALIGN(offsetof(struct rte_mbuf, rearm_data), 16));
+
+ __m256i rearm_arr[8];
+
+ rearm_arr[6] = _mm256_blend_epi32(mbuf_init,
+ _mm256_slli_si256(mbuf_flags, 8), 0x04);
+ rearm_arr[4] = _mm256_blend_epi32(mbuf_init,
+ _mm256_slli_si256(mbuf_flags, 4), 0x04);
+ rearm_arr[2] = _mm256_blend_epi32(mbuf_init, mbuf_flags, 0x04);
+ rearm_arr[0] = _mm256_blend_epi32(mbuf_init,
+ _mm256_srli_si256(mbuf_flags, 4), 0x04);
+
+ rearm_arr[6] = _mm256_permute2f128_si256(rearm_arr[6], mbufs6_7, 0x20);
+ rearm_arr[4] = _mm256_permute2f128_si256(rearm_arr[4], mbufs4_5, 0x20);
+ rearm_arr[2] = _mm256_permute2f128_si256(rearm_arr[2], mbufs2_3, 0x20);
+ rearm_arr[0] = _mm256_permute2f128_si256(rearm_arr[0], mbufs0_1, 0x20);
+
+ _mm256_storeu_si256((__m256i *)&rx_pkts[i + 6]->rearm_data, rearm_arr[6]);
+ _mm256_storeu_si256((__m256i *)&rx_pkts[i + 4]->rearm_data, rearm_arr[4]);
+ _mm256_storeu_si256((__m256i *)&rx_pkts[i + 2]->rearm_data, rearm_arr[2]);
+ _mm256_storeu_si256((__m256i *)&rx_pkts[i + 0]->rearm_data, rearm_arr[0]);
+
+ const __m256i tmp_mbuf_flags =
+ _mm256_castsi128_si256(_mm256_extracti128_si256(mbuf_flags, 1));
+
+ rearm_arr[7] = _mm256_blend_epi32(mbuf_init,
+ _mm256_slli_si256(tmp_mbuf_flags, 8), 4);
+ rearm_arr[5] = _mm256_blend_epi32(mbuf_init,
+ _mm256_slli_si256(tmp_mbuf_flags, 4), 4);
+ rearm_arr[3] = _mm256_blend_epi32(mbuf_init, tmp_mbuf_flags, 4);
+ rearm_arr[1] = _mm256_blend_epi32(mbuf_init,
+ _mm256_srli_si256(tmp_mbuf_flags, 4), 4);
+
+ rearm_arr[7] = _mm256_blend_epi32(rearm_arr[7], mbufs6_7, 0XF0);
+ rearm_arr[5] = _mm256_blend_epi32(rearm_arr[5], mbufs4_5, 0XF0);
+ rearm_arr[3] = _mm256_blend_epi32(rearm_arr[3], mbufs2_3, 0XF0);
+ rearm_arr[1] = _mm256_blend_epi32(rearm_arr[1], mbufs0_1, 0XF0);
+
+ _mm256_storeu_si256((__m256i *)&rx_pkts[i + 7]->rearm_data, rearm_arr[7]);
+ _mm256_storeu_si256((__m256i *)&rx_pkts[i + 5]->rearm_data, rearm_arr[5]);
+ _mm256_storeu_si256((__m256i *)&rx_pkts[i + 3]->rearm_data, rearm_arr[3]);
+ _mm256_storeu_si256((__m256i *)&rx_pkts[i + 1]->rearm_data, rearm_arr[1]);
+
+ if (umbcast_flags) {
+ const __m256i umbcast_mask =
+ _mm256_set1_epi32(SXE2_RX_DESC_STATUS_UMBCAST_MASK);
+ __m256i umbcast_bits_256 =
+ _mm256_and_si256(staterrs0_7, umbcast_mask);
+
+ umbcast_bits_256 = _mm256_srli_epi32(umbcast_bits_256, 24);
+ __m128i umbcast_bits_128 =
+ _mm_packs_epi32(_mm256_castsi256_si128(umbcast_bits_256),
+ _mm256_extractf128_si256(umbcast_bits_256, 1));
+
+ umbcast_bits_128 = _mm_shuffle_epi8(umbcast_bits_128, eop_shuf_mask);
+
+ *(uint64_t *)umbcast_flags = _mm_cvtsi128_si64(umbcast_bits_128);
+ umbcast_flags += SXE2_RX_NUM_PER_LOOP_AVX;
+ }
+
+ if (split_rxe_flags) {
+ const __m256i eop_rxe_mask =
+ _mm256_set1_epi32(SXE2_RX_DESC_STATUS_EOP_MASK |
+ SXE2_RX_DESC_ERROR_RXE_MASK |
+ SXE2_RX_DESC_ERROR_OVERSIZE_MASK);
+ const __m128i eop_mask_128 =
+ _mm_set1_epi16(SXE2_RX_DESC_STATUS_EOP_MASK);
+ const __m128i rxe_mask_128 =
+ _mm_set1_epi16(SXE2_RX_DESC_ERROR_RXE_MASK |
+ SXE2_RX_DESC_ERROR_OVERSIZE_MASK);
+
+ const __m256i tmp_stats = _mm256_and_si256(staterrs0_7, eop_rxe_mask);
+
+ const __m128i eop_rxe_bits = _mm_packs_epi32
+ (_mm256_castsi256_si128(tmp_stats),
+ _mm256_extractf128_si256(tmp_stats, 1));
+
+ __m128i not_eop_bits = _mm_andnot_si128(eop_rxe_bits, eop_mask_128);
+
+ not_eop_bits =
+ _mm_or_si128(not_eop_bits,
+ _mm_srli_epi16(_mm_and_si128(eop_rxe_bits,
+ rxe_mask_128),
+ 7));
+
+ not_eop_bits = _mm_shuffle_epi8(not_eop_bits, eop_shuf_mask);
+
+ *(uint64_t *)split_rxe_flags = _mm_cvtsi128_si64(not_eop_bits);
+ split_rxe_flags += SXE2_RX_NUM_PER_LOOP_AVX;
+ }
+
+ staterrs0_7 = _mm256_and_si256(staterrs0_7, dd_mask);
+
+ staterrs0_7 = _mm256_packs_epi32(staterrs0_7, _mm256_setzero_si256());
+
+ bit_num = rte_popcount64
+ (_mm_cvtsi128_si64(_mm256_extracti128_si256(staterrs0_7, 1)));
+ bit_num += rte_popcount64
+ (_mm_cvtsi128_si64(_mm256_castsi256_si128(staterrs0_7)));
+ done_num += bit_num;
+
+ if (bit_num != SXE2_RX_NUM_PER_LOOP_AVX)
+ break;
+ }
+
+ rxq->processing_idx += done_num;
+ rxq->processing_idx &= (rxq->ring_depth - 1);
+ if ((rxq->processing_idx & 1) == 1 && done_num > 1) {
+ rxq->processing_idx--;
+ done_num--;
+ }
+ rxq->realloc_num += done_num;
+
+l_end:
+ PMD_LOG_DEBUG(RX, "port_id=%u queue_id=%u last_id=%u recv_pkts=%d",
+ rxq->port_id, rxq->queue_id, rxq->processing_idx, done_num);
+ return done_num;
+}
+
+static __rte_always_inline uint16_t
+sxe2_rx_pkts_scattered_batch_vec_avx512(struct sxe2_rx_queue *rxq, struct rte_mbuf **rx_pkts,
+ uint16_t nb_pkts, bool do_offload)
+{
+ const uint64_t *split_rxe_flags64;
+ uint8_t split_rxe_flags[SXE2_RX_PKTS_BURST_BATCH_NUM_VEC] = {0};
+ uint8_t umbcast_flags[SXE2_RX_PKTS_BURST_BATCH_NUM_VEC] = {0};
+ uint16_t rx_done_num;
+ uint16_t rx_pkt_done_num;
+
+ rx_pkt_done_num = 0;
+
+ if (rxq->vsi->adapter->devargs.sw_stats_en) {
+ rx_done_num = sxe2_rx_pkts_common_vec_avx512(rxq, rx_pkts,
+ nb_pkts, split_rxe_flags,
+ umbcast_flags, do_offload);
+ } else {
+ rx_done_num = sxe2_rx_pkts_common_vec_avx512(rxq, rx_pkts,
+ nb_pkts, split_rxe_flags,
+ NULL, do_offload);
+ }
+ if (rx_done_num == 0)
+ goto l_end;
+
+ if (!rxq->vsi->adapter->devargs.sw_stats_en) {
+ split_rxe_flags64 = (uint64_t *)split_rxe_flags;
+
+ if (rxq->pkt_first_seg == NULL &&
+ !split_rxe_flags64[0] && !split_rxe_flags64[1] &&
+ !split_rxe_flags64[2] && !split_rxe_flags64[3]) {
+ rx_pkt_done_num = rx_done_num;
+ goto l_end;
+ }
+
+ if (rxq->pkt_first_seg == NULL) {
+ while (rx_pkt_done_num < rx_done_num &&
+ split_rxe_flags[rx_pkt_done_num] == 0)
+ rx_pkt_done_num++;
+
+ if (rx_pkt_done_num == rx_done_num)
+ goto l_end;
+
+ rxq->pkt_first_seg = rx_pkts[rx_pkt_done_num];
+ }
+ }
+
+ rx_pkt_done_num += sxe2_rx_pkts_refactor(rxq, &rx_pkts[rx_pkt_done_num],
+ rx_done_num - rx_pkt_done_num, &split_rxe_flags[rx_pkt_done_num],
+ &umbcast_flags[rx_pkt_done_num]);
+
+l_end:
+
+ return rx_pkt_done_num;
+}
+
+static __rte_always_inline uint16_t
+sxe2_rx_pkts_scattered_common_vec_avx512(void *rx_queue,
+ struct rte_mbuf **rx_pkts, uint16_t nb_pkts, bool offload)
+{
+ uint16_t done_num = 0;
+ uint16_t once_num = 0;
+
+ while (nb_pkts > SXE2_RX_PKTS_BURST_BATCH_NUM) {
+ once_num = sxe2_rx_pkts_scattered_batch_vec_avx512(rx_queue, rx_pkts + done_num,
+ SXE2_RX_PKTS_BURST_BATCH_NUM, offload);
+
+ done_num += once_num;
+ nb_pkts -= once_num;
+
+ if (once_num < SXE2_RX_PKTS_BURST_BATCH_NUM)
+ goto end;
+ }
+
+ done_num += sxe2_rx_pkts_scattered_batch_vec_avx512(rx_queue,
+ rx_pkts + done_num, nb_pkts, offload);
+
+end:
+ return done_num;
+}
+
+uint16_t sxe2_rx_pkts_scattered_vec_avx512(void *rx_queue,
+ struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
+{
+ return sxe2_rx_pkts_scattered_common_vec_avx512(rx_queue,
+ rx_pkts, nb_pkts, false);
+}
+
+uint16_t sxe2_rx_pkts_scattered_vec_avx512_offload(void *rx_queue,
+ struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
+{
+ return sxe2_rx_pkts_scattered_common_vec_avx512(rx_queue,
+ rx_pkts, nb_pkts, true);
+}
+
+#endif
--
2.52.0
^ permalink raw reply related
* [PATCH v2 00/20] net/sxe2: added Linkdata sxe2 ethernet driver
From: liujie5 @ 2026-06-14 9:23 UTC (permalink / raw)
To: stephen; +Cc: dev, Jie Liu
In-Reply-To: <20260614092328.201826-1-liujie5@linkdatatechnology.com>
From: Jie Liu <liujie5@linkdatatechnology.com>
This patch set implements core functionality for the SXE2 PMD,
including basic driver framework, data path setup, and advanced
offload features (VLAN, RSS,TM, PTP etc.).
V2:
Defensive ULONG_MAX checks after strtoul() in devarg parsers
Move testpmd commands out of driver library; remove 14 RTE_EXPORT_EXPERIMENTAL_SYMBOL
Implement rte_flow_dev_dump op; remove "sxe2 flow rule dump" command
Remove "sxe2 udp_tunnel_port add|rm" command (redundant)
Complete xstats coverage; remove "sxe2 show stats" command
Remove ipsec SA management testpmd commands
Retain 7 devargs with full documentation and rationale in sxe2.rst
Add RTE_PMD_REGISTER_PARAM_STRING for all devargs
Jie Liu (20):
net/sxe2: support AVX512 vectorized path for Rx and Tx
net/sxe2: add AVX2 vector data path for Rx and Tx
drivers: add supported packet types get callback
net/sxe2: support L2 filtering and MAC config
drivers: support RSS feature
net/sxe2: support TM hierarchy and shaping
net/sxe2: support IPsec inline protocol offload
net/sxe2: support statistics and multi-process
drivers: interrupt handling
net/sxe2: add NEON vec Rx/Tx burst functions
drivers: add support for VF representors
net/sxe2: add support for custom UDP tunnel ports
net/sxe2: support firmware version reading
net/sxe2: implement get monitor address
common/sxe2: add shared SFP module definitions
net/sxe2: support SFP module info and EEPROM access
net/sxe2: implement private dump info
net/sxe2: add mbuf validation in Tx debug mode
drivers: add parameters parsed using rte_kvargs
net/sxe2: update sxe2 feature matrix docs
doc/guides/nics/features/sxe2.ini | 56 +
doc/guides/nics/sxe2.rst | 132 ++
drivers/common/sxe2/sxe2_common.c | 156 ++
drivers/common/sxe2/sxe2_common.h | 4 +
drivers/common/sxe2/sxe2_flow_public.h | 633 +++++++
drivers/common/sxe2/sxe2_ioctl_chnl.c | 178 +-
drivers/common/sxe2/sxe2_ioctl_chnl_func.h | 18 +
drivers/common/sxe2/sxe2_msg.h | 118 ++
drivers/common/sxe2/sxe2_ptype.h | 1793 ++++++++++++++++++
drivers/net/sxe2/meson.build | 54 +-
drivers/net/sxe2/sxe2_cmd_chnl.c | 1587 +++++++++++++++-
drivers/net/sxe2/sxe2_cmd_chnl.h | 139 ++
drivers/net/sxe2/sxe2_drv_cmd.h | 521 +++++-
drivers/net/sxe2/sxe2_dump.c | 304 +++
drivers/net/sxe2/sxe2_dump.h | 12 +
drivers/net/sxe2/sxe2_ethdev.c | 1532 +++++++++++++++-
drivers/net/sxe2/sxe2_ethdev.h | 107 +-
drivers/net/sxe2/sxe2_ethdev_repr.c | 610 ++++++
drivers/net/sxe2/sxe2_ethdev_repr.h | 32 +
drivers/net/sxe2/sxe2_filter.c | 895 +++++++++
drivers/net/sxe2/sxe2_filter.h | 100 +
drivers/net/sxe2/sxe2_flow.c | 1394 ++++++++++++++
drivers/net/sxe2/sxe2_flow.h | 30 +
drivers/net/sxe2/sxe2_flow_define.h | 144 ++
drivers/net/sxe2/sxe2_flow_parse_action.c | 1182 ++++++++++++
drivers/net/sxe2/sxe2_flow_parse_action.h | 23 +
drivers/net/sxe2/sxe2_flow_parse_engine.c | 106 ++
drivers/net/sxe2/sxe2_flow_parse_engine.h | 13 +
drivers/net/sxe2/sxe2_flow_parse_pattern.c | 1935 ++++++++++++++++++++
drivers/net/sxe2/sxe2_flow_parse_pattern.h | 46 +
drivers/net/sxe2/sxe2_ipsec.c | 1565 ++++++++++++++++
drivers/net/sxe2/sxe2_ipsec.h | 254 +++
drivers/net/sxe2/sxe2_irq.c | 1026 +++++++++++
drivers/net/sxe2/sxe2_irq.h | 25 +
drivers/net/sxe2/sxe2_mac.c | 535 ++++++
drivers/net/sxe2/sxe2_mac.h | 84 +
drivers/net/sxe2/sxe2_mp.c | 414 +++++
drivers/net/sxe2/sxe2_mp.h | 67 +
drivers/net/sxe2/sxe2_queue.c | 17 +-
drivers/net/sxe2/sxe2_rss.c | 584 ++++++
drivers/net/sxe2/sxe2_rss.h | 81 +
drivers/net/sxe2/sxe2_rx.c | 38 +
drivers/net/sxe2/sxe2_rx.h | 2 +
drivers/net/sxe2/sxe2_security.c | 335 ++++
drivers/net/sxe2/sxe2_security.h | 77 +
drivers/net/sxe2/sxe2_stats.c | 591 ++++++
drivers/net/sxe2/sxe2_stats.h | 39 +
drivers/net/sxe2/sxe2_switchdev.c | 332 ++++
drivers/net/sxe2/sxe2_switchdev.h | 33 +
drivers/net/sxe2/sxe2_tm.c | 1169 ++++++++++++
drivers/net/sxe2/sxe2_tm.h | 78 +
drivers/net/sxe2/sxe2_tx.c | 7 +
drivers/net/sxe2/sxe2_txrx.c | 176 +-
drivers/net/sxe2/sxe2_txrx.h | 4 +
drivers/net/sxe2/sxe2_txrx_check_mbuf.c | 595 ++++++
drivers/net/sxe2/sxe2_txrx_check_mbuf.h | 38 +
drivers/net/sxe2/sxe2_txrx_poll.c | 243 ++-
drivers/net/sxe2/sxe2_txrx_vec.c | 46 +-
drivers/net/sxe2/sxe2_txrx_vec.h | 38 +-
drivers/net/sxe2/sxe2_txrx_vec_avx2.c | 776 ++++++++
drivers/net/sxe2/sxe2_txrx_vec_avx512.c | 897 +++++++++
drivers/net/sxe2/sxe2_txrx_vec_common.h | 1 +
drivers/net/sxe2/sxe2_txrx_vec_neon.c | 721 ++++++++
drivers/net/sxe2/sxe2_vsi.c | 146 ++
drivers/net/sxe2/sxe2_vsi.h | 12 +-
drivers/net/sxe2/sxe2vf_regs.h | 85 +
66 files changed, 24852 insertions(+), 133 deletions(-)
create mode 100644 drivers/common/sxe2/sxe2_flow_public.h
create mode 100644 drivers/common/sxe2/sxe2_msg.h
create mode 100644 drivers/common/sxe2/sxe2_ptype.h
create mode 100644 drivers/net/sxe2/sxe2_dump.c
create mode 100644 drivers/net/sxe2/sxe2_dump.h
create mode 100644 drivers/net/sxe2/sxe2_ethdev_repr.c
create mode 100644 drivers/net/sxe2/sxe2_ethdev_repr.h
create mode 100644 drivers/net/sxe2/sxe2_filter.c
create mode 100644 drivers/net/sxe2/sxe2_filter.h
create mode 100644 drivers/net/sxe2/sxe2_flow.c
create mode 100644 drivers/net/sxe2/sxe2_flow.h
create mode 100644 drivers/net/sxe2/sxe2_flow_define.h
create mode 100644 drivers/net/sxe2/sxe2_flow_parse_action.c
create mode 100644 drivers/net/sxe2/sxe2_flow_parse_action.h
create mode 100644 drivers/net/sxe2/sxe2_flow_parse_engine.c
create mode 100644 drivers/net/sxe2/sxe2_flow_parse_engine.h
create mode 100644 drivers/net/sxe2/sxe2_flow_parse_pattern.c
create mode 100644 drivers/net/sxe2/sxe2_flow_parse_pattern.h
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_irq.c
create mode 100644 drivers/net/sxe2/sxe2_mac.c
create mode 100644 drivers/net/sxe2/sxe2_mac.h
create mode 100644 drivers/net/sxe2/sxe2_mp.c
create mode 100644 drivers/net/sxe2/sxe2_mp.h
create mode 100644 drivers/net/sxe2/sxe2_rss.c
create mode 100644 drivers/net/sxe2/sxe2_rss.h
create mode 100644 drivers/net/sxe2/sxe2_security.c
create mode 100644 drivers/net/sxe2/sxe2_security.h
create mode 100644 drivers/net/sxe2/sxe2_stats.c
create mode 100644 drivers/net/sxe2/sxe2_stats.h
create mode 100644 drivers/net/sxe2/sxe2_switchdev.c
create mode 100644 drivers/net/sxe2/sxe2_switchdev.h
create mode 100644 drivers/net/sxe2/sxe2_tm.c
create mode 100644 drivers/net/sxe2/sxe2_tm.h
create mode 100644 drivers/net/sxe2/sxe2_txrx_check_mbuf.c
create mode 100644 drivers/net/sxe2/sxe2_txrx_check_mbuf.h
create mode 100644 drivers/net/sxe2/sxe2_txrx_vec_avx2.c
create mode 100644 drivers/net/sxe2/sxe2_txrx_vec_avx512.c
create mode 100644 drivers/net/sxe2/sxe2_txrx_vec_neon.c
create mode 100644 drivers/net/sxe2/sxe2vf_regs.h
--
2.52.0
^ permalink raw reply
* Re: [PATCH 19/20] drivers: add testpmd commands for private features
From: liujie5 @ 2026-06-14 9:23 UTC (permalink / raw)
To: stephen; +Cc: dev
In-Reply-To: <20260614092328.201826-1-liujie5@linkdatatechnology.com>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=a, Size: 5452 bytes --]
您好,
感谢详细的审查意见。以下是我们对每条反馈的逐条回复以及 v2 计划变更。
---
### 1. strtoul() 值越界处理
重新检查了 [`sxe2_ethdev.c`](drivers/net/sxe2/sxe2_ethdev.c) 中的 devargs 解析代码后,我们确认所有解析器都已处理越界值:
- [`sxe2_parse_u8()`](drivers/net/sxe2/sxe2_ethdev.c:1074) — 检查 `val > UINT8_MAX`(第 1092 行),返回 `-ERANGE`
- [`sxe2_parse_bool()`](drivers/net/sxe2/sxe2_ethdev.c:1103) — 检查 `bool_val != 0 && bool_val != 1`(第 1121 行)
- [`sxe2_parse_fnav_stat_type()`](drivers/net/sxe2/sxe2_ethdev.c:989) — 检查是否超过 `SXE2_FNAV_STAT_ENA_ALL`(第 1007 行)
- [`sxe2_parse_sched_layer_mode()`](drivers/net/sxe2/sxe2_ethdev.c:1018) — 检查是否超过 `SXE2_TXSCH_NODE_ADJ_LVL_MAX`(第 1036 行)
- [`sxe2_parse_high_performance_mode()`](drivers/net/sxe2/sxe2_ethdev.c:1046) — 检查 `high_performance_mode != 1`(第 1064 行),覆盖零和越界值
每个函数在 `strtoul()` 前设置 `errno = 0`,之后检查 `errno != 0`,从而捕获 `ERANGE`(溢出)。之后再执行语义范围检查。v2 中我们将在每个 `strtoul()` 调用后增加显式的 `ULONG_MAX` 比较以增加防御性。
---
### 2. 从驱动库导出 testpmd 符号
**同意。** 没有上游驱动为其 testpmd 命令导出符号。v2 中将:
- 将 `sxe2_testpmd_lib.c` 的实现移至 `sxe2_testpmd.c`,通过 meson.build 中的 `testpmd_sources` 编译,与 i40e、ixgbe、mlx5、bnxt 等驱动的模式一致。
- **删除所有 14 个 `RTE_EXPORT_EXPERIMENTAL_SYMBOL` 条目。** 这些从未作为公共 API。
- 将应用状态(`g_tx_session[][]`、`g_rx_session[][]`、`g_esp_header_offset[]`、`g_sess_pool`)移至 testpmd 侧代码。
- 驱动内部函数继续通过 `drivers/net/sxe2/` 下的内部头文件访问。
---
### 3. 与标准 testpmd 功能重复的命令
**三个命令都同意删除。**
- **"sxe2 flow rule dump"** → 我们将实现 `rte_flow_dev_dump` op。之后标准命令 `flow dump <port_id> all` 即可正常工作。私有命令将被删除。
- **"sxe2 udp_tunnel_port add|rm"** → 该命令调用 `rte_eth_dev_udp_tunnel_port_add/rm`,已由 `port config <port_id> udp_tunnel_port add|rm` 暴露。私有命令是冗余的,将被删除。
- **"sxe2 show stats"** → 我们将审查 xstats 并补充缺失的计数器;用户改用 `show port xstats <port_id>`。私有命令将被删除。
---
### 4. IPsec SA 管理套件
**同意。** 我们将:
- 从 testpmd 扩展中删除 9 个子命令的 ipsec SA 管理命令。
- 文档中说明 `examples/ipsec-secgw` 是使用此驱动验证 inline crypto 的支持方式,与其他 inline-crypto PMD 一致。
- 如果将来需要 testpmd 中的交互式 SA 管理,我们将提议作为通用的 testpmd 命令基于 `rte_security` 实现,使所有驱动受益。
---
### 5. 私有 devargs
所有 7 个 devargs 的文档已添加到 [`doc/guides/nics/sxe2.rst`](doc/guides/nics/sxe2.rst)(Runtime Configuration 章节),同时添加了 `RTE_PMD_REGISTER_PARAM_STRING` 以保证可发现性。以下是保留每个 devargs 的理由:
**flow-duplicate-pattern** — 控制硬件 switch engine 是否接受重复的 flow rule。这不会改变 `rte_flow` 语义;它配置了一个硬件特定的能力。switch engine 支持两种模式:(a) 拒绝重复规则用于错误检测,(b) 通过 per-rule 元数据标志允许重复。默认值(1 = 允许)确保标准行为。目前没有标准 API 用于控制 switch 级别的重复规则行为。
**fnav-stat-type** — 在初始化时选择硬件计数器资源配置(仅包计数 / 仅字节计数 / 两者)。这是一个静态硬件配置决策,而非运行时开关。目前没有标准 API 用于选择计数器资源分配模式。
**drv-sw-stats** — 某些包类型上硬件计数器可能存在不准确性。此参数启用 Rx 数据路径中的软件累计路径作为 workaround。per-packet 软件分类的开销使得通过 devarg 控制而非始终开启是合理的。计数器通过 xstats 暴露(`rx_sw_unicast_packets` 等)。
**sched-layer-mode** — 不同硬件 SKU 支持不同的最大调度层级数(0-3)。该参数在初始化时限制层级深度。`rte_tm` API 目前没有在配置前查询最大调度深度的接口。
**high-performance-mode** — Tx 绕过硬件调度器以获得更低延迟。不适合作为默认值,因为 TM 功能对许多用户很重要。现已记录完整的性能权衡说明。
**rx-low-latency** — Rx 中断调节调优。类似 devarg 在其他驱动中也存在(例如 mlx5 的 `rxqs_min_bth`)。
**function-flow-direct** — 控制 flow rule 的 PF/VF 重定向范围。`rte_flow` 没有针对此功能的 per-rule 标志。
---
### v2 计划变更
1. devarg 解析器中 `strtoul()` 后增加防御性 `ULONG_MAX` 检查
2. testpmd 命令移出驱动库;删除 14 个 `RTE_EXPORT_EXPERIMENTAL_SYMBOL`
3. 实现 `rte_flow_dev_dump` op;删除 "sxe2 flow rule dump" 命令
4. 删除 "sxe2 udp_tunnel_port add|rm" 命令(冗余)
5. 完善 xstats 覆盖;删除 "sxe2 show stats" 命令
6. 删除 ipsec SA 管理 testpmd 命令
7. 保留 7 个 devargs,在 sxe2.rst 中提供完整文档和理由
8. 为所有 devargs 添加 `RTE_PMD_REGISTER_PARAM_STRING`
我们将尽快发送 v2。如有其他问题请告知。
谢谢,
[署名]
^ permalink raw reply
* [PATCH v2 00/20] sxe2: address review comments - testpmd restructuring, devargs documentation, and code cleanup
From: liujie5 @ 2026-06-14 9:23 UTC (permalink / raw)
To: stephen; +Cc: dev
In-Reply-To: <20260610013936.3634968-21-liujie5@linkdatatechnology.com>
Hi all,
Thank you for the detailed review of the sxe2 PMD patch series. We have
prepared a v2 addressing the feedback. Below is our point-by-point response.
---
### 1. strtoul() out-of-range handling
> This memory stuff looks problematic and needs more review. At a minimum
> I see a pattern of not handling values from strtoul() that are out of range.
After re-examining the devargs parsing code in sxe2_ethdev.c, we confirmed
that the existing parsers handle out-of-range values:
- sxe2_parse_u8(): checks val > UINT8_MAX, returns -ERANGE
- sxe2_parse_bool(): checks bool_val != 0 && bool_val != 1
- sxe2_parse_fnav_stat_type(): checks val > the maximum valid enum value
- sxe2_parse_sched_layer_mode(): checks val > SXE2_TXSCH_NODE_ADJ_LVL_MAX
- sxe2_parse_high_performance_mode(): checks val != 1
Each function sets errno = 0 before strtoul() and checks errno != 0
afterward, which catches ERANGE (overflow). This is followed by a semantic
range check specific to each parameter.
Nevertheless, to make the overflow path more explicit and defensive, we will
add explicit ULONG_MAX comparisons after each strtoul() call in the v2.
---
### 2. testpmd command symbols exported from driver library
> Error: the command logic is placed in sxe2_testpmd_lib.c, compiled into
> the driver library, and exposed through 14 new RTE_EXPORT_EXPERIMENTAL_SYMBOL
> entries. No upstream driver exports symbols for its testpmd commands; all six
> existing drivers with testpmd integration compile their *_testpmd.c into
> testpmd via testpmd_sources and use internal access. These exports are
> vendor public API that any application can link against.
Agreed. This is a valid concern. We will restructure as follows:
- Move the testpmd command implementation from sxe2_testpmd_lib.c into
sxe2_testpmd.c, compiled via testpmd_sources in the meson build,
matching the pattern used by i40e, ixgbe, mlx5, bnxt, and others.
- Remove all 14 RTE_EXPORT_EXPERIMENTAL_SYMBOL entries. These were never
intended as public API.
- Keep driver-internal functions accessible through internal headers only
(they are already declared in driver-local headers under drivers/net/sxe2/).
- Move application state variables (g_tx_session[][], g_rx_session[][],
g_esp_header_offset[], g_sess_pool) into the testpmd-side code.
---
### 3. Commands duplicating standard testpmd functionality
> Error: three commands duplicate standard testpmd functionality the driver
> already supports.
> "sxe2 flow rule dump" -> implement the rte_flow dev_dump op
> "sxe2 udp_tunnel_port add|rm" -> port config udp_tunnel_port add|rm
> "sxe2 show stats" -> show port xstats
Agreed on all three:
- **sxe2 flow rule dump**: We will implement the rte_flow_dev_dump() op in
the driver. After that, the standard "flow dump <port_id> all" command
works for every application. The private command will be removed.
- **sxe2 udp_tunnel_port add|rm**: This calls rte_eth_dev_udp_tunnel_port_add/
rm, which is already exposed by "port config <port_id> udp_tunnel_port
add|rm". The private command is redundant and will be removed.
- **sxe2 show stats**: We will audit the xstats implementation and ensure
all statistics currently shown by the private formatter are available
through rte_eth_xstats_get(). Any missing counters will be added as
xstats entries. The private command will be removed; users will use
"show port xstats <port_id>" instead.
---
### 4. IPsec SA management suite in testpmd commands
> Warning: the 9-subcommand ipsec suite (egress/ingress add/rm/show,
> session-id and esp-hdr-offset set/get, flush, stats) is an SA management
> application embedded in the driver. Inline crypto is exercised with
> examples/ipsec-secgw, as done for other inline-crypto PMDs.
Understood. We will:
- Remove the ipsec SA management commands from the testpmd extension.
- Document that examples/ipsec-secgw is the supported method for
exercising inline crypto on this driver, consistent with other
inline-crypto PMDs (e.g., mlx5, ice).
- If interactive SA management in testpmd is needed in the future,
we will propose it as generic testpmd commands over rte_security,
benefiting all drivers equally.
---
### 5. Private devargs
> Warning: seven private devargs are added with no documentation.
> Each surviving devarg needs documentation and a rationale for why
> no standard API covers it.
Documentation has been added to doc/guides/nics/sxe2.rst (Runtime
Configuration section) for all seven devargs, along with
RTE_PMD_REGISTER_PARAM_STRING for discoverability.
Below is the rationale for each devarg that we believe should be retained:
**flow-duplicate-pattern**
This controls whether the hardware switch engine accepts flow rules with
identical match patterns. It does NOT change rte_flow semantics; it
configures a hardware-specific behavior. The switch engine supports two
modes: (a) reject duplicate rules (useful for catching configuration
errors), and (b) allow duplicates by setting a per-rule metadata flag.
This is a hardware capability toggle, analogous to how some NICs support
configurable TCAM overlap behavior. Default value (1 = allow duplicates)
ensures standard rte_flow behavior out of the box. The standard rte_flow
API does not provide a mechanism to control switch-level duplicate rule
behavior.
**fnav-stat-type**
This selects how the Fnav flow engine partitions its hardware counter
resources (packets only, bytes only, or both). This is set at device
initialization and cannot be changed dynamically; it determines the
hardware resource allocation. When only packet counts are needed, the
hardware can allocate the full counter width to packet counting. The
resulting counters are queried via the standard rte_flow_query() API.
No standard API currently exists to select hardware counter resource
allocation mode at initialization time; it is a hardware-specific
configuration decision.
**drv-sw-stats**
Hardware packet statistics counters may be inaccurate for certain packet
types due to hardware design limitations. This devarg enables a software
accumulation path in the Rx data path as a workaround. When enabled, the
driver classifies each received packet (unicast/multicast/broadcast/drop)
and accumulates counts in software. The counters are exposed as xstats
(rx_sw_unicast_packets, etc.). The devarg controls whether the per-packet
software accumulation overhead is incurred; it is an optimization choice
for users who do not require this level of accuracy. The rationale for
keeping this as a devarg rather than always-on xstats is that the
software accumulation adds overhead to the Rx fast path; users who do
not need per-packet classification accuracy should not pay this cost.
**sched-layer-mode**
Different hardware SKUs support different numbers of Tx scheduling levels
(0-3). This parameter caps the maximum scheduling depth at initialization.
This is NOT a TM topology configuration -- the application still builds
its rte_tm hierarchy as usual. Rather, it constrains the hierarchy depth
to match hardware capability across SKU variants. The rte_tm API does not
currently provide a mechanism to query or constrain the maximum scheduling
depth before configuring the hierarchy, so a devarg is the practical
approach.
**high-performance-mode**
When enabled, the Tx path bypasses the hardware scheduling module and
sends packets directly to the port. This trades TM scheduling capability
for lower latency and higher throughput. It is not appropriate to make
this the default because TM functionality is important for many users.
The devarg (now documented) makes the performance trade-off explicit.
**rx-low-latency**
Controls whether Rx interrupt moderation is tuned for minimum latency vs.
batching efficiency. This is a hardware-specific tuning parameter with
no equivalent in the standard Ethdev API. Many drivers have analogous
low-latency devargs (e.g., mlx5 has rxqs_min_bth for similar purposes).
**function-flow-direct**
Controls whether flow rules can directly target a specific PF/VF function.
This is a hardware switch engine feature that affects the scope of flow
redirection. The standard rte_flow API does not have a per-rule flag for
this; the devarg controls the default redirect behavior.
---
### Summary of changes for v2
1. Add explicit ULONG_MAX checks after strtoul() in all devarg parsers
2. Move testpmd command implementation out of driver library into
testpmd_sources; remove all 14 RTE_EXPORT_EXPERIMENTAL_SYMBOL
3. Implement rte_flow_dev_dump op; remove "sxe2 flow rule dump" command
4. Remove "sxe2 udp_tunnel_port add|rm" command (redundant)
5. Add missing counters to xstats; remove "sxe2 show stats" command
6. Remove ipsec SA management testpmd commands
7. Retain 7 devargs with documentation and rationale in sxe2.rst
8. Add RTE_PMD_REGISTER_PARAM_STRING for all devargs
We will send v2 shortly. Please let us know if there are any further
concerns.
Thanks,
[sender name]
^ permalink raw reply
* [PATCH v4 6/6] net/gve: reconstruct HW timestamps from DQO
From: Mark Blasko @ 2026-06-13 4:22 UTC (permalink / raw)
To: stephen; +Cc: dev, joshwash, jtranoleary, blasko
In-Reply-To: <20260613042300.3760470-1-blasko@google.com>
A full 64-bit NIC timestamp is periodically synced via an AdminQ
command and cached in the driver. In the RX datapath, this cached
value is used as a base to expand the 32-bit hardware timestamp into
a full 64-bit value, which is then stored in the mbuf's dynamic
timestamp field.
Signed-off-by: Mark Blasko <blasko@google.com>
Reviewed-by: Joshua Washington <joshwash@google.com>
Reviewed-by: Jasper Tran O'Leary <jtranoleary@google.com>
---
v4:
- Clarify in GVE documentation that both read_clock ethdev op and
per-packet RX timestamp offloading require the DQO queue format.
v2:
- Scoped timestamp offload capability advertisement strictly
to DQO queues.
- Predicated capability advertisement directly on memzone
allocation.
- Initialized mbuf_timestamp_offset to -1.
- Added blank line separating release notes.
---
doc/guides/nics/features/gve.ini | 1 +
doc/guides/nics/gve.rst | 20 ++++++++++++++++++++
doc/guides/rel_notes/release_26_07.rst | 4 ++++
drivers/net/gve/base/gve_desc_dqo.h | 8 ++++++--
drivers/net/gve/gve_ethdev.c | 15 ++++++++++++++-
drivers/net/gve/gve_ethdev.h | 25 +++++++++++++++++++++++++
drivers/net/gve/gve_rx_dqo.c | 26 ++++++++++++++++++++++++++
7 files changed, 96 insertions(+), 3 deletions(-)
diff --git a/doc/guides/nics/features/gve.ini b/doc/guides/nics/features/gve.ini
index 89c97fd27a..117ad4fc65 100644
--- a/doc/guides/nics/features/gve.ini
+++ b/doc/guides/nics/features/gve.ini
@@ -13,6 +13,7 @@ RSS hash = Y
RSS key update = Y
RSS reta update = Y
L4 checksum offload = Y
+Timestamp offload = Y
Basic stats = Y
FreeBSD = Y
Linux = Y
diff --git a/doc/guides/nics/gve.rst b/doc/guides/nics/gve.rst
index be855b645d..b73375c5c9 100644
--- a/doc/guides/nics/gve.rst
+++ b/doc/guides/nics/gve.rst
@@ -72,6 +72,7 @@ Supported features of the GVE PMD are:
- Tx UDP/TCP/SCTP Checksum
- RSS hash configuration
- RSS redirection table query and update
+- Timestamp offload
Currently, only GQI_QPL and GQI_RDA queue format are supported in PMD.
Jumbo Frame is not supported in PMD for now.
@@ -132,6 +133,25 @@ Security Protocols
- Flow priorities are not supported (must be 0).
- Masking is limited to full matches i.e. ``0x00...0`` or ``0xFF...F``.
+Timestamp Offload
+^^^^^^^^^^^^^^^^^
+
+The driver supports hardware-based packet timestamping on supported
+devices via the standard ``RTE_ETH_RX_OFFLOAD_TIMESTAMP`` offload capability.
+Both the ethdev ``.read_clock`` operation and per-packet RX timestamp offloading
+require the DQO queue format.
+
+**Limitations**
+
+- If the driver fails to fetch the NIC hardware clock for 7 consecutive periods,
+ the cached timestamp is marked as stale,
+ and the reconstructed timestamps are no longer propagated to the mbuf.
+- The timestamp reconstruction is only accurate
+ if the time between a packet's reception
+ and the last hardware clock sync is less than approximately 2 seconds.
+ The driver's internal clock sync period is set to respect this limitation.
+
+
Device Reset
^^^^^^^^^^^^
diff --git a/doc/guides/rel_notes/release_26_07.rst b/doc/guides/rel_notes/release_26_07.rst
index 2e449d3ee8..73c9a36007 100644
--- a/doc/guides/rel_notes/release_26_07.rst
+++ b/doc/guides/rel_notes/release_26_07.rst
@@ -91,6 +91,10 @@ New Features
Added network driver for the LinkData network adapters.
+* **Updated Google GVE net driver.**
+
+ * Added hardware timestamping support on DQO queues.
+
* **Updated Intel iavf driver.**
* Added support for transmitting LLDP packets based on mbuf packet type.
diff --git a/drivers/net/gve/base/gve_desc_dqo.h b/drivers/net/gve/base/gve_desc_dqo.h
index 71d9d60bb9..c1534959c2 100644
--- a/drivers/net/gve/base/gve_desc_dqo.h
+++ b/drivers/net/gve/base/gve_desc_dqo.h
@@ -226,7 +226,8 @@ struct gve_rx_compl_desc_dqo {
u8 status_error1;
- __le16 reserved5;
+ u8 reserved5;
+ u8 ts_sub_nsecs_low;
__le16 buf_id; /* Buffer ID which was sent on the buffer queue. */
union {
@@ -237,9 +238,12 @@ struct gve_rx_compl_desc_dqo {
};
__le32 hash;
__le32 reserved6;
- __le64 reserved7;
+ __le32 reserved7;
+ __le32 ts; /* timestamp in nanosecs */
} __packed;
+#define GVE_DQO_RX_HWTSTAMP_VALID 0x1
+
GVE_CHECK_STRUCT_LEN(32, gve_rx_compl_desc_dqo);
/* Ringing the doorbell too often can hurt performance.
diff --git a/drivers/net/gve/gve_ethdev.c b/drivers/net/gve/gve_ethdev.c
index 111f66efa8..0b02dcb3ad 100644
--- a/drivers/net/gve/gve_ethdev.c
+++ b/drivers/net/gve/gve_ethdev.c
@@ -214,6 +214,7 @@ static int
gve_dev_configure(struct rte_eth_dev *dev)
{
struct gve_priv *priv = dev->data->dev_private;
+ int err;
if (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) {
dev->data->dev_conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
@@ -223,13 +224,22 @@ gve_dev_configure(struct rte_eth_dev *dev)
if (dev->data->dev_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO)
priv->enable_rsc = 1;
+ if (dev->data->dev_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP) {
+ err = rte_mbuf_dyn_rx_timestamp_register(&priv->mbuf_timestamp_offset,
+ &priv->mbuf_timestamp_mask);
+ if (err < 0) {
+ PMD_DRV_LOG(ERR, "Failed to register dynamic timestamp field");
+ return err;
+ }
+ }
+
/* Reset RSS RETA in case number of queues changed. */
if (priv->rss_config.indir) {
struct gve_rss_config update_reta_config;
gve_init_rss_config_from_priv(priv, &update_reta_config);
gve_generate_rss_reta(dev, &update_reta_config);
- int err = gve_adminq_configure_rss(priv, &update_reta_config);
+ err = gve_adminq_configure_rss(priv, &update_reta_config);
if (err)
PMD_DRV_LOG(ERR,
"Could not reconfigure RSS redirection table.");
@@ -828,6 +838,8 @@ gve_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
dev_info->min_mtu = RTE_ETHER_MIN_MTU;
dev_info->rx_offload_capa = RTE_ETH_RX_OFFLOAD_RSS_HASH;
+ if (!gve_is_gqi(priv) && priv->nic_ts_report_mz)
+ dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_TIMESTAMP;
dev_info->tx_offload_capa =
RTE_ETH_TX_OFFLOAD_MULTI_SEGS |
RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
@@ -1683,6 +1695,7 @@ gve_dev_init(struct rte_eth_dev *eth_dev)
pthread_mutex_init(&priv->nic_ts_lock, &mutexattr);
pthread_mutexattr_destroy(&mutexattr);
+ priv->mbuf_timestamp_offset = -1;
err = gve_init_priv(priv, false);
if (err) {
pthread_mutex_destroy(&priv->flow_rule_lock);
diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h
index 1e80f3a906..4a7e5ecdf3 100644
--- a/drivers/net/gve/gve_ethdev.h
+++ b/drivers/net/gve/gve_ethdev.h
@@ -261,6 +261,7 @@ struct gve_rx_queue {
struct rte_mbuf **refill_bufs;
uint8_t is_gqi_qpl;
+ bool timestamp_enabled;
};
struct gve_flow {
@@ -372,8 +373,32 @@ struct gve_priv {
RTE_ATOMIC(uint8_t) nic_ts_stale;
rte_thread_t nic_ts_thread_id;
RTE_ATOMIC(uint8_t) nic_ts_thread_should_stop;
+
+ int mbuf_timestamp_offset;
+ uint64_t mbuf_timestamp_mask;
};
+/* Expand the hardware timestamp to the full 64 bits of width.
+ *
+ * This algorithm works by using the passed hardware timestamp to generate a
+ * diff relative to the last read of the nic clock. This diff can be positive or
+ * negative, as it is possible that we have read the clock more recently than
+ * the hardware has received this packet. To detect this, we use the high bit of
+ * the diff, and assume that the read is more recent if the high bit is set. In
+ * this case we invert the process.
+ *
+ * Note that this means if the time delta between packet reception and the last
+ * clock read is greater than ~2 seconds, this will provide invalid results.
+ */
+static inline uint64_t
+gve_reconstruct_ts(uint64_t last_sync, uint32_t ts)
+{
+ uint32_t low = (uint32_t)last_sync;
+ int32_t diff = (int32_t)(ts - low);
+
+ return last_sync + diff;
+}
+
static inline bool
gve_is_gqi(struct gve_priv *priv)
{
diff --git a/drivers/net/gve/gve_rx_dqo.c b/drivers/net/gve/gve_rx_dqo.c
index 8035aee572..cc343f3fd8 100644
--- a/drivers/net/gve/gve_rx_dqo.c
+++ b/drivers/net/gve/gve_rx_dqo.c
@@ -160,6 +160,8 @@ gve_rx_burst_dqo(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
{
volatile struct gve_rx_compl_desc_dqo *rx_desc;
struct gve_rx_queue *rxq;
+ uint64_t last_sync = 0;
+ struct gve_priv *priv;
struct rte_mbuf *rxm;
uint16_t rx_buf_id;
uint16_t pkt_len;
@@ -171,6 +173,15 @@ gve_rx_burst_dqo(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
nb_rx = 0;
rxq = rx_queue;
rx_id = rxq->rx_tail;
+ priv = rxq->hw;
+
+ if (rxq->timestamp_enabled &&
+ !rte_atomic_load_explicit(&priv->nic_ts_stale,
+ rte_memory_order_acquire)) {
+ last_sync =
+ rte_atomic_load_explicit(&priv->last_read_nic_timestamp,
+ rte_memory_order_relaxed);
+ }
while (nb_rx < nb_pkts) {
rx_desc = &rxq->compl_ring[rx_id];
@@ -208,6 +219,16 @@ gve_rx_burst_dqo(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
gve_parse_csum_ol_flags(rxm, rx_desc);
rxm->hash.rss = rte_le_to_cpu_32(rx_desc->hash);
+ if (last_sync != 0 &&
+ (rx_desc->ts_sub_nsecs_low & GVE_DQO_RX_HWTSTAMP_VALID) &&
+ priv->mbuf_timestamp_offset >= 0) {
+ uint32_t ts = rte_le_to_cpu_32(rx_desc->ts);
+ uint64_t full_ts = gve_reconstruct_ts(last_sync, ts);
+
+ *RTE_MBUF_DYNFIELD(rxm, priv->mbuf_timestamp_offset, uint64_t *) = full_ts;
+ rxm->ol_flags |= priv->mbuf_timestamp_mask;
+ }
+
rx_pkts[nb_rx++] = rxm;
bytes += pkt_len;
}
@@ -320,6 +341,11 @@ gve_rx_queue_setup_dqo(struct rte_eth_dev *dev, uint16_t queue_id,
return -ENOMEM;
}
+ /* Setup hardware timestamping if enabled */
+ if ((conf->offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP) ||
+ (dev->data->dev_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP))
+ rxq->timestamp_enabled = true;
+
/* check free_thresh here */
free_thresh = conf->rx_free_thresh ?
conf->rx_free_thresh : GVE_DEFAULT_RX_FREE_THRESH;
--
2.54.0.1136.gdb2ca164c4-goog
^ permalink raw reply related
* [PATCH v4 5/6] net/gve: support read clock ethdev op
From: Mark Blasko @ 2026-06-13 4:22 UTC (permalink / raw)
To: stephen; +Cc: dev, joshwash, jtranoleary, blasko
In-Reply-To: <20260613042300.3760470-1-blasko@google.com>
Implement the read_clock operation in eth_dev_ops. The function calls
the AdminQ command to fetch the current NIC timestamp synchronously,
updates the cached timestamp used for reconstruction, and returns the
full 64-bit value.
Signed-off-by: Mark Blasko <blasko@google.com>
Reviewed-by: Joshua Washington <joshwash@google.com>
Reviewed-by: Jasper Tran O'Leary <jtranoleary@google.com>
---
v4:
- Fix mutex initialization order: initialize nic_ts_lock before
calling gve_init_priv() (which invokes early setup-time read).
- Fix mutex teardown order: destroy nic_ts_lock only after the
background sync thread has been joined and stopped.
v3:
- Add mutex lock to protect shared NIC timestamp memzone access.
- Fix missing read_clock assignment to DQO queue ops table
(accidental omission in v2).
v2:
- Scoped read_clock ethdev operation strictly to DQO queues.
---
drivers/net/gve/gve_ethdev.c | 57 +++++++++++++++++++++++++++++++-----
drivers/net/gve/gve_ethdev.h | 1 +
2 files changed, 50 insertions(+), 8 deletions(-)
diff --git a/drivers/net/gve/gve_ethdev.c b/drivers/net/gve/gve_ethdev.c
index fa91575b3e..111f66efa8 100644
--- a/drivers/net/gve/gve_ethdev.c
+++ b/drivers/net/gve/gve_ethdev.c
@@ -463,11 +463,13 @@ gve_read_nic_clock(void *arg)
if (!priv || !priv->nic_ts_report_mz)
return;
+ pthread_mutex_lock(&priv->nic_ts_lock);
memset(priv->nic_ts_report, 0, sizeof(struct gve_nic_ts_report));
err = gve_adminq_report_nic_timestamp(priv, priv->nic_ts_report_mz->iova);
if (err == 0) {
ts = be64_to_cpu(priv->nic_ts_report->nic_timestamp);
+ pthread_mutex_unlock(&priv->nic_ts_lock);
rte_atomic_store_explicit(&priv->last_read_nic_timestamp, ts,
rte_memory_order_relaxed);
PMD_DRV_LOG(DEBUG, "Fetched NIC Timestamp: %" PRIu64, ts);
@@ -476,6 +478,7 @@ gve_read_nic_clock(void *arg)
rte_atomic_store_explicit(&priv->nic_ts_stale, 0,
rte_memory_order_release);
} else {
+ pthread_mutex_unlock(&priv->nic_ts_lock);
PMD_DRV_LOG(ERR, "Failed to read NIC clock, AQ err: %d", err);
fails = rte_atomic_fetch_add_explicit(&priv->nic_ts_read_fails, 1,
rte_memory_order_relaxed) + 1;
@@ -705,12 +708,13 @@ gve_dev_close(struct rte_eth_dev *dev)
if (gve_get_flow_subsystem_ok(priv))
gve_teardown_flow_subsystem(priv);
- pthread_mutex_destroy(&priv->flow_rule_lock);
-
gve_free_queues(dev);
gve_teardown_device_resources(priv);
gve_adminq_free(priv);
+ pthread_mutex_destroy(&priv->flow_rule_lock);
+ pthread_mutex_destroy(&priv->nic_ts_lock);
+
dev->data->mac_addrs = NULL;
return err;
@@ -1278,6 +1282,38 @@ gve_flow_ops_get(struct rte_eth_dev *dev, const struct rte_flow_ops **ops)
return 0;
}
+static int
+gve_read_clock(struct rte_eth_dev *dev, uint64_t *clock)
+{
+ struct gve_priv *priv = dev->data->dev_private;
+ uint64_t ts;
+ int err;
+
+ if (!priv->nic_timestamp_supported)
+ return -EOPNOTSUPP;
+
+ if (!priv->nic_ts_report_mz)
+ return -EIO;
+
+ pthread_mutex_lock(&priv->nic_ts_lock);
+ err = gve_adminq_report_nic_timestamp(priv, priv->nic_ts_report_mz->iova);
+ if (err != 0) {
+ pthread_mutex_unlock(&priv->nic_ts_lock);
+ return err;
+ }
+
+ ts = be64_to_cpu(priv->nic_ts_report->nic_timestamp);
+ pthread_mutex_unlock(&priv->nic_ts_lock);
+ *clock = ts;
+
+ /* Update the cached value */
+ rte_atomic_store_explicit(&priv->last_read_nic_timestamp, ts, rte_memory_order_relaxed);
+ rte_atomic_store_explicit(&priv->nic_ts_read_fails, 0, rte_memory_order_relaxed);
+ rte_atomic_store_explicit(&priv->nic_ts_stale, 0, rte_memory_order_release);
+
+ return 0;
+}
+
static const struct eth_dev_ops gve_eth_dev_ops = {
.dev_configure = gve_dev_configure,
.dev_start = gve_dev_start,
@@ -1332,6 +1368,7 @@ static const struct eth_dev_ops gve_eth_dev_ops_dqo = {
.rss_hash_conf_get = gve_rss_hash_conf_get,
.reta_update = gve_rss_reta_update,
.reta_query = gve_rss_reta_query,
+ .read_clock = gve_read_clock,
};
static int
@@ -1640,9 +1677,18 @@ gve_dev_init(struct rte_eth_dev *eth_dev)
priv->max_nb_txq = max_tx_queues;
priv->max_nb_rxq = max_rx_queues;
+ pthread_mutexattr_init(&mutexattr);
+ pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);
+ pthread_mutex_init(&priv->flow_rule_lock, &mutexattr);
+ pthread_mutex_init(&priv->nic_ts_lock, &mutexattr);
+ pthread_mutexattr_destroy(&mutexattr);
+
err = gve_init_priv(priv, false);
- if (err)
+ if (err) {
+ pthread_mutex_destroy(&priv->flow_rule_lock);
+ pthread_mutex_destroy(&priv->nic_ts_lock);
return err;
+ }
if (gve_is_gqi(priv)) {
eth_dev->dev_ops = &gve_eth_dev_ops;
@@ -1656,11 +1702,6 @@ gve_dev_init(struct rte_eth_dev *eth_dev)
eth_dev->data->mac_addrs = &priv->dev_addr;
- pthread_mutexattr_init(&mutexattr);
- pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);
- pthread_mutex_init(&priv->flow_rule_lock, &mutexattr);
- pthread_mutexattr_destroy(&mutexattr);
-
return 0;
}
diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h
index 4dcbaa9971..1e80f3a906 100644
--- a/drivers/net/gve/gve_ethdev.h
+++ b/drivers/net/gve/gve_ethdev.h
@@ -366,6 +366,7 @@ struct gve_priv {
bool nic_timestamp_supported;
const struct rte_memzone *nic_ts_report_mz;
struct gve_nic_ts_report *nic_ts_report;
+ pthread_mutex_t nic_ts_lock;
RTE_ATOMIC(uint64_t) last_read_nic_timestamp;
RTE_ATOMIC(uint32_t) nic_ts_read_fails;
RTE_ATOMIC(uint8_t) nic_ts_stale;
--
2.54.0.1136.gdb2ca164c4-goog
^ permalink raw reply related
* [PATCH v4 4/6] net/gve: add periodic NIC clock synchronization
From: Mark Blasko @ 2026-06-13 4:22 UTC (permalink / raw)
To: stephen; +Cc: dev, joshwash, jtranoleary, blasko
In-Reply-To: <20260613042300.3760470-1-blasko@google.com>
Introduce a mechanism to periodically fetch the NIC hardware timestamp
using the GVE_ADMINQ_REPORT_NIC_TIMESTAMP AdminQ command. The
synchronization runs every 250ms using rte_alarm. If the read fails,
the alarm is still rescheduled. After 7 consecutive failures, the
timestamp is marked as stale, indicating to the RX path that
reconstructed timestamps may be unreliable.
Atomics exist because of the potential for async callers (introduced
here) and async callers (introduced later in the RX datapath) accessing
the cached state.
Signed-off-by: Mark Blasko <blasko@google.com>
Reviewed-by: Joshua Washington <joshwash@google.com>
Reviewed-by: Jasper Tran O'Leary <jtranoleary@google.com>
---
v4:
- Replace EAL alarm thread with a dedicated control thread to
prevent blocking shared EAL interrupt thread for up to 2s
on GVE AdminQ timeouts.
- Implement incremental sleep loop to support fast termination.
v2:
- Removed redundant void* casts.
- Handled alarm reschedule failures by marking timestamp stale.
- Added transient error logging on memzone allocation failure.
---
drivers/net/gve/gve_ethdev.c | 122 +++++++++++++++++++++++++++++++++++
drivers/net/gve/gve_ethdev.h | 12 ++++
2 files changed, 134 insertions(+)
diff --git a/drivers/net/gve/gve_ethdev.c b/drivers/net/gve/gve_ethdev.c
index 476b2c311f..fa91575b3e 100644
--- a/drivers/net/gve/gve_ethdev.c
+++ b/drivers/net/gve/gve_ethdev.c
@@ -452,6 +452,94 @@ gve_dev_start(struct rte_eth_dev *dev)
return 0;
}
+static void
+gve_read_nic_clock(void *arg)
+{
+ struct gve_priv *priv = arg;
+ uint32_t fails;
+ uint64_t ts;
+ int err;
+
+ if (!priv || !priv->nic_ts_report_mz)
+ return;
+
+ memset(priv->nic_ts_report, 0, sizeof(struct gve_nic_ts_report));
+
+ err = gve_adminq_report_nic_timestamp(priv, priv->nic_ts_report_mz->iova);
+ if (err == 0) {
+ ts = be64_to_cpu(priv->nic_ts_report->nic_timestamp);
+ rte_atomic_store_explicit(&priv->last_read_nic_timestamp, ts,
+ rte_memory_order_relaxed);
+ PMD_DRV_LOG(DEBUG, "Fetched NIC Timestamp: %" PRIu64, ts);
+ rte_atomic_store_explicit(&priv->nic_ts_read_fails, 0,
+ rte_memory_order_relaxed);
+ rte_atomic_store_explicit(&priv->nic_ts_stale, 0,
+ rte_memory_order_release);
+ } else {
+ PMD_DRV_LOG(ERR, "Failed to read NIC clock, AQ err: %d", err);
+ fails = rte_atomic_fetch_add_explicit(&priv->nic_ts_read_fails, 1,
+ rte_memory_order_relaxed) + 1;
+ if (fails >= GVE_NIC_CLOCK_READ_MAX_FAILS) {
+ if (!rte_atomic_load_explicit(&priv->nic_ts_stale,
+ rte_memory_order_relaxed))
+ PMD_DRV_LOG(ERR,
+ "NIC timestamping marked as stale after %u consecutive failures",
+ GVE_NIC_CLOCK_READ_MAX_FAILS);
+ rte_atomic_store_explicit(&priv->nic_ts_stale, 1,
+ rte_memory_order_release);
+ }
+ }
+}
+
+static uint32_t
+gve_nic_ts_thread(void *arg)
+{
+ struct gve_priv *priv = arg;
+ unsigned int sleep_cnt;
+
+ while (!rte_atomic_load_explicit(&priv->nic_ts_thread_should_stop,
+ rte_memory_order_relaxed)) {
+ gve_read_nic_clock(priv);
+ for (sleep_cnt = 0; sleep_cnt < GVE_NIC_CLOCK_READ_PERIOD_MS / 10; sleep_cnt++) {
+ if (rte_atomic_load_explicit(&priv->nic_ts_thread_should_stop,
+ rte_memory_order_relaxed))
+ break;
+ rte_delay_us_sleep(10000);
+ }
+ }
+ return 0;
+}
+
+static int
+gve_alloc_nic_ts_report(struct gve_priv *priv)
+{
+ char z_name[RTE_MEMZONE_NAMESIZE];
+
+ snprintf(z_name, sizeof(z_name), "gve_%s_nic_ts_report",
+ priv->pci_dev->device.name);
+ priv->nic_ts_report_mz = rte_memzone_reserve_aligned(z_name,
+ sizeof(struct gve_nic_ts_report), rte_socket_id(),
+ RTE_MEMZONE_IOVA_CONTIG, PAGE_SIZE);
+
+ if (!priv->nic_ts_report_mz) {
+ PMD_DRV_LOG(ERR, "Failed to allocate memzone for NIC TS report");
+ return -ENOMEM;
+ }
+ priv->nic_ts_report = priv->nic_ts_report_mz->addr;
+ rte_atomic_store_explicit(&priv->nic_ts_read_fails, 0, rte_memory_order_relaxed);
+ return 0;
+}
+
+static void
+gve_free_nic_ts_report(struct gve_priv *priv)
+{
+ if (priv->nic_ts_report_mz) {
+ rte_memzone_free(priv->nic_ts_report_mz);
+ priv->nic_ts_report_mz = NULL;
+ priv->nic_ts_report = NULL;
+ }
+}
+
static int
gve_dev_stop(struct rte_eth_dev *dev)
{
@@ -586,6 +674,13 @@ gve_teardown_device_resources(struct gve_priv *priv)
err);
}
+ if (priv->nic_ts_report_mz) {
+ rte_atomic_store_explicit(&priv->nic_ts_thread_should_stop, 1,
+ rte_memory_order_relaxed);
+ rte_thread_join(priv->nic_ts_thread_id, NULL);
+ gve_free_nic_ts_report(priv);
+ }
+
gve_free_ptype_lut_dqo(priv);
gve_free_counter_array(priv);
gve_free_irq_db(priv);
@@ -1252,6 +1347,32 @@ pci_dev_msix_vec_count(struct rte_pci_device *pdev)
return 0;
}
+static void
+gve_setup_nic_timestamp(struct gve_priv *priv)
+{
+ int err;
+
+ if (!priv->nic_timestamp_supported)
+ return;
+
+ rte_atomic_store_explicit(&priv->nic_ts_read_fails, 0, rte_memory_order_relaxed);
+ rte_atomic_store_explicit(&priv->nic_ts_stale, 1, rte_memory_order_relaxed);
+ err = gve_alloc_nic_ts_report(priv);
+ if (err == 0) {
+ gve_read_nic_clock(priv);
+ rte_atomic_store_explicit(&priv->nic_ts_thread_should_stop, 0,
+ rte_memory_order_relaxed);
+ err = rte_thread_create_internal_control(&priv->nic_ts_thread_id, "gve-ts",
+ gve_nic_ts_thread, priv);
+ if (err != 0) {
+ PMD_DRV_LOG(ERR, "Failed to create NIC clock sync thread, err=%d", err);
+ gve_free_nic_ts_report(priv);
+ }
+ } else {
+ PMD_DRV_LOG(ERR, "Failed to allocate memory for NIC timestamping subsystem. Please reset device to retry.");
+ }
+}
+
static int
gve_setup_device_resources(struct gve_priv *priv)
{
@@ -1307,6 +1428,7 @@ gve_setup_device_resources(struct gve_priv *priv)
goto free_ptype_lut;
}
}
+ gve_setup_nic_timestamp(priv);
gve_set_device_resources_ok(priv);
diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h
index b67f82c263..4dcbaa9971 100644
--- a/drivers/net/gve/gve_ethdev.h
+++ b/drivers/net/gve/gve_ethdev.h
@@ -12,6 +12,8 @@
#include <rte_pci.h>
#include <pthread.h>
#include <rte_bitmap.h>
+#include <rte_memzone.h>
+#include <rte_thread.h>
#include "base/gve.h"
@@ -39,6 +41,9 @@
#define GVE_RSS_HASH_KEY_SIZE 40
#define GVE_RSS_INDIR_SIZE 128
+#define GVE_NIC_CLOCK_READ_PERIOD_MS 250
+#define GVE_NIC_CLOCK_READ_MAX_FAILS 7
+
#define GVE_TX_CKSUM_OFFLOAD_MASK ( \
RTE_MBUF_F_TX_L4_MASK | \
RTE_MBUF_F_TX_TCP_SEG)
@@ -359,6 +364,13 @@ struct gve_priv {
/* HW Timestamping Fields */
bool nic_timestamp_supported;
+ const struct rte_memzone *nic_ts_report_mz;
+ struct gve_nic_ts_report *nic_ts_report;
+ RTE_ATOMIC(uint64_t) last_read_nic_timestamp;
+ RTE_ATOMIC(uint32_t) nic_ts_read_fails;
+ RTE_ATOMIC(uint8_t) nic_ts_stale;
+ rte_thread_t nic_ts_thread_id;
+ RTE_ATOMIC(uint8_t) nic_ts_thread_should_stop;
};
static inline bool
--
2.54.0.1136.gdb2ca164c4-goog
^ permalink raw reply related
* [PATCH v4 3/6] net/gve: add AdminQ command for NIC timestamps
From: Mark Blasko @ 2026-06-13 4:22 UTC (permalink / raw)
To: stephen; +Cc: dev, joshwash, jtranoleary, blasko
In-Reply-To: <20260613042300.3760470-1-blasko@google.com>
Introduce the necessary definitions and functions for the
GVE_ADMINQ_REPORT_NIC_TIMESTAMP AdminQ command.
Signed-off-by: Mark Blasko <blasko@google.com>
Reviewed-by: Joshua Washington <joshwash@google.com>
Reviewed-by: Jasper Tran O'Leary <jtranoleary@google.com>
---
v2:
- Added adminq timestamp counter reset to gve_adminq_alloc.
---
drivers/net/gve/base/gve_adminq.c | 20 ++++++++++++++++++++
drivers/net/gve/base/gve_adminq.h | 20 ++++++++++++++++++++
drivers/net/gve/gve_ethdev.h | 1 +
3 files changed, 41 insertions(+)
diff --git a/drivers/net/gve/base/gve_adminq.c b/drivers/net/gve/base/gve_adminq.c
index 1ced1e442e..2b25c7f390 100644
--- a/drivers/net/gve/base/gve_adminq.c
+++ b/drivers/net/gve/base/gve_adminq.c
@@ -263,6 +263,8 @@ int gve_adminq_alloc(struct gve_priv *priv)
priv->adminq_get_ptype_map_cnt = 0;
priv->adminq_cfg_flow_rule_cnt = 0;
+ priv->adminq_report_nic_timestamp_cnt = 0;
+
pthread_mutexattr_init(&mutexattr);
pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&priv->adminq_lock, &mutexattr);
@@ -522,6 +524,10 @@ static int gve_adminq_issue_cmd(struct gve_priv *priv,
case GVE_ADMINQ_CONFIGURE_FLOW_RULE:
priv->adminq_cfg_flow_rule_cnt++;
break;
+ case GVE_ADMINQ_REPORT_NIC_TIMESTAMP:
+ priv->adminq_report_nic_timestamp_cnt++;
+ break;
+
default:
PMD_DRV_LOG(ERR, "unknown AQ command opcode %d", opcode);
}
@@ -636,6 +642,20 @@ int gve_adminq_reset_flow_rules(struct gve_priv *priv)
return gve_adminq_configure_flow_rule(priv, &flow_rule_cmd);
}
+int gve_adminq_report_nic_timestamp(struct gve_priv *priv, dma_addr_t nic_ts_report_addr)
+{
+ union gve_adminq_command cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.opcode = cpu_to_be32(GVE_ADMINQ_REPORT_NIC_TIMESTAMP);
+ cmd.report_nic_timestamp = (struct gve_adminq_report_nic_timestamp) {
+ .nic_ts_report_len = cpu_to_be64(sizeof(struct gve_nic_ts_report)),
+ .nic_timestamp_addr = cpu_to_be64(nic_ts_report_addr),
+ };
+
+ return gve_adminq_execute_cmd(priv, &cmd);
+}
+
/* The device specifies that the management vector can either be the first irq
* or the last irq. ntfy_blk_msix_base_idx indicates the first irq assigned to
* the ntfy blks. It if is 0 then the management vector is last, if it is 1 then
diff --git a/drivers/net/gve/base/gve_adminq.h b/drivers/net/gve/base/gve_adminq.h
index eaee5649f2..954be39fbf 100644
--- a/drivers/net/gve/base/gve_adminq.h
+++ b/drivers/net/gve/base/gve_adminq.h
@@ -26,6 +26,7 @@ enum gve_adminq_opcodes {
GVE_ADMINQ_REPORT_LINK_SPEED = 0xD,
GVE_ADMINQ_GET_PTYPE_MAP = 0xE,
GVE_ADMINQ_VERIFY_DRIVER_COMPATIBILITY = 0xF,
+ GVE_ADMINQ_REPORT_NIC_TIMESTAMP = 0x11,
/* For commands that are larger than 56 bytes */
GVE_ADMINQ_EXTENDED_COMMAND = 0xFF,
};
@@ -373,6 +374,23 @@ struct gve_stats_report {
GVE_CHECK_STRUCT_LEN(8, gve_stats_report);
+struct gve_adminq_report_nic_timestamp {
+ __be64 nic_ts_report_len;
+ __be64 nic_timestamp_addr;
+};
+
+GVE_CHECK_STRUCT_LEN(16, gve_adminq_report_nic_timestamp);
+
+struct gve_nic_ts_report {
+ __be64 nic_timestamp; /* NIC clock in nanoseconds */
+ __be64 pre_cycles; /* System cycle counter before NIC clock read */
+ __be64 post_cycles; /* System cycle counter after NIC clock read */
+ __be64 reserved3;
+ __be64 reserved4;
+};
+
+GVE_CHECK_STRUCT_LEN(40, gve_nic_ts_report);
+
/* Numbers of gve tx/rx stats in stats report. */
#define GVE_TX_STATS_REPORT_NUM 6
#define GVE_RX_STATS_REPORT_NUM 2
@@ -490,6 +508,7 @@ union gve_adminq_command {
struct gve_adminq_verify_driver_compatibility
verify_driver_compatibility;
struct gve_adminq_extended_command extended_command;
+ struct gve_adminq_report_nic_timestamp report_nic_timestamp;
};
};
u8 reserved[64];
@@ -537,5 +556,6 @@ int gve_adminq_add_flow_rule(struct gve_priv *priv,
struct gve_flow_rule_params *rule, u32 loc);
int gve_adminq_del_flow_rule(struct gve_priv *priv, u32 loc);
int gve_adminq_reset_flow_rules(struct gve_priv *priv);
+int gve_adminq_report_nic_timestamp(struct gve_priv *priv, dma_addr_t nic_ts_report_addr);
#endif /* _GVE_ADMINQ_H */
diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h
index b9b4688367..b67f82c263 100644
--- a/drivers/net/gve/gve_ethdev.h
+++ b/drivers/net/gve/gve_ethdev.h
@@ -328,6 +328,7 @@ struct gve_priv {
uint32_t adminq_get_ptype_map_cnt;
uint32_t adminq_verify_driver_compatibility_cnt;
uint32_t adminq_cfg_flow_rule_cnt;
+ uint32_t adminq_report_nic_timestamp_cnt;
volatile uint32_t state_flags;
/* Gvnic device link speed from hypervisor. */
--
2.54.0.1136.gdb2ca164c4-goog
^ permalink raw reply related
* [PATCH v4 2/6] net/gve: add device option support for HW timestamps
From: Mark Blasko @ 2026-06-13 4:22 UTC (permalink / raw)
To: stephen; +Cc: dev, joshwash, jtranoleary, blasko
In-Reply-To: <20260613042300.3760470-1-blasko@google.com>
Introduce the necessary definitions and functions for the device
option flag (GVE_DEV_OPT_ID_NIC_TIMESTAMP) to detect hardware
timestamping support in the gvnic device.
Signed-off-by: Mark Blasko <blasko@google.com>
Reviewed-by: Joshua Washington <joshwash@google.com>
Reviewed-by: Jasper Tran O'Leary <jtranoleary@google.com>
---
drivers/net/gve/base/gve_adminq.c | 41 ++++++++++++++++++++++++++-----
drivers/net/gve/base/gve_adminq.h | 9 +++++++
drivers/net/gve/gve_ethdev.h | 3 +++
3 files changed, 47 insertions(+), 6 deletions(-)
diff --git a/drivers/net/gve/base/gve_adminq.c b/drivers/net/gve/base/gve_adminq.c
index 743ab8e7ae..1ced1e442e 100644
--- a/drivers/net/gve/base/gve_adminq.c
+++ b/drivers/net/gve/base/gve_adminq.c
@@ -38,7 +38,8 @@ void gve_parse_device_option(struct gve_priv *priv,
struct gve_device_option_dqo_rda **dev_op_dqo_rda,
struct gve_device_option_flow_steering **dev_op_flow_steering,
struct gve_device_option_modify_ring **dev_op_modify_ring,
- struct gve_device_option_jumbo_frames **dev_op_jumbo_frames)
+ struct gve_device_option_jumbo_frames **dev_op_jumbo_frames,
+ struct gve_device_option_nic_timestamp **dev_op_nic_timestamp)
{
u32 req_feat_mask = be32_to_cpu(option->required_features_mask);
u16 option_length = be16_to_cpu(option->option_length);
@@ -168,6 +169,24 @@ void gve_parse_device_option(struct gve_priv *priv,
}
*dev_op_jumbo_frames = RTE_PTR_ADD(option, sizeof(*option));
break;
+ case GVE_DEV_OPT_ID_NIC_TIMESTAMP:
+ if (option_length < sizeof(**dev_op_nic_timestamp) ||
+ req_feat_mask != GVE_DEV_OPT_REQ_FEAT_MASK_NIC_TIMESTAMP) {
+ PMD_DRV_LOG(WARNING, GVE_DEVICE_OPTION_ERROR_FMT,
+ "Nic Timestamp",
+ (int)sizeof(**dev_op_nic_timestamp),
+ GVE_DEV_OPT_REQ_FEAT_MASK_NIC_TIMESTAMP,
+ option_length, req_feat_mask);
+ break;
+ }
+
+ if (option_length > sizeof(**dev_op_nic_timestamp)) {
+ PMD_DRV_LOG(WARNING,
+ GVE_DEVICE_OPTION_TOO_BIG_FMT,
+ "Nic Timestamp");
+ }
+ *dev_op_nic_timestamp = RTE_PTR_ADD(option, sizeof(*option));
+ break;
default:
/* If we don't recognize the option just continue
* without doing anything.
@@ -186,7 +205,8 @@ gve_process_device_options(struct gve_priv *priv,
struct gve_device_option_dqo_rda **dev_op_dqo_rda,
struct gve_device_option_flow_steering **dev_op_flow_steering,
struct gve_device_option_modify_ring **dev_op_modify_ring,
- struct gve_device_option_jumbo_frames **dev_op_jumbo_frames)
+ struct gve_device_option_jumbo_frames **dev_op_jumbo_frames,
+ struct gve_device_option_nic_timestamp **dev_op_nic_timestamp)
{
const int num_options = be16_to_cpu(descriptor->num_device_options);
struct gve_device_option *dev_opt;
@@ -207,7 +227,8 @@ gve_process_device_options(struct gve_priv *priv,
gve_parse_device_option(priv, dev_opt,
dev_op_gqi_rda, dev_op_gqi_qpl,
dev_op_dqo_rda, dev_op_flow_steering,
- dev_op_modify_ring, dev_op_jumbo_frames);
+ dev_op_modify_ring, dev_op_jumbo_frames,
+ dev_op_nic_timestamp);
dev_opt = next_opt;
}
@@ -920,7 +941,8 @@ static void gve_enable_supported_features(struct gve_priv *priv,
u32 supported_features_mask,
const struct gve_device_option_flow_steering *dev_op_flow_steering,
const struct gve_device_option_modify_ring *dev_op_modify_ring,
- const struct gve_device_option_jumbo_frames *dev_op_jumbo_frames)
+ const struct gve_device_option_jumbo_frames *dev_op_jumbo_frames,
+ const struct gve_device_option_nic_timestamp *dev_op_nic_timestamp)
{
if (dev_op_flow_steering &&
(supported_features_mask & GVE_SUP_FLOW_STEERING_MASK) &&
@@ -947,6 +969,11 @@ static void gve_enable_supported_features(struct gve_priv *priv,
PMD_DRV_LOG(INFO, "JUMBO FRAMES device option enabled.");
priv->max_mtu = be16_to_cpu(dev_op_jumbo_frames->max_mtu);
}
+ if (dev_op_nic_timestamp &&
+ (supported_features_mask & GVE_SUP_NIC_TIMESTAMP_MASK)) {
+ PMD_DRV_LOG(INFO, "NIC TIMESTAMP device option enabled.");
+ priv->nic_timestamp_supported = true;
+ }
}
int gve_adminq_describe_device(struct gve_priv *priv)
@@ -954,6 +981,7 @@ int gve_adminq_describe_device(struct gve_priv *priv)
struct gve_device_option_jumbo_frames *dev_op_jumbo_frames = NULL;
struct gve_device_option_modify_ring *dev_op_modify_ring = NULL;
struct gve_device_option_flow_steering *dev_op_flow_steering = NULL;
+ struct gve_device_option_nic_timestamp *dev_op_nic_timestamp = NULL;
struct gve_device_option_gqi_rda *dev_op_gqi_rda = NULL;
struct gve_device_option_gqi_qpl *dev_op_gqi_qpl = NULL;
struct gve_device_option_dqo_rda *dev_op_dqo_rda = NULL;
@@ -983,7 +1011,8 @@ int gve_adminq_describe_device(struct gve_priv *priv)
&dev_op_gqi_qpl, &dev_op_dqo_rda,
&dev_op_flow_steering,
&dev_op_modify_ring,
- &dev_op_jumbo_frames);
+ &dev_op_jumbo_frames,
+ &dev_op_nic_timestamp);
if (err)
goto free_device_descriptor;
@@ -1038,7 +1067,7 @@ int gve_adminq_describe_device(struct gve_priv *priv)
gve_enable_supported_features(priv, supported_features_mask,
dev_op_flow_steering, dev_op_modify_ring,
- dev_op_jumbo_frames);
+ dev_op_jumbo_frames, dev_op_nic_timestamp);
free_device_descriptor:
gve_free_dma_mem(&descriptor_dma_mem);
diff --git a/drivers/net/gve/base/gve_adminq.h b/drivers/net/gve/base/gve_adminq.h
index d8e5e6a352..eaee5649f2 100644
--- a/drivers/net/gve/base/gve_adminq.h
+++ b/drivers/net/gve/base/gve_adminq.h
@@ -153,6 +153,12 @@ struct gve_device_option_jumbo_frames {
GVE_CHECK_STRUCT_LEN(8, gve_device_option_jumbo_frames);
+struct gve_device_option_nic_timestamp {
+ __be32 supported_features_mask;
+};
+
+GVE_CHECK_STRUCT_LEN(4, gve_device_option_nic_timestamp);
+
/* Terminology:
*
* RDA - Raw DMA Addressing - Buffers associated with SKBs are directly DMA
@@ -169,6 +175,7 @@ enum gve_dev_opt_id {
GVE_DEV_OPT_ID_MODIFY_RING = 0x6,
GVE_DEV_OPT_ID_JUMBO_FRAMES = 0x8,
GVE_DEV_OPT_ID_FLOW_STEERING = 0xb,
+ GVE_DEV_OPT_ID_NIC_TIMESTAMP = 0xd,
};
enum gve_dev_opt_req_feat_mask {
@@ -179,12 +186,14 @@ enum gve_dev_opt_req_feat_mask {
GVE_DEV_OPT_REQ_FEAT_MASK_FLOW_STEERING = 0x0,
GVE_DEV_OPT_REQ_FEAT_MASK_MODIFY_RING = 0x0,
GVE_DEV_OPT_REQ_FEAT_MASK_JUMBO_FRAMES = 0x0,
+ GVE_DEV_OPT_REQ_FEAT_MASK_NIC_TIMESTAMP = 0x0,
};
enum gve_sup_feature_mask {
GVE_SUP_MODIFY_RING_MASK = 1 << 0,
GVE_SUP_JUMBO_FRAMES_MASK = 1 << 2,
GVE_SUP_FLOW_STEERING_MASK = 1 << 5,
+ GVE_SUP_NIC_TIMESTAMP_MASK = 1 << 8,
};
#define GVE_DEV_OPT_LEN_GQI_RAW_ADDRESSING 0x0
diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h
index 524e48e723..b9b4688367 100644
--- a/drivers/net/gve/gve_ethdev.h
+++ b/drivers/net/gve/gve_ethdev.h
@@ -355,6 +355,9 @@ struct gve_priv {
void *avail_flow_rule_bmp_mem; /* Backing memory for the bitmap */
pthread_mutex_t flow_rule_lock; /* Lock for bitmap and tailq access */
TAILQ_HEAD(, gve_flow) active_flows;
+
+ /* HW Timestamping Fields */
+ bool nic_timestamp_supported;
};
static inline bool
--
2.54.0.1136.gdb2ca164c4-goog
^ permalink raw reply related
* [PATCH v4 1/6] net/gve: add thread safety to admin queue
From: Mark Blasko @ 2026-06-13 4:22 UTC (permalink / raw)
To: stephen; +Cc: dev, joshwash, jtranoleary, blasko
In-Reply-To: <20260613042300.3760470-1-blasko@google.com>
Introduce a pthread_mutex to protect the admin queue operations.
Locking was added around gve_adminq_execute_cmd and the batch
queue creation/destruction functions.
Signed-off-by: Mark Blasko <blasko@google.com>
Reviewed-by: Joshua Washington <joshwash@google.com>
Reviewed-by: Jasper Tran O'Leary <jtranoleary@google.com>
---
v2:
- Dropped ROBUST mutex attribute.
---
.mailmap | 1 +
drivers/net/gve/base/gve_adminq.c | 67 +++++++++++++++++++++++++------
drivers/net/gve/gve_ethdev.h | 1 +
3 files changed, 56 insertions(+), 13 deletions(-)
diff --git a/.mailmap b/.mailmap
index e052b85213..1b10cfca35 100644
--- a/.mailmap
+++ b/.mailmap
@@ -1016,6 +1016,7 @@ Mario Carrillo <mario.alfredo.c.arevalo@intel.com>
Mário Kuka <kuka@cesnet.cz>
Mariusz Drost <mariuszx.drost@intel.com>
Mark Asselstine <mark.asselstine@windriver.com>
+Mark Blasko <blasko@google.com>
Mark Bloch <mbloch@nvidia.com> <markb@mellanox.com>
Mark Gillott <mgillott@vyatta.att-mail.com>
Mark Kavanagh <mark.b.kavanagh@intel.com>
diff --git a/drivers/net/gve/base/gve_adminq.c b/drivers/net/gve/base/gve_adminq.c
index 9c5316fb00..743ab8e7ae 100644
--- a/drivers/net/gve/base/gve_adminq.c
+++ b/drivers/net/gve/base/gve_adminq.c
@@ -216,6 +216,7 @@ gve_process_device_options(struct gve_priv *priv,
int gve_adminq_alloc(struct gve_priv *priv)
{
+ pthread_mutexattr_t mutexattr;
uint8_t pci_rev_id;
priv->adminq = gve_alloc_dma_mem(&priv->adminq_dma_mem, PAGE_SIZE);
@@ -241,6 +242,11 @@ int gve_adminq_alloc(struct gve_priv *priv)
priv->adminq_get_ptype_map_cnt = 0;
priv->adminq_cfg_flow_rule_cnt = 0;
+ pthread_mutexattr_init(&mutexattr);
+ pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);
+ pthread_mutex_init(&priv->adminq_lock, &mutexattr);
+ pthread_mutexattr_destroy(&mutexattr);
+
/* Setup Admin queue with the device */
rte_pci_read_config(priv->pci_dev, &pci_rev_id, sizeof(pci_rev_id),
RTE_PCI_REVISION_ID);
@@ -304,6 +310,7 @@ void gve_adminq_free(struct gve_priv *priv)
return;
gve_adminq_release(priv);
gve_free_dma_mem(&priv->adminq_dma_mem);
+ pthread_mutex_destroy(&priv->adminq_lock);
gve_clear_admin_queue_ok(priv);
}
@@ -418,7 +425,10 @@ static int gve_adminq_issue_cmd(struct gve_priv *priv,
(tail & priv->adminq_mask)) {
int err;
- /* Flush existing commands to make room. */
+ /* Flush existing commands to make room.
+ * Note: This kicks the doorbell for all staged commands.
+ * Any failure here means we failed after attempting to kick.
+ */
err = gve_adminq_kick_and_wait(priv);
if (err)
return err;
@@ -509,17 +519,24 @@ static int gve_adminq_execute_cmd(struct gve_priv *priv,
u32 tail, head;
int err;
+ pthread_mutex_lock(&priv->adminq_lock);
tail = ioread32be(&priv->reg_bar0->adminq_event_counter);
head = priv->adminq_prod_cnt;
- if (tail != head)
+ if (tail != head) {
/* This is not a valid path */
- return -EINVAL;
+ err = -EINVAL;
+ goto unlock_and_return;
+ }
err = gve_adminq_issue_cmd(priv, cmd_orig);
if (err)
- return err;
+ goto unlock_and_return;
- return gve_adminq_kick_and_wait(priv);
+ err = gve_adminq_kick_and_wait(priv);
+
+unlock_and_return:
+ pthread_mutex_unlock(&priv->adminq_lock);
+ return err;
}
static int gve_adminq_execute_extended_cmd(struct gve_priv *priv, u32 opcode,
@@ -693,13 +710,19 @@ int gve_adminq_create_tx_queues(struct gve_priv *priv, u32 num_queues)
int err;
u32 i;
+ pthread_mutex_lock(&priv->adminq_lock);
+
for (i = 0; i < num_queues; i++) {
err = gve_adminq_create_tx_queue(priv, i);
if (err)
- return err;
+ goto unlock_and_return;
}
- return gve_adminq_kick_and_wait(priv);
+ err = gve_adminq_kick_and_wait(priv);
+
+unlock_and_return:
+ pthread_mutex_unlock(&priv->adminq_lock);
+ return err;
}
static int gve_adminq_create_rx_queue(struct gve_priv *priv, u32 queue_index)
@@ -747,13 +770,19 @@ int gve_adminq_create_rx_queues(struct gve_priv *priv, u32 num_queues)
int err;
u32 i;
+ pthread_mutex_lock(&priv->adminq_lock);
+
for (i = 0; i < num_queues; i++) {
err = gve_adminq_create_rx_queue(priv, i);
if (err)
- return err;
+ goto unlock_and_return;
}
- return gve_adminq_kick_and_wait(priv);
+ err = gve_adminq_kick_and_wait(priv);
+
+unlock_and_return:
+ pthread_mutex_unlock(&priv->adminq_lock);
+ return err;
}
static int gve_adminq_destroy_tx_queue(struct gve_priv *priv, u32 queue_index)
@@ -779,13 +808,19 @@ int gve_adminq_destroy_tx_queues(struct gve_priv *priv, u32 num_queues)
int err;
u32 i;
+ pthread_mutex_lock(&priv->adminq_lock);
+
for (i = 0; i < num_queues; i++) {
err = gve_adminq_destroy_tx_queue(priv, i);
if (err)
- return err;
+ goto unlock_and_return;
}
- return gve_adminq_kick_and_wait(priv);
+ err = gve_adminq_kick_and_wait(priv);
+
+unlock_and_return:
+ pthread_mutex_unlock(&priv->adminq_lock);
+ return err;
}
static int gve_adminq_destroy_rx_queue(struct gve_priv *priv, u32 queue_index)
@@ -811,13 +846,19 @@ int gve_adminq_destroy_rx_queues(struct gve_priv *priv, u32 num_queues)
int err;
u32 i;
+ pthread_mutex_lock(&priv->adminq_lock);
+
for (i = 0; i < num_queues; i++) {
err = gve_adminq_destroy_rx_queue(priv, i);
if (err)
- return err;
+ goto unlock_and_return;
}
- return gve_adminq_kick_and_wait(priv);
+ err = gve_adminq_kick_and_wait(priv);
+
+unlock_and_return:
+ pthread_mutex_unlock(&priv->adminq_lock);
+ return err;
}
static int gve_set_desc_cnt(struct gve_priv *priv,
diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h
index 0577f03974..524e48e723 100644
--- a/drivers/net/gve/gve_ethdev.h
+++ b/drivers/net/gve/gve_ethdev.h
@@ -339,6 +339,7 @@ struct gve_priv {
struct gve_tx_queue **txqs;
struct gve_rx_queue **rxqs;
+ pthread_mutex_t adminq_lock; /* Protects AdminQ command execution */
uint32_t stats_report_len;
const struct rte_memzone *stats_report_mem;
uint16_t stats_start_idx; /* start index of array of stats written by NIC */
--
2.54.0.1136.gdb2ca164c4-goog
^ permalink raw reply related
* [PATCH v4 0/6] net/gve: add hardware timestamping support
From: Mark Blasko @ 2026-06-13 4:22 UTC (permalink / raw)
To: stephen; +Cc: dev, joshwash, jtranoleary, blasko
In-Reply-To: <20260605213022.2770893-1-blasko@google.com>
This patch series introduces support for GVE hardware timestamping
on DQO queues. To support concurrent access, a mutex lock is introduced
to protect admin queue operations. A mechanism is then added to
periodically synchronize the NIC clock via a dedicated control thread,
and support is introduced for the read_clock ethdev operation.
Finally, the RX datapath is updated to reconstruct full 64-bit
timestamps from the 32-bit values in DQO descriptors.
---
v4:
- Patch 4: Offload periodic NIC clock reads to a dedicated control thread.
- Patch 5: Correct mutex initialization and teardown ordering.
- Patch 6: Update GVE documentation to clarify queue format requirements.
v3:
- Patch 5:
- Add mutex lock to protect shared NIC timestamp memzone access.
- Fix missing read_clock assignment to DQO queue ops table
(accidental omission in v2).
v2:
- Patch 1: Dropped ROBUST mutex attribute.
- Patch 3: Added adminq timestamp counter reset to gve_adminq_alloc.
- Patch 4:
- Removed redundant void* casts.
- Handled alarm reschedule failures by marking timestamp stale.
- Added transient error logging on memzone allocation failure.
- Patch 5: Scoped read_clock ethdev operation strictly to DQO queues.
- Patch 6:
- Scoped timestamp offload capability advertisement strictly to
DQO queues.
- Predicated capability advertisement directly on memzone
allocation.
- Initialized mbuf_timestamp_offset to -1.
- Added blank line separating release notes.
---
Mark Blasko (6):
net/gve: add thread safety to admin queue
net/gve: add device option support for HW timestamps
net/gve: add AdminQ command for NIC timestamps
net/gve: add periodic NIC clock synchronization
net/gve: support read clock ethdev op
net/gve: reconstruct HW timestamps from DQO
.mailmap | 1 +
doc/guides/nics/features/gve.ini | 1 +
doc/guides/nics/gve.rst | 20 +++
doc/guides/rel_notes/release_26_07.rst | 4 +
drivers/net/gve/base/gve_adminq.c | 128 +++++++++++++---
drivers/net/gve/base/gve_adminq.h | 29 ++++
drivers/net/gve/base/gve_desc_dqo.h | 8 +-
drivers/net/gve/gve_ethdev.c | 194 +++++++++++++++++++++++--
drivers/net/gve/gve_ethdev.h | 43 ++++++
drivers/net/gve/gve_rx_dqo.c | 26 ++++
10 files changed, 424 insertions(+), 30 deletions(-)
--
2.54.0.1136.gdb2ca164c4-goog
^ permalink raw reply
* [PATCH v2] tools: AI review handle empty Error sections
From: Matthew Gee @ 2026-06-12 19:08 UTC (permalink / raw)
To: dev; +Cc: stephen, aconole, lylavoie, Matthew Gee
In-Reply-To: <20260612190225.1016275-1-mgee@iol.unh.edu>
Previous review-patch.py would detect and report and error or warning
based off of the occurrence of the headers of the error and warning
sections. This led to consistent false positives as often AI reviewers
will create the header but put "none" or similar filler text within
the following body.
This patch updates the code in order to check if the AI review has a
body with error or warnings to fix and not just filler text. This is
done by querying multiple lines at once and adjusting the regex to
filter out headers followed only by filler text or formatting in the
review.
These changes were tested against 10+ AI review outputs with several
variations in formatting and filler text in order to catch a good
variety of cases to make sure code reviews with actual errors or
warnings are caught and not missed.
Signed-off-by: Matthew Gee <mgee@iol.unh.edu>
---
devtools/ai/review-patch.py | 35 +++++++++++++++++++++++++++--------
1 file changed, 27 insertions(+), 8 deletions(-)
diff --git a/devtools/ai/review-patch.py b/devtools/ai/review-patch.py
index 52601ac156..eb608566d2 100755
--- a/devtools/ai/review-patch.py
+++ b/devtools/ai/review-patch.py
@@ -19,6 +19,7 @@
from email.message import EmailMessage
from pathlib import Path
from typing import Any, Iterator
+from itertools import tee, islice, chain
from _common import (
PROVIDERS,
@@ -147,19 +148,37 @@ def classify_review(review_text: str, output_format: str) -> int:
pass # Fall through to text scanning
if not has_errors and not has_warnings:
- # Scan review text for severity indicators.
- # Match section headers and inline markers across text/markdown/html.
- for line in review_text.splitlines():
- stripped = line.strip().lower()
+ # Matches against error or warning section headers
+ rgx_should_match: str = r"#+\s(\*+)?{err_or_warn}"
+ # Matches against headers followed only by filler text, formatting, or no additional text
+ rgx_should_not_match: str = r"#+\s(\*+)?{err_or_warn}(s?)(\*+)?(none(.)?$| \(must fix\)$|$)"
+
+ curr_lines: iter[str]
+ next_lines: iter[str | None]
+ next_next_lines: iter[str | None]
+ curr_lines, next_lines, next_next_lines = tee(review_text.splitlines(), 3)
+ next_lines = chain(islice(next_lines, 1, None), [None])
+ next_next_lines = chain(islice(next_next_lines, 2, None), [None, None])
+
+ curr_lines: str
+ next_lines: str | None
+ next_next_lines: str | None
+ for curr_line, next_line, next_next_line in zip(curr_lines, next_lines, next_next_lines):
+ stripped: str = curr_line.strip().lower() + str(
+ next_line or '').strip().lower() + str(next_next_line or '').strip().lower()
# Skip quoted patch context lines
if stripped.startswith(">") or stripped.startswith("diff --git"):
continue
- if re.match(r"^(#{1,3}\s+)?(\*{0,2})error", stripped) or re.match(
- r"^<h[1-3]>\s*error", stripped
+
+ elif re.match(rgx_should_match.format(err_or_warn='error'),
+ stripped) and not re.match(
+ rgx_should_not_match.format(err_or_warn='error'), stripped
):
has_errors = True
- elif re.match(r"^(#{1,3}\s+)?(\*{0,2})warning", stripped) or re.match(
- r"^<h[1-3]>\s*warning", stripped
+
+ elif re.match(rgx_should_match.format(err_or_warn='warning'),
+ stripped) and not re.match(
+ rgx_should_not_match.format(err_or_warn='warning'), stripped
):
has_warnings = True
--
2.54.0
^ permalink raw reply related
* [PATCH v1] tools: AI review handle empty Error sections
From: Matthew Gee @ 2026-06-12 19:02 UTC (permalink / raw)
To: dev; +Cc: stephen, aconole, lylavoie, Matthew Gee
Previous review-patch.py would detect and report and error or warning
based off of the occurrence of the headers of the error and warning
sections. This led to consistent false positives as often AI reviewers
will create the header but put "none" or similar filler text within
the following body.
This patch updates the code in order to check if the AI review has a
body with error or warnings to fix and not just filler text. This is
done by querying multiple lines at once and adjusting the regex to
filter out headers followed only by filler text or formatting in the
review.
These changes were tested against 10+ AI review outputs with several
variations in formatting and filler text in order to catch a good
variety of cases to make sure code reviews with actual errors or
warnings are caught and not missed.
Signed-off-by: Matthew Gee <mgee@iol.unh.edu>
---
devtools/ai/review-patch.py | 35 +++++++++++++++++++++++++++--------
1 file changed, 27 insertions(+), 8 deletions(-)
diff --git a/devtools/ai/review-patch.py b/devtools/ai/review-patch.py
index 52601ac156..b009368638 100755
--- a/devtools/ai/review-patch.py
+++ b/devtools/ai/review-patch.py
@@ -19,6 +19,7 @@
from email.message import EmailMessage
from pathlib import Path
from typing import Any, Iterator
+from itertools import tee, islice, chain
from _common import (
PROVIDERS,
@@ -147,19 +148,37 @@ def classify_review(review_text: str, output_format: str) -> int:
pass # Fall through to text scanning
if not has_errors and not has_warnings:
- # Scan review text for severity indicators.
- # Match section headers and inline markers across text/markdown/html.
- for line in review_text.splitlines():
- stripped = line.strip().lower()
+ # Matches against error or warning section headers
+ rgx_should_match: str = r"#+\s(\*+)?{err_or_warn}"
+ # Matches against headers followed only by filler text, formatting, or no additional text
+ rgx_should_not_match: str = r"#+\s(\*+)?{err_or_warn}(s?)(\*+)?(none(.)?$| \(must fix\)$|$)"
+
+ curr_lines: iter[str]
+ next_lines: iter[str | None]
+ next_next_lines: iter[str | None]
+ curr_lines, next_lines, next_next_lines = tee(review_text.splitlines(), 3)
+ next_lines = chain(islice(next_lines, 1, None), [None])
+ next_next_lines = chain(islice(next_next_lines, 2, None), [None, None])
+
+ curr_lines: str
+ next_lines: str | None
+ next_next_lines: str | None
+ for curr_line, next_line, next_next_line in zip(curr_lines, next_lines, next_next_lines):
+ stripped: str = curr_line.strip().lower() + str(
+ next_line or '').strip().lower() + str(next_next_line or '').strip().lower()
# Skip quoted patch context lines
if stripped.startswith(">") or stripped.startswith("diff --git"):
continue
- if re.match(r"^(#{1,3}\s+)?(\*{0,2})error", stripped) or re.match(
- r"^<h[1-3]>\s*error", stripped
+
+ elif re.match(rgx_should_match.format(err_or_warn='error'),
+ stripped) and not re.match(
+ rgx_should_not_match.format(err_or_warn='error'), stripped
):
has_errors = True
- elif re.match(r"^(#{1,3}\s+)?(\*{0,2})warning", stripped) or re.match(
- r"^<h[1-3]>\s*warning", stripped
+
+ elif re.match(rgx_should_match.format(err_or_warn='warning'),
+ stripped) and not re.match(
+ rgx_should_not_match.format(err_or_warn='warning'), stripped
):
has_warnings = True
--
2.54.0
^ permalink raw reply related
* Re: [PATCH v2] app/testpmd: add padding mode to txonly engine
From: Stephen Hemminger @ 2026-06-12 16:13 UTC (permalink / raw)
To: Xingui Yang
Cc: dev, david.marchand, aman.deep.singh, fengchengwen, yangshuaisong,
lihuisong, liuyonglong, kangfenglong
In-Reply-To: <20260612091217.2899755-1-yangxingui@huawei.com>
On Fri, 12 Jun 2026 17:12:17 +0800
Xingui Yang <yangxingui@huawei.com> wrote:
> Add a new padding mode to the txonly forwarding engine, which allows
> sending packets with configurable small sizes without standard L2/L3
> headers. This is useful for testing NIC padding logic.
>
> When padding mode is enabled via --tx-pkt-pad-mode flag:
> - l2_len and l3_len are set to 0 instead of standard header lengths
> - Packet data is filled with a static pattern instead of
> Ethernet/IP/UDP headers
> - Minimum packet length validation is bypassed to allow small
> packet sizes (e.g., set txpkts 14)
>
> Signed-off-by: Xingui Yang <yangxingui@huawei.com>
> Signed-off-by: Huisong Li <lihuisong@huawei.com>
> ---
> v2: Fix compilation exception of unterminated-string-initialization
> ---
What about something like this (*not tested*) patch.
From 84ff35849f9881a93eed65ccd43a5cd1197cecb8 Mon Sep 17 00:00:00 2001
From: Stephen Hemminger <stephen@networkplumber.org>
Date: Fri, 12 Jun 2026 09:10:17 -0700
Subject: [PATCH] testpnd: allow configuring runt frames
Allow setting transmit size to be a small value which has
ethernet header but no IP or UDP header.
---
app/test-pmd/config.c | 12 +++----
app/test-pmd/txonly.c | 35 +++++++++++++++++++--
doc/guides/testpmd_app_ug/testpmd_funcs.rst | 13 ++++++++
3 files changed, 51 insertions(+), 9 deletions(-)
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 9d457ca88e..46ff678b9f 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -6327,9 +6327,6 @@ set_tx_pkt_segments(unsigned int *seg_lengths, unsigned int nb_segs)
/*
* Check that each segment length is greater or equal than
* the mbuf data size.
- * Check also that the total packet length is greater or equal than the
- * size of an empty UDP/IP packet (sizeof(struct rte_ether_hdr) +
- * 20 + 8).
*/
tx_pkt_len = 0;
for (i = 0; i < nb_segs; i++) {
@@ -6341,10 +6338,11 @@ set_tx_pkt_segments(unsigned int *seg_lengths, unsigned int nb_segs)
}
tx_pkt_len = (uint16_t)(tx_pkt_len + seg_lengths[i]);
}
- if (tx_pkt_len < (sizeof(struct rte_ether_hdr) + 20 + 8)) {
- fprintf(stderr, "total packet length=%u < %d - give up\n",
- (unsigned) tx_pkt_len,
- (int)(sizeof(struct rte_ether_hdr) + 20 + 8));
+
+ /* Allow runt packets this is a test tool. */
+ if (tx_pkt_len < (sizeof(struct rte_ether_hdr))) {
+ fprintf(stderr, "total packet length=%u < %zu - give up\n",
+ tx_pkt_len, sizeof(struct rte_ether_hdr));
return;
}
diff --git a/app/test-pmd/txonly.c b/app/test-pmd/txonly.c
index 64893fa205..2e0abe361e 100644
--- a/app/test-pmd/txonly.c
+++ b/app/test-pmd/txonly.c
@@ -76,6 +76,12 @@ copy_buf_to_pkt_segs(void* buf, unsigned len, struct rte_mbuf *pkt,
while (offset >= seg->data_len) {
offset -= seg->data_len;
seg = seg->next;
+ /*
+ * The packet may be shorter than the header stack when
+ * generating runt frames; stop once it runs out of segments.
+ */
+ if (seg == NULL)
+ return;
}
copy_len = seg->data_len - offset;
seg_buf = rte_pktmbuf_mtod_offset(seg, char *, offset);
@@ -84,6 +90,8 @@ copy_buf_to_pkt_segs(void* buf, unsigned len, struct rte_mbuf *pkt,
len -= copy_len;
buf = ((char*) buf + copy_len);
seg = seg->next;
+ if (seg == NULL)
+ return;
seg_buf = rte_pktmbuf_mtod(seg, char *);
copy_len = seg->data_len;
}
@@ -193,7 +201,6 @@ pkt_burst_prepare(struct rte_mbuf *pkt, struct rte_mempool *mbp,
pkt->vlan_tci = vlan_tci;
pkt->vlan_tci_outer = vlan_tci_outer;
pkt->l2_len = sizeof(struct rte_ether_hdr);
- pkt->l3_len = sizeof(struct rte_ipv4_hdr);
pkt_len = pkt->data_len;
pkt_seg = pkt;
@@ -204,6 +211,24 @@ pkt_burst_prepare(struct rte_mbuf *pkt, struct rte_mempool *mbp,
pkt_len += pkt_seg->data_len;
}
pkt_seg->next = NULL; /* Last segment of packet. */
+
+ /*
+ * A runt frame may be too short to carry a full IPv4/UDP header.
+ * Clamp l3_len and drop any checksum offload whose header is not
+ * fully present, so the PMD is never asked to checksum bytes that
+ * are not in the frame. pkt_len is at least sizeof(rte_ether_hdr),
+ * so the subtraction below cannot underflow.
+ */
+ pkt->l3_len = RTE_MIN(sizeof(struct rte_ipv4_hdr),
+ pkt_len - sizeof(struct rte_ether_hdr));
+ if (pkt_len < sizeof(struct rte_ether_hdr) +
+ sizeof(struct rte_ipv4_hdr))
+ pkt->ol_flags &= ~(RTE_MBUF_F_TX_IP_CKSUM |
+ RTE_MBUF_F_TX_L4_MASK);
+ else if (pkt_len < sizeof(struct rte_ether_hdr) +
+ sizeof(struct rte_ipv4_hdr) +
+ sizeof(struct rte_udp_hdr))
+ pkt->ol_flags &= ~RTE_MBUF_F_TX_L4_MASK;
/*
* Copy headers in first packet segment(s).
*/
@@ -405,7 +430,13 @@ tx_only_begin(portid_t pi)
pkt_hdr_len = (uint16_t)(sizeof(struct rte_ether_hdr) +
sizeof(struct rte_ipv4_hdr) +
sizeof(struct rte_udp_hdr));
- pkt_data_len = tx_pkt_length - pkt_hdr_len;
+ /*
+ * tx_pkt_length may be smaller than the full header stack when
+ * generating runt frames; clamp the payload length to zero in that
+ * case so the IP/UDP length fields stay sane.
+ */
+ pkt_data_len = tx_pkt_length > pkt_hdr_len ?
+ tx_pkt_length - pkt_hdr_len : 0;
if ((tx_pkt_split == TX_PKT_SPLIT_RND || txonly_multi_flow) &&
tx_pkt_seg_lengths[0] < pkt_hdr_len) {
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index f0f2b0758b..d2e5b63586 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -876,6 +876,19 @@ Set the length of each segment of the TX-ONLY packets or length of packet for FL
Where x[,y]* represents a CSV list of values, without white space.
+The total packet length may be set as small as the Ethernet header
+(``sizeof(struct rte_ether_hdr)``), which is below the size of an empty
+UDP/IPv4 packet. This generates runt frames with a truncated (or absent)
+IPv4/UDP header, which is useful for testing how a driver handles
+undersized frames. Any header bytes that do not fit in the requested
+length are simply not emitted. Checksum offloads are automatically
+dropped for a frame too short to contain the corresponding header.
+
+Note that random split (``set txsplit rand``) and multi-flow
+(``set txonly-flows``) still require the first segment to hold the full
+Ethernet/IPv4/UDP header stack, so they cannot be combined with runt
+lengths.
+
set txtimes
~~~~~~~~~~~
--
2.53.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox