* Re: [PATCH] net/af_packet: fix qpairs argument upper bound check
From: Stephen Hemminger @ 2026-06-03 15:27 UTC (permalink / raw)
To: Denis Sergeev; +Cc: dev, sdl.dpdk
In-Reply-To: <20260603044228.117357-1-denserg.edu@gmail.com>
On Wed, 3 Jun 2026 07:42:18 +0300
Denis Sergeev <denserg.edu@gmail.com> wrote:
> diff --git a/drivers/net/af_packet/rte_eth_af_packet.c b/drivers/net/af_packet/rte_eth_af_packet.c
> index 0ee94e71ea..ebf015dd9a 100644
> --- a/drivers/net/af_packet/rte_eth_af_packet.c
> +++ b/drivers/net/af_packet/rte_eth_af_packet.c
> @@ -1169,7 +1169,7 @@ rte_eth_from_packet(struct rte_vdev_device *dev,
> pair = &kvlist->pairs[k_idx];
> if (strstr(pair->key, ETH_AF_PACKET_NUM_Q_ARG) != NULL) {
> qpairs = atoi(pair->value);
> - if (qpairs < 1) {
> + if (qpairs < 1 || qpairs > RTE_MAX_QUEUES_PER_PORT) {
> PMD_LOG(ERR,
> "%s: invalid qpairs value",
> name);
> --
I would rather see atoi() not used in DPDK, it accepts too much and does not do
enough validation. Replace with strtoul() instead.
^ permalink raw reply
* Re: [PATCH v7] mempool: improve cache behaviour and performance
From: Thomas Monjalon @ 2026-06-03 15:44 UTC (permalink / raw)
To: Andrew Rybchenko, Bruce Richardson, Hemant Agrawal,
Morten Brørup, Konstantin Ananyev, David Marchand,
Robin Jarry, Jerin Jacob
Cc: dev, Jingjing Wu, Praveen Shetty, Sachin Saxena
In-Reply-To: <20260601164007.252063-1-mb@smartsharesystems.com>
01/06/2026 18:40, Morten Brørup:
> This patch refactors the mempool cache to eliminate some unexpected
> behaviour and reduce the mempool cache miss rate.
I feel we need more opinions about this behaviour change.
Bruce was suggesting some user-tuning. What do you think?
Also the decision may be easier if we have some performance benchmarks.
Who could help to show some numbers before/after in various cases please?
^ permalink raw reply
* Re: [PATCH] test/latency: fix intermittent failure on slow platforms
From: Thomas Monjalon @ 2026-06-03 15:37 UTC (permalink / raw)
To: Stephen Hemminger
Cc: dev, stable, Reshma Pattan, Bruce Richardson, Luca Boccassi
In-Reply-To: <CAMw=ZnRB+wv7ZN6c5YkF=LfTB328uYcBmf=xCqjTU8hSjzuVZQ@mail.gmail.com>
01/06/2026 12:23, Luca Boccassi:
> On Sun, 31 May 2026 at 19:01, Stephen Hemminger
> <stephen@networkplumber.org> wrote:
> >
> > The forwarding loop was bounded by a fixed interval of 0.5ms
> > but on slow or emulated platforms with a low-frequency timebase
> > (e.g. RISC-V rdtime) this fails because the loop only ran once.
> > The test needs two iterations to get any samples.
> >
> > Rearrange the forwarding loop so that a minimum number of iterations
> > are required. The loop still has an upper bound on packets and time
> > interval which is expanded to 10 ms.
> >
> > If no samples are collected, mark the test as skipped.
> > Refactor the forwarding loop test so that cleanup happens on
> > failure.
> >
> > Reported-by: Luca Boccassi <bluca@debian.org>
> > Fixes: b34508b9cbcd ("test/latency: update with more checks")
> > Cc: stable@dpdk.org
> >
> > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> > ---
> > app/test/test_latencystats.c | 75 ++++++++++++++++++++++--------------
> > 1 file changed, 46 insertions(+), 29 deletions(-)
>
> Thanks, this has been failing consistently in riscv64 since at least
> 25.11, hopefully this makes it stable.
>
> Acked-by: Luca Boccassi <luca.boccassi@gmail.com>
Applied, thanks.
^ permalink raw reply
* RE: [EXTERNAL] Re: [PATCH v5 1/1] net/mana: add device reset support
From: Wei Hu @ 2026-06-03 15:27 UTC (permalink / raw)
To: Stephen Hemminger, Wei Hu; +Cc: dev@dpdk.org, Long Li
In-Reply-To: <20260601095802.36cec727@phoenix.local>
Thanks for the review on v5, Stephen.
> -----Original Message-----
> From: Stephen Hemminger <stephen@networkplumber.org>
> Sent: Tuesday, June 2, 2026 12:58 AM
> To: Wei Hu <weh@linux.microsoft.com>
> Cc: dev@dpdk.org; Long Li <longli@microsoft.com>; Wei Hu
> <weh@microsoft.com>
> Subject: [EXTERNAL] Re: [PATCH v5 1/1] net/mana: add device reset support
>
> The RCU use is not really RCU. thread_online/offline are called on every rx/tx
> burst, and the "thread" token is the queue index, not a thread. So it is a per-
> queue in-use flag paid for on the hottest path, plus a new library dependency,
> to express "wait until no queue is mid-burst" -- which the driver already half
> does by swapping the burst function to mana_*_burst_removed and checking
> dev_state. Please drop the rcu use. If you must drain readers, a per-queue
> atomic flag is lighter and local; the fast path already has the dev_state acquire-
> load it needs.
>
I have tested just swapping to mana_*_burst_removed doesn't stop
the application from entering the burst functions. I will add per-queue atomic
flags and spin poll all queue flags in the slower reset path. I think the actual
fast path cost is nearly identical. However, it does remove the rcu library
dependency.
> The data path only needs the atomic, and that part is fine. The lock is
> legitimate for serializing the teardown/rebuild against control ops, but the way
> it is used is the problem: it is acquired in mana_intr_handler, released in
> mana_reset_enter, re-acquired in mana_reset_thread, and released in
> mana_reset_exit_delay. That cross-function, cross-thread handoff is exactly
> why every function needs __rte_no_thread_safety_analysis.
> Acquire and release the lock in the same function and the annotations all go
> away. Turning off thread-safety analysis needs strong justification and this
> does not have it.
I will remove the __rte_no_thread_safety_analysis from the code. It was added
when I used spin lock and it caused clang build warnings. Now I have
changed it to pthread mutex and clang build is clean without this.
> - thread_online is taken at the top of the burst functions but
> thread_offline is only on some return paths. Any early return that
> misses it leaves a token non-quiescent and rte_rcu_qsbr_check() in
> mana_reset_enter spins forever. This is the kind of breakage the per-burst
> bracketing invites -- another reason to drop it.
>
I have checked mana_rx_burst and mana_tx_burst. There's no actual bug
now -- every return path has thread-offline. Changing rcu to per-queue flags
would still need to reset the flag in every return path. I agree it is kind of
fragile. However, the reset path needs it to make sure there is no thread still
in the fast path before it can start to tear down the resources.
I will send out a new revision.
Thanks,
Wei
^ permalink raw reply
* Re: [PATCH] eal: fix function versioning with LTO
From: Stephen Hemminger @ 2026-06-03 15:24 UTC (permalink / raw)
To: David Marchand; +Cc: dev, stable, Thomas Monjalon
In-Reply-To: <CAJFAV8w+bUJGTBSOgqp8xOHXm5av2xdFMo8TNwr=kP87R30AYg@mail.gmail.com>
On Wed, 3 Jun 2026 12:01:48 +0200
David Marchand <david.marchand@redhat.com> wrote:
> Hello,
>
> On Wed, 3 Jun 2026 at 00:57, Stephen Hemminger
> <stephen@networkplumber.org> wrote:
> >
> > When using function versioning and building with Link Time Optimization,
> > the compiler does not see the __asm__ annotation of symbols and
> > therefore thinks there are two versions of the same symbol.
> >
> > The fix is to use compiler symver attribute on the function which
> > was added in GCC 10. Keep the older method for backward compatibility
> > with older compilers.
> >
> > Bugzilla ID: 1949
> > Fixes: e30e194c4d06 ("eal: rework function versioning macros")
>
> We never used the symver stuff, so it seems unlikely the issue was
> introduced with this rework.
>
> The fact that clang does not support this attribute is a concern.
>
>
> > Cc: stable@dpdk.org
>
> Why do we need to backport?
>
> LTO is kind of experimental, so it seems good enough to reply "not
> expected to work in older LTS" if someone reported an issue.
>
> And in practice, no LTS release call the versioning macros, since a
> LTS drops all compatibility.
>
> > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
>
> I would like to reproduce, but I can't build main with LTO.
> What patches did you apply locally to avoid warnings on the hash library?
I get no warnings from current main with GCC 15
I was doing test build of net-next with this patch:
https://patchwork.dpdk.org/project/dpdk/patch/20260529000748.275863-1-stephen@networkplumber.org/
The LTO build is done by:
$ meson setup build-lto -Db_lto=true
The result was:
cc -o lib/librte_ethdev.so.26.2 lib/librte_ethdev.so.26.2.p/ethdev_ethdev_driver.c.o lib/librte_ethdev.so.26.2.p/ethdev_ethdev_private.c.o lib/librte_ethdev.so.26.2.p/ethdev_ethdev_profile.c.o lib/librte_ethdev.so.26.2.p/ethdev_ethdev_trace_points.c.o lib/librte_ethdev.so.26.2.p/ethdev_rte_class_eth.c.o lib/librte_ethdev.so.26.2.p/ethdev_rte_ethdev.c.o lib/librte_ethdev.so.26.2.p/ethdev_rte_ethdev_cman.c.o lib/librte_ethdev.so.26.2.p/ethdev_rte_ethdev_telemetry.c.o lib/librte_ethdev.so.26.2.p/ethdev_rte_flow.c.o lib/librte_ethdev.so.26.2.p/ethdev_rte_mtr.c.o lib/librte_ethdev.so.26.2.p/ethdev_rte_tm.c.o lib/librte_ethdev.so.26.2.p/ethdev_sff_telemetry.c.o lib/librte_ethdev.so.26.2.p/ethdev_sff_common.c.o lib/librte_ethdev.so.26.2.p/ethdev_sff_8079.c.o lib/librte_ethdev.so.26.2.p/ethdev_sff_8472.c.o lib/librte_ethdev.so.26.2.p/ethdev_sff_8636.c.o lib/librte_ethdev.so.26.2.p/ethdev_ethdev_linux_ethtool.c.o -flto=auto -Wl,--as-needed -Wl,--no-undefined -Wl,-O1 -shared -fPIC -Wl,-soname,librte_ethdev.so.26 -Wl,--no-as-needed -Wl,--undefined-version -pthread -Wl,--start-group -lm -ldl -lnuma -lfdt '-Wl,-rpath,$ORIGIN/' lib/librte_eal.so.26.2 lib/librte_kvargs.so.26.2 lib/librte_log.so.26.2 lib/librte_telemetry.so.26.2 lib/librte_argparse.so.26.2 lib/librte_net.so.26.2 lib/librte_mbuf.so.26.2 lib/librte_mempool.so.26.2 lib/librte_ring.so.26.2 lib/librte_meter.so.26.2 -Wl,--version-script=/home/shemminger/DPDK/lto/build-lto/lib/ethdev_exports.map /usr/lib/x86_64-linux-gnu/libbsd.so /usr/lib/x86_64-linux-gnu/libarchive.so -Wl,--end-group
/tmp/cc3RQyqL.s: Assembler messages:
/tmp
Fed the result into Claude, and it said "yeah, I see the same problem on
other projects, the answer is ...". With a little searching found an example
in Gentoo https://github.com/InBetweenNames/gentooLTO/pull/458
With this change symbol versioning with LTO works on both GCC >= 10 and Clang.
Clang LTO doesn't have the attribute, but it also doesn't have the same LTO issue.
^ permalink raw reply
* Re: [PATCH v2] mempool: introduce statistics reset function
From: Thomas Monjalon @ 2026-06-03 15:14 UTC (permalink / raw)
To: Morten Brørup; +Cc: Stephen Hemminger, dev, Andrew Rybchenko
In-Reply-To: <b2fa41c0-aed1-420f-ad89-775fe0024dce@oktetlabs.ru>
24/02/2026 10:57, Andrew Rybchenko:
> On 2/24/26 12:28 PM, Morten Brørup wrote:
> > Populating a mempool with objects is accounted for in the statistics.
> > When analyzing mempool cache statistics, this may distort the data.
> > In order to simplify mempool cache statistics analysis, a mempool
> > statistics reset function was added.
> >
> > Furthermore, details about average burst sizes and mempool cache miss
> > rates were added to the statistics shown when dumping a mempool.
> >
> > Signed-off-by: Morten Brørup <mb@smartsharesystems.com>
>
> Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Applied with version changed to 26.07, thanks.
^ permalink raw reply
* [PATCH 2/2] net/i40e: fix blocking link wait on device start
From: Ciara Loftus @ 2026-06-03 14:34 UTC (permalink / raw)
To: dev; +Cc: Ciara Loftus, stable
In-Reply-To: <20260603143407.1108527-1-ciara.loftus@intel.com>
Currently, device start performs a synchronous link status update,
blocking for up to one second if the link is not yet up. This causes
unnecessary startup delay in scenarios where the link partner is slow to
come up or unavailable.
The wait was introduced alongside the maximum frame size MAC config
command. Some devices require the link to be up before issuing that
command, so the solution was to block at device start until link was
established.
To address the issue, remove the unconditional blocking wait. Take note
if the link was down at the time of the MAC config command during device
start and if it was, re-issue the command upon notification of the first
link-up event.
In the case where all interrupt vectors are consumed by Rx queues, no
interrupt or alarm handler is available to process link-up events. The
blocking wait is retained for this narrow case to preserve correctness.
Fixes: 82fcf20d039c ("net/i40e: fix maximum frame size configuration")
Cc: stable@dpdk.org
Signed-off-by: Ciara Loftus <ciara.loftus@intel.com>
---
drivers/net/intel/i40e/i40e_ethdev.c | 25 +++++++++++++++++++++----
drivers/net/intel/i40e/i40e_ethdev.h | 2 ++
2 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/drivers/net/intel/i40e/i40e_ethdev.c b/drivers/net/intel/i40e/i40e_ethdev.c
index e818b6fc7c..a7c00033e5 100644
--- a/drivers/net/intel/i40e/i40e_ethdev.c
+++ b/drivers/net/intel/i40e/i40e_ethdev.c
@@ -2565,15 +2565,19 @@ i40e_dev_start(struct rte_eth_dev *dev)
I40E_AQ_EVENT_MEDIA_NA), NULL);
if (ret != I40E_SUCCESS)
PMD_DRV_LOG(WARNING, "Fail to set phy mask");
-
- /* Call get_link_info aq command to enable/disable LSE */
- i40e_dev_link_update(dev, 1);
}
if (dev->data->dev_conf.intr_conf.rxq == 0) {
+ i40e_dev_link_update(dev, 0);
+ pf->mac_config_on_link_up = !dev->data->dev_link.link_status;
rte_eal_alarm_set(I40E_ALARM_INTERVAL,
i40e_dev_alarm_handler, dev);
} else {
+ /* Block if no interrupt handler can process link-up events, to help
+ * ensure that MAC config is applied when the link is up.
+ */
+ i40e_dev_link_update(dev, !rte_intr_allow_others(intr_handle));
+ pf->mac_config_on_link_up = !dev->data->dev_link.link_status;
/* enable uio intr after callback register */
rte_intr_enable(intr_handle);
}
@@ -6867,6 +6871,7 @@ static void
i40e_dev_handle_aq_msg(struct rte_eth_dev *dev)
{
struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
struct i40e_arq_event_info info;
uint16_t pending, opcode;
uint8_t msg_buf[I40E_AQ_BUF_SZ] = {0};
@@ -6899,9 +6904,21 @@ i40e_dev_handle_aq_msg(struct rte_eth_dev *dev)
break;
case i40e_aqc_opc_get_link_status:
ret = i40e_dev_link_update(dev, 0);
- if (!ret)
+ /* Some devices require MAC config to be applied when the link comes up. */
+ if (!ret) {
+ if (pf->mac_config_on_link_up && dev->data->dev_link.link_status) {
+ uint16_t max_frame_size;
+
+ max_frame_size = dev->data->mtu ?
+ dev->data->mtu + I40E_ETH_OVERHEAD :
+ I40E_FRAME_SIZE_MAX;
+ i40e_aq_set_mac_config(hw, max_frame_size, TRUE,
+ false, 0, NULL);
+ pf->mac_config_on_link_up = false;
+ }
rte_eth_dev_callback_process(dev,
RTE_ETH_EVENT_INTR_LSC, NULL);
+ }
break;
default:
PMD_DRV_LOG(DEBUG, "Request %u is not supported yet",
diff --git a/drivers/net/intel/i40e/i40e_ethdev.h b/drivers/net/intel/i40e/i40e_ethdev.h
index d57c53f661..7524defdb7 100644
--- a/drivers/net/intel/i40e/i40e_ethdev.h
+++ b/drivers/net/intel/i40e/i40e_ethdev.h
@@ -1191,6 +1191,8 @@ struct i40e_pf {
/* When firmware > 8.3, the enable flag for outer VLAN processing */
bool fw8_3gt;
+ /* MAC config needs re-applying when link first comes up */
+ bool mac_config_on_link_up;
struct i40e_vf_msg_cfg vf_msg_cfg;
uint64_t prev_rx_bytes;
--
2.43.0
^ permalink raw reply related
* [PATCH 1/2] net/ice: revert fix link up when starting device
From: Ciara Loftus @ 2026-06-03 14:34 UTC (permalink / raw)
To: dev; +Cc: Ciara Loftus
In-Reply-To: <20260603143407.1108527-1-ciara.loftus@intel.com>
This reverts commit 6c76b76dc64183eb2f24a52b90d4ff9feb4872f4.
The reverted commit worked around a potential timing issue where the
link could be reported down immediately after the link was enabled
during device start. The commit introduced a blocking wait which gave
the driver a better chance to read the correct link state before
returning from device start. However, since the auto link update flag is
set when setting the link up in device start, an adminq notification
should arrive once the link is up, which will be handled and correctly
set the link status. This means we can remove the delay from device
start as it does not need to guarantee link up before returning.
Signed-off-by: Ciara Loftus <ciara.loftus@intel.com>
---
drivers/net/intel/ice/ice_ethdev.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/intel/ice/ice_ethdev.c b/drivers/net/intel/ice/ice_ethdev.c
index d2734b6688..da570d03cb 100644
--- a/drivers/net/intel/ice/ice_ethdev.c
+++ b/drivers/net/intel/ice/ice_ethdev.c
@@ -4464,7 +4464,7 @@ ice_dev_start(struct rte_eth_dev *dev)
ice_dev_set_link_up(dev);
/* Call get_link_info aq command to enable/disable LSE */
- ice_link_update(dev, 1);
+ ice_link_update(dev, 0);
pf->adapter_stopped = false;
--
2.43.0
^ permalink raw reply related
* [PATCH 0/2] net/intel: fix blocking link wait on device start
From: Ciara Loftus @ 2026-06-03 14:34 UTC (permalink / raw)
To: dev; +Cc: Ciara Loftus
Device start in both ice and i40e has historically blocked for up to
two seconds waiting for link to come up before returning. This causes
noticeable startup delay when a link partner is slow to come up or
absent entirely. This series reverts the wait in ice, and removes the
wait in i40e while ensuring that the MAC config is applied when the
link is up which is a requirement for some devices.
Ciara Loftus (2):
net/ice: revert fix link up when starting device
net/i40e: fix blocking link wait on device start
drivers/net/intel/i40e/i40e_ethdev.c | 25 +++++++++++++++++++++----
drivers/net/intel/i40e/i40e_ethdev.h | 2 ++
drivers/net/intel/ice/ice_ethdev.c | 2 +-
3 files changed, 24 insertions(+), 5 deletions(-)
--
2.43.0
^ permalink raw reply
* RE: [PATCH v4 1/2] net/intel: write mbuf for last Tx desc of segment
From: Loftus, Ciara @ 2026-06-03 14:21 UTC (permalink / raw)
To: Richardson, Bruce, dev@dpdk.org; +Cc: mb@smartsharesystems.com
In-Reply-To: <20260602154513.1079865-2-bruce.richardson@intel.com>
> Subject: [PATCH v4 1/2] net/intel: write mbuf for last Tx desc of segment
>
> When a single mbuf segment has more data than can be handled by a single
> Tx data descriptor in the TSO case, adjust how the storing of mbufs is
> being done. Rather than putting the mbuf pointer in the first slot for
> that segment, store it in the last slot instead. This guarantees for us
> that the descriptor for which we have desc-done (DD) writeback always
> has a valid mbuf associated with it.
>
> Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
The fix looks good to me.
Acked-by: Ciara Loftus <ciara.loftus@intel.com>
> ---
> drivers/net/intel/common/tx_scalar.h | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/intel/common/tx_scalar.h
> b/drivers/net/intel/common/tx_scalar.h
> index 9fcd2e4733..7809bd53e8 100644
> --- a/drivers/net/intel/common/tx_scalar.h
> +++ b/drivers/net/intel/common/tx_scalar.h
> @@ -509,7 +509,6 @@ ci_xmit_pkts(struct ci_tx_queue *txq,
>
> if (txe->mbuf)
> rte_pktmbuf_free_seg(txe->mbuf);
> - txe->mbuf = m_seg;
>
> /* Setup TX Descriptor */
> /* Calculate segment length, using IPsec callback if
> provided */
> @@ -528,6 +527,7 @@ ci_xmit_pkts(struct ci_tx_queue *txq,
> ((uint64_t)CI_MAX_DATA_PER_TXD
> << CI_TXD_QW1_TX_BUF_SZ_S) |
> ((uint64_t)td_tag <<
> CI_TXD_QW1_L2TAG1_S);
> write_txd(txd, buf_dma_addr,
> cmd_type_offset_bsz);
> + txe->mbuf = NULL;
>
> buf_dma_addr += CI_MAX_DATA_PER_TXD;
> slen -= CI_MAX_DATA_PER_TXD;
> @@ -548,6 +548,7 @@ ci_xmit_pkts(struct ci_tx_queue *txq,
> ((uint64_t)slen <<
> CI_TXD_QW1_TX_BUF_SZ_S) |
> ((uint64_t)td_tag <<
> CI_TXD_QW1_L2TAG1_S);
> write_txd(txd, buf_dma_addr, cmd_type_offset_bsz);
> + txe->mbuf = m_seg;
>
> tx_id = txe->next_id;
> txe = txn;
> --
> 2.53.0
^ permalink raw reply
* [PATCH] doc: using container to build and run applications
From: Andrea Panattoni @ 2026-06-03 14:04 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: dev, Andrea Panattoni
Add explanation about how container runtimes like podman
or docker can be used to build and run DPDK application.
Signed-off-by: Andrea Panattoni <apanatto@redhat.com>
---
.mailmap | 1 +
doc/guides/linux_gsg/build_dpdk.rst | 48 ++++++++++++++++++++++
doc/guides/linux_gsg/build_sample_apps.rst | 32 +++++++++++++++
3 files changed, 81 insertions(+)
diff --git a/.mailmap b/.mailmap
index 89ba6ffccc..48133a4b45 100644
--- a/.mailmap
+++ b/.mailmap
@@ -109,6 +109,7 @@ Andre Muezerie <andremue@linux.microsoft.com> <andremue@microsoft.com>
Andre Richter <andre.o.richter@gmail.com>
Andrea Arcangeli <aarcange@redhat.com>
Andrea Grandi <andrea.grandi@intel.com>
+Andrea Panattoni <apanatto@redhat.com>
Andrew Bailey <abailey@iol.unh.edu>
Andrew Boyer <andrew.boyer@amd.com> <aboyer@pensando.io>
Andrew Harvey <agh@cisco.com>
diff --git a/doc/guides/linux_gsg/build_dpdk.rst b/doc/guides/linux_gsg/build_dpdk.rst
index ed30e4a5f1..cfd10c0310 100644
--- a/doc/guides/linux_gsg/build_dpdk.rst
+++ b/doc/guides/linux_gsg/build_dpdk.rst
@@ -337,3 +337,51 @@ build system is shown below:
dpdk = dependency('libdpdk')
sources = files('main.c')
executable('dpdk-app', sources, dependencies: dpdk)
+
+
+.. _building_dpdk_in_container:
+
+Building Applications in a Container
+------------------------------------
+
+DPDK can be built inside a container to provide a reproducible build environment.
+The following example uses Podman with a Fedora-based Containerfile.
+
+.. note::
+
+ These instructions also work with Docker by replacing ``podman`` with ``docker``.
+
+Create a ``Containerfile`` in the top-level DPDK source directory:
+
+.. code-block:: none
+
+ FROM fedora:latest
+
+ RUN dnf -y upgrade && dnf -y install \
+ libbsd-devel \
+ numactl-devel \
+ meson \
+ ninja-build \
+ python3-pyelftools \
+ && dnf group install -y development-tools \
+ && dnf clean all
+
+ COPY ./ /dpdk
+ WORKDIR /dpdk
+
+ RUN meson setup build -Dexamples=helloworld && ninja -C build install
+
+Build the container image from the DPDK source directory:
+
+.. code-block:: console
+
+ podman build -t dpdk-builder -f Containerfile .
+
+Once the build completes, verify that the helloworld example runs:
+
+.. code-block:: console
+
+ podman run --rm dpdk-builder /dpdk/build/examples/dpdk-helloworld
+
+See :ref:`running_sample_app_in_container` for how to run DPDK applications
+from this container image.
diff --git a/doc/guides/linux_gsg/build_sample_apps.rst b/doc/guides/linux_gsg/build_sample_apps.rst
index 5195af67ad..7154f64723 100644
--- a/doc/guides/linux_gsg/build_sample_apps.rst
+++ b/doc/guides/linux_gsg/build_sample_apps.rst
@@ -125,3 +125,35 @@ Additional sample applications are included in the DPDK examples directory.
These sample applications may be built and run in a manner similar to that described in earlier sections in this manual.
In addition, see the *DPDK Sample Applications User Guide* for a description of the application,
specific instructions on compilation and execution and some explanation of the code.
+
+
+.. _running_sample_app_in_container:
+
+Running Sample Application in a Container
+-----------------------------------------
+
+A DPDK application can be run inside a container using the image built
+in :ref:`building_dpdk_in_container`.
+
+.. warning::
+
+ Hugepages must be configured on the host before running a DPDK application
+ in a container.
+ Refer to :ref:`linux_gsg_hugepages` for setup instructions.
+
+The following example runs testpmd in interactive mode with no physical NICs:
+
+.. code-block:: console
+
+ podman run -it --privileged \
+ -v /dev/hugepages:/dev/hugepages \
+ dpdk-builder \
+ ./build/app/dpdk-testpmd --no-pci -- -i
+
+.. note::
+
+ The ``--privileged`` flag grants access to hugepages and hardware resources.
+ For production deployments, consider using more fine-grained capabilities
+ and device access instead.
+
+ These instructions also work with Docker by replacing ``podman`` with ``docker``.
--
2.54.0
^ permalink raw reply related
* Re: [PATCH v6 03/27] net/intel/common: add common flow action parsing
From: Bruce Richardson @ 2026-06-03 13:03 UTC (permalink / raw)
To: Anatoly Burakov; +Cc: dev
In-Reply-To: <6834ddc6a6bc96b18f0078c2b99a58114bda54e7.1780068633.git.anatoly.burakov@intel.com>
On Fri, May 29, 2026 at 04:36:05PM +0100, Anatoly Burakov wrote:
> Currently, each driver has their own code for action parsing, which results
> in a lot of duplication and subtle mismatches in behavior between drivers.
>
> Add common infrastructure, based on the following assumptions:
>
> - All drivers support at most 32 actions at once, but usually far less
> - Not every action is supported by all drivers
> - We can check a few common things to filter out obviously wrong actions
> - Driver performs semantic checks on all valid actions
>
> So, the intention is to reject everything we can reasonably reject at the
> outset without knowing anything about the drivers, parametrize what is
> trivial to parametrize, and leave the rest for the driver to implement.
>
> While we're at it, also add logging infrastructure for Intel common code,
> using the new component name defines that are automatically passed to each
> DPDK driver as it is being built.
>
> Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
> ---
> drivers/net/intel/common/flow_check.h | 279 ++++++++++++++++++++++++++
> drivers/net/intel/common/log.h | 40 ++++
> 2 files changed, 319 insertions(+)
> create mode 100644 drivers/net/intel/common/flow_check.h
> create mode 100644 drivers/net/intel/common/log.h
>
<snip>
> +/**
> + * Validate and parse a list of rte_flow_action into a parsed action list.
> + *
> + * @param actions pointer to array of rte_flow_action, terminated by RTE_FLOW_ACTION_TYPE_END
> + * @param param pointer to ci_flow_actions_check_param structure (can be NULL)
> + * @param parsed_actions pointer to ci_flow_actions structure to store parsed actions
> + * @param error pointer to rte_flow_error structure for error reporting
> + *
> + * @return 0 on success, negative errno on failure.
> + */
> +static inline int
> +ci_flow_check_actions(const struct rte_flow_action *actions,
> + const struct ci_flow_actions_check_param *param,
> + struct ci_flow_actions *parsed_actions,
> + struct rte_flow_error *error)
> +{
> + size_t i = 0;
> + int ret;
> +
> + if (actions == NULL) {
> + return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
> + NULL, "Missing actions");
> + }
> +
> + /* reset the list */
> + *parsed_actions = (struct ci_flow_actions){0};
> +
> + while (actions[i].type != RTE_FLOW_ACTION_TYPE_END) {
> + const struct rte_flow_action *action = &actions[i++];
> +
> + /* skip VOID actions */
> + if (action->type == RTE_FLOW_ACTION_TYPE_VOID)
> + continue;
> +
> + /* generic validation for actions - this will check against param as well */
> + ret = __flow_action_check_generic(action, param, error);
> + if (ret < 0)
> + return ret;
> +
> + /* check against global maximum number of actions */
> + if (parsed_actions->count >= RTE_DIM(parsed_actions->actions)) {
> + return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
> + action, "Too many actions");
> + }
> + /* user may have specified a maximum number of actions */
> + if (param != NULL && param->max_actions != 0 &&
> + parsed_actions->count >= param->max_actions) {
> + return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
> + action, "Too many actions");
> + }
> + /* add action to the list */
> + CI_DRV_LOG(DEBUG, "Parsed action %u: type=%s", parsed_actions->count,
> + ci_flow_action_type_to_str(action->type));
> + parsed_actions->actions[parsed_actions->count++] = action;
> + }
> +
> + /* now, call into user validation if specified */
> + if (param != NULL && param->check != NULL) {
> + ret = param->check(parsed_actions, param, error);
> + if (ret < 0)
> + return ret;
> + }
Running an AI review on this code myself, it highlights the fact that we
are missing a check for an empty parsed_actions array here, and not all
check handlers verify the length as being >0 before dereferencing. For
example, in patch 10, the callbacks don't explicitly check for empty lists
I think it would be reasonable to have the return -EINVAL before this
callback check, right?
> + /* if we didn't parse anything, valid action list is empty */
> + return parsed_actions->count == 0 ? -EINVAL : 0;
> +}
> +
> +#ifdef __cplusplus
> +}
> +#endif
<snip>
^ permalink raw reply
* ARM v8 rte_power_pause
From: Morten Brørup @ 2026-06-03 11:56 UTC (permalink / raw)
To: Wathsala Vithanage, Hemant Agrawal, Sachin Saxena; +Cc: dev, Maxime Leroy
Hi Wathsala, Hemant and Sachin,
Over at the Grout project, we are discussing power management in the context of 100 Gbit/s latency deadlines [1].
rte_power_pause() is not implemented for ARM v8 / Cortex-A72.
Syscalls such as nanosleep() have too much overhead, and cannot be used.
Any suggestions for a power-reducing method to make a CPU core "sleep" (i.e. do nothing) for durations in the order of 1 microsecond?
[1]: https://github.com/DPDK/grout/pull/624#issuecomment-4602036364
-Morten
^ permalink raw reply
* Re: [PATCH] eal: fix function versioning with LTO
From: David Marchand @ 2026-06-03 10:01 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: dev, stable, Thomas Monjalon
In-Reply-To: <20260602225722.950617-1-stephen@networkplumber.org>
Hello,
On Wed, 3 Jun 2026 at 00:57, Stephen Hemminger
<stephen@networkplumber.org> wrote:
>
> When using function versioning and building with Link Time Optimization,
> the compiler does not see the __asm__ annotation of symbols and
> therefore thinks there are two versions of the same symbol.
>
> The fix is to use compiler symver attribute on the function which
> was added in GCC 10. Keep the older method for backward compatibility
> with older compilers.
>
> Bugzilla ID: 1949
> Fixes: e30e194c4d06 ("eal: rework function versioning macros")
We never used the symver stuff, so it seems unlikely the issue was
introduced with this rework.
The fact that clang does not support this attribute is a concern.
> Cc: stable@dpdk.org
Why do we need to backport?
LTO is kind of experimental, so it seems good enough to reply "not
expected to work in older LTS" if someone reported an issue.
And in practice, no LTS release call the versioning macros, since a
LTS drops all compatibility.
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
I would like to reproduce, but I can't build main with LTO.
What patches did you apply locally to avoid warnings on the hash library?
--
David Marchand
^ permalink raw reply
* [PATCH v4] ethdev: support inline calculating masked item value
From: Bing Zhao @ 2026-06-03 9:28 UTC (permalink / raw)
To: viacheslavo, dev, rasland, stephen
Cc: orika, dsosnowski, suanmingm, matan, thomas
In-Reply-To: <20260603081941.9049-1-bingz@nvidia.com>
In the asynchronous API definition and some drivers, the
rte_flow_item spec value may not be calculated by the driver due to the
reason of speed of light rule insertion rate and sometimes the input
parameters will be copied and changed internally.
After copying, the spec and last will be protected by the keyword
const and cannot be changed in the code itself. And also the driver
needs some extra memory to do the calculation and extra conditions
to understand the length of each item spec. This is not efficient.
To solve the issue and support usage of the following fix, a new OP
was introduced to calculate the spec and last values after applying
the mask inline.
Signed-off-by: Bing Zhao <bingz@nvidia.com>
---
v3:
- add test code
- fix the issue found by AI
v4: reabse on top of the main
---
app/test/test_ethdev_api.c | 76 ++++++++++++++++++++++++++
doc/guides/rel_notes/release_26_07.rst | 6 ++
lib/ethdev/rte_flow.c | 46 ++++++++++++++--
lib/ethdev/rte_flow.h | 13 +++++
4 files changed, 135 insertions(+), 6 deletions(-)
diff --git a/app/test/test_ethdev_api.c b/app/test/test_ethdev_api.c
index 76afd0345c..5cae1cdc1d 100644
--- a/app/test/test_ethdev_api.c
+++ b/app/test/test_ethdev_api.c
@@ -4,6 +4,7 @@
#include <rte_log.h>
#include <rte_ethdev.h>
+#include <rte_flow.h>
#include <rte_test.h>
#include "test.h"
@@ -15,6 +16,80 @@
#define NUM_MBUF 1024
#define MBUF_CACHE_SIZE 256
+static int32_t
+ethdev_api_flow_conv_pattern_masked(void)
+{
+ const struct rte_flow_item_eth spec = {
+ .hdr.dst_addr.addr_bytes = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 },
+ .hdr.src_addr.addr_bytes = { 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ .hdr.ether_type = RTE_BE16(0x1234),
+ };
+ const struct rte_flow_item_eth last = {
+ .hdr.dst_addr.addr_bytes = { 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 },
+ .hdr.src_addr.addr_bytes = { 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+ .hdr.ether_type = RTE_BE16(0x5678),
+ };
+ const struct rte_flow_item_eth mask = {
+ .hdr.dst_addr.addr_bytes = { 0xff, 0xff, 0x00, 0x00, 0xff, 0xff },
+ .hdr.src_addr.addr_bytes = { 0xff, 0x00, 0xff, 0x00, 0xff, 0x00 },
+ .hdr.ether_type = RTE_BE16(0xffff),
+ };
+ const struct rte_flow_item pattern[] = {
+ {
+ .type = RTE_FLOW_ITEM_TYPE_ETH,
+ .spec = &spec,
+ .last = &last,
+ .mask = &mask,
+ },
+ { .type = RTE_FLOW_ITEM_TYPE_END },
+ };
+ union {
+ struct rte_flow_item item;
+ struct rte_flow_item_eth eth;
+ double align;
+ uint8_t raw[256];
+ } dst;
+ const struct rte_flow_item *item;
+ const struct rte_flow_item_eth *conv_spec;
+ const struct rte_flow_item_eth *conv_last;
+ int ret;
+
+ ret = rte_flow_conv(RTE_FLOW_CONV_OP_PATTERN_MASKED, NULL, 0, pattern, NULL);
+ TEST_ASSERT(ret > 0, "Masked pattern conversion size query failed");
+ TEST_ASSERT((size_t)ret <= sizeof(dst.raw),
+ "Masked pattern conversion needs too much storage");
+
+ memset(&dst, 0, sizeof(dst));
+ ret = rte_flow_conv(RTE_FLOW_CONV_OP_PATTERN_MASKED, dst.raw,
+ sizeof(dst.raw), pattern, NULL);
+ TEST_ASSERT(ret > 0, "Masked pattern conversion failed");
+
+ item = (const struct rte_flow_item *)dst.raw;
+ conv_spec = item[0].spec;
+ conv_last = item[0].last;
+ TEST_ASSERT_NOT_NULL(conv_spec, "Converted spec must be set");
+ TEST_ASSERT_NOT_NULL(conv_last, "Converted last must be set");
+
+ TEST_ASSERT_EQUAL(conv_spec->hdr.dst_addr.addr_bytes[0], 0x01,
+ "Masked spec dst byte 0 mismatch");
+ TEST_ASSERT_EQUAL(conv_spec->hdr.dst_addr.addr_bytes[2], 0x00,
+ "Masked spec dst byte 2 mismatch");
+ TEST_ASSERT_EQUAL(conv_spec->hdr.src_addr.addr_bytes[1], 0x00,
+ "Masked spec src byte 1 mismatch");
+ TEST_ASSERT_EQUAL(conv_spec->hdr.ether_type, RTE_BE16(0x1234),
+ "Masked spec ether type mismatch");
+ TEST_ASSERT_EQUAL(conv_last->hdr.dst_addr.addr_bytes[0], 0x11,
+ "Masked last dst byte 0 mismatch");
+ TEST_ASSERT_EQUAL(conv_last->hdr.dst_addr.addr_bytes[2], 0x00,
+ "Masked last dst byte 2 mismatch");
+ TEST_ASSERT_EQUAL(conv_last->hdr.src_addr.addr_bytes[1], 0x00,
+ "Masked last src byte 1 mismatch");
+ TEST_ASSERT_EQUAL(conv_last->hdr.ether_type, RTE_BE16(0x5678),
+ "Masked last ether type mismatch");
+
+ return TEST_SUCCESS;
+}
+
static int32_t
ethdev_api_queue_status(void)
{
@@ -167,6 +242,7 @@ static struct unit_test_suite ethdev_api_testsuite = {
.setup = NULL,
.teardown = NULL,
.unit_test_cases = {
+ TEST_CASE(ethdev_api_flow_conv_pattern_masked),
TEST_CASE(ethdev_api_queue_status),
/* TODO: Add deferred_start queue status test */
TEST_CASES_END() /**< NULL terminate unit test array */
diff --git a/doc/guides/rel_notes/release_26_07.rst b/doc/guides/rel_notes/release_26_07.rst
index b8a3e2ced9..5f01420d2b 100644
--- a/doc/guides/rel_notes/release_26_07.rst
+++ b/doc/guides/rel_notes/release_26_07.rst
@@ -134,6 +134,12 @@ API Changes
Also, make sure to start the actual text at the margin.
=======================================================
+* ethdev: Added masked pattern conversion.
+
+ Added ``RTE_FLOW_CONV_OP_PATTERN_MASKED`` to ``rte_flow_conv()``
+ to copy an entire pattern while applying each item's mask to its
+ ``spec`` and ``last`` fields.
+
ABI Changes
-----------
diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
index 7a51b667cf..7cf9f6f6f3 100644
--- a/lib/ethdev/rte_flow.c
+++ b/lib/ethdev/rte_flow.c
@@ -178,6 +178,14 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = {
MK_FLOW_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
};
+static inline size_t
+rte_flow_conv_item_mask_size(const struct rte_flow_item *item)
+{
+ if ((int)item->type >= 0)
+ return rte_flow_desc_item[item->type].size;
+ return sizeof(void *);
+}
+
/** Generate flow_action[] entry. */
#define MK_FLOW_ACTION(t, s) \
[RTE_FLOW_ACTION_TYPE_ ## t] = { \
@@ -835,6 +843,8 @@ rte_flow_conv_action_conf(void *buf, const size_t size,
* RTE_FLOW_ITEM_TYPE_END is encountered.
* @param[out] error
* Perform verbose error reporting if not NULL.
+ * @param[in] with_mask
+ * If true, @p src mask will be applied to spec and last.
*
* @return
* A positive value representing the number of bytes needed to store
@@ -847,12 +857,13 @@ rte_flow_conv_pattern(struct rte_flow_item *dst,
const size_t size,
const struct rte_flow_item *src,
unsigned int num,
+ bool with_mask,
struct rte_flow_error *error)
{
uintptr_t data = (uintptr_t)dst;
size_t off;
size_t ret;
- unsigned int i;
+ unsigned int i, j;
for (i = 0, off = 0; !num || i != num; ++i, ++src, ++dst) {
/**
@@ -876,15 +887,27 @@ rte_flow_conv_pattern(struct rte_flow_item *dst,
src -= num;
dst -= num;
do {
+ uint8_t *c_spec = NULL, *c_last = NULL;
+ const uint8_t *mask = src->mask;
+ size_t item_mask_size = mask ? rte_flow_conv_item_mask_size(src) : 0;
+
if (src->spec) {
off = RTE_ALIGN_CEIL(off, sizeof(double));
ret = rte_flow_conv_item_spec
((void *)(data + off),
size > off ? size - off : 0, src,
RTE_FLOW_CONV_ITEM_SPEC);
- if (size && size >= off + ret)
+ if (size && size >= off + ret) {
dst->spec = (void *)(data + off);
+ c_spec = (uint8_t *)(data + off);
+ }
off += ret;
+ if (with_mask && c_spec && mask) {
+ size_t mask_size = RTE_MIN(ret, item_mask_size);
+
+ for (j = 0; j < mask_size; j++)
+ c_spec[j] &= mask[j];
+ }
}
if (src->last) {
@@ -893,9 +916,17 @@ rte_flow_conv_pattern(struct rte_flow_item *dst,
((void *)(data + off),
size > off ? size - off : 0, src,
RTE_FLOW_CONV_ITEM_LAST);
- if (size && size >= off + ret)
+ if (size && size >= off + ret) {
dst->last = (void *)(data + off);
+ c_last = (uint8_t *)(data + off);
+ }
off += ret;
+ if (with_mask && c_last && mask) {
+ size_t mask_size = RTE_MIN(ret, item_mask_size);
+
+ for (j = 0; j < mask_size; j++)
+ c_last[j] &= mask[j];
+ }
}
if (src->mask) {
off = RTE_ALIGN_CEIL(off, sizeof(double));
@@ -1042,7 +1073,7 @@ rte_flow_conv_rule(struct rte_flow_conv_rule *dst,
off = RTE_ALIGN_CEIL(off, sizeof(double));
ret = rte_flow_conv_pattern((void *)((uintptr_t)dst + off),
size > off ? size - off : 0,
- src->pattern_ro, 0, error);
+ src->pattern_ro, 0, false, error);
if (ret < 0)
return ret;
if (size && size >= off + (size_t)ret)
@@ -1143,7 +1174,7 @@ rte_flow_conv(enum rte_flow_conv_op op,
ret = sizeof(*attr);
break;
case RTE_FLOW_CONV_OP_ITEM:
- ret = rte_flow_conv_pattern(dst, size, src, 1, error);
+ ret = rte_flow_conv_pattern(dst, size, src, 1, false, error);
break;
case RTE_FLOW_CONV_OP_ITEM_MASK:
item = src;
@@ -1158,7 +1189,7 @@ rte_flow_conv(enum rte_flow_conv_op op,
ret = rte_flow_conv_actions(dst, size, src, 1, error);
break;
case RTE_FLOW_CONV_OP_PATTERN:
- ret = rte_flow_conv_pattern(dst, size, src, 0, error);
+ ret = rte_flow_conv_pattern(dst, size, src, 0, false, error);
break;
case RTE_FLOW_CONV_OP_ACTIONS:
ret = rte_flow_conv_actions(dst, size, src, 0, error);
@@ -1178,6 +1209,9 @@ rte_flow_conv(enum rte_flow_conv_op op,
case RTE_FLOW_CONV_OP_ACTION_NAME_PTR:
ret = rte_flow_conv_name(1, 1, dst, size, src, error);
break;
+ case RTE_FLOW_CONV_OP_PATTERN_MASKED:
+ ret = rte_flow_conv_pattern(dst, size, src, 0, true, error);
+ break;
default:
ret = rte_flow_error_set
(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
index eacfd7c5f7..5f8d4b00f0 100644
--- a/lib/ethdev/rte_flow.h
+++ b/lib/ethdev/rte_flow.h
@@ -4558,6 +4558,19 @@ enum rte_flow_conv_op {
* @code const char ** @endcode
*/
RTE_FLOW_CONV_OP_ACTION_NAME_PTR,
+
+ /**
+ * Convert an entire pattern.
+ *
+ * Duplicates all pattern items at once, applying @p mask to @p spec
+ * and @p last.
+ *
+ * - @p src type:
+ * @code const struct rte_flow_item * @endcode
+ * - @p dst type:
+ * @code struct rte_flow_item * @endcode
+ */
+ RTE_FLOW_CONV_OP_PATTERN_MASKED,
};
/**
--
2.34.1
^ permalink raw reply related
* [PATCH 2/2] crypto/ipsec_mb: remove ZUC and SNOW 3G drivers from x86 build
From: Radu Nicolau @ 2026-06-03 9:27 UTC (permalink / raw)
To: dev
Cc: paul.elliott, Shebu.VargheseKuriakose, tomasz.kantecki,
Islam.Ragimov, Gowtham.SureshKumar, emma.finn, marcel.d.cornu,
gakhil, john.mcnamara, Jonathan.Wright, Dhruv.Tripathi,
wathsala.vithanage, Radu Nicolau, Kai Ji, Pablo de Lara
In-Reply-To: <20260603092736.664428-1-radu.nicolau@intel.com>
The ZUC and SNOW 3G crypto drivers are using APIs that are now
deprecated in the Intel IPsec Multi-Buffer library.
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
doc/guides/cryptodevs/aesni_mb.rst | 2 +-
doc/guides/cryptodevs/snow3g.rst | 15 ++++-----------
doc/guides/cryptodevs/zuc.rst | 13 +++----------
doc/guides/rel_notes/release_26_07.rst | 5 +++++
drivers/crypto/ipsec_mb/ipsec_mb_private.h | 6 ++++++
drivers/crypto/ipsec_mb/meson.build | 9 +++++++--
6 files changed, 26 insertions(+), 24 deletions(-)
diff --git a/doc/guides/cryptodevs/aesni_mb.rst b/doc/guides/cryptodevs/aesni_mb.rst
index 9d886657f2..5efbadb8d1 100644
--- a/doc/guides/cryptodevs/aesni_mb.rst
+++ b/doc/guides/cryptodevs/aesni_mb.rst
@@ -82,7 +82,7 @@ Limitations
DOCSIS security protocol.
AESNI MB PMD selection over SNOW3G/ZUC PMDs
---------------------------------------------------
+-------------------------------------------
This PMD supports wireless cipher suite (SNOW3G and ZUC).
On Intel processors, it is recommended to use this PMD
diff --git a/doc/guides/cryptodevs/snow3g.rst b/doc/guides/cryptodevs/snow3g.rst
index 0fe914ffd3..d7f494a963 100644
--- a/doc/guides/cryptodevs/snow3g.rst
+++ b/doc/guides/cryptodevs/snow3g.rst
@@ -5,8 +5,8 @@ SNOW 3G Crypto Poll Mode Driver
===============================
The SNOW3G PMD (**librte_crypto_snow3g**) provides poll mode crypto driver support for
-utilizing `Intel IPSec Multi-buffer library <https://github.com/01org/intel-ipsec-mb>`_
-which implements F8 and F8 functions for SNOW 3G UEA2 cipher and UIA2 hash algorithms.
+utilizing the ARM64 port of `Intel IPSec Multi-buffer library <https://gitlab.arm.com/arm-reference-solutions/ipsec-mb>`_
+which implements F8 and F9 functions for SNOW 3G UEA2 cipher and UIA2 hash algorithms.
Features
--------
@@ -36,9 +36,7 @@ Limitations
SNOW3G PMD vs AESNI MB PMD
--------------------------
-AESNI MB PMD also supports SNOW3G cipher and authentication algorithms.
-It is recommended to use the AESNI MB PMD,
-which offers better performance on Intel processors.
+On Intel processors this PMD is no longer supported, please use the AESNI MB PMD.
Take a look at the PMD documentation (:doc:`aesni_mb`) for more information.
Installation
@@ -47,12 +45,7 @@ Installation
To build DPDK with the SNOW3G_PMD the user is required to download the multi-buffer
library and compile it on their user system before building DPDK.
-For x86 system, the multi-buffer library is available
-`here <https://github.com/01org/intel-ipsec-mb>`_.
-The latest version of the library supported by this PMD is v1.5, which
-can be downloaded from `<https://github.com/01org/intel-ipsec-mb/archive/v1.5.zip>`_.
-
-For Arm system, ARM64 port of the multi-buffer library can be downloaded from
+The ARM64 port of the multi-buffer library can be downloaded from
`<https://gitlab.arm.com/arm-reference-solutions/ipsec-mb/-/tree/main/>`_. The
latest version of the library supported by this PMD is tagged as SECLIB-IPSEC-2024.07.08.
diff --git a/doc/guides/cryptodevs/zuc.rst b/doc/guides/cryptodevs/zuc.rst
index 7c6b83e7eb..e4c86814f1 100644
--- a/doc/guides/cryptodevs/zuc.rst
+++ b/doc/guides/cryptodevs/zuc.rst
@@ -5,7 +5,7 @@ ZUC Crypto Poll Mode Driver
===========================
The ZUC PMD (**librte_crypto_zuc**) provides poll mode crypto driver support for
-utilizing `Intel IPSec Multi-buffer library <https://github.com/01org/intel-ipsec-mb>`_
+utilizing the ARM64 port of `Intel IPSec Multi-buffer library <https://gitlab.arm.com/arm-reference-solutions/ipsec-mb>`_
which implements F8 and F9 functions for ZUC EEA3 cipher and EIA3 hash algorithms.
Features
@@ -35,9 +35,7 @@ Limitations
ZUC PMD vs AESNI MB PMD
-----------------------
-AESNI MB PMD also supports ZUC cipher and authentication algorithms.
-It is recommended to use the AESNI MB PMD,
-which offers better performance on Intel processors.
+On Intel processors this PMD is no longer supported, please use the AESNI MB PMD.
Take a look at the PMD documentation (:doc:`aesni_mb`) for more information.
Installation
@@ -46,12 +44,7 @@ Installation
To build DPDK with the ZUC_PMD the user is required to download the multi-buffer
library and compile it on their user system before building DPDK.
-For x86 system, the multi-buffer library is available
-`here <https://github.com/01org/intel-ipsec-mb>`_.
-The latest version of the library supported by this PMD is v1.5, which
-can be downloaded from `<https://github.com/01org/intel-ipsec-mb/archive/v1.5.zip>`_.
-
-For Arm system, ARM64 port of the multi-buffer library can be downloaded from
+The ARM64 port of the multi-buffer library can be downloaded from
`<https://gitlab.arm.com/arm-reference-solutions/ipsec-mb/-/tree/main/>`_. The
latest version of the library supported by this PMD is tagged as SECLIB-IPSEC-2024.07.08.
diff --git a/doc/guides/rel_notes/release_26_07.rst b/doc/guides/rel_notes/release_26_07.rst
index 64c8b038d1..388642851a 100644
--- a/doc/guides/rel_notes/release_26_07.rst
+++ b/doc/guides/rel_notes/release_26_07.rst
@@ -123,6 +123,11 @@ Removed Items
* The Chacha20-poly1305 and KASUMI drivers were just wrappers around
the main AESNI_MB driver.
+* **Removed ZUC and SNOW 3G crypto drivers from the x86 release.**
+
+ * The ZUC and SNOW 3G crypto drivers are using APIs that are now
+ deprecated in the Intel IPsec Multi-Buffer library.
+
API Changes
-----------
diff --git a/drivers/crypto/ipsec_mb/ipsec_mb_private.h b/drivers/crypto/ipsec_mb/ipsec_mb_private.h
index 9712bf5b4c..fc7d6f5f06 100644
--- a/drivers/crypto/ipsec_mb/ipsec_mb_private.h
+++ b/drivers/crypto/ipsec_mb/ipsec_mb_private.h
@@ -45,11 +45,13 @@ extern RTE_DEFINE_PER_LCORE(IMB_MGR *, mb_mgr);
#define CRYPTODEV_NAME_AESNI_GCM_PMD crypto_aesni_gcm
/**< IPSEC Multi buffer PMD aesni_gcm device name */
+#if defined(RTE_ARCH_ARM)
#define CRYPTODEV_NAME_SNOW3G_PMD crypto_snow3g
/**< IPSEC Multi buffer PMD snow3g device name */
#define CRYPTODEV_NAME_ZUC_PMD crypto_zuc
/**< IPSEC Multi buffer PMD zuc device name */
+#endif
/** PMD LOGTYPE DRIVER, common to all PMDs */
extern int ipsec_mb_logtype_driver;
@@ -62,8 +64,10 @@ extern int ipsec_mb_logtype_driver;
enum ipsec_mb_pmd_types {
IPSEC_MB_PMD_TYPE_AESNI_MB = 0,
IPSEC_MB_PMD_TYPE_AESNI_GCM,
+#if defined(RTE_ARCH_ARM)
IPSEC_MB_PMD_TYPE_SNOW3G,
IPSEC_MB_PMD_TYPE_ZUC,
+#endif
IPSEC_MB_N_PMD_TYPES
};
@@ -96,10 +100,12 @@ ipsec_mb_get_driver_id(enum ipsec_mb_pmd_types pmd_type)
return pmd_driver_id_aesni_mb;
case IPSEC_MB_PMD_TYPE_AESNI_GCM:
return pmd_driver_id_aesni_gcm;
+#if defined(RTE_ARCH_ARM)
case IPSEC_MB_PMD_TYPE_SNOW3G:
return pmd_driver_id_snow3g;
case IPSEC_MB_PMD_TYPE_ZUC:
return pmd_driver_id_zuc;
+#endif
default:
break;
}
diff --git a/drivers/crypto/ipsec_mb/meson.build b/drivers/crypto/ipsec_mb/meson.build
index 6c5e4e2259..eb2085725b 100644
--- a/drivers/crypto/ipsec_mb/meson.build
+++ b/drivers/crypto/ipsec_mb/meson.build
@@ -42,8 +42,13 @@ sources = files(
'ipsec_mb_ops.c',
'pmd_aesni_mb.c',
'pmd_aesni_gcm.c',
- 'pmd_snow3g.c',
- 'pmd_zuc.c',
)
+# PMDs supported only on ARM build
+if arch_subdir == 'arm'
+ sources += files(
+ 'pmd_snow3g.c',
+ 'pmd_zuc.c',
+ )
+endif
deps += ['bus_vdev', 'net', 'security']
require_iova_in_mbuf = false
--
2.52.0
^ permalink raw reply related
* [PATCH 1/2] crypto/ipsec_mb: remove chacha-poly and kasumi drivers
From: Radu Nicolau @ 2026-06-03 9:27 UTC (permalink / raw)
To: dev
Cc: paul.elliott, Shebu.VargheseKuriakose, tomasz.kantecki,
Islam.Ragimov, Gowtham.SureshKumar, emma.finn, marcel.d.cornu,
gakhil, john.mcnamara, Jonathan.Wright, Dhruv.Tripathi,
wathsala.vithanage, Radu Nicolau, Thomas Monjalon, Fan Zhang,
Kai Ji, Pablo de Lara
The Chacha20-poly1305 and KASUMI drivers were just wrappers around
the main AESNI_MB driver, hence redundant and removed.
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
MAINTAINERS | 4 -
app/test/test_cryptodev.c | 20 ---
app/test/test_cryptodev.h | 2 -
doc/guides/cryptodevs/aesni_mb.rst | 14 +-
doc/guides/cryptodevs/chacha20_poly1305.rst | 100 -------------
.../cryptodevs/features/chacha20_poly1305.ini | 42 ------
doc/guides/cryptodevs/features/kasumi.ini | 39 ------
doc/guides/cryptodevs/index.rst | 2 -
doc/guides/cryptodevs/kasumi.rst | 131 ------------------
doc/guides/rel_notes/release_26_07.rst | 5 +
doc/guides/tools/cryptoperf.rst | 1 -
drivers/crypto/ipsec_mb/ipsec_mb_private.h | 14 --
drivers/crypto/ipsec_mb/meson.build | 2 -
drivers/crypto/ipsec_mb/pmd_chacha_poly.c | 74 ----------
.../crypto/ipsec_mb/pmd_chacha_poly_priv.h | 46 ------
drivers/crypto/ipsec_mb/pmd_kasumi.c | 76 ----------
drivers/crypto/ipsec_mb/pmd_kasumi_priv.h | 61 --------
17 files changed, 8 insertions(+), 625 deletions(-)
delete mode 100644 doc/guides/cryptodevs/chacha20_poly1305.rst
delete mode 100644 doc/guides/cryptodevs/features/chacha20_poly1305.ini
delete mode 100644 doc/guides/cryptodevs/features/kasumi.ini
delete mode 100644 doc/guides/cryptodevs/kasumi.rst
delete mode 100644 drivers/crypto/ipsec_mb/pmd_chacha_poly.c
delete mode 100644 drivers/crypto/ipsec_mb/pmd_chacha_poly_priv.h
delete mode 100644 drivers/crypto/ipsec_mb/pmd_kasumi.c
delete mode 100644 drivers/crypto/ipsec_mb/pmd_kasumi_priv.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 72fc12b1f2..567d1c872e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1234,14 +1234,10 @@ M: Pablo de Lara <pablo.de.lara.guarch@intel.com>
F: drivers/crypto/ipsec_mb/
F: doc/guides/cryptodevs/aesni_gcm.rst
F: doc/guides/cryptodevs/aesni_mb.rst
-F: doc/guides/cryptodevs/chacha20_poly1305.rst
-F: doc/guides/cryptodevs/kasumi.rst
F: doc/guides/cryptodevs/snow3g.rst
F: doc/guides/cryptodevs/zuc.rst
F: doc/guides/cryptodevs/features/aesni_gcm.ini
F: doc/guides/cryptodevs/features/aesni_mb.ini
-F: doc/guides/cryptodevs/features/chacha20_poly1305.ini
-F: doc/guides/cryptodevs/features/kasumi.ini
F: doc/guides/cryptodevs/features/snow3g.ini
F: doc/guides/cryptodevs/features/zuc.ini
diff --git a/app/test/test_cryptodev.c b/app/test/test_cryptodev.c
index a60983c6b7..b908f10317 100644
--- a/app/test/test_cryptodev.c
+++ b/app/test/test_cryptodev.c
@@ -20602,17 +20602,6 @@ test_cryptodev_cpu_aesni_mb(void)
return rc;
}
-static int
-test_cryptodev_chacha_poly_mb(void)
-{
- int32_t rc;
- enum rte_security_session_action_type at = gbl_action_type;
- rc = run_cryptodev_testsuite(
- RTE_STR(CRYPTODEV_NAME_CHACHA20_POLY1305_PMD));
- gbl_action_type = at;
- return rc;
-}
-
static int
test_cryptodev_openssl(void)
{
@@ -20654,12 +20643,6 @@ test_cryptodev_sw_snow3g(void)
return run_cryptodev_testsuite(RTE_STR(CRYPTODEV_NAME_SNOW3G_PMD));
}
-static int
-test_cryptodev_sw_kasumi(void)
-{
- return run_cryptodev_testsuite(RTE_STR(CRYPTODEV_NAME_KASUMI_PMD));
-}
-
static int
test_cryptodev_sw_zuc(void)
{
@@ -20910,8 +20893,6 @@ REGISTER_DRIVER_TEST(cryptodev_qat_autotest, test_cryptodev_qat);
REGISTER_DRIVER_TEST(cryptodev_aesni_mb_autotest, test_cryptodev_aesni_mb);
REGISTER_DRIVER_TEST(cryptodev_cpu_aesni_mb_autotest,
test_cryptodev_cpu_aesni_mb);
-REGISTER_DRIVER_TEST(cryptodev_chacha_poly_mb_autotest,
- test_cryptodev_chacha_poly_mb);
REGISTER_DRIVER_TEST(cryptodev_openssl_autotest, test_cryptodev_openssl);
REGISTER_DRIVER_TEST(cryptodev_aesni_gcm_autotest, test_cryptodev_aesni_gcm);
REGISTER_DRIVER_TEST(cryptodev_cpu_aesni_gcm_autotest,
@@ -20919,7 +20900,6 @@ REGISTER_DRIVER_TEST(cryptodev_cpu_aesni_gcm_autotest,
REGISTER_DRIVER_TEST(cryptodev_mlx5_autotest, test_cryptodev_mlx5);
REGISTER_DRIVER_TEST(cryptodev_null_autotest, test_cryptodev_null);
REGISTER_DRIVER_TEST(cryptodev_sw_snow3g_autotest, test_cryptodev_sw_snow3g);
-REGISTER_DRIVER_TEST(cryptodev_sw_kasumi_autotest, test_cryptodev_sw_kasumi);
REGISTER_DRIVER_TEST(cryptodev_sw_zuc_autotest, test_cryptodev_sw_zuc);
REGISTER_DRIVER_TEST(cryptodev_sw_armv8_autotest, test_cryptodev_armv8);
REGISTER_DRIVER_TEST(cryptodev_sw_mvsam_autotest, test_cryptodev_mrvl);
diff --git a/app/test/test_cryptodev.h b/app/test/test_cryptodev.h
index 23d12ec961..49aa45ec17 100644
--- a/app/test/test_cryptodev.h
+++ b/app/test/test_cryptodev.h
@@ -59,9 +59,7 @@
#define CRYPTODEV_NAME_QAT_SYM_PMD crypto_qat
#define CRYPTODEV_NAME_QAT_ASYM_PMD crypto_qat_asym
#define CRYPTODEV_NAME_SNOW3G_PMD crypto_snow3g
-#define CRYPTODEV_NAME_KASUMI_PMD crypto_kasumi
#define CRYPTODEV_NAME_ZUC_PMD crypto_zuc
-#define CRYPTODEV_NAME_CHACHA20_POLY1305_PMD crypto_chacha20_poly1305
#define CRYPTODEV_NAME_ARMV8_PMD crypto_armv8
#define CRYPTODEV_NAME_DPAA_SEC_PMD crypto_dpaa_sec
#define CRYPTODEV_NAME_DPAA2_SEC_PMD crypto_dpaa2_sec
diff --git a/doc/guides/cryptodevs/aesni_mb.rst b/doc/guides/cryptodevs/aesni_mb.rst
index 7ce92305d1..9d886657f2 100644
--- a/doc/guides/cryptodevs/aesni_mb.rst
+++ b/doc/guides/cryptodevs/aesni_mb.rst
@@ -81,23 +81,15 @@ Limitations
* RTE_CRYPTO_CIPHER_DES_DOCSISBPI is not supported for combined Crypto-CRC
DOCSIS security protocol.
-AESNI MB PMD selection over SNOW3G/ZUC/KASUMI PMDs
+AESNI MB PMD selection over SNOW3G/ZUC PMDs
--------------------------------------------------
-This PMD supports wireless cipher suite (SNOW3G, ZUC and KASUMI).
+This PMD supports wireless cipher suite (SNOW3G and ZUC).
On Intel processors, it is recommended to use this PMD
-instead of SNOW3G, ZUC and KASUMI PMDs, as it enables algorithm mixing
+instead of SNOW3G and ZUC PMDs, as it enables algorithm mixing
(e.g. cipher algorithm SNOW3G-UEA2 with authentication algorithm AES-CMAC-128)
and performance over IMIX (packet size mix) traffic is significantly higher.
-AESNI MB PMD selection over CHACHA20-POLY1305 PMD
--------------------------------------------------
-
-This PMD supports Chacha20-Poly1305 algorithm.
-On Intel processors, it is recommended to use this PMD instead of CHACHA20-POLY1305 PMD,
-as it delivers better performance on single segment buffers.
-For multi-segment buffers, it is still recommended to use CHACHA20-POLY1305 PMD,
-until the new SGL API is introduced in the AESNI MB PMD.
Installation
------------
diff --git a/doc/guides/cryptodevs/chacha20_poly1305.rst b/doc/guides/cryptodevs/chacha20_poly1305.rst
deleted file mode 100644
index 37d9d2e8af..0000000000
--- a/doc/guides/cryptodevs/chacha20_poly1305.rst
+++ /dev/null
@@ -1,100 +0,0 @@
-.. SPDX-License-Identifier: BSD-3-Clause
- Copyright(c) 2021 Intel Corporation.
-
-Chacha20-poly1305 Crypto Poll Mode Driver
-=========================================
-
-The Chacha20-poly1305 PMD provides poll mode crypto driver support for
-utilizing `Intel IPSec Multi-buffer library <https://github.com/01org/intel-ipsec-mb>`_.
-
-Features
---------
-
-Chacha20-poly1305 PMD has support for:
-
-AEAD algorithms:
-
-* RTE_CRYPTO_AEAD_CHACHA20_POLY1305
-
-Chaha20_Poly1305 PMD vs AESNI MB PMD
-------------------------------------
-
-AESNI MB PMD also supports CHACHA20-POLY1305 algorithms.
-It is recommended to use the AESNI MB PMD,
-which offers better performance on Intel processors,
-when single-segment buffers are used.
-Take a look at the PMD documentation (:doc:`aesni_mb`) for more information.
-
-Installation
-------------
-
-To build DPDK with the Chacha20-poly1305 PMD the user is required to download
-the multi-buffer library from `here <https://github.com/01org/intel-ipsec-mb>`_
-and compile it on their user system before building DPDK.
-The latest version of the library supported by this PMD is v1.5, which
-can be downloaded from `<https://github.com/01org/intel-ipsec-mb/archive/v1.5.zip>`_.
-
-After downloading the library, the user needs to unpack and compile it
-on their system before building DPDK:
-
-.. code-block:: console
-
- make
- make install
-
-The library requires NASM to be built. Depending on the library version, it might
-require a minimum NASM version (e.g. v0.54 requires at least NASM 2.14).
-
-NASM is packaged for different OS. However, on some OS the version is too old,
-so a manual installation is required. In that case, NASM can be downloaded from
-`NASM website <https://www.nasm.us/pub/nasm/releasebuilds/?C=M;O=D>`_.
-Once it is downloaded, extract it and follow these steps:
-
-.. code-block:: console
-
- ./configure
- make
- make install
-
-As a reference, the following table shows a mapping between the past DPDK versions
-and the external crypto libraries supported by them:
-
-.. _table_chacha20_poly1305_versions:
-
-.. table:: DPDK and external crypto library version compatibility
-
- ============= ================================
- DPDK version Crypto library version
- ============= ================================
- 21.11 - 24.07 Multi-buffer library 1.0 - 1.5
- 24.11+ Multi-buffer library 1.4+
- ============= ================================
-
-Initialization
---------------
-
-In order to enable this virtual crypto PMD, user must:
-
-* Build the multi buffer library (explained in Installation section).
-
-To use the PMD in an application, user must:
-
-* Call rte_vdev_init("crypto_chacha20_poly1305") within the application.
-
-* Use --vdev="crypto_chacha20_poly1305" in the EAL options, which will call
- rte_vdev_init() internally.
-
-The following parameters (all optional) can be provided in the previous two calls:
-
-* socket_id: Specify the socket where the memory for the device is going to be allocated
- (by default, socket_id will be the socket where the core that is creating the PMD is running on).
-
-* max_nb_queue_pairs: Specify the maximum number of queue pairs in the device (8 by default).
-
-* max_nb_sessions: Specify the maximum number of sessions that can be created (2048 by default).
-
-Example:
-
-.. code-block:: console
-
- --vdev="crypto_chacha20_poly1305,socket_id=0,max_nb_sessions=128"
diff --git a/doc/guides/cryptodevs/features/chacha20_poly1305.ini b/doc/guides/cryptodevs/features/chacha20_poly1305.ini
deleted file mode 100644
index b5a7b39bd0..0000000000
--- a/doc/guides/cryptodevs/features/chacha20_poly1305.ini
+++ /dev/null
@@ -1,42 +0,0 @@
-;
-; Supported features of the 'chacha20_poly1305' crypto driver.
-;
-; Refer to default.ini for the full list of available PMD features.
-;
-[Features]
-Symmetric crypto = Y
-Sym operation chaining = Y
-Symmetric sessionless = Y
-Non-Byte aligned data = Y
-In Place SGL = Y
-OOP SGL In LB Out = Y
-OOP LB In LB Out = Y
-CPU crypto = Y
-
-;
-; Supported crypto algorithms of the 'chacha20_poly1305' crypto driver.
-;
-[Cipher]
-
-;
-; Supported authentication algorithms of the 'chacha20_poly1305' crypto driver.
-;
-[Auth]
-
-;
-; Supported AEAD algorithms of the 'chacha20_poly1305' crypto driver.
-;
-[AEAD]
-CHACHA20-POLY1305 = Y
-
-;
-; Supported Asymmetric algorithms of the 'chacha20_poly1305' crypto driver.
-;
-[Asymmetric]
-
-;
-; Supported Operating systems of the 'chacha20_poly1305' crypto driver.
-;
-[OS]
-Linux = Y
-FreeBSD = Y
diff --git a/doc/guides/cryptodevs/features/kasumi.ini b/doc/guides/cryptodevs/features/kasumi.ini
deleted file mode 100644
index d400a4269d..0000000000
--- a/doc/guides/cryptodevs/features/kasumi.ini
+++ /dev/null
@@ -1,39 +0,0 @@
-;
-; Supported features of the 'kasumi' crypto driver.
-;
-; Refer to default.ini for the full list of available PMD features.
-;
-[Features]
-Symmetric crypto = Y
-Sym operation chaining = Y
-Symmetric sessionless = Y
-Non-Byte aligned data = Y
-OOP LB In LB Out = Y
-
-;
-; Supported crypto algorithms of the 'kasumi' crypto driver.
-;
-[Cipher]
-KASUMI F8 = Y
-;
-; Supported authentication algorithms of the 'kasumi' crypto driver.
-;
-[Auth]
-KASUMI F9 = Y
-
-;
-; Supported AEAD algorithms of the 'kasumi' crypto driver.
-;
-[AEAD]
-
-;
-; Supported Asymmetric algorithms of the 'kasumi' crypto driver.
-;
-[Asymmetric]
-
-;
-; Supported Operating systems of the 'kasumi' crypto driver.
-;
-[OS]
-Linux = Y
-FreeBSD = Y
diff --git a/doc/guides/cryptodevs/index.rst b/doc/guides/cryptodevs/index.rst
index 7c19629e17..cfb6a494bf 100644
--- a/doc/guides/cryptodevs/index.rst
+++ b/doc/guides/cryptodevs/index.rst
@@ -16,12 +16,10 @@ Crypto Device Drivers
bcmfs
caam_jr
ccp
- chacha20_poly1305
cnxk
dpaa2_sec
dpaa_sec
ionic
- kasumi
octeontx
openssl
mlx5
diff --git a/doc/guides/cryptodevs/kasumi.rst b/doc/guides/cryptodevs/kasumi.rst
deleted file mode 100644
index ce1db4e905..0000000000
--- a/doc/guides/cryptodevs/kasumi.rst
+++ /dev/null
@@ -1,131 +0,0 @@
-.. SPDX-License-Identifier: BSD-3-Clause
- Copyright(c) 2016-2019 Intel Corporation.
-
-KASUMI Crypto Poll Mode Driver
-===============================
-
-The KASUMI PMD (**librte_crypto_kasumi**) provides poll mode crypto driver support for
-utilizing `Intel IPSec Multi-buffer library <https://github.com/01org/intel-ipsec-mb>`_
-which implements F8 and F9 functions for KASUMI UEA1 cipher and UIA1 hash algorithms.
-
-Features
---------
-
-KASUMI PMD has support for:
-
-Cipher algorithm:
-
-* RTE_CRYPTO_CIPHER_KASUMI_F8
-
-Authentication algorithm:
-
-* RTE_CRYPTO_AUTH_KASUMI_F9
-
-Limitations
------------
-
-* Chained mbufs are not supported.
-* KASUMI(F9) supported only if hash offset and length field is byte-aligned.
-* In-place bit-level operations for KASUMI(F8) are not supported
- (if length and/or offset of data to be ciphered is not byte-aligned).
-
-
-KASUMI PMD vs AESNI MB PMD
---------------------------
-
-AESNI MB PMD also supports KASUMI cipher and authentication algorithms.
-It is recommended to use the AESNI MB PMD,
-which offers better performance on Intel processors.
-Take a look at the PMD documentation (:doc:`aesni_mb`) for more information.
-
-Installation
-------------
-
-To build DPDK with the KASUMI_PMD the user is required to download the multi-buffer
-library from `here <https://github.com/01org/intel-ipsec-mb>`_
-and compile it on their user system before building DPDK.
-The latest version of the library supported by this PMD is v1.5, which
-can be downloaded from `<https://github.com/01org/intel-ipsec-mb/archive/v1.5.zip>`_.
-
-After downloading the library, the user needs to unpack and compile it
-on their system before building DPDK:
-
-.. code-block:: console
-
- make
- make install
-
-The library requires NASM to be built. Depending on the library version, it might
-require a minimum NASM version (e.g. v0.54 requires at least NASM 2.14).
-
-NASM is packaged for different OS. However, on some OS the version is too old,
-so a manual installation is required. In that case, NASM can be downloaded from
-`NASM website <https://www.nasm.us/pub/nasm/releasebuilds/?C=M;O=D>`_.
-Once it is downloaded, extract it and follow these steps:
-
-.. code-block:: console
-
- ./configure
- make
- make install
-
-As a reference, the following table shows a mapping between the past DPDK versions
-and the external crypto libraries supported by them:
-
-.. _table_kasumi_versions:
-
-.. table:: DPDK and external crypto library version compatibility
-
- ============= ================================
- DPDK version Crypto library version
- ============= ================================
- 20.02 - 21.08 Multi-buffer library 0.53 - 1.3
- 21.11 - 24.07 Multi-buffer library 1.0 - 1.5
- 24.11+ Multi-buffer library 1.4 - 1.5
- ============= ================================
-
-Initialization
---------------
-
-In order to enable this virtual crypto PMD, user must:
-
-* Build the multi buffer library (explained in Installation section).
-
-To use the PMD in an application, user must:
-
-* Call rte_vdev_init("crypto_kasumi") within the application.
-
-* Use --vdev="crypto_kasumi" in the EAL options, which will call rte_vdev_init() internally.
-
-The following parameters (all optional) can be provided in the previous two calls:
-
-* socket_id: Specify the socket where the memory for the device is going to be allocated
- (by default, socket_id will be the socket where the core that is creating the PMD is running on).
-
-* max_nb_queue_pairs: Specify the maximum number of queue pairs in the device (8 by default).
-
-* max_nb_sessions: Specify the maximum number of sessions that can be created (2048 by default).
-
-Example:
-
-.. code-block:: console
-
- ./dpdk-l2fwd-crypto -l 1 --vdev="crypto_kasumi,socket_id=0,max_nb_sessions=128" \
- -- -p 1 --cdev SW --chain CIPHER_ONLY --cipher_algo "kasumi-f8"
-
-Extra notes on KASUMI F9
-------------------------
-
-When using KASUMI F9 authentication algorithm, the input buffer must be
-constructed according to the 3GPP KASUMI specifications (section 4.4, page 13):
-`<http://cryptome.org/3gpp/35201-900.pdf>`_.
-Input buffer has to have COUNT (4 bytes), FRESH (4 bytes), MESSAGE and DIRECTION (1 bit)
-concatenated. After the DIRECTION bit, a single '1' bit is appended, followed by
-between 0 and 7 '0' bits, so that the total length of the buffer is multiple of 8 bits.
-Note that the actual message can be any length, specified in bits.
-
-Once this buffer is passed this way, when creating the crypto operation,
-length of data to authenticate (op.sym.auth.data.length) must be the length
-of all the items described above, including the padding at the end.
-Also, offset of data to authenticate (op.sym.auth.data.offset)
-must be such that points at the start of the COUNT bytes.
diff --git a/doc/guides/rel_notes/release_26_07.rst b/doc/guides/rel_notes/release_26_07.rst
index b8a3e2ced9..64c8b038d1 100644
--- a/doc/guides/rel_notes/release_26_07.rst
+++ b/doc/guides/rel_notes/release_26_07.rst
@@ -118,6 +118,11 @@ Removed Items
Also, make sure to start the actual text at the margin.
=======================================================
+* **Removed Chacha20-poly1305 and KASUMI crypto drivers.**
+
+ * The Chacha20-poly1305 and KASUMI drivers were just wrappers around
+ the main AESNI_MB driver.
+
API Changes
-----------
diff --git a/doc/guides/tools/cryptoperf.rst b/doc/guides/tools/cryptoperf.rst
index 846487c5e6..2ce9bc9a96 100644
--- a/doc/guides/tools/cryptoperf.rst
+++ b/doc/guides/tools/cryptoperf.rst
@@ -153,7 +153,6 @@ The following are the application command-line options:
crypto_cn10k
crypto_dpaa_sec
crypto_dpaa2_sec
- crypto_kasumi
crypto_mvsam
crypto_null
crypto_octeontx
diff --git a/drivers/crypto/ipsec_mb/ipsec_mb_private.h b/drivers/crypto/ipsec_mb/ipsec_mb_private.h
index 025767cfce..9712bf5b4c 100644
--- a/drivers/crypto/ipsec_mb/ipsec_mb_private.h
+++ b/drivers/crypto/ipsec_mb/ipsec_mb_private.h
@@ -45,18 +45,12 @@ extern RTE_DEFINE_PER_LCORE(IMB_MGR *, mb_mgr);
#define CRYPTODEV_NAME_AESNI_GCM_PMD crypto_aesni_gcm
/**< IPSEC Multi buffer PMD aesni_gcm device name */
-#define CRYPTODEV_NAME_KASUMI_PMD crypto_kasumi
-/**< IPSEC Multi buffer PMD kasumi device name */
-
#define CRYPTODEV_NAME_SNOW3G_PMD crypto_snow3g
/**< IPSEC Multi buffer PMD snow3g device name */
#define CRYPTODEV_NAME_ZUC_PMD crypto_zuc
/**< IPSEC Multi buffer PMD zuc device name */
-#define CRYPTODEV_NAME_CHACHA20_POLY1305_PMD crypto_chacha20_poly1305
-/**< IPSEC Multi buffer PMD chacha20_poly1305 device name */
-
/** PMD LOGTYPE DRIVER, common to all PMDs */
extern int ipsec_mb_logtype_driver;
#define RTE_LOGTYPE_IPSEC_MB ipsec_mb_logtype_driver
@@ -68,10 +62,8 @@ extern int ipsec_mb_logtype_driver;
enum ipsec_mb_pmd_types {
IPSEC_MB_PMD_TYPE_AESNI_MB = 0,
IPSEC_MB_PMD_TYPE_AESNI_GCM,
- IPSEC_MB_PMD_TYPE_KASUMI,
IPSEC_MB_PMD_TYPE_SNOW3G,
IPSEC_MB_PMD_TYPE_ZUC,
- IPSEC_MB_PMD_TYPE_CHACHA20_POLY1305,
IPSEC_MB_N_PMD_TYPES
};
@@ -92,10 +84,8 @@ enum ipsec_mb_operation {
extern uint8_t pmd_driver_id_aesni_mb;
extern uint8_t pmd_driver_id_aesni_gcm;
-extern uint8_t pmd_driver_id_kasumi;
extern uint8_t pmd_driver_id_snow3g;
extern uint8_t pmd_driver_id_zuc;
-extern uint8_t pmd_driver_id_chacha20_poly1305;
/** Helper function. Gets driver ID based on PMD type */
static __rte_always_inline uint8_t
@@ -106,14 +96,10 @@ ipsec_mb_get_driver_id(enum ipsec_mb_pmd_types pmd_type)
return pmd_driver_id_aesni_mb;
case IPSEC_MB_PMD_TYPE_AESNI_GCM:
return pmd_driver_id_aesni_gcm;
- case IPSEC_MB_PMD_TYPE_KASUMI:
- return pmd_driver_id_kasumi;
case IPSEC_MB_PMD_TYPE_SNOW3G:
return pmd_driver_id_snow3g;
case IPSEC_MB_PMD_TYPE_ZUC:
return pmd_driver_id_zuc;
- case IPSEC_MB_PMD_TYPE_CHACHA20_POLY1305:
- return pmd_driver_id_chacha20_poly1305;
default:
break;
}
diff --git a/drivers/crypto/ipsec_mb/meson.build b/drivers/crypto/ipsec_mb/meson.build
index 5fcff5b04b..6c5e4e2259 100644
--- a/drivers/crypto/ipsec_mb/meson.build
+++ b/drivers/crypto/ipsec_mb/meson.build
@@ -42,8 +42,6 @@ sources = files(
'ipsec_mb_ops.c',
'pmd_aesni_mb.c',
'pmd_aesni_gcm.c',
- 'pmd_chacha_poly.c',
- 'pmd_kasumi.c',
'pmd_snow3g.c',
'pmd_zuc.c',
)
diff --git a/drivers/crypto/ipsec_mb/pmd_chacha_poly.c b/drivers/crypto/ipsec_mb/pmd_chacha_poly.c
deleted file mode 100644
index 24488d4921..0000000000
--- a/drivers/crypto/ipsec_mb/pmd_chacha_poly.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2021 Intel Corporation
- */
-
-#include "pmd_chacha_poly_priv.h"
-#include "pmd_aesni_mb_priv.h"
-
-struct rte_cryptodev_ops chacha20_poly1305_pmd_ops = {
- .dev_configure = ipsec_mb_config,
- .dev_start = ipsec_mb_start,
- .dev_stop = ipsec_mb_stop,
- .dev_close = ipsec_mb_close,
-
- .stats_get = ipsec_mb_stats_get,
- .stats_reset = ipsec_mb_stats_reset,
-
- .dev_infos_get = ipsec_mb_info_get,
-
- .queue_pair_setup = ipsec_mb_qp_setup,
- .queue_pair_release = ipsec_mb_qp_release,
-
- .sym_session_get_size = ipsec_mb_sym_session_get_size,
- .sym_session_configure = ipsec_mb_sym_session_configure,
- .sym_session_clear = ipsec_mb_sym_session_clear
-};
-
-struct rte_cryptodev_ops *rte_chacha20_poly1305_pmd_ops =
- &chacha20_poly1305_pmd_ops;
-
-static int
-chacha20_poly1305_probe(struct rte_vdev_device *vdev)
-{
- return ipsec_mb_create(vdev, IPSEC_MB_PMD_TYPE_CHACHA20_POLY1305);
-}
-
-static struct rte_vdev_driver cryptodev_chacha20_poly1305_pmd_drv = {
- .probe = chacha20_poly1305_probe,
- .remove = ipsec_mb_remove
-};
-
-static struct cryptodev_driver chacha20_poly1305_crypto_drv;
-
-RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_CHACHA20_POLY1305_PMD,
- cryptodev_chacha20_poly1305_pmd_drv);
-RTE_PMD_REGISTER_ALIAS(CRYPTODEV_NAME_CHACHA20_POLY1305_PMD,
- cryptodev_chacha20_poly1305_pmd);
-RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_CHACHA20_POLY1305_PMD,
- "max_nb_queue_pairs=<int> socket_id=<int>");
-RTE_PMD_REGISTER_CRYPTO_DRIVER(chacha20_poly1305_crypto_drv,
- cryptodev_chacha20_poly1305_pmd_drv.driver,
- pmd_driver_id_chacha20_poly1305);
-
-/* Constructor function to register chacha20_poly1305 PMD */
-RTE_INIT(ipsec_mb_register_chacha20_poly1305)
-{
- struct ipsec_mb_internals *chacha_poly_data
- = &ipsec_mb_pmds[IPSEC_MB_PMD_TYPE_CHACHA20_POLY1305];
-
- chacha_poly_data->caps = chacha20_poly1305_capabilities;
- chacha_poly_data->dequeue_burst = aesni_mb_dequeue_burst;
- chacha_poly_data->feature_flags =
- RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
- RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
- RTE_CRYPTODEV_FF_IN_PLACE_SGL |
- RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT |
- RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT |
- RTE_CRYPTODEV_FF_SYM_CPU_CRYPTO |
- RTE_CRYPTODEV_FF_SYM_SESSIONLESS;
- chacha_poly_data->internals_priv_size = 0;
- chacha_poly_data->ops = &chacha20_poly1305_pmd_ops;
- chacha_poly_data->qp_priv_size = sizeof(struct aesni_mb_qp_data);
- chacha_poly_data->session_configure = aesni_mb_session_configure;
- chacha_poly_data->session_priv_size = sizeof(struct aesni_mb_session);
-}
diff --git a/drivers/crypto/ipsec_mb/pmd_chacha_poly_priv.h b/drivers/crypto/ipsec_mb/pmd_chacha_poly_priv.h
deleted file mode 100644
index e668bfe07f..0000000000
--- a/drivers/crypto/ipsec_mb/pmd_chacha_poly_priv.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2021 Intel Corporation
- */
-
-#ifndef _PMD_CHACHA_POLY_PRIV_H_
-#define _PMD_CHACHA_POLY_PRIV_H_
-
-#include "ipsec_mb_private.h"
-
-#define CHACHA20_POLY1305_DIGEST_LENGTH 16
-
-static const
-struct rte_cryptodev_capabilities chacha20_poly1305_capabilities[] = {
- {/* CHACHA20-POLY1305 */
- .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
- {.sym = {
- .xform_type = RTE_CRYPTO_SYM_XFORM_AEAD,
- {.aead = {
- .algo = RTE_CRYPTO_AEAD_CHACHA20_POLY1305,
- .block_size = 64,
- .key_size = {
- .min = 32,
- .max = 32,
- .increment = 0},
- .digest_size = {
- .min = 16,
- .max = 16,
- .increment = 0},
- .aad_size = {
- .min = 0,
- .max = 240,
- .increment = 1},
- .iv_size = {
- .min = 12,
- .max = 12,
- .increment = 0},
- },
- }
- },}
- },
- RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
-};
-
-uint8_t pmd_driver_id_chacha20_poly1305;
-
-#endif /* _PMD_CHACHA_POLY_PRIV_H_ */
diff --git a/drivers/crypto/ipsec_mb/pmd_kasumi.c b/drivers/crypto/ipsec_mb/pmd_kasumi.c
deleted file mode 100644
index f83539232d..0000000000
--- a/drivers/crypto/ipsec_mb/pmd_kasumi.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2016-2021 Intel Corporation
- */
-
-#include <bus_vdev_driver.h>
-#include <rte_common.h>
-#include <rte_cpuflags.h>
-#include <rte_cryptodev.h>
-#include <rte_hexdump.h>
-#include <rte_malloc.h>
-
-#include "pmd_kasumi_priv.h"
-#include "pmd_aesni_mb_priv.h"
-
-struct rte_cryptodev_ops kasumi_pmd_ops = {
- .dev_configure = ipsec_mb_config,
- .dev_start = ipsec_mb_start,
- .dev_stop = ipsec_mb_stop,
- .dev_close = ipsec_mb_close,
-
- .stats_get = ipsec_mb_stats_get,
- .stats_reset = ipsec_mb_stats_reset,
-
- .dev_infos_get = ipsec_mb_info_get,
-
- .queue_pair_setup = ipsec_mb_qp_setup,
- .queue_pair_release = ipsec_mb_qp_release,
-
- .sym_session_get_size = ipsec_mb_sym_session_get_size,
- .sym_session_configure = ipsec_mb_sym_session_configure,
- .sym_session_clear = ipsec_mb_sym_session_clear
-};
-
-struct rte_cryptodev_ops *rte_kasumi_pmd_ops = &kasumi_pmd_ops;
-
-static int
-kasumi_probe(struct rte_vdev_device *vdev)
-{
- return ipsec_mb_create(vdev, IPSEC_MB_PMD_TYPE_KASUMI);
-}
-
-static struct rte_vdev_driver cryptodev_kasumi_pmd_drv = {
- .probe = kasumi_probe,
- .remove = ipsec_mb_remove
-};
-
-static struct cryptodev_driver kasumi_crypto_drv;
-
-RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_KASUMI_PMD, cryptodev_kasumi_pmd_drv);
-RTE_PMD_REGISTER_ALIAS(CRYPTODEV_NAME_KASUMI_PMD, cryptodev_kasumi_pmd);
-RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_KASUMI_PMD,
- "max_nb_queue_pairs=<int> socket_id=<int>");
-RTE_PMD_REGISTER_CRYPTO_DRIVER(kasumi_crypto_drv,
- cryptodev_kasumi_pmd_drv.driver,
- pmd_driver_id_kasumi);
-
-/* Constructor function to register kasumi PMD */
-RTE_INIT(ipsec_mb_register_kasumi)
-{
- struct ipsec_mb_internals *kasumi_data
- = &ipsec_mb_pmds[IPSEC_MB_PMD_TYPE_KASUMI];
-
- kasumi_data->caps = kasumi_capabilities;
- kasumi_data->dequeue_burst = aesni_mb_dequeue_burst;
- kasumi_data->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO
- | RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING
- | RTE_CRYPTODEV_FF_NON_BYTE_ALIGNED_DATA
- | RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT
- | RTE_CRYPTODEV_FF_SYM_SESSIONLESS
- | RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT;
- kasumi_data->internals_priv_size = 0;
- kasumi_data->ops = &kasumi_pmd_ops;
- kasumi_data->qp_priv_size = sizeof(struct aesni_mb_qp_data);
- kasumi_data->session_configure = aesni_mb_session_configure;
- kasumi_data->session_priv_size = sizeof(struct aesni_mb_session);
-}
diff --git a/drivers/crypto/ipsec_mb/pmd_kasumi_priv.h b/drivers/crypto/ipsec_mb/pmd_kasumi_priv.h
deleted file mode 100644
index 3223cf1a14..0000000000
--- a/drivers/crypto/ipsec_mb/pmd_kasumi_priv.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2016-2021 Intel Corporation
- */
-
-#ifndef _PMD_KASUMI_PRIV_H_
-#define _PMD_KASUMI_PRIV_H_
-
-#include "ipsec_mb_private.h"
-
-#define KASUMI_KEY_LENGTH 16
-#define KASUMI_IV_LENGTH 8
-#define KASUMI_DIGEST_LENGTH 4
-
-uint8_t pmd_driver_id_kasumi;
-
-static const struct rte_cryptodev_capabilities kasumi_capabilities[] = {
- { /* KASUMI (F9) */
- .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
- {.sym = {
- .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
- {.auth = {
- .algo = RTE_CRYPTO_AUTH_KASUMI_F9,
- .block_size = 8,
- .key_size = {
- .min = KASUMI_KEY_LENGTH,
- .max = KASUMI_KEY_LENGTH,
- .increment = 0
- },
- .digest_size = {
- .min = KASUMI_DIGEST_LENGTH,
- .max = KASUMI_DIGEST_LENGTH,
- .increment = 0
- },
- .iv_size = { 0 }
- }, }
- }, }
- },
- { /* KASUMI (F8) */
- .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
- {.sym = {
- .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
- {.cipher = {
- .algo = RTE_CRYPTO_CIPHER_KASUMI_F8,
- .block_size = 8,
- .key_size = {
- .min = KASUMI_KEY_LENGTH,
- .max = KASUMI_KEY_LENGTH,
- .increment = 0
- },
- .iv_size = {
- .min = KASUMI_IV_LENGTH,
- .max = KASUMI_IV_LENGTH,
- .increment = 0
- }
- }, }
- }, }
- },
- RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
-};
-
-#endif /* _PMD_KASUMI_PRIV_H_ */
--
2.52.0
^ permalink raw reply related
* Re: [PATCH v2 4/5] eal: fix async IPC resource leaks on partial failure
From: Burakov, Anatoly @ 2026-06-03 8:28 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: dev, Jianfeng Tan
In-Reply-To: <68rC0bdETzqwIkoItqSb_Q@monjalon.net>
On 6/1/2026 2:16 PM, Thomas Monjalon wrote:
> 29/05/2026 17:26, Anatoly Burakov:
>> Use a numeric request ID for alarm callback lookup so stale callbacks
>> from rolled-back requests become harmless no-ops.
> [...]
>> +static struct pending_request *
>> +find_pending_request_by_id(unsigned long id)
>> +{
>> + struct pending_request *r;
>> +
>> + TAILQ_FOREACH(r, &pending_requests.requests, next) {
>> + if (r->id == id)
>> + return r;
>> + }
>> +
>> + return NULL;
>> +}
>
> This function is supposed to find only async requests?
> What will happen if id wraparound and becomes 0,
> matching sync requests?
>
> I feel we should filter with r->type == REQUEST_TYPE_ASYNC
>
>
I mean it could happen if you submit `unsigned long` worth of IPC
requests, but I didn't think it was a problem that needed solving. But
sure, we can add an additional check.
--
Thanks,
Anatoly
^ permalink raw reply
* [PATCH v3] ethdev: support inline calculating masked item value
From: Bing Zhao @ 2026-06-03 8:19 UTC (permalink / raw)
To: viacheslavo, dev, rasland, stephen
Cc: orika, dsosnowski, suanmingm, matan, thomas
In-Reply-To: <20260213133143.22120-1-bingz@nvidia.com>
In the asynchronous API definition and some drivers, the
rte_flow_item spec value may not be calculated by the driver due to the
reason of speed of light rule insertion rate and sometimes the input
parameters will be copied and changed internally.
After copying, the spec and last will be protected by the keyword
const and cannot be changed in the code itself. And also the driver
needs some extra memory to do the calculation and extra conditions
to understand the length of each item spec. This is not efficient.
To solve the issue and support usage of the following fix, a new OP
was introduced to calculate the spec and last values after applying
the mask inline.
Signed-off-by: Bing Zhao <bingz@nvidia.com>
---
v3:
- add test code
- fix the issue found by AI
---
app/test/test_ethdev_api.c | 76 ++++++++++++++++++++++++++
doc/guides/rel_notes/release_26_07.rst | 6 ++
lib/ethdev/rte_flow.c | 46 ++++++++++++++--
lib/ethdev/rte_flow.h | 13 +++++
4 files changed, 135 insertions(+), 6 deletions(-)
diff --git a/app/test/test_ethdev_api.c b/app/test/test_ethdev_api.c
index 76afd0345c..5cae1cdc1d 100644
--- a/app/test/test_ethdev_api.c
+++ b/app/test/test_ethdev_api.c
@@ -4,6 +4,7 @@
#include <rte_log.h>
#include <rte_ethdev.h>
+#include <rte_flow.h>
#include <rte_test.h>
#include "test.h"
@@ -15,6 +16,80 @@
#define NUM_MBUF 1024
#define MBUF_CACHE_SIZE 256
+static int32_t
+ethdev_api_flow_conv_pattern_masked(void)
+{
+ const struct rte_flow_item_eth spec = {
+ .hdr.dst_addr.addr_bytes = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 },
+ .hdr.src_addr.addr_bytes = { 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ .hdr.ether_type = RTE_BE16(0x1234),
+ };
+ const struct rte_flow_item_eth last = {
+ .hdr.dst_addr.addr_bytes = { 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 },
+ .hdr.src_addr.addr_bytes = { 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+ .hdr.ether_type = RTE_BE16(0x5678),
+ };
+ const struct rte_flow_item_eth mask = {
+ .hdr.dst_addr.addr_bytes = { 0xff, 0xff, 0x00, 0x00, 0xff, 0xff },
+ .hdr.src_addr.addr_bytes = { 0xff, 0x00, 0xff, 0x00, 0xff, 0x00 },
+ .hdr.ether_type = RTE_BE16(0xffff),
+ };
+ const struct rte_flow_item pattern[] = {
+ {
+ .type = RTE_FLOW_ITEM_TYPE_ETH,
+ .spec = &spec,
+ .last = &last,
+ .mask = &mask,
+ },
+ { .type = RTE_FLOW_ITEM_TYPE_END },
+ };
+ union {
+ struct rte_flow_item item;
+ struct rte_flow_item_eth eth;
+ double align;
+ uint8_t raw[256];
+ } dst;
+ const struct rte_flow_item *item;
+ const struct rte_flow_item_eth *conv_spec;
+ const struct rte_flow_item_eth *conv_last;
+ int ret;
+
+ ret = rte_flow_conv(RTE_FLOW_CONV_OP_PATTERN_MASKED, NULL, 0, pattern, NULL);
+ TEST_ASSERT(ret > 0, "Masked pattern conversion size query failed");
+ TEST_ASSERT((size_t)ret <= sizeof(dst.raw),
+ "Masked pattern conversion needs too much storage");
+
+ memset(&dst, 0, sizeof(dst));
+ ret = rte_flow_conv(RTE_FLOW_CONV_OP_PATTERN_MASKED, dst.raw,
+ sizeof(dst.raw), pattern, NULL);
+ TEST_ASSERT(ret > 0, "Masked pattern conversion failed");
+
+ item = (const struct rte_flow_item *)dst.raw;
+ conv_spec = item[0].spec;
+ conv_last = item[0].last;
+ TEST_ASSERT_NOT_NULL(conv_spec, "Converted spec must be set");
+ TEST_ASSERT_NOT_NULL(conv_last, "Converted last must be set");
+
+ TEST_ASSERT_EQUAL(conv_spec->hdr.dst_addr.addr_bytes[0], 0x01,
+ "Masked spec dst byte 0 mismatch");
+ TEST_ASSERT_EQUAL(conv_spec->hdr.dst_addr.addr_bytes[2], 0x00,
+ "Masked spec dst byte 2 mismatch");
+ TEST_ASSERT_EQUAL(conv_spec->hdr.src_addr.addr_bytes[1], 0x00,
+ "Masked spec src byte 1 mismatch");
+ TEST_ASSERT_EQUAL(conv_spec->hdr.ether_type, RTE_BE16(0x1234),
+ "Masked spec ether type mismatch");
+ TEST_ASSERT_EQUAL(conv_last->hdr.dst_addr.addr_bytes[0], 0x11,
+ "Masked last dst byte 0 mismatch");
+ TEST_ASSERT_EQUAL(conv_last->hdr.dst_addr.addr_bytes[2], 0x00,
+ "Masked last dst byte 2 mismatch");
+ TEST_ASSERT_EQUAL(conv_last->hdr.src_addr.addr_bytes[1], 0x00,
+ "Masked last src byte 1 mismatch");
+ TEST_ASSERT_EQUAL(conv_last->hdr.ether_type, RTE_BE16(0x5678),
+ "Masked last ether type mismatch");
+
+ return TEST_SUCCESS;
+}
+
static int32_t
ethdev_api_queue_status(void)
{
@@ -167,6 +242,7 @@ static struct unit_test_suite ethdev_api_testsuite = {
.setup = NULL,
.teardown = NULL,
.unit_test_cases = {
+ TEST_CASE(ethdev_api_flow_conv_pattern_masked),
TEST_CASE(ethdev_api_queue_status),
/* TODO: Add deferred_start queue status test */
TEST_CASES_END() /**< NULL terminate unit test array */
diff --git a/doc/guides/rel_notes/release_26_07.rst b/doc/guides/rel_notes/release_26_07.rst
index 8b4f8401e2..46a83cfea5 100644
--- a/doc/guides/rel_notes/release_26_07.rst
+++ b/doc/guides/rel_notes/release_26_07.rst
@@ -116,6 +116,12 @@ API Changes
Also, make sure to start the actual text at the margin.
=======================================================
+* ethdev: Added masked pattern conversion.
+
+ Added ``RTE_FLOW_CONV_OP_PATTERN_MASKED`` to ``rte_flow_conv()``
+ to copy an entire pattern while applying each item's mask to its
+ ``spec`` and ``last`` fields.
+
ABI Changes
-----------
diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
index 7a51b667cf..7cf9f6f6f3 100644
--- a/lib/ethdev/rte_flow.c
+++ b/lib/ethdev/rte_flow.c
@@ -178,6 +178,14 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = {
MK_FLOW_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
};
+static inline size_t
+rte_flow_conv_item_mask_size(const struct rte_flow_item *item)
+{
+ if ((int)item->type >= 0)
+ return rte_flow_desc_item[item->type].size;
+ return sizeof(void *);
+}
+
/** Generate flow_action[] entry. */
#define MK_FLOW_ACTION(t, s) \
[RTE_FLOW_ACTION_TYPE_ ## t] = { \
@@ -835,6 +843,8 @@ rte_flow_conv_action_conf(void *buf, const size_t size,
* RTE_FLOW_ITEM_TYPE_END is encountered.
* @param[out] error
* Perform verbose error reporting if not NULL.
+ * @param[in] with_mask
+ * If true, @p src mask will be applied to spec and last.
*
* @return
* A positive value representing the number of bytes needed to store
@@ -847,12 +857,13 @@ rte_flow_conv_pattern(struct rte_flow_item *dst,
const size_t size,
const struct rte_flow_item *src,
unsigned int num,
+ bool with_mask,
struct rte_flow_error *error)
{
uintptr_t data = (uintptr_t)dst;
size_t off;
size_t ret;
- unsigned int i;
+ unsigned int i, j;
for (i = 0, off = 0; !num || i != num; ++i, ++src, ++dst) {
/**
@@ -876,15 +887,27 @@ rte_flow_conv_pattern(struct rte_flow_item *dst,
src -= num;
dst -= num;
do {
+ uint8_t *c_spec = NULL, *c_last = NULL;
+ const uint8_t *mask = src->mask;
+ size_t item_mask_size = mask ? rte_flow_conv_item_mask_size(src) : 0;
+
if (src->spec) {
off = RTE_ALIGN_CEIL(off, sizeof(double));
ret = rte_flow_conv_item_spec
((void *)(data + off),
size > off ? size - off : 0, src,
RTE_FLOW_CONV_ITEM_SPEC);
- if (size && size >= off + ret)
+ if (size && size >= off + ret) {
dst->spec = (void *)(data + off);
+ c_spec = (uint8_t *)(data + off);
+ }
off += ret;
+ if (with_mask && c_spec && mask) {
+ size_t mask_size = RTE_MIN(ret, item_mask_size);
+
+ for (j = 0; j < mask_size; j++)
+ c_spec[j] &= mask[j];
+ }
}
if (src->last) {
@@ -893,9 +916,17 @@ rte_flow_conv_pattern(struct rte_flow_item *dst,
((void *)(data + off),
size > off ? size - off : 0, src,
RTE_FLOW_CONV_ITEM_LAST);
- if (size && size >= off + ret)
+ if (size && size >= off + ret) {
dst->last = (void *)(data + off);
+ c_last = (uint8_t *)(data + off);
+ }
off += ret;
+ if (with_mask && c_last && mask) {
+ size_t mask_size = RTE_MIN(ret, item_mask_size);
+
+ for (j = 0; j < mask_size; j++)
+ c_last[j] &= mask[j];
+ }
}
if (src->mask) {
off = RTE_ALIGN_CEIL(off, sizeof(double));
@@ -1042,7 +1073,7 @@ rte_flow_conv_rule(struct rte_flow_conv_rule *dst,
off = RTE_ALIGN_CEIL(off, sizeof(double));
ret = rte_flow_conv_pattern((void *)((uintptr_t)dst + off),
size > off ? size - off : 0,
- src->pattern_ro, 0, error);
+ src->pattern_ro, 0, false, error);
if (ret < 0)
return ret;
if (size && size >= off + (size_t)ret)
@@ -1143,7 +1174,7 @@ rte_flow_conv(enum rte_flow_conv_op op,
ret = sizeof(*attr);
break;
case RTE_FLOW_CONV_OP_ITEM:
- ret = rte_flow_conv_pattern(dst, size, src, 1, error);
+ ret = rte_flow_conv_pattern(dst, size, src, 1, false, error);
break;
case RTE_FLOW_CONV_OP_ITEM_MASK:
item = src;
@@ -1158,7 +1189,7 @@ rte_flow_conv(enum rte_flow_conv_op op,
ret = rte_flow_conv_actions(dst, size, src, 1, error);
break;
case RTE_FLOW_CONV_OP_PATTERN:
- ret = rte_flow_conv_pattern(dst, size, src, 0, error);
+ ret = rte_flow_conv_pattern(dst, size, src, 0, false, error);
break;
case RTE_FLOW_CONV_OP_ACTIONS:
ret = rte_flow_conv_actions(dst, size, src, 0, error);
@@ -1178,6 +1209,9 @@ rte_flow_conv(enum rte_flow_conv_op op,
case RTE_FLOW_CONV_OP_ACTION_NAME_PTR:
ret = rte_flow_conv_name(1, 1, dst, size, src, error);
break;
+ case RTE_FLOW_CONV_OP_PATTERN_MASKED:
+ ret = rte_flow_conv_pattern(dst, size, src, 0, true, error);
+ break;
default:
ret = rte_flow_error_set
(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
index ba3bcc89a3..f3102f4bb0 100644
--- a/lib/ethdev/rte_flow.h
+++ b/lib/ethdev/rte_flow.h
@@ -4558,6 +4558,19 @@ enum rte_flow_conv_op {
* @code const char ** @endcode
*/
RTE_FLOW_CONV_OP_ACTION_NAME_PTR,
+
+ /**
+ * Convert an entire pattern.
+ *
+ * Duplicates all pattern items at once, applying @p mask to @p spec
+ * and @p last.
+ *
+ * - @p src type:
+ * @code const struct rte_flow_item * @endcode
+ * - @p dst type:
+ * @code struct rte_flow_item * @endcode
+ */
+ RTE_FLOW_CONV_OP_PATTERN_MASKED,
};
/**
--
2.34.1
^ permalink raw reply related
* RE: [PATCH v2] app/test-pmd: add generic PROG action parser support
From: Konstantin Ananyev @ 2026-06-03 6:53 UTC (permalink / raw)
To: Ajmera, Megha, Stephen Hemminger
Cc: Richardson, Bruce, Dumitrescu, Cristian, Shetty, Praveen,
Singh, Aman Deep, dev@dpdk.org
In-Reply-To: <MW4PR11MB589283F734826ED3A83EBC9B97122@MW4PR11MB5892.namprd11.prod.outlook.com>
> > Ok, so it is predefined by the FW.
> > Then shouldn't CPFL PG contain a list of supported PROGs and their arguments?
> > Again, some tests/examples for it with testpmd/DTS.
> > Or that's all will be the next step (patch-series)?
> >
> For now, this can be independent patch since it only enable parsing in test-pmd.
> With this change one can use and test PROG actions for PMDs.
Well, right now there is simply no way for the user to test/try this functionality.
Usual requirement for introducing new HW/SW feature for DPDK:
1) provide at least one implementation (exist, cpfl)
2) provide some test cases for it (app/test-pmd, app/test, ...)
3) document it properly - what prog/args are supported for each HW, etc.
#2 and #3 are missing completely - which means that for DPDK community
that functionality is sort of dead code.
TBH, I think it shouldn't be accepted at all at first place in such incomplete stage.
Konstantin
^ permalink raw reply
* [PATCH v8 14/20] net/sxe2: implement get monitor address
From: liujie5 @ 2026-06-03 6:29 UTC (permalink / raw)
To: stephen; +Cc: dev, Jie Liu
In-Reply-To: <20260603062945.1253672-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 215ae772b5..45e245740b 100644
--- a/drivers/net/sxe2/sxe2_ethdev.c
+++ b/drivers/net/sxe2/sxe2_ethdev.c
@@ -184,6 +184,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 v8 12/20] net/sxe2: add support for custom UDP tunnel ports
From: liujie5 @ 2026-06-03 6:29 UTC (permalink / raw)
To: stephen; +Cc: dev, Jie Liu
In-Reply-To: <20260603062945.1253672-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 | 206 ++++++++++++++++++++-
drivers/net/sxe2/sxe2_ethdev.h | 12 ++
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, 566 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 9db8cb1ad1..9b18365cb8 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 317101fb60..14c8f6c16d 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
@@ -115,6 +116,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,
@@ -162,6 +168,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,
@@ -226,6 +235,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.");
@@ -271,6 +286,188 @@ 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;
+}
+
+int32_t sxe2_udp_tunnel_port_get_common(struct sxe2_adapter *ad,
+ struct sxe2_udp_tunnel_cfg *tunnel_config)
+{
+ return sxe2_drv_udp_tunnel_get(ad, tunnel_config);
+}
+
+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)
{
@@ -1300,15 +1497,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 ca4e23f5a8..32efa893d1 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;
@@ -374,6 +375,17 @@ 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_get_common(struct sxe2_adapter *ad,
+ struct sxe2_udp_tunnel_cfg *tunnel_config);
+
+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 v8 15/20] common/sxe2: add shared SFP module definitions
From: liujie5 @ 2026-06-03 6:29 UTC (permalink / raw)
To: stephen; +Cc: dev, Jie Liu
In-Reply-To: <20260603062945.1253672-1-liujie5@linkdatatechnology.com>
From: Jie Liu <liujie5@linkdatatechnology.com>
This patch adds a new shared header file 'sxe2_msg.h' which
contains definitions for SFP/SFP+ modules. This file is shared across
Firmware, Kernel driver, and DPDK PMD to ensure consistent protocol
handling.
The header includes:
- SFP EEPROM memory map offsets.
- Module type encoding definitions.
By using this shared header, the PMD can correctly identify module
capabilities and report diagnostic information in a way that is
consistent with the underlying firmware logic.
Signed-off-by: Jie Liu <liujie5@linkdatatechnology.com>
---
drivers/common/sxe2/sxe2_msg.h | 118 +++++++++++++++++++++++++++++++++
1 file changed, 118 insertions(+)
create mode 100644 drivers/common/sxe2/sxe2_msg.h
diff --git a/drivers/common/sxe2/sxe2_msg.h b/drivers/common/sxe2/sxe2_msg.h
new file mode 100644
index 0000000000..f08944f7c9
--- /dev/null
+++ b/drivers/common/sxe2/sxe2_msg.h
@@ -0,0 +1,118 @@
+
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#ifndef __SXE2_MSG_H__
+#define __SXE2_MSG_H__
+
+enum sfp_type_identifier {
+ SXE2_SFP_TYPE_UNKNOWN = 0x00,
+ SXE2_SFP_TYPE_SFP = 0x03,
+
+ SXE2_SFP_TYPE_QSFP_PLUS = 0x0D,
+ SXE2_SFP_TYPE_QSFP28 = 0x11,
+
+ SXE2_SFP_TYPE_MAX = 0xFF,
+};
+
+#ifndef SFP_DEFINE
+#define SFP_DEFINE
+
+#define SXE2_SFP_EEP_WR 0x1
+#define SXE2_SFP_EEP_QSFP 0x1
+
+enum sfp_bus_addr {
+ SXE2_SFP_EEP_I2C_ADDR0 = 0xA0,
+ SXE2_SFP_EEP_I2C_ADDR1 = 0xA2,
+ SXE2_SFP_EEP_I2C_ADDR_NR = 0xFFFF,
+};
+
+struct sxe2_sfp_req {
+ uint8_t is_wr;
+ uint8_t is_qsfp;
+ uint16_t bus_addr;
+ uint16_t page_cnt;
+ uint16_t offset;
+ uint16_t data_len;
+ uint16_t rvd;
+ uint8_t data[];
+};
+
+struct sxe2_sfp_resp {
+ uint8_t is_wr;
+ uint8_t is_qsfp;
+ uint16_t data_len;
+ uint8_t data[];
+};
+
+enum sfp_page_cnt {
+ SXE2_SFP_EEP_PAGE_CNT0 = 0,
+ SXE2_SFP_EEP_PAGE_CNT1,
+ SXE2_SFP_EEP_PAGE_CNT2,
+ SXE2_SFP_EEP_PAGE_CNT3,
+ SXE2_SFP_EEP_PAGE_CNT20 = 20,
+ SXE2_SFP_EEP_PAGE_CNT21 = 21,
+
+ SXE2_SFP_EEP_PAGE_CNT_NR = 0xFFFF,
+};
+
+#define SXE2_SFP_E2P_I2C_7BIT_ADDR0 (SXE2_SFP_EEP_I2C_ADDR0 >> 1)
+#define SXE2_SFP_E2P_I2C_7BIT_ADDR1 (SXE2_SFP_EEP_I2C_ADDR1 >> 1)
+
+#define SXE2_QSFP_PAGE_OFST_START 128
+#define SXE2_SFP_EEP_OFST_MAX 255
+#define SXE2_SFP_EEP_LEN_MAX 256
+#endif
+
+#ifndef FW_STATE_DEFINE
+#define FW_STATE_DEFINE
+
+#define SXE2_FW_STATUS_MAIN_SHIF (16)
+#define SXE2_FW_STATUS_MAIN_MASK (0xFF0000)
+#define SXE2_FW_STATUS_SUB_MASK (0xFFFF)
+
+enum Sxe2FwStateMain {
+ SXE2_FW_STATE_MAIN_UNDEFINED = 0x00,
+ SXE2_FW_STATE_MAIN_INIT = 0x10000,
+ SXE2_FW_STATE_MAIN_RUN = 0x20000,
+ SXE2_FW_STATE_MAIN_ABNOMAL = 0x30000,
+};
+
+enum Sxe2FwState {
+ SXE2_FW_START_STATE_UNDEFINED = SXE2_FW_STATE_MAIN_UNDEFINED,
+ SXE2_FW_START_STATE_INIT_BASE = (SXE2_FW_STATE_MAIN_INIT + 0x1),
+ SXE2_FW_START_STATE_SCAN_DEVICE = (SXE2_FW_STATE_MAIN_INIT + 0x20),
+ SXE2_FW_START_STATE_FINISHED = (SXE2_FW_STATE_MAIN_RUN + 0x0),
+ SXE2_FW_START_STATE_UPGRADE = (SXE2_FW_STATE_MAIN_RUN + 0x1),
+ SXE2_FW_START_STATE_SYNC = (SXE2_FW_STATE_MAIN_RUN + 0x2),
+ SXE2_FW_RUNNING_STATE_ABNOMAL = (SXE2_FW_STATE_MAIN_ABNOMAL + 0x1),
+ SXE2_FW_RUNNING_STATE_ABNOMAL_CORE1 = (SXE2_FW_STATE_MAIN_ABNOMAL + 0x2),
+ SXE2_FW_RUNNING_STATE_ABNOMAL_HEART = (SXE2_FW_STATE_MAIN_ABNOMAL + 0x3),
+ SXE2_FW_START_STATE_MASK = (SXE2_FW_STATUS_MAIN_MASK | SXE2_FW_STATUS_SUB_MASK),
+};
+#endif
+
+#ifndef LED_DEFINE
+#define LED_DEFINE
+
+enum sxe2_led_mode {
+ SXE2_IDENTIFY_LED_BLINK_ON = 0,
+ SXE2_IDENTIFY_LED_BLINK_OFF,
+ SXE2_IDENTIFY_LED_ON,
+ SXE2_IDENTIFY_LED_OFF,
+ SXE2_IDENTIFY_LED_RESET,
+};
+
+
+typedef struct sxe2_led_ctrl {
+ uint32_t mode;
+ uint32_t duration;
+} sxe2_led_ctrl_s;
+
+typedef struct sxe2_led_ctrl_resp {
+ uint32_t ack;
+} sxe2_led_ctrl_resp_s;
+#endif
+
+#endif /* __SXE2_MSG_H__ */
--
2.52.0
^ permalink raw reply related
* [PATCH v8 05/20] drivers: support RSS feature
From: liujie5 @ 2026-06-03 6:29 UTC (permalink / raw)
To: stephen; +Cc: dev, Jie Liu
In-Reply-To: <20260603062945.1253672-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 6399f22c5c..b644b205c5 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 9b117f097e..d48841b8e4 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 34a4a45e4f..3955788634 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 v8 19/20] drivers: add testpmd commands for private features
From: liujie5 @ 2026-06-03 6:29 UTC (permalink / raw)
To: stephen; +Cc: dev, Jie Liu
In-Reply-To: <20260603062945.1253672-1-liujie5@linkdatatechnology.com>
From: Jie Liu <liujie5@linkdatatechnology.com>
Introduce private testpmd commands and implementation files to enable
debugging and testing of sxe2-specific hardware features (such as
packet scheduling reset, UDP tunnel configuration, and IPsec ingress/
egress offloads) directly within the testpmd application.
The parameters are parsed using the standard 'rte_kvargs' library during
the PCI/vdev probing phase. Documentation for these parameters is also
updated.
During memory hotplug events, the SXE2 driver needs to track memory
segment layout changes to maintain internal DMA mappings. However,
existing memseg walk functions (rte_memseg_walk) acquire memory locks
and cannot be called from within memory event callbacks, leading to
potential deadlocks.
This commit introduces sxe2_memseg_walk_cb() as a helper that walks
memory segments using the thread-unsafe variant
rte_memseg_walk_thread_unsafe(), which is safe to call from
memory-related callbacks [citation:1][citation:3][citation:5].
The implementation follows the standard rte_memseg_walk_t prototype,
processing each memseg to update driver-specific data structures.
Signed-off-by: Jie Liu <liujie5@linkdatatechnology.com>
---
drivers/common/sxe2/sxe2_common.c | 110 +++
drivers/common/sxe2/sxe2_common.h | 2 +
drivers/common/sxe2/sxe2_ioctl_chnl.c | 2 +-
drivers/net/sxe2/meson.build | 5 +-
drivers/net/sxe2/sxe2_cmd_chnl.c | 21 +
drivers/net/sxe2/sxe2_cmd_chnl.h | 3 +
drivers/net/sxe2/sxe2_drv_cmd.h | 17 +
drivers/net/sxe2/sxe2_dump.c | 15 +
drivers/net/sxe2/sxe2_ethdev.c | 287 +++++++-
drivers/net/sxe2/sxe2_ethdev.h | 8 +
drivers/net/sxe2/sxe2_irq.c | 29 +
drivers/net/sxe2/sxe2_rx.c | 12 +
drivers/net/sxe2/sxe2_testpmd.c | 733 +++++++++++++++++++
drivers/net/sxe2/sxe2_testpmd_lib.c | 969 ++++++++++++++++++++++++++
drivers/net/sxe2/sxe2_testpmd_lib.h | 142 ++++
drivers/net/sxe2/sxe2_tm.c | 18 +
drivers/net/sxe2/sxe2_tm.h | 2 +
17 files changed, 2371 insertions(+), 4 deletions(-)
create mode 100644 drivers/net/sxe2/sxe2_testpmd.c
create mode 100644 drivers/net/sxe2/sxe2_testpmd_lib.c
create mode 100644 drivers/net/sxe2/sxe2_testpmd_lib.h
diff --git a/drivers/common/sxe2/sxe2_common.c b/drivers/common/sxe2/sxe2_common.c
index a5d36998e1..5e6e13dd19 100644
--- a/drivers/common/sxe2/sxe2_common.c
+++ b/drivers/common/sxe2/sxe2_common.c
@@ -196,6 +196,102 @@ static int32_t sxe2_parse_representor(const char *key, const char *value, void *
PMD_LOG_INFO(COM, "representor arg %s: \"%s\".", key, value);
+l_end:
+ return ret;
+}
+static int32_t sxe2_dma_mem_map(struct sxe2_common_device *cdev,
+ const void *addr, size_t len, bool do_map)
+{
+ struct rte_memseg_list *msl;
+ struct rte_memseg *ms;
+ size_t cur_len = 0;
+ int32_t ret = 0;
+
+ msl = rte_mem_virt2memseg_list(addr);
+ if (msl == NULL) {
+ ret = -EINVAL;
+ PMD_LOG_ERR(COM, "Invalid virt addr=%p.", addr);
+ goto l_end;
+ }
+
+ if ((uintptr_t)addr != RTE_ALIGN((uintptr_t)addr, msl->page_sz) ||
+ (len != RTE_ALIGN(len, msl->page_sz))) {
+ ret = -EINVAL;
+ PMD_LOG_ERR(COM, "Addr=%p and len=%zu not align page size=%" PRIu64 ".",
+ addr, len, msl->page_sz);
+ goto l_end;
+ }
+
+ /* memsegs are contiguous in memory */
+ ms = rte_mem_virt2memseg(addr, msl);
+ while (cur_len < len) {
+ /* some memory segments may have invalid IOVA */
+ if (ms->iova == RTE_BAD_IOVA) {
+ PMD_LOG_WARN(COM, "Memory segment at %p has bad IOVA, skipping.",
+ ms->addr);
+ goto next;
+ }
+ if (do_map)
+ sxe2_drv_dev_dma_map(cdev, ms->addr_64,
+ ms->iova, ms->len);
+ else
+ sxe2_drv_dev_dma_unmap(cdev, ms->iova);
+
+next:
+ cur_len += ms->len;
+ ++ms;
+ }
+
+l_end:
+ return ret;
+}
+
+RTE_EXPORT_INTERNAL_SYMBOL(sxe2_common_mem_event_cb)
+void
+sxe2_common_mem_event_cb(enum rte_mem_event type,
+ const void *addr, size_t size, void *arg __rte_unused)
+{
+ struct sxe2_common_device *cdev = NULL;
+
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+ goto l_end;
+
+ pthread_mutex_lock(&sxe2_common_devices_list_lock);
+ switch (type) {
+ case RTE_MEM_EVENT_FREE:
+ TAILQ_FOREACH(cdev, &sxe2_common_devices_list, next)
+ (void)sxe2_dma_mem_map(cdev, addr, size, 0);
+ break;
+ case RTE_MEM_EVENT_ALLOC:
+ TAILQ_FOREACH(cdev, &sxe2_common_devices_list, next)
+ (void)sxe2_dma_mem_map(cdev, addr, size, 1);
+ break;
+ default:
+ break;
+ }
+ pthread_mutex_unlock(&sxe2_common_devices_list_lock);
+l_end:
+ return;
+}
+
+static int32_t sxe2_memseg_walk_cb(const struct rte_memseg_list *msl,
+ const struct rte_memseg *ms, void *arg)
+{
+ struct sxe2_common_device *cdev = arg;
+ int32_t ret = 0;
+
+ if (msl->external && !msl->heap)
+ goto l_end;
+
+ if (ms->iova == RTE_BAD_IOVA)
+ goto l_end;
+
+ ret = sxe2_drv_dev_dma_map(cdev, ms->addr_64, ms->iova, ms->len);
+ if (ret != 0) {
+ PMD_LOG_ERR(COM, "Fail to memseg dma map.");
+ goto l_end;
+ }
+
l_end:
return ret;
}
@@ -220,6 +316,18 @@ static int32_t sxe2_common_device_setup(struct sxe2_common_device *cdev)
goto l_close_dev;
}
+ rte_mcfg_mem_read_lock();
+ ret = rte_memseg_walk_thread_unsafe(sxe2_memseg_walk_cb, cdev);
+ if (ret) {
+ PMD_LOG_ERR(COM, "Fail to walk memseg, ret=%d", ret);
+ rte_mcfg_mem_read_unlock();
+ goto l_close_dev;
+ }
+ rte_mcfg_mem_read_unlock();
+
+ (void)rte_mem_event_callback_register("SXE2_MEM_EVENT_CB",
+ sxe2_common_mem_event_cb, NULL);
+
goto l_end;
l_close_dev:
@@ -251,6 +359,7 @@ static struct sxe2_common_device *sxe2_common_device_alloc(
}
cdev->dev = rte_dev;
cdev->class_type = class_type;
+ cdev->config.cmd_fd = SXE2_CMD_FD_INVALID;
cdev->config.kernel_reset = false;
pthread_mutex_init(&cdev->config.lock, NULL);
@@ -631,6 +740,7 @@ static int32_t sxe2_common_pci_id_table_update(const struct rte_pci_id *id_table
updated_table = calloc(num_ids, sizeof(*updated_table));
if (!updated_table) {
+ ret = -ENOMEM;
PMD_LOG_ERR(COM, "Failed to allocate memory for PCI ID table");
goto l_end;
}
diff --git a/drivers/common/sxe2/sxe2_common.h b/drivers/common/sxe2/sxe2_common.h
index b02b6317da..efc8d3585a 100644
--- a/drivers/common/sxe2/sxe2_common.h
+++ b/drivers/common/sxe2/sxe2_common.h
@@ -14,6 +14,8 @@
#define SXE2_COMMON_PCI_DRIVER_NAME "sxe2_pci"
+#define SXE2_CMD_FD_INVALID (-1)
+
#define SXE2_CDEV_TO_CMD_FD(cdev) \
((cdev)->config.cmd_fd)
diff --git a/drivers/common/sxe2/sxe2_ioctl_chnl.c b/drivers/common/sxe2/sxe2_ioctl_chnl.c
index 173d8d57ae..a233a78136 100644
--- a/drivers/common/sxe2/sxe2_ioctl_chnl.c
+++ b/drivers/common/sxe2/sxe2_ioctl_chnl.c
@@ -110,7 +110,7 @@ sxe2_drv_dev_close(struct sxe2_common_device *cdev)
if (fd >= 0)
close(fd);
PMD_LOG_INFO(COM, "closed device fd=%d", fd);
- SXE2_CDEV_TO_CMD_FD(cdev) = -1;
+ SXE2_CDEV_TO_CMD_FD(cdev) = SXE2_CMD_FD_INVALID;
}
RTE_EXPORT_INTERNAL_SYMBOL(sxe2_drv_dev_handshake)
diff --git a/drivers/net/sxe2/meson.build b/drivers/net/sxe2/meson.build
index 4fb2333926..04369402b7 100644
--- a/drivers/net/sxe2/meson.build
+++ b/drivers/net/sxe2/meson.build
@@ -9,9 +9,10 @@ endif
cflags += ['-g']
-deps += ['common_sxe2', 'hash','cryptodev','security']
+deps += ['common_sxe2', 'hash', 'cryptodev', 'security', 'cmdline']
includes += include_directories('../../common/sxe2')
+testpmd_sources = files('sxe2_testpmd.c')
if arch_subdir == 'x86'
sources += files('sxe2_txrx_vec_sse.c')
@@ -79,5 +80,5 @@ sources += files(
'sxe2_flow_parse_engine.c',
'sxe2_dump.c',
'sxe2_txrx_check_mbuf.c',
-
+ 'sxe2_testpmd_lib.c',
)
diff --git a/drivers/net/sxe2/sxe2_cmd_chnl.c b/drivers/net/sxe2/sxe2_cmd_chnl.c
index 43e8c59487..b09989fe50 100644
--- a/drivers/net/sxe2/sxe2_cmd_chnl.c
+++ b/drivers/net/sxe2/sxe2_cmd_chnl.c
@@ -99,6 +99,27 @@ int32_t sxe2_drv_dev_info_get(struct sxe2_adapter *adapter,
return ret;
}
+int32_t sxe2_drv_fc_state_get(struct sxe2_adapter *adapter,
+ struct sxe2_drv_vsi_fc_get_resp *dev_fc_state_resp)
+{
+ int32_t ret = 0;
+ struct sxe2_common_device *cdev = adapter->cdev;
+ struct sxe2_drv_cmd_params param = {0};
+ struct sxe2_drv_vsi_fc_get_req req = {0};
+
+ req.vsi_id = adapter->vsi_ctxt.main_vsi->vsi_id;
+ sxe2_drv_cmd_params_fill(adapter, ¶m, SXE2_DRV_CMD_VSI_FC_GET,
+ &req, sizeof(req),
+ dev_fc_state_resp,
+ sizeof(*dev_fc_state_resp));
+ ret = sxe2_drv_cmd_exec(cdev, ¶m);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, DRV, "get fc state failed, ret=%d", ret);
+ ret = -EIO;
+ }
+ return ret;
+}
+
int32_t sxe2_drv_dev_fw_info_get(struct sxe2_adapter *adapter,
struct sxe2_drv_dev_fw_info_resp *dev_fw_info_resp)
{
diff --git a/drivers/net/sxe2/sxe2_cmd_chnl.h b/drivers/net/sxe2/sxe2_cmd_chnl.h
index 988d4b458b..d63caad526 100644
--- a/drivers/net/sxe2/sxe2_cmd_chnl.h
+++ b/drivers/net/sxe2/sxe2_cmd_chnl.h
@@ -99,6 +99,9 @@ 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_fc_state_get(struct sxe2_adapter *adapter,
+ struct sxe2_drv_vsi_fc_get_resp *dev_fc_state_resp);
+
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);
diff --git a/drivers/net/sxe2/sxe2_drv_cmd.h b/drivers/net/sxe2/sxe2_drv_cmd.h
index bcb9fb4ff9..8aa443919b 100644
--- a/drivers/net/sxe2/sxe2_drv_cmd.h
+++ b/drivers/net/sxe2/sxe2_drv_cmd.h
@@ -651,6 +651,23 @@ struct __rte_aligned(4) __rte_packed_begin sxe2_drv_sfp_resp {
uint8_t data[];
} __rte_packed_end;
+enum sxe2_fc_type {
+ SXE2_FC_T_DIS = 0,
+ SXE2_FC_T_LFC,
+ SXE2_FC_T_PFC,
+ SXE2_FC_T_UNKNOWN = 255,
+};
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_vsi_fc_get_req {
+ uint16_t vsi_id;
+ uint8_t rsv[2];
+} __rte_packed_end;
+
+struct __rte_aligned(4) __rte_packed_begin sxe2_drv_vsi_fc_get_resp {
+ uint8_t fc_enable;
+ 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_dump.c b/drivers/net/sxe2/sxe2_dump.c
index 9898456aea..e2fbb9a384 100644
--- a/drivers/net/sxe2/sxe2_dump.c
+++ b/drivers/net/sxe2/sxe2_dump.c
@@ -188,6 +188,20 @@ static void sxe2_dump_filter_info(FILE *file, struct rte_eth_dev *dev)
return;
}
+static void sxe2_dump_fc_state(FILE *file, struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+
+ if (!(adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_FC_STATE))
+ goto l_end;
+
+ fprintf(file, " -- fc state:\n"
+ "\t -- curr_state: %u\n",
+ adapter->fc_state_ctx.curr_state);
+l_end:
+ return;
+}
+
static const char *sxe2_vsi_id_str(uint16_t vsi_id, char *buf, size_t len)
{
if (vsi_id == SXE2_INVALID_VSI_ID)
@@ -274,6 +288,7 @@ int32_t sxe2_eth_dev_priv_dump(struct rte_eth_dev *dev, FILE *file)
sxe2_dump_dev_args_info(str, dev);
sxe2_dump_filter_info(str, dev);
sxe2_dump_switchdev_info(str, dev);
+ sxe2_dump_fc_state(str, dev);
(void)fflush(str);
diff --git a/drivers/net/sxe2/sxe2_ethdev.c b/drivers/net/sxe2/sxe2_ethdev.c
index 73a92d99f8..702f84668c 100644
--- a/drivers/net/sxe2/sxe2_ethdev.c
+++ b/drivers/net/sxe2/sxe2_ethdev.c
@@ -68,7 +68,14 @@ static const struct rte_pci_id pci_id_sxe2_tbl[] = {
{ RTE_PCI_DEVICE(SXE2_PCI_VENDOR_ID_206F, SXE2_PCI_DEVICE_ID_VF_1)},
{ .vendor_id = 0, },
};
-
+#define SXE2_TXSCH_NODE_ADJ_LVL_MAX 3
+#define SXE2_DEVARG_FLOW_DULP_PATTERN_MODE "flow-duplicate-pattern"
+#define SXE2_DEVARG_FUNC_FLOW_DIRCT "function-flow-direct"
+#define SXE2_DEVARG_FNAV_STAT_TYPE "fnav-stat-type"
+#define SXE2_DEVARG_SW_STATS "drv-sw-stats"
+#define SXE2_DEVARG_HIGH_PERFORMANCE_MODE "high-performance-mode"
+#define SXE2_DEVARG_SCHED_LAYER_MODE "sched-layer-mode"
+#define SXE2_DEVARG_RX_LOW_LATENCY "rx-low-latency"
static struct sxe2_pci_map_addr_info sxe2_net_map_addr_info_pf[SXE2_PCI_MAP_RES_MAX_COUNT] = {
[SXE2_PCI_MAP_RES_INVALID] = {.addr_base = 0,
.bar_idx = 0,
@@ -980,6 +987,149 @@ static inline void sxe2_init_ptype_tbl(struct rte_eth_dev *dev)
sxe2_init_ptype_list(ptype);
}
+static int32_t sxe2_parse_fnav_stat_type(const char *key, const char *value, void *args)
+{
+ int32_t ret = -EINVAL;
+ uint8_t *num = (uint8_t *)args;
+ uint8_t fnav_stat_type = 0;
+ char *endptr = NULL;
+
+ if (value == NULL || args == NULL) {
+ ret = 0;
+ goto l_end;
+ }
+ errno = 0;
+ fnav_stat_type = (uint8_t)strtoul(value, &endptr, 10);
+ if (errno != 0 || *endptr != '\0') {
+ PMD_LOG_WARN(INIT, "%s: \"%s\" is not a valid int value.",
+ key, value);
+ goto l_end;
+ }
+ if (fnav_stat_type > SXE2_FNAV_STAT_ENA_ALL ||
+ fnav_stat_type == SXE2_FNAV_STAT_ENA_NONE) {
+ PMD_LOG_ERR(INIT, "%s: \"%s\" out of range [1-3].",
+ key, value);
+ goto l_end;
+ }
+ *num = fnav_stat_type;
+ ret = 0;
+l_end:
+ return ret;
+}
+static int32_t sxe2_parse_sched_layer_mode(const char *key, const char *value, void *args)
+{
+ int32_t ret = -EINVAL;
+ uint8_t *num = (uint8_t *)args;
+ uint8_t sched_layer_mode;
+ char *endptr = NULL;
+
+ if (value == NULL || args == NULL) {
+ ret = 0;
+ goto l_end;
+ }
+ errno = 0;
+ sched_layer_mode = (uint8_t)strtoul(value, &endptr, 10);
+ if (errno != 0 || *endptr != '\0') {
+ PMD_LOG_WARN(INIT, "%s: \"%s\" is not a valid int value.",
+ key, value);
+ goto l_end;
+ }
+ if (sched_layer_mode > SXE2_TXSCH_NODE_ADJ_LVL_MAX) {
+ PMD_LOG_ERR(INIT, "%s: \"%s\" > 3.",
+ key, value);
+ goto l_end;
+ }
+ *num = sched_layer_mode;
+ ret = 0;
+l_end:
+ return ret;
+}
+static int32_t sxe2_parse_high_performance_mode(const char *key, const char *value, void *args)
+{
+ int32_t ret = -EINVAL;
+ uint8_t *num = (uint8_t *)args;
+ uint8_t high_performance_mode;
+ char *endptr = NULL;
+
+ if (value == NULL || args == NULL) {
+ ret = 0;
+ goto l_end;
+ }
+ errno = 0;
+ high_performance_mode = (uint8_t)strtoul(value, &endptr, 10);
+ if (errno != 0 || *endptr != '\0') {
+ PMD_LOG_WARN(INIT, "%s: \"%s\" is not a valid int value.",
+ key, value);
+ goto l_end;
+ }
+ if (high_performance_mode != 1) {
+ PMD_LOG_ERR(INIT, "%s: \"%s\" != 1.",
+ key, value);
+ goto l_end;
+ }
+ *num = high_performance_mode;
+ ret = 0;
+l_end:
+ return ret;
+}
+static int32_t sxe2_parse_u8(const char *key, const char *value, void *args)
+{
+ uint8_t *num = (uint8_t *)args;
+ char *end;
+ unsigned long val;
+ int32_t ret = -EINVAL;
+
+ if (value == NULL || args == NULL) {
+ ret = 0;
+ goto l_end;
+ }
+ errno = 0;
+ val = strtoul(value, &end, 10);
+ if (errno != 0 || end == value || *end != '\0') {
+ PMD_LOG_ERR(INIT, "Invalid 8-bit integer value for key %s: %s", key, value);
+ return -EINVAL;
+ }
+
+ if (val > UINT8_MAX) {
+ PMD_LOG_ERR(INIT, "%s: \"%s\" out of range [0-255].",
+ key, value);
+ return -ERANGE;
+ }
+
+ *num = val;
+ ret = 0;
+l_end:
+ return ret;
+}
+static int32_t sxe2_parse_bool(const char *key, const char *value, void *args)
+{
+ int32_t ret = -EINVAL;
+ uint8_t *num = (uint8_t *)args;
+ uint8_t bool_val = 0;
+ char *endptr = NULL;
+
+ if (value == NULL || args == NULL) {
+ ret = 0;
+ goto l_end;
+ }
+ errno = 0;
+ bool_val = (uint8_t)strtoul(value, &endptr, 10);
+ if (errno != 0 || *endptr != '\0') {
+ PMD_LOG_WARN(INIT, "%s: \"%s\" is not a valid int value.",
+ key, value);
+ goto l_end;
+ }
+ if (bool_val != 0 && bool_val != 1) {
+ PMD_LOG_ERR(INIT, "%s: \"%s\" out of range [0|1].",
+ key, value);
+ goto l_end;
+ }
+ *num = bool_val;
+ ret = 0;
+l_end:
+ return ret;
+}
+
struct sxe2_pci_map_bar_info *sxe2_dev_get_bar_info(struct sxe2_adapter *adapter,
enum sxe2_pci_map_resource res_type)
{
@@ -1047,6 +1197,69 @@ void *sxe2_pci_map_addr_get(struct sxe2_adapter *adapter,
return addr;
}
+static int32_t sxe2_args_parse(struct rte_eth_dev *dev, struct sxe2_dev_kvargs_info *kvargs)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ int32_t ret = 0;
+ PMD_INIT_FUNC_TRACE();
+
+ if (kvargs == NULL)
+ goto l_end;
+ ret = sxe2_kvargs_process(kvargs, SXE2_DEVARG_FNAV_STAT_TYPE,
+ &sxe2_parse_fnav_stat_type,
+ &adapter->devargs.fnav_stat_type);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to parse fnav stat type, ret:%d", ret);
+ goto l_end;
+ }
+ ret = sxe2_kvargs_process(kvargs, SXE2_DEVARG_SW_STATS,
+ &sxe2_parse_bool,
+ &adapter->devargs.sw_stats_en);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to parse sw stats enable, ret:%d", ret);
+ goto l_end;
+ }
+ ret = sxe2_kvargs_process(kvargs, SXE2_DEVARG_HIGH_PERFORMANCE_MODE,
+ &sxe2_parse_high_performance_mode,
+ &adapter->devargs.high_performance_mode);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to parse high performance, ret:%d", ret);
+ goto l_end;
+ }
+ ret = sxe2_kvargs_process(kvargs, SXE2_DEVARG_SCHED_LAYER_MODE,
+ &sxe2_parse_sched_layer_mode,
+ &adapter->devargs.sched_layer_mode);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to parse sched layer mode, ret:%d", ret);
+ goto l_end;
+ }
+ ret = sxe2_kvargs_process(kvargs, SXE2_DEVARG_FLOW_DULP_PATTERN_MODE,
+ &sxe2_parse_u8,
+ &adapter->devargs.flow_dup_pattern_mode);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to parse switch dulpliate flow pattern mode,"
+ "ret:%d", ret);
+ goto l_end;
+ }
+ ret = sxe2_kvargs_process(kvargs, SXE2_DEVARG_FUNC_FLOW_DIRCT,
+ &sxe2_parse_bool,
+ &adapter->devargs.func_flow_direct_en);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to parse function flow rule enable,"
+ "ret:%d", ret);
+ goto l_end;
+ }
+ ret = sxe2_kvargs_process(kvargs, SXE2_DEVARG_RX_LOW_LATENCY,
+ &sxe2_parse_bool,
+ &adapter->devargs.rx_low_latency);
+ if (ret) {
+ PMD_DEV_LOG_ERR(adapter, INIT, "Failed to parse rx low latency, ret:%d", ret);
+ goto l_end;
+ }
+l_end:
+ return ret;
+}
+
static int32_t sxe2_eth_init(struct rte_eth_dev *dev)
{
int32_t ret = 0;
@@ -1599,6 +1812,37 @@ void sxe2_dev_pci_map_uinit(struct rte_eth_dev *dev)
adapter->dev_info.dev_data = NULL;
}
+static int32_t sxe2_fc_state_init(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter =
+ SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_drv_vsi_fc_get_resp fc_resp = {0};
+ int32_t ret;
+
+ if (!(adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_FC_STATE)) {
+ adapter->fc_state_ctx.cfg_state = 0;
+ adapter->fc_state_ctx.curr_state = 0;
+ ret = 0;
+ goto l_end;
+ }
+ ret = sxe2_drv_fc_state_get(adapter, &fc_resp);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to get fc state, ret=[%d]", ret);
+ goto l_end;
+ }
+ adapter->fc_state_ctx.cfg_state = fc_resp.fc_enable;
+ adapter->fc_state_ctx.curr_state = 0;
+l_end:
+ return ret;
+}
+static void sxe2_fc_state_uinit(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter =
+ SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ adapter->fc_state_ctx.cfg_state = 0;
+ adapter->fc_state_ctx.curr_state = 0;
+}
+
uint32_t sxe2_sched_mode_get(struct sxe2_adapter *adapter)
{
uint32_t ret_mode = SXE2_SCHED_MODE_INVALID;
@@ -1661,6 +1905,32 @@ static int32_t sxe2_sched_uinit(struct rte_eth_dev *dev)
return ret;
}
+int32_t sxe2_sched_reset(struct rte_eth_dev *dev)
+{
+ int32_t ret = 0;
+
+ if (dev->data->dev_started) {
+ PMD_LOG_ERR(DRV, "Device failed to Stop.");
+ ret = -EPERM;
+ goto l_end;
+ }
+
+ ret = sxe2_tm_conf_reset(dev);
+ if (ret)
+ goto l_end;
+
+ ret = sxe2_sched_uinit(dev);
+ if (ret)
+ goto l_end;
+
+ ret = sxe2_sched_init(dev);
+ if (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)
{
@@ -1683,6 +1953,12 @@ static int32_t sxe2_dev_init(struct rte_eth_dev *dev,
sxe2_init_ptype_tbl(dev);
+ ret = sxe2_args_parse(dev, kvargs);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to parse devargs, ret=%d", ret);
+ goto l_end;
+ }
+
ret = sxe2_hw_init(dev);
if (ret) {
PMD_LOG_ERR(INIT, "Failed to initialize hw, ret=[%d]", ret);
@@ -1749,6 +2025,12 @@ static int32_t sxe2_dev_init(struct rte_eth_dev *dev,
goto init_flow_err;
}
+ ret = sxe2_fc_state_init(dev);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to init fc state, ret=%d", ret);
+ goto init_fc_state_err;
+ }
+
ret = sxe2_sched_init(dev);
if (ret) {
PMD_LOG_ERR(INIT, "Failed to init sched, ret=%d", ret);
@@ -1772,6 +2054,8 @@ static int32_t sxe2_dev_init(struct rte_eth_dev *dev,
init_xstats_err:
(void)sxe2_sched_uinit(dev);
init_sched_err:
+ sxe2_fc_state_uinit(dev);
+init_fc_state_err:
(void)sxe2_flow_uninit(dev);
init_flow_err:
init_rss_err:
@@ -1817,6 +2101,7 @@ static int32_t sxe2_dev_close(struct rte_eth_dev *dev)
sxe2_eth_uinit(dev);
sxe2_dev_pci_map_uinit(dev);
sxe2_free_repr_info(dev);
+ sxe2_fc_state_uinit(dev);
l_end:
return 0;
diff --git a/drivers/net/sxe2/sxe2_ethdev.h b/drivers/net/sxe2/sxe2_ethdev.h
index b103679c78..34550384e9 100644
--- a/drivers/net/sxe2/sxe2_ethdev.h
+++ b/drivers/net/sxe2/sxe2_ethdev.h
@@ -311,6 +311,11 @@ struct sxe2_filter_context {
bool cur_l2_config;
};
+struct sxe2_fc_state_ctxt {
+ uint8_t curr_state;
+ uint8_t cfg_state;
+};
+
struct sxe2_adapter {
struct sxe2_common_device *cdev;
struct sxe2_dev_info dev_info;
@@ -332,6 +337,7 @@ struct sxe2_adapter {
struct sxe2_security_ctx security_ctx;
struct sxe2_repr_context repr_ctxt;
struct sxe2_switchdev_info switchdev_info;
+ struct sxe2_fc_state_ctxt fc_state_ctx;
bool rule_started;
bool flow_isolated;
bool flow_isolate_cfg;
@@ -362,6 +368,8 @@ bool sxe2_ethdev_check(struct rte_eth_dev *dev);
uint32_t sxe2_sched_mode_get(struct sxe2_adapter *adapter);
+int32_t sxe2_sched_reset(struct rte_eth_dev *dev);
+
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_irq.c b/drivers/net/sxe2/sxe2_irq.c
index c26098ef3a..1246cdbeef 100644
--- a/drivers/net/sxe2/sxe2_irq.c
+++ b/drivers/net/sxe2/sxe2_irq.c
@@ -47,6 +47,31 @@ static struct sxe2_event_handler event_handler = {
static RTE_ATOMIC(uint32_t)event_thread_run;
+static int32_t sxe2_fc_state_callback(struct rte_eth_dev *dev)
+{
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_drv_vsi_fc_get_resp fc_resp = {0};
+ int32_t ret;
+
+ if (!(adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_FC_STATE)) {
+ ret = 0;
+ goto l_end;
+ }
+ ret = sxe2_drv_fc_state_get(adapter, &fc_resp);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "Failed to get fc state, ret=[%d]", ret);
+ goto l_end;
+ }
+ adapter->fc_state_ctx.cfg_state = fc_resp.fc_enable;
+ if (dev->data->dev_started) {
+ PMD_LOG_NOTICE(DRV, "Interrupt event: FC status changed."
+ "cfg_state:%u curr_state:%u",
+ adapter->fc_state_ctx.cfg_state,
+ adapter->fc_state_ctx.curr_state);
+ }
+l_end:
+ return ret;
+}
static void sxe2_event_irq_common_handler(struct sxe2_adapter *adapter, uint64_t oicr)
{
@@ -68,6 +93,10 @@ static void sxe2_event_irq_common_handler(struct sxe2_adapter *adapter, uint64_t
PMD_DEV_LOG_INFO(adapter, DRV, "event notify legacy");
(void)sxe2_switchdev_notify_callback(adapter, false);
}
+ if (oicr & RTE_BIT32(SXE2_COM_FC_ST_CHANGE)) {
+ PMD_DEV_LOG_INFO(adapter, DRV, "fc event notify legacy");
+ (void)sxe2_fc_state_callback(dev);
+ }
}
static uint32_t sxe2_event_intr_handle(void *param __rte_unused)
diff --git a/drivers/net/sxe2/sxe2_rx.c b/drivers/net/sxe2/sxe2_rx.c
index 79e65cfbf1..b5dd9950f0 100644
--- a/drivers/net/sxe2/sxe2_rx.c
+++ b/drivers/net/sxe2/sxe2_rx.c
@@ -467,12 +467,24 @@ int32_t __rte_cold sxe2_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queu
int32_t __rte_cold sxe2_rxqs_all_start(struct rte_eth_dev *dev)
{
struct rte_eth_dev_data *data = dev->data;
+ struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ struct sxe2_drv_vsi_fc_get_resp fc_resp = {0};
struct sxe2_rx_queue *rxq;
uint16_t nb_rxq;
uint16_t nb_started_rxq;
int32_t ret;
PMD_INIT_FUNC_TRACE();
+ if (adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_FC_STATE) {
+ ret = sxe2_drv_fc_state_get(adapter, &fc_resp);
+ if (ret) {
+ PMD_LOG_ERR(RX, "Failed to get fc state, ret=[%d]", ret);
+ goto l_end;
+ }
+ adapter->fc_state_ctx.cfg_state = fc_resp.fc_enable;
+ adapter->fc_state_ctx.curr_state = adapter->fc_state_ctx.cfg_state;
+ }
+
for (nb_rxq = 0; nb_rxq < data->nb_rx_queues; nb_rxq++) {
rxq = dev->data->rx_queues[nb_rxq];
if (!rxq || rxq->rx_deferred_start)
diff --git a/drivers/net/sxe2/sxe2_testpmd.c b/drivers/net/sxe2/sxe2_testpmd.c
new file mode 100644
index 0000000000..5792058212
--- /dev/null
+++ b/drivers/net/sxe2/sxe2_testpmd.c
@@ -0,0 +1,733 @@
+
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#ifndef SXE2_TEST
+#include <cmdline_parse_num.h>
+#include <cmdline_parse_string.h>
+#include <stdlib.h>
+#include <testpmd.h>
+
+#include "sxe2_common_log.h"
+#include "sxe2_testpmd_lib.h"
+
+#define SXE2_SWITCH_BUFF_SIZE (4 * 1024 * 1024)
+
+struct cmd_stats_info_show_result {
+ cmdline_fixed_string_t sxe2;
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t stats;
+ portid_t port_id;
+};
+cmdline_parse_token_string_t cmd_stats_info_sxe2 =
+ TOKEN_STRING_INITIALIZER(struct cmd_stats_info_show_result, sxe2, "sxe2");
+cmdline_parse_token_string_t cmd_stats_info_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_stats_info_show_result, show, "show");
+cmdline_parse_token_string_t cmd_stats_info_stats =
+ TOKEN_STRING_INITIALIZER(struct cmd_stats_info_show_result, stats, "stats");
+cmdline_parse_token_num_t cmd_stats_info_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_stats_info_show_result, port_id, RTE_UINT16);
+
+struct cmd_flow_rule_result {
+ cmdline_fixed_string_t sxe2;
+ cmdline_fixed_string_t flow;
+ cmdline_fixed_string_t rule;
+ cmdline_fixed_string_t dump;
+ portid_t port_id;
+};
+cmdline_parse_token_string_t cmd_flow_rule_sxe2 =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_rule_result, sxe2, "sxe2");
+cmdline_parse_token_string_t cmd_flow_rule_flow =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_rule_result, flow, "flow");
+cmdline_parse_token_string_t cmd_flow_rule_rule =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_rule_result, rule, "rule");
+cmdline_parse_token_string_t cmd_flow_rule_dmp =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_rule_result, dump, "dump");
+cmdline_parse_token_num_t cmd_flow_rule_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_rule_result, port_id, RTE_UINT16);
+
+struct cmd_udp_tunnel {
+ cmdline_fixed_string_t sxe2;
+ cmdline_fixed_string_t tunnel_type;
+ cmdline_fixed_string_t action;
+ cmdline_fixed_string_t udp_tunnel_port;
+ uint16_t udp_port;
+ portid_t port_id;
+};
+
+cmdline_parse_token_string_t cmd_udp_tunnel_sxe2 =
+ TOKEN_STRING_INITIALIZER(struct cmd_udp_tunnel, sxe2, "sxe2");
+cmdline_parse_token_string_t cmd_udp_tunnel_action =
+ TOKEN_STRING_INITIALIZER(struct cmd_udp_tunnel, action, "add#rm#show");
+cmdline_parse_token_string_t cmd_udp_tunnel_udp_tunnel_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_udp_tunnel, udp_tunnel_port, "udp_tunnel_port");
+cmdline_parse_token_string_t cmd_udp_tunnel_tunnel_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_udp_tunnel,
+ tunnel_type, "vxlan#vxlan-gpe#geneve#gtp-c#gtp-u#pfcp#ecpri#mpls#nvgre#l2tp#teredo");
+cmdline_parse_token_num_t cmd_udp_tunnel_udp_port =
+ TOKEN_NUM_INITIALIZER(struct cmd_udp_tunnel, udp_port, RTE_UINT16);
+cmdline_parse_token_num_t cmd_udp_tunnel_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_udp_tunnel, port_id, RTE_UINT16);
+
+struct cmd_sched_result {
+ cmdline_fixed_string_t sxe2;
+ cmdline_fixed_string_t sched;
+ cmdline_fixed_string_t reset;
+ portid_t port_id;
+};
+
+cmdline_parse_token_string_t cmd_sched_sxe2 =
+ TOKEN_STRING_INITIALIZER(struct cmd_sched_result, sxe2, "sxe2");
+cmdline_parse_token_string_t cmd_sched_sched =
+ TOKEN_STRING_INITIALIZER(struct cmd_sched_result, sched, "sched");
+cmdline_parse_token_string_t cmd_sched_reset =
+ TOKEN_STRING_INITIALIZER(struct cmd_sched_result, reset, "reset");
+cmdline_parse_token_num_t cmd_sched_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_sched_result, port_id, RTE_UINT16);
+
+struct cmd_ipsec_result {
+ cmdline_fixed_string_t sxe2;
+ cmdline_fixed_string_t engin;
+ cmdline_fixed_string_t dir;
+ cmdline_fixed_string_t op;
+ portid_t port_id;
+ uint16_t session_id;
+ cmdline_fixed_string_t encrypt_algo;
+ cmdline_fixed_string_t encrypt_key;
+ cmdline_fixed_string_t auth_algo;
+ cmdline_fixed_string_t auth_key;
+ cmdline_fixed_string_t dst_ip;
+ uint16_t sport;
+ uint16_t dport;
+ uint32_t spi;
+};
+cmdline_parse_token_string_t cmd_ipsec_mgt_sxe2 =
+ TOKEN_STRING_INITIALIZER(struct cmd_ipsec_result, sxe2, "sxe2");
+cmdline_parse_token_string_t cmd_ipsec_mgt_module =
+ TOKEN_STRING_INITIALIZER(struct cmd_ipsec_result, engin, "ipsec");
+cmdline_parse_token_string_t cmd_ipsec_mgt_dir =
+ TOKEN_STRING_INITIALIZER(struct cmd_ipsec_result, dir, "egress#ingress");
+cmdline_parse_token_string_t cmd_ipsec_mgt_op =
+ TOKEN_STRING_INITIALIZER(struct cmd_ipsec_result, op, "add#rm#show");
+cmdline_parse_token_num_t cmd_ipsec_mgt_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_ipsec_result, port_id, RTE_UINT16);
+cmdline_parse_token_num_t cmd_ipsec_mgt_session_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_ipsec_result, session_id, RTE_UINT16);
+cmdline_parse_token_string_t cmd_ipsec_mgt_encrypt_algo =
+ TOKEN_STRING_INITIALIZER(struct cmd_ipsec_result, encrypt_algo, "aes-cbc#sm4-cbc#null");
+cmdline_parse_token_string_t cmd_ipsec_mgt_encrypt_key =
+ TOKEN_STRING_INITIALIZER(struct cmd_ipsec_result, encrypt_key, NULL);
+cmdline_parse_token_string_t cmd_ipsec_mgt_auth_algo =
+ TOKEN_STRING_INITIALIZER(struct cmd_ipsec_result, auth_algo, "sha-hmac#sm3-hmac#null");
+cmdline_parse_token_string_t cmd_ipsec_mgt_auth_key =
+ TOKEN_STRING_INITIALIZER(struct cmd_ipsec_result, auth_key, NULL);
+cmdline_parse_token_string_t cmd_ipsec_mgt_dst_ip =
+ TOKEN_STRING_INITIALIZER(struct cmd_ipsec_result, dst_ip, NULL);
+cmdline_parse_token_num_t cmd_ipsec_mgt_sport =
+ TOKEN_NUM_INITIALIZER(struct cmd_ipsec_result, sport, RTE_UINT16);
+cmdline_parse_token_num_t cmd_ipsec_mgt_dport =
+ TOKEN_NUM_INITIALIZER(struct cmd_ipsec_result, dport, RTE_UINT16);
+cmdline_parse_token_num_t cmd_ipsec_mgt_spi =
+ TOKEN_NUM_INITIALIZER(struct cmd_ipsec_result, spi, RTE_UINT32);
+
+struct cmd_ipsec_set_result {
+ cmdline_fixed_string_t sxe2;
+ cmdline_fixed_string_t engin;
+ cmdline_fixed_string_t op;
+ cmdline_fixed_string_t type;
+ portid_t port_id;
+ uint16_t conf_value;
+};
+cmdline_parse_token_string_t cmd_ipsec_set_sxe2 =
+ TOKEN_STRING_INITIALIZER(struct cmd_ipsec_set_result, sxe2, "sxe2");
+cmdline_parse_token_string_t cmd_ipsec_set_module =
+ TOKEN_STRING_INITIALIZER(struct cmd_ipsec_set_result, engin, "ipsec");
+cmdline_parse_token_string_t cmd_ipsec_set_op =
+ TOKEN_STRING_INITIALIZER(struct cmd_ipsec_set_result, op, "set#get");
+cmdline_parse_token_string_t cmd_ipsec_set_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_ipsec_set_result, type, "session-id#esp-hdr-offset");
+cmdline_parse_token_num_t cmd_ipsec_set_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_ipsec_set_result, port_id, RTE_UINT16);
+cmdline_parse_token_num_t cmd_ipsec_set_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_ipsec_set_result, conf_value, RTE_UINT16);
+
+struct cmd_ipsec_flush_result {
+ cmdline_fixed_string_t sxe2;
+ cmdline_fixed_string_t engin;
+ cmdline_fixed_string_t op;
+ portid_t port_id;
+};
+cmdline_parse_token_string_t cmd_ipsec_flush_sxe2 =
+ TOKEN_STRING_INITIALIZER(struct cmd_ipsec_flush_result, sxe2, "sxe2");
+cmdline_parse_token_string_t cmd_ipsec_flush_module =
+ TOKEN_STRING_INITIALIZER(struct cmd_ipsec_flush_result, engin, "ipsec");
+cmdline_parse_token_string_t cmd_ipsec_flush_op =
+ TOKEN_STRING_INITIALIZER(struct cmd_ipsec_flush_result, op, "flush");
+cmdline_parse_token_num_t cmd_ipsec_flush_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_ipsec_flush_result, port_id, RTE_UINT16);
+
+struct cmd_inject_irq {
+ cmdline_fixed_string_t sxe2;
+ cmdline_fixed_string_t inject;
+ cmdline_fixed_string_t irq;
+ portid_t port_id;
+ cmdline_fixed_string_t type;
+};
+cmdline_parse_token_string_t cmd_inject_irq_sxe2 =
+ TOKEN_STRING_INITIALIZER(struct cmd_inject_irq, sxe2, "sxe2");
+cmdline_parse_token_string_t cmd_inject_irq_inject =
+ TOKEN_STRING_INITIALIZER(struct cmd_inject_irq, inject, "inject");
+cmdline_parse_token_string_t cmd_inject_irq_irq =
+ TOKEN_STRING_INITIALIZER(struct cmd_inject_irq, irq, "irq");
+cmdline_parse_token_num_t cmd_inject_irq_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_inject_irq, port_id, RTE_UINT16);
+cmdline_parse_token_string_t cmd_inject_irq_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_inject_irq, type, "reset#lsc");
+
+static void cmd_dump_flow_rule_parsed(void *parsed_result,
+ struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_flow_rule_result *res = parsed_result;
+ int ret = -1;
+
+ ret = sxe2_flow_rule_dump(res->port_id, cl);
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ cmdline_printf(cl, "Invalid parameters.\n");
+ break;
+ case -ENODEV:
+ cmdline_printf(cl, "Device doesn't support\n");
+ break;
+ default:
+ cmdline_printf(cl,
+ "Failed to switch rule dump,"
+ " error: (%s)\n",
+ strerror(-ret));
+ }
+}
+
+static void cmd_udp_tunnel_set_parsed(void *parsed_result,
+ struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_udp_tunnel *res = parsed_result;
+ int32_t ret = -1;
+ uint8_t action;
+ const char *action_str[SXE2_TESTPMD_CMD_UDP_TUNNEL_MAX] = {
+ [SXE2_TESTPMD_CMD_UDP_TUNNEL_ADD] = "add",
+ [SXE2_TESTPMD_CMD_UDP_TUNNEL_DEL] = "rm",
+ [SXE2_TESTPMD_CMD_UDP_TUNNEL_GET] = "show"};
+
+ for (action = 0; action < SXE2_TESTPMD_CMD_UDP_TUNNEL_MAX; action++)
+ if (!strcmp(res->action, action_str[action]))
+ break;
+
+ if (action >= SXE2_TESTPMD_CMD_UDP_TUNNEL_MAX) {
+ cmdline_printf(cl, "Invalid action!\n");
+ return;
+ }
+
+ ret = sxe2_udp_tunnel_operations(res->port_id, cl, action,
+ res->udp_port,
+ res->tunnel_type);
+ if (ret)
+ cmdline_printf(cl, "%s udp tunnel port failed, ret = %d\n",
+ action_str[action], ret);
+}
+
+static void cmd_dump_stats_info_parsed(void *parsed_result,
+ struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_stats_info_show_result *res = parsed_result;
+ int ret = -1;
+
+ ret = sxe2_stats_info_show(res->port_id);
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ cmdline_printf(cl, "Invalid parameters.\n");
+ break;
+ case -ENODEV:
+ cmdline_printf(cl, "Device doesn't support\n");
+ break;
+ default:
+ cmdline_printf(cl,
+ "Failed to show stats info,"
+ " error: (%s)\n", strerror(-ret));
+ }
+}
+
+static uint8_t cmd_ipsec_op_get(char *op)
+{
+ uint8_t i;
+ const char *op_type[SXE2_TESTPMD_CMD_IPSEC_OP_MAX] = {
+ [SXE2_TESTPMD_CMD_IPSEC_OP_ADD] = "add",
+ [SXE2_TESTPMD_CMD_IPSEC_OP_RM] = "rm",
+ [SXE2_TESTPMD_CMD_IPSEC_OP_SHOW] = "show",
+ };
+
+ for (i = 0; i < SXE2_TESTPMD_CMD_IPSEC_OP_MAX; i++) {
+ if (!strcmp(op, op_type[i]))
+ break;
+ }
+
+ return i;
+}
+
+static uint8_t cmd_ipsec_dir_get(char *dir)
+{
+ uint8_t i;
+ const char *dir_type[SXE2_TESTPMD_CMD_IPSEC_DIR_MAX] = {
+ [SXE2_TESTPMD_CMD_IPSEC_DIR_EGRESS] = "egress",
+ [SXE2_TESTPMD_CMD_IPSEC_DIR_INGRESS] = "ingress"
+ };
+
+ for (i = 0; i < SXE2_TESTPMD_CMD_IPSEC_DIR_MAX; i++) {
+ if (!strcmp(dir, dir_type[i]))
+ break;
+ }
+
+ return i;
+}
+
+static int sxe2_hex_to_val(char c)
+{
+ int val = 0;
+
+ if (c >= '0' && c <= '9')
+ val = c - '0';
+ if (c >= 'A' && c <= 'F')
+ val = 10 + c - 'A';
+ if (c >= 'a' && c <= 'f')
+ val = 10 + c - 'a';
+ return val;
+}
+
+static void sxe2_hex_to_bytes(uint8_t *enc_key, char *hex_str, uint8_t len)
+{
+ uint8_t i;
+ int high = 0;
+ int low = 0;
+
+ for (i = 0; i < len; i++) {
+ high = sxe2_hex_to_val(hex_str[2 * i]);
+ low = sxe2_hex_to_val(hex_str[2 * i + 1]);
+ enc_key[i] = (high << 4) | low;
+ }
+}
+
+static int32_t cmd_ipsec_add_param_fill(struct sxe2_ipsec_conf_param *param,
+ struct cmdline *cl,
+ struct cmd_ipsec_result *res)
+{
+ uint8_t i;
+ uint8_t j;
+ int32_t ret = -1;
+ const char *encrypt_algo[SXE2_TESTPMD_CMD_IPSEC_EN_ALGO_MAX] = {
+ [SXE2_TESTPMD_CMD_IPSEC_EN_ALGO_AES_CBC] = "aes-cbc",
+ [SXE2_TESTPMD_CMD_IPSEC_EN_ALGO_SM4_CBC] = "sm4-cbc",
+ [SXE2_TESTPMD_CMD_IPSEC_EN_ALGO_NULL] = "null"
+ };
+
+ const char *auth_algo[SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_MAX] = {
+ [SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_SHA_HMAC] = "sha-hmac",
+ [SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_SM3_HMAC] = "sm3-hmac",
+ [SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_NULL] = "null"
+ };
+
+ for (i = 0; i < SXE2_TESTPMD_CMD_IPSEC_EN_ALGO_MAX; i++)
+ if (!strcmp(res->encrypt_algo, encrypt_algo[i]))
+ break;
+
+ if (i >= SXE2_TESTPMD_CMD_IPSEC_EN_ALGO_MAX) {
+ cmdline_printf(cl, "Invalid ipsec encrypt algo: %s!\n", res->encrypt_algo);
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ for (j = 0; j < SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_MAX; j++) {
+ if (!strcmp(res->auth_algo, auth_algo[j]))
+ break;
+ }
+
+
+ if (j >= SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_MAX) {
+ cmdline_printf(cl, "Invalid ipsec auth algo: %s!\n", res->auth_algo);
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ param->encrypt_algo = i;
+ param->auth_algo = j;
+ if (param->encrypt_algo == SXE2_TESTPMD_CMD_IPSEC_EN_ALGO_SM4_CBC)
+ param->enc_len = 16;
+ else
+ param->enc_len = 32;
+
+ sxe2_hex_to_bytes(param->enc_key, res->encrypt_key, param->enc_len);
+ if (param->auth_algo != SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_NULL) {
+ param->auth_len = 32;
+ sxe2_hex_to_bytes(param->auth_key, res->auth_key, param->auth_len);
+ }
+
+ ret = 0;
+
+l_end:
+ return ret;
+}
+
+static int32_t cmd_ipsec_egress_op_parsed(struct sxe2_ipsec_conf_param *param,
+ struct cmdline *cl,
+ struct cmd_ipsec_result *res)
+{
+ int32_t ret = -1;
+
+ switch (param->op) {
+ case SXE2_TESTPMD_CMD_IPSEC_OP_ADD:
+ ret = cmd_ipsec_add_param_fill(param, cl, res);
+ if (ret)
+ goto l_end;
+ ret = sxe2_ipsec_egress_create(param, cl);
+ break;
+ case SXE2_TESTPMD_CMD_IPSEC_OP_RM:
+ param->session_id = res->session_id;
+ ret = sxe2_ipsec_egress_destroy(param, cl);
+ break;
+ case SXE2_TESTPMD_CMD_IPSEC_OP_SHOW:
+ ret = sxe2_ipsec_egress_show(param, cl);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+l_end:
+ return ret;
+}
+
+static int32_t cmd_ipsec_ip_addr_parsed(struct sxe2_ipsec_conf_param *param,
+ struct cmdline *cl,
+ struct cmd_ipsec_result *res)
+{
+ int32_t ret = -1;
+ struct in_addr addr4;
+ struct in6_addr addr6;
+
+ if (inet_pton(AF_INET, res->dst_ip, &addr4) == 1) {
+ param->ip_addr.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+ param->ip_addr.dst_ipv4 = addr4.s_addr;
+ ret = 0;
+ } else if (inet_pton(AF_INET6, res->dst_ip, &addr6) == 1) {
+ param->ip_addr.type = RTE_SECURITY_IPSEC_TUNNEL_IPV6;
+ memcpy(¶m->ip_addr.dst_ipv6, &addr6, sizeof(param->ip_addr.dst_ipv6));
+ ret = 0;
+ } else {
+ cmdline_printf(cl, "Invalid ip address: %s!\n", res->dst_ip);
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+l_end:
+ return ret;
+}
+
+static int32_t cmd_ipsec_ingress_op_parsed(struct sxe2_ipsec_conf_param *param,
+ struct cmdline *cl,
+ struct cmd_ipsec_result *res)
+{
+ int32_t ret = -1;
+
+ switch (param->op) {
+ case SXE2_TESTPMD_CMD_IPSEC_OP_ADD:
+ ret = cmd_ipsec_add_param_fill(param, cl, res);
+ if (ret)
+ goto l_end;
+ param->sport = htons(res->sport);
+ param->dport = htons(res->dport);
+ param->spi = htonl(res->spi);
+ ret = cmd_ipsec_ip_addr_parsed(param, cl, res);
+ if (ret)
+ goto l_end;
+ ret = sxe2_ipsec_ingress_create(param, cl);
+ break;
+ case SXE2_TESTPMD_CMD_IPSEC_OP_RM:
+ param->session_id = res->session_id;
+ ret = sxe2_ipsec_ingress_destroy(param, cl);
+ break;
+ case SXE2_TESTPMD_CMD_IPSEC_OP_SHOW:
+ ret = sxe2_ipsec_ingress_show(param, cl);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+l_end:
+ return ret;
+}
+
+static int32_t cmd_ipsec_dir_parsed(struct sxe2_ipsec_conf_param *param,
+ struct cmdline *cl,
+ struct cmd_ipsec_result *res)
+{
+ int32_t ret = -1;
+
+ switch (param->dir) {
+ case SXE2_TESTPMD_CMD_IPSEC_DIR_EGRESS:
+ ret = cmd_ipsec_egress_op_parsed(param, cl, res);
+ break;
+ case SXE2_TESTPMD_CMD_IPSEC_DIR_INGRESS:
+ ret = cmd_ipsec_ingress_op_parsed(param, cl, res);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static void cmd_ipsec_mgt_parsed(void *parsed_result,
+ struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_ipsec_result *res = parsed_result;
+ struct sxe2_ipsec_conf_param param;
+ int32_t ret = -1;
+ uint8_t dir = 0;
+ uint8_t op = 0;
+
+ dir = cmd_ipsec_dir_get(res->dir);
+ if (dir >= SXE2_TESTPMD_CMD_IPSEC_DIR_MAX) {
+ cmdline_printf(cl, "Invalid ipsec direction: %s!\n", res->dir);
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ op = cmd_ipsec_op_get(res->op);
+ if (op >= SXE2_TESTPMD_CMD_IPSEC_OP_MAX) {
+ cmdline_printf(cl, "Invalid ipsec operation: %s!\n", res->op);
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ memset(¶m, 0, sizeof(struct sxe2_ipsec_conf_param));
+ param.dir = dir;
+ param.op = op;
+ param.port_id = res->port_id;
+ ret = cmd_ipsec_dir_parsed(¶m, cl, res);
+
+ if (ret)
+ cmdline_printf(cl, "Command execute failed, ret = %d\n", ret);
+
+l_end:
+ return;
+}
+
+static void cmd_ipsec_set_parsed(void *parsed_result,
+ struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_ipsec_set_result *res = parsed_result;
+ int32_t ret = -1;
+
+ if (!strcmp(res->op, "set"))
+ ret = sxe2_ipsec_conf_set(res->port_id, cl, res->type, res->conf_value);
+ else if (!strcmp(res->op, "get"))
+ ret = sxe2_ipsec_conf_get(res->port_id, cl, res->type);
+ else
+ cmdline_printf(cl, "Invalid op: %s\n", res->op);
+
+ if (ret)
+ cmdline_printf(cl, "Command execute failed, ret = %d\n", ret);
+}
+
+static void cmd_ipsec_flush_parsed(void *parsed_result,
+ struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_ipsec_flush_result *res = parsed_result;
+ int32_t ret = -1;
+
+ ret = sxe2_ipsec_flush(res->port_id, cl);
+
+ if (ret)
+ cmdline_printf(cl, "Command execute failed, ret = %d\n", ret);
+}
+
+cmdline_parse_inst_t cmd_flow_rule_dump = {
+ .f = cmd_dump_flow_rule_parsed,
+ .data = NULL,
+ .help_str = "sxe2 flow rule dump <port_id>",
+ .tokens = {
+ (void *)&cmd_flow_rule_sxe2,
+ (void *)&cmd_flow_rule_flow,
+ (void *)&cmd_flow_rule_rule,
+ (void *)&cmd_flow_rule_dmp,
+ (void *)&cmd_flow_rule_port_id,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_udp_tunnel_set = {
+ .f = cmd_udp_tunnel_set_parsed,
+ .data = NULL,
+ .help_str = "sxe2 <port_id> udp_tunnel_port add|rm|show "
+ "vxlan|vxlan-gpe|geneve|gtp-c|gtp-u|pfcp|ecpri|mpls|nvgre|l2tp|teredo <udp_port>",
+ .tokens = {
+ (void *)&cmd_udp_tunnel_sxe2,
+ (void *)&cmd_udp_tunnel_port_id,
+ (void *)&cmd_udp_tunnel_udp_tunnel_port,
+ (void *)&cmd_udp_tunnel_action,
+ (void *)&cmd_udp_tunnel_tunnel_type,
+ (void *)&cmd_udp_tunnel_udp_port,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_stats_mgt = {
+ .f = cmd_dump_stats_info_parsed,
+ .data = NULL,
+ .help_str = "sxe2 show stats <port_id>",
+ .tokens = {
+ (void *)&cmd_stats_info_sxe2,
+ (void *)&cmd_stats_info_show,
+ (void *)&cmd_stats_info_stats,
+ (void *)&cmd_stats_info_port_id,
+ NULL,
+ },
+};
+
+static void cmd_sched_reset_cfg(void *parsed_result,
+ struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_sched_result *res = parsed_result;
+ int32_t ret = -1;
+
+ ret = sxe2_testpmd_sched_reset(res->port_id);
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ cmdline_printf(cl, "invalid sched ops\n");
+ break;
+ case -ENOTSUP:
+ cmdline_printf(cl, "function not implemented\n");
+ break;
+ default:
+ cmdline_printf(cl, "programming error: (%s)\n",
+ strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_sched_reset_cmd = {
+ .f = cmd_sched_reset_cfg,
+ .data = NULL,
+ .help_str = "sxe2 sched reset <port_id>",
+ .tokens = {
+ (void *)&cmd_sched_sxe2,
+ (void *)&cmd_sched_sched,
+ (void *)&cmd_sched_reset,
+ (void *)&cmd_sched_port_id,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_ipsec_mgt = {
+ .f = cmd_ipsec_mgt_parsed,
+ .data = NULL,
+ .help_str = "sxe2 ipsec egress|ingress add|rm|show "
+ "<port_id> <session_id> aes-cbc|sm4-cbc|null <encrypt_key> sha-hmac|sm3-hmac|null "
+ "<auth_key> <dst_ip> <sport> <dport> <spi>",
+ .tokens = {
+ (void *)&cmd_ipsec_mgt_sxe2,
+ (void *)&cmd_ipsec_mgt_module,
+ (void *)&cmd_ipsec_mgt_dir,
+ (void *)&cmd_ipsec_mgt_op,
+ (void *)&cmd_ipsec_mgt_port_id,
+ (void *)&cmd_ipsec_mgt_session_id,
+ (void *)&cmd_ipsec_mgt_encrypt_algo,
+ (void *)&cmd_ipsec_mgt_encrypt_key,
+ (void *)&cmd_ipsec_mgt_auth_algo,
+ (void *)&cmd_ipsec_mgt_auth_key,
+ (void *)&cmd_ipsec_mgt_dst_ip,
+ (void *)&cmd_ipsec_mgt_sport,
+ (void *)&cmd_ipsec_mgt_dport,
+ (void *)&cmd_ipsec_mgt_spi,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_ipsec_set = {
+ .f = cmd_ipsec_set_parsed,
+ .data = NULL,
+ .help_str = "sxe2 ipsec set|get esp-hdr-offset|session-id <port_id> <value>",
+ .tokens = {
+ (void *)&cmd_ipsec_set_sxe2,
+ (void *)&cmd_ipsec_set_module,
+ (void *)&cmd_ipsec_set_op,
+ (void *)&cmd_ipsec_set_type,
+ (void *)&cmd_ipsec_set_port_id,
+ (void *)&cmd_ipsec_set_value,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_ipsec_flush = {
+ .f = cmd_ipsec_flush_parsed,
+ .data = NULL,
+ .help_str = "sxe2 ipsec flush <port_id>.\n",
+ .tokens = {
+ (void *)&cmd_ipsec_flush_sxe2,
+ (void *)&cmd_ipsec_flush_module,
+ (void *)&cmd_ipsec_flush_op,
+ (void *)&cmd_ipsec_flush_port_id,
+ NULL,
+ },
+};
+
+static struct testpmd_driver_commands sxe2_cmds = {
+ .commands = {
+ {
+ &cmd_udp_tunnel_set,
+ "sxe2 udp tunnel port set.\n"
+ "Add or remove a customed udp port for specific tunnel protocol\n\n",
+ },
+ {
+ &cmd_sched_reset_cmd,
+ "sxe2 sched reset <port_id>.\n"
+ "Reset sched node on the port\n\n",
+ },
+ {
+ &cmd_stats_mgt,
+ "sxe2 show stats.\n"
+ "Dump a runtime sxe2 dev stats on a port\n\n",
+ },
+ {
+ &cmd_ipsec_mgt,
+ "sxe2 ipsec <dir> <op> <port_id> <session_id> <encrypt_algo> <encrypt_key>"
+ "<encrypt_len> <auth_algo> <auth_key> <auth_len> <dst_ip> <sport> <dport> <spi>.\n"
+ "Create/query/remove ipsec security session\n\n",
+ },
+ {
+ &cmd_ipsec_set,
+ "sxe2 ipsec set <port_id> <session_id> <esp_hdr_offset>.\n"
+ "Set enabled tx session id or esp offset.\n\n",
+ },
+ {
+ &cmd_ipsec_flush,
+ "sxe2 ipsec flush <port_id>.\n"
+ "Flush ipsec all configurations\n\n",
+ },
+ { NULL, NULL},
+ },
+};
+TESTPMD_ADD_DRIVER_COMMANDS(sxe2_cmds)
+#endif
diff --git a/drivers/net/sxe2/sxe2_testpmd_lib.c b/drivers/net/sxe2/sxe2_testpmd_lib.c
new file mode 100644
index 0000000000..ab2530ffe6
--- /dev/null
+++ b/drivers/net/sxe2/sxe2_testpmd_lib.c
@@ -0,0 +1,969 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#include <rte_bus.h>
+#include <eal_export.h>
+
+#include "sxe2_common_log.h"
+#include "sxe2_ethdev.h"
+#include "sxe2_stats.h"
+#include "sxe2_testpmd_lib.h"
+
+struct rte_mempool *g_sess_pool;
+
+bool g_sxe2_ipsec_mgt_init;
+struct sxe2_ipsec_session_mgt g_tx_session[SXE2_IPSEC_PORT_MAX][SXE2_IPSEC_SESSION_MAX];
+struct sxe2_ipsec_session_mgt g_rx_session[SXE2_IPSEC_PORT_MAX][SXE2_IPSEC_SESSION_MAX];
+uint16_t g_tx_sess_id[SXE2_IPSEC_PORT_MAX] = {0};
+uint16_t g_esp_header_offset[SXE2_IPSEC_PORT_MAX] = {0};
+
+static bool sxe2_is_supported(struct rte_eth_dev *dev)
+{
+ return sxe2_ethdev_check(dev);
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(sxe2_testpmd_sched_reset, 26.07)
+int32_t
+sxe2_testpmd_sched_reset(uint16_t port_id)
+{
+ struct rte_eth_dev *dev = NULL;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+ dev = &rte_eth_devices[port_id];
+ if (!sxe2_is_supported(dev)) {
+ PMD_LOG_ERR(DRV, "Invalid dev.");
+ return -ENODEV;
+ }
+
+ return sxe2_sched_reset(dev);
+}
+
+extern const char *sxe2_flow_type_name[SXE2_FLOW_TYPE_MAX];
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(sxe2_flow_rule_dump, 26.07)
+int32_t
+sxe2_flow_rule_dump(uint16_t port_id, struct cmdline *cl)
+{
+ struct rte_eth_dev *dev = NULL;
+ struct sxe2_adapter *adapter = NULL;
+ int32_t ret = -1;
+ struct rte_flow_list_t *flow_list = NULL;
+ struct rte_flow *flow = NULL;
+ uint32_t index = 0;
+ struct sxe2_flow *hw_flow = NULL;
+ uint8_t i = 0;
+
+ const char *sxe2_flow_engine_name[SXE2_FLOW_ENGINE_MAX] = {
+ [SXE2_FLOW_ENGINE_ACL] = "acl",
+ [SXE2_FLOW_ENGINE_RSS] = "rss",
+ [SXE2_FLOW_ENGINE_SWITCH] = "switch",
+ [SXE2_FLOW_ENGINE_FNAV] = "fnav",
+ };
+ const char *sxe2_flow_action_name[SXE2_FLOW_ACTION_MAX] = {
+ [SXE2_FLOW_ACTION_DROP] = "drop",
+ [SXE2_FLOW_ACTION_TC_REDIRECT] = "tc_redirect",
+ [SXE2_FLOW_ACTION_TO_VSI] = "to_vsi",
+ [SXE2_FLOW_ACTION_TO_VSI_LIST] = "to_vsi_list",
+ [SXE2_FLOW_ACTION_PASSTHRU] = "passthru",
+ [SXE2_FLOW_ACTION_QUEUE] = "queue",
+ [SXE2_FLOW_ACTION_Q_REGION] = "q_region",
+ [SXE2_FLOW_ACTION_MARK] = "mark",
+ [SXE2_FLOW_ACTION_COUNT] = "count",
+ [SXE2_FLOW_ACTION_RSS] = "rss",
+ };
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+ dev = &rte_eth_devices[port_id];
+ if (!sxe2_is_supported(dev)) {
+ PMD_LOG_ERR(DRV, "Invalid dev");
+ ret = -ENODEV;
+ goto l_end;
+ }
+ adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
+ flow_list = &adapter->flow_ctxt.rte_flow_list;
+ cmdline_printf(cl, "Dump sxe2 flow rule:\n");
+ TAILQ_FOREACH(flow, flow_list, next) {
+ cmdline_printf(cl, "rule index: %d\n", index++);
+ TAILQ_FOREACH(hw_flow, &flow->sxe2_flow_list, next) {
+ cmdline_printf(cl, "\thw flow id: %d\n", hw_flow->flow_id);
+ cmdline_printf(cl, "\t\ttype: %s\n",
+ sxe2_flow_type_name[hw_flow->meta.flow_type]);
+ cmdline_printf(cl, "\t\tprio: %d\n", hw_flow->meta.flow_prio);
+ cmdline_printf(cl, "\t\tsrc vsi: %d,rule vsi: %d\n",
+ hw_flow->meta.flow_src_vsi, hw_flow->meta.flow_rule_vsi);
+ cmdline_printf(cl, "\t\tengine type: %s\n",
+ sxe2_flow_engine_name[hw_flow->engine_type]);
+ cmdline_printf(cl, "\t\taction:");
+ for (i = 0; i < SXE2_FLOW_ACTION_MAX; i++) {
+ if (sxe2_test_bit(i, hw_flow->action.act_types))
+ cmdline_printf(cl, "%s ", sxe2_flow_action_name[i]);
+ }
+ cmdline_printf(cl, "\n");
+ }
+ }
+ cmdline_printf(cl, "Dump sxe2 flow rule end.\n");
+ ret = 0;
+l_end:
+ return ret;
+}
+
+static const char *tunnel_type_list[SXE2_UDP_TUNNEL_MAX] = {
+ [SXE2_UDP_TUNNEL_PROTOCOL_VXLAN] = "vxlan",
+ [SXE2_UDP_TUNNEL_PROTOCOL_VXLAN_GPE] = "vxlan-gpe",
+ [SXE2_UDP_TUNNEL_PROTOCOL_GENEVE] = "geneve",
+ [SXE2_UDP_TUNNEL_PROTOCOL_GTP_C] = "gtp-c",
+ [SXE2_UDP_TUNNEL_PROTOCOL_GTP_U] = "gtp-u",
+ [SXE2_UDP_TUNNEL_PROTOCOL_PFCP] = "pfcp",
+ [SXE2_UDP_TUNNEL_PROTOCOL_ECPRI] = "ecpri",
+ [SXE2_UDP_TUNNEL_PROTOCOL_MPLS] = "mpls",
+ [SXE2_UDP_TUNNEL_PROTOCOL_NVGRE] = "nvgre",
+ [SXE2_UDP_TUNNEL_PROTOCOL_L2TP] = "l2tp",
+ [SXE2_UDP_TUNNEL_PROTOCOL_TEREDO] = "teredo"
+};
+
+static enum sxe2_udp_tunnel_protocol sxe2_udp_tunnel_type_str2proto(const char *tunnel_type)
+{
+ enum sxe2_udp_tunnel_protocol proto;
+
+ for (proto = 0; proto < SXE2_UDP_TUNNEL_MAX; proto++) {
+ if (tunnel_type_list[proto] != NULL &&
+ strcmp(tunnel_type_list[proto], tunnel_type) == 0) {
+ break;
+ }
+ }
+
+ return proto;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(sxe2_udp_tunnel_operations, 26.07)
+int32_t
+sxe2_udp_tunnel_operations(uint16_t port_id, struct cmdline *cl, uint8_t action,
+ uint16_t udp_port, const char *tunnel_type)
+{
+ enum sxe2_udp_tunnel_protocol proto = sxe2_udp_tunnel_type_str2proto(tunnel_type);
+ struct rte_eth_dev *dev = NULL;
+ struct sxe2_adapter *adapter = NULL;
+ struct sxe2_udp_tunnel_cfg tunnel_config = { 0 };
+ int32_t ret = -1;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+ dev = &rte_eth_devices[port_id];
+ if (!sxe2_is_supported(dev)) {
+ PMD_LOG_ERR(DRV, "Invalid dev.");
+ ret = -ENODEV;
+ goto l_end;
+ }
+
+ if (proto >= SXE2_UDP_TUNNEL_MAX) {
+ cmdline_printf(cl, "Invalid tunnel type!\n");
+ goto l_end;
+ }
+ adapter = dev->data->dev_private;
+ switch (action) {
+ case SXE2_TESTPMD_CMD_UDP_TUNNEL_ADD:
+ ret = sxe2_udp_tunnel_port_add_common(adapter, proto, udp_port);
+ break;
+ case SXE2_TESTPMD_CMD_UDP_TUNNEL_DEL:
+ ret = sxe2_udp_tunnel_port_del_common(adapter, proto, udp_port);
+ break;
+ case SXE2_TESTPMD_CMD_UDP_TUNNEL_GET:
+ tunnel_config.protocol = proto;
+ ret = sxe2_udp_tunnel_port_get_common(adapter, &tunnel_config);
+ if (!ret) {
+ cmdline_printf(cl, "Dump firmware udp tunnel config: [proto:%s, port:%d,"
+ "enable:%d, src/dst:%d/%d, used:%d]\n",
+ tunnel_type_list[proto], tunnel_config.fw_port,
+ tunnel_config.fw_status, tunnel_config.fw_src_en,
+ tunnel_config.fw_dst_en, tunnel_config.fw_used);
+ }
+ break;
+ default:
+ break;
+ }
+
+l_end:
+ return ret;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(sxe2_stats_info_show, 26.07)
+int32_t
+sxe2_stats_info_show(uint16_t port_id)
+{
+ struct rte_eth_dev *dev = NULL;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+ dev = &rte_eth_devices[port_id];
+ if (!sxe2_is_supported(dev)) {
+ PMD_LOG_ERR(DRV, "Invalid dev.");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int32_t sxe2_ipsec_init_mempools(void *sec_ctx)
+{
+ uint16_t nb_sess = 8192;
+ uint32_t sess_sz;
+ char s[64];
+ int32_t ret = -1;
+
+ sess_sz = rte_security_session_get_size(sec_ctx);
+ if (g_sess_pool == NULL) {
+ snprintf(s, sizeof(s), "sess_pool");
+ g_sess_pool = rte_mempool_create(s, nb_sess, sess_sz,
+ MEMPOOL_CACHE_SIZE, 0,
+ NULL, NULL, NULL, NULL,
+ SOCKET_ID_ANY, 0);
+ if (g_sess_pool == NULL) {
+ ret = -ENOMEM;
+ PMD_LOG_ERR(DRV, "Failed to malloc session pool memory.");
+ goto l_end;
+ }
+ }
+ ret = 0;
+
+l_end:
+ return ret;
+}
+
+static void sxe2_ipsec_init_session_mgt(void)
+{
+ uint16_t i;
+ uint8_t port_id;
+
+ if (g_sxe2_ipsec_mgt_init)
+ return;
+
+ for (port_id = 0; port_id < SXE2_IPSEC_PORT_MAX; port_id++) {
+ for (i = 0; i < SXE2_IPSEC_SESSION_MAX; i++) {
+ g_tx_session[port_id][i].session = NULL;
+ g_tx_session[port_id][i].encrypt_algo = SXE2_TESTPMD_CMD_IPSEC_EN_ALGO_NULL;
+ g_tx_session[port_id][i].auth_algo = SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_NULL;
+ g_tx_session[port_id][i].session_id = i;
+ g_tx_session[port_id][i].status = 0;
+ }
+ }
+
+ for (port_id = 0; port_id < SXE2_IPSEC_PORT_MAX; port_id++) {
+ for (i = 0; i < SXE2_IPSEC_SESSION_MAX; i++) {
+ g_rx_session[port_id][i].session = NULL;
+ g_rx_session[port_id][i].encrypt_algo = SXE2_TESTPMD_CMD_IPSEC_EN_ALGO_NULL;
+ g_rx_session[port_id][i].auth_algo = SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_NULL;
+ g_rx_session[port_id][i].session_id = i;
+ g_rx_session[port_id][i].status = 0;
+ }
+ }
+
+ g_sxe2_ipsec_mgt_init = true;
+}
+
+static uint16_t sxe2_ipsec_session_mgt_alloc(enum sxe2_testpmd_ipsec_dir dir, uint16_t port_id)
+{
+ uint16_t i;
+ uint16_t index = 0XFFFF;
+ struct sxe2_ipsec_session_mgt *mgt = NULL;
+
+ if (dir == SXE2_TESTPMD_CMD_IPSEC_DIR_EGRESS)
+ mgt = g_tx_session[port_id];
+ else
+ mgt = g_rx_session[port_id];
+
+ for (i = 0; i < SXE2_IPSEC_SESSION_MAX; i++) {
+ if (mgt[i].status == 0) {
+ index = i;
+ mgt[i].status = 1;
+ break;
+ }
+ }
+
+ return index;
+}
+
+static void sxe2_ipsec_session_mgt_free(enum sxe2_testpmd_ipsec_dir dir,
+ uint16_t index, uint16_t port_id)
+{
+ struct sxe2_ipsec_session_mgt *mgt = NULL;
+
+ if (dir == SXE2_TESTPMD_CMD_IPSEC_DIR_EGRESS)
+ mgt = g_tx_session[port_id];
+ else
+ mgt = g_rx_session[port_id];
+
+ mgt[index].session = NULL;
+ mgt[index].status = 0;
+}
+
+static int32_t sxe2_ipsec_egress_construct(struct cmdline *cl,
+ struct rte_crypto_sym_xform **xform,
+ struct sxe2_ipsec_conf_param *param)
+{
+ struct rte_crypto_sym_xform *cur_xform = NULL;
+ struct rte_crypto_sym_xform *next_xform = NULL;
+ int32_t ret = -1;
+
+ cur_xform = rte_zmalloc("current xform",
+ sizeof(struct rte_crypto_sym_xform), 0);
+ if (cur_xform == NULL) {
+ ret = -ENOMEM;
+ cmdline_printf(cl, "Failed to malloc memory!\n");
+ goto l_end;
+ }
+ cur_xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cur_xform->cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
+ if (param->encrypt_algo == SXE2_TESTPMD_CMD_IPSEC_EN_ALGO_AES_CBC)
+ cur_xform->cipher.algo = SXE2_RTE_CRYPTO_CIPHER_AES_CBC;
+ else
+ cur_xform->cipher.algo = SXE2_RTE_RTE_CRYPTO_CIPHER_SM4_CBC;
+ cur_xform->cipher.key.length = param->enc_len;
+ cur_xform->cipher.key.data = param->enc_key;
+
+ if (param->auth_algo == SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_NULL) {
+ ret = 0;
+ goto l_end;
+ }
+
+ next_xform = rte_zmalloc("next xform",
+ sizeof(struct rte_crypto_sym_xform), 0);
+ if (next_xform == NULL) {
+ rte_free(cur_xform);
+ ret = -ENOMEM;
+ cmdline_printf(cl, "Failed to malloc memory!\n");
+ goto l_end;
+ }
+ next_xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ next_xform->auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
+ if (param->auth_algo == SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_SHA_HMAC)
+ next_xform->auth.algo = SXE2_RTE_CRYPTO_AUTH_SHA256_HMAC;
+ else
+ next_xform->auth.algo = SXE2_RTE_CRYPTO_AUTH_SM3_HMAC;
+ next_xform->auth.key.length = param->auth_len;
+ next_xform->auth.key.data = param->auth_key;
+ cur_xform->next = next_xform;
+ ret = 0;
+
+l_end:
+ *xform = cur_xform;
+ return ret;
+}
+
+static int32_t sxe2_ipsec_ingress_construct(struct cmdline *cl,
+ struct rte_crypto_sym_xform **xform,
+ struct sxe2_ipsec_conf_param *param)
+{
+ struct rte_crypto_sym_xform *cur_xform = NULL;
+ struct rte_crypto_sym_xform *next_xform = NULL;
+ int32_t ret = -1;
+
+ cur_xform = rte_zmalloc("current xform",
+ sizeof(struct rte_crypto_sym_xform), 0);
+ if (cur_xform == NULL) {
+ ret = -ENOMEM;
+ cmdline_printf(cl, "Failed to malloc memory!\n");
+ goto l_end;
+ }
+
+ if (param->auth_algo == SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_NULL) {
+ cur_xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cur_xform->cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
+ if (param->encrypt_algo == SXE2_TESTPMD_CMD_IPSEC_EN_ALGO_AES_CBC)
+ cur_xform->cipher.algo = SXE2_RTE_CRYPTO_CIPHER_AES_CBC;
+ else
+ cur_xform->cipher.algo = SXE2_RTE_RTE_CRYPTO_CIPHER_SM4_CBC;
+ cur_xform->cipher.key.length = param->enc_len;
+ cur_xform->cipher.key.data = param->enc_key;
+ ret = 0;
+ goto l_end;
+ }
+
+ cur_xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cur_xform->auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
+ if (param->auth_algo == SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_SHA_HMAC)
+ cur_xform->auth.algo = SXE2_RTE_CRYPTO_AUTH_SHA256_HMAC;
+ else
+ cur_xform->auth.algo = SXE2_RTE_CRYPTO_AUTH_SM3_HMAC;
+
+ cur_xform->auth.key.length = param->auth_len;
+ cur_xform->auth.key.data = param->auth_key;
+
+ next_xform = rte_zmalloc("next xform",
+ sizeof(struct rte_crypto_sym_xform), 0);
+ if (next_xform == NULL) {
+ rte_free(cur_xform);
+ ret = -ENOMEM;
+ cmdline_printf(cl, "Failed to malloc memory!\n");
+ goto l_end;
+ }
+
+ next_xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ next_xform->cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
+ if (param->encrypt_algo == SXE2_TESTPMD_CMD_IPSEC_EN_ALGO_AES_CBC)
+ next_xform->cipher.algo = SXE2_RTE_CRYPTO_CIPHER_AES_CBC;
+ else
+ next_xform->cipher.algo = SXE2_RTE_RTE_CRYPTO_CIPHER_SM4_CBC;
+ next_xform->cipher.key.length = param->enc_len;
+ next_xform->cipher.key.data = param->enc_key;
+ cur_xform->next = next_xform;
+ ret = 0;
+
+l_end:
+ *xform = cur_xform;
+ return ret;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(sxe2_ipsec_ingress_create, 26.07)
+int32_t
+sxe2_ipsec_ingress_create(struct sxe2_ipsec_conf_param *param, struct cmdline *cl)
+{
+ struct rte_eth_dev *dev = NULL;
+ struct rte_security_session_conf conf;
+ struct rte_crypto_sym_xform *encrypt_xform = NULL;
+ void *session = NULL;
+ struct rte_security_ctx *p_ctx = NULL;
+ int32_t ret = -1;
+ uint16_t index;
+ uint8_t i;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(param->port_id, -ENODEV);
+
+ dev = &rte_eth_devices[param->port_id];
+ if (!sxe2_is_supported(dev)) {
+ PMD_LOG_ERR(DRV, "Invalid dev.");
+ ret = -ENODEV;
+ goto l_end;
+ }
+
+ if (dev->data->dev_started != 0) {
+ cmdline_printf(cl, "port %d must be stopped.\n", dev->data->port_id);
+ ret = 0;
+ goto l_end;
+ }
+
+ p_ctx = rte_eth_dev_get_sec_ctx(param->port_id);
+
+ if (g_sess_pool == NULL) {
+ ret = sxe2_ipsec_init_mempools(p_ctx);
+ if (ret)
+ goto l_end;
+ }
+
+ sxe2_ipsec_init_session_mgt();
+
+ memset(&conf, 0, sizeof(conf));
+ conf.protocol = RTE_SECURITY_PROTOCOL_IPSEC;
+ conf.action_type = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO;
+ conf.ipsec.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+ conf.ipsec.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP;
+ conf.ipsec.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
+ conf.ipsec.spi = param->spi;
+ conf.ipsec.udp.sport = param->sport;
+ conf.ipsec.udp.dport = param->dport;
+ conf.ipsec.tunnel.type = param->ip_addr.type;
+ if (param->sport || param->dport)
+ conf.ipsec.options.udp_encap = true;
+ if (param->ip_addr.type == RTE_SECURITY_IPSEC_TUNNEL_IPV4)
+ conf.ipsec.tunnel.ipv4.dst_ip.s_addr = param->ip_addr.dst_ipv4;
+ else
+ memcpy(&conf.ipsec.tunnel.ipv6.dst_addr,
+ ¶m->ip_addr.dst_ipv6,
+ sizeof(param->ip_addr.dst_ipv6));
+
+ ret = sxe2_ipsec_ingress_construct(cl, &encrypt_xform, param);
+ if (ret)
+ goto l_end;
+ conf.crypto_xform = encrypt_xform;
+
+ session = rte_security_session_create(p_ctx, &conf, g_sess_pool);
+ if (session == NULL) {
+ ret = -1;
+ goto l_free;
+ }
+
+ index = sxe2_ipsec_session_mgt_alloc(param->dir, param->port_id);
+ if (index == 0XFFFF) {
+ ret = -1;
+ goto l_free;
+ }
+
+ g_rx_session[param->port_id][index].session = session;
+ g_rx_session[param->port_id][index].encrypt_algo = param->encrypt_algo;
+ g_rx_session[param->port_id][index].auth_algo = param->auth_algo;
+ for (i = 0; i < 32; i++) {
+ g_rx_session[param->port_id][index].enc_key[i] = param->enc_key[i];
+ g_rx_session[param->port_id][index].auth_key[i] = param->auth_key[i];
+ }
+ g_rx_session[param->port_id][index].sport = ntohs(param->sport);
+ g_rx_session[param->port_id][index].dport = ntohs(param->dport);
+ g_rx_session[param->port_id][index].spi = ntohl(param->spi);
+ memcpy(&g_rx_session[param->port_id][index].ip_addr,
+ ¶m->ip_addr,
+ sizeof(struct sxe2_ipsec_ip_param));
+
+ ret = 0;
+
+l_free:
+ if (encrypt_xform->next)
+ rte_free(encrypt_xform->next);
+ if (encrypt_xform)
+ rte_free(encrypt_xform);
+
+l_end:
+ return ret;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(sxe2_ipsec_ingress_destroy, 26.07)
+int32_t
+sxe2_ipsec_ingress_destroy(struct sxe2_ipsec_conf_param *param, struct cmdline *cl)
+{
+ struct rte_eth_dev *dev = NULL;
+ struct rte_security_ctx *p_ctx = NULL;
+ struct rte_security_session *session = NULL;
+ int32_t ret = -1;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(param->port_id, -ENODEV);
+
+ dev = &rte_eth_devices[param->port_id];
+ if (!sxe2_is_supported(dev)) {
+ cmdline_printf(cl, "Invalid dev.\n");
+ ret = -ENODEV;
+ goto l_end;
+ }
+
+ if (dev->data->dev_started != 0) {
+ cmdline_printf(cl, "port %d must be stopped.\n", dev->data->port_id);
+ ret = 0;
+ goto l_end;
+ }
+
+ if (param->session_id >= SXE2_IPSEC_SESSION_MAX) {
+ PMD_LOG_ERR(DRV, "Invalid session id.");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if (!g_rx_session[param->port_id][param->session_id].status) {
+ PMD_LOG_ERR(DRV, "Invalid session status.");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if (g_rx_session[param->port_id][param->session_id].session == NULL) {
+ PMD_LOG_ERR(DRV, "Invalid session data.");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ p_ctx = rte_eth_dev_get_sec_ctx(param->port_id);
+
+ session = g_rx_session[param->port_id][param->session_id].session;
+ ret = rte_security_session_destroy(p_ctx, session);
+ if (ret)
+ goto l_end;
+ sxe2_ipsec_session_mgt_free(param->dir, param->session_id, param->port_id);
+
+ ret = 0;
+l_end:
+ return ret;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(sxe2_ipsec_ingress_show, 26.07)
+int32_t
+sxe2_ipsec_ingress_show(struct sxe2_ipsec_conf_param *param, struct cmdline *cl)
+{
+ struct rte_eth_dev *dev = NULL;
+ int32_t ret = -1;
+ uint16_t i;
+ uint8_t j;
+ char encrypt_key[65];
+ char auth_key[65];
+ const char *encrypt_algo[SXE2_TESTPMD_CMD_IPSEC_EN_ALGO_MAX] = {
+ [SXE2_TESTPMD_CMD_IPSEC_EN_ALGO_AES_CBC] = "aes-cbc",
+ [SXE2_TESTPMD_CMD_IPSEC_EN_ALGO_SM4_CBC] = "sm4-cbc",
+ [SXE2_TESTPMD_CMD_IPSEC_EN_ALGO_NULL] = "null"
+ };
+
+ const char *auth_algo[SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_MAX] = {
+ [SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_SHA_HMAC] = "sha-hmac",
+ [SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_SM3_HMAC] = "sm3-hmac",
+ [SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_NULL] = "null"
+ };
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(param->port_id, -ENODEV);
+
+ dev = &rte_eth_devices[param->port_id];
+ if (!sxe2_is_supported(dev)) {
+ PMD_LOG_ERR(DRV, "Invalid dev.");
+ ret = -ENODEV;
+ goto l_end;
+ }
+
+ for (i = 0; i < SXE2_IPSEC_SESSION_MAX; i++) {
+ if (g_rx_session[param->port_id][i].status &&
+ g_rx_session[param->port_id][i].session) {
+ memset(encrypt_key, '\0', sizeof(encrypt_key));
+ memset(auth_key, '\0', sizeof(auth_key));
+ for (j = 0; j < 32; j++) {
+ sprintf(encrypt_key + 2 * j, "%02x",
+ g_rx_session[param->port_id][i].enc_key[j]);
+ }
+
+ if (g_rx_session[param->port_id][i].auth_algo !=
+ SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_NULL) {
+ for (j = 0; j < 32; j++) {
+ sprintf(auth_key + 2 * j, "%02x",
+ g_rx_session[param->port_id][i].auth_key[j]);
+ }
+ }
+
+ cmdline_printf(cl, "session_id:%u, direction:rx ,"
+ "encrypt_algo:%s, encrypt_key:0x%s,"
+ "auth_algo:%s, auth_key:0x%s, sport:%u, dport:%u, spi:%u\n",
+ i,
+ encrypt_algo[g_rx_session[param->port_id][i].encrypt_algo],
+ encrypt_key,
+ auth_algo[g_rx_session[param->port_id][i].auth_algo],
+ auth_key,
+ g_rx_session[param->port_id][i].sport,
+ g_rx_session[param->port_id][i].dport,
+ g_rx_session[param->port_id][i].spi);
+ }
+ }
+
+ ret = 0;
+
+l_end:
+ return ret;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(sxe2_ipsec_egress_create, 26.07)
+int32_t
+sxe2_ipsec_egress_create(struct sxe2_ipsec_conf_param *param, struct cmdline *cl)
+{
+ struct rte_eth_dev *dev = NULL;
+ struct rte_security_session_conf conf;
+ struct rte_crypto_sym_xform *encrypt_xform = NULL;
+ void *session = NULL;
+ struct rte_security_ctx *p_ctx = NULL;
+ int32_t ret = -1;
+ uint16_t index;
+ uint8_t i;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(param->port_id, -ENODEV);
+
+ dev = &rte_eth_devices[param->port_id];
+ if (!sxe2_is_supported(dev)) {
+ PMD_LOG_ERR(DRV, "Invalid dev.");
+ ret = -ENODEV;
+ goto l_end;
+ }
+
+ if (dev->data->dev_started != 0) {
+ cmdline_printf(cl, "port %d must be stopped.\n", dev->data->port_id);
+ ret = 0;
+ goto l_end;
+ }
+
+ p_ctx = rte_eth_dev_get_sec_ctx(param->port_id);
+
+ if (g_sess_pool == NULL) {
+ ret = sxe2_ipsec_init_mempools(p_ctx);
+ if (ret)
+ goto l_end;
+ }
+
+ sxe2_ipsec_init_session_mgt();
+
+ memset(&conf, 0, sizeof(conf));
+ conf.protocol = RTE_SECURITY_PROTOCOL_IPSEC;
+ conf.action_type = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO;
+ conf.ipsec.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+ conf.ipsec.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP;
+ conf.ipsec.direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS;
+
+ ret = sxe2_ipsec_egress_construct(cl, &encrypt_xform, param);
+ if (ret)
+ goto l_end;
+ conf.crypto_xform = encrypt_xform;
+
+ session = rte_security_session_create(p_ctx, &conf, g_sess_pool);
+ if (session == NULL) {
+ ret = -1;
+ goto l_free;
+ }
+
+ index = sxe2_ipsec_session_mgt_alloc(param->dir, param->port_id);
+ if (index == 0XFFFF) {
+ ret = -1;
+ goto l_free;
+ }
+
+ g_tx_session[param->port_id][index].session = session;
+ g_tx_session[param->port_id][index].encrypt_algo = param->encrypt_algo;
+ g_tx_session[param->port_id][index].auth_algo = param->auth_algo;
+ for (i = 0; i < 32; i++) {
+ g_tx_session[param->port_id][index].enc_key[i] = param->enc_key[i];
+ g_tx_session[param->port_id][index].auth_key[i] = param->auth_key[i];
+ }
+ ret = 0;
+
+l_free:
+ if (encrypt_xform->next)
+ rte_free(encrypt_xform->next);
+ if (encrypt_xform)
+ rte_free(encrypt_xform);
+
+l_end:
+ return ret;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(sxe2_ipsec_egress_destroy, 26.07)
+int32_t
+sxe2_ipsec_egress_destroy(struct sxe2_ipsec_conf_param *param, struct cmdline *cl)
+{
+ struct rte_eth_dev *dev = NULL;
+ struct rte_security_ctx *p_ctx = NULL;
+ struct rte_security_session *session = NULL;
+ int32_t ret = -1;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(param->port_id, -ENODEV);
+
+ dev = &rte_eth_devices[param->port_id];
+ if (!sxe2_is_supported(dev)) {
+ PMD_LOG_ERR(DRV, "Invalid dev.");
+ ret = -ENODEV;
+ goto l_end;
+ }
+
+ if (dev->data->dev_started != 0) {
+ cmdline_printf(cl, "port %d must be stopped.\n", dev->data->port_id);
+ ret = 0;
+ goto l_end;
+ }
+
+ if (param->session_id >= SXE2_IPSEC_SESSION_MAX) {
+ PMD_LOG_ERR(DRV, "Invalid session id.");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if (!g_tx_session[param->port_id][param->session_id].status) {
+ PMD_LOG_ERR(DRV, "Invalid session status.");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ if (g_tx_session[param->port_id][param->session_id].session == NULL) {
+ PMD_LOG_ERR(DRV, "Invalid session data.");
+ ret = -EINVAL;
+ goto l_end;
+ }
+
+ p_ctx = rte_eth_dev_get_sec_ctx(param->port_id);
+
+ session = g_tx_session[param->port_id][param->session_id].session;
+ ret = rte_security_session_destroy(p_ctx, session);
+ if (ret)
+ goto l_end;
+ sxe2_ipsec_session_mgt_free(param->dir, param->session_id, param->port_id);
+
+ ret = 0;
+
+l_end:
+ return ret;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(sxe2_ipsec_egress_show, 26.07)
+int32_t
+sxe2_ipsec_egress_show(struct sxe2_ipsec_conf_param *param, struct cmdline *cl)
+{
+ struct rte_eth_dev *dev = NULL;
+ int32_t ret = -1;
+ uint16_t i;
+ uint8_t j;
+ char encrypt_key[65];
+ char auth_key[65];
+ const char *encrypt_algo[SXE2_TESTPMD_CMD_IPSEC_EN_ALGO_MAX] = {
+ [SXE2_TESTPMD_CMD_IPSEC_EN_ALGO_AES_CBC] = "aes-cbc",
+ [SXE2_TESTPMD_CMD_IPSEC_EN_ALGO_SM4_CBC] = "sm4-cbc",
+ [SXE2_TESTPMD_CMD_IPSEC_EN_ALGO_NULL] = "null"
+ };
+
+ const char *auth_algo[SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_MAX] = {
+ [SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_SHA_HMAC] = "sha-hmac",
+ [SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_SM3_HMAC] = "sm3-hmac",
+ [SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_NULL] = "null"
+ };
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(param->port_id, -ENODEV);
+
+ dev = &rte_eth_devices[param->port_id];
+ if (!sxe2_is_supported(dev)) {
+ PMD_LOG_ERR(DRV, "Invalid dev.");
+ ret = -ENODEV;
+ goto l_end;
+ }
+
+ for (i = 0; i < SXE2_IPSEC_SESSION_MAX; i++) {
+ if (g_tx_session[param->port_id][i].status &&
+ g_tx_session[param->port_id][i].session) {
+ memset(encrypt_key, '\0', sizeof(encrypt_key));
+ memset(auth_key, '\0', sizeof(auth_key));
+ for (j = 0; j < 32; j++)
+ sprintf(encrypt_key + 2 * j, "%02x",
+ g_tx_session[param->port_id][i].enc_key[j]);
+ if (g_tx_session[param->port_id][i].auth_algo !=
+ SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_NULL)
+ for (j = 0; j < 32; j++)
+ sprintf(auth_key + 2 * j, "%02x",
+ g_tx_session[param->port_id][i].auth_key[j]);
+
+ cmdline_printf(cl, "id:%u, tx , encrypt_algo:%s,"
+ "encrypt_key:0x%s, auth_algo:%s, auth_key:0x%s.\n",
+ i,
+ encrypt_algo[g_tx_session[param->port_id][i].encrypt_algo],
+ encrypt_key,
+ auth_algo[g_tx_session[param->port_id][i].auth_algo],
+ auth_key);
+ }
+ }
+
+ ret = 0;
+
+l_end:
+ return ret;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(sxe2_ipsec_conf_get, 26.07)
+int32_t
+sxe2_ipsec_conf_get(uint16_t port_id, struct cmdline *cl, char type[])
+{
+ struct rte_eth_dev *dev = NULL;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+ dev = &rte_eth_devices[port_id];
+ if (!sxe2_is_supported(dev)) {
+ PMD_LOG_ERR(DRV, "Invalid dev.");
+ return -ENODEV;
+ }
+ if (!strcmp(type, "session-id"))
+ cmdline_printf(cl, "session-id: %u\n",
+ g_tx_sess_id[port_id]);
+ else if (!strcmp(type, "esp-hdr-offset"))
+ cmdline_printf(cl, "esp-hdr-offset: %u\n",
+ g_esp_header_offset[port_id]);
+ else
+ cmdline_printf(cl, "Invalid type: %s\n", type);
+
+ return 0;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(sxe2_ipsec_conf_set, 26.07)
+int32_t
+sxe2_ipsec_conf_set(uint16_t port_id, struct cmdline *cl, char type[], uint16_t value)
+{
+ struct rte_eth_dev *dev = NULL;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+ dev = &rte_eth_devices[port_id];
+ if (!sxe2_is_supported(dev)) {
+ PMD_LOG_ERR(DRV, "Invalid dev.");
+ return -ENODEV;
+ }
+ if (!strcmp(type, "session-id")) {
+ if (value >= 4096 || !g_tx_session[port_id][value].status) {
+ cmdline_printf(cl, "Invalid session-id: %u,"
+ "0 <= value <= 4095 or the session is inactive.\n", value);
+ return -EINVAL;
+ }
+ g_tx_sess_id[port_id] = value;
+ cmdline_printf(cl, "session-id: %u\n", g_tx_sess_id[port_id]);
+ } else if (!strcmp(type, "esp-hdr-offset")) {
+ if (value < 34 || value > 512) {
+ cmdline_printf(cl, "Invalid esp-hdr-offset: %u,"
+ "34 <= value <= 512.\n", value);
+ return -EINVAL;
+ }
+ g_esp_header_offset[port_id] = value;
+ cmdline_printf(cl, "esp-hdr-offset: %u\n",
+ g_esp_header_offset[port_id]);
+ } else {
+ cmdline_printf(cl, "Invalid type: %s\n", type);
+ }
+
+ return 0;
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(sxe2_ipsec_stats_show, 26.07)
+int32_t
+sxe2_ipsec_stats_show(uint16_t port_id)
+{
+ (void)port_id;
+ return 0;
+}
+
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(sxe2_ipsec_flush, 26.07)
+int32_t
+sxe2_ipsec_flush(uint16_t port_id, struct cmdline *cl)
+{
+ struct rte_eth_dev *dev = NULL;
+ struct rte_security_ctx *p_ctx = NULL;
+ struct rte_security_session *session = NULL;
+ int32_t ret = -1;
+ uint16_t i;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+ dev = &rte_eth_devices[port_id];
+ if (!sxe2_is_supported(dev)) {
+ cmdline_printf(cl, "Invalid dev.\n");
+ ret = -ENODEV;
+ goto l_end;
+ }
+
+ if (dev->data->dev_started != 0) {
+ cmdline_printf(cl, "port %d must be stopped.\n", dev->data->port_id);
+ ret = 0;
+ goto l_end;
+ }
+
+ p_ctx = rte_eth_dev_get_sec_ctx(port_id);
+
+ g_esp_header_offset[port_id] = 0;
+ g_tx_sess_id[port_id] = 0;
+
+ for (i = 0; i < SXE2_IPSEC_SESSION_MAX; i++) {
+ session = g_tx_session[port_id][i].session;
+ if (g_tx_session[port_id][i].status && session) {
+ ret = rte_security_session_destroy(p_ctx, session);
+ if (ret)
+ cmdline_printf(cl, "failed to destroy tx session: %d.\n", i);
+ else
+ sxe2_ipsec_session_mgt_free(SXE2_TESTPMD_CMD_IPSEC_DIR_EGRESS,
+ i, port_id);
+ }
+ }
+
+ for (i = 0; i < SXE2_IPSEC_SESSION_MAX; i++) {
+ session = g_rx_session[port_id][i].session;
+ if (g_rx_session[port_id][i].status && session) {
+ ret = rte_security_session_destroy(p_ctx, session);
+ if (ret)
+ cmdline_printf(cl, "failed to destroy rx session: %d.\n", i);
+ else
+ sxe2_ipsec_session_mgt_free(SXE2_TESTPMD_CMD_IPSEC_DIR_INGRESS,
+ i, port_id);
+ }
+ }
+
+ g_sxe2_ipsec_mgt_init = false;
+ ret = 0;
+
+l_end:
+ return ret;
+}
diff --git a/drivers/net/sxe2/sxe2_testpmd_lib.h b/drivers/net/sxe2/sxe2_testpmd_lib.h
new file mode 100644
index 0000000000..3d2659ef00
--- /dev/null
+++ b/drivers/net/sxe2/sxe2_testpmd_lib.h
@@ -0,0 +1,142 @@
+
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+ */
+
+#ifndef __SXE2_TESTPMD_LIB_H__
+#define __SXE2_TESTPMD_LIB_H__
+#include <cmdline.h>
+#include "sxe2_ipsec.h"
+
+#define SXE2_IPSEC_SESSION_MAX (4096)
+#define SXE2_IPSEC_PORT_MAX RTE_MAX_ETHPORTS
+#define MEMPOOL_CACHE_SIZE (512 / 2)
+
+enum {
+ SXE2_TESTPMD_CMD_UDP_TUNNEL_ADD = 0,
+ SXE2_TESTPMD_CMD_UDP_TUNNEL_DEL = 1,
+ SXE2_TESTPMD_CMD_UDP_TUNNEL_GET = 2,
+ SXE2_TESTPMD_CMD_UDP_TUNNEL_MAX,
+};
+
+enum sxe2_testpmd_ipsec_op {
+ SXE2_TESTPMD_CMD_IPSEC_OP_ADD = 0,
+ SXE2_TESTPMD_CMD_IPSEC_OP_RM = 1,
+ SXE2_TESTPMD_CMD_IPSEC_OP_SHOW = 2,
+ SXE2_TESTPMD_CMD_IPSEC_OP_MAX,
+};
+
+enum sxe2_testpmd_ipsec_dir {
+ SXE2_TESTPMD_CMD_IPSEC_DIR_EGRESS = 0,
+ SXE2_TESTPMD_CMD_IPSEC_DIR_INGRESS = 1,
+ SXE2_TESTPMD_CMD_IPSEC_DIR_MAX,
+};
+
+enum sxe2_testpmd_ipsec_encrypt_algo {
+ SXE2_TESTPMD_CMD_IPSEC_EN_ALGO_AES_CBC = 0,
+ SXE2_TESTPMD_CMD_IPSEC_EN_ALGO_SM4_CBC = 1,
+ SXE2_TESTPMD_CMD_IPSEC_EN_ALGO_NULL = 2,
+ SXE2_TESTPMD_CMD_IPSEC_EN_ALGO_MAX,
+};
+
+enum sxe2_testpmd_ipsec_auth_algo {
+ SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_SHA_HMAC = 0,
+ SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_SM3_HMAC = 1,
+ SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_NULL = 2,
+ SXE2_TESTPMD_CMD_IPSEC_AUTH_ALGO_MAX,
+};
+
+struct sxe2_ipsec_conf_param {
+ enum sxe2_testpmd_ipsec_dir dir;
+ enum sxe2_testpmd_ipsec_op op;
+ enum sxe2_testpmd_ipsec_encrypt_algo encrypt_algo;
+ enum sxe2_testpmd_ipsec_auth_algo auth_algo;
+ struct sxe2_ipsec_ip_param ip_addr;
+ uint32_t spi;
+ uint16_t port_id;
+ uint16_t session_id;
+ uint16_t sport;
+ uint16_t dport;
+ uint8_t enc_key[32];
+ uint8_t enc_len;
+ uint8_t auth_key[32];
+ uint8_t auth_len;
+};
+
+struct sxe2_ipsec_session_mgt {
+ void *session;
+ enum sxe2_testpmd_ipsec_encrypt_algo encrypt_algo;
+ enum sxe2_testpmd_ipsec_auth_algo auth_algo;
+ struct sxe2_ipsec_ip_param ip_addr;
+ uint32_t spi;
+ uint16_t session_id;
+ uint16_t sport;
+ uint16_t dport;
+ uint8_t enc_key[32];
+ uint8_t auth_key[32];
+ uint8_t status;
+};
+
+__rte_experimental
+int32_t
+sxe2_testpmd_sched_reset(uint16_t port_id);
+
+__rte_experimental
+int32_t
+sxe2_flow_rule_dump(uint16_t port_id, struct cmdline *cl);
+
+__rte_experimental
+int32_t
+sxe2_udp_tunnel_operations(uint16_t port_id, struct cmdline *cl, uint8_t action,
+ uint16_t udp_port, const char *tunnel_type);
+
+__rte_experimental
+int32_t
+sxe2_stats_info_show(uint16_t port_id);
+
+__rte_experimental
+int32_t
+sxe2_ipsec_ingress_create(struct sxe2_ipsec_conf_param *param, struct cmdline *cl);
+
+__rte_experimental
+int32_t
+sxe2_ipsec_ingress_destroy(struct sxe2_ipsec_conf_param *param, struct cmdline *cl);
+
+__rte_experimental
+int32_t
+sxe2_ipsec_ingress_show(struct sxe2_ipsec_conf_param *param, struct cmdline *cl);
+
+__rte_experimental
+int32_t
+sxe2_ipsec_egress_create(struct sxe2_ipsec_conf_param *param, struct cmdline *cl);
+
+__rte_experimental
+int32_t
+sxe2_ipsec_egress_destroy(struct sxe2_ipsec_conf_param *param, struct cmdline *cl);
+
+__rte_experimental
+int32_t
+sxe2_ipsec_egress_show(struct sxe2_ipsec_conf_param *param, struct cmdline *cl);
+
+__rte_experimental
+int32_t
+sxe2_ipsec_conf_get(uint16_t port_id, struct cmdline *cl, char type[]);
+
+__rte_experimental
+int32_t
+sxe2_ipsec_conf_set(uint16_t port_id, struct cmdline *cl, char type[], uint16_t value);
+
+__rte_experimental
+int32_t
+sxe2_ipsec_stats_show(uint16_t port_id);
+
+__rte_experimental
+int32_t
+sxe2_ipsec_flush(uint16_t port_id, struct cmdline *cl);
+
+extern struct sxe2_ipsec_session_mgt g_tx_session[SXE2_IPSEC_PORT_MAX][SXE2_IPSEC_SESSION_MAX];
+extern uint16_t g_tx_sess_id[SXE2_IPSEC_PORT_MAX];
+extern uint16_t g_esp_header_offset[SXE2_IPSEC_PORT_MAX];
+extern struct rte_mempool *g_sess_pool;
+
+#endif /* __SXE2_TESTPMD_LIB_H__ */
diff --git a/drivers/net/sxe2/sxe2_tm.c b/drivers/net/sxe2/sxe2_tm.c
index 4c4f793cd5..5de9b5d3b7 100644
--- a/drivers/net/sxe2/sxe2_tm.c
+++ b/drivers/net/sxe2/sxe2_tm.c
@@ -982,6 +982,24 @@ int32_t sxe2_tm_init(struct rte_eth_dev *dev)
return ret;
}
+int32_t sxe2_tm_conf_reset(struct rte_eth_dev *dev)
+{
+ int32_t ret;
+
+ ret = sxe2_tm_uninit(dev);
+ if (ret)
+ goto l_end;
+
+ ret = sxe2_tm_init(dev);
+ if (ret)
+ goto l_end;
+
+ PMD_LOG_DEBUG(DRV, "Tm config reset succeed.");
+
+l_end:
+ return ret;
+}
+
static int32_t sxe2_tm_chk_all_leaf(struct rte_eth_dev *dev)
{
int32_t ret = 0;
diff --git a/drivers/net/sxe2/sxe2_tm.h b/drivers/net/sxe2/sxe2_tm.h
index c4f8da6a8e..b0bfc2091d 100644
--- a/drivers/net/sxe2/sxe2_tm.h
+++ b/drivers/net/sxe2/sxe2_tm.h
@@ -73,4 +73,6 @@ int32_t sxe2_tm_init(struct rte_eth_dev *dev);
int32_t sxe2_tm_uninit(struct rte_eth_dev *dev);
+int32_t sxe2_tm_conf_reset(struct rte_eth_dev *dev);
+
#endif /* __SXE2_TM_H__ */
--
2.52.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