* Re: [PATCH v2] net/mlx5: use port index as representor index
From: Raslan Darawsheh @ 2026-06-04 9:36 UTC (permalink / raw)
To: Dariusz Sosnowski, Viacheslav Ovsiienko, Bing Zhao, Ori Kam,
Suanming Mou, Matan Azrad
Cc: dev, stable
In-Reply-To: <20260525091733.558838-1-dsosnowski@nvidia.com>
Hi,
On 25/05/2026 12:17 PM, Dariusz Sosnowski wrote:
> Since the offending commit, mlx5 driver supports probing
> representors on BlueField DPUs with Socket Direct (SD).
> Such card can be connected to 2 different CPUs on the host system.
> On DPU, user would see the following network devices:
>
> - p0 and p1 - physical ports
> - pf0hpf and pf2hpf - PF0 on CPU 0 and CPU 1 respectively
> - pf1hpf and pf3hpf - PF1 on CPU 0 and CPU 1 respectively
>
> mlx5 driver finds the relevant netdev by matching information
> provided in representor devarg to phys_port_name
> reported by Linux kernel.
> For the above interfaces phys_port_name's would be reported
> and probed as:
>
> - p0 -> p0, no need for representor devarg
> - p1 -> p1, with representor=pf1
> - pf0hpf -> c1pf0, with representor=c1pf0vf65535
> - pf1hpf -> c1pf1, with representor=c1pf1vf65535
> - pf2hpf -> c2pf0, with representor=c2pf0vf65535
> - pf3hpf -> c2pf1, with representor=c2pf1vf65535
>
> Although hot-plugging all these representors is successful,
> RTE_ETH_FOREACH_MATCHING_DEV() macro would not find DPDK ports.
> This is caused missing information reported by mlx5 driver,
> through rte_eth_representor_info_get() API.
> Specifically, mlx5 driver did not report controller index for all
> representor ranges.
>
> Until now mlx5 driver used static encoding for 16-bit representor_id:
>
> - 2 bits for representor type
> - 2 bits for PF index
> - 12 bits for representor index (either VF or SF number)
>
> Controller index was not encoded. This caused the mentioned issue
> and on top of that:
>
> - limits the number of PFs
> - limits the number of SFs
>
> This patch changes the mlx5 driver logic for
> rte_eth_representor_info_get().
> Instead of static encoding:
>
> - representor_id's will be dynamically assigned
> to each probed representor.
> - rte_eth_representor_info_get() will report N ranges:
> - N == number of probed ports on single embedded switch
> - Each range will define single representor_id
> for given controller/PF/VF/SF.
>
> Fixes: 2f7cdd821b1b ("net/mlx5: fix probing to allow BlueField Socket Direct")
> Cc: stable@dpdk.org
>
> Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
> Acked-by: Bing Zhao <bingz@nvidia.com>
> ---
> v2:
> - Added missing "not" in "RTE_ETH_FOREACH_MATCHING_DEV() macro would not find DPDK ports"
> in the commit message.
> - Fixed typo in number of bits for representor index.
> Should be 12, not 2.
>
> drivers/net/mlx5/linux/mlx5_os.c | 6 +-
> drivers/net/mlx5/mlx5.h | 19 +++
> drivers/net/mlx5/mlx5_ethdev.c | 284 +++++++++++++++++++------------
> 3 files changed, 199 insertions(+), 110 deletions(-)
>
--
Patch applied to next-net-mlx,
Kindest regards
Raslan Darawsheh
^ permalink raw reply
* Re: [PATCH] net/mlx5: remove nonsensical flow action class_id checks
From: Raslan Darawsheh @ 2026-06-04 9:36 UTC (permalink / raw)
To: Adrian Schollmeyer, Dariusz Sosnowski, Viacheslav Ovsiienko,
Bing Zhao, Ori Kam, Suanming Mou, Matan Azrad, Michael Baum
Cc: dev, Michael Pfeiffer, stable
In-Reply-To: <20260520132533.159996-1-a.schollmeyer@syseleven.de>
Hi,
On 20/05/2026 4:25 PM, Adrian Schollmeyer wrote:
> From: Michael Pfeiffer <m.pfeiffer@syseleven.de>
>
> For a MODIFY_FIELD action, flow_hw_validate_action_modify_field() is
> invoked and enforces class_id == 0 in the action's source and
> destination, if the modified field is none of
> RTE_FLOW_FIELD_GENEVE_OPT_*, as the value is used solely for GENEVE
> fields.
>
> However, this check is flawed due to the way rte_flow_field_data is
> initialized. As it consists of unions and anonymous structs as members,
> empty initialization of this struct or initializing just the tag_index
> only guarantees initialization of the first union member, while the
> remaining member's default initialization behavior is unspecified.
> Therefore, depending on the compiler type, version and configuration,
> the remaining members may either be default-initialized as well or
> contain bytes from uninitialized memory. This causes the check to fail
> depending on how the struct is initialized wherever it is used.
>
> For example, rte_flow_configure() sometimes fails on mlx5 under these
> circumstances with an error "destination class id is not supported"
> during creation of representor tagging rules, as these internally use
> MODIFY_FIELD actions in the following call stack:
>
> 1. rte_flow_configure
> 2. mlx5_flow_port_configure
> 3. flow_hw_configure
> 4. __flow_hw_configure
> 5. flow_hw_setup_tx_repr_tagging
> 6. flow_hw_create_tx_repr_tag_jump_acts_tmpl
> --> various rte_flow_action_modify_field are initialized here, but
> class_id remains uninitialized
> 7. __flow_hw_actions_template_create
> 8. mlx5_flow_hw_actions_validate
> 9. flow_hw_validate_action_modify_field
> --> invoked with class_id containing uninitialized bytes and
> non-GENEVE field type
>
> Remove the two checks for class_id in the non-GENEVE case, as this field
> is unused for these actions and avoids additional implicit dependencies
> on the correct ordering of union members.
>
> Fixes: 1caa89ec1891 ("net/mlx5: support GENEVE options modification")
> Cc: stable@dpdk.org
>
> Signed-off-by: Michael Pfeiffer <m.pfeiffer@syseleven.de>
> Signed-off-by: Adrian Schollmeyer <a.schollmeyer@syseleven.de>
Patch applied to next-net-mlx,
Kindest regards
Raslan Darawsheh
^ permalink raw reply
* Re: [PATCH] net/mlx5: fix uninitialized skip count
From: Raslan Darawsheh @ 2026-06-04 9:35 UTC (permalink / raw)
To: Dariusz Sosnowski, Viacheslav Ovsiienko, Bing Zhao, Ori Kam,
Suanming Mou, Matan Azrad, Alexander Kozyrev
Cc: dev, Kiran Vedere, stable
In-Reply-To: <20260515123358.354191-1-dsosnowski@nvidia.com>
Hi,
On 15/05/2026 3:33 PM, Dariusz Sosnowski wrote:
> From: Kiran Vedere <kiranv@nvidia.com>
>
> mlx5_rx_poll_len() may return MLX5_ERROR_CQE_MASK when
> mlx5_rx_err_handle() reports MLX5_CQE_STATUS_HW_OWN while the Rx queue
> is in IGNORE error state. In this HW_OWN case mlx5_rx_err_handle()
> does not necessarily write to *skip_cnt, yet the caller (mlx5_rx_burst)
> unconditionally uses skip_cnt to advance rq_ci.
>
> This can cause rq_ci to jump by an undefined value, desynchronizing the
> RQ and CQ rings and leading to persistent bad packet delivery until the
> queue is reset.
>
> Fixes: aa67ed308458 ("net/mlx5: ignore non-critical syndromes for Rx queue")
> Cc: akozyrev@nvidia.com
> Cc: stable@dpdk.org
>
> Signed-off-by: Kiran Vedere <kiranv@nvidia.com>
> Acked-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
Patch applied to next-net-mlx,
Kindest regards
Raslan Darawsheh
^ permalink raw reply
* Re: [PATCH] net/mlx5: redirect LACP traffic for legacy E-Switch
From: Raslan Darawsheh @ 2026-06-04 9:34 UTC (permalink / raw)
To: Dariusz Sosnowski, Viacheslav Ovsiienko, Bing Zhao, Ori Kam,
Suanming Mou, Matan Azrad
Cc: dev, stable
In-Reply-To: <20260515123700.354341-1-dsosnowski@nvidia.com>
Hi,
On 15/05/2026 3:37 PM, Dariusz Sosnowski wrote:
> Offending patch fixed the LACP miss rule logic for NICs where
> switchdev is enabled. In this case, LACP miss rules should be inserted
> if and only if started port is a main port on the embedded switch.
> Side effect of that change was that LACP miss rules are not inserted
> when switchdev is disabled and legacy SR-IOV switch mode is used.
>
> This patch addresses that:
>
> - Fix the LACP rule insertion condition.
> - Move HWS table for LACP rule creation out of FDB rules,
> so they can be created separately.
>
> Fixes: 87e4384d2662 ("net/mlx5: fix condition of LACP miss flow")
> Cc: stable@dpdk.org
>
> Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
Patch applied to next-net-mlx,
Kindest regards
Raslan Darawsheh
^ permalink raw reply
* Re: [PATCH v3] net/mlx5: add validation for indirect actions
From: Raslan Darawsheh @ 2026-06-04 9:32 UTC (permalink / raw)
To: Rayane Boussanni, dev; +Cc: dsosnowski
In-Reply-To: <20260514193359.195017-1-rboussanni@gmail.com>
Hi,
On 14/05/2026 10:33 PM, Rayane Boussanni wrote:
> This patch implements missing validation logic for RSS and Connection
> Tracking (ConnTrack) indirect actions in the Hardware Steering (HWS)
> flow engine.
>
> Previously, these actions were accepted without being validated
> against hardware capabilities, which could lead to unexpected behavior
> when applying flow rules. The specialist validation functions
> (mlx5_hw_validate_action_rss and mlx5_hw_validate_action_conntrack)
> already existed but were not wired up to the indirect action handler.
>
> The signature of flow_hw_validate_action_indirect was updated to
> include the actions template attributes (attr), allowing it to pass
> the necessary traffic direction context (ingress/egress/transfer)
> to the underlying validation specialists. For indirect RSS, only the
> template attributes are validated, as the RSS configuration itself is
> already validated when the indirect action handle is created.
>
> Reported-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
> Signed-off-by: Rayane Boussanni <rboussanni@gmail.com>
> ---
> v3:
> - Fix segfault reported by Dariusz Sosnowski when an actions template
> references an indirect RSS action. v2 called
> mlx5_hw_validate_action_rss() on the indirect path, which
> dereferences action->conf as struct rte_flow_action_rss. For indirect
> actions action->conf is an opaque action handle, not an RSS config.
> Add bool is_indirect to mlx5_hw_validate_action_rss() so the indirect
> path validates only the template attributes
> (ingress/egress/transfer).
>
> drivers/net/mlx5/mlx5_flow_hw.c | 36 ++++++++++++++++++++++++++++++---
> 1 file changed, 33 insertions(+), 3 deletions(-)
>
Patch applied to next-net-mlx,
Kindest regards
Raslan Darawsheh
^ permalink raw reply
* Re: [PATCH v2] net/mlx5: query hardware capability for max lro size
From: Raslan Darawsheh @ 2026-06-04 9:28 UTC (permalink / raw)
To: Rayane Boussanni, dsosnowski
Cc: bingz, dev, matan, orika, suanmingm, viacheslavo
In-Reply-To: <20260424142732.1904-1-rboussanni@gmail.com>
Hi,
On 24/04/2026 5:27 PM, Rayane Boussanni wrote:
> Resolve a FIXME in mlx5_dev_infos_get() by dynamically checking the
> lro_allowed flag instead of unconditionally advertising
> MLX5_MAX_LRO_SIZE.
>
> Signed-off-by: Rayane Boussanni <rboussanni@gmail.com>
> ---
Patch applied to next-net-mlx,
Kindest regards
Raslan Darawsheh
^ permalink raw reply
* Re: [PATCH 1/1] net/mlx5: fix crash if malloc FCQS fails
From: Raslan Darawsheh @ 2026-06-04 9:27 UTC (permalink / raw)
To: Yunjian Wang, dev
Cc: matan, suanmingm, viacheslavo, dsosnowski, jerry.lilijun, stable
In-Reply-To: <1777027713-91888-1-git-send-email-wangyunjian@huawei.com>
Hi,
On 24/04/2026 1:48 PM, Yunjian Wang wrote:
> A crash is triggered when memory malloc for FCQS fails. Currently,
> the abnormal branch releases the txq, and it removes the 'txq_ctrl->obj'
> from the linked list, but the 'txq_ctrl->obj' has not actually been
> added to the linked list yet. This triggers a null pointer reference
> issue.
>
> The call stack is as follows:
> Program terminated with signal 11, Segmentation fault.
> 1210 LIST_REMOVE(txq_ctrl->obj, next);
> (gdb) bt
> #0 mlx5_txq_release
> #1 mlx5_txq_start
> #2 mlx5_dev_start
> #3 rte_eth_dev_start
> #4 member_start
> #5 bond_ethdev_start
>
> Fixes: f49f44839df3 ("net/mlx5: share Tx control code")
> Cc: stable@dpdk.org
>
> Signed-off-by: Yunjian Wang <wangyunjian@huawei.com>
Patch applied to next-net-mlx,
Kindest regards
Raslan Darawsheh
^ permalink raw reply
* Re: [PATCH] net/mlx5: improve error when group table type mismatch
From: Raslan Darawsheh @ 2026-06-04 9:26 UTC (permalink / raw)
To: Maayan Kashani, dev
Cc: dsosnowski, Viacheslav Ovsiienko, Bing Zhao, Ori Kam,
Suanming Mou, Matan Azrad
In-Reply-To: <20260325215426.9519-1-mkashani@nvidia.com>
Hi,
On 25/03/2026 11:54 PM, Maayan Kashani wrote:
> HWS fixes a flow group's DR table type (FDB_UNIFIED,
> FDB_RX, FDB_TX, etc.) on first use.
> If a later table uses the same group with a different domain
> (e.g. transfer wire_orig) the driver returns a generic type mismatch.
>
> - Add mlx5dr_table_type_name() to map table type enum to readable strings
> (e.g. FDB_RX(wire_orig), FDB_UNIFIED).
>
> This makes it easier to fix ordering issues
> (e.g. create wire_origtable before the table that jumps to the group).
>
> Signed-off-by: Maayan Kashani <mkashani@nvidia.com>
> Acked-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
Patch applied to next-net-mlx,
Kindest regards
Raslan Darawsheh
^ permalink raw reply
* Re: [PATCH v3 0/6] Make VA reservation limits configurable
From: Thomas Monjalon @ 2026-06-04 8:22 UTC (permalink / raw)
To: Anatoly Burakov; +Cc: dev, Bruce Richardson
In-Reply-To: <cover.1780071269.git.anatoly.burakov@intel.com>
> Anatoly Burakov (6):
> eal: reject non-numeric input in str to size
> eal/memory: remove per-list segment and memory limits
> eal/memory: allocate all VA space in one go
> eal/memory: get rid of global VA space limits
> eal/memory: store default segment limits in config
> eal/memory: add page size VA limits EAL parameter
Thank you for the simplification and the new runtime option.
Applied with release notes added, thanks.
^ permalink raw reply
* Re: [PATCH] eal: fix function versioning with LTO
From: David Marchand @ 2026-06-04 7:50 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: dev, stable, Thomas Monjalon
In-Reply-To: <20260603085359.739ab626@phoenix.local>
On Wed, 3 Jun 2026 at 17:56, Stephen Hemminger
<stephen@networkplumber.org> wrote:
>
> 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.
>
> Clang doesn't have this problem. It works as is.
The Fixes: tag is wrong regardless.
The issue is probably present since introduction of the versioning
macros, or introduction of LTO in DPDK (not sure which came first).
> > > Cc: stable@dpdk.org
> >
> > Why do we need to backport?
>
> Well LTO has worked for a long time, it is not experimental just
> not commonly done since it takes so long to build.
>
> We were doing it years ago at MSFT.
Well, sorry, but every time I enable LTO, I end up with some warnings somewhere.
I don't think I am doing stuff really exotic though.
Looking at bugzilla, we had various fixes for LTO over the years.
We still have one open bz btw: https://bugs.dpdk.org/show_bug.cgi?id=1709
Hence my feeling this feature is not something used by many people around.
And without a CI, we will keep on having to fix bugs/issues.
> > 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.
Just to be clear, we don't need fixing the macros in LTS: every time
we prepare a LTS rc0, we drop any kind of symbol compat.
> >
> > > 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 use Debian testing and GCC 15 but shows up on older versions as well
> I get no warnings building main
Building from scratch, I do avoid the warnings I hit yesterday.
The fix looks correct, my problem is with the form.
Fixes: tags accuracy is important.
And I prefer we stick to "It is not broken, don't fix it".
Thanks.
>
> $ git am ~/Downloads/v2-ethdev-add-buffer-size-parameter-to-rte_eth_dev_get_name_by_port.patch
> $ meson setup build-lto -Db_lto=true
> $ ninja -C build-lto
> ninja: Entering directory `build-lto'
> [620/3781] Linking target lib/librte_ethdev.so.26.2
> FAILED: [code=1] lib/librte_ethdev.so.26.2
> 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/cc3RQyqL.s: Error: invalid attempt to declare external version name as default in symbol `rte_eth_dev_get_name_by_port@@DPDK_27'
> make: *** [/tmp/ccVzgiZ2.mk:2: /tmp/ccTlGfA9.ltrans0.ltrans.o] Error 1
> make: *** Waiting for unfinished jobs....
> lto-wrapper: fatal error: make returned 2 exit status
> compilation terminated.
>
--
David Marchand
^ permalink raw reply
* [DPDK/core Bug 1952] hash: build fails with LTO
From: bugzilla @ 2026-06-04 7:46 UTC (permalink / raw)
To: dev
http://bugs.dpdk.org/show_bug.cgi?id=1952
Bug ID: 1952
Summary: hash: build fails with LTO
Product: DPDK
Version: unspecified
Hardware: All
OS: All
Status: UNCONFIRMED
Severity: normal
Priority: Normal
Component: core
Assignee: bruce.richardson@intel.com
Reporter: david.marchand@redhat.com
CC: dev@dpdk.org, konstantin.v.ananyev@yandex.ru,
ktraynor@redhat.com, vladimir.medvedkin@intel.com
Target Milestone: ---
It is similar to a previous report, that resulting in silencing associated
warnings in dea4c5415506 ("ring: silence GCC 12 warnings").
For now, I associate the issue to the hash library, though the problem may be
on the ring library side.
Minimal reproducer:
# rm -rf build; meson setup build -Db_lto=true -Dcpu_instruction_set=generic
-Doptimization=0 -Ddisable_libs=* -Denable_apps=test-pmd
-Denable_drivers=net/null -Ddeveloper_mode=disabled && ninja -C build
...
The Meson build system
Version: 1.7.2
...
Project version: 26.07.0-rc0
C compiler for the host machine: ccache cc (gcc 15.2.1 "cc (GCC) 15.2.1
20260123 (Red Hat 15.2.1-7)")
C linker for the host machine: cc ld.bfd 2.44-12
...
Found pkg-config: YES (/usr/bin/pkg-config) 2.3.0
...
Compiler for C supports arguments -ffat-lto-objects: YES
...
Found ninja-1.12.1 at /usr/bin/ninja
ninja: Entering directory `build'
[280/284] Linking target lib/librte_hash.so.26.2
In function ‘__rte_ring_enqueue_elems_128’,
inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
inlined from ‘rte_hash_create’ at ../lib/hash/rte_cuckoo_hash.c:375:4:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
108 | memcpy((void *)(ring + idx),
| ^
../lib/hash/rte_cuckoo_hash.c: In function ‘rte_hash_create’:
../lib/hash/rte_cuckoo_hash.c:184:18: note: source object ‘i’ of size 4
184 | uint32_t i;
| ^
In function ‘__rte_ring_enqueue_elems_128’,
inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
inlined from ‘rte_hash_create’ at ../lib/hash/rte_cuckoo_hash.c:524:3:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
108 | memcpy((void *)(ring + idx),
| ^
../lib/hash/rte_cuckoo_hash.c: In function ‘rte_hash_create’:
../lib/hash/rte_cuckoo_hash.c:184:18: note: source object ‘i’ of size 4
184 | uint32_t i;
| ^
In function ‘__rte_ring_enqueue_elems_128’,
inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
inlined from ‘rte_hash_reset’ at ../lib/hash/rte_cuckoo_hash.c:730:3:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
108 | memcpy((void *)(ring + idx),
| ^
../lib/hash/rte_cuckoo_hash.c: In function ‘rte_hash_reset’:
../lib/hash/rte_cuckoo_hash.c:693:32: note: source object ‘i’ of size 4
693 | uint32_t tot_ring_cnt, i;
| ^
In function ‘__rte_ring_enqueue_elems_128’,
inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
inlined from ‘rte_hash_reset’ at ../lib/hash/rte_cuckoo_hash.c:735:4:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
108 | memcpy((void *)(ring + idx),
| ^
../lib/hash/rte_cuckoo_hash.c: In function ‘rte_hash_reset’:
../lib/hash/rte_cuckoo_hash.c:693:32: note: source object ‘i’ of size 4
693 | uint32_t tot_ring_cnt, i;
| ^
In function ‘__rte_ring_enqueue_elems_128’,
inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
inlined from ‘enqueue_slot_back’ at ../lib/hash/rte_cuckoo_hash.c:761:3:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
108 | memcpy((void *)(ring + idx),
| ^
../lib/hash/rte_cuckoo_hash.c: In function ‘enqueue_slot_back’:
../lib/hash/rte_cuckoo_hash.c:755:26: note: source object ‘slot_id’ of size 4
755 | uint32_t slot_id)
| ^
In function ‘__rte_ring_dequeue_elems_128’,
inlined from ‘__rte_ring_do_dequeue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:279:3,
inlined from ‘__rte_ring_dequeue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:298:2,
inlined from ‘__rte_ring_do_dequeue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:466:2,
inlined from ‘rte_ring_sc_dequeue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:344:9,
inlined from ‘rte_ring_sc_dequeue_elem’ at
../lib/ring/rte_ring_elem.h:444:9,
inlined from ‘alloc_slot’ at ../lib/hash/rte_cuckoo_hash.c:1098:7:
../lib/ring/rte_ring_elem_pvt.h:250:25: warning: ‘memcpy’ writing 32 bytes into
a region of size 4 overflows the destination [-Wstringop-overflow=]
250 | memcpy((obj + i), (const void *)(ring + idx),
32);
| ^
../lib/hash/rte_cuckoo_hash.c: In function ‘alloc_slot’:
../lib/hash/rte_cuckoo_hash.c:1078:18: note: destination object ‘slot_id’ of
size 4
1078 | uint32_t slot_id;
| ^
In function ‘__rte_ring_dequeue_elems_128’,
inlined from ‘__rte_ring_do_dequeue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:279:3,
inlined from ‘__rte_ring_dequeue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:298:2,
inlined from ‘__rte_ring_do_dequeue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:466:2,
inlined from ‘rte_ring_sc_dequeue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:344:9,
inlined from ‘rte_ring_sc_dequeue_elem’ at
../lib/ring/rte_ring_elem.h:444:9,
inlined from ‘__rte_hash_add_key_with_hash’ at
../lib/hash/rte_cuckoo_hash.c:1260:6:
../lib/ring/rte_ring_elem_pvt.h:250:25: warning: ‘memcpy’ writing 32 bytes into
a region of size 4 overflows the destination [-Wstringop-overflow=]
250 | memcpy((obj + i), (const void *)(ring + idx),
32);
| ^
../lib/hash/rte_cuckoo_hash.c: In function ‘__rte_hash_add_key_with_hash’:
../lib/hash/rte_cuckoo_hash.c:1114:18: note: destination object ‘ext_bkt_id’ of
size 4
1114 | uint32_t ext_bkt_id = 0;
| ^
In function ‘__rte_ring_dequeue_elems_128’,
inlined from ‘__rte_ring_do_dequeue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:279:3,
inlined from ‘__rte_ring_dequeue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:298:2,
inlined from ‘__rte_ring_do_dequeue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:466:2,
inlined from ‘rte_ring_sc_dequeue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:344:9,
inlined from ‘rte_ring_sc_dequeue_elem’ at
../lib/ring/rte_ring_elem.h:444:9,
inlined from ‘__rte_hash_add_key_with_hash’ at
../lib/hash/rte_cuckoo_hash.c:1267:5:
../lib/ring/rte_ring_elem_pvt.h:250:25: warning: ‘memcpy’ writing 32 bytes into
a region of size 4 overflows the destination [-Wstringop-overflow=]
250 | memcpy((obj + i), (const void *)(ring + idx),
32);
| ^
../lib/hash/rte_cuckoo_hash.c: In function ‘__rte_hash_add_key_with_hash’:
../lib/hash/rte_cuckoo_hash.c:1114:18: note: destination object ‘ext_bkt_id’ of
size 4
1114 | uint32_t ext_bkt_id = 0;
| ^
In function ‘__rte_ring_enqueue_elems_128’,
inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
inlined from ‘__hash_rcu_qsbr_free_resource’ at
../lib/hash/rte_cuckoo_hash.c:1616:3:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 12 [-Wstringop-overread]
108 | memcpy((void *)(ring + idx),
| ^
../lib/hash/rte_cuckoo_hash.c: In function ‘__hash_rcu_qsbr_free_resource’:
../lib/hash/rte_cuckoo_hash.c:1592:40: note: at offset [4, 16] into source
object ‘rcu_dq_entry’ of size 16
1592 | struct __rte_hash_rcu_dq_entry rcu_dq_entry =
| ^
In function ‘__rte_ring_enqueue_elems_128’,
inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
inlined from ‘__rte_hash_del_key_with_hash’ at
../lib/hash/rte_cuckoo_hash.c:1899:4:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
108 | memcpy((void *)(ring + idx),
| ^
../lib/hash/rte_cuckoo_hash.c: In function ‘__rte_hash_del_key_with_hash’:
../lib/hash/rte_cuckoo_hash.c:1831:18: note: source object ‘index’ of size 4
1831 | uint32_t index = EMPTY_SLOT;
| ^
In function ‘__rte_ring_enqueue_elems_128’,
inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
inlined from ‘rte_hash_free_key_with_position’ at
../lib/hash/rte_cuckoo_hash.c:1981:4:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
108 | memcpy((void *)(ring + idx),
| ^
../lib/hash/rte_cuckoo_hash.c: In function ‘rte_hash_free_key_with_position’:
../lib/hash/rte_cuckoo_hash.c:1978:26: note: source object ‘index’ of size 4
1978 | uint32_t index = h->ext_bkt_to_free[position];
| ^
[284/284] Linking target app/dpdk-testpmd
In function ‘__rte_ring_enqueue_elems_128’,
inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
inlined from ‘rte_hash_create’ at ../lib/hash/rte_cuckoo_hash.c:375:4:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
108 | memcpy((void *)(ring + idx),
| ^
../lib/hash/rte_cuckoo_hash.c: In function ‘rte_hash_create’:
../lib/hash/rte_cuckoo_hash.c:184:18: note: source object ‘i’ of size 4
184 | uint32_t i;
| ^
In function ‘__rte_ring_enqueue_elems_128’,
inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
inlined from ‘rte_hash_create’ at ../lib/hash/rte_cuckoo_hash.c:524:3:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
108 | memcpy((void *)(ring + idx),
| ^
../lib/hash/rte_cuckoo_hash.c: In function ‘rte_hash_create’:
../lib/hash/rte_cuckoo_hash.c:184:18: note: source object ‘i’ of size 4
184 | uint32_t i;
| ^
In function ‘__rte_ring_enqueue_elems_128’,
inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
inlined from ‘rte_hash_reset’ at ../lib/hash/rte_cuckoo_hash.c:730:3:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
108 | memcpy((void *)(ring + idx),
| ^
../lib/hash/rte_cuckoo_hash.c: In function ‘rte_hash_reset’:
../lib/hash/rte_cuckoo_hash.c:693:32: note: source object ‘i’ of size 4
693 | uint32_t tot_ring_cnt, i;
| ^
In function ‘__rte_ring_enqueue_elems_128’,
inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
inlined from ‘rte_hash_reset’ at ../lib/hash/rte_cuckoo_hash.c:735:4:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
108 | memcpy((void *)(ring + idx),
| ^
../lib/hash/rte_cuckoo_hash.c: In function ‘rte_hash_reset’:
../lib/hash/rte_cuckoo_hash.c:693:32: note: source object ‘i’ of size 4
693 | uint32_t tot_ring_cnt, i;
| ^
In function ‘__rte_ring_enqueue_elems_128’,
inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
inlined from ‘enqueue_slot_back’ at ../lib/hash/rte_cuckoo_hash.c:761:3:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
108 | memcpy((void *)(ring + idx),
| ^
../lib/hash/rte_cuckoo_hash.c: In function ‘enqueue_slot_back’:
../lib/hash/rte_cuckoo_hash.c:755:26: note: source object ‘slot_id’ of size 4
755 | uint32_t slot_id)
| ^
In function ‘__rte_ring_dequeue_elems_128’,
inlined from ‘__rte_ring_do_dequeue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:279:3,
inlined from ‘__rte_ring_dequeue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:298:2,
inlined from ‘__rte_ring_do_dequeue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:466:2,
inlined from ‘rte_ring_sc_dequeue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:344:9,
inlined from ‘rte_ring_sc_dequeue_elem’ at
../lib/ring/rte_ring_elem.h:444:9,
inlined from ‘alloc_slot’ at ../lib/hash/rte_cuckoo_hash.c:1098:7:
../lib/ring/rte_ring_elem_pvt.h:250:25: warning: ‘memcpy’ writing 32 bytes into
a region of size 4 overflows the destination [-Wstringop-overflow=]
250 | memcpy((obj + i), (const void *)(ring + idx),
32);
| ^
../lib/hash/rte_cuckoo_hash.c: In function ‘alloc_slot’:
../lib/hash/rte_cuckoo_hash.c:1078:18: note: destination object ‘slot_id’ of
size 4
1078 | uint32_t slot_id;
| ^
In function ‘__rte_ring_dequeue_elems_128’,
inlined from ‘__rte_ring_do_dequeue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:279:3,
inlined from ‘__rte_ring_dequeue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:298:2,
inlined from ‘__rte_ring_do_dequeue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:466:2,
inlined from ‘rte_ring_sc_dequeue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:344:9,
inlined from ‘rte_ring_sc_dequeue_elem’ at
../lib/ring/rte_ring_elem.h:444:9,
inlined from ‘__rte_hash_add_key_with_hash’ at
../lib/hash/rte_cuckoo_hash.c:1260:6:
../lib/ring/rte_ring_elem_pvt.h:250:25: warning: ‘memcpy’ writing 32 bytes into
a region of size 4 overflows the destination [-Wstringop-overflow=]
250 | memcpy((obj + i), (const void *)(ring + idx),
32);
| ^
../lib/hash/rte_cuckoo_hash.c: In function ‘__rte_hash_add_key_with_hash’:
../lib/hash/rte_cuckoo_hash.c:1114:18: note: destination object ‘ext_bkt_id’ of
size 4
1114 | uint32_t ext_bkt_id = 0;
| ^
In function ‘__rte_ring_dequeue_elems_128’,
inlined from ‘__rte_ring_do_dequeue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:279:3,
inlined from ‘__rte_ring_dequeue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:298:2,
inlined from ‘__rte_ring_do_dequeue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:466:2,
inlined from ‘rte_ring_sc_dequeue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:344:9,
inlined from ‘rte_ring_sc_dequeue_elem’ at
../lib/ring/rte_ring_elem.h:444:9,
inlined from ‘__rte_hash_add_key_with_hash’ at
../lib/hash/rte_cuckoo_hash.c:1267:5:
../lib/ring/rte_ring_elem_pvt.h:250:25: warning: ‘memcpy’ writing 32 bytes into
a region of size 4 overflows the destination [-Wstringop-overflow=]
250 | memcpy((obj + i), (const void *)(ring + idx),
32);
| ^
../lib/hash/rte_cuckoo_hash.c: In function ‘__rte_hash_add_key_with_hash’:
../lib/hash/rte_cuckoo_hash.c:1114:18: note: destination object ‘ext_bkt_id’ of
size 4
1114 | uint32_t ext_bkt_id = 0;
| ^
In function ‘__rte_ring_enqueue_elems_128’,
inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
inlined from ‘__hash_rcu_qsbr_free_resource’ at
../lib/hash/rte_cuckoo_hash.c:1616:3:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 12 [-Wstringop-overread]
108 | memcpy((void *)(ring + idx),
| ^
../lib/hash/rte_cuckoo_hash.c: In function ‘__hash_rcu_qsbr_free_resource’:
../lib/hash/rte_cuckoo_hash.c:1592:40: note: at offset [4, 16] into source
object ‘rcu_dq_entry’ of size 16
1592 | struct __rte_hash_rcu_dq_entry rcu_dq_entry =
| ^
In function ‘__rte_ring_enqueue_elems_128’,
inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
inlined from ‘__rte_hash_del_key_with_hash’ at
../lib/hash/rte_cuckoo_hash.c:1899:4:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
108 | memcpy((void *)(ring + idx),
| ^
../lib/hash/rte_cuckoo_hash.c: In function ‘__rte_hash_del_key_with_hash’:
../lib/hash/rte_cuckoo_hash.c:1831:18: note: source object ‘index’ of size 4
1831 | uint32_t index = EMPTY_SLOT;
| ^
In function ‘__rte_ring_enqueue_elems_128’,
inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
inlined from ‘rte_hash_free_key_with_position’ at
../lib/hash/rte_cuckoo_hash.c:1981:4:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
108 | memcpy((void *)(ring + idx),
| ^
../lib/hash/rte_cuckoo_hash.c: In function ‘rte_hash_free_key_with_position’:
../lib/hash/rte_cuckoo_hash.c:1978:26: note: source object ‘index’ of size 4
1978 | uint32_t index = h->ext_bkt_to_free[position];
| ^
--
You are receiving this mail because:
You are on the CC list for the bug.
^ permalink raw reply
* [PATCH] net/mlx5: fix the eCPRI match on HWS root table
From: Bing Zhao @ 2026-06-04 3:52 UTC (permalink / raw)
To: viacheslavo, dev, rasland; +Cc: orika, dsosnowski, suanmingm, matan, thomas
When inserting a rule on the root table in HWS mode, the DV
interfaces are still being used for the matcher and value
translation.
For item eCPRI in HWS mode, the DWs of message header and body may be
0 for a valid rule. So we need to use some flags on root table to
decide if the sample ID and matching value should be set for the
rule. Since the table and rule may be created in turn for
asynchronous flow API, the flags should be per table to avoid
over-written. In SWS mode, nothing would be done separately for the
matcher itself.
On the non-root table in HWS, the callbacks to fill the WQE will
handle such case automatically.
Fixes: 93c7d4c22628 ("net/mlx5: support eCPRI with HWS")
Signed-off-by: Bing Zhao <bingz@nvidia.com>
Acked-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
---
drivers/net/mlx5/hws/mlx5dr_matcher.c | 1 +
drivers/net/mlx5/hws/mlx5dr_matcher.h | 1 +
drivers/net/mlx5/hws/mlx5dr_rule.c | 1 +
drivers/net/mlx5/mlx5_flow.h | 7 +++
drivers/net/mlx5/mlx5_flow_dv.c | 77 +++++++++++++++++++++------
5 files changed, 70 insertions(+), 17 deletions(-)
diff --git a/drivers/net/mlx5/hws/mlx5dr_matcher.c b/drivers/net/mlx5/hws/mlx5dr_matcher.c
index 8c07ea8882..511f394448 100644
--- a/drivers/net/mlx5/hws/mlx5dr_matcher.c
+++ b/drivers/net/mlx5/hws/mlx5dr_matcher.c
@@ -1381,6 +1381,7 @@ static int mlx5dr_matcher_init_root(struct mlx5dr_matcher *matcher)
LIST_INSERT_HEAD(&matcher->tbl->head, matcher, next);
pthread_spin_unlock(&ctx->ctrl_lock);
+ matcher->hws_root_match_flags = flow_attr.hws_root_match_flags;
return 0;
free_mask:
diff --git a/drivers/net/mlx5/hws/mlx5dr_matcher.h b/drivers/net/mlx5/hws/mlx5dr_matcher.h
index ef42b7de6b..fbcf9fe09e 100644
--- a/drivers/net/mlx5/hws/mlx5dr_matcher.h
+++ b/drivers/net/mlx5/hws/mlx5dr_matcher.h
@@ -82,6 +82,7 @@ struct mlx5dr_matcher {
uint8_t num_of_at;
/* enum mlx5dr_matcher_flags */
uint8_t flags;
+ uint32_t hws_root_match_flags;
struct mlx5dr_devx_obj *end_ft;
struct mlx5dr_matcher *col_matcher;
struct mlx5dr_matcher *resize_dst;
diff --git a/drivers/net/mlx5/hws/mlx5dr_rule.c b/drivers/net/mlx5/hws/mlx5dr_rule.c
index 0fda0a2d71..fe69721c92 100644
--- a/drivers/net/mlx5/hws/mlx5dr_rule.c
+++ b/drivers/net/mlx5/hws/mlx5dr_rule.c
@@ -741,6 +741,7 @@ int mlx5dr_rule_create_root_no_comp(struct mlx5dr_rule *rule,
}
flow_attr.tbl_type = rule->matcher->tbl->type;
+ flow_attr.hws_root_match_flags = rule->matcher->hws_root_match_flags;
ret = mlx5_flow_dv_translate_items_hws(items, &flow_attr, value->match_buf,
MLX5_SET_MATCHER_HS_V, NULL,
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index c9e72a33d6..39c85eb9a4 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -117,6 +117,9 @@ enum mlx5_indirect_type {
((struct rte_flow_action_handle *)(uintptr_t) \
((MLX5_INDIRECT_ACTION_TYPE_CT << MLX5_INDIRECT_ACTION_TYPE_OFFSET) | (index)))
+#define MLX5_EMPTY_ECPRI_TYPE_MASK RTE_BIT32(0)
+#define MLX5_EMPTY_ECPRI_BODY_MASK RTE_BIT32(1)
+
enum mlx5_indirect_list_type {
MLX5_INDIRECT_ACTION_LIST_TYPE_ERR = 0,
MLX5_INDIRECT_ACTION_LIST_TYPE_LEGACY = 1,
@@ -1264,6 +1267,7 @@ struct mlx5_flow_attr {
/* Action flags, used by priority adjustment. */
uint32_t act_flags;
uint32_t tbl_type; /* Flow table type. */
+ uint32_t hws_root_match_flags;
};
/* Flow structure. */
@@ -1985,6 +1989,8 @@ struct mlx5_flow_workspace {
uint32_t skip_matcher_reg:1;
/* Indicates if need to skip matcher register in translate. */
uint32_t mark:1; /* Indicates if flow contains mark action. */
+ uint32_t empty_ecpri_type_mask:1; /* Indicates if eCPRI type was not masked. */
+ uint32_t empty_ecpri_body_mask:1; /* Indicates if 1st DW of eCPRI payload was not masked. */
uint32_t vport_meta_tag; /* Used for vport index match. */
};
@@ -2018,6 +2024,7 @@ struct mlx5_dv_matcher_workspace {
const struct rte_flow_item *tunnel_item; /* Flow tunnel item. */
const struct rte_flow_item *gre_item; /* Flow GRE item. */
const struct rte_flow_item *integrity_items[2];
+ uint32_t *p_root_flags;
};
struct mlx5_flow_split_info {
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index c2a2874913..307354c886 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -7798,7 +7798,7 @@ mlx5_flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
.u32 =
RTE_BE32(((const struct rte_ecpri_common_hdr) {
.type = 0xFF,
- }).u32),
+ }).u32),
},
.dummy[0] = 0xffffffff,
},
@@ -11401,6 +11401,20 @@ flow_dv_translate_item_gtp_psc(void *key, const struct rte_flow_item *item,
return 0;
}
+
+static inline void
+flow_dv_set_ecpri_sample1(void *misc4_v,
+ const struct rte_flow_item_ecpri *ecpri_m,
+ const struct rte_flow_item_ecpri *ecpri_v,
+ uint32_t sample1)
+{
+ void *dw_v;
+ dw_v = MLX5_ADDR_OF(fte_match_set_misc4, misc4_v, prog_sample_field_value_1);
+ *(uint32_t *)dw_v = ecpri_v->hdr.dummy[0] & ecpri_m->hdr.dummy[0];
+ /* Sample#1, to match message body, offset 4. */
+ MLX5_SET(fte_match_set_misc4, misc4_v, prog_sample_field_id_1, sample1);
+}
+
/**
* Add eCPRI item to matcher and to the value.
*
@@ -11418,6 +11432,7 @@ flow_dv_translate_item_gtp_psc(void *key, const struct rte_flow_item *item,
static void
flow_dv_translate_item_ecpri(struct rte_eth_dev *dev, void *key,
const struct rte_flow_item *item,
+ struct mlx5_dv_matcher_workspace *wks,
uint64_t last_item, uint32_t key_type)
{
struct mlx5_priv *priv = dev->data->dev_private;
@@ -11446,18 +11461,32 @@ flow_dv_translate_item_ecpri(struct rte_eth_dev *dev, void *key,
RTE_BE16(RTE_ETHER_TYPE_ECPRI);
}
}
+ /* HWS matcher does need a non-empty mask. */
if (MLX5_ITEM_VALID(item, key_type))
return;
- MLX5_ITEM_UPDATE(item, key_type, ecpri_v, ecpri_m,
- &rte_flow_item_ecpri_mask);
+ MLX5_ITEM_UPDATE(item, key_type, ecpri_v, ecpri_m, &rte_flow_item_ecpri_mask);
/*
* Maximal four DW samples are supported in a single matching now.
* Two are used now for a eCPRI matching:
* 1. Type: one byte, mask should be 0x00ff0000 in network order
* 2. ID of a message: one or two bytes, mask 0xffff0000 or 0xff000000
* if any.
+ * Translation also handles the following cases.
+ * 1. HWS mode may face a case with NULL mask and value all zeros.
+ * 2. Matching all eCPRI packets will be done in ETH / VLAN item.
+ * 3. If type is not masked, then message body will not be masked either, forcefully.
*/
- if (!ecpri_m->hdr.common.u32)
+ if (key_type == MLX5_SET_MATCHER_HS_M) {
+ if (!ecpri_m->hdr.common.u32) {
+ *wks->p_root_flags |= MLX5_EMPTY_ECPRI_TYPE_MASK;
+ return;
+ }
+ /* Initialized with 0, this should not hit. */
+ *wks->p_root_flags &= ~MLX5_EMPTY_ECPRI_TYPE_MASK;
+ }
+ if (key_type == MLX5_SET_MATCHER_HS_V && (*wks->p_root_flags & MLX5_EMPTY_ECPRI_TYPE_MASK))
+ return;
+ if ((key_type & MLX5_SET_MATCHER_SW) && !ecpri_m->hdr.common.u32)
return;
samples = priv->sh->ecpri_parser.ids;
/* Need to take the whole DW as the mask to fill the entry. */
@@ -11473,27 +11502,40 @@ flow_dv_translate_item_ecpri(struct rte_eth_dev *dev, void *key,
* Checking if message body part needs to be matched.
* Some wildcard rules only matching type field should be supported.
*/
- if (ecpri_m->hdr.dummy[0]) {
- if (key_type == MLX5_SET_MATCHER_SW_M)
- common.u32 = rte_be_to_cpu_32(ecpri_vv->hdr.common.u32);
- else
- common.u32 = rte_be_to_cpu_32(ecpri_v->hdr.common.u32);
+ if (key_type == MLX5_SET_MATCHER_HS_M) {
+ if (!ecpri_m->hdr.dummy[0]) {
+ *wks->p_root_flags |= MLX5_EMPTY_ECPRI_BODY_MASK;
+ return;
+ }
+ *wks->p_root_flags &= ~MLX5_EMPTY_ECPRI_BODY_MASK;
+ }
+ if (key_type == MLX5_SET_MATCHER_HS_V && (*wks->p_root_flags & MLX5_EMPTY_ECPRI_BODY_MASK))
+ return;
+ if (key_type & MLX5_SET_MATCHER_SW) {
+ if (!ecpri_m->hdr.dummy[0])
+ return;
+ common.u32 = rte_be_to_cpu_32(ecpri_vv->hdr.common.u32);
+ } else if (key_type == MLX5_SET_MATCHER_HS_V) {
+ common.u32 = rte_be_to_cpu_32(ecpri_v->hdr.common.u32);
+ }
+ if (key_type != MLX5_SET_MATCHER_HS_M) {
switch (common.type) {
case RTE_ECPRI_MSG_TYPE_IQ_DATA:
case RTE_ECPRI_MSG_TYPE_RTC_CTRL:
case RTE_ECPRI_MSG_TYPE_DLY_MSR:
- dw_v = MLX5_ADDR_OF(fte_match_set_misc4, misc4_v,
- prog_sample_field_value_1);
- *(uint32_t *)dw_v = ecpri_v->hdr.dummy[0] &
- ecpri_m->hdr.dummy[0];
- /* Sample#1, to match message body, offset 4. */
- MLX5_SET(fte_match_set_misc4, misc4_v,
- prog_sample_field_id_1, samples[1]);
+ flow_dv_set_ecpri_sample1(misc4_v, ecpri_v, ecpri_m, samples[1]);
break;
default:
/* Others, do not match any sample ID. */
break;
}
+ } else {
+ /* When MLX5_SET_MATCHER_HS_M on root table (default value),
+ * the sample ID and mask should be set, or else prog_sample_field_id_1 will
+ * be zero and a mismatch with the HWS rule.
+ * Empty body mask for a matcher returns directly in the previous lines.
+ */
+ flow_dv_set_ecpri_sample1(misc4_v, ecpri_v, ecpri_m, samples[1]);
}
}
@@ -14501,7 +14543,7 @@ flow_dv_translate_items(struct rte_eth_dev *dev,
"cannot create eCPRI parser");
}
flow_dv_translate_item_ecpri
- (dev, key, items, last_item, key_type);
+ (dev, key, items, wks, last_item, key_type);
/* No other protocol should follow eCPRI layer. */
last_item = MLX5_FLOW_LAYER_ECPRI;
break;
@@ -14698,6 +14740,7 @@ mlx5_flow_dv_translate_items_hws_impl(const struct rte_flow_item *items,
.attr = &rattr,
.rss_desc = &rss_desc,
.group = attr->group,
+ .p_root_flags = &attr->hws_root_match_flags,
};
int ret = 0;
--
2.21.0
^ permalink raw reply related
* [PATCH v2] net/ark: use standard IPv4 address parser
From: Denis Sergeev @ 2026-06-04 3:48 UTC (permalink / raw)
To: dev; +Cc: shepard.siegel, ed.czeck, john.miller, stephen, Denis Sergeev,
stable
In-Reply-To: <20260603054742.120101-1-denserg.edu@gmail.com>
The IPv4 parsing helper used by pktgen and pktchkr read each octet with
"%u", which accepts values above 255 from the configuration file and
encodes them into unintended device register values.
Replace the hand-rolled parser in both modules with inet_pton(), which
validates the dotted-quad format and the octet range, and matches the
IPv4 parsing already used by other DPDK drivers. For valid input the
returned value is byte-order identical to the previous helper, so the
register contents are unchanged.
Fixes: 9c7188a68d7b ("net/ark: provide API for hardware modules pktchkr and pktgen")
Cc: stable@dpdk.org
Signed-off-by: Denis Sergeev <denserg.edu@gmail.com>
---
v2:
- Replace the hand-rolled parser with inet_pton() in both modules
instead of adding explicit octet range checks.
drivers/net/ark/ark_pktchkr.c | 9 +++++----
drivers/net/ark/ark_pktgen.c | 9 +++++----
2 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ark/ark_pktchkr.c b/drivers/net/ark/ark_pktchkr.c
index e1f336c73c..67405ac18a 100644
--- a/drivers/net/ark/ark_pktchkr.c
+++ b/drivers/net/ark/ark_pktchkr.c
@@ -4,9 +4,11 @@
#include <stdlib.h>
#include <unistd.h>
+#include <arpa/inet.h>
#include <rte_string_fns.h>
#include <rte_malloc.h>
+#include <rte_byteorder.h>
#include "ark_pktchkr.h"
#include "ark_logs.h"
@@ -374,12 +376,11 @@ static int32_t parse_ipv4_string(char const *ip_address);
static int32_t
parse_ipv4_string(char const *ip_address)
{
- unsigned int ip[4];
+ struct in_addr addr;
- if (sscanf(ip_address, "%u.%u.%u.%u",
- &ip[0], &ip[1], &ip[2], &ip[3]) != 4)
+ if (inet_pton(AF_INET, ip_address, &addr) != 1)
return 0;
- return ip[3] + ip[2] * 0x100 + ip[1] * 0x10000ul + ip[0] * 0x1000000ul;
+ return rte_be_to_cpu_32(addr.s_addr);
}
void
diff --git a/drivers/net/ark/ark_pktgen.c b/drivers/net/ark/ark_pktgen.c
index 69ff7072b2..05d5773d44 100644
--- a/drivers/net/ark/ark_pktgen.c
+++ b/drivers/net/ark/ark_pktgen.c
@@ -4,9 +4,11 @@
#include <stdlib.h>
#include <unistd.h>
+#include <arpa/inet.h>
#include <rte_string_fns.h>
#include <rte_malloc.h>
+#include <rte_byteorder.h>
#include <rte_thread.h>
#include "ark_pktgen.h"
@@ -355,12 +357,11 @@ static int32_t parse_ipv4_string(char const *ip_address);
static int32_t
parse_ipv4_string(char const *ip_address)
{
- unsigned int ip[4];
+ struct in_addr addr;
- if (sscanf(ip_address, "%u.%u.%u.%u",
- &ip[0], &ip[1], &ip[2], &ip[3]) != 4)
+ if (inet_pton(AF_INET, ip_address, &addr) != 1)
return 0;
- return ip[3] + ip[2] * 0x100 + ip[1] * 0x10000ul + ip[0] * 0x1000000ul;
+ return rte_be_to_cpu_32(addr.s_addr);
}
static void
--
2.50.1
^ permalink raw reply related
* [PATCH 10/10] net/bnxt: fix v3 vector mode not selecting cksum unknown unknown
From: Mohammad Shuab Siddique @ 2026-06-04 3:18 UTC (permalink / raw)
To: dev; +Cc: kishore.padmanabha, stable, Keegan Freyhof,
Mohammad Shuab Siddique
In-Reply-To: <20260604031851.2267548-1-Mohammad-Shuab.Siddique@broadcom.com>
From: Keegan Freyhof <keegan.freyhof@broadcom.com>
The v3 vector mode would default to all cksums being good rather
than cksum unknown in the case that flags2 cscalc section was 0.
Added an entry in the lookup table for this case and corrected
the logic.
Signed-off-by: Keegan Freyhof <keegan.freyhof@broadcom.com>
Signed-off-by: Mohammad Shuab Siddique <mohammad-shuab.siddique@broadcom.com>
---
drivers/net/bnxt/bnxt_rxtx_vec_avx2.c | 14 ++++++++------
drivers/net/bnxt/bnxt_rxtx_vec_common.h | 3 ++-
2 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c b/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c
index 38aca98cb1..b5fb9d35c4 100644
--- a/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c
+++ b/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c
@@ -1111,14 +1111,16 @@ recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pk
* RX_PKT_CMPL_ERRORS_T_IP_CS_ERROR | RX_PKT_CMPL_ERRORS_L4_CS_ERROR |
* RX_PKT_CMPL_ERRORS_IP_CS_ERROR
*/
- errors_csum_idx = _mm256_srli_epi32(_mm256_and_si256(errors_v2,
- _mm256_slli_epi32(mask_fs, 4)), 4);
+ errors_csum_idx = _mm256_and_si256(_mm256_srli_epi32(errors_v2, 4),
+ mask_fs);
meta_format = _mm256_cmpeq_epi32(_mm256_and_si256(cs_calc,
- _mm256_slli_epi32(mask_fs, 4)),
- _mm256_setzero_si256());
+ _mm256_slli_epi32(mask_fs, 4)),
+ _mm256_setzero_si256());
cs_valid = _mm256_cmpeq_epi32(_mm256_and_si256(cs_calc, mask_fs),
- _mm256_setzero_si256());
- errors_csum_idx = _mm256_andnot_si256(cs_valid, errors_csum_idx);
+ _mm256_setzero_si256());
+ errors_csum_idx = _mm256_add_epi32(_mm256_andnot_si256(cs_valid, mask_1s),
+ _mm256_andnot_si256(cs_valid,
+ errors_csum_idx));
/*
* Load ol_flags for eight packets using gather. Gather
diff --git a/drivers/net/bnxt/bnxt_rxtx_vec_common.h b/drivers/net/bnxt/bnxt_rxtx_vec_common.h
index d8659d1001..c75a8bd09f 100644
--- a/drivers/net/bnxt/bnxt_rxtx_vec_common.h
+++ b/drivers/net/bnxt/bnxt_rxtx_vec_common.h
@@ -178,7 +178,8 @@ bnxt_tx_cmp_vec(struct bnxt_tx_queue *txq, uint32_t nr_pkts)
txr->tx_raw_cons = raw_cons;
}
-static const uint32_t errors_to_olflags_v3[16] = {
+static const uint32_t errors_to_olflags_v3[17] = {
+ RTE_MBUF_F_RX_IP_CKSUM_UNKNOWN,
RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD | RTE_MBUF_F_RX_L4_CKSUM_GOOD |
RTE_MBUF_F_RX_IP_CKSUM_GOOD,
RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD | RTE_MBUF_F_RX_L4_CKSUM_GOOD |
--
2.47.3
^ permalink raw reply related
* [PATCH 09/10] net/bnxt: add vector AVX2 burst mode indicator for v3
From: Mohammad Shuab Siddique @ 2026-06-04 3:18 UTC (permalink / raw)
To: dev; +Cc: kishore.padmanabha, stable, Keegan Freyhof,
Mohammad Shuab Siddique
In-Reply-To: <20260604031851.2267548-1-Mohammad-Shuab.Siddique@broadcom.com>
From: Keegan Freyhof <keegan.freyhof@broadcom.com>
When querying the burst mode while the AVX2 RX vector
mode was in use, bnxt_rx_burst_mode_get added nothing
to the mode->info as the bnxt_rx_burst_info was not
populated with an entry for the v3. Added an entry
for v3 in bnxt_rx_burst_info.
Fixes: 15276ba987bd ("net/bnxt: fix getting burst mode for Arm")
Cc: stable@dpdk.org
Signed-off-by: Keegan Freyhof <keegan.freyhof@broadcom.com>
Signed-off-by: Mohammad Shuab Siddique <mohammad-shuab.siddique@broadcom.com>
---
drivers/net/bnxt/bnxt_ethdev.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 791a89f040..63f9f6fb48 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -3326,6 +3326,7 @@ static const struct {
{bnxt_recv_pkts_vec, "Vector SSE"},
{bnxt_crx_pkts_vec_avx2, "Vector AVX2"},
{bnxt_recv_pkts_vec_avx2, "Vector AVX2"},
+ {bnxt_recv_pkts_vec_avx2_v3, "Vector AVX2"},
#endif
#if defined(RTE_ARCH_ARM64)
{bnxt_recv_pkts_vec, "Vector Neon"},
--
2.47.3
^ permalink raw reply related
* [PATCH 08/10] net/bnxt: fix for VLAN stripping being set incorrectly
From: Mohammad Shuab Siddique @ 2026-06-04 3:18 UTC (permalink / raw)
To: dev; +Cc: kishore.padmanabha, stable, Keegan Freyhof,
Mohammad Shuab Siddique
In-Reply-To: <20260604031851.2267548-1-Mohammad-Shuab.Siddique@broadcom.com>
From: Keegan Freyhof <keegan.freyhof@broadcom.com>
Driver was setting the VLAN strip ol flag based on port
settings rather than per packet for V3. This caused
TruFlow's per packet flows to incorrectly not report
VLAN_STRIPPED, as the TruFlow might set a flow to strip
VLAN based on other markers in the packet rather than
always for the port. Changed the logic to set the flag
per packet.
Fixes: 15276ba987bd ("net/bnxt: fix getting burst mode for Arm")
Cc: stable@dpdk.org
Signed-off-by: Keegan Freyhof <keegan.freyhof@broadcom.com>
Signed-off-by: Mohammad Shuab Siddique <mohammad-shuab.siddique@broadcom.com>
---
drivers/net/bnxt/bnxt_rxr.c | 6 +--
drivers/net/bnxt/bnxt_rxr.h | 12 +++---
drivers/net/bnxt/bnxt_rxtx_vec_avx2.c | 54 +++++++++++++++++++++++----
3 files changed, 56 insertions(+), 16 deletions(-)
diff --git a/drivers/net/bnxt/bnxt_rxr.c b/drivers/net/bnxt/bnxt_rxr.c
index ee49d85d43..0fab4ddf78 100644
--- a/drivers/net/bnxt/bnxt_rxr.c
+++ b/drivers/net/bnxt/bnxt_rxr.c
@@ -1127,7 +1127,6 @@ static int bnxt_rx_pkt(struct rte_mbuf **rx_pkt,
uint16_t cmp_type;
uint32_t vfr_flag = 0, mark_id = 0;
struct bnxt *bp = rxq->bp;
- struct bnxt_vnic_info *vnic = rxq->vnic;
rxcmp = (struct rx_pkt_cmpl *)
&cpr->cp_desc_ring[cp_cons];
@@ -1236,8 +1235,7 @@ static int bnxt_rx_pkt(struct rte_mbuf **rx_pkt,
if (cmp_type == CMPL_BASE_TYPE_RX_L2_V3) {
bnxt_parse_csum_v3(mbuf, rxcmp1);
bnxt_parse_pkt_type_v3(mbuf, rxcmp, rxcmp1);
- bnxt_rx_vlan_v3(mbuf, rxcmp, rxcmp1, vnic->vlan_strip);
-
+ bnxt_rx_vlan_v3(mbuf, rxcmp, rxcmp1);
/* Packet cannot be a PTP ethertype if it is detected as L4 */
if (mbuf->ol_flags & RTE_MBUF_F_RX_L4_CKSUM_GOOD) {
mbuf->ol_flags &= ~RTE_MBUF_F_RX_IEEE1588_PTP;
@@ -1259,7 +1257,7 @@ static int bnxt_rx_pkt(struct rte_mbuf **rx_pkt,
if (cmp_type == CMPL_BASE_TYPE_RX_L2_V2) {
bnxt_parse_csum_v2(mbuf, rxcmp1);
bnxt_parse_pkt_type_v2(mbuf, rxcmp, rxcmp1);
- bnxt_rx_vlan_v2(mbuf, rxcmp, rxcmp1);
+ bnxt_rx_vlan_v2(mbuf, bp, rxcmp, rxcmp1);
/* TODO Add support for cfa_code parsing */
goto reuse_rx_mbuf;
}
diff --git a/drivers/net/bnxt/bnxt_rxr.h b/drivers/net/bnxt/bnxt_rxr.h
index 352d509210..c971233dc3 100644
--- a/drivers/net/bnxt/bnxt_rxr.h
+++ b/drivers/net/bnxt/bnxt_rxr.h
@@ -276,12 +276,15 @@ static inline void bnxt_set_vlan(struct rx_pkt_cmpl_hi *rxcmp1,
RX_PKT_V2_CMPL_HI_METADATA0_PRI_MASK))
static inline void bnxt_rx_vlan_v2(struct rte_mbuf *mbuf,
+ const struct bnxt *bp,
struct rx_pkt_cmpl *rxcmp,
struct rx_pkt_cmpl_hi *rxcmp1)
{
if (RX_CMP_VLAN_VALID(rxcmp)) {
mbuf->vlan_tci = RX_CMP_METADATA0_VID(rxcmp1);
- mbuf->ol_flags |= RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED;
+ mbuf->ol_flags |= RTE_MBUF_F_RX_VLAN;
+ if (BNXT_RX_VLAN_STRIP_EN(bp))
+ mbuf->ol_flags |= RTE_MBUF_F_RX_VLAN_STRIPPED;
}
}
@@ -483,14 +486,13 @@ bnxt_parse_pkt_type_v2(struct rte_mbuf *mbuf,
RX_PKT_V3_CMPL_HI_METADATA0_PRI_MASK))
static inline void bnxt_rx_vlan_v3(struct rte_mbuf *mbuf,
- struct rx_pkt_cmpl *rxcmp,
- struct rx_pkt_cmpl_hi *rxcmp1,
- bool stripped)
+ struct rx_pkt_cmpl *rxcmp,
+ struct rx_pkt_cmpl_hi *rxcmp1)
{
if (RX_CMP_V3_VLAN_VALID(rxcmp)) {
mbuf->vlan_tci = RX_CMP_V3_METADATA0_VID(rxcmp1);
mbuf->ol_flags |= RTE_MBUF_F_RX_VLAN;
- if (stripped)
+ if (rxcmp1->flags2 & RX_PKT_V3_CMPL_HI_FLAGS2_META_FORMAT_MASK)
mbuf->ol_flags |= RTE_MBUF_F_RX_VLAN_STRIPPED;
}
}
diff --git a/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c b/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c
index 5e22b4fc11..38aca98cb1 100644
--- a/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c
+++ b/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c
@@ -70,6 +70,17 @@ recv_burst_vec_avx2(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
_mm256_set1_epi32(RX_PKT_CMPL_FLAGS2_IP_TYPE);
const __m256i rss_mask =
_mm256_set1_epi32(RX_PKT_CMPL_FLAGS_RSS_VALID);
+ /*
+ * ol_flags_table already sets RX_VLAN|RX_VLAN_STRIPPED when VLAN strip
+ * is enabled. For completeness, also OR in the flags here based on the
+ * per-packet VLAN-metadata bit so that the two sources agree. The
+ * constant is broadcast once: non-zero only when strip offload is on.
+ */
+ const __m256i vlan_ol_val =
+ BNXT_RX_VLAN_STRIP_EN(rxq->bp) ?
+ _mm256_set1_epi32((uint32_t)(RTE_MBUF_F_RX_VLAN |
+ RTE_MBUF_F_RX_VLAN_STRIPPED)) :
+ _mm256_setzero_si256();
__m256i t0, t1, flags_type, flags2, index, errors;
__m256i ptype_idx, ptypes, is_tunnel;
__m256i mbuf01, mbuf23, mbuf45, mbuf67;
@@ -286,6 +297,25 @@ recv_burst_vec_avx2(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
rss_flags = _mm256_srli_epi32(rss_flags, 9);
ol_flags = _mm256_or_si256(ol_flags, errors);
ol_flags = _mm256_or_si256(ol_flags, rss_flags);
+ /*
+ * Set RX_VLAN | RX_VLAN_STRIPPED for packets whose vlan_tci
+ * is non-zero (i.e. hardware reported VLAN metadata, indicated
+ * by RX_PKT_CMPL_FLAGS2_META_FORMAT_VLAN in index bit 4).
+ * vlan_ol_val is the broadcast constant computed before the
+ * loop: non-zero only when VLAN RX strip offload is enabled.
+ * _mm256_cmpeq_epi32 produces 0xFFFFFFFF per lane when the
+ * VLAN bit is set, masking the constant to those lanes only.
+ */
+ {
+ const __m256i vlan_bit =
+ _mm256_set1_epi32(RX_PKT_CMPL_FLAGS2_META_FORMAT_VLAN);
+ __m256i vlan_mask =
+ _mm256_cmpeq_epi32(_mm256_and_si256(index, vlan_bit),
+ vlan_bit);
+ ol_flags = _mm256_or_si256(ol_flags,
+ _mm256_and_si256(vlan_mask,
+ vlan_ol_val));
+ }
ol_flags_hi = _mm256_permute2f128_si256(ol_flags,
ol_flags, 0x11);
@@ -908,7 +938,6 @@ static uint16_t
recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
{
struct bnxt_rx_queue *rxq = rx_queue;
- struct bnxt_vnic_info *vnic = rxq->vnic;
const __m256i mbuf_init =
_mm256_set_epi64x(0, 0, 0, rxq->mbuf_initializer);
struct bnxt_cp_ring_info *cpr = rxq->cp_ring;
@@ -1001,8 +1030,8 @@ recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pk
mbcons += BNXT_RX_DESCS_PER_LOOP_VEC256) {
__m256i desc0, desc1, desc2, desc3, desc4, desc5, desc6, desc7;
__m256i rxcmp0_1, rxcmp2_3, rxcmp4_5, rxcmp6_7, info3_v;
+ __m256i errors_v2, cs_calc, cs_valid, meta_format;
__m256i md1_0123, lo2_3, md1_4567, lo6_7;
- __m256i errors_v2, cs_calc, cs_valid;
uint32_t num_valid;
t0 = _mm256_loadu_si256((void *)&rxr->rx_buf_ring[mbcons]);
@@ -1070,7 +1099,9 @@ recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pk
flags2 = _mm256_unpackhi_epi64(t0, t1);
/* fs mask used for RX_PKT_CMPL_CALC */
cs_calc = _mm256_and_si256(flags2, mask_fs);
- cs_valid = _mm256_cmpeq_epi32(cs_calc, _mm256_setzero_si256());
+ /* Add the meta_format to cs_calc */
+ cs_calc = _mm256_or_si256(cs_calc, _mm256_and_si256(flags2,
+ _mm256_slli_epi32(mask_fs, 4)));
/* Extract metadata0 and errors from high completion */
t0 = _mm256_unpackhi_epi32(rxcmp0_1, rxcmp2_3);
@@ -1082,6 +1113,11 @@ recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pk
*/
errors_csum_idx = _mm256_srli_epi32(_mm256_and_si256(errors_v2,
_mm256_slli_epi32(mask_fs, 4)), 4);
+ meta_format = _mm256_cmpeq_epi32(_mm256_and_si256(cs_calc,
+ _mm256_slli_epi32(mask_fs, 4)),
+ _mm256_setzero_si256());
+ cs_valid = _mm256_cmpeq_epi32(_mm256_and_si256(cs_calc, mask_fs),
+ _mm256_setzero_si256());
errors_csum_idx = _mm256_andnot_si256(cs_valid, errors_csum_idx);
/*
@@ -1104,10 +1140,14 @@ recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pk
vlan_flags = _mm256_and_si256(metadata1, _mm256_slli_epi32(mask_1s, 15));
vlan_flags = _mm256_min_epu32(vlan_flags, mask_1s);
- if (vnic->vlan_strip) {
- vlan_flags = _mm256_or_si256(vlan_flags,
- _mm256_slli_epi32(vlan_flags, 6));
- }
+ /*
+ * VLAN present in mbuf when metadata valid (vlan_flags) and
+ * meta_format is non-zero in flags2. andnot(cmpeq(tci,0), vlan_flags) is
+ * (~zero_mask) & vlan_flags.
+ */
+ t0 = _mm256_andnot_si256(meta_format, vlan_flags);
+ /* RTE_MBUF_F_RX_VLAN + STRIPPED when hardware reports valid VLAN. */
+ vlan_flags = _mm256_or_si256(vlan_flags, _mm256_slli_epi32(t0, 6));
/* Extract flags_type from low completion for eight packets */
t0 = _mm256_unpacklo_epi32(rxcmp0_1, rxcmp2_3);
--
2.47.3
^ permalink raw reply related
* [PATCH 07/10] net/bnxt: optimization of the AVX2 RX paths
From: Mohammad Shuab Siddique @ 2026-06-04 3:18 UTC (permalink / raw)
To: dev; +Cc: kishore.padmanabha, stable, Keegan Freyhof,
Mohammad Shuab Siddique
In-Reply-To: <20260604031851.2267548-1-Mohammad-Shuab.Siddique@broadcom.com>
From: Keegan Freyhof <keegan.freyhof@broadcom.com>
Fixed some dead code and some variable names to make them more
descriptive. Also optimized the V3 path to stay under 16
registers.
Signed-off-by: Keegan Freyhof <keegan.freyhof@broadcom.com>
Signed-off-by: Mohammad Shuab Siddique <mohammad-shuab.siddique@broadcom.com>
---
drivers/net/bnxt/bnxt_rxtx_vec_avx2.c | 240 +++++++++++-------------
drivers/net/bnxt/bnxt_rxtx_vec_common.h | 2 +-
2 files changed, 114 insertions(+), 128 deletions(-)
diff --git a/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c b/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c
index 46b51b20e4..5e22b4fc11 100644
--- a/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c
+++ b/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c
@@ -187,15 +187,12 @@ recv_burst_vec_avx2(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
t0 = _mm256_unpacklo_epi32(rxcmp0_1, rxcmp2_3);
t1 = _mm256_unpacklo_epi32(rxcmp4_5, rxcmp6_7);
flags_type = _mm256_unpacklo_epi64(t0, t1);
+ flags2 = _mm256_unpackhi_epi64(t0, t1);
ptype_idx = _mm256_and_si256(flags_type, flags_type_mask);
ptype_idx = _mm256_srli_epi32(ptype_idx,
RX_PKT_CMPL_FLAGS_ITYPE_SFT -
BNXT_PTYPE_TBL_TYPE_SFT);
- t0 = _mm256_unpacklo_epi32(rxcmp0_1, rxcmp2_3);
- t1 = _mm256_unpacklo_epi32(rxcmp4_5, rxcmp6_7);
- flags2 = _mm256_unpackhi_epi64(t0, t1);
-
t0 = _mm256_srli_epi32(_mm256_and_si256(flags2, flags2_mask1),
RX_PKT_CMPL_FLAGS2_META_FORMAT_SFT -
BNXT_PTYPE_TBL_VLAN_SFT);
@@ -251,9 +248,6 @@ recv_burst_vec_avx2(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
* bits and count the number of set bits in order to determine
* the number of valid descriptors.
*/
- const __m256i perm_msk =
- _mm256_set_epi32(7, 3, 6, 2, 5, 1, 4, 0);
- info3_v = _mm256_permutevar8x32_epi32(errors_v2, perm_msk);
info3_v = _mm256_and_si256(errors_v2, info3_v_mask);
info3_v = _mm256_xor_si256(info3_v, valid_target);
@@ -904,7 +898,6 @@ bnxt_xmit_pkts_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
return nb_sent;
}
-
/*
* V3 (Thor2) RX burst processing - AVX2 vectorized implementation
*
@@ -924,7 +917,6 @@ recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pk
uint16_t rx_ring_size = rxr->rx_ring_struct->ring_size;
struct cmpl_base *cp_desc_ring = cpr->cp_desc_ring;
uint64_t valid, desc_valid_mask = ~0ULL;
- const __m256i info3_v_mask = _mm256_set1_epi32(CMPL_BASE_V);
uint32_t raw_cons = cpr->cp_raw_cons;
uint32_t cons, mbcons;
int nb_rx_pkts = 0;
@@ -937,12 +929,12 @@ recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pk
*/
const __m256i shuf_msk =
_mm256_set_epi8(15, 14, 13, 12, /* rss */
- 0xFF, 0xFF, /* vlan_tci (filled separately) */
+ 11, 10, /* vlan_tci */
3, 2, /* data_len */
0xFF, 0xFF, 3, 2, /* pkt_len */
0xFF, 0xFF, 0xFF, 0xFF, /* pkt_type (zeroes) */
15, 14, 13, 12, /* rss */
- 0xFF, 0xFF, /* vlan_tci (filled separately) */
+ 11, 10, /* vlan_tci */
3, 2, /* data_len */
0xFF, 0xFF, 3, 2, /* pkt_len */
0xFF, 0xFF, 0xFF, 0xFF); /* pkt_type (zeroes) */
@@ -952,40 +944,24 @@ recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pk
_mm256_set_epi8(0xff, 0xff, 0xff, 0xff, /* Zeroes */
11, 10, /* metadata0 (vlan_tci) */
9, 8, /* errors_v2 */
- 5, 4, /* metadata1 (payload_offset) */
+ 5, 4, /* metadata2 */
1, 0, /* flags2 low */
0xff, 0xff, 0xff, 0xff, /* Zeroes */
0xff, 0xff, 0xff, 0xff, /* Zeroes */
11, 10, /* metadata0 (vlan_tci) */
9, 8, /* errors_v2 */
- 5, 4, /* metadata1 (payload_offset) */
+ 5, 4, /* metadata2 */
1, 0, /* flags2 low */
0xff, 0xff, 0xff, 0xff); /* Zeroes */
+ const __m256i mask_1s =
+ _mm256_set1_epi32(0x1);
+ const __m256i mask_fs =
+ _mm256_set1_epi32(0xf);
- const __m256i flags_type_mask =
- _mm256_set1_epi32(RX_PKT_V3_CMPL_FLAGS_ITYPE_MASK);
- const __m256i flags2_ip_type_mask =
- _mm256_set1_epi32(RX_PKT_V3_CMPL_HI_FLAGS2_IP_TYPE);
- const __m256i rss_mask =
- _mm256_set1_epi32(RX_PKT_V3_CMPL_FLAGS_RSS_VALID);
- const __m256i metadata1_valid_mask =
- _mm256_set1_epi32(RX_PKT_V3_CMPL_METADATA1_VALID);
- const __m256i vlan_tci_mask =
- _mm256_set1_epi32(RX_PKT_V3_CMPL_HI_METADATA0_VID_MASK |
- RX_PKT_V3_CMPL_HI_METADATA0_DE |
- RX_PKT_V3_CMPL_HI_METADATA0_PRI_MASK);
- const __m256i cs_err_mask =
- _mm256_set1_epi32(RX_PKT_CMPL_ERRORS_T_L4_CS_ERROR |
- RX_PKT_CMPL_ERRORS_T_IP_CS_ERROR |
- RX_PKT_CMPL_ERRORS_L4_CS_ERROR |
- RX_PKT_CMPL_ERRORS_IP_CS_ERROR);
- const __m256i cs_calc_mask =
- _mm256_set1_epi32(RX_PKT_CMPL_CALC);
-
- __m256i t0, t1, flags_type, flags2, errors, metadata1;
- __m256i ptype_idx, ptypes, vlan_tci, vlan_flags;
- __m256i mbuf01, mbuf23, mbuf45, mbuf67;
__m256i rearm0, rearm1, rearm2, rearm3, rearm4, rearm5, rearm6, rearm7;
+ __m256i t0, t1, flags_type, flags2, errors_csum_idx, metadata1;
+ __m256i mbuf01, mbuf23, mbuf45, mbuf67;
+ __m256i ptype_idx, ptypes, vlan_flags;
__m256i ol_flags, ol_flags_hi;
__m256i rss_flags;
@@ -1025,7 +1001,8 @@ recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pk
mbcons += BNXT_RX_DESCS_PER_LOOP_VEC256) {
__m256i desc0, desc1, desc2, desc3, desc4, desc5, desc6, desc7;
__m256i rxcmp0_1, rxcmp2_3, rxcmp4_5, rxcmp6_7, info3_v;
- __m256i errors_v2, meta0_err, cs_calc, cs_valid;
+ __m256i md1_0123, lo2_3, md1_4567, lo6_7;
+ __m256i errors_v2, cs_calc, cs_valid;
uint32_t num_valid;
t0 = _mm256_loadu_si256((void *)&rxr->rx_buf_ring[mbcons]);
@@ -1057,119 +1034,134 @@ recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pk
/*
* Pack needed fields from each descriptor pair.
- * For V3: extract rxcmp (low) for flags_type, len, rss
+ * extract rxcmp (low) for flags_type, len, rss
* and rxcmp1 (hi) for flags2, metadata0, metadata1, errors_v2
+ * metadata1 is incrementally extracted to save on
+ * register pressure
*/
t0 = _mm256_permute2f128_si256(desc6, desc7, 0x20);
t1 = _mm256_permute2f128_si256(desc6, desc7, 0x31);
t1 = _mm256_shuffle_epi8(t1, dsc_shuf_msk);
rxcmp6_7 = _mm256_blend_epi32(t0, t1, 0x66);
+ lo6_7 = t0;
t0 = _mm256_permute2f128_si256(desc4, desc5, 0x20);
t1 = _mm256_permute2f128_si256(desc4, desc5, 0x31);
t1 = _mm256_shuffle_epi8(t1, dsc_shuf_msk);
rxcmp4_5 = _mm256_blend_epi32(t0, t1, 0x66);
+ md1_4567 = _mm256_unpackhi_epi32(t0, lo6_7);
t0 = _mm256_permute2f128_si256(desc2, desc3, 0x20);
t1 = _mm256_permute2f128_si256(desc2, desc3, 0x31);
t1 = _mm256_shuffle_epi8(t1, dsc_shuf_msk);
rxcmp2_3 = _mm256_blend_epi32(t0, t1, 0x66);
+ lo2_3 = t0;
t0 = _mm256_permute2f128_si256(desc0, desc1, 0x20);
t1 = _mm256_permute2f128_si256(desc0, desc1, 0x31);
t1 = _mm256_shuffle_epi8(t1, dsc_shuf_msk);
rxcmp0_1 = _mm256_blend_epi32(t0, t1, 0x66);
+ md1_0123 = _mm256_unpackhi_epi32(t0, lo2_3);
+ metadata1 = _mm256_unpacklo_epi64(md1_0123, md1_4567);
- /* Extract flags_type from low completion for eight packets */
- t0 = _mm256_unpacklo_epi32(rxcmp0_1, rxcmp2_3);
- t1 = _mm256_unpacklo_epi32(rxcmp4_5, rxcmp6_7);
- flags_type = _mm256_unpacklo_epi64(t0, t1);
-
- /* Compute ptype_idx from flags_type itype field */
- ptype_idx = _mm256_and_si256(flags_type, flags_type_mask);
- ptype_idx = _mm256_srli_epi32(ptype_idx,
- RX_PKT_V3_CMPL_FLAGS_ITYPE_SFT -
- BNXT_PTYPE_TBL_TYPE_SFT);
-
- /* Extract flags2 from high completion */
+ /* Extract flags2 from high completion for eight packets */
t0 = _mm256_unpacklo_epi32(rxcmp0_1, rxcmp2_3);
t1 = _mm256_unpacklo_epi32(rxcmp4_5, rxcmp6_7);
flags2 = _mm256_unpackhi_epi64(t0, t1);
+ /* fs mask used for RX_PKT_CMPL_CALC */
+ cs_calc = _mm256_and_si256(flags2, mask_fs);
+ cs_valid = _mm256_cmpeq_epi32(cs_calc, _mm256_setzero_si256());
- t0 = _mm256_srli_epi32(_mm256_and_si256(flags2, flags2_ip_type_mask),
- RX_PKT_V3_CMPL_FLAGS2_IP_TYPE_SFT -
- BNXT_PTYPE_TBL_IP_VER_SFT);
- ptype_idx = _mm256_or_si256(ptype_idx, t0);
-
- /*
- * Extract metadata1 (contains VLAN valid bit) from LOW completion.
- * metadata1_payload_offset is at word 2 of rxcmp (low 128 bits of desc).
+ /* Extract metadata0 and errors from high completion */
+ t0 = _mm256_unpackhi_epi32(rxcmp0_1, rxcmp2_3);
+ t1 = _mm256_unpackhi_epi32(rxcmp4_5, rxcmp6_7);
+ errors_v2 = _mm256_unpacklo_epi64(t0, t1);
+ /* mask_fs used in place of RX_PKT_CMPL_ERRORS_T_L4_CS_ERROR |
+ * RX_PKT_CMPL_ERRORS_T_IP_CS_ERROR | RX_PKT_CMPL_ERRORS_L4_CS_ERROR |
+ * RX_PKT_CMPL_ERRORS_IP_CS_ERROR
*/
- {
- __m128i m01, m23, hi;
- hi =
- _mm_unpacklo_epi64(_mm_unpackhi_epi32(_mm256_castsi256_si128(desc4),
- _mm256_castsi256_si128(desc5)),
- _mm_unpackhi_epi32(_mm256_castsi256_si128(desc6),
- _mm256_castsi256_si128(desc7)));
- m01 = _mm_unpackhi_epi32(_mm256_castsi256_si128(desc0),
- _mm256_castsi256_si128(desc1));
- m23 = _mm_unpackhi_epi32(_mm256_castsi256_si128(desc2),
- _mm256_castsi256_si128(desc3));
- metadata1 =
- _mm256_inserti128_si256(_mm256_castsi128_si256(_mm_unpacklo_epi64(m01,
- m23)), hi, 1);
- }
- metadata1 = _mm256_srli_epi32(metadata1, 16);
-
- t0 = _mm256_srli_epi32(_mm256_and_si256(metadata1, metadata1_valid_mask),
- RX_PKT_V3_CMPL_METADATA1_VALID_SFT -
- BNXT_PTYPE_TBL_VLAN_SFT);
- ptype_idx = _mm256_or_si256(ptype_idx, t0);
+ errors_csum_idx = _mm256_srli_epi32(_mm256_and_si256(errors_v2,
+ _mm256_slli_epi32(mask_fs, 4)), 4);
+ errors_csum_idx = _mm256_andnot_si256(cs_valid, errors_csum_idx);
/*
- * Load ptypes for eight packets using gather.
+ * Load ol_flags for eight packets using gather. Gather
+ * operations have extremely high latency (~19 cycles),
+ * execution and use of result should be separated as much
+ * as possible.
*/
- ptypes = _mm256_i32gather_epi32((int *)bnxt_ptype_table,
- ptype_idx, sizeof(uint32_t));
-
- /* Extract RSS valid flags for eight packets */
- rss_flags = _mm256_and_si256(flags_type, rss_mask);
- rss_flags = _mm256_srli_epi32(rss_flags, 9);
-
- /* Extract metadata0 (contains vlan_tci) and errors from high completion */
- t0 = _mm256_unpackhi_epi32(rxcmp0_1, rxcmp2_3);
- t1 = _mm256_unpackhi_epi32(rxcmp4_5, rxcmp6_7);
- meta0_err = _mm256_unpacklo_epi64(t0, t1);
+ ol_flags = _mm256_i32gather_epi32((const int *)errors_to_olflags_v3,
+ errors_csum_idx, sizeof(uint32_t));
- /* Extract vlan_tci from high 16 bits of meta0_err (metadata0) */
- vlan_tci = _mm256_and_si256(_mm256_srli_epi32(meta0_err, 16), vlan_tci_mask);
+ /* Exctract if the packet is VLAN and the VLAN tci */
+ metadata1 = _mm256_srli_epi32(metadata1, 16);
+ /* mask_1s used in place of RX_PKT_V3_CMPL_METADATA1_VALID */
+ ptype_idx = _mm256_srli_epi32(_mm256_and_si256(metadata1,
+ _mm256_slli_epi32(mask_1s, 15)),
+ RX_PKT_V3_CMPL_METADATA1_VALID_SFT -
+ BNXT_PTYPE_TBL_VLAN_SFT);
- vlan_flags = _mm256_and_si256(metadata1, metadata1_valid_mask);
- vlan_flags = _mm256_min_epu32(vlan_flags, _mm256_set1_epi32(1));
+ vlan_flags = _mm256_and_si256(metadata1, _mm256_slli_epi32(mask_1s, 15));
+ vlan_flags = _mm256_min_epu32(vlan_flags, mask_1s);
if (vnic->vlan_strip) {
vlan_flags = _mm256_or_si256(vlan_flags,
- _mm256_slli_epi32(vlan_flags, 6));
+ _mm256_slli_epi32(vlan_flags, 6));
}
- errors_v2 = meta0_err;
+ /* Extract flags_type from low completion for eight packets */
+ t0 = _mm256_unpacklo_epi32(rxcmp0_1, rxcmp2_3);
+ t1 = _mm256_unpacklo_epi32(rxcmp4_5, rxcmp6_7);
+ flags_type = _mm256_unpacklo_epi64(t0, t1);
- errors = _mm256_srli_epi32(_mm256_and_si256(meta0_err, cs_err_mask), 4);
+ /* Compute ptype_idx from flags_type itype field
+ * mask_fs is used in place of
+ * RX_PKT_V3_CMPL_FLAGS_ITYPE_MASK
+ */
+ t0 = _mm256_and_si256(flags_type,
+ _mm256_slli_epi32(mask_fs, 12));
+ t0 = _mm256_srli_epi32(t0, RX_PKT_V3_CMPL_FLAGS_ITYPE_SFT -
+ BNXT_PTYPE_TBL_TYPE_SFT);
+ ptype_idx = _mm256_or_si256(ptype_idx, t0);
- cs_calc = _mm256_and_si256(flags2, cs_calc_mask);
+ /* Extract flags2 from low completion for eight packets
+ * flags2 is re-extracted to save on registers
+ */
+ t0 = _mm256_unpacklo_epi32(rxcmp0_1, rxcmp2_3);
+ t1 = _mm256_unpacklo_epi32(rxcmp4_5, rxcmp6_7);
+ flags2 = _mm256_unpackhi_epi64(t0, t1);
+
+ /* mask_fs is being used in place of
+ * RX_PKT_CMPL_CALC
+ */
+ cs_calc = _mm256_and_si256(flags2, mask_fs);
cs_valid = _mm256_cmpeq_epi32(cs_calc, _mm256_setzero_si256());
- errors = _mm256_andnot_si256(cs_valid, errors);
- ol_flags = _mm256_i32gather_epi32((const int *)errors_to_olflags_v3,
- errors, sizeof(uint32_t));
- __m256i unknown_flags = _mm256_and_si256(cs_valid,
- _mm256_set1_epi32(RTE_MBUF_F_RX_IP_CKSUM_UNKNOWN));
- ol_flags = _mm256_or_si256(ol_flags, unknown_flags);
+ ol_flags = _mm256_andnot_si256(cs_valid, ol_flags);
- const __m256i perm_msk =
- _mm256_set_epi32(7, 3, 6, 2, 5, 1, 4, 0);
- info3_v = _mm256_permutevar8x32_epi32(errors_v2, perm_msk);
- info3_v = _mm256_and_si256(errors_v2, info3_v_mask);
+ /* mask_1s is being used in place of
+ * RX_PKT_V3_CMPL_HI_FLAGS2_IP_TYPE
+ */
+ t0 = _mm256_srli_epi32(_mm256_and_si256(flags2,
+ _mm256_slli_epi32(mask_1s, 8)),
+ RX_PKT_V3_CMPL_FLAGS2_IP_TYPE_SFT -
+ BNXT_PTYPE_TBL_IP_VER_SFT);
+ ptype_idx = _mm256_or_si256(ptype_idx, t0);
+
+ /*
+ * Load ptypes for eight packets using gather. Gather operations
+ * have extremely high latency (~19 cycles), execution and use
+ * of result should be separated as much as possible.
+ */
+ ptypes = _mm256_i32gather_epi32((int *)bnxt_ptype_table,
+ ptype_idx, sizeof(uint32_t));
+
+ /*
+ * Pack the 128-bit array of valid descriptor flags into 64
+ * bits and count the number of set bits in order to determine
+ * the number of valid descriptors.
+ * mask_1s is used in place of CMPL_BASE_V
+ */
+ info3_v = _mm256_and_si256(errors_v2, mask_1s);
info3_v = _mm256_xor_si256(info3_v, valid_target);
info3_v = _mm256_packs_epi32(info3_v, _mm256_setzero_si256());
@@ -1181,6 +1173,11 @@ recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pk
if (num_valid == 0)
break;
+ /* Extract flags_type from low completion for eight packets*/
+ t0 = _mm256_unpacklo_epi32(rxcmp0_1, rxcmp2_3);
+ t1 = _mm256_unpacklo_epi32(rxcmp4_5, rxcmp6_7);
+ flags_type = _mm256_unpacklo_epi64(t0, t1);
+
mbuf01 = _mm256_shuffle_epi8(rxcmp0_1, shuf_msk);
mbuf23 = _mm256_shuffle_epi8(rxcmp2_3, shuf_msk);
mbuf45 = _mm256_shuffle_epi8(rxcmp4_5, shuf_msk);
@@ -1194,29 +1191,18 @@ recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pk
mbuf67 = _mm256_blend_epi32(mbuf67,
_mm256_srli_si256(ptypes, 12), 0x11);
- const __m256i tci_perm_01 = _mm256_set_epi32(1, 1, 1, 1, 0, 0, 0, 0);
- const __m256i tci_perm_23 = _mm256_set_epi32(3, 3, 3, 3, 2, 2, 2, 2);
- const __m256i tci_perm_45 = _mm256_set_epi32(5, 5, 5, 5, 4, 4, 4, 4);
- const __m256i tci_perm_67 = _mm256_set_epi32(7, 7, 7, 7, 6, 6, 6, 6);
-
- mbuf01 = _mm256_blend_epi16(mbuf01,
- _mm256_slli_si256(_mm256_permutevar8x32_epi32(vlan_tci,
- tci_perm_01), 10), 0x20);
- mbuf23 = _mm256_blend_epi16(mbuf23,
- _mm256_slli_si256(_mm256_permutevar8x32_epi32(vlan_tci,
- tci_perm_23), 10), 0x20);
- mbuf45 = _mm256_blend_epi16(mbuf45,
- _mm256_slli_si256(_mm256_permutevar8x32_epi32(vlan_tci,
- tci_perm_45), 10), 0x20);
- mbuf67 = _mm256_blend_epi16(mbuf67,
- _mm256_slli_si256(_mm256_permutevar8x32_epi32(vlan_tci,
- tci_perm_67), 10), 0x20);
-
rearm0 = _mm256_permute2f128_si256(mbuf_init, mbuf01, 0x20);
rearm1 = _mm256_blend_epi32(mbuf_init, mbuf01, 0xF0);
rearm2 = _mm256_permute2f128_si256(mbuf_init, mbuf23, 0x20);
rearm3 = _mm256_blend_epi32(mbuf_init, mbuf23, 0xF0);
+ /* Extract RSS valid flags for eight packets
+ * mask_1s is being used in place of
+ * RX_PKT_V3_CMPL_FLAGS_RSS_VALID
+ */
+ rss_flags = _mm256_and_si256(flags_type,
+ _mm256_slli_epi32(mask_1s, 10));
+ rss_flags = _mm256_srli_epi32(rss_flags, 9);
ol_flags = _mm256_or_si256(ol_flags, rss_flags);
ol_flags = _mm256_or_si256(ol_flags, vlan_flags);
ol_flags_hi = _mm256_permute2f128_si256(ol_flags,
diff --git a/drivers/net/bnxt/bnxt_rxtx_vec_common.h b/drivers/net/bnxt/bnxt_rxtx_vec_common.h
index e8da010dc3..d8659d1001 100644
--- a/drivers/net/bnxt/bnxt_rxtx_vec_common.h
+++ b/drivers/net/bnxt/bnxt_rxtx_vec_common.h
@@ -178,7 +178,7 @@ bnxt_tx_cmp_vec(struct bnxt_tx_queue *txq, uint32_t nr_pkts)
txr->tx_raw_cons = raw_cons;
}
-static const uint64_t errors_to_olflags_v3[16] = {
+static const uint32_t errors_to_olflags_v3[16] = {
RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD | RTE_MBUF_F_RX_L4_CKSUM_GOOD |
RTE_MBUF_F_RX_IP_CKSUM_GOOD,
RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD | RTE_MBUF_F_RX_L4_CKSUM_GOOD |
--
2.47.3
^ permalink raw reply related
* [PATCH 06/10] net/bnxt: fix packet burst truncation after invalid Tx descriptor descriptor
From: Mohammad Shuab Siddique @ 2026-06-04 3:18 UTC (permalink / raw)
To: dev; +Cc: kishore.padmanabha, stable, Zoe Cheimets, Mohammad Shuab Siddique
In-Reply-To: <20260604031851.2267548-1-Mohammad-Shuab.Siddique@broadcom.com>
From: Zoe Cheimets <zoe.cheimets@broadcom.com>
When bnxt_start_xmit() returned -EINVAL for a bad packet, the burst
loop broke immediately, dropping all subsequent valid packets. The
Tx ring was also left in a corrupt state because tx_raw_prod was not
rolled back after a partial descriptor write. Additionally, the
tx_mbuf_drop oerrors accumulation was gated behind a tx_started
check, silently omitting drops from the statistics.
Fix by rolling back tx_raw_prod and any partially-written ring slots
on the drop path, replacing the break with continue so the burst
loop keeps processing remaining packets, and moving the tx_mbuf_drop
read to before the tx_started guard in both stats paths. Return
value is corrected to RTE_MIN(nb_tx_pkts + dropped, nb_pkts) to
accurately report consumed packet count.
Fixes: 220de9869bc3 ("net/bnxt: optimize Tx batching")
Cc: stable@dpdk.org
Signed-off-by: Zoe Cheimets <zoe.cheimets@broadcom.com>
Signed-off-by: Mohammad Shuab Siddique <mohammad-shuab.siddique@broadcom.com>
---
drivers/net/bnxt/bnxt_txr.c | 34 ++++++++++++++++++++++++++++++----
1 file changed, 30 insertions(+), 4 deletions(-)
diff --git a/drivers/net/bnxt/bnxt_txr.c b/drivers/net/bnxt/bnxt_txr.c
index a6b062637c..bb9917d705 100644
--- a/drivers/net/bnxt/bnxt_txr.c
+++ b/drivers/net/bnxt/bnxt_txr.c
@@ -239,15 +239,17 @@ static int bnxt_start_xmit(struct rte_mbuf *tx_pkt,
uint16_t *coal_pkts,
struct tx_bd_long **last_txbd)
{
+ struct tx_bd_long *last_txbd_save = *last_txbd;
struct bnxt_tx_ring_info *txr = txq->tx_ring;
struct bnxt_ring *ring = txr->tx_ring_struct;
+ uint16_t tx_raw_prod_save = txr->tx_raw_prod;
uint32_t outer_tpid_bd = 0;
struct tx_bd_long *txbd;
struct tx_bd_long_hi *txbd1 = NULL;
uint32_t vlan_tag_flags;
bool long_bd = false;
unsigned short nr_bds;
- uint16_t prod;
+ uint16_t prod, idx;
bool pkt_needs_ts = 0;
struct rte_mbuf *m_seg;
struct rte_mbuf **tx_buf;
@@ -507,6 +509,24 @@ static int bnxt_start_xmit(struct rte_mbuf *tx_pkt,
return 0;
drop:
+ /* Roll back any descriptors and tx_buf_ring slots that were written
+ * for this packet before the failure was detected. Walking from the
+ * saved producer index up to (but not including) the current one is
+ * safe because we hold the Tx lock and the HW has not been notified
+ * (the doorbell is only rung after bnxt_start_xmit() returns
+ * successfully).
+ */
+ idx = tx_raw_prod_save;
+
+ while (idx != txr->tx_raw_prod) {
+ uint16_t slot = RING_IDX(ring, idx);
+
+ txr->tx_buf_ring[slot] = NULL;
+ txr->tx_desc_ring[slot].address = 0;
+ idx = RING_NEXT(idx);
+ }
+ txr->tx_raw_prod = tx_raw_prod_save;
+ *last_txbd = last_txbd_save;
rte_pktmbuf_free(tx_pkt);
ret:
return rc;
@@ -836,22 +856,28 @@ uint16_t _bnxt_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
if (unlikely(rc)) {
if (rc == -EINVAL) {
+ coal_pkts--;
rte_atomic_fetch_add_explicit(&txq->tx_mbuf_drop, 1,
rte_memory_order_relaxed);
dropped++;
+ continue;
}
break;
}
}
- if (likely(nb_tx_pkts)) {
+ /* last_txbd is used to check for if any packets have been sent in
+ * the burst as bnxt_start_xmit will update it to the most recent
+ * non-dropped buffer descriptor in the burst.
+ */
+ if (likely(last_txbd != NULL)) {
/* Request a completion on the last packet */
last_txbd->flags_type &= ~TX_BD_LONG_FLAGS_NO_CMPL;
bnxt_db_write(&txq->tx_ring->tx_db, txq->tx_ring->tx_raw_prod);
}
- nb_tx_pkts += dropped;
- return nb_tx_pkts;
+ return RTE_MIN((uint16_t)(nb_tx_pkts + dropped), nb_pkts);
+
}
int bnxt_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
--
2.47.3
^ permalink raw reply related
* [PATCH 05/10] net/bnxt: fix RX timestamping for non-PTP packets
From: Mohammad Shuab Siddique @ 2026-06-04 3:18 UTC (permalink / raw)
To: dev; +Cc: kishore.padmanabha, stable, Chenna Arnoori,
Mohammad Shuab Siddique
In-Reply-To: <20260604031851.2267548-1-Mohammad-Shuab.Siddique@broadcom.com>
From: Chenna Arnoori <chenna.arnoori@broadcom.com>
When the adapter is configured to timestamp all incoming packets,
timestamps were silently missing for non-PTP traffic (such as IPv6
packets). A previous update incorrectly restricted the timestamp
processing to only recognised PTP packets by changing an OR condition
to an AND condition. This is corrected so that timestamps are properly
extracted for all received packets when promiscuous timestamping is
enabled.
A comment is added to clarify the two conditions under which the
hardware timestamp is extracted from the completion record:
1. The packet is explicitly classified as a PTP packet (with or
without timestamp).
2. Promiscuous timestamping is enabled (ptp_all_rx_tstamp), which
instructs the hardware to timestamp all packets, including
non-PTP traffic (e.g., IPv6).
Cc: stable@dpdk.org
Fixes: 925cd0705836 ("net/bnxt: update PTP support on Thor")
Signed-off-by: Chenna Arnoori <chenna.arnoori@broadcom.com>
Signed-off-by: Mohammad Shuab Siddique <mohammad-shuab.siddique@broadcom.com>
---
drivers/net/bnxt/bnxt_rxr.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/drivers/net/bnxt/bnxt_rxr.c b/drivers/net/bnxt/bnxt_rxr.c
index 046276f931..ee49d85d43 100644
--- a/drivers/net/bnxt/bnxt_rxr.c
+++ b/drivers/net/bnxt/bnxt_rxr.c
@@ -1203,13 +1203,21 @@ static int bnxt_rx_pkt(struct rte_mbuf **rx_pkt,
mbuf->data_len = mbuf->pkt_len;
mbuf->port = rxq->port_id;
- if (unlikely((((rte_le_to_cpu_16(rxcmp->flags_type) &
+ /* Extract the hardware timestamp from the completion record if:
+ * 1. The packet is explicitly classified as a PTP packet (with or
+ * without timestamp), OR
+ * 2. Promiscuous timestamping is enabled (ptp_all_rx_tstamp), which
+ * instructs the hardware to timestamp all packets, including
+ * non-PTP traffic (e.g., IPv6).
+ */
+ if (unlikely(((rte_le_to_cpu_16(rxcmp->flags_type) &
RX_PKT_CMPL_FLAGS_MASK) ==
RX_PKT_CMPL_FLAGS_ITYPE_PTP_W_TIMESTAMP) ||
((rte_le_to_cpu_16(rxcmp->flags_type) &
RX_PKT_CMPL_FLAGS_MASK) ==
- RX_PKT_CMPL_FLAGS_ITYPE_PTP_WO_TIMESTAMP)) &&
- bp->ptp_all_rx_tstamp) && bp->ieee_1588 &&
+ RX_PKT_CMPL_FLAGS_ITYPE_PTP_WO_TIMESTAMP) ||
+ bp->ptp_all_rx_tstamp) &&
+ bp->ieee_1588 &&
bp->ptp_cfg) {
mbuf->ol_flags |= RTE_MBUF_F_RX_IEEE1588_PTP |
RTE_MBUF_F_RX_IEEE1588_TMST;
--
2.47.3
^ permalink raw reply related
* [PATCH 04/10] net/bnxt: scalar rx path disregarded rxcmp flags for setting ptp mbuf flag setting ptp mbuf flag
From: Mohammad Shuab Siddique @ 2026-06-04 3:18 UTC (permalink / raw)
To: dev; +Cc: kishore.padmanabha, stable, Mohammad Shuab Siddique,
Keegan Freyhof
In-Reply-To: <20260604031851.2267548-1-Mohammad-Shuab.Siddique@broadcom.com>
From: Mohammad Shuab Siddique <mohammad-shuab.siddique@broadcom.com>
Added a check so that if bp->ptp_all_rx_tstamp is true
- it is always set to true when set fwd ieee1588 is called via
bnxt_timesync_enable - the hardware must also report that the packet
is ptp. Also changed the code so that the path properly reports if
the packet has a timestamp.
Fixes: 925cd0705836 ("net/bnxt: update PTP support on Thor")
Cc: stable@dpdk.org
Signed-off-by: Keegan Freyhof <keegan.freyhof@broadcom.com>
Signed-off-by: Mohammad Shuab Siddique <mohammad-shuab.siddique@broadcom.com>
---
drivers/net/bnxt/bnxt_ethdev.c | 2 --
drivers/net/bnxt/bnxt_hwrm.c | 28 +++-------------------------
drivers/net/bnxt/bnxt_rxr.c | 13 ++++++++-----
drivers/net/bnxt/bnxt_stats.c | 3 +++
drivers/net/bnxt/bnxt_txr.c | 34 ++++++++++++++++++++++++++++++----
4 files changed, 14 insertions(+), 32 deletions(-)
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 5bd51de3cd..791a89f040 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -1493,8 +1493,6 @@ bnxt_receive_function(struct rte_eth_dev *eth_dev)
bp->flags |= BNXT_FLAG_RX_VECTOR_PKT_MODE;
if (bnxt_compressed_rx_cqe_mode_enabled(bp))
return bnxt_crx_pkts_vec_avx2;
- if (BNXT_TRUFLOW_EN(bp) && bnxt_ulp_explicit_mark_enabled(bp))
- goto use_scalar_rx;
if (BNXT_CHIP_P7(bp))
return bnxt_recv_pkts_vec_avx2_v3;
else
diff --git a/drivers/net/bnxt/bnxt_hwrm.c b/drivers/net/bnxt/bnxt_hwrm.c
index 590543ad6a..4a5b83d29c 100644
--- a/drivers/net/bnxt/bnxt_hwrm.c
+++ b/drivers/net/bnxt/bnxt_hwrm.c
@@ -4347,6 +4347,9 @@ static int bnxt_hwrm_set_tpa(struct bnxt *bp)
bool tpa_flags = 0;
int rc, i;
+ if (!BNXT_SUPPORTS_TPA(bp))
+ return 0;
+
tpa_flags = (rx_offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO) ? true : false;
for (i = 0; i < bp->max_vnics; i++) {
struct bnxt_vnic_info *vnic = &bp->vnic_info[i];
@@ -4946,31 +4949,6 @@ int bnxt_hwrm_pf_evb_mode(struct bnxt *bp)
return rc;
}
-static int bnxt_hwrm_set_tpa(struct bnxt *bp)
-{
- struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
- uint64_t rx_offloads = dev_conf->rxmode.offloads;
- bool tpa_flags = 0;
- int rc, i;
-
- if (!BNXT_SUPPORTS_TPA(bp))
- return 0;
-
- tpa_flags = (rx_offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO) ? true : false;
- for (i = 0; i < bp->max_vnics; i++) {
- struct bnxt_vnic_info *vnic = &bp->vnic_info[i];
-
- if (vnic->fw_vnic_id == INVALID_HW_RING_ID)
- continue;
-
- rc = bnxt_hwrm_vnic_tpa_cfg(bp, vnic, tpa_flags);
- if (rc)
- return rc;
- }
- return 0;
-}
-
-
int bnxt_hwrm_tunnel_dst_port_alloc(struct bnxt *bp, uint16_t port,
uint8_t tunnel_type)
{
diff --git a/drivers/net/bnxt/bnxt_rxr.c b/drivers/net/bnxt/bnxt_rxr.c
index ab2175d21a..046276f931 100644
--- a/drivers/net/bnxt/bnxt_rxr.c
+++ b/drivers/net/bnxt/bnxt_rxr.c
@@ -1203,11 +1203,14 @@ static int bnxt_rx_pkt(struct rte_mbuf **rx_pkt,
mbuf->data_len = mbuf->pkt_len;
mbuf->port = rxq->port_id;
- if (unlikely(((rte_le_to_cpu_16(rxcmp->flags_type) &
- RX_PKT_CMPL_FLAGS_MASK) ==
- RX_PKT_CMPL_FLAGS_ITYPE_PTP_W_TIMESTAMP) ||
- bp->ptp_all_rx_tstamp) && bp->ieee_1588 &&
- bp->ptp_cfg) {
+ if (unlikely((((rte_le_to_cpu_16(rxcmp->flags_type) &
+ RX_PKT_CMPL_FLAGS_MASK) ==
+ RX_PKT_CMPL_FLAGS_ITYPE_PTP_W_TIMESTAMP) ||
+ ((rte_le_to_cpu_16(rxcmp->flags_type) &
+ RX_PKT_CMPL_FLAGS_MASK) ==
+ RX_PKT_CMPL_FLAGS_ITYPE_PTP_WO_TIMESTAMP)) &&
+ bp->ptp_all_rx_tstamp) && bp->ieee_1588 &&
+ bp->ptp_cfg) {
mbuf->ol_flags |= RTE_MBUF_F_RX_IEEE1588_PTP |
RTE_MBUF_F_RX_IEEE1588_TMST;
if (BNXT_CHIP_P5_P7(bp))
diff --git a/drivers/net/bnxt/bnxt_stats.c b/drivers/net/bnxt/bnxt_stats.c
index 49367588e4..ba858710a5 100644
--- a/drivers/net/bnxt/bnxt_stats.c
+++ b/drivers/net/bnxt/bnxt_stats.c
@@ -695,6 +695,9 @@ static int bnxt_stats_get_ext(struct rte_eth_dev *eth_dev,
struct bnxt_cp_ring_info *cpr = txq->cp_ring;
struct bnxt_ring_stats_ext ring_stats = {0};
+ bnxt_stats->oerrors += rte_atomic_load_explicit(&txq->tx_mbuf_drop,
+ rte_memory_order_relaxed);
+
if (!txq->tx_started)
continue;
^ permalink raw reply related
* [PATCH 03/10] net/bnxt: fix advertising RX LRO offload capability
From: Mohammad Shuab Siddique @ 2026-06-04 3:18 UTC (permalink / raw)
To: dev
Cc: kishore.padmanabha, stable, Damodharam Ammepalli,
Mohammad Shuab Siddique
In-Reply-To: <20260604031851.2267548-1-Mohammad-Shuab.Siddique@broadcom.com>
From: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
Do not set the RX LRO offload capability bit mask if the
hardware did not advertise the function, and let
the driver take non-tpa path in configuring the vnic
in such cases.
Fixes: b150a7e7ee66 ("net/bnxt: support LRO on Thor adapters")
Cc: stable@dpdk.org
Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
Signed-off-by: Mohammad Shuab Siddique <mohammad-shuab.siddique@broadcom.com>
---
drivers/net/bnxt/bnxt.h | 1 +
drivers/net/bnxt/bnxt_hwrm.c | 29 +++++++++++++++++++++++++++--
drivers/net/bnxt/bnxt_rxq.c | 3 ++-
3 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h
index f21753e40c..5ae4e620a4 100644
--- a/drivers/net/bnxt/bnxt.h
+++ b/drivers/net/bnxt/bnxt.h
@@ -1273,6 +1273,7 @@ extern int bnxt_logtype_driver;
#define BNXT_LINK_SPEEDS_V2(bp) (((bp)->link_info) && (((bp)->link_info->support_speeds_v2) || \
BNXT_LINK_SPEEDS_V2_VF((bp))))
#define BNXT_MAX_SPEED_LANES 8
+#define BNXT_SUPPORTS_TPA(bp) (!BNXT_CHIP_P5_P7(bp) || (bp)->max_tpa_v2)
extern const struct rte_flow_ops bnxt_ulp_rte_flow_ops;
int32_t bnxt_ulp_port_init(struct bnxt *bp);
void bnxt_ulp_port_deinit(struct bnxt *bp);
diff --git a/drivers/net/bnxt/bnxt_hwrm.c b/drivers/net/bnxt/bnxt_hwrm.c
index 02a5d00738..590543ad6a 100644
--- a/drivers/net/bnxt/bnxt_hwrm.c
+++ b/drivers/net/bnxt/bnxt_hwrm.c
@@ -3120,10 +3120,10 @@ int bnxt_hwrm_vnic_tpa_cfg(struct bnxt *bp,
return -ENOTSUP;
}
- if ((BNXT_CHIP_P5(bp) || BNXT_CHIP_P7(bp)) && !bp->max_tpa_v2) {
+ if (!BNXT_SUPPORTS_TPA(bp)) {
if (enable)
PMD_DRV_LOG_LINE(ERR, "No HW support for LRO");
- return -ENOTSUP;
+ return 0;
}
if (vnic->fw_vnic_id == INVALID_HW_RING_ID) {
@@ -4946,6 +4946,31 @@ int bnxt_hwrm_pf_evb_mode(struct bnxt *bp)
return rc;
}
+static int bnxt_hwrm_set_tpa(struct bnxt *bp)
+{
+ struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
+ uint64_t rx_offloads = dev_conf->rxmode.offloads;
+ bool tpa_flags = 0;
+ int rc, i;
+
+ if (!BNXT_SUPPORTS_TPA(bp))
+ return 0;
+
+ tpa_flags = (rx_offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO) ? true : false;
+ for (i = 0; i < bp->max_vnics; i++) {
+ struct bnxt_vnic_info *vnic = &bp->vnic_info[i];
+
+ if (vnic->fw_vnic_id == INVALID_HW_RING_ID)
+ continue;
+
+ rc = bnxt_hwrm_vnic_tpa_cfg(bp, vnic, tpa_flags);
+ if (rc)
+ return rc;
+ }
+ return 0;
+}
+
+
int bnxt_hwrm_tunnel_dst_port_alloc(struct bnxt *bp, uint16_t port,
uint8_t tunnel_type)
{
diff --git a/drivers/net/bnxt/bnxt_rxq.c b/drivers/net/bnxt/bnxt_rxq.c
index b93f5043de..023cb0e174 100644
--- a/drivers/net/bnxt/bnxt_rxq.c
+++ b/drivers/net/bnxt/bnxt_rxq.c
@@ -38,7 +38,8 @@ uint64_t bnxt_get_rx_port_offloads(struct bnxt *bp)
RTE_ETH_RX_OFFLOAD_VLAN_EXTEND);
- if (!bnxt_compressed_rx_cqe_mode_enabled(bp))
+ if (!bnxt_compressed_rx_cqe_mode_enabled(bp) &&
+ BNXT_SUPPORTS_TPA(bp))
rx_offload_capa |= RTE_ETH_RX_OFFLOAD_TCP_LRO;
if (bp->flags & BNXT_FLAG_PTP_SUPPORTED)
rx_offload_capa |= RTE_ETH_RX_OFFLOAD_TIMESTAMP;
--
2.47.3
^ permalink raw reply related
* [PATCH 02/10] net/bnxt: stale values in nr_bds are cleared
From: Mohammad Shuab Siddique @ 2026-06-04 3:18 UTC (permalink / raw)
To: dev; +Cc: kishore.padmanabha, stable, Keegan Freyhof,
Mohammad Shuab Siddique
In-Reply-To: <20260604031851.2267548-1-Mohammad-Shuab.Siddique@broadcom.com>
From: Keegan Freyhof <keegan.freyhof@broadcom.com>
Fixed an issue where the stale value held in txr->nr_bds[0]
would get read when the ring loops back around and cause
the tx producer to get behind the tx consumer position.
This then causes the driver to think that there were no
available buffers.
Fixes: 925cd0705836 ("net/bnxt: update PTP support on Thor")
Cc: stable@dpdk.org
Signed-off-by: Keegan Freyhof <keegan.freyhof@broadcom.com>
Signed-off-by: Mohammad Shuab Siddique <mohammad-shuab.siddique@broadcom.com>
---
drivers/net/bnxt/bnxt_txr.c | 136 ++++++++++++++++++++++++++++++++++--
1 file changed, 130 insertions(+), 6 deletions(-)
diff --git a/drivers/net/bnxt/bnxt_txr.c b/drivers/net/bnxt/bnxt_txr.c
index d37a38735c..45d1a93fdc 100644
--- a/drivers/net/bnxt/bnxt_txr.c
+++ b/drivers/net/bnxt/bnxt_txr.c
@@ -511,11 +511,48 @@ static int bnxt_start_xmit(struct rte_mbuf *tx_pkt,
return rc;
}
+static void bnxt_tx_coal_cmp_fast(struct bnxt_tx_queue *txq, int nr_cons)
+{
+ struct bnxt_tx_ring_info *txr = txq->tx_ring;
+ struct bnxt_ring *ring = txr->tx_ring_struct;
+ struct rte_mbuf **free = txq->free;
+ uint16_t raw_cons = txr->tx_raw_cons;
+ unsigned int blk = 0;
+ int cons, bds;
+
+ for (cons = 0; cons < nr_cons; cons++) {
+ struct rte_mbuf **tx_buf;
+ unsigned short nr_bds;
+
+ tx_buf = &txr->tx_buf_ring[RING_IDX(ring, raw_cons)];
+ nr_bds = (*tx_buf)->nb_segs +
+ bnxt_xmit_need_long_bd(*tx_buf, txq);
+ for (bds = 0; bds < nr_bds; bds++) {
+ if (*tx_buf) {
+ free[blk++] = *tx_buf;
+ /*
+ * Each BD also tracks a consumer index.
+ * Update cons, otherwise it will fall behind.
+ */
+ cons++;
+ *tx_buf = NULL;
+ }
+ raw_cons = RING_NEXT(raw_cons);
+ tx_buf = &txr->tx_buf_ring[RING_IDX(ring, raw_cons)];
+ }
+ }
+ if (blk)
+ rte_mempool_put_bulk(free[0]->pool, (void *)free, blk);
+
+ txr->tx_raw_cons = raw_cons;
+}
+
/*
* Transmit completion function for use when RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE
* is enabled.
*/
-static void bnxt_tx_cmp_fast(struct bnxt_tx_queue *txq, int nr_pkts)
+static void bnxt_tx_cmp_fast(struct bnxt_tx_queue *txq, int nb_tx,
+ bool tx_coal_cmp)
{
struct bnxt_tx_ring_info *txr = txq->tx_ring;
struct bnxt_ring *ring = txr->tx_ring_struct;
@@ -524,7 +561,10 @@ static void bnxt_tx_cmp_fast(struct bnxt_tx_queue *txq, int nr_pkts)
unsigned int blk = 0;
int i, j;
- for (i = 0; i < nr_pkts; i++) {
+ if (tx_coal_cmp)
+ return bnxt_tx_coal_cmp_fast(txq, nb_tx);
+
+ for (i = 0; i < nb_tx; i++) {
struct rte_mbuf **tx_buf;
unsigned short nr_bds;
@@ -547,7 +587,72 @@ static void bnxt_tx_cmp_fast(struct bnxt_tx_queue *txq, int nr_pkts)
txr->tx_raw_cons = raw_cons;
}
-static void bnxt_tx_cmp(struct bnxt_tx_queue *txq, int nr_pkts)
+static void bnxt_tx_coal_cmp(struct bnxt_tx_queue *txq, int nr_cons)
+{
+ struct bnxt_tx_ring_info *txr = txq->tx_ring;
+ struct bnxt_ring *ring = txr->tx_ring_struct;
+ struct rte_mempool *pool = NULL;
+ struct rte_mbuf **free = txq->free;
+ uint16_t raw_cons = txr->tx_raw_cons;
+ unsigned int blk = 0;
+ int cons, bds;
+
+ for (cons = 0; cons < nr_cons; cons++) {
+ struct rte_mbuf *mbuf;
+ struct rte_mbuf **tx_buf;
+ unsigned short nr_bds;
+
+ tx_buf = &txr->tx_buf_ring[RING_IDX(ring, raw_cons)];
+ nr_bds = txr->nr_bds[RING_IDX(ring, raw_cons)];
+ /* Clear the now stale number of buffer descriptors */
+ txr->nr_bds[RING_IDX(ring, raw_cons)] = 0;
+
+ for (bds = 0; bds < nr_bds; bds++) {
+ mbuf = *tx_buf;
+ *tx_buf = NULL;
+ raw_cons = RING_NEXT(raw_cons);
+ /*
+ * Each BD also tracks a consumer index. So update the cons.
+ * Otherwise the cons will fall behind.
+ */
+ cons++;
+ tx_buf = &txr->tx_buf_ring[RING_IDX(ring, raw_cons)];
+ if (!mbuf) /* long_bd's tx_buf ? */
+ continue;
+
+ mbuf = rte_pktmbuf_prefree_seg(mbuf);
+ if (unlikely(!mbuf))
+ continue;
+
+ /* EW - no need to unmap DMA memory? */
+
+ if (likely(mbuf->pool == pool)) {
+ /* Add mbuf to the bulk free array */
+ free[blk++] = mbuf;
+ } else {
+ /* Found an mbuf from a different pool. Free
+ * mbufs accumulated so far to the previous
+ * pool
+ */
+ if (likely(pool != NULL))
+ rte_mempool_put_bulk(pool,
+ (void *)free,
+ blk);
+
+ /* Start accumulating mbufs in a new pool */
+ free[0] = mbuf;
+ pool = mbuf->pool;
+ blk = 1;
+ }
+ }
+ }
+ if (blk)
+ rte_mempool_put_bulk(pool, (void *)free, blk);
+
+ txr->tx_raw_cons = raw_cons;
+}
+
+static void bnxt_tx_cmp(struct bnxt_tx_queue *txq, int nb_tx, bool tx_coal_cmp)
{
struct bnxt_tx_ring_info *txr = txq->tx_ring;
struct bnxt_ring *ring = txr->tx_ring_struct;
@@ -557,13 +662,19 @@ static void bnxt_tx_cmp(struct bnxt_tx_queue *txq, int nr_pkts)
unsigned int blk = 0;
int i, j;
- for (i = 0; i < nr_pkts; i++) {
+ if (tx_coal_cmp)
+ return bnxt_tx_coal_cmp(txq, nb_tx);
+
+ for (i = 0; i < nb_tx; i++) {
struct rte_mbuf *mbuf;
struct rte_mbuf **tx_buf;
unsigned short nr_bds;
tx_buf = &txr->tx_buf_ring[RING_IDX(ring, raw_cons)];
nr_bds = txr->nr_bds[RING_IDX(ring, raw_cons)];
+ /* Clear the now stale number of buffer descriptors */
+ txr->nr_bds[RING_IDX(ring, raw_cons)] = 0;
+
for (j = 0; j < nr_bds; j++) {
mbuf = *tx_buf;
*tx_buf = NULL;
@@ -631,6 +742,8 @@ static int bnxt_handle_tx_cp(struct bnxt_tx_queue *txq)
struct bnxt_cp_ring_info *cpr = txq->cp_ring;
uint32_t raw_cons = cpr->cp_raw_cons;
struct bnxt_ring *cp_ring_struct;
+ uint32_t tx_ring_mask;
+ bool tx_coal_cmp = false;
struct tx_cmpl *txcmp;
if (bnxt_tx_bds_in_hw(txq) < txq->tx_free_thresh)
@@ -638,6 +751,7 @@ static int bnxt_handle_tx_cp(struct bnxt_tx_queue *txq)
cp_ring_struct = cpr->cp_ring_struct;
ring_mask = cp_ring_struct->ring_mask;
+ tx_ring_mask = txq->tx_ring->tx_ring_struct->ring_mask;
do {
cons = RING_CMPL(ring_mask, raw_cons);
@@ -646,6 +760,16 @@ static int bnxt_handle_tx_cp(struct bnxt_tx_queue *txq)
if (!bnxt_cpr_cmp_valid(txcmp, raw_cons, ring_mask + 1))
break;
+ if (CMP_TYPE(txcmp) == CMPL_BASE_TYPE_TX_L2_COAL) {
+ struct tx_cmpl_coal *txcmp_c = (struct tx_cmpl_coal *)txcmp;
+
+ nb_tx_pkts = (rte_le_to_cpu_32(txcmp_c->sq_cons_idx) -
+ (txq->tx_ring->tx_raw_cons & tx_ring_mask)) & tx_ring_mask;
+ raw_cons = NEXT_RAW_CMP(raw_cons);
+ tx_coal_cmp = true;
+ break;
+ }
+
opaque = rte_le_to_cpu_32(txcmp->opaque);
if (bnxt_is_tx_cmpl_type(CMP_TYPE(txcmp)))
@@ -661,9 +785,9 @@ static int bnxt_handle_tx_cp(struct bnxt_tx_queue *txq)
if (nb_tx_pkts) {
if (txq->offloads & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE)
- bnxt_tx_cmp_fast(txq, nb_tx_pkts);
+ bnxt_tx_cmp_fast(txq, nb_tx_pkts, tx_coal_cmp);
else
- bnxt_tx_cmp(txq, nb_tx_pkts);
+ bnxt_tx_cmp(txq, nb_tx_pkts, tx_coal_cmp);
cpr->cp_raw_cons = raw_cons;
bnxt_db_cq(cpr);
}
--
2.47.3
^ permalink raw reply related
* [PATCH 01/10] net/bnxt: vector mode implementation for V3 packets
From: Mohammad Shuab Siddique @ 2026-06-04 3:18 UTC (permalink / raw)
To: dev; +Cc: kishore.padmanabha, stable, Keegan Freyhof,
Mohammad Shuab Siddique
In-Reply-To: <20260604031851.2267548-1-Mohammad-Shuab.Siddique@broadcom.com>
From: Keegan Freyhof <keegan.freyhof@broadcom.com>
Added support for AVX2 vector mode reporting of the
VLAN TCI for Thor 2.
Signed-off-by: Keegan Freyhof <keegan.freyhof@broadcom.com>
Signed-off-by: Mohammad Shuab Siddique <mohammad-shuab.siddique@broadcom.com>
---
drivers/net/bnxt/bnxt_ethdev.c | 7 +-
drivers/net/bnxt/bnxt_rxr.h | 2 +
drivers/net/bnxt/bnxt_rxtx_vec_avx2.c | 402 ++++++++++++++++++++++++
drivers/net/bnxt/bnxt_rxtx_vec_common.h | 36 +++
4 files changed, 446 insertions(+), 1 deletion(-)
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index c45afdb20a..5bd51de3cd 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -1493,7 +1493,12 @@ bnxt_receive_function(struct rte_eth_dev *eth_dev)
bp->flags |= BNXT_FLAG_RX_VECTOR_PKT_MODE;
if (bnxt_compressed_rx_cqe_mode_enabled(bp))
return bnxt_crx_pkts_vec_avx2;
- return bnxt_recv_pkts_vec_avx2;
+ if (BNXT_TRUFLOW_EN(bp) && bnxt_ulp_explicit_mark_enabled(bp))
+ goto use_scalar_rx;
+ if (BNXT_CHIP_P7(bp))
+ return bnxt_recv_pkts_vec_avx2_v3;
+ else
+ return bnxt_recv_pkts_vec_avx2;
}
#endif
if (rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_128) {
diff --git a/drivers/net/bnxt/bnxt_rxr.h b/drivers/net/bnxt/bnxt_rxr.h
index 2a28fa2073..352d509210 100644
--- a/drivers/net/bnxt/bnxt_rxr.h
+++ b/drivers/net/bnxt/bnxt_rxr.h
@@ -165,6 +165,8 @@ int bnxt_rxq_vec_setup(struct bnxt_rx_queue *rxq);
#if defined(RTE_ARCH_X86)
uint16_t bnxt_recv_pkts_vec_avx2(void *rx_queue, struct rte_mbuf **rx_pkts,
uint16_t nb_pkts);
+uint16_t bnxt_recv_pkts_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts,
+ uint16_t nb_pkts);
uint16_t bnxt_crx_pkts_vec_avx2(void *rx_queue, struct rte_mbuf **rx_pkts,
uint16_t nb_pkts);
#endif
diff --git a/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c b/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c
index 35550534de..46b51b20e4 100644
--- a/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c
+++ b/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c
@@ -903,3 +903,405 @@ bnxt_xmit_pkts_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
return nb_sent;
}
+
+
+/*
+ * V3 (Thor2) RX burst processing - AVX2 vectorized implementation
+ *
+ * V3 completions have a different layout for checksum and VLAN handling
+ * compared to the standard and compressed completion formats.
+ */
+static uint16_t
+recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
+{
+ struct bnxt_rx_queue *rxq = rx_queue;
+ struct bnxt_vnic_info *vnic = rxq->vnic;
+ const __m256i mbuf_init =
+ _mm256_set_epi64x(0, 0, 0, rxq->mbuf_initializer);
+ struct bnxt_cp_ring_info *cpr = rxq->cp_ring;
+ struct bnxt_rx_ring_info *rxr = rxq->rx_ring;
+ uint16_t cp_ring_size = cpr->cp_ring_struct->ring_size;
+ uint16_t rx_ring_size = rxr->rx_ring_struct->ring_size;
+ struct cmpl_base *cp_desc_ring = cpr->cp_desc_ring;
+ uint64_t valid, desc_valid_mask = ~0ULL;
+ const __m256i info3_v_mask = _mm256_set1_epi32(CMPL_BASE_V);
+ uint32_t raw_cons = cpr->cp_raw_cons;
+ uint32_t cons, mbcons;
+ int nb_rx_pkts = 0;
+ int i;
+ const __m256i valid_target =
+ _mm256_set1_epi32(!!(raw_cons & cp_ring_size));
+
+ /*
+ * Shuffle mask for V3 descriptors to rearrange fields into mbuf layout.
+ */
+ const __m256i shuf_msk =
+ _mm256_set_epi8(15, 14, 13, 12, /* rss */
+ 0xFF, 0xFF, /* vlan_tci (filled separately) */
+ 3, 2, /* data_len */
+ 0xFF, 0xFF, 3, 2, /* pkt_len */
+ 0xFF, 0xFF, 0xFF, 0xFF, /* pkt_type (zeroes) */
+ 15, 14, 13, 12, /* rss */
+ 0xFF, 0xFF, /* vlan_tci (filled separately) */
+ 3, 2, /* data_len */
+ 0xFF, 0xFF, 3, 2, /* pkt_len */
+ 0xFF, 0xFF, 0xFF, 0xFF); /* pkt_type (zeroes) */
+
+ /* Shuffle mask for high completion to extract metadata0 and errors */
+ const __m256i dsc_shuf_msk =
+ _mm256_set_epi8(0xff, 0xff, 0xff, 0xff, /* Zeroes */
+ 11, 10, /* metadata0 (vlan_tci) */
+ 9, 8, /* errors_v2 */
+ 5, 4, /* metadata1 (payload_offset) */
+ 1, 0, /* flags2 low */
+ 0xff, 0xff, 0xff, 0xff, /* Zeroes */
+ 0xff, 0xff, 0xff, 0xff, /* Zeroes */
+ 11, 10, /* metadata0 (vlan_tci) */
+ 9, 8, /* errors_v2 */
+ 5, 4, /* metadata1 (payload_offset) */
+ 1, 0, /* flags2 low */
+ 0xff, 0xff, 0xff, 0xff); /* Zeroes */
+
+ const __m256i flags_type_mask =
+ _mm256_set1_epi32(RX_PKT_V3_CMPL_FLAGS_ITYPE_MASK);
+ const __m256i flags2_ip_type_mask =
+ _mm256_set1_epi32(RX_PKT_V3_CMPL_HI_FLAGS2_IP_TYPE);
+ const __m256i rss_mask =
+ _mm256_set1_epi32(RX_PKT_V3_CMPL_FLAGS_RSS_VALID);
+ const __m256i metadata1_valid_mask =
+ _mm256_set1_epi32(RX_PKT_V3_CMPL_METADATA1_VALID);
+ const __m256i vlan_tci_mask =
+ _mm256_set1_epi32(RX_PKT_V3_CMPL_HI_METADATA0_VID_MASK |
+ RX_PKT_V3_CMPL_HI_METADATA0_DE |
+ RX_PKT_V3_CMPL_HI_METADATA0_PRI_MASK);
+ const __m256i cs_err_mask =
+ _mm256_set1_epi32(RX_PKT_CMPL_ERRORS_T_L4_CS_ERROR |
+ RX_PKT_CMPL_ERRORS_T_IP_CS_ERROR |
+ RX_PKT_CMPL_ERRORS_L4_CS_ERROR |
+ RX_PKT_CMPL_ERRORS_IP_CS_ERROR);
+ const __m256i cs_calc_mask =
+ _mm256_set1_epi32(RX_PKT_CMPL_CALC);
+
+ __m256i t0, t1, flags_type, flags2, errors, metadata1;
+ __m256i ptype_idx, ptypes, vlan_tci, vlan_flags;
+ __m256i mbuf01, mbuf23, mbuf45, mbuf67;
+ __m256i rearm0, rearm1, rearm2, rearm3, rearm4, rearm5, rearm6, rearm7;
+ __m256i ol_flags, ol_flags_hi;
+ __m256i rss_flags;
+
+ /* Validate ptype table indexing at build time. */
+ bnxt_check_ptype_constants();
+
+ if (unlikely(!rxq->rx_started))
+ return 0;
+
+ if (rxq->rxrearm_nb >= rxq->rx_free_thresh)
+ bnxt_rxq_rearm(rxq, rxr);
+
+ nb_pkts = RTE_ALIGN_FLOOR(nb_pkts, BNXT_RX_DESCS_PER_LOOP_VEC256);
+
+ cons = raw_cons & (cp_ring_size - 1);
+ mbcons = (raw_cons / 2) & (rx_ring_size - 1);
+
+ if (!bnxt_cpr_cmp_valid(&cp_desc_ring[cons], raw_cons, cp_ring_size))
+ return 0;
+
+ nb_pkts = RTE_MIN(nb_pkts, RTE_MIN(rx_ring_size - mbcons,
+ (cp_ring_size - cons) / 2));
+ /*
+ * If we are at the end of the ring, ensure that descriptors after the
+ * last valid entry are not treated as valid.
+ */
+ if (nb_pkts < BNXT_RX_DESCS_PER_LOOP_VEC256) {
+ desc_valid_mask >>=
+ CHAR_BIT * (BNXT_RX_DESCS_PER_LOOP_VEC256 - nb_pkts);
+ } else {
+ nb_pkts =
+ RTE_ALIGN_FLOOR(nb_pkts, BNXT_RX_DESCS_PER_LOOP_VEC256);
+ }
+
+ for (i = 0; i < nb_pkts; i += BNXT_RX_DESCS_PER_LOOP_VEC256,
+ cons += BNXT_RX_DESCS_PER_LOOP_VEC256 * 2,
+ mbcons += BNXT_RX_DESCS_PER_LOOP_VEC256) {
+ __m256i desc0, desc1, desc2, desc3, desc4, desc5, desc6, desc7;
+ __m256i rxcmp0_1, rxcmp2_3, rxcmp4_5, rxcmp6_7, info3_v;
+ __m256i errors_v2, meta0_err, cs_calc, cs_valid;
+ uint32_t num_valid;
+
+ t0 = _mm256_loadu_si256((void *)&rxr->rx_buf_ring[mbcons]);
+ _mm256_storeu_si256((void *)&rx_pkts[i], t0);
+#ifdef RTE_ARCH_X86_64
+ t0 = _mm256_loadu_si256((void *)&rxr->rx_buf_ring[mbcons + 4]);
+ _mm256_storeu_si256((void *)&rx_pkts[i + 4], t0);
+#endif
+
+ /*
+ * Load eight receive completion descriptors into 256-bit
+ * registers. Loads are issued in reverse order for consistent state.
+ */
+ desc7 = _mm256_load_si256((void *)&cp_desc_ring[cons + 14]);
+ rte_compiler_barrier();
+ desc6 = _mm256_load_si256((void *)&cp_desc_ring[cons + 12]);
+ rte_compiler_barrier();
+ desc5 = _mm256_load_si256((void *)&cp_desc_ring[cons + 10]);
+ rte_compiler_barrier();
+ desc4 = _mm256_load_si256((void *)&cp_desc_ring[cons + 8]);
+ rte_compiler_barrier();
+ desc3 = _mm256_load_si256((void *)&cp_desc_ring[cons + 6]);
+ rte_compiler_barrier();
+ desc2 = _mm256_load_si256((void *)&cp_desc_ring[cons + 4]);
+ rte_compiler_barrier();
+ desc1 = _mm256_load_si256((void *)&cp_desc_ring[cons + 2]);
+ rte_compiler_barrier();
+ desc0 = _mm256_load_si256((void *)&cp_desc_ring[cons + 0]);
+
+ /*
+ * Pack needed fields from each descriptor pair.
+ * For V3: extract rxcmp (low) for flags_type, len, rss
+ * and rxcmp1 (hi) for flags2, metadata0, metadata1, errors_v2
+ */
+ t0 = _mm256_permute2f128_si256(desc6, desc7, 0x20);
+ t1 = _mm256_permute2f128_si256(desc6, desc7, 0x31);
+ t1 = _mm256_shuffle_epi8(t1, dsc_shuf_msk);
+ rxcmp6_7 = _mm256_blend_epi32(t0, t1, 0x66);
+
+ t0 = _mm256_permute2f128_si256(desc4, desc5, 0x20);
+ t1 = _mm256_permute2f128_si256(desc4, desc5, 0x31);
+ t1 = _mm256_shuffle_epi8(t1, dsc_shuf_msk);
+ rxcmp4_5 = _mm256_blend_epi32(t0, t1, 0x66);
+
+ t0 = _mm256_permute2f128_si256(desc2, desc3, 0x20);
+ t1 = _mm256_permute2f128_si256(desc2, desc3, 0x31);
+ t1 = _mm256_shuffle_epi8(t1, dsc_shuf_msk);
+ rxcmp2_3 = _mm256_blend_epi32(t0, t1, 0x66);
+
+ t0 = _mm256_permute2f128_si256(desc0, desc1, 0x20);
+ t1 = _mm256_permute2f128_si256(desc0, desc1, 0x31);
+ t1 = _mm256_shuffle_epi8(t1, dsc_shuf_msk);
+ rxcmp0_1 = _mm256_blend_epi32(t0, t1, 0x66);
+
+ /* Extract flags_type from low completion for eight packets */
+ t0 = _mm256_unpacklo_epi32(rxcmp0_1, rxcmp2_3);
+ t1 = _mm256_unpacklo_epi32(rxcmp4_5, rxcmp6_7);
+ flags_type = _mm256_unpacklo_epi64(t0, t1);
+
+ /* Compute ptype_idx from flags_type itype field */
+ ptype_idx = _mm256_and_si256(flags_type, flags_type_mask);
+ ptype_idx = _mm256_srli_epi32(ptype_idx,
+ RX_PKT_V3_CMPL_FLAGS_ITYPE_SFT -
+ BNXT_PTYPE_TBL_TYPE_SFT);
+
+ /* Extract flags2 from high completion */
+ t0 = _mm256_unpacklo_epi32(rxcmp0_1, rxcmp2_3);
+ t1 = _mm256_unpacklo_epi32(rxcmp4_5, rxcmp6_7);
+ flags2 = _mm256_unpackhi_epi64(t0, t1);
+
+ t0 = _mm256_srli_epi32(_mm256_and_si256(flags2, flags2_ip_type_mask),
+ RX_PKT_V3_CMPL_FLAGS2_IP_TYPE_SFT -
+ BNXT_PTYPE_TBL_IP_VER_SFT);
+ ptype_idx = _mm256_or_si256(ptype_idx, t0);
+
+ /*
+ * Extract metadata1 (contains VLAN valid bit) from LOW completion.
+ * metadata1_payload_offset is at word 2 of rxcmp (low 128 bits of desc).
+ */
+ {
+ __m128i m01, m23, hi;
+ hi =
+ _mm_unpacklo_epi64(_mm_unpackhi_epi32(_mm256_castsi256_si128(desc4),
+ _mm256_castsi256_si128(desc5)),
+ _mm_unpackhi_epi32(_mm256_castsi256_si128(desc6),
+ _mm256_castsi256_si128(desc7)));
+ m01 = _mm_unpackhi_epi32(_mm256_castsi256_si128(desc0),
+ _mm256_castsi256_si128(desc1));
+ m23 = _mm_unpackhi_epi32(_mm256_castsi256_si128(desc2),
+ _mm256_castsi256_si128(desc3));
+ metadata1 =
+ _mm256_inserti128_si256(_mm256_castsi128_si256(_mm_unpacklo_epi64(m01,
+ m23)), hi, 1);
+ }
+ metadata1 = _mm256_srli_epi32(metadata1, 16);
+
+ t0 = _mm256_srli_epi32(_mm256_and_si256(metadata1, metadata1_valid_mask),
+ RX_PKT_V3_CMPL_METADATA1_VALID_SFT -
+ BNXT_PTYPE_TBL_VLAN_SFT);
+ ptype_idx = _mm256_or_si256(ptype_idx, t0);
+
+ /*
+ * Load ptypes for eight packets using gather.
+ */
+ ptypes = _mm256_i32gather_epi32((int *)bnxt_ptype_table,
+ ptype_idx, sizeof(uint32_t));
+
+ /* Extract RSS valid flags for eight packets */
+ rss_flags = _mm256_and_si256(flags_type, rss_mask);
+ rss_flags = _mm256_srli_epi32(rss_flags, 9);
+
+ /* Extract metadata0 (contains vlan_tci) and errors from high completion */
+ t0 = _mm256_unpackhi_epi32(rxcmp0_1, rxcmp2_3);
+ t1 = _mm256_unpackhi_epi32(rxcmp4_5, rxcmp6_7);
+ meta0_err = _mm256_unpacklo_epi64(t0, t1);
+
+ /* Extract vlan_tci from high 16 bits of meta0_err (metadata0) */
+ vlan_tci = _mm256_and_si256(_mm256_srli_epi32(meta0_err, 16), vlan_tci_mask);
+
+ vlan_flags = _mm256_and_si256(metadata1, metadata1_valid_mask);
+ vlan_flags = _mm256_min_epu32(vlan_flags, _mm256_set1_epi32(1));
+
+ if (vnic->vlan_strip) {
+ vlan_flags = _mm256_or_si256(vlan_flags,
+ _mm256_slli_epi32(vlan_flags, 6));
+ }
+
+ errors_v2 = meta0_err;
+
+ errors = _mm256_srli_epi32(_mm256_and_si256(meta0_err, cs_err_mask), 4);
+
+ cs_calc = _mm256_and_si256(flags2, cs_calc_mask);
+ cs_valid = _mm256_cmpeq_epi32(cs_calc, _mm256_setzero_si256());
+ errors = _mm256_andnot_si256(cs_valid, errors);
+ ol_flags = _mm256_i32gather_epi32((const int *)errors_to_olflags_v3,
+ errors, sizeof(uint32_t));
+ __m256i unknown_flags = _mm256_and_si256(cs_valid,
+ _mm256_set1_epi32(RTE_MBUF_F_RX_IP_CKSUM_UNKNOWN));
+ ol_flags = _mm256_or_si256(ol_flags, unknown_flags);
+
+ const __m256i perm_msk =
+ _mm256_set_epi32(7, 3, 6, 2, 5, 1, 4, 0);
+ info3_v = _mm256_permutevar8x32_epi32(errors_v2, perm_msk);
+ info3_v = _mm256_and_si256(errors_v2, info3_v_mask);
+ info3_v = _mm256_xor_si256(info3_v, valid_target);
+
+ info3_v = _mm256_packs_epi32(info3_v, _mm256_setzero_si256());
+ valid = _mm_cvtsi128_si64(_mm256_extracti128_si256(info3_v, 1));
+ valid = (valid << CHAR_BIT) |
+ _mm_cvtsi128_si64(_mm256_castsi256_si128(info3_v));
+ num_valid = rte_popcount64(valid & desc_valid_mask);
+
+ if (num_valid == 0)
+ break;
+
+ mbuf01 = _mm256_shuffle_epi8(rxcmp0_1, shuf_msk);
+ mbuf23 = _mm256_shuffle_epi8(rxcmp2_3, shuf_msk);
+ mbuf45 = _mm256_shuffle_epi8(rxcmp4_5, shuf_msk);
+ mbuf67 = _mm256_shuffle_epi8(rxcmp6_7, shuf_msk);
+
+ mbuf01 = _mm256_blend_epi32(mbuf01, ptypes, 0x11);
+ mbuf23 = _mm256_blend_epi32(mbuf23,
+ _mm256_srli_si256(ptypes, 4), 0x11);
+ mbuf45 = _mm256_blend_epi32(mbuf45,
+ _mm256_srli_si256(ptypes, 8), 0x11);
+ mbuf67 = _mm256_blend_epi32(mbuf67,
+ _mm256_srli_si256(ptypes, 12), 0x11);
+
+ const __m256i tci_perm_01 = _mm256_set_epi32(1, 1, 1, 1, 0, 0, 0, 0);
+ const __m256i tci_perm_23 = _mm256_set_epi32(3, 3, 3, 3, 2, 2, 2, 2);
+ const __m256i tci_perm_45 = _mm256_set_epi32(5, 5, 5, 5, 4, 4, 4, 4);
+ const __m256i tci_perm_67 = _mm256_set_epi32(7, 7, 7, 7, 6, 6, 6, 6);
+
+ mbuf01 = _mm256_blend_epi16(mbuf01,
+ _mm256_slli_si256(_mm256_permutevar8x32_epi32(vlan_tci,
+ tci_perm_01), 10), 0x20);
+ mbuf23 = _mm256_blend_epi16(mbuf23,
+ _mm256_slli_si256(_mm256_permutevar8x32_epi32(vlan_tci,
+ tci_perm_23), 10), 0x20);
+ mbuf45 = _mm256_blend_epi16(mbuf45,
+ _mm256_slli_si256(_mm256_permutevar8x32_epi32(vlan_tci,
+ tci_perm_45), 10), 0x20);
+ mbuf67 = _mm256_blend_epi16(mbuf67,
+ _mm256_slli_si256(_mm256_permutevar8x32_epi32(vlan_tci,
+ tci_perm_67), 10), 0x20);
+
+ rearm0 = _mm256_permute2f128_si256(mbuf_init, mbuf01, 0x20);
+ rearm1 = _mm256_blend_epi32(mbuf_init, mbuf01, 0xF0);
+ rearm2 = _mm256_permute2f128_si256(mbuf_init, mbuf23, 0x20);
+ rearm3 = _mm256_blend_epi32(mbuf_init, mbuf23, 0xF0);
+
+ ol_flags = _mm256_or_si256(ol_flags, rss_flags);
+ ol_flags = _mm256_or_si256(ol_flags, vlan_flags);
+ ol_flags_hi = _mm256_permute2f128_si256(ol_flags,
+ ol_flags, 0x11);
+
+ rearm0 = _mm256_blend_epi32(rearm0,
+ _mm256_slli_si256(ol_flags, 8),
+ 0x04);
+ rearm1 = _mm256_blend_epi32(rearm1,
+ _mm256_slli_si256(ol_flags_hi, 8),
+ 0x04);
+ rearm2 = _mm256_blend_epi32(rearm2,
+ _mm256_slli_si256(ol_flags, 4),
+ 0x04);
+ rearm3 = _mm256_blend_epi32(rearm3,
+ _mm256_slli_si256(ol_flags_hi, 4),
+ 0x04);
+
+ _mm256_storeu_si256((void *)&rx_pkts[i + 0]->rearm_data,
+ rearm0);
+ _mm256_storeu_si256((void *)&rx_pkts[i + 1]->rearm_data,
+ rearm1);
+ _mm256_storeu_si256((void *)&rx_pkts[i + 2]->rearm_data,
+ rearm2);
+ _mm256_storeu_si256((void *)&rx_pkts[i + 3]->rearm_data,
+ rearm3);
+
+ rearm4 = _mm256_permute2f128_si256(mbuf_init, mbuf45, 0x20);
+ rearm5 = _mm256_blend_epi32(mbuf_init, mbuf45, 0xF0);
+ rearm6 = _mm256_permute2f128_si256(mbuf_init, mbuf67, 0x20);
+ rearm7 = _mm256_blend_epi32(mbuf_init, mbuf67, 0xF0);
+
+ rearm4 = _mm256_blend_epi32(rearm4, ol_flags, 0x04);
+ rearm5 = _mm256_blend_epi32(rearm5, ol_flags_hi, 0x04);
+ rearm6 = _mm256_blend_epi32(rearm6,
+ _mm256_srli_si256(ol_flags, 4),
+ 0x04);
+ rearm7 = _mm256_blend_epi32(rearm7,
+ _mm256_srli_si256(ol_flags_hi, 4),
+ 0x04);
+
+ _mm256_storeu_si256((void *)&rx_pkts[i + 4]->rearm_data,
+ rearm4);
+ _mm256_storeu_si256((void *)&rx_pkts[i + 5]->rearm_data,
+ rearm5);
+ _mm256_storeu_si256((void *)&rx_pkts[i + 6]->rearm_data,
+ rearm6);
+ _mm256_storeu_si256((void *)&rx_pkts[i + 7]->rearm_data,
+ rearm7);
+
+ nb_rx_pkts += num_valid;
+ if (num_valid < BNXT_RX_DESCS_PER_LOOP_VEC256)
+ break;
+ }
+
+ if (nb_rx_pkts) {
+ rxr->rx_raw_prod = RING_ADV(rxr->rx_raw_prod, nb_rx_pkts);
+
+ rxq->rxrearm_nb += nb_rx_pkts;
+ cpr->cp_raw_cons += 2 * nb_rx_pkts;
+ bnxt_db_cq(cpr);
+ }
+
+ return nb_rx_pkts;
+}
+
+uint16_t
+bnxt_recv_pkts_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts,
+ uint16_t nb_pkts)
+{
+ struct bnxt_rx_queue *rxq = rx_queue;
+ uint32_t expected_burst = rxq->rx_free_thresh;
+ uint16_t cnt = 0;
+
+ while (nb_pkts > expected_burst) {
+ uint16_t burst;
+
+ burst = recv_burst_vec_avx2_v3(rx_queue, rx_pkts + cnt, expected_burst);
+
+ cnt += burst;
+ nb_pkts -= burst;
+
+ if (burst < expected_burst)
+ return cnt;
+ }
+ return cnt + recv_burst_vec_avx2_v3(rx_queue, rx_pkts + cnt, nb_pkts);
+}
+
diff --git a/drivers/net/bnxt/bnxt_rxtx_vec_common.h b/drivers/net/bnxt/bnxt_rxtx_vec_common.h
index e185005293..e8da010dc3 100644
--- a/drivers/net/bnxt/bnxt_rxtx_vec_common.h
+++ b/drivers/net/bnxt/bnxt_rxtx_vec_common.h
@@ -177,4 +177,40 @@ bnxt_tx_cmp_vec(struct bnxt_tx_queue *txq, uint32_t nr_pkts)
}
txr->tx_raw_cons = raw_cons;
}
+
+static const uint64_t errors_to_olflags_v3[16] = {
+ RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD | RTE_MBUF_F_RX_L4_CKSUM_GOOD |
+ RTE_MBUF_F_RX_IP_CKSUM_GOOD,
+ RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD | RTE_MBUF_F_RX_L4_CKSUM_GOOD |
+ RTE_MBUF_F_RX_IP_CKSUM_BAD,
+ RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD | RTE_MBUF_F_RX_L4_CKSUM_BAD |
+ RTE_MBUF_F_RX_IP_CKSUM_GOOD,
+ RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD | RTE_MBUF_F_RX_L4_CKSUM_BAD |
+ RTE_MBUF_F_RX_IP_CKSUM_BAD,
+ RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD | RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD |
+ RTE_MBUF_F_RX_L4_CKSUM_GOOD,
+ RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD | RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD |
+ RTE_MBUF_F_RX_L4_CKSUM_GOOD | RTE_MBUF_F_RX_IP_CKSUM_BAD,
+ RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD | RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD |
+ RTE_MBUF_F_RX_L4_CKSUM_BAD,
+ RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD | RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD |
+ RTE_MBUF_F_RX_L4_CKSUM_BAD | RTE_MBUF_F_RX_IP_CKSUM_BAD,
+ RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD | RTE_MBUF_F_RX_L4_CKSUM_GOOD |
+ RTE_MBUF_F_RX_IP_CKSUM_GOOD,
+ RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD | RTE_MBUF_F_RX_L4_CKSUM_GOOD |
+ RTE_MBUF_F_RX_IP_CKSUM_BAD,
+ RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD | RTE_MBUF_F_RX_L4_CKSUM_BAD |
+ RTE_MBUF_F_RX_IP_CKSUM_GOOD,
+ RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD | RTE_MBUF_F_RX_L4_CKSUM_BAD |
+ RTE_MBUF_F_RX_IP_CKSUM_BAD,
+ RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD | RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD |
+ RTE_MBUF_F_RX_L4_CKSUM_GOOD,
+ RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD | RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD |
+ RTE_MBUF_F_RX_L4_CKSUM_GOOD | RTE_MBUF_F_RX_IP_CKSUM_BAD,
+ RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD | RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD |
+ RTE_MBUF_F_RX_L4_CKSUM_BAD,
+ RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD | RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD |
+ RTE_MBUF_F_RX_L4_CKSUM_BAD | RTE_MBUF_F_RX_IP_CKSUM_BAD
+};
+
#endif /* _BNXT_RXTX_VEC_COMMON_H_ */
--
2.47.3
^ permalink raw reply related
* [PATCH 00/10] net/bnxt: vector mode V3 implementation and AVX2 improvements
From: Mohammad Shuab Siddique @ 2026-06-04 3:18 UTC (permalink / raw)
To: dev; +Cc: kishore.padmanabha, stable, Mohammad Shuab Siddique
From: Mohammad Shuab Siddique <mohammad-shuab.siddique@broadcom.com>
This series adds vector mode support for BCM5760X (Thor2 / V3 packets)
and fixes several AVX2 path issues:
- Implement AVX2 vector RX for V3 packet completions with VLAN TCI reporting
- Fix stale nr_bds values that could cause the producer to lag the consumer
- Fix incorrect advertisement of LRO offload capability
- Fix scalar RX path not checking rxcmp flags before setting the PTP mbuf flag
- Fix missing timestamps for non-PTP traffic when promiscuous timestamping is on
- Fix Tx ring corruption and burst truncation after an invalid Tx descriptor
- Optimise the AVX2 RX paths (dead code removal, register reduction for V3)
- Fix VLAN strip ol_flag being set per-port instead of per-packet for V3
- Add burst mode info entry for V3 in bnxt_rx_burst_info
- Fix V3 vector mode defaulting to cksum-good instead of cksum-unknown
Most patches carry Fixes: tags. New functionality (V3 vector mode, AVX2
optimisation) is targeted at 26.07.
Note: this series depends on series "net/bnxt: stability fixes".
Chenna Arnoori (1):
net/bnxt: fix RX timestamping for non-PTP packets
Damodharam Ammepalli (1):
net/bnxt: fix advertising RX LRO offload capability
Keegan Freyhof (6):
net/bnxt: vector mode implementation for V3 packets
net/bnxt: stale values in nr_bds are cleared
net/bnxt: optimization of the AVX2 RX paths
net/bnxt: fix for VLAN stripping being set incorrectly
net/bnxt: add vector AVX2 burst mode indicator for v3
net/bnxt: fix v3 vector mode not selecting cksum unknown
Mohammad Shuab Siddique (1):
net/bnxt: scalar rx path disregarded rxcmp flags for setting ptp mbuf
flag
Zoe Cheimets (1):
net/bnxt: fix packet burst truncation after invalid Tx descriptor
.gitignore | 1 +
drivers/net/bnxt/bnxt.h | 1 +
drivers/net/bnxt/bnxt_ethdev.c | 6 +-
drivers/net/bnxt/bnxt_hwrm.c | 7 +-
drivers/net/bnxt/bnxt_rxq.c | 3 +-
drivers/net/bnxt/bnxt_rxr.c | 25 +-
drivers/net/bnxt/bnxt_rxr.h | 14 +-
drivers/net/bnxt/bnxt_rxtx_vec_avx2.c | 444 +++++++++++++++++++++++-
drivers/net/bnxt/bnxt_rxtx_vec_common.h | 37 ++
drivers/net/bnxt/bnxt_stats.c | 3 +
drivers/net/bnxt/bnxt_txr.c | 170 ++++++++-
11 files changed, 677 insertions(+), 34 deletions(-)
--
2.47.3
^ permalink raw reply
* [PATCH v9 19/20] drivers: add testpmd commands for private features
From: liujie5 @ 2026-06-04 1:54 UTC (permalink / raw)
To: stephen; +Cc: dev, Jie Liu
In-Reply-To: <20260604015404.1552953-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 09b2f7d125..59a8aa6f13 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 1753eccf99..fd0a99d6fd 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 b5adc31d69..b70b3e4162 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