* [PATCH] net/virtio-user: fix eventfd sharing in secondary process
From: Samar Yadav @ 2026-06-24 8:57 UTC (permalink / raw)
To: dev; +Cc: maxime.coquelin, chenbox, Samar Yadav, tiwei.bie, stable
virtio_user secondary processes cannot communicate with the vhost
backend: the kick/call eventfds are opened by the primary and never
shared, so a secondary's queue notification writes to an invalid fd
and traffic stalls.
Share the fds over a dedicated virtio-user multiprocess channel. The
primary registers a process-wide MP action that returns a port's
kick/call fds (looked up by port name); a secondary requests them at
probe time, before the port is announced.
The received fds are stored in eth_dev->process_private, which is
per-process, instead of the primary-owned shared dev->kickfds and
dev->callfds arrays; the secondary data path notifies the backend using
its own kickfd. In the primary, the MP handler reads the fd arrays under
dev->mutex, and the teardown path takes the same lock while closing and
freeing them, so the two cannot race.
Fixes: 1c8489da561b ("net/virtio-user: fix multi-process support")
Cc: tiwei.bie@intel.com
Cc: stable@dpdk.org
Signed-off-by: Samar Yadav <samaryadav5@gmail.com>
---
.mailmap | 1 +
.../net/virtio/virtio_user/virtio_user_dev.c | 56 +++-
.../net/virtio/virtio_user/virtio_user_dev.h | 20 ++
drivers/net/virtio/virtio_user_ethdev.c | 260 +++++++++++++++++-
4 files changed, 333 insertions(+), 4 deletions(-)
diff --git a/.mailmap b/.mailmap
index 4001e5fb0e70..8f921d4b9f46 100644
--- a/.mailmap
+++ b/.mailmap
@@ -1448,6 +1448,7 @@ Salem Sol <salems@nvidia.com>
Sam Andrew <samandrew@microsoft.com>
Sam Chen <sam.chen@nebula-matrix.com>
Sam Grove <sam.grove@sifive.com>
+Samar Yadav <samaryadav5@gmail.com> <samar.yadav@broadcom.com>
Sameer Vaze <svaze@qti.qualcomm.com>
Sameh Gobriel <sameh.gobriel@intel.com>
Samik Gupta <samik.gupta@broadcom.com>
diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.c b/drivers/net/virtio/virtio_user/virtio_user_dev.c
index f3df73c1f0ca..5e431ebc6511 100644
--- a/drivers/net/virtio/virtio_user/virtio_user_dev.c
+++ b/drivers/net/virtio/virtio_user/virtio_user_dev.c
@@ -34,6 +34,54 @@ const char * const virtio_user_backend_strings[] = {
[VIRTIO_USER_BACKEND_VHOST_VDPA] = "VHOST_VDPA",
};
+/*
+ * Collect the primary device's kick/call fds (interleaved kick,call per queue)
+ * for sharing with a secondary process. Caller must serialize against the
+ * control path (dev->mutex) so the fd arrays are not freed concurrently.
+ */
+int
+virtio_user_get_eventfds_from_dev(struct virtio_user_dev *dev,
+ int fds[VIRTIO_USER_MAX_EVENTFDS])
+{
+ uint32_t max_queues;
+ int i, total_fds = 0;
+ int kickfd, callfd;
+
+ if (dev == NULL || fds == NULL)
+ return -EINVAL;
+
+ if (dev->kickfds == NULL || dev->callfds == NULL) {
+ PMD_INIT_LOG(ERR, "Device eventfd arrays not initialized");
+ return -EINVAL;
+ }
+
+ max_queues = dev->max_queue_pairs * 2;
+ if (dev->hw_cvq)
+ max_queues += 1;
+
+ /* each queue contributes a kick and a call fd */
+ if (max_queues * 2 > VIRTIO_USER_MAX_EVENTFDS) {
+ PMD_INIT_LOG(ERR,
+ "Device needs %u eventfds, exceeds MP limit %d",
+ max_queues * 2, VIRTIO_USER_MAX_EVENTFDS);
+ return -E2BIG;
+ }
+
+ for (i = 0; i < (int)max_queues; i++) {
+ kickfd = dev->kickfds[i];
+ callfd = dev->callfds[i];
+ if (kickfd < 0 || callfd < 0) {
+ PMD_INIT_LOG(ERR, "Queue %d has invalid fds (kick=%d call=%d)",
+ i, kickfd, callfd);
+ return -EINVAL;
+ }
+ fds[total_fds++] = kickfd;
+ fds[total_fds++] = callfd;
+ }
+
+ return total_fds;
+}
+
static int
virtio_user_uninit_notify_queue(struct virtio_user_dev *dev, uint32_t queue_sel)
{
@@ -865,9 +913,15 @@ virtio_user_dev_uninit(struct virtio_user_dev *dev)
rte_mem_event_callback_unregister(VIRTIO_USER_MEM_EVENT_CLB_NAME, dev);
+ /*
+ * Serialize closing/freeing the kick/call fd arrays against the MP
+ * handler, which reads them under the same lock to share them with
+ * secondary processes.
+ */
+ pthread_mutex_lock(&dev->mutex);
virtio_user_dev_uninit_notify(dev);
-
virtio_user_free_vrings(dev);
+ pthread_mutex_unlock(&dev->mutex);
free(dev->ifname);
diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.h b/drivers/net/virtio/virtio_user/virtio_user_dev.h
index 66400b3b6295..c00297c79ed8 100644
--- a/drivers/net/virtio/virtio_user/virtio_user_dev.h
+++ b/drivers/net/virtio/virtio_user/virtio_user_dev.h
@@ -11,6 +11,11 @@
#include "../virtio.h"
#include "../virtio_ring.h"
+#include <rte_eal.h>
+
+/* Max eventfds shareable over the MP channel (bounded by SCM_RIGHTS). */
+#define VIRTIO_USER_MAX_EVENTFDS RTE_MP_MAX_FD_NUM
+
enum virtio_user_backend_type {
VIRTIO_USER_BACKEND_UNKNOWN,
VIRTIO_USER_BACKEND_VHOST_USER,
@@ -89,5 +94,20 @@ int virtio_user_dev_get_rss_config(struct virtio_user_dev *dev, void *dst, size_
int length);
void virtio_user_dev_delayed_disconnect_handler(void *param);
int virtio_user_dev_server_reconnect(struct virtio_user_dev *dev);
+
+/**
+ * Collect a primary device's kick/call eventfds for sharing with a
+ * secondary process over the multiprocess channel.
+ *
+ * @param dev
+ * Pointer to the virtio_user device (primary).
+ * @param fds
+ * Output array, must hold at least VIRTIO_USER_MAX_EVENTFDS elements.
+ * @return
+ * Number of fds written on success, negative errno on error.
+ */
+int virtio_user_get_eventfds_from_dev(struct virtio_user_dev *dev,
+ int fds[VIRTIO_USER_MAX_EVENTFDS]);
+
extern const char * const virtio_user_backend_strings[];
#endif
diff --git a/drivers/net/virtio/virtio_user_ethdev.c b/drivers/net/virtio/virtio_user_ethdev.c
index 747dddeb2eba..1c724ad59ea6 100644
--- a/drivers/net/virtio/virtio_user_ethdev.c
+++ b/drivers/net/virtio/virtio_user_ethdev.c
@@ -27,6 +27,35 @@
#include "virtio_rxtx.h"
#include "virtio_user/virtio_user_dev.h"
#include "virtio_user/vhost.h"
+#include <errno.h>
+#include <rte_errno.h>
+#include <rte_string_fns.h>
+#include <rte_spinlock.h>
+
+/* Virtio-user multiprocess communication channel */
+#define VIRTIO_USER_MP_NAME "virtio_user_mp"
+
+struct virtio_user_mp_param {
+ char port_name[RTE_DEV_NAME_MAX_LEN];
+};
+
+/*
+ * Per-process private data, referenced by eth_dev->process_private which (unlike
+ * dev_private) is NOT shared between primary and secondary processes. A secondary
+ * stores the kick/call fds it receives from the primary here, so it never mutates
+ * the primary-owned shared dev->kickfds/dev->callfds arrays. callfds are kept for
+ * a complete per-process view of the backend fds; only kickfds are used by the
+ * secondary data path today.
+ */
+struct virtio_user_proc_priv {
+ uint32_t nr_queues;
+ int *kickfds;
+ int *callfds;
+};
+
+/* Guards one-time registration of the process-wide MP action. */
+static rte_spinlock_t virtio_user_mp_lock = RTE_SPINLOCK_INITIALIZER;
+static bool virtio_user_mp_registered;
#define virtio_user_get_dev(hwp) container_of(hwp, struct virtio_user_dev, hw)
@@ -269,6 +298,26 @@ virtio_user_del_queue(struct virtio_hw *hw, struct virtqueue *vq)
virtio_user_dev_destroy_shadow_cvq(dev);
}
+/*
+ * Return the kick fd to notify the backend for a queue in the running process.
+ * The secondary uses its own fds (process_private); the primary owns dev->kickfds.
+ */
+static int
+virtio_user_get_kickfd(struct virtio_hw *hw, struct virtio_user_dev *dev,
+ uint16_t queue_idx)
+{
+ if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
+ struct rte_eth_dev *eth_dev = &rte_eth_devices[hw->port_id];
+ struct virtio_user_proc_priv *pp = eth_dev->process_private;
+
+ if (pp == NULL || queue_idx >= pp->nr_queues)
+ return -1;
+ return pp->kickfds[queue_idx];
+ }
+
+ return dev->kickfds[queue_idx];
+}
+
static void
virtio_user_notify_queue(struct virtio_hw *hw, struct virtqueue *vq)
{
@@ -282,8 +331,10 @@ virtio_user_notify_queue(struct virtio_hw *hw, struct virtqueue *vq)
}
if (!dev->notify_area) {
- if (write(dev->kickfds[vq->vq_queue_index], ¬ify_data,
- sizeof(notify_data)) < 0)
+ int kickfd = virtio_user_get_kickfd(hw, dev, vq->vq_queue_index);
+
+ if (kickfd < 0 || write(kickfd, ¬ify_data,
+ sizeof(notify_data)) < 0)
PMD_DRV_LOG(ERR, "failed to kick backend: %s",
strerror(errno));
return;
@@ -495,6 +546,166 @@ virtio_user_eth_dev_free(struct rte_eth_dev *eth_dev)
rte_eth_dev_release_port(eth_dev);
}
+/* Close and free a secondary's per-process eventfd storage. */
+static void
+virtio_user_free_proc_priv(struct rte_eth_dev *eth_dev)
+{
+ struct virtio_user_proc_priv *pp = eth_dev->process_private;
+ uint32_t i;
+
+ if (pp == NULL)
+ return;
+
+ for (i = 0; i < pp->nr_queues; i++) {
+ if (pp->kickfds != NULL && pp->kickfds[i] >= 0)
+ close(pp->kickfds[i]);
+ if (pp->callfds != NULL && pp->callfds[i] >= 0)
+ close(pp->callfds[i]);
+ }
+
+ rte_free(pp->kickfds);
+ rte_free(pp->callfds);
+ rte_free(pp);
+ eth_dev->process_private = NULL;
+}
+
+/*
+ * Primary-side MP handler: reply with this port's kick/call eventfds so the
+ * requesting secondary can talk to the vhost backend. Always sends a reply
+ * (num_fds == 0 on error) so the secondary fails fast instead of timing out.
+ */
+static int
+virtio_user_mp_primary_handler(const struct rte_mp_msg *msg, const void *peer)
+{
+ const struct virtio_user_mp_param *param =
+ (const struct virtio_user_mp_param *)msg->param;
+ int eventfds[VIRTIO_USER_MAX_EVENTFDS];
+ struct rte_eth_dev *eth_dev;
+ struct virtio_user_dev *dev;
+ struct rte_mp_msg reply;
+ int num_fds;
+ int i;
+
+ memset(&reply, 0, sizeof(reply));
+ strlcpy(reply.name, msg->name, sizeof(reply.name));
+ reply.len_param = 0;
+ reply.num_fds = 0;
+
+ eth_dev = rte_eth_dev_get_by_name(param->port_name);
+ if (eth_dev == NULL || eth_dev->data->dev_private == NULL) {
+ PMD_INIT_LOG(ERR, "Failed to find virtio_user port: %s",
+ param->port_name);
+ return rte_mp_reply(&reply, peer);
+ }
+
+ dev = eth_dev->data->dev_private;
+
+ /* serialize against control-path changes to the fd arrays */
+ pthread_mutex_lock(&dev->mutex);
+ num_fds = virtio_user_get_eventfds_from_dev(dev, eventfds);
+ if (num_fds >= 0 && num_fds <= RTE_MP_MAX_FD_NUM) {
+ reply.num_fds = num_fds;
+ for (i = 0; i < num_fds; i++)
+ reply.fds[i] = eventfds[i];
+ } else {
+ PMD_INIT_LOG(ERR, "Cannot share eventfds for %s (ret=%d)",
+ param->port_name, num_fds);
+ }
+ pthread_mutex_unlock(&dev->mutex);
+
+ return rte_mp_reply(&reply, peer);
+}
+
+/*
+ * Secondary-side: request the primary's kick/call eventfds and store them in
+ * this process's eth_dev->process_private. The shared dev->kickfds/dev->callfds
+ * arrays (owned by the primary) are never touched.
+ */
+static int
+virtio_user_sync_eventfds(struct rte_eth_dev *eth_dev, struct virtio_user_dev *dev)
+{
+ struct rte_mp_msg mp_req, *mp_rep;
+ struct rte_mp_reply mp_reply = {0};
+ struct virtio_user_mp_param *req_param;
+ struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
+ struct virtio_user_proc_priv *pp;
+ uint32_t total_queues, i;
+ int nr_fds, ret = 0;
+
+ if (dev == NULL)
+ return -EINVAL;
+
+ if (rte_eal_process_type() != RTE_PROC_SECONDARY)
+ return -EINVAL;
+
+ total_queues = dev->max_queue_pairs * 2 + (dev->hw_cvq ? 1 : 0);
+
+ pp = rte_zmalloc("virtio_user_proc_priv", sizeof(*pp), 0);
+ if (pp == NULL)
+ return -ENOMEM;
+
+ pp->kickfds = rte_malloc("virtio_user_proc_priv",
+ total_queues * sizeof(int), 0);
+ pp->callfds = rte_malloc("virtio_user_proc_priv",
+ total_queues * sizeof(int), 0);
+ if (pp->kickfds == NULL || pp->callfds == NULL) {
+ ret = -ENOMEM;
+ goto err_free;
+ }
+ for (i = 0; i < total_queues; i++) {
+ pp->kickfds[i] = -1;
+ pp->callfds[i] = -1;
+ }
+
+ memset(&mp_req, 0, sizeof(mp_req));
+ req_param = (struct virtio_user_mp_param *)mp_req.param;
+ strlcpy(req_param->port_name, eth_dev->data->name,
+ sizeof(req_param->port_name));
+ strlcpy(mp_req.name, VIRTIO_USER_MP_NAME, RTE_MP_MAX_NAME_LEN);
+ mp_req.len_param = sizeof(*req_param);
+ mp_req.num_fds = 0;
+
+ if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) < 0 ||
+ mp_reply.nb_received != 1) {
+ PMD_INIT_LOG(ERR, "Failed to request eventfds from primary");
+ free(mp_reply.msgs);
+ ret = -EIO;
+ goto err_free;
+ }
+
+ mp_rep = &mp_reply.msgs[0];
+ nr_fds = mp_rep->num_fds;
+
+ /* a partially-synced device cannot work: treat any mismatch as fatal */
+ if (nr_fds != (int)total_queues * 2) {
+ PMD_INIT_LOG(ERR, "Expected %u eventfds, received %d",
+ total_queues * 2, nr_fds);
+ for (i = 0; i < (uint32_t)nr_fds; i++)
+ close(mp_rep->fds[i]);
+ free(mp_reply.msgs);
+ ret = -EPROTO;
+ goto err_free;
+ }
+
+ for (i = 0; i < total_queues; i++) {
+ pp->kickfds[i] = mp_rep->fds[i * 2];
+ pp->callfds[i] = mp_rep->fds[i * 2 + 1];
+ }
+ pp->nr_queues = total_queues;
+ free(mp_reply.msgs);
+
+ eth_dev->process_private = pp;
+ PMD_INIT_LOG(DEBUG, "Synced %u queue eventfds for secondary port %s",
+ total_queues, eth_dev->data->name);
+ return 0;
+
+err_free:
+ rte_free(pp->kickfds);
+ rte_free(pp->callfds);
+ rte_free(pp);
+ return ret;
+}
+
/* Dev initialization routine. Invoked once for each virtio vdev at
* EAL init time, see rte_bus_probe().
* Returns 0 on success.
@@ -542,6 +753,17 @@ virtio_user_pmd_probe(struct rte_vdev_device *vdev)
eth_dev->dev_ops = &virtio_user_secondary_eth_dev_ops;
eth_dev->device = &vdev->device;
+
+ /* populate this process's eventfds before announcing the port */
+ ret = virtio_user_sync_eventfds(eth_dev, dev);
+ if (ret < 0) {
+ PMD_INIT_LOG(ERR,
+ "Failed to sync eventfds in secondary: %d",
+ ret);
+ rte_eth_dev_release_port(eth_dev);
+ return ret;
+ }
+
rte_eth_dev_probing_finish(eth_dev);
return 0;
}
@@ -722,6 +944,36 @@ virtio_user_pmd_probe(struct rte_vdev_device *vdev)
}
}
+ /*
+ * Register the process-wide MP action once so secondaries can fetch a
+ * port's eventfds by name. It is intentionally left registered for the
+ * lifetime of the process (cleaned up at exit): unregistering per device
+ * cannot drain handler calls already dispatched on the EAL MP thread.
+ */
+ rte_spinlock_lock(&virtio_user_mp_lock);
+ if (!virtio_user_mp_registered) {
+ ret = rte_mp_action_register(VIRTIO_USER_MP_NAME,
+ virtio_user_mp_primary_handler);
+ if (ret < 0 && rte_errno != EEXIST) {
+ rte_spinlock_unlock(&virtio_user_mp_lock);
+ if (rte_errno == ENOTSUP) {
+ PMD_INIT_LOG(WARNING,
+ "MP unsupported, secondary eventfd sharing disabled");
+ rte_eth_dev_probing_finish(eth_dev);
+ ret = 0;
+ goto end;
+ }
+ PMD_INIT_LOG(ERR, "Failed to register MP handler: %s",
+ strerror(rte_errno));
+ virtio_user_dev_uninit(dev);
+ virtio_user_eth_dev_free(eth_dev);
+ ret = -1;
+ goto end;
+ }
+ virtio_user_mp_registered = true;
+ }
+ rte_spinlock_unlock(&virtio_user_mp_lock);
+
rte_eth_dev_probing_finish(eth_dev);
ret = 0;
@@ -749,8 +1001,10 @@ virtio_user_pmd_remove(struct rte_vdev_device *vdev)
if (!eth_dev)
return 0;
- if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
+ virtio_user_free_proc_priv(eth_dev);
return rte_eth_dev_release_port(eth_dev);
+ }
/* make sure the device is stopped, queues freed */
return rte_eth_dev_close(eth_dev->data->port_id);
--
2.52.0
^ permalink raw reply related
* Re: [PATCH v2] dts: update dts check format script and resolve errors
From: Thomas Monjalon @ 2026-06-24 13:04 UTC (permalink / raw)
To: Patrick Robb
Cc: Koushik Bhargav Nimoji, luca.vizzarro, dev, abailey, ahassick,
lylavoie
In-Reply-To: <CAK6Duxs-o_OcgjM9_dm-oBFTU7zKjk1g1X0bvbS=gtgwFSd0=Q@mail.gmail.com>
24/06/2026 00:34, Patrick Robb:
> I remember Thomas mentioning that DTS was not checking the
> dts-check-format.sh at DPDK Summit and that confused me. Perhaps he is
> running DTS and dts-check-format.sh outside of poetry (which we have said
> is okay to do) and he is on newer versions of the formatting dependencies
> than what we currently have committed to the poetry.lock.
Yes, newer versions are failing.
But with poetry, it runs fine.
^ permalink raw reply
* Re: [PATCH v5] graph: add optional profiling stats
From: saeed bishara @ 2026-06-24 13:09 UTC (permalink / raw)
To: Morten Brørup
Cc: Pavan Nikhilesh, Stephen Hemminger, Wathsala Vithanage,
Bruce Richardson, thomas, Jerin Jacob, dev, Jerin Jacob,
Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan
In-Reply-To: <98CBD80474FA8B44BF855DF32C47DC35F6593C@smartserver.smartshare.dk>
On Wed, Jun 24, 2026 at 10:59 AM Morten Brørup <mb@smartsharesystems.com> wrote:
>
> +Pavan Nikhilesh, +Stephen Hemminger, +Wathsala Vithanage, +Bruce Richardson, +Thomas Monjalon
>
> > From: saeed bishara [mailto:saeed.bishara.os@gmail.com]
> > Sent: Tuesday, 23 June 2026 16.11
> >
> > > > also, instead of adding cacheline for this profiling data, can we
> > > > share with line 1 that used solely for xstats?
> > >
> > > This profiling data is 4 indexes * 2 values * 8-byte fields, so one
> > cache line in itself.
> > make sense.
> > btw, the default value of RTE_GRAPH_BURST_SIZE is 256, I suspect that
> > real applications will enforce smaller burst when pulling from input
> > devices (e.g. 32). Do you expect such cases to change
> > RTE_GRAPH_BURST_SIZE?
>
> Excellent question! I don't know.
> They should. E.g. an application optimized for latency should certainly not process bursts of 256 objects.
>
> IMO, the root problem is the lack of a unified burst size across DPDK, which causes every library to be designed with its own optimal burst size.
> E.g. the Mbuf library uses 64 (for rte_pktmbuf_free_bulk()), and the Graph library uses 256.
>
> There has been an attempt at introducing a unified burst size [1] for DPDK, but it met a lot of resistance, so it still needs to be refined before we can reach a conclusion.
> The drivers supposedly can report an "optimal" burst size at run-time, which the application can then use. But the application is unable to configure its internal burst sizes if one driver reports 64 and another reports 32.
> I'm strongly in favor of a build time constant, used across DPDK. The default value should work reasonably well across drivers and libraries.
> And if an application wants to optimize for performance (either throughput or latency), the developer should experiment to find the optimal value.
> Furthermore, designing for a build time constant max burst size throughout DPDK might provide performance benefits in itself, as the compiler can optimize for this.
>
> [1]: https://inbox.dpdk.org/dev/KdOygM96Qb6d6ADK1-AcnA@monjalon.net/
>
> Now, back to your question...
> As a workaround, I can sample Graph node performance data for 32 objects, instead of sampling for RTE_GRAPH_BURST_SIZE / 2.
I see, so there is no simple static parameter here. what about
tracking max burst, then report the calls/cycles for that case, the
user will also find what was that max burst, and how often it occured.
saeed
^ permalink raw reply
* [PATCH v2 0/4] add versioned symbols for recently stabilized APIs
From: Dariusz Sosnowski @ 2026-06-24 13:13 UTC (permalink / raw)
To: David Marchand, Bruce Richardson, Thomas Monjalon,
Andrew Rybchenko, Viacheslav Ovsiienko, Bing Zhao, Ori Kam,
Suanming Mou, Matan Azrad
Cc: dev, Yu Jiang
In-Reply-To: <20260623113752.1100072-1-dsosnowski@nvidia.com>
Main goal of this patchset is to address https://bugs.dpdk.org/show_bug.cgi?id=1957
but it also handles other recently stabilized symbols and has some minor fixes:
- Patch 1 - Fix RTE_VERSION_EXPERIMENTAL_SYMBOL macro on clang.
- Patch 2 - Allow function versioning inside drivers.
- Patch 3 - Version the function symbols stabilized in
https://git.dpdk.org/dpdk/commit/?id=e8cab133645f5466ef75e511629add43b68a5027
- Patch 4 - Version the rte_flow_dynf_metadata_register() function stabilized in
https://git.dpdk.org/dpdk/commit/?id=4ee2f5c1cedf9ee7f39afa667f71b07f4004ba5c
Restore EXPERIMENTAL version on global variable symbols
rte_flow_dynf_metadata_offs and rte_flow_dynf_metadata_mask.
v2:
- Drop patches introducing versioning macros for symbol aliases
and their usage (patch 4 and 5 from v1)
- EXPERIMENTAL version on global variable symbols
rte_flow_dynf_metadata_offs and rte_flow_dynf_metadata_mask,
as discussed under v1.
- Change commit title prefix in patch (2) from "drivers" to "build".
v1: https://inbox.dpdk.org/dev/20260623113752.1100072-1-dsosnowski@nvidia.com/
Dariusz Sosnowski (4):
eal: fix macro for versioned experimental symbol
build: support function versioning for drivers
net/mlx5: fix stabilized function versions
ethdev: fix promoted flow metadata symbols
drivers/meson.build | 8 ++++++++
drivers/net/mlx5/meson.build | 2 ++
drivers/net/mlx5/mlx5_driver_event.c | 22 ++++++++++++++++------
drivers/net/mlx5/mlx5_flow.c | 18 ++++++++++++------
lib/eal/common/eal_export.h | 2 +-
lib/ethdev/meson.build | 2 ++
lib/ethdev/rte_flow.c | 13 ++++++++-----
7 files changed, 49 insertions(+), 18 deletions(-)
--
2.47.3
^ permalink raw reply
* [PATCH v2 2/4] build: support function versioning for drivers
From: Dariusz Sosnowski @ 2026-06-24 13:13 UTC (permalink / raw)
To: David Marchand, Bruce Richardson; +Cc: dev, Yu Jiang
In-Reply-To: <20260624131337.1127323-1-dsosnowski@nvidia.com>
Add support for enabling function versioning
(through use_function_versioning meson variable) for drivers,
similar to libraries.
Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
---
drivers/meson.build | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/meson.build b/drivers/meson.build
index 4d95604ecd..a63d93372a 100644
--- a/drivers/meson.build
+++ b/drivers/meson.build
@@ -171,6 +171,7 @@ foreach subpath:subdirs
pkgconfig_extra_libs = []
testpmd_sources = []
require_iova_in_mbuf = true
+ use_function_versioning = false
# for handling base code files which may need extra cflags
base_sources = []
base_cflags = []
@@ -273,6 +274,13 @@ foreach subpath:subdirs
endif
dpdk_conf.set(lib_name.to_upper(), 1)
+ if developer_mode and is_windows and use_function_versioning
+ message('@0@: Function versioning is not supported by Windows.'.format(name))
+ endif
+ if use_function_versioning
+ cflags += '-DRTE_USE_FUNCTION_VERSIONING'
+ endif
+
dpdk_extra_ldflags += pkgconfig_extra_libs
dpdk_headers += headers
--
2.47.3
^ permalink raw reply related
* [PATCH v2 3/4] net/mlx5: fix stabilized function versions
From: Dariusz Sosnowski @ 2026-06-24 13:13 UTC (permalink / raw)
To: David Marchand, Bruce Richardson, Viacheslav Ovsiienko, Bing Zhao,
Ori Kam, Suanming Mou, Matan Azrad
Cc: dev, Yu Jiang
In-Reply-To: <20260624131337.1127323-1-dsosnowski@nvidia.com>
Offending patch stabilized the following function symbols:
- rte_pmd_mlx5_driver_event_cb_register
- rte_pmd_mlx5_driver_event_cb_unregister
- rte_pmd_mlx5_enable_steering
- rte_pmd_mlx5_disable_steering
These function symbols were introduced in 25.11.
Any application using these functions, linked against 25.11 version,
would fail when used with 26.07 libraries, because only DPDK_26 versions
of these symbols were exported.
This patch fixes that by adding proper function symbol versioning
to these symbols.
Fixes: e8cab133645f ("net/mlx5: promote some private API to stable")
Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
---
drivers/net/mlx5/meson.build | 2 ++
drivers/net/mlx5/mlx5_driver_event.c | 22 ++++++++++++++++------
drivers/net/mlx5/mlx5_flow.c | 18 ++++++++++++------
3 files changed, 30 insertions(+), 12 deletions(-)
diff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build
index 82a7dfe782..0fa6322779 100644
--- a/drivers/net/mlx5/meson.build
+++ b/drivers/net/mlx5/meson.build
@@ -2,6 +2,8 @@
# Copyright 2018 6WIND S.A.
# Copyright 2018 Mellanox Technologies, Ltd
+use_function_versioning = true
+
if not (is_linux or is_windows)
build = false
reason = 'only supported on Linux and Windows'
diff --git a/drivers/net/mlx5/mlx5_driver_event.c b/drivers/net/mlx5/mlx5_driver_event.c
index 89e49331c8..d0e22d6151 100644
--- a/drivers/net/mlx5/mlx5_driver_event.c
+++ b/drivers/net/mlx5/mlx5_driver_event.c
@@ -236,9 +236,8 @@ notify_existing_devices(rte_pmd_mlx5_driver_event_callback_t cb, void *opaque)
notify_existing_queues(port_id, cb, opaque);
}
-RTE_EXPORT_SYMBOL(rte_pmd_mlx5_driver_event_cb_register)
-int
-rte_pmd_mlx5_driver_event_cb_register(rte_pmd_mlx5_driver_event_callback_t cb, void *opaque)
+RTE_DEFAULT_SYMBOL(26, int, rte_pmd_mlx5_driver_event_cb_register,
+ (rte_pmd_mlx5_driver_event_callback_t cb, void *opaque))
{
struct registered_cb *r;
@@ -264,9 +263,14 @@ rte_pmd_mlx5_driver_event_cb_register(rte_pmd_mlx5_driver_event_callback_t cb, v
return 0;
}
-RTE_EXPORT_SYMBOL(rte_pmd_mlx5_driver_event_cb_unregister)
-int
-rte_pmd_mlx5_driver_event_cb_unregister(rte_pmd_mlx5_driver_event_callback_t cb)
+RTE_VERSION_EXPERIMENTAL_SYMBOL(int, rte_pmd_mlx5_driver_event_cb_register,
+ (rte_pmd_mlx5_driver_event_callback_t cb, void *opaque))
+{
+ return rte_pmd_mlx5_driver_event_cb_register(cb, opaque);
+}
+
+RTE_DEFAULT_SYMBOL(26, int, rte_pmd_mlx5_driver_event_cb_unregister,
+ (rte_pmd_mlx5_driver_event_callback_t cb))
{
struct registered_cb *r;
bool found = false;
@@ -289,6 +293,12 @@ rte_pmd_mlx5_driver_event_cb_unregister(rte_pmd_mlx5_driver_event_callback_t cb)
return 0;
}
+RTE_VERSION_EXPERIMENTAL_SYMBOL(int, rte_pmd_mlx5_driver_event_cb_unregister,
+ (rte_pmd_mlx5_driver_event_callback_t cb))
+{
+ return rte_pmd_mlx5_driver_event_cb_unregister(cb);
+}
+
RTE_FINI(rte_pmd_mlx5_driver_event_cb_cleanup) {
struct registered_cb *r;
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index a95dd9dc94..4b984df892 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -12506,9 +12506,7 @@ flow_disable_steering_run_on_related(struct rte_eth_dev *dev,
}
}
-RTE_EXPORT_SYMBOL(rte_pmd_mlx5_disable_steering)
-void
-rte_pmd_mlx5_disable_steering(void)
+RTE_DEFAULT_SYMBOL(26, void, rte_pmd_mlx5_disable_steering, (void))
{
uint16_t port_id;
@@ -12532,9 +12530,12 @@ rte_pmd_mlx5_disable_steering(void)
mlx5_steering_disabled = true;
}
-RTE_EXPORT_SYMBOL(rte_pmd_mlx5_enable_steering)
-int
-rte_pmd_mlx5_enable_steering(void)
+RTE_VERSION_EXPERIMENTAL_SYMBOL(void, rte_pmd_mlx5_disable_steering, (void))
+{
+ rte_pmd_mlx5_disable_steering();
+}
+
+RTE_DEFAULT_SYMBOL(26, int, rte_pmd_mlx5_enable_steering, (void))
{
uint16_t port_id;
@@ -12551,6 +12552,11 @@ rte_pmd_mlx5_enable_steering(void)
return 0;
}
+RTE_VERSION_EXPERIMENTAL_SYMBOL(int, rte_pmd_mlx5_enable_steering, (void))
+{
+ return rte_pmd_mlx5_enable_steering();
+}
+
bool
mlx5_vport_rx_metadata_passing_enabled(const struct mlx5_dev_ctx_shared *sh)
{
--
2.47.3
^ permalink raw reply related
* [PATCH v2 1/4] eal: fix macro for versioned experimental symbol
From: Dariusz Sosnowski @ 2026-06-24 13:13 UTC (permalink / raw)
To: David Marchand, Bruce Richardson; +Cc: dev, Yu Jiang
In-Reply-To: <20260624131337.1127323-1-dsosnowski@nvidia.com>
Add a missing semicolon after __asm__ block in
RTE_VERSION_EXPERIMENTAL_SYMBOL macro.
It's lack triggers the following compilation error with clang:
../lib/ethdev/rte_flow.c:320:1: error: expected ';' after top-level asm block
320 | RTE_VERSION_EXPERIMENTAL_SYMBOL(int, rte_flow_dynf_metadata_register, (void))
| ^
../lib/eal/common/eal_export.h:75:74: note: expanded from macro 'RTE_VERSION_EXPERIMENTAL_SYMBOL'
75 | __asm__(".symver " RTE_STR(name) "_exp, " RTE_STR(name) "@EXPERIMENTAL") \
| ^
../lib/eal/include/rte_common.h:237:20: note: expanded from macro '\
__rte_used'
237 | #define __rte_used __attribute__((used))
| ^
Fixes: e30e194c4d06 ("eal: rework function versioning macros")
Cc: david.marchand@redhat.com
Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
---
lib/eal/common/eal_export.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/eal/common/eal_export.h b/lib/eal/common/eal_export.h
index 888fd9f9ed..7971bf8d7a 100644
--- a/lib/eal/common/eal_export.h
+++ b/lib/eal/common/eal_export.h
@@ -72,7 +72,7 @@ __rte_used type name ## _v ## ver args; \
type name ## _v ## ver args
#define RTE_VERSION_EXPERIMENTAL_SYMBOL(type, name, args) VERSIONING_WARN \
-__asm__(".symver " RTE_STR(name) "_exp, " RTE_STR(name) "@EXPERIMENTAL") \
+__asm__(".symver " RTE_STR(name) "_exp, " RTE_STR(name) "@EXPERIMENTAL"); \
__rte_used type name ## _exp args; \
type name ## _exp args
--
2.47.3
^ permalink raw reply related
* [PATCH v2 4/4] ethdev: fix promoted flow metadata symbols
From: Dariusz Sosnowski @ 2026-06-24 13:13 UTC (permalink / raw)
To: David Marchand, Bruce Richardson, Thomas Monjalon,
Andrew Rybchenko, Ori Kam
Cc: dev, Yu Jiang
In-Reply-To: <20260624131337.1127323-1-dsosnowski@nvidia.com>
Offending commit stabilized the following symbols
related to flow metadata:
- 1 function symbol:
- rte_flow_dynf_metadata_register
- 2 variable symbols:
- rte_flow_dynf_metadata_offs
- rte_flow_dynf_metadata_mask
Any application using experimental flow metadata symbols,
which was linked dynamically against 25.11 version of ethdev
library and using current version of ethdev library
would fail to start on symbol lookup error:
/tmp/dpdk-25.11/usr/local/bin/dpdk-testpmd:
symbol lookup error: /tmp/dpdk-25.11/usr/local/bin/dpdk-testpmd:
undefined symbol: rte_flow_dynf_metadata_offs, version EXPERIMENTAL
This patch addresses that issue by restoring EXPERIMENTAL version
on the global variables to keep ABI compatibility [1].
Related inline helpers and variable declarations are kept as stable
(i.e., no __rte_experimental marker).
EXPERIMENTAL version will be removed from these global variables
in 26.11 release cycle on next ABI version bump.
Standard function symbol versioning is also applied on
rte_flow_dynf_metadata_register() function.
[1]: https://inbox.dpdk.org/dev/m7s3jl2566kibbapr2mfa2ic2opuc6b4ok2g67j3il5dgduzih@cz5wcdstb75n/
Bugzilla ID: 1957
Fixes: 4ee2f5c1cedf ("ethdev: promote flow metadata API to stable")
Reported-by: Yu Jiang <yux.jiang@intel.com>
Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
---
lib/ethdev/meson.build | 2 ++
lib/ethdev/rte_flow.c | 13 ++++++++-----
2 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/lib/ethdev/meson.build b/lib/ethdev/meson.build
index 8ba6c708a2..63fd866af9 100644
--- a/lib/ethdev/meson.build
+++ b/lib/ethdev/meson.build
@@ -1,6 +1,8 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2017 Intel Corporation
+use_function_versioning = true
+
sources = files(
'ethdev_driver.c',
'ethdev_private.c',
diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
index ec0fe08355..24eb5a95b0 100644
--- a/lib/ethdev/rte_flow.c
+++ b/lib/ethdev/rte_flow.c
@@ -23,11 +23,11 @@
#define FLOW_LOG RTE_ETHDEV_LOG_LINE
/* Mbuf dynamic field name for metadata. */
-RTE_EXPORT_SYMBOL(rte_flow_dynf_metadata_offs)
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_flow_dynf_metadata_offs, 19.11)
int32_t rte_flow_dynf_metadata_offs = -1;
/* Mbuf dynamic field flag bit number for metadata. */
-RTE_EXPORT_SYMBOL(rte_flow_dynf_metadata_mask)
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_flow_dynf_metadata_mask, 19.11)
uint64_t rte_flow_dynf_metadata_mask;
/**
@@ -281,9 +281,7 @@ static const struct rte_flow_desc_data rte_flow_desc_action[] = {
MK_FLOW_ACTION(JUMP_TO_TABLE_INDEX, sizeof(struct rte_flow_action_jump_to_table_index)),
};
-RTE_EXPORT_SYMBOL(rte_flow_dynf_metadata_register)
-int
-rte_flow_dynf_metadata_register(void)
+RTE_DEFAULT_SYMBOL(26, int, rte_flow_dynf_metadata_register, (void))
{
int offset;
int flag;
@@ -316,6 +314,11 @@ rte_flow_dynf_metadata_register(void)
return -rte_errno;
}
+RTE_VERSION_EXPERIMENTAL_SYMBOL(int, rte_flow_dynf_metadata_register, (void))
+{
+ return rte_flow_dynf_metadata_register();
+}
+
static inline void
fts_enter(struct rte_eth_dev *dev)
{
--
2.47.3
^ permalink raw reply related
* RE: [PATCH v4 3/7] test/bpf: add test for large shift
From: Marat Khalili @ 2026-06-24 13:44 UTC (permalink / raw)
To: Stephen Hemminger, dev@dpdk.org; +Cc: Konstantin Ananyev
In-Reply-To: <8c882f31aaec46d984fc4c689ad92602@huawei.com>
> > +/*
> > + * Shift by an immediate that doesn't fit in a signed byte: the C1 shift
> > + * group takes a fixed 1-byte immediate, but imm_size() returns 4 for
> > + * counts >= 128, so the x86 JIT emits 3 stray bytes and desyncs the
> > + * instruction stream. The shift results are discarded (a count >= 64 is
> > + * UB in the interpreter); the test returns a known constant, which the
> > + * corrupted stream fails to produce.
> > + */
> > +static const struct ebpf_insn test_shift_big_imm_prog[] = {
> > + {
> > + .code = (BPF_ALU | EBPF_MOV | BPF_K),
> > + .dst_reg = EBPF_REG_2,
> > + .imm = 0x1,
> > + },
> > + {
> > + .code = (EBPF_ALU64 | BPF_LSH | BPF_K),
> > + .dst_reg = EBPF_REG_2,
> > + .imm = 137,
> > + },
> > + {
> > + .code = (EBPF_ALU64 | BPF_RSH | BPF_K),
> > + .dst_reg = EBPF_REG_2,
> > + .imm = 200,
> > + },
> > + {
> > + .code = (EBPF_ALU64 | EBPF_ARSH | BPF_K),
> > + .dst_reg = EBPF_REG_2,
> > + .imm = 255,
> > + },
> > + /* known result; a desynced stream won't reproduce it */
> > + {
> > + .code = (BPF_ALU | EBPF_MOV | BPF_K),
> > + .dst_reg = EBPF_REG_0,
> > + .imm = 0x55,
> > + },
> > + {
> > + .code = (BPF_JMP | EBPF_EXIT),
> > + },
> > +};
>
> // snip the rest
>
> Thanks a lot for adding this test. Can we use the shift results though, instead
> of discarding them, maybe as another test case? If the interpreter is unable to
> reproduce them or triggers sanitizer it needs to be fixed as well. (Apologies
> for this scope creep but I hope we get to the bottom of it eventually.)
Speaking of scope creep, this currently fails on ARM since emit_lsl (as well as
emit_lsr, emit_asr) does not clear unused immediate bits and thus the value
does not fit in the encoding.
^ permalink raw reply
* [PATCH] vhost/crypto: fix segfault
From: Radu Nicolau @ 2026-06-24 14:20 UTC (permalink / raw)
To: dev; +Cc: Radu Nicolau, stable, Maxime Coquelin, Chenbo Xia, Jay Zhou,
Fan Zhang
Fix potential call with dev->mem uninitialized, one common usecase
example being running the autotest with more than one device.
Fixes: 3bb595ecd682 ("vhost/crypto: add request handler")
Cc: stable@dpdk.org
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
lib/vhost/vhost_crypto.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/vhost/vhost_crypto.c b/lib/vhost/vhost_crypto.c
index 648e2d731b..3679eaca1e 100644
--- a/lib/vhost/vhost_crypto.c
+++ b/lib/vhost/vhost_crypto.c
@@ -1512,6 +1512,10 @@ vhost_crypto_process_one_req(struct vhost_crypto *vcrypto,
VC_LOG_ERR("Invalid descriptor");
return -1;
}
+ if (unlikely((vc_req->dev->mem) == NULL)) {
+ VC_LOG_ERR("Uninitialized vhost device");
+ return -1;
+ }
dlen = head->len;
src_desc = IOVA_TO_VVA(struct vring_desc *, vc_req->dev, vq,
--
2.52.0
^ permalink raw reply related
* Re: [PATCH] net/virtio-user: fix eventfd sharing in secondary process
From: Stephen Hemminger @ 2026-06-24 15:16 UTC (permalink / raw)
To: Samar Yadav; +Cc: dev, maxime.coquelin, chenbox, tiwei.bie, stable
In-Reply-To: <20260624085741.2195573-1-samaryadav5@gmail.com>
On Wed, 24 Jun 2026 08:57:41 +0000
Samar Yadav <samaryadav5@gmail.com> wrote:
> @@ -865,9 +913,15 @@ virtio_user_dev_uninit(struct virtio_user_dev *dev)
>
> rte_mem_event_callback_unregister(VIRTIO_USER_MEM_EVENT_CLB_NAME, dev);
>
> + /*
> + * Serialize closing/freeing the kick/call fd arrays against the MP
> + * handler, which reads them under the same lock to share them with
> + * secondary processes.
> + */
> + pthread_mutex_lock(&dev->mutex);
> virtio_user_dev_uninit_notify(dev);
> -
> virtio_user_free_vrings(dev);
> + pthread_mutex_unlock(&dev->mutex);
>
> free(dev->ifname);
Related bug. virtio_user is not initializing mutex as safe between
processes. See rte_thread_mutex_init_shared() vs pthread_mutex_init()
^ permalink raw reply
* Re: [PATCH] net/virtio-user: fix eventfd sharing in secondary process
From: Stephen Hemminger @ 2026-06-24 15:10 UTC (permalink / raw)
To: Samar Yadav; +Cc: dev, maxime.coquelin, chenbox, tiwei.bie, stable
In-Reply-To: <20260624085741.2195573-1-samaryadav5@gmail.com>
On Wed, 24 Jun 2026 08:57:41 +0000
Samar Yadav <samaryadav5@gmail.com> wrote:
> + pp = rte_zmalloc("virtio_user_proc_priv", sizeof(*pp), 0);
> + if (pp == NULL)
> + return -ENOMEM;
> +
> + pp->kickfds = rte_malloc("virtio_user_proc_priv",
> + total_queues * sizeof(int), 0);
> + pp->callfds = rte_malloc("virtio_user_proc_priv",
> + total_queues * sizeof(int), 0);
Better to use rte_calloc.
^ permalink raw reply
* Re: [PATCH v2] dts: update dts check format script and resolve errors
From: Koushik Bhargav Nimoji @ 2026-06-24 15:44 UTC (permalink / raw)
To: Patrick Robb
Cc: luca.vizzarro, dev, abailey, ahassick, lylavoie,
NBU-Contact-Thomas Monjalon
In-Reply-To: <CAK6Duxs-o_OcgjM9_dm-oBFTU7zKjk1g1X0bvbS=gtgwFSd0=Q@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2344 bytes --]
On Tue, Jun 23, 2026 at 6:35 PM Patrick Robb <patrickrobb1997@gmail.com>
wrote:
> Looks like your patch is failing some of the checks on patchwork,
> including doc build:
> https://github.com/ovsrobot/dpdk/actions/runs/27789008643
>
> Remember to run a doc build locally before sending any patches:
>
> meson setup build
> ninja -C build doc
>
>
I will resolve this and send a patch out shortly.
Otherwise, please provide a little more info regarding your info. So, you
> have updated some of the dependencies used in the dts check format script.
> I think what I see from a quick look that is relevant is:
>
> -mypy = "^1.13.0"
> +mypy = "^2.1.0"
> toml = "^0.10.2"
> -ruff = "^0.8.1"
> -types-paramiko = "^3.5.0.20240928"
> +ruff = "^0.15.16"
> +types-paramiko = "^4.0.0.20260518"
> types-invoke = "^2.0.0.10"
> -types-pyyaml = "^6.0.12.20240917"
> +types-pyyaml = "^6.0.12.20260518"
>
> What is being done broadly? All dependencies covered by poetry are being
> updated? or just the subset included in format checks? Are dependencies
> being brought to current latest or something different?
>
Overall, only the dependencies being used by the dts-check-format.sh script
were updated. They were brought to the latest versions that were compatible
with each other. This allows for more rigorous format checking, as new
errors surfaced once the tool versions were updated.
>
> I remember Thomas mentioning that DTS was not checking the
> dts-check-format.sh at DPDK Summit and that confused me. Perhaps he is
> running DTS and dts-check-format.sh outside of poetry (which we have said
> is okay to do) and he is on newer versions of the formatting dependencies
> than what we currently have committed to the poetry.lock.
>
The lab was notified by Thomas about the following:
"About DTS, I think you are running an old version of the tools used in
devtools/dts-check-format.sh. When I run it, I have a lot of warnings. We
should fix them in DTS and then update the tools in the lab."
This may be what he was referring to at the DPDK summit. When running on
poetry it uses the older tool versions, to which none of the errors show
up. When running outside of poetry, it most likely uses the newer tool
versions which causes the underlying errors to appear.
Thanks,
Koushik
[-- Attachment #2: Type: text/html, Size: 3639 bytes --]
^ permalink raw reply
* Re: [PATCH v10 13/21] net/txgbe: fix link stability for 40G NIC
From: Stephen Hemminger @ 2026-06-24 16:18 UTC (permalink / raw)
To: Zaiyu Wang; +Cc: dev, stable, Jiawen Wu
In-Reply-To: <20260624115254.20348-14-zaiyuwang@trustnetic.com>
On Wed, 24 Jun 2026 19:52:45 +0800
Zaiyu Wang <zaiyuwang@trustnetic.com> wrote:
> +
> +void txgbe_e56_rx_rd_second_code_40g(struct txgbe_hw *hw, int *SECOND_CODE, int lane)
> +{
> + int i, median;
> + unsigned int rdata;
> + u32 addr;
> + int RXS_BBCDR_SECOND_ORDER_ST[RXS_READ_COUNT];
> +
> + /* Set ovrd_en=0 to read ASIC value */
> + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (lane * E56PHY_RXS_OFFSET);
> + rdata = rd32_ephy(hw, addr);
> + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_int_cstm_i) = 0;
> + wr32_ephy(hw, addr, rdata);
> +
> + /*
> + * As status update from RXS hardware is asynchronous to read status of SECOND_ORDER,
> + * follow sequence mentioned below.
> + */
> + for (i = 0; i < RXS_READ_COUNT; i = i + 1) {
> + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (lane * E56PHY_RXS_OFFSET);
> + rdata = rd32_ephy(hw, addr);
> + RXS_BBCDR_SECOND_ORDER_ST[i] = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5,
> + ana_bbcdr_int_cstm_i);
> + usec_delay(100);
> + }
> +
> + /* sort array RXS_BBCDR_SECOND_ORDER_ST[i] */
> + qsort(RXS_BBCDR_SECOND_ORDER_ST, RXS_READ_COUNT, sizeof(int), txgbe_e56_int_cmp);
> +
> + median = ((RXS_READ_COUNT + 1) / 2) - 1;
> + *SECOND_CODE = RXS_BBCDR_SECOND_ORDER_ST[median];
> +
> + return;
> +}
These extra returns are causing extra checkpatch warnings.
I know this is base code but if possible could you remove them.
WARNING:RETURN_VOID: void function return statements are not generally useful
#707: FILE: drivers/net/txgbe/base/txgbe_e56.c:1806:
+ return;
+}
WARNING:RETURN_VOID: void function return statements are not generally useful
#736: FILE: drivers/net/txgbe/base/txgbe_e56.c:1835:
+ return;
+}
^ permalink raw reply
* [PATCH] checkpatches: suppress warnings about msleep()
From: Stephen Hemminger @ 2026-06-24 16:25 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, Thomas Monjalon
The DPDK checkpatch uses the underlying kernel tool which
does some checks that are only relevant in kernel code.
The warning about msleep() time only makes sense in the
kernel.
Suppress feedback like:
WARNING:MSLEEP: msleep < 20ms can sleep for up to 20ms; see function description of msleep().
+ msleep(10);
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
devtools/checkpatches.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/devtools/checkpatches.sh b/devtools/checkpatches.sh
index f5dd77443f..071bdb2c15 100755
--- a/devtools/checkpatches.sh
+++ b/devtools/checkpatches.sh
@@ -34,7 +34,7 @@ PREFER_KERNEL_TYPES,PREFER_FALLTHROUGH,BIT_MACRO,CONST_STRUCT,\
SPLIT_STRING,LONG_LINE_STRING,C99_COMMENT_TOLERANCE,\
LINE_SPACING,PARENTHESIS_ALIGNMENT,NETWORKING_BLOCK_COMMENT_STYLE,\
NEW_TYPEDEFS,COMPARISON_TO_NULL,AVOID_BUG,EXPORT_SYMBOL,\
-BAD_REPORTED_BY_LINK"
+BAD_REPORTED_BY_LINK,MSLEEP"
options="$options $DPDK_CHECKPATCH_OPTIONS"
print_usage () {
--
2.53.0
^ permalink raw reply related
* Re: [PATCH v6 00/23] net/sxe2: added Linkdata sxe2 ethernet driver
From: Stephen Hemminger @ 2026-06-24 16:38 UTC (permalink / raw)
To: liujie5; +Cc: dev
In-Reply-To: <20260624020211.3687062-1-liujie5@linkdatatechnology.com>
On Wed, 24 Jun 2026 10:02:11 +0800
liujie5@linkdatatechnology.com wrote:
> From: Jie Liu <liujie5@linkdatatechnology.com>
>
> This patch set implements core functionality for the SXE2 PMD,
> including basic driver framework, data path setup, and advanced
> offload features (VLAN, RSS,TM, PTP etc.).
>
> V6:
> Refactored sxe2_ptype_tbl from adapter-indirection pattern (adapter->ptype_tbl[])
> to extern const direct-access pattern, matching txgbe PMD convention
>
> All vector/SIMD Rx paths (SSE, AVX2, AVX512, NEON) index sxe2_ptype_tbl[] directly without local pointer indirection
>
> remove flow_dup_pattern_mode devarg
>
> Jie Liu (23):
> net/sxe2: remove software statistics devargs
> net/sxe2: add Rx framework and packet types callback
> net/sxe2: support AVX512 vectorized path for Rx and Tx
> net/sxe2: add AVX2 vector data path for Rx and Tx
> net/sxe2: add link update callback
> net/sxe2: support L2 filtering and MAC config
> drivers: support RSS feature
> net/sxe2: support TM hierarchy and shaping
> net/sxe2: support IPsec inline protocol offload
> net/sxe2: support statistics and multi-process
> drivers: interrupt handling
> net/sxe2: add NEON vec Rx/Tx burst functions
> drivers: add support for VF representors
> net/sxe2: add support for custom UDP tunnel ports
> net/sxe2: support firmware version reading
> net/sxe2: implement get monitor address
> common/sxe2: add shared SFP module definitions
> net/sxe2: support SFP module info and EEPROM access
> net/sxe2: implement private dump info
> net/sxe2: add mbuf validation in Tx debug mode
> common/sxe2: add callback for memory event handling
> net/sxe2: add private devargs parsing
> net/sxe2: update sxe2 feature matrix docs
>
> doc/guides/nics/features/sxe2.ini | 56 +
> doc/guides/nics/sxe2.rst | 147 ++
> drivers/common/sxe2/sxe2_common.c | 156 ++
> drivers/common/sxe2/sxe2_common.h | 4 +
> drivers/common/sxe2/sxe2_flow_public.h | 633 +++++++
> drivers/common/sxe2/sxe2_ioctl_chnl.c | 178 +-
> drivers/common/sxe2/sxe2_ioctl_chnl_func.h | 18 +
> drivers/common/sxe2/sxe2_msg.h | 118 ++
> drivers/net/sxe2/meson.build | 52 +
> drivers/net/sxe2/sxe2_cmd_chnl.c | 1587 +++++++++++++++-
> drivers/net/sxe2/sxe2_cmd_chnl.h | 139 ++
> drivers/net/sxe2/sxe2_drv_cmd.h | 523 +++++-
> drivers/net/sxe2/sxe2_dump.c | 300 +++
> drivers/net/sxe2/sxe2_dump.h | 12 +
> drivers/net/sxe2/sxe2_ethdev.c | 1468 ++++++++++++++-
> drivers/net/sxe2/sxe2_ethdev.h | 111 +-
> drivers/net/sxe2/sxe2_ethdev_repr.c | 609 ++++++
> drivers/net/sxe2/sxe2_ethdev_repr.h | 32 +
> drivers/net/sxe2/sxe2_filter.c | 895 +++++++++
> drivers/net/sxe2/sxe2_filter.h | 100 +
> drivers/net/sxe2/sxe2_flow.c | 1391 ++++++++++++++
> drivers/net/sxe2/sxe2_flow.h | 30 +
> drivers/net/sxe2/sxe2_flow_define.h | 144 ++
> drivers/net/sxe2/sxe2_flow_parse_action.c | 1182 ++++++++++++
> drivers/net/sxe2/sxe2_flow_parse_action.h | 23 +
> drivers/net/sxe2/sxe2_flow_parse_engine.c | 106 ++
> drivers/net/sxe2/sxe2_flow_parse_engine.h | 13 +
> drivers/net/sxe2/sxe2_flow_parse_pattern.c | 1935 +++++++++++++++++++
> drivers/net/sxe2/sxe2_flow_parse_pattern.h | 46 +
> drivers/net/sxe2/sxe2_ipsec.c | 1565 ++++++++++++++++
> drivers/net/sxe2/sxe2_ipsec.h | 254 +++
> drivers/net/sxe2/sxe2_irq.c | 1026 ++++++++++
> drivers/net/sxe2/sxe2_irq.h | 25 +
> drivers/net/sxe2/sxe2_mac.c | 530 ++++++
> drivers/net/sxe2/sxe2_mac.h | 84 +
> drivers/net/sxe2/sxe2_mp.c | 414 +++++
> drivers/net/sxe2/sxe2_mp.h | 67 +
> drivers/net/sxe2/sxe2_queue.c | 17 +-
> drivers/net/sxe2/sxe2_queue.h | 15 +-
> drivers/net/sxe2/sxe2_rss.c | 584 ++++++
> drivers/net/sxe2/sxe2_rss.h | 81 +
> drivers/net/sxe2/sxe2_rx.c | 93 +-
> drivers/net/sxe2/sxe2_rx.h | 2 +
> drivers/net/sxe2/sxe2_security.c | 335 ++++
> drivers/net/sxe2/sxe2_security.h | 77 +
> drivers/net/sxe2/sxe2_stats.c | 586 ++++++
> drivers/net/sxe2/sxe2_stats.h | 39 +
> drivers/net/sxe2/sxe2_switchdev.c | 332 ++++
> drivers/net/sxe2/sxe2_switchdev.h | 33 +
> drivers/net/sxe2/sxe2_tm.c | 1151 ++++++++++++
> drivers/net/sxe2/sxe2_tm.h | 76 +
> drivers/net/sxe2/sxe2_tx.c | 7 +
> drivers/net/sxe2/sxe2_txrx.c | 1958 +++++++++++++++++++-
> drivers/net/sxe2/sxe2_txrx.h | 8 +
> drivers/net/sxe2/sxe2_txrx_check_mbuf.c | 595 ++++++
> drivers/net/sxe2/sxe2_txrx_check_mbuf.h | 38 +
> drivers/net/sxe2/sxe2_txrx_poll.c | 284 ++-
> drivers/net/sxe2/sxe2_txrx_vec.c | 46 +-
> drivers/net/sxe2/sxe2_txrx_vec.h | 38 +-
> drivers/net/sxe2/sxe2_txrx_vec_avx2.c | 747 ++++++++
> drivers/net/sxe2/sxe2_txrx_vec_avx512.c | 867 +++++++++
> drivers/net/sxe2/sxe2_txrx_vec_common.h | 54 +-
> drivers/net/sxe2/sxe2_txrx_vec_neon.c | 689 +++++++
> drivers/net/sxe2/sxe2_txrx_vec_sse.c | 38 +-
> drivers/net/sxe2/sxe2_vsi.c | 146 ++
> drivers/net/sxe2/sxe2_vsi.h | 12 +-
> drivers/net/sxe2/sxe2vf_regs.h | 85 +
> 67 files changed, 24733 insertions(+), 273 deletions(-)
> create mode 100644 drivers/common/sxe2/sxe2_flow_public.h
> create mode 100644 drivers/common/sxe2/sxe2_msg.h
> create mode 100644 drivers/net/sxe2/sxe2_dump.c
> create mode 100644 drivers/net/sxe2/sxe2_dump.h
> create mode 100644 drivers/net/sxe2/sxe2_ethdev_repr.c
> create mode 100644 drivers/net/sxe2/sxe2_ethdev_repr.h
> create mode 100644 drivers/net/sxe2/sxe2_filter.c
> create mode 100644 drivers/net/sxe2/sxe2_filter.h
> create mode 100644 drivers/net/sxe2/sxe2_flow.c
> create mode 100644 drivers/net/sxe2/sxe2_flow.h
> create mode 100644 drivers/net/sxe2/sxe2_flow_define.h
> create mode 100644 drivers/net/sxe2/sxe2_flow_parse_action.c
> create mode 100644 drivers/net/sxe2/sxe2_flow_parse_action.h
> create mode 100644 drivers/net/sxe2/sxe2_flow_parse_engine.c
> create mode 100644 drivers/net/sxe2/sxe2_flow_parse_engine.h
> create mode 100644 drivers/net/sxe2/sxe2_flow_parse_pattern.c
> create mode 100644 drivers/net/sxe2/sxe2_flow_parse_pattern.h
> create mode 100644 drivers/net/sxe2/sxe2_ipsec.c
> create mode 100644 drivers/net/sxe2/sxe2_ipsec.h
> create mode 100644 drivers/net/sxe2/sxe2_irq.c
> create mode 100644 drivers/net/sxe2/sxe2_mac.c
> create mode 100644 drivers/net/sxe2/sxe2_mac.h
> create mode 100644 drivers/net/sxe2/sxe2_mp.c
> create mode 100644 drivers/net/sxe2/sxe2_mp.h
> create mode 100644 drivers/net/sxe2/sxe2_rss.c
> create mode 100644 drivers/net/sxe2/sxe2_rss.h
> create mode 100644 drivers/net/sxe2/sxe2_security.c
> create mode 100644 drivers/net/sxe2/sxe2_security.h
> create mode 100644 drivers/net/sxe2/sxe2_stats.c
> create mode 100644 drivers/net/sxe2/sxe2_stats.h
> create mode 100644 drivers/net/sxe2/sxe2_switchdev.c
> create mode 100644 drivers/net/sxe2/sxe2_switchdev.h
> create mode 100644 drivers/net/sxe2/sxe2_tm.c
> create mode 100644 drivers/net/sxe2/sxe2_tm.h
> create mode 100644 drivers/net/sxe2/sxe2_txrx_check_mbuf.c
> create mode 100644 drivers/net/sxe2/sxe2_txrx_check_mbuf.h
> create mode 100644 drivers/net/sxe2/sxe2_txrx_vec_avx2.c
> create mode 100644 drivers/net/sxe2/sxe2_txrx_vec_avx512.c
> create mode 100644 drivers/net/sxe2/sxe2_txrx_vec_neon.c
> create mode 100644 drivers/net/sxe2/sxe2vf_regs.h
>
On the duplicate flow devargs; your observation was correct, mlx5 has similar devarg option.
Sorry that I didn't strongly nudge AI in the right direction earlier.
To be clear:
- sxe2 should use same devarg as mlx5 for this "allow_duplicate_pattern"
- default should be 1
- make sure documentation matches flag.
The patch looks much better; but there is a bisection breaking
patch ordering around 6 and 7.
After I pushed AI review to follow that, the review was the following:
(I means Claude AI, not me Stephen)
[PATCH v6 00/23] sxe2 driver feature additions
The flow-duplicate-pattern situation regressed in the wrong direction.
I reread mlx5's allow_duplicate_pattern in light of your "align to mlx5"
guidance and I was wrong to push for removal in v4 and v5. mlx5 has the same
devarg: name allow_duplicate_pattern, default 1, valid 0|1, and both values
expose a real hardware capability that rte_flow itself does not articulate
(value 0 -> EEXIST on duplicate; value 1 -> hardware queues duplicates as
shadow rules that activate when prior rules are deleted). That is not a
"standard API by boot flag" semantics violation as I had read it - it is a
hardware capability switch, and it is documented in doc/guides/nics/mlx5.rst
exactly the way sxe2's was. My v4-v5 push to drop it was based on a
misreading.
Unfortunately the v6 response is to half-remove the devarg in a way that is
worse than either keeping it or removing it cleanly:
[PATCH v6 22/23] flow-duplicate-pattern parsing removed, field left behind
Verified in the assembled tree:
drivers/net/sxe2/sxe2_ethdev.h:138:
uint8_t flow_dup_pattern_mode; /* field still in struct */
drivers/net/sxe2/sxe2_flow.c:806:
rte_flow_error_set(error, EEXIST, ..., NULL,
adapter->devargs.flow_dup_pattern_mode ?
"Duplicate flow pattern." :
"Duplicate flow pattern is not allowed.");
drivers/common/sxe2/sxe2_flow_public.h:603:
uint8_t switch_pattern_dup_allow; /* still in flow metadata */
The devarg's parser, default-setter, register_param_string entry, and
documentation are all gone, but the storage and the read site remain.
The field is zero-initialized and never written, so the ternary always picks
the "is not allowed" string. The hardware-capability path that the value=1
branch used to drive (setting switch_pattern_dup_allow on per-rule metadata)
has no caller now either. None of this is a correctness bug - duplicate
rules are uniformly rejected with EEXIST, which is the conservative
behaviour - but it is dead code that misleads the next reader.
Suggested fix: revert the v5-to-v6 changes that removed the parser and
docs, and instead align with mlx5:
- Rename the devarg to allow_duplicate_pattern (underscore, matching
mlx5's spelling).
- Keep default = 1, matching mlx5's non-HWS default.
- Reuse mlx5's documentation wording in sxe2.rst, adapted for the
switch engine. The "only the first rule takes effect, the next
activates when the first is deleted" semantic from mlx5.rst describes
what the value=1 path does in hardware, and that wording is what was
missing from v5's documentation.
- Keep switch_pattern_dup_allow in flow metadata since it is what
propagates the policy to the hardware programming path.
Or, if the cleaner path is preferred: actually finish the removal. Drop
flow_dup_pattern_mode from struct sxe2_devargs, replace the ternary in
sxe2_flow.c with the single "is not allowed" string, and drop
switch_pattern_dup_allow from struct (or wire it to a compile-time
constant if hardware programming truly needs it). Either direction is
defensible; the v6 in-between state is not.
[PATCH v6 06/23 and 07/23] patches posted in wrong order in the bundle
The bundle has 07/23 (drivers: support RSS feature) before 06/23
(net/sxe2: support L2 filtering and MAC config). git am applies them in
mbox order, so the series fails to apply: 07/23 depends on symbols 06/23
introduces. The fix is just to repost the bundle in numeric order;
contents are byte-identical to v5 for both patches. Worth fixing before
the next post because anyone running git am < bundle.mbox hits this.
Once the mbox order is fixed and the flow-duplicate-pattern situation is
resolved one way or the other, this is ready.
^ permalink raw reply
* Re: [PATCH v10 00/21] Wangxun Fixes
From: Stephen Hemminger @ 2026-06-24 16:43 UTC (permalink / raw)
To: Zaiyu Wang; +Cc: dev
In-Reply-To: <20260624115254.20348-1-zaiyuwang@trustnetic.com>
On Wed, 24 Jun 2026 19:52:32 +0800
Zaiyu Wang <zaiyuwang@trustnetic.com> wrote:
> This series fixes several issues found on Wangxun Emerald, Sapphire and
> Amber-lite NICs, with a focus on link-related problems.
> ---
> v10:
> - Fixed compilation error on clang
> - Renamed unprefixed symbols
> ---
> v9:
> - Fixed several checkpatch errors
> ---
> v8:
> - Fixed compilation error by replacing RTE_ETH_DEV_TO_PCI with RTE_CLASS_TO_BUS_DEVICE
> ---
> v7:
> - Fixed inverted semantics of is_flat_mem to match SFF8636
> ---
> v6:
> - Fixed more issues identified by AI review
> ---
> v5:
> - Fixed issues identified by AI review
> ---
> v4:
> - Fixed issues identified by devtools scripts
> ---
> v3:
> - Addressed Stephen's comments
> ---
> v2:
> - Fixed compilation error and code style issues
> ---
>
> Zaiyu Wang (21):
> net/txgbe: remove duplicate xstats counters
> net/ngbe: remove duplicate xstats counters
> net/ngbe: add missing CDR config for YT PHY
> net/ngbe: fix VF promiscuous and allmulticast
> net/txgbe: fix inaccuracy in Tx rate limiting
> net/txgbe: fix link status check condition
> net/txgbe: fix Tx desc free logic
> net/txgbe: fix link flow control registers for Amber-Lite
> net/txgbe: fix link flow control config for Sapphire
> net/txgbe: fix a mass of unknown interrupts
> net/txgbe: fix traffic class priority configuration
> net/txgbe: fix link stability for 25G NIC
> net/txgbe: fix link stability for 40G NIC
> net/txgbe: fix link stability for Amber-Lite backplane mode
> net/txgbe: fix FEC mode configuration on 25G NIC
> net/txgbe: fix SFP module identification
> net/txgbe: fix get module info operation
> net/txgbe: fix get EEPROM operation
> net/txgbe: fix to reset Tx write-back pointer
> net/txgbe: fix to enable Tx desc check
> net/txgbe: fix temperature track for AML NIC
>
> drivers/net/ngbe/base/ngbe_phy_yt.c | 3 +
> drivers/net/ngbe/ngbe_ethdev.c | 5 -
> drivers/net/ngbe/ngbe_ethdev_vf.c | 11 +-
> drivers/net/txgbe/base/meson.build | 2 +
> drivers/net/txgbe/base/txgbe.h | 2 +
> drivers/net/txgbe/base/txgbe_aml.c | 185 +-
> drivers/net/txgbe/base/txgbe_aml.h | 6 +-
> drivers/net/txgbe/base/txgbe_aml40.c | 114 +-
> drivers/net/txgbe/base/txgbe_aml40.h | 6 +-
> drivers/net/txgbe/base/txgbe_dcb_hw.c | 2 +-
> drivers/net/txgbe/base/txgbe_e56.c | 3746 +++++++++++++++++++++
> drivers/net/txgbe/base/txgbe_e56.h | 1778 ++++++++++
> drivers/net/txgbe/base/txgbe_e56_bp.c | 2597 ++++++++++++++
> drivers/net/txgbe/base/txgbe_e56_bp.h | 282 ++
> drivers/net/txgbe/base/txgbe_hw.c | 54 +-
> drivers/net/txgbe/base/txgbe_hw.h | 4 +-
> drivers/net/txgbe/base/txgbe_osdep.h | 4 +
> drivers/net/txgbe/base/txgbe_phy.c | 362 +-
> drivers/net/txgbe/base/txgbe_phy.h | 46 +-
> drivers/net/txgbe/base/txgbe_regs.h | 13 +-
> drivers/net/txgbe/base/txgbe_type.h | 43 +-
> drivers/net/txgbe/txgbe_ethdev.c | 472 ++-
> drivers/net/txgbe/txgbe_ethdev.h | 7 +-
> drivers/net/txgbe/txgbe_rxtx.c | 111 +-
> drivers/net/txgbe/txgbe_rxtx.h | 38 +-
> drivers/net/txgbe/txgbe_rxtx_vec_common.h | 17 +-
> 26 files changed, 9464 insertions(+), 446 deletions(-)
> create mode 100644 drivers/net/txgbe/base/txgbe_e56.c
> create mode 100644 drivers/net/txgbe/base/txgbe_e56.h
> create mode 100644 drivers/net/txgbe/base/txgbe_e56_bp.c
> create mode 100644 drivers/net/txgbe/base/txgbe_e56_bp.h
>
Applied to net-next.
If you want to cleanup some of the checkpatch warnings, I can swap in a new version.
^ permalink raw reply
* Re: [PATCH v2] dts: update dts check format script and resolve errors
From: Koushik Bhargav Nimoji @ 2026-06-24 16:47 UTC (permalink / raw)
To: luca.vizzarro, patrickrobb1997; +Cc: dev, abailey, ahassick, lylavoie
In-Reply-To: <20260618204525.1010218-1-knimoji@iol.unh.edu>
[-- Attachment #1: Type: text/plain, Size: 81764 bytes --]
Recheck-request: github-robot: build
On Thu, Jun 18, 2026 at 4:45 PM Koushik Bhargav Nimoji <knimoji@iol.unh.edu>
wrote:
> This patch updates the tool versions used in the dts-check-format.sh
> script; by doing so, formatting and type hinting errors that weren't
> previously visible have now appeared. This patch also resolves those
> new formatting and type hinting errors.
>
> Signed-off-by: Koushik Bhargav Nimoji <knimoji@iol.unh.edu>
> ---
> v2:
> *Fixed type hinting issues stemming from ParamSpec
> issues.
> *Fixed tarball write type parameter for copying
> directories from one node to another.
> ---
> dts/api/packet.py | 15 +-
> dts/api/testpmd/__init__.py | 12 +-
> dts/api/testpmd/types.py | 6 +-
> dts/framework/config/__init__.py | 24 +-
> dts/framework/config/test_run.py | 12 +-
> dts/framework/context.py | 8 +-
> .../interactive_remote_session.py | 2 +-
> .../remote_session/interactive_shell.py | 6 +-
> .../remote_session/remote_session.py | 4 +-
> dts/framework/remote_session/shell_pool.py | 2 +-
> dts/framework/settings.py | 8 +-
> dts/framework/testbed_model/cpu.py | 2 +-
> .../testbed_model/traffic_generator/scapy.py | 6 +-
> .../testbed_model/traffic_generator/trex.py | 6 +-
> dts/framework/utils.py | 13 +-
> dts/poetry.lock | 368 ++++++++++++++----
> dts/pyproject.toml | 8 +-
> dts/tests/TestSuite_cryptodev_throughput.py | 4 +-
> dts/tests/TestSuite_port_control.py | 3 +-
> .../TestSuite_single_core_forward_perf.py | 2 +-
> 20 files changed, 372 insertions(+), 139 deletions(-)
>
> diff --git a/dts/api/packet.py b/dts/api/packet.py
> index 094a1b7a9d..3dda18e781 100644
> --- a/dts/api/packet.py
> +++ b/dts/api/packet.py
> @@ -87,9 +87,9 @@ def send_packets_and_capture(
> CapturingTrafficGenerator,
> )
>
> - assert isinstance(
> - get_ctx().func_tg, CapturingTrafficGenerator
> - ), "Cannot capture with a non-capturing traffic generator"
> + assert isinstance(get_ctx().func_tg, CapturingTrafficGenerator), (
> + "Cannot capture with a non-capturing traffic generator"
> + )
> tg: CapturingTrafficGenerator = cast(CapturingTrafficGenerator,
> get_ctx().func_tg)
> # TODO: implement @requires for types of traffic generator
> packets = adjust_addresses(packets)
> @@ -308,8 +308,7 @@ def _verify_l2_frame(received_packet: Ether,
> contains_l3: bool) -> bool:
> if contains_l3:
> expected_src_mac = get_ctx().topology.sut_port_egress.mac_address
> log_debug(
> - f"Comparing received src mac '{received_packet.src}' "
> - f"with expected '{expected_src_mac}'."
> + f"Comparing received src mac '{received_packet.src}' with
> expected '{expected_src_mac}'."
> )
> if received_packet.src != expected_src_mac:
> return False
> @@ -344,9 +343,9 @@ def assess_performance_by_packet(
> PerformanceTrafficGenerator,
> )
>
> - assert isinstance(
> - get_ctx().perf_tg, PerformanceTrafficGenerator
> - ), "Cannot send performance traffic with non-performance traffic
> generator"
> + assert isinstance(get_ctx().perf_tg, PerformanceTrafficGenerator), (
> + "Cannot send performance traffic with non-performance traffic
> generator"
> + )
> tg: PerformanceTrafficGenerator = cast(PerformanceTrafficGenerator,
> get_ctx().perf_tg)
> # TODO: implement @requires for types of traffic generator
> return tg.calculate_traffic_and_stats(packet, duration, send_mpps)
> diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
> index e9187440bb..f4767c6aeb 100644
> --- a/dts/api/testpmd/__init__.py
> +++ b/dts/api/testpmd/__init__.py
> @@ -76,7 +76,9 @@ def _requires_stopped_ports(func: TestPmdMethod) ->
> TestPmdMethod:
> """
>
> @functools.wraps(func)
> - def _wrapper(self: "TestPmd", *args: P.args, **kwargs: P.kwargs) ->
> Any:
> + def _wrapper(
> + self: "TestPmd", *args: P.args, **kwargs: P.kwargs
> + ) -> Callable[Concatenate["TestPmd", P], Any]:
> if self.ports_started:
> self._logger.debug("Ports need to be stopped to continue.")
> self.stop_all_ports()
> @@ -100,7 +102,9 @@ def _requires_started_ports(func: TestPmdMethod) ->
> TestPmdMethod:
> """
>
> @functools.wraps(func)
> - def _wrapper(self: "TestPmd", *args: P.args, **kwargs: P.kwargs) ->
> Any:
> + def _wrapper(
> + self: "TestPmd", *args: P.args, **kwargs: P.kwargs
> + ) -> Callable[Concatenate["TestPmd", P], Any]:
> if not self.ports_started:
> self._logger.debug("Ports need to be started to continue.")
> self.start_all_ports()
> @@ -128,7 +132,9 @@ def _add_remove_mtu(mtu: int = 1500) ->
> Callable[[TestPmdMethod], TestPmdMethod]
>
> def decorator(func: TestPmdMethod) -> TestPmdMethod:
> @functools.wraps(func)
> - def wrapper(self: "TestPmd", *args: P.args, **kwargs: P.kwargs)
> -> Any:
> + def wrapper(
> + self: "TestPmd", *args: P.args, **kwargs: P.kwargs
> + ) -> Callable[Concatenate["TestPmd", P], Any]:
> original_mtu = self.ports[0].mtu
> self.set_port_mtu_all(mtu=mtu, verify=False)
> retval = func(self, *args, **kwargs)
> diff --git a/dts/api/testpmd/types.py b/dts/api/testpmd/types.py
> index 0d322aece2..af3263682e 100644
> --- a/dts/api/testpmd/types.py
> +++ b/dts/api/testpmd/types.py
> @@ -279,7 +279,7 @@ def from_list_string(cls, names: str) -> Self:
> Returns:
> An instance of this flag.
> """
> - flag = cls(0)
> + flag: RSSOffloadTypesFlag = cls(0)
> for name in names.split():
> flag |= cls.from_str(name)
> return flag
> @@ -960,7 +960,7 @@ def from_list_string(cls, names: str) -> Self:
> Returns:
> An instance of this flag.
> """
> - flag = cls(0)
> + flag: PacketOffloadFlag = cls(0)
> for name in names.split():
> flag |= cls.from_str(name)
> return flag
> @@ -1168,7 +1168,7 @@ def from_list_string(cls, names: str) -> Self:
> Returns:
> An instance of this flag.
> """
> - flag = cls(0)
> + flag: RtePTypes = cls(0)
> for name in names.split():
> flag |= cls.from_str(name)
> return flag
> diff --git a/dts/framework/config/__init__.py
> b/dts/framework/config/__init__.py
> index d2f0138e4a..a8861894b7 100644
> --- a/dts/framework/config/__init__.py
> +++ b/dts/framework/config/__init__.py
> @@ -85,9 +85,9 @@ def validate_port_links(self) -> Self:
> sut_node_port_peer = existing_port_links.get(
> (self.test_run.system_under_test_node, link.sut_port),
> None
> )
> - assert (
> - sut_node_port_peer is not None
> - ), f"Invalid SUT node port specified for link
> port_topology.{link_idx}."
> + assert sut_node_port_peer is not None, (
> + f"Invalid SUT node port specified for link
> port_topology.{link_idx}."
> + )
>
> assert sut_node_port_peer is False or sut_node_port_peer ==
> link.right, (
> f"The SUT node port for link port_topology.{link_idx} is "
> @@ -97,9 +97,9 @@ def validate_port_links(self) -> Self:
> tg_node_port_peer = existing_port_links.get(
> (self.test_run.traffic_generator_node, link.tg_port), None
> )
> - assert (
> - tg_node_port_peer is not None
> - ), f"Invalid TG node port specified for link
> port_topology.{link_idx}."
> + assert tg_node_port_peer is not None, (
> + f"Invalid TG node port specified for link
> port_topology.{link_idx}."
> + )
>
> assert tg_node_port_peer is False or sut_node_port_peer ==
> link.left, (
> f"The TG node port for link port_topology.{link_idx} is "
> @@ -117,16 +117,16 @@ def validate_test_run_against_nodes(self) -> Self:
> sut_node_name = self.test_run.system_under_test_node
> sut_node = next((n for n in self.nodes if n.name ==
> sut_node_name), None)
>
> - assert (
> - sut_node is not None
> - ), f"The system_under_test_node {sut_node_name} is not a valid
> node name."
> + assert sut_node is not None, (
> + f"The system_under_test_node {sut_node_name} is not a valid
> node name."
> + )
>
> tg_node_name = self.test_run.traffic_generator_node
> tg_node = next((n for n in self.nodes if n.name ==
> tg_node_name), None)
>
> - assert (
> - tg_node is not None
> - ), f"The traffic_generator_name {tg_node_name} is not a valid
> node name."
> + assert tg_node is not None, (
> + f"The traffic_generator_name {tg_node_name} is not a valid
> node name."
> + )
>
> return self
>
> diff --git a/dts/framework/config/test_run.py
> b/dts/framework/config/test_run.py
> index 76e24d1785..3cd643981d 100644
> --- a/dts/framework/config/test_run.py
> +++ b/dts/framework/config/test_run.py
> @@ -233,9 +233,9 @@ def test_suite_spec(self) -> "TestSuiteSpec":
> from framework.test_suite import find_by_name
>
> test_suite_spec = find_by_name(self.test_suite_name)
> - assert (
> - test_suite_spec is not None
> - ), f"{self.test_suite_name} is not a valid test suite module
> name."
> + assert test_suite_spec is not None, (
> + f"{self.test_suite_name} is not a valid test suite module
> name."
> + )
> return test_suite_spec
>
> @cached_property
> @@ -384,9 +384,9 @@ def convert_from_string(cls, data: Any) -> Any:
> @model_validator(mode="after")
> def verify_distinct_nodes(self) -> Self:
> """Verify that each side of the link has distinct nodes."""
> - assert (
> - self.left.node_type != self.right.node_type
> - ), "Linking ports of the same node is unsupported."
> + assert self.left.node_type != self.right.node_type, (
> + "Linking ports of the same node is unsupported."
> + )
> return self
>
>
> diff --git a/dts/framework/context.py b/dts/framework/context.py
> index 8f1021dc96..efe9af0645 100644
> --- a/dts/framework/context.py
> +++ b/dts/framework/context.py
> @@ -60,9 +60,9 @@ def reset(self) -> None:
> else _field.default
> )
>
> - assert (
> - default is not MISSING
> - ), "{LocalContext.__name__} must have defaults on all fields!"
> + assert default is not MISSING, (
> + "{LocalContext.__name__} must have defaults on all
> fields!"
> + )
>
> setattr(self, _field.name, default)
>
> @@ -108,7 +108,7 @@ def filter_cores(
> ) -> Callable[[type["TestProtocol"]], Callable]:
> """Decorates functions that require a temporary update to the lcore
> specifier."""
>
> - def decorator(func: type["TestProtocol"]) -> Callable:
> + def decorator(func: type["TestProtocol"]) -> Callable[P,
> type["TestProtocol"]]:
> @functools.wraps(func)
> def wrapper(*args: P.args, **kwargs: P.kwargs) -> Any:
> local_ctx = get_ctx().local
> diff --git a/dts/framework/remote_session/interactive_remote_session.py
> b/dts/framework/remote_session/interactive_remote_session.py
> index c8156b4345..fc42e862bc 100644
> --- a/dts/framework/remote_session/interactive_remote_session.py
> +++ b/dts/framework/remote_session/interactive_remote_session.py
> @@ -109,7 +109,7 @@ def _connect(self) -> None:
> self._logger.debug(traceback.format_exc())
> self._logger.warning(e)
> self._logger.info(
> - f"Retrying interactive session connection: retry
> number {retry_attempt +1}"
> + f"Retrying interactive session connection: retry
> number {retry_attempt + 1}"
> )
> else:
> break
> diff --git a/dts/framework/remote_session/interactive_shell.py
> b/dts/framework/remote_session/interactive_shell.py
> index a65cbce209..6bba58a4f6 100644
> --- a/dts/framework/remote_session/interactive_shell.py
> +++ b/dts/framework/remote_session/interactive_shell.py
> @@ -50,7 +50,9 @@
> def only_active(func: InteractiveShellMethod) -> InteractiveShellMethod:
> """This decorator will skip running the method if the SSH channel is
> not active."""
>
> - def _wrapper(self: "InteractiveShell", *args: P.args, **kwargs:
> P.kwargs) -> R | None:
> + def _wrapper(
> + self: "InteractiveShell", *args: P.args, **kwargs: P.kwargs
> + ) -> Callable[P, "InteractiveShell"] | None:
> if self._ssh_channel.active:
> return func(self, *args, **kwargs)
> return None
> @@ -167,7 +169,7 @@ def start_application(self, prompt: str | None = None,
> add_to_shell_pool: bool =
> break
> except InteractiveSSHTimeoutError:
> self._logger.info(
> - f"Interactive shell failed to start (attempt
> {attempt+1} out of "
> + f"Interactive shell failed to start (attempt {attempt
> + 1} out of "
> f"{self._init_attempts})"
> )
> else:
> diff --git a/dts/framework/remote_session/remote_session.py
> b/dts/framework/remote_session/remote_session.py
> index 158325bb7f..fb5f6fedf5 100644
> --- a/dts/framework/remote_session/remote_session.py
> +++ b/dts/framework/remote_session/remote_session.py
> @@ -72,9 +72,7 @@ def __post_init__(self, init_stdout: str, init_stderr:
> str) -> None:
> def __str__(self) -> str:
> """Format the command outputs."""
> return (
> - f"stdout: '{self.stdout}'\n"
> - f"stderr: '{self.stderr}'\n"
> - f"return_code: '{self.return_code}'"
> + f"stdout: '{self.stdout}'\nstderr:
> '{self.stderr}'\nreturn_code: '{self.return_code}'"
> )
>
>
> diff --git a/dts/framework/remote_session/shell_pool.py
> b/dts/framework/remote_session/shell_pool.py
> index 241737eab3..710107c6cb 100644
> --- a/dts/framework/remote_session/shell_pool.py
> +++ b/dts/framework/remote_session/shell_pool.py
> @@ -74,7 +74,7 @@ def unregister_shell(self, shell: "InteractiveShell") ->
> None:
>
> def start_new_pool(self) -> None:
> """Start a new shell pool."""
> - self._logger.debug(f"Starting new shell pool and advancing to
> level {self.pool_level+1}.")
> + self._logger.debug(f"Starting new shell pool and advancing to
> level {self.pool_level + 1}.")
> self._pools.append(set())
>
> def terminate_current_pool(self) -> None:
> diff --git a/dts/framework/settings.py b/dts/framework/settings.py
> index b08373b7ea..f329677804 100644
> --- a/dts/framework/settings.py
> +++ b/dts/framework/settings.py
> @@ -249,9 +249,9 @@ def error(self, message) -> NoReturn:
> if _is_from_env(action):
> action_name = _get_action_name(action)
> env_var_name = _get_env_var_name(action)
> - assert (
> - env_var_name is not None
> - ), "Action was set from environment, but no environment
> variable name was found."
> + assert env_var_name is not None, (
> + "Action was set from environment, but no environment
> variable name was found."
> + )
> env_var_value = os.environ.get(env_var_name)
>
> message = message.replace(
> @@ -260,7 +260,7 @@ def error(self, message) -> NoReturn:
> )
>
> print(f"{self.prog}: error: {message}\n", file=sys.stderr)
> - self.exit(2, "For help and usage, " "run the command with the
> --help flag.\n")
> + self.exit(2, "For help and usage, run the command with the --help
> flag.\n")
>
>
> class _EnvVarHelpFormatter(ArgumentDefaultsHelpFormatter):
> diff --git a/dts/framework/testbed_model/cpu.py
> b/dts/framework/testbed_model/cpu.py
> index 6e2ecca080..a9471709dd 100644
> --- a/dts/framework/testbed_model/cpu.py
> +++ b/dts/framework/testbed_model/cpu.py
> @@ -105,7 +105,7 @@ def __init__(self, lcore_list: list[int] | list[str] |
> list[LogicalCore] | str)
>
> # the input lcores may not be sorted
> self._lcore_list.sort()
> - self._lcore_str =
> f'{",".join(self._get_consecutive_lcores_range(self._lcore_list))}'
> + self._lcore_str =
> f"{','.join(self._get_consecutive_lcores_range(self._lcore_list))}"
>
> @property
> def lcore_list(self) -> list[int]:
> diff --git a/dts/framework/testbed_model/traffic_generator/scapy.py
> b/dts/framework/testbed_model/traffic_generator/scapy.py
> index c6e9006205..62853a34e4 100644
> --- a/dts/framework/testbed_model/traffic_generator/scapy.py
> +++ b/dts/framework/testbed_model/traffic_generator/scapy.py
> @@ -314,9 +314,9 @@ def __init__(self, tg_node: Node, config:
> ScapyTrafficGeneratorConfig, **kwargs:
> kwargs: Additional keyword arguments. Supported arguments
> correspond to the parameters
> of :meth:`PythonShell.__init__` in this case.
> """
> - assert (
> - tg_node.config.os == OS.linux
> - ), "Linux is the only supported OS for scapy traffic generation"
> + assert tg_node.config.os == OS.linux, (
> + "Linux is the only supported OS for scapy traffic generation"
> + )
>
> super().__init__(tg_node=tg_node, config=config, **kwargs)
>
> diff --git a/dts/framework/testbed_model/traffic_generator/trex.py
> b/dts/framework/testbed_model/traffic_generator/trex.py
> index 2abfbfc5ab..d53791b0a6 100644
> --- a/dts/framework/testbed_model/traffic_generator/trex.py
> +++ b/dts/framework/testbed_model/traffic_generator/trex.py
> @@ -95,9 +95,9 @@ def __init__(self, tg_node: Node, config:
> TrexTrafficGeneratorConfig) -> None:
> tg_node: TG node the TRex instance is operating on.
> config: Traffic generator config provided for TRex instance.
> """
> - assert (
> - tg_node.config.os == OS.linux
> - ), "Linux is the only supported OS for trex traffic generation"
> + assert tg_node.config.os == OS.linux, (
> + "Linux is the only supported OS for trex traffic generation"
> + )
>
> super().__init__(tg_node=tg_node, config=config)
> self._tg_node_config = tg_node.config
> diff --git a/dts/framework/utils.py b/dts/framework/utils.py
> index 9917ffbfaa..5753c1b7fe 100644
> --- a/dts/framework/utils.py
> +++ b/dts/framework/utils.py
> @@ -21,7 +21,7 @@
> import tarfile
> from enum import Enum, Flag
> from pathlib import Path
> -from typing import Any, Callable
> +from typing import Any, Callable, Literal, TypeAlias, cast
>
> from scapy.layers.inet import IP, TCP, UDP, Ether
> from scapy.packet import Packet
> @@ -39,6 +39,8 @@
> rf"(?:(sut|tg)\.)?({REGEX_FOR_IDENTIFIER})" # right side
> )
>
> +Tar_modes: TypeAlias = Literal["w:gz", "w:bz2", "w:xz", "w:tar"]
> +
>
> def expand_range(range_str: str) -> list[int]:
> """Process `range_str` into a list of integers.
> @@ -154,7 +156,11 @@ def extension(self) -> str:
> For other compression formats, the extension will be in the format
> 'tar.{compression format}'.
> """
> - return f"{self.value}" if self == self.none else
> f"{type(self).none.value}.{self.value}"
> + return (
> + f"{self.value}"
> + if self == self.none
> + else f"{TarCompressionFormat.none.value}.{self.value}"
> + )
>
>
> def convert_to_list_of_string(value: Any | list[Any]) -> list[str]:
> @@ -207,7 +213,8 @@ def filter_func(tarinfo: tarfile.TarInfo) ->
> tarfile.TarInfo | None:
> return None
>
> target_tarball_path =
> dir_path.with_suffix(f".{compress_format.extension}")
> - with tarfile.open(target_tarball_path, f"w:{compress_format.value}")
> as tar:
> + tarball_mode = cast(Tar_modes, f"w:{compress_format.value}")
> + with tarfile.open(target_tarball_path, tarball_mode) as tar:
> tar.add(dir_path, arcname=dir_path.name,
> filter=create_filter_function(exclude))
>
> return target_tarball_path
> diff --git a/dts/poetry.lock b/dts/poetry.lock
> index 0ad5d32b85..eda7cc2fec 100644
> --- a/dts/poetry.lock
> +++ b/dts/poetry.lock
> @@ -1,4 +1,4 @@
> -# This file is automatically @generated by Poetry 1.8.3 and should not be
> changed by hand.
> +# This file is automatically @generated by Poetry 2.3.2 and should not be
> changed by hand.
>
> [[package]]
> name = "aenum"
> @@ -6,6 +6,7 @@ version = "3.1.15"
> description = "Advanced Enumerations (compatible with Python's stdlib
> Enum), NamedTuples, and NamedConstants"
> optional = false
> python-versions = "*"
> +groups = ["main"]
> files = [
> {file = "aenum-3.1.15-py2-none-any.whl", hash =
> "sha256:27b1710b9d084de6e2e695dab78fe9f269de924b51ae2850170ee7e1ca6288a5"},
> {file = "aenum-3.1.15-py3-none-any.whl", hash =
> "sha256:e0dfaeea4c2bd362144b87377e2c61d91958c5ed0b4daf89cb6f45ae23af6288"},
> @@ -18,17 +19,62 @@ version = "0.7.0"
> description = "Reusable constraint types to use with typing.Annotated"
> optional = false
> python-versions = ">=3.8"
> +groups = ["main"]
> files = [
> {file = "annotated_types-0.7.0-py3-none-any.whl", hash =
> "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"},
> {file = "annotated_types-0.7.0.tar.gz", hash =
> "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"},
> ]
>
> +[[package]]
> +name = "ast-serialize"
> +version = "0.5.0"
> +description = "Python bindings for mypy AST serialization"
> +optional = false
> +python-versions = ">=3.7"
> +groups = ["dev"]
> +files = [
> + {file = "ast_serialize-0.5.0-cp314-cp314t-macosx_10_12_x86_64.whl",
> hash =
> "sha256:8f5c14f169eb0972c0c21bada5358b23d6047c76583b005234f865b11f1fa00a"},
> + {file = "ast_serialize-0.5.0-cp314-cp314t-macosx_11_0_arm64.whl",
> hash =
> "sha256:7d1a2de9de5be04652f0ed60738356ef94f66db37924a9499fffe98dc491aa0b"},
> + {file =
> "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
> hash =
> "sha256:be5173fb66f9b49026d9d5a2ff0fc7c7009077107c0eb285b2d60fdf1fe10bd1"},
> + {file =
> "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",
> hash =
> "sha256:f8015cd071ac1339924ee2b8098c93e00e155f30a16f40ec9816fcf84f4753f6"},
> + {file =
> "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",
> hash =
> "sha256:5499e8797edff2a9186aa313ed382c6b422e798e9332d9953badcee6e69a88f2"},
> + {file =
> "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl",
> hash =
> "sha256:6848f2a093fb5548751a9a09bff8fcd229e2bbeb0e3331f391b6ae6d26cd9903"},
> + {file =
> "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
> hash =
> "sha256:832d4c998e0b091fd60a6d6bceee535483c4d490de9ba85003af835225719261"},
> + {file =
> "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash =
> "sha256:16db7c62ec0b8efe1d7afd283a388d8f74f2605d56032e5a37747d2de8dba027"},
> + {file =
> "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl",
> hash =
> "sha256:baf5eb061eb5bccade4128ad42da33787d72f6013809cd1b590376ece8b3c937"},
> + {file = "ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl",
> hash =
> "sha256:104e4a35bd7c124173c41760ef9aaea17ddb3f86c65cb643671d59afbe3ee94c"},
> + {file = "ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_armv7l.whl",
> hash =
> "sha256:36be371028fc1675acb38a331bde160dbab7ff907fdf00b67eb6911aa106951b"},
> + {file = "ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_i686.whl",
> hash =
> "sha256:061ee58bdb52341c8201a6df41182a977736bae3b7ded87ca7176ca25a8a47ab"},
> + {file = "ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl",
> hash =
> "sha256:b15219e9cdc9f53f6f4cb51c009203507228226148c05c5e8fe451c28b435eb3"},
> + {file = "ast_serialize-0.5.0-cp314-cp314t-win32.whl", hash =
> "sha256:842d1c004bb466c7df036f95fabef789570541922b10976b12f5592a69cf0b38"},
> + {file = "ast_serialize-0.5.0-cp314-cp314t-win_amd64.whl", hash =
> "sha256:b0c06d760909b095cc466356dfccd05a1c7233a6ca191c020dca2c6a6f16c24c"},
> + {file = "ast_serialize-0.5.0-cp314-cp314t-win_arm64.whl", hash =
> "sha256:787baedb0262cc49e8ce37cc15c00ae818e46a165a3b36f5e21ed174998104cb"},
> + {file = "ast_serialize-0.5.0-cp39-abi3-macosx_10_12_x86_64.whl", hash
> =
> "sha256:0668aa9459cfa8c9c49ddd2163ebcf43088ba045ef7492af6fe22e0098303101"},
> + {file = "ast_serialize-0.5.0-cp39-abi3-macosx_11_0_arm64.whl", hash =
> "sha256:bf683d6363edf2b39eed6b6d4fe22d34b6203867a67e27134d9e2a2680c4bc4a"},
> + {file =
> "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
> hash =
> "sha256:9cc22cf0c9be65e71cf88fda130af60d61eb4a79370ad4cfe7900d48a4aa2211"},
> + {file =
> "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",
> hash =
> "sha256:f66173891548c9f2726bf27957b41cabce12fa679dc6da505ddbde4d4b3b31cf"},
> + {file =
> "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",
> hash =
> "sha256:e42d729ef2be96a14efbad355093284739e3670ece3e534f82cc8832790911d9"},
> + {file =
> "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl",
> hash =
> "sha256:b725026bafa801dbd7310eb13a75f0a2e370e7e51b2cb225f9d21fcfadf919ee"},
> + {file =
> "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
> hash =
> "sha256:b54f60c1d78767a53b67eaa663f0dfac3afe606aa07f1301572f588b73d64809"},
> + {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_31_riscv64.whl",
> hash =
> "sha256:27d51654fc240a1e87e742d353d98eb45b75f62f129086b3596ab53df2ac2a43"},
> + {file =
> "ast_serialize-0.5.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl",
> hash =
> "sha256:2782c36237c46dd1674542f2109740ea5ea485a169bf1431939ada0434e17934"},
> + {file = "ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_aarch64.whl",
> hash =
> "sha256:1943db345233cc7194a470f13afa9c59772c0b123dea0c9414c4d4ca54369759"},
> + {file = "ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_armv7l.whl",
> hash =
> "sha256:df1c00022cbbcb064bfaa505aa9c9295362443ce5dacb459d1331d3da353f887"},
> + {file = "ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_i686.whl", hash
> =
> "sha256:cae65289fc456fde04af979a2be09302ef5d8ab92ef23e596d6746dc267ada27"},
> + {file = "ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_x86_64.whl",
> hash =
> "sha256:239a4c354e8d676e9d94631d1d4a64edc6b266f86ff3a5a80aedd344f342c01d"},
> + {file = "ast_serialize-0.5.0-cp39-abi3-win32.whl", hash =
> "sha256:143a4ef63285a075871908fda3672dc21864b83a8ec3ee12304aa3e4c5387b9a"},
> + {file = "ast_serialize-0.5.0-cp39-abi3-win_amd64.whl", hash =
> "sha256:cf25572c526add400f26a4750dc6ce0c3bb93fc1f75e7ae0cad4ce4f2cd5c590"},
> + {file = "ast_serialize-0.5.0-cp39-abi3-win_arm64.whl", hash =
> "sha256:92a31c9c20d25a076edaeec76b128a3535d74a24f340b9a8a7e96c9b86dc9642"},
> + {file = "ast_serialize-0.5.0.tar.gz", hash =
> "sha256:5880091bfe6f4f986f22866375c2e884843e7a0b6343ae41aeea659613d879b6"},
> +]
> +
> [[package]]
> name = "bcrypt"
> version = "4.2.1"
> description = "Modern password hashing for your software and your servers"
> optional = false
> python-versions = ">=3.7"
> +groups = ["main"]
> files = [
> {file = "bcrypt-4.2.1-cp37-abi3-macosx_10_12_universal2.whl", hash =
> "sha256:1340411a0894b7d3ef562fb233e4b6ed58add185228650942bdc885362f32c17"},
> {file =
> "bcrypt-4.2.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
> hash =
> "sha256:b1ee315739bc8387aa36ff127afc99120ee452924e0df517a8f3e4c0187a0f5f"},
> @@ -67,6 +113,7 @@ version = "1.17.1"
> description = "Foreign Function Interface for Python calling C code."
> optional = false
> python-versions = ">=3.8"
> +groups = ["main", "dev"]
> files = [
> {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash =
> "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"},
> {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash =
> "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"},
> @@ -136,6 +183,7 @@ files = [
> {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash =
> "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"},
> {file = "cffi-1.17.1.tar.gz", hash =
> "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"},
> ]
> +markers = {dev = "platform_python_implementation != \"PyPy\""}
>
> [package.dependencies]
> pycparser = "*"
> @@ -146,6 +194,7 @@ version = "44.0.0"
> description = "cryptography is a package which provides cryptographic
> recipes and primitives to Python developers."
> optional = false
> python-versions = "!=3.9.0,!=3.9.1,>=3.7"
> +groups = ["main", "dev"]
> files = [
> {file = "cryptography-44.0.0-cp37-abi3-macosx_10_9_universal2.whl",
> hash =
> "sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123"},
> {file =
> "cryptography-44.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
> hash =
> "sha256:b15492a11f9e1b62ba9d73c210e2416724633167de94607ec6069ef724fad092"},
> @@ -180,10 +229,10 @@ files = [
> cffi = {version = ">=1.12", markers = "platform_python_implementation !=
> \"PyPy\""}
>
> [package.extras]
> -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0)"]
> +docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0) ; python_version
> >= \"3.8\""]
> docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)",
> "sphinxcontrib-spelling (>=7.3.1)"]
> -nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2)"]
> -pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.4)", "ruff
> (>=0.3.6)"]
> +nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2) ; python_version >=
> \"3.8\""]
> +pep8test = ["check-sdist ; python_version >= \"3.8\"", "click (>=8.0.1)",
> "mypy (>=1.4)", "ruff (>=0.3.6)"]
> sdist = ["build (>=1.0.0)"]
> ssh = ["bcrypt (>=3.1.5)"]
> test = ["certifi (>=2024)", "cryptography-vectors (==44.0.0)", "pretend
> (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov
> (>=2.10.1)", "pytest-xdist (>=3.5.0)"]
> @@ -195,6 +244,7 @@ version = "5.1.1"
> description = "Decorators for Humans"
> optional = false
> python-versions = ">=3.5"
> +groups = ["main"]
> files = [
> {file = "decorator-5.1.1-py3-none-any.whl", hash =
> "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"},
> {file = "decorator-5.1.1.tar.gz", hash =
> "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"},
> @@ -206,6 +256,7 @@ version = "1.2.18"
> description = "Python @deprecated decorator to deprecate old python
> classes, functions or methods."
> optional = false
> python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7"
> +groups = ["main"]
> files = [
> {file = "Deprecated-1.2.18-py2.py3-none-any.whl", hash =
> "sha256:bd5011788200372a32418f888e326a09ff80d0214bd961147cfed01b5c018eec"},
> {file = "deprecated-1.2.18.tar.gz", hash =
> "sha256:422b6f6d859da6f2ef57857761bfb392480502a64c3028ca9bbe86085d72115d"},
> @@ -215,7 +266,7 @@ files = [
> wrapt = ">=1.10,<2"
>
> [package.extras]
> -dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "setuptools", "tox"]
> +dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "setuptools ;
> python_version >= \"3.12\"", "tox"]
>
> [[package]]
> name = "fabric"
> @@ -223,6 +274,7 @@ version = "3.2.2"
> description = "High level SSH command execution"
> optional = false
> python-versions = "*"
> +groups = ["main"]
> files = [
> {file = "fabric-3.2.2-py3-none-any.whl", hash =
> "sha256:91c47c0be68b14936c88b34da8a1f55e5710fd28397dac5d4ff2e21558113a6f"},
> {file = "fabric-3.2.2.tar.gz", hash =
> "sha256:8783ca42e3b0076f08b26901aac6b9d9b1f19c410074e7accfab902c184ff4a3"},
> @@ -243,56 +295,177 @@ version = "2.2.0"
> description = "Pythonic task execution"
> optional = false
> python-versions = ">=3.6"
> +groups = ["main"]
> files = [
> {file = "invoke-2.2.0-py3-none-any.whl", hash =
> "sha256:6ea924cc53d4f78e3d98bc436b08069a03077e6f85ad1ddaa8a116d7dad15820"},
> {file = "invoke-2.2.0.tar.gz", hash =
> "sha256:ee6cbb101af1a859c7fe84f2a264c059020b0cb7fe3535f9424300ab568f6bd5"},
> ]
>
> +[[package]]
> +name = "librt"
> +version = "0.11.0"
> +description = "Mypyc runtime library"
> +optional = false
> +python-versions = ">=3.9"
> +groups = ["dev"]
> +markers = "platform_python_implementation != \"PyPy\""
> +files = [
> + {file = "librt-0.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash =
> "sha256:6e94ebfcfa2d5e9926d6c3b9aa4617ffc42a845b4321fb84021b872358c82a0f"},
> + {file = "librt-0.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash =
> "sha256:ae627397a2f351560440d872d6f7c8dbb4072e57868e7b2fc5b8b430fe489d45"},
> + {file =
> "librt-0.11.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:dc329359321b67d24efdf4bc69012b0597001649544db662c001db5a0184794c"},
> + {file =
> "librt-0.11.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl",
> hash =
> "sha256:7e82e642ab0f7608ce2fe53d76ca2280a9ee33a1b06556142c7c6fe80a86fc33"},
> + {file =
> "librt-0.11.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:88145c15c67731d54283d135b03244028c750cc9edc334a96a4f5950ebdb2884"},
> + {file =
> "librt-0.11.0-cp310-cp310-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl",
> hash =
> "sha256:9d36a51b3d93320b686588e27123f4995804dbf1bce81df78c02fc3c6eea9280"},
> + {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash =
> "sha256:d00f3ac06a2a8b246327f11e186a53a100a4d5c7ed52346367e5ec751d51586c"},
> + {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_i686.whl", hash =
> "sha256:461bbceede621f1ffb8839755f8663e886087ee7af16294cab7fb4d782c62eeb"},
> + {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash =
> "sha256:0cad8a4d6a8ff03c9b76f9414caccd78e7cfbc8a2e12fa334d8e1d9932753783"},
> + {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash =
> "sha256:f37aa505b3cf60701562eddb32df74b12a9e380c207fd8b06dd157a943ac7ea0"},
> + {file = "librt-0.11.0-cp310-cp310-win32.whl", hash =
> "sha256:94663a21534637f0e787ec2a2a756022df6e5b7b2335a5cdd7d8e33d68a2af89"},
> + {file = "librt-0.11.0-cp310-cp310-win_amd64.whl", hash =
> "sha256:dec7db73758c2b54953fd8b7fe348c45188fe26b39ee18446196edd08453a5d4"},
> + {file = "librt-0.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash =
> "sha256:93d95bd45b7d58343d8b90d904450a545144eec19a002511163426f8ab1fae29"},
> + {file = "librt-0.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash =
> "sha256:4ee278c769a713638cdacd4c0436d72156e75df3ebc0166ab2b9dc43acc386c9"},
> + {file =
> "librt-0.11.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:f230cb1cbc9faaa616f9a678f530ebcf186e414b6bcbd88b960e4ba1b92428d5"},
> + {file =
> "librt-0.11.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl",
> hash =
> "sha256:5d63c855d86938d9de93e265c9bd8c705b51ec494de5738340ee93767a686e4b"},
> + {file =
> "librt-0.11.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:993f028be9e96a08d31df3479ac80d99be374d17f3b78e4796b3fd3c913d4e89"},
> + {file =
> "librt-0.11.0-cp311-cp311-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl",
> hash =
> "sha256:258d73a0aa66a055e65b2e4d1b8cdb23b9d132c5bb915d9547d804fcaed116cc"},
> + {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash =
> "sha256:0827efe7854718f04aaddf6496e96960a956e676fe1d0f04eb41511fd8ad06d5"},
> + {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_i686.whl", hash =
> "sha256:7753e57d6e12d019c0d8786f1c09c709f4c3fcc57c3887b24e36e6c06ec938b7"},
> + {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash =
> "sha256:11bd19822431cc21af9f27374e7ae2e58103c7d98bda823536a6c47f6bb2bb3d"},
> + {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash =
> "sha256:22bdf239b219d3993761a148ffa134b19e52e9989c84f845d5d7b71d70a17412"},
> + {file = "librt-0.11.0-cp311-cp311-win32.whl", hash =
> "sha256:46c60b61e308eb535fbd6fa622b1ee1bb2815691c1ad9c98bf7b84952ec3bc8d"},
> + {file = "librt-0.11.0-cp311-cp311-win_amd64.whl", hash =
> "sha256:902e546ff044f579ff1c953ff5fce97b636fe9e3943996b2177710c6ef076f73"},
> + {file = "librt-0.11.0-cp311-cp311-win_arm64.whl", hash =
> "sha256:65ac3bc20f78aa0ee5ae84baa68917f89fef4af63e941084dd019a0d0e749f0c"},
> + {file = "librt-0.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash =
> "sha256:b87504f1690a23b9a2cca841191a04f83895d4fc2dd04df91d82b1a04ca2ad46"},
> + {file = "librt-0.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash =
> "sha256:40071fc5fe0ce8daa6de616702314a01e1250711682b0523d6ab8d4525910cb3"},
> + {file =
> "librt-0.11.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:137e79445c896a0ea7b265f52d23954e05b64222ee1af69e2cb34219067cbb67"},
> + {file =
> "librt-0.11.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl",
> hash =
> "sha256:cca6644054e78746d8d4ef238681f9c34ff8b584fe6b988ecebb8db3b15e622a"},
> + {file =
> "librt-0.11.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:d5b0eea49f5562861ee8d757a32ef7d559c1d35be2aaaa1ec28941d74c9ffc8a"},
> + {file =
> "librt-0.11.0-cp312-cp312-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl",
> hash =
> "sha256:0d1029d7e1ae1a7e647ed6fb5df8c4ce2dffefb7a9f5fd1376a4554d96dac09f"},
> + {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash =
> "sha256:bc3ce6b33c5828d9e80592011a5c584cb2ce86edbc4088405f70da47dc1d1b3b"},
> + {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_i686.whl", hash =
> "sha256:936c5995f3514a42111f20099397d8177c79b4d7e70961e396c6f5a0a3566766"},
> + {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash =
> "sha256:9bc0ca6ad9381cbe8e4aa6e5726e4c80c78115a6e9723c599ed1d73e092bc49d"},
> + {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash =
> "sha256:070aa8c26c0a74774317a72df8851facc7f0f012a5b406557ac56992d92e1ec8"},
> + {file = "librt-0.11.0-cp312-cp312-win32.whl", hash =
> "sha256:6bf14feb84b05ae945277395451998c89c54d0def4070eb5c08de544930b245a"},
> + {file = "librt-0.11.0-cp312-cp312-win_amd64.whl", hash =
> "sha256:75672f0bc524ede266287d532d7923dbce94c7514ad07627bac3d0c6d92cc4d9"},
> + {file = "librt-0.11.0-cp312-cp312-win_arm64.whl", hash =
> "sha256:2f10cf143e4a9bb0f4f5af568a00df94a2d69ef41c2579584454bb0fe5cc642c"},
> + {file = "librt-0.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash =
> "sha256:78dc31f7fdfe9c9d0eb0e8f42d139db230e826415bbcabd9f0e9faaaee909894"},
> + {file = "librt-0.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash =
> "sha256:fa475675db22290c3158e1d42326d0f5a65f04f44a0e68c3630a25b53560fb9c"},
> + {file =
> "librt-0.11.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:621db29691044bdeda22e789e482e1b0f3a985d90e3426c9c6d17606416205ea"},
> + {file =
> "librt-0.11.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl",
> hash =
> "sha256:a9010e2ed5b3a9e158c5fd966b3ab7e834bb3d3aacc8f66c91dd4b57a3799230"},
> + {file =
> "librt-0.11.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:7c39513d8b7477a2e1ed8c43fc21c524e8d5a0f8d4e8b7b074dbdbe7820a08e2"},
> + {file =
> "librt-0.11.0-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl",
> hash =
> "sha256:7aef3cf1d5af86e770ab04bfd993dfc4ae8b8c17f66fb77dd4a7d50de7bbb1a3"},
> + {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash =
> "sha256:557183ddc36babe46b27dd60facbd5adb4492181a5be887587d57cda6e092f21"},
> + {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_i686.whl", hash =
> "sha256:83d3e1f72bd42f6c5c0b7daec530c3f829bd02db42c70b8ddf0c2d90a2459930"},
> + {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash =
> "sha256:4ce1f21fbe589bc1afd7872dece84fb0e1144f794a288e58a10d2c54a55c43be"},
> + {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash =
> "sha256:970b09f7044ea2b64c9da42fd3d335666518cfd1c6e8a182c95da73d0214b41e"},
> + {file = "librt-0.11.0-cp313-cp313-win32.whl", hash =
> "sha256:78fddc31cd4d3caa897ad5d31f856b1faadc9474021ad6cb182b9018793e254e"},
> + {file = "librt-0.11.0-cp313-cp313-win_amd64.whl", hash =
> "sha256:8ca8aa88751a775870b764e93bad5135385f563cb8dcee399abf034ea4d3cb47"},
> + {file = "librt-0.11.0-cp313-cp313-win_arm64.whl", hash =
> "sha256:96f044bb325fd9cf1a723015638c219e9143f0dfbc0ca54c565df2b7fc748b44"},
> + {file = "librt-0.11.0-cp314-cp314-macosx_10_13_x86_64.whl", hash =
> "sha256:4a017a95e5837dc15a8c5661d60e05daa96b90908b1aa6b7acdf443cd25c8ebd"},
> + {file = "librt-0.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash =
> "sha256:b1ecbd9819deccc39b7542bf4d2a740d8a620694d39989e58661d3763458f8d4"},
> + {file =
> "librt-0.11.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:7da327dacd7be8f8ec36547373550744a3cc0e536d54665cd83f8bcd961200e8"},
> + {file =
> "librt-0.11.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl",
> hash =
> "sha256:0dc56b1f8d06e60db362cc3fdae206681817f86ce4725d34511473487f12a34b"},
> + {file =
> "librt-0.11.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:05fb8fb2ab90e21c8d12ea240d744ad514da9baf381ebfa70d91d20d21713175"},
> + {file =
> "librt-0.11.0-cp314-cp314-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl",
> hash =
> "sha256:cae74872be221df4374d10fec61f93ed1513b9546ea84f2c0bf73ab3e9bd0b03"},
> + {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash =
> "sha256:32bcc918c0148eb7e3d57385125bac7e5f9e4359d05f07448b09f6f778c2f31c"},
> + {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_i686.whl", hash =
> "sha256:f9743fc99135d5f78d2454435615f6dec0473ca507c26ce9d92b10b562a280d3"},
> + {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash =
> "sha256:5ba067f4aadae8fda802d91d2124c90c42195ff32d9161d3549e6d05cfe26f96"},
> + {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash =
> "sha256:de3bf945454d032f9e390b85c4072e0a0570bf825421c8be0e71209fa65e1abe"},
> + {file = "librt-0.11.0-cp314-cp314-win32.whl", hash =
> "sha256:d2277a05f6dcb9fd13db9566aac4fabd68c3ea1ea46ee5567d4eef8efa495a2f"},
> + {file = "librt-0.11.0-cp314-cp314-win_amd64.whl", hash =
> "sha256:ab73e8db5e3f564d812c1f5c3a175930a5f9bc96ccb5e3b22a34d7858b401cf7"},
> + {file = "librt-0.11.0-cp314-cp314-win_arm64.whl", hash =
> "sha256:aea3caa317752e3a466fa8af45d91ee0ea8c7fdd96e42b0a8dd9b76a7931eba1"},
> + {file = "librt-0.11.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash =
> "sha256:d1b36540d7aaf9b9101b3a6f376c8d8e9f7a9aec93ed05918f2c69d493ffef72"},
> + {file = "librt-0.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash =
> "sha256:efbb343ab2ce3540f4ecbe6315d677ed70f37cd9a72b1e58066c918ca83acbaa"},
> + {file =
> "librt-0.11.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:aa0dd688aab3f7914d3e6e5e3554978e0383312fb8e771d84be008a35b9ee548"},
> + {file =
> "librt-0.11.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl",
> hash =
> "sha256:f5fb36b8c6c63fdcbb1d526d94c0d1331610d43f4118cc1beb4efef4f3faacb2"},
> + {file =
> "librt-0.11.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:4a9a237d13addb93715b6fee74023d5ee3469b53fce527626c0e088aa585805f"},
> + {file =
> "librt-0.11.0-cp314-cp314t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl",
> hash =
> "sha256:5ddd17bd87b2c56ddd60e546a7984a2e64c4e8eab92fb4cf3830a48ad5469d51"},
> + {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash =
> "sha256:bd43992b4473d42f12ff9e68326079f0696d9d4e6000e8f39a0238d482ba6ee2"},
> + {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_i686.whl", hash =
> "sha256:f8e3e8056dd674e279741485e2e512d6e9a751c7455809d0114e6ebf8d781085"},
> + {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash =
> "sha256:c1f708d8ae9c56cf38a903c44297243d2ec83fd82b396b977e0144a3e76217e3"},
> + {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash =
> "sha256:0add982e0e7b9fc14cf4b33789d5f13f66581889b88c2f58099f6ce8f92617bd"},
> + {file = "librt-0.11.0-cp314-cp314t-win32.whl", hash =
> "sha256:2b481d846ac894c4e8403c5fd0e87c5d11d6499e404b474602508a224ff531c8"},
> + {file = "librt-0.11.0-cp314-cp314t-win_amd64.whl", hash =
> "sha256:28edb433edde181112a908c78907af28f964eabc15f4dd16c9d66c834302677c"},
> + {file = "librt-0.11.0-cp314-cp314t-win_arm64.whl", hash =
> "sha256:dee008f20b542e3cd162ba338a7f9ec0f6d23d395f66fe8aeeec3c9d067ea253"},
> + {file = "librt-0.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash =
> "sha256:6bd72d903911d995ab666dbd1871f8b1e80925a699af8063fbf50053329fb05f"},
> + {file = "librt-0.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash =
> "sha256:0ef69ac715f3cd8e5cd252cb2aebfa72c015492aacc339d5d7bf8fef3c62c677"},
> + {file =
> "librt-0.11.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:624a40c4a4ad7773315c287276cd024509b2c66ff5904f504bfc08d2c70293ab"},
> + {file =
> "librt-0.11.0-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl",
> hash =
> "sha256:41dc19fe150b69716c8ece4f76773a9e8813fe3e35e032a58b4d46423fb8d7c0"},
> + {file =
> "librt-0.11.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:4e8bd98ea9c47ae90b319a087ab28dac493f1ffbc1ecd1f28fcdbf3b7e1108d1"},
> + {file =
> "librt-0.11.0-cp39-cp39-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl",
> hash =
> "sha256:84308fc49423ce6475d1c5d1985cd69a8ca9f0325fc7d5f81bb690a3f3625d4e"},
> + {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash =
> "sha256:ff0fbaf5f44a21beeb0110f2ab64f45135a9536a834b79c0d1ef018f2786bbfa"},
> + {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_i686.whl", hash =
> "sha256:9c028a9442a18e266955d364ce42259136e79a7ba14d773e0d778d5f70cd56f1"},
> + {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_riscv64.whl", hash =
> "sha256:9f1692105a02bcf853f355032a5fdc5494358ef83d8fd22d16de375c85cec3f5"},
> + {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash =
> "sha256:7a80a71e1fda83cc752a9141e87aae7fef279538597564d670e9ce513f286192"},
> + {file = "librt-0.11.0-cp39-cp39-win32.whl", hash =
> "sha256:140695816ddf3c86eb972981a26f35efd871c44b0c3aed44c8cd01749386617f"},
> + {file = "librt-0.11.0-cp39-cp39-win_amd64.whl", hash =
> "sha256:92f7ff819c197fc30473190a12c2856f325ac90aabfccbeb2072d28cc2e234e3"},
> + {file = "librt-0.11.0.tar.gz", hash =
> "sha256:075dc3ef4458a278e0195cbf6ac9d38808d9b906c5a6c7f7f79c3888276a3fb1"},
> +]
> +
> [[package]]
> name = "mypy"
> -version = "1.13.0"
> +version = "2.1.0"
> description = "Optional static typing for Python"
> optional = false
> -python-versions = ">=3.8"
> +python-versions = ">=3.10"
> +groups = ["dev"]
> files = [
> - {file = "mypy-1.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash =
> "sha256:6607e0f1dd1fb7f0aca14d936d13fd19eba5e17e1cd2a14f808fa5f8f6d8f60a"},
> - {file = "mypy-1.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash =
> "sha256:8a21be69bd26fa81b1f80a61ee7ab05b076c674d9b18fb56239d72e21d9f4c80"},
> - {file =
> "mypy-1.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:7b2353a44d2179846a096e25691d54d59904559f4232519d420d64da6828a3a7"},
> - {file = "mypy-1.13.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash =
> "sha256:0730d1c6a2739d4511dc4253f8274cdd140c55c32dfb0a4cf8b7a43f40abfa6f"},
> - {file = "mypy-1.13.0-cp310-cp310-win_amd64.whl", hash =
> "sha256:c5fc54dbb712ff5e5a0fca797e6e0aa25726c7e72c6a5850cfd2adbc1eb0a372"},
> - {file = "mypy-1.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash =
> "sha256:581665e6f3a8a9078f28d5502f4c334c0c8d802ef55ea0e7276a6e409bc0d82d"},
> - {file = "mypy-1.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash =
> "sha256:3ddb5b9bf82e05cc9a627e84707b528e5c7caaa1c55c69e175abb15a761cec2d"},
> - {file =
> "mypy-1.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:20c7ee0bc0d5a9595c46f38beb04201f2620065a93755704e141fcac9f59db2b"},
> - {file = "mypy-1.13.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash =
> "sha256:3790ded76f0b34bc9c8ba4def8f919dd6a46db0f5a6610fb994fe8efdd447f73"},
> - {file = "mypy-1.13.0-cp311-cp311-win_amd64.whl", hash =
> "sha256:51f869f4b6b538229c1d1bcc1dd7d119817206e2bc54e8e374b3dfa202defcca"},
> - {file = "mypy-1.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash =
> "sha256:5c7051a3461ae84dfb5dd15eff5094640c61c5f22257c8b766794e6dd85e72d5"},
> - {file = "mypy-1.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash =
> "sha256:39bb21c69a5d6342f4ce526e4584bc5c197fd20a60d14a8624d8743fffb9472e"},
> - {file =
> "mypy-1.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:164f28cb9d6367439031f4c81e84d3ccaa1e19232d9d05d37cb0bd880d3f93c2"},
> - {file = "mypy-1.13.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash =
> "sha256:a4c1bfcdbce96ff5d96fc9b08e3831acb30dc44ab02671eca5953eadad07d6d0"},
> - {file = "mypy-1.13.0-cp312-cp312-win_amd64.whl", hash =
> "sha256:a0affb3a79a256b4183ba09811e3577c5163ed06685e4d4b46429a271ba174d2"},
> - {file = "mypy-1.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash =
> "sha256:a7b44178c9760ce1a43f544e595d35ed61ac2c3de306599fa59b38a6048e1aa7"},
> - {file = "mypy-1.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash =
> "sha256:5d5092efb8516d08440e36626f0153b5006d4088c1d663d88bf79625af3d1d62"},
> - {file =
> "mypy-1.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:de2904956dac40ced10931ac967ae63c5089bd498542194b436eb097a9f77bc8"},
> - {file = "mypy-1.13.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash =
> "sha256:7bfd8836970d33c2105562650656b6846149374dc8ed77d98424b40b09340ba7"},
> - {file = "mypy-1.13.0-cp313-cp313-win_amd64.whl", hash =
> "sha256:9f73dba9ec77acb86457a8fc04b5239822df0c14a082564737833d2963677dbc"},
> - {file = "mypy-1.13.0-cp38-cp38-macosx_10_9_x86_64.whl", hash =
> "sha256:100fac22ce82925f676a734af0db922ecfea991e1d7ec0ceb1e115ebe501301a"},
> - {file = "mypy-1.13.0-cp38-cp38-macosx_11_0_arm64.whl", hash =
> "sha256:7bcb0bb7f42a978bb323a7c88f1081d1b5dee77ca86f4100735a6f541299d8fb"},
> - {file =
> "mypy-1.13.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:bde31fc887c213e223bbfc34328070996061b0833b0a4cfec53745ed61f3519b"},
> - {file = "mypy-1.13.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash =
> "sha256:07de989f89786f62b937851295ed62e51774722e5444a27cecca993fc3f9cd74"},
> - {file = "mypy-1.13.0-cp38-cp38-win_amd64.whl", hash =
> "sha256:4bde84334fbe19bad704b3f5b78c4abd35ff1026f8ba72b29de70dda0916beb6"},
> - {file = "mypy-1.13.0-cp39-cp39-macosx_10_9_x86_64.whl", hash =
> "sha256:0246bcb1b5de7f08f2826451abd947bf656945209b140d16ed317f65a17dc7dc"},
> - {file = "mypy-1.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash =
> "sha256:7f5b7deae912cf8b77e990b9280f170381fdfbddf61b4ef80927edd813163732"},
> - {file =
> "mypy-1.13.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:7029881ec6ffb8bc233a4fa364736789582c738217b133f1b55967115288a2bc"},
> - {file = "mypy-1.13.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash =
> "sha256:3e38b980e5681f28f033f3be86b099a247b13c491f14bb8b1e1e134d23bb599d"},
> - {file = "mypy-1.13.0-cp39-cp39-win_amd64.whl", hash =
> "sha256:a6789be98a2017c912ae6ccb77ea553bbaf13d27605d2ca20a76dfbced631b24"},
> - {file = "mypy-1.13.0-py3-none-any.whl", hash =
> "sha256:9c250883f9fd81d212e0952c92dbfcc96fc237f4b7c92f56ac81fd48460b3e5a"},
> - {file = "mypy-1.13.0.tar.gz", hash =
> "sha256:0291a61b6fbf3e6673e3405cfcc0e7650bebc7939659fdca2702958038bd835e"},
> + {file = "mypy-2.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash =
> "sha256:11a6beb180257a805961aea9ec591bbd0bd17f1e18d35b8456d57aee5bedfedc"},
> + {file = "mypy-2.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash =
> "sha256:8ef78c1d306bbf9a8a12f526c44902c9c28dffd6c52c52bf6a72641ce18d3849"},
> + {file =
> "mypy-2.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:c209a90853081ff01d01ee895cafe10f7db1474e0d95beaeef0f6c1db9119bbd"},
> + {file =
> "mypy-2.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:47cebf61abde7c088a4e27718a8b13a81655686b2e9c251f5c0915a802248166"},
> + {file = "mypy-2.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash =
> "sha256:d57a90ae5e872138a425ec328edbc9b235d1934c4377881a33ec05b341acc9a8"},
> + {file = "mypy-2.1.0-cp310-cp310-win_amd64.whl", hash =
> "sha256:aea7f7a8a55b459c34275fc468ada6ca7c173a5e43a68f5dbe588a563d8a06b8"},
> + {file = "mypy-2.1.0-cp310-cp310-win_arm64.whl", hash =
> "sha256:c989640253f0d76843e9c6c1bbf4bd48c5e85ada61bde4beb37cb3eca035685e"},
> + {file = "mypy-2.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash =
> "sha256:a683016b16fe2f572dc04c72be7ee0504ac1605a265d0200f5cea695fb788f41"},
> + {file = "mypy-2.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash =
> "sha256:1a293c534adb55271fef24a26da04b855540a8c13cc07bc5917b9fd2c394f2ca"},
> + {file =
> "mypy-2.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:7406f4d048e71e576f5356d317e5b0a9e666dfd966bd99f9d14ca06e1a341538"},
> + {file =
> "mypy-2.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:e0210d626fc8b31ccc90233754c7bc90e1f43205e85d96387f7db1285b55c398"},
> + {file = "mypy-2.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash =
> "sha256:3712c20deed54e814eaaa825603bada8ea1c390670a397c95b98405347acc563"},
> + {file = "mypy-2.1.0-cp311-cp311-win_amd64.whl", hash =
> "sha256:fcaa0e479066e31f7cceb6a3bea39cb22b2ff51a6b2f24f193d19179ba17c389"},
> + {file = "mypy-2.1.0-cp311-cp311-win_arm64.whl", hash =
> "sha256:0b1a5260c95aa443083f9ed3592662941951bca3d4ca224a5dc517c38b7cf666"},
> + {file = "mypy-2.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash =
> "sha256:244358bf1c0da7722230bce60683d52e8e9fd030554926f15b747a84efb5b3af"},
> + {file = "mypy-2.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash =
> "sha256:4ec7c57657493c7a75534df2751c8ae2cda383c16ecc55d2106c54476b1b16f6"},
> + {file =
> "mypy-2.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:d8161b6ff4392410023224f0969d17db93e1e154bc3e4ba62598e720723ae211"},
> + {file =
> "mypy-2.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:bf03e12003084a67395184d3eb8cbd6a489dc3655b5664b28c210a9e2403ab0b"},
> + {file = "mypy-2.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash =
> "sha256:20509760fd791c51579d573153407d226385ec1f8bcce55d730b354f3336bc22"},
> + {file = "mypy-2.1.0-cp312-cp312-win_amd64.whl", hash =
> "sha256:6753d0c1fdd6b1a23b9e4f283ce80b2153b724adcb2653b20b85a8a28ac6436b"},
> + {file = "mypy-2.1.0-cp312-cp312-win_arm64.whl", hash =
> "sha256:98ebb6589bb3b6d0c6f0c459d53ca55b8091fbc13d277c4041c885392e8195e8"},
> + {file = "mypy-2.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash =
> "sha256:35aac3bb114e03888f535d5eb51b8bafbb3266586b599da1940f9b1be3ec5bd5"},
> + {file = "mypy-2.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash =
> "sha256:8de55a8c861f2a49331f807be98d90caeceeef520bde13d43a160207f8af613e"},
> + {file =
> "mypy-2.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:5fdf2941a07434af755837d9880f7d7d25f1dacb1af9dcd4b9b66f2220a3024e"},
> + {file =
> "mypy-2.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:e195b817c13f02352a9c124301f9f30f078405444679b6753c1b96b6eed37285"},
> + {file = "mypy-2.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash =
> "sha256:5431d42af987ebd92ba2f71d45c85ed41d8e6ca9f5fd209a69f68f707d2469e5"},
> + {file = "mypy-2.1.0-cp313-cp313-win_amd64.whl", hash =
> "sha256:767fe8c66dc3e01e19e1737d4c38ebefead16125e1b8e58ad421903b376f5c65"},
> + {file = "mypy-2.1.0-cp313-cp313-win_arm64.whl", hash =
> "sha256:ecfe70d43775ab99562ab128ce49854a362044c9f894961f68f898c23cb7429d"},
> + {file = "mypy-2.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash =
> "sha256:7354c5a7f69d9345c3d6e69921d57088eea3ddeeb6b20d34c1b3855b02c36ec2"},
> + {file = "mypy-2.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash =
> "sha256:49890d4f76ac9e06ec117f9e09f3174da70a620a0c300953d8595c926e80947f"},
> + {file =
> "mypy-2.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:761be68e023ef5d94678772396a8af1220030f80837a3afd8d0aef3b419666f4"},
> + {file =
> "mypy-2.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:c90345fc182dc363b891350457ec69c35140858538f38b4540845afcc32b1aef"},
> + {file = "mypy-2.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash =
> "sha256:b84802e7b5a6daf1f5e15bc9fcd7ddae77be13981ffab037f1c67bb84d67d135"},
> + {file = "mypy-2.1.0-cp314-cp314-win_amd64.whl", hash =
> "sha256:022c771234936ceac541ebaf836fe9e2abeb3f5e09aff21588fe543ff006fe21"},
> + {file = "mypy-2.1.0-cp314-cp314-win_arm64.whl", hash =
> "sha256:498207db725cec88829a6a5c2fc771205fd043719ef98bc49aba8fb9fc4e6d57"},
> + {file = "mypy-2.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash =
> "sha256:7d5e5cad0efeba72b93cd17490cc0d69c5ac9ca132994fe3fb0314808aeeb83e"},
> + {file = "mypy-2.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash =
> "sha256:ff715050c127d724fd260a2e666e7747fdd83511c0c47d449d98238970aef780"},
> + {file =
> "mypy-2.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:82208da9e09414d520e912d3e462d454854bed0810b71540bb016dcbca7308fd"},
> + {file =
> "mypy-2.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:e79ebc1b904b84f0310dff7469655a9c36c7a68bddb37bdd42b67a332df61d08"},
> + {file = "mypy-2.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash =
> "sha256:e583edc957cfb0deb142079162ae826f58449b116c1d442f2d91c69d9fced081"},
> + {file = "mypy-2.1.0-cp314-cp314t-win_amd64.whl", hash =
> "sha256:b33b6cd332695bba180d55e717a79d3038e479a2c49cc5eb3d53603409b9a5d7"},
> + {file = "mypy-2.1.0-cp314-cp314t-win_arm64.whl", hash =
> "sha256:4f910fe825376a7b66ef7ca8c98e5a149e8cd64c19ae71d84047a74ee060d4e6"},
> + {file = "mypy-2.1.0-py3-none-any.whl", hash =
> "sha256:a663814603a5c563fb87a4f96fb473eeb30d1f5a4885afcf44f9db000a366289"},
> + {file = "mypy-2.1.0.tar.gz", hash =
> "sha256:81e76ad12c2d804512e9b13240d1588316531bfba07558286078bfbce9613633"},
> ]
>
> [package.dependencies]
> -mypy-extensions = ">=1.0.0"
> +ast-serialize = ">=0.3.0,<1.0.0"
> +librt = {version = ">=0.11.0", markers = "platform_python_implementation
> != \"PyPy\""}
> +mypy_extensions = ">=1.0.0"
> +pathspec = ">=1.0.0"
> tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
> -typing-extensions = ">=4.6.0"
> +typing_extensions = [
> + {version = ">=4.6.0", markers = "python_version < \"3.15\""},
> + {version = ">=4.14.0", markers = "python_version >= \"3.15\""},
> +]
>
> [package.extras]
> dmypy = ["psutil (>=4.0)"]
> @@ -307,6 +480,7 @@ version = "1.0.0"
> description = "Type system extensions for programs checked with the mypy
> type checker."
> optional = false
> python-versions = ">=3.5"
> +groups = ["dev"]
> files = [
> {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash =
> "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
> {file = "mypy_extensions-1.0.0.tar.gz", hash =
> "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
> @@ -318,6 +492,7 @@ version = "3.5.0"
> description = "SSH2 protocol library"
> optional = false
> python-versions = ">=3.6"
> +groups = ["main"]
> files = [
> {file = "paramiko-3.5.0-py3-none-any.whl", hash =
> "sha256:1fedf06b085359051cd7d0d270cebe19e755a8a921cc2ddbfa647fb0cd7d68f9"},
> {file = "paramiko-3.5.0.tar.gz", hash =
> "sha256:ad11e540da4f55cedda52931f1a3f812a8238a7af7f62a60de538cd80bb28124"},
> @@ -329,20 +504,39 @@ cryptography = ">=3.3"
> pynacl = ">=1.5"
>
> [package.extras]
> -all = ["gssapi (>=1.4.1)", "invoke (>=2.0)", "pyasn1 (>=0.1.7)", "pywin32
> (>=2.1.8)"]
> -gssapi = ["gssapi (>=1.4.1)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8)"]
> +all = ["gssapi (>=1.4.1) ; platform_system != \"Windows\"", "invoke
> (>=2.0)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8) ; platform_system ==
> \"Windows\""]
> +gssapi = ["gssapi (>=1.4.1) ; platform_system != \"Windows\"", "pyasn1
> (>=0.1.7)", "pywin32 (>=2.1.8) ; platform_system == \"Windows\""]
> invoke = ["invoke (>=2.0)"]
>
> +[[package]]
> +name = "pathspec"
> +version = "1.1.1"
> +description = "Utility library for gitignore style pattern matching of
> file paths."
> +optional = false
> +python-versions = ">=3.9"
> +groups = ["dev"]
> +files = [
> + {file = "pathspec-1.1.1-py3-none-any.whl", hash =
> "sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189"},
> + {file = "pathspec-1.1.1.tar.gz", hash =
> "sha256:17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a"},
> +]
> +
> +[package.extras]
> +hyperscan = ["hyperscan (>=0.7)"]
> +optional = ["typing-extensions (>=4)"]
> +re2 = ["google-re2 (>=1.1)"]
> +
> [[package]]
> name = "pycparser"
> version = "2.22"
> description = "C parser in Python"
> optional = false
> python-versions = ">=3.8"
> +groups = ["main", "dev"]
> files = [
> {file = "pycparser-2.22-py3-none-any.whl", hash =
> "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"},
> {file = "pycparser-2.22.tar.gz", hash =
> "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"},
> ]
> +markers = {dev = "platform_python_implementation != \"PyPy\""}
>
> [[package]]
> name = "pydantic"
> @@ -350,6 +544,7 @@ version = "2.10.3"
> description = "Data validation using Python type hints"
> optional = false
> python-versions = ">=3.8"
> +groups = ["main"]
> files = [
> {file = "pydantic-2.10.3-py3-none-any.whl", hash =
> "sha256:be04d85bbc7b65651c5f8e6b9976ed9c6f41782a55524cef079a34a0bb82144d"},
> {file = "pydantic-2.10.3.tar.gz", hash =
> "sha256:cb5ac360ce894ceacd69c403187900a02c4b20b693a9dd1d643e1effab9eadf9"},
> @@ -362,7 +557,7 @@ typing-extensions = ">=4.12.2"
>
> [package.extras]
> email = ["email-validator (>=2.0.0)"]
> -timezone = ["tzdata"]
> +timezone = ["tzdata ; python_version >= \"3.9\" and platform_system ==
> \"Windows\""]
>
> [[package]]
> name = "pydantic-core"
> @@ -370,6 +565,7 @@ version = "2.27.1"
> description = "Core functionality for Pydantic validation and
> serialization"
> optional = false
> python-versions = ">=3.8"
> +groups = ["main"]
> files = [
> {file = "pydantic_core-2.27.1-cp310-cp310-macosx_10_12_x86_64.whl",
> hash =
> "sha256:71a5e35c75c021aaf400ac048dacc855f000bdfed91614b4a726f7432f1f3d6a"},
> {file = "pydantic_core-2.27.1-cp310-cp310-macosx_11_0_arm64.whl",
> hash =
> "sha256:f82d068a2d6ecfc6e054726080af69a6764a10015467d7d7b9f66d6ed5afa23b"},
> @@ -482,6 +678,7 @@ version = "1.5.0"
> description = "Python binding to the Networking and Cryptography (NaCl)
> library"
> optional = false
> python-versions = ">=3.6"
> +groups = ["main"]
> files = [
> {file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash =
> "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"},
> {file =
> "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl",
> hash =
> "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"},
> @@ -508,6 +705,7 @@ version = "6.0.2"
> description = "YAML parser and emitter for Python"
> optional = false
> python-versions = ">=3.8"
> +groups = ["main"]
> files = [
> {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash =
> "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"},
> {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash =
> "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"},
> @@ -566,29 +764,30 @@ files = [
>
> [[package]]
> name = "ruff"
> -version = "0.8.2"
> +version = "0.15.16"
> description = "An extremely fast Python linter and code formatter,
> written in Rust."
> optional = false
> python-versions = ">=3.7"
> +groups = ["dev"]
> files = [
> - {file = "ruff-0.8.2-py3-none-linux_armv6l.whl", hash =
> "sha256:c49ab4da37e7c457105aadfd2725e24305ff9bc908487a9bf8d548c6dad8bb3d"},
> - {file = "ruff-0.8.2-py3-none-macosx_10_12_x86_64.whl", hash =
> "sha256:ec016beb69ac16be416c435828be702ee694c0d722505f9c1f35e1b9c0cc1bf5"},
> - {file = "ruff-0.8.2-py3-none-macosx_11_0_arm64.whl", hash =
> "sha256:f05cdf8d050b30e2ba55c9b09330b51f9f97d36d4673213679b965d25a785f3c"},
> - {file =
> "ruff-0.8.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
> hash =
> "sha256:60f578c11feb1d3d257b2fb043ddb47501ab4816e7e221fbb0077f0d5d4e7b6f"},
> - {file =
> "ruff-0.8.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash
> =
> "sha256:cbd5cf9b0ae8f30eebc7b360171bd50f59ab29d39f06a670b3e4501a36ba5897"},
> - {file =
> "ruff-0.8.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash =
> "sha256:b402ddee3d777683de60ff76da801fa7e5e8a71038f57ee53e903afbcefdaa58"},
> - {file =
> "ruff-0.8.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash =
> "sha256:705832cd7d85605cb7858d8a13d75993c8f3ef1397b0831289109e953d833d29"},
> - {file =
> "ruff-0.8.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",
> hash =
> "sha256:32096b41aaf7a5cc095fa45b4167b890e4c8d3fd217603f3634c92a541de7248"},
> - {file =
> "ruff-0.8.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash =
> "sha256:e769083da9439508833cfc7c23e351e1809e67f47c50248250ce1ac52c21fb93"},
> - {file =
> "ruff-0.8.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash
> =
> "sha256:5fe716592ae8a376c2673fdfc1f5c0c193a6d0411f90a496863c99cd9e2ae25d"},
> - {file = "ruff-0.8.2-py3-none-musllinux_1_2_aarch64.whl", hash =
> "sha256:81c148825277e737493242b44c5388a300584d73d5774defa9245aaef55448b0"},
> - {file = "ruff-0.8.2-py3-none-musllinux_1_2_armv7l.whl", hash =
> "sha256:d261d7850c8367704874847d95febc698a950bf061c9475d4a8b7689adc4f7fa"},
> - {file = "ruff-0.8.2-py3-none-musllinux_1_2_i686.whl", hash =
> "sha256:1ca4e3a87496dc07d2427b7dd7ffa88a1e597c28dad65ae6433ecb9f2e4f022f"},
> - {file = "ruff-0.8.2-py3-none-musllinux_1_2_x86_64.whl", hash =
> "sha256:729850feed82ef2440aa27946ab39c18cb4a8889c1128a6d589ffa028ddcfc22"},
> - {file = "ruff-0.8.2-py3-none-win32.whl", hash =
> "sha256:ac42caaa0411d6a7d9594363294416e0e48fc1279e1b0e948391695db2b3d5b1"},
> - {file = "ruff-0.8.2-py3-none-win_amd64.whl", hash =
> "sha256:2aae99ec70abf43372612a838d97bfe77d45146254568d94926e8ed5bbb409ea"},
> - {file = "ruff-0.8.2-py3-none-win_arm64.whl", hash =
> "sha256:fb88e2a506b70cfbc2de6fae6681c4f944f7dd5f2fe87233a7233d888bad73e8"},
> - {file = "ruff-0.8.2.tar.gz", hash =
> "sha256:b84f4f414dda8ac7f75075c1fa0b905ac0ff25361f42e6d5da681a465e0f78e5"},
> + {file = "ruff-0.15.16-py3-none-linux_armv6l.whl", hash =
> "sha256:6ac3c0b3969cc6cf6b158c4e2f8f682acb58e7d700d8a44b65ecdc72d66ab0b2"},
> + {file = "ruff-0.15.16-py3-none-macosx_10_12_x86_64.whl", hash =
> "sha256:197c207ed75ffba54a0dec23db4aa939a27a3053073e085e0042433cbdc58e4a"},
> + {file = "ruff-0.15.16-py3-none-macosx_11_0_arm64.whl", hash =
> "sha256:3a39fec45ab316cc23e7558f23fea4a70403ddb5648ea9a4a3854a16973d0071"},
> + {file =
> "ruff-0.15.16-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
> hash =
> "sha256:ba93191d79003116b95128c9d306e045200fdbd0bccb782b110f3cd1d4abc5cf"},
> + {file =
> "ruff-0.15.16-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",
> hash =
> "sha256:c6ee4b90520630120ef032aa5cc10db483852dff950e78b1d717e2993a61ac8d"},
> + {file =
> "ruff-0.15.16-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash =
> "sha256:4e4215bc938bc3c8215c1472c1aa437e310fee20cd427335fec9d7e609563628"},
> + {file =
> "ruff-0.15.16-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",
> hash =
> "sha256:7c8d26be963b090f10e29abc8b3e74a2a321f6fa34e02424e30b5af89350ecbb"},
> + {file =
> "ruff-0.15.16-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash
> =
> "sha256:f198cf4123602a2280ed46c307bcbafe41758d6fee5b456b6b6058ca1514b3b4"},
> + {file =
> "ruff-0.15.16-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
> hash =
> "sha256:bb27515fa6240fb586ae82b901a59e67d24acff86f2190b433dc542fe0435aeb"},
> + {file = "ruff-0.15.16-py3-none-manylinux_2_31_riscv64.whl", hash =
> "sha256:a267c46ba1593fc26b8eecbea050b39d40c0b6bb7781ee11c90a02cd10032951"},
> + {file = "ruff-0.15.16-py3-none-musllinux_1_2_aarch64.whl", hash =
> "sha256:528c68f39a91498a8d50e91ff5985df3d105782bab49cc378e73ac26bff083e8"},
> + {file = "ruff-0.15.16-py3-none-musllinux_1_2_armv7l.whl", hash =
> "sha256:7ed55c58950df60589a9a7a5d2f8fa5f54ebd287163be805adfe6ee95a9de123"},
> + {file = "ruff-0.15.16-py3-none-musllinux_1_2_i686.whl", hash =
> "sha256:d482feaf51512b50f9790ceb417a56a61dd1e9d9bf967662b9ed27c01b34f53a"},
> + {file = "ruff-0.15.16-py3-none-musllinux_1_2_x86_64.whl", hash =
> "sha256:1e15bc8c94513dae2a40cc9ef07c94fdd4ecc9e29dabebeebe170f952322c9e3"},
> + {file = "ruff-0.15.16-py3-none-win32.whl", hash =
> "sha256:580378f7bd4aa25f72e74aa54948a9622f142b1e509521dd10902e886681cc1e"},
> + {file = "ruff-0.15.16-py3-none-win_amd64.whl", hash =
> "sha256:408256017284eddf98fff77b29aa4fb30f586042d535b2d9befc6512f400aaec"},
> + {file = "ruff-0.15.16-py3-none-win_arm64.whl", hash =
> "sha256:8cd61783afb39638a7133ef0d2dfb1e91277593962f81b5a8423eb0b888a6121"},
> + {file = "ruff-0.15.16.tar.gz", hash =
> "sha256:d05e78d38c78caf020b03789e25106c93017db5a0cb6e2819885018c61343b78"},
> ]
>
> [[package]]
> @@ -597,6 +796,7 @@ version = "2.6.1"
> description = "Scapy: interactive packet manipulation tool"
> optional = false
> python-versions = "<4,>=3.7"
> +groups = ["main"]
> files = [
> {file = "scapy-2.6.1-py3-none-any.whl", hash =
> "sha256:88a998572049b511a1f3e44f4aa7c62dd39c6ea2aa1bb58434f503956641789d"},
> {file = "scapy-2.6.1.tar.gz", hash =
> "sha256:7600d7e2383c853e5c3a6e05d37e17643beebf2b3e10d7914dffcc3bc3c6e6c5"},
> @@ -613,6 +813,7 @@ version = "0.10.2"
> description = "Python Library for Tom's Obvious, Minimal Language"
> optional = false
> python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
> +groups = ["dev"]
> files = [
> {file = "toml-0.10.2-py2.py3-none-any.whl", hash =
> "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
> {file = "toml-0.10.2.tar.gz", hash =
> "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
> @@ -624,6 +825,8 @@ version = "2.2.1"
> description = "A lil' TOML parser"
> optional = false
> python-versions = ">=3.8"
> +groups = ["dev"]
> +markers = "python_version == \"3.10\""
> files = [
> {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash =
> "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"},
> {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash =
> "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"},
> @@ -665,6 +868,7 @@ version = "2.0.0.10"
> description = "Typing stubs for invoke"
> optional = false
> python-versions = ">=3.7"
> +groups = ["dev"]
> files = [
> {file = "types-invoke-2.0.0.10.tar.gz", hash =
> "sha256:a54d7ecdc19e0c22cd2786ef2e64c2631715c78eba8a1bf40b511d0608f33a88"},
> {file = "types_invoke-2.0.0.10-py3-none-any.whl", hash =
> "sha256:2404e4279601fa96e14ef68321fd10a660a828677aabdcaeef6a5189778084ef"},
> @@ -672,13 +876,14 @@ files = [
>
> [[package]]
> name = "types-paramiko"
> -version = "3.5.0.20240928"
> +version = "4.0.0.20260518"
> description = "Typing stubs for paramiko"
> optional = false
> -python-versions = ">=3.8"
> +python-versions = ">=3.10"
> +groups = ["dev"]
> files = [
> - {file = "types-paramiko-3.5.0.20240928.tar.gz", hash =
> "sha256:79dd9b2ee510b76a3b60d8ac1f3f348c45fcecf01347ca79e14db726bbfc442d"},
> - {file = "types_paramiko-3.5.0.20240928-py3-none-any.whl", hash =
> "sha256:cda0aff4905fe8efe4b5448331a80e943d42a796bd4beb77a3eed3485bc96a85"},
> + {file = "types_paramiko-4.0.0.20260518-py3-none-any.whl", hash =
> "sha256:0ffaf1a6eb796833a49653cba4c7be13af51c8269d75234972d6239763dda270"},
> + {file = "types_paramiko-4.0.0.20260518.tar.gz", hash =
> "sha256:286f6830945cba63797eedf375ed87138d93198121253afe66c5d6dbcf91318d"},
> ]
>
> [package.dependencies]
> @@ -686,13 +891,14 @@ cryptography = ">=37.0.0"
>
> [[package]]
> name = "types-pyyaml"
> -version = "6.0.12.20240917"
> +version = "6.0.12.20260518"
> description = "Typing stubs for PyYAML"
> optional = false
> -python-versions = ">=3.8"
> +python-versions = ">=3.10"
> +groups = ["dev"]
> files = [
> - {file = "types-PyYAML-6.0.12.20240917.tar.gz", hash =
> "sha256:d1405a86f9576682234ef83bcb4e6fff7c9305c8b1fbad5e0bcd4f7dbdc9c587"},
> - {file = "types_PyYAML-6.0.12.20240917-py3-none-any.whl", hash =
> "sha256:392b267f1c0fe6022952462bf5d6523f31e37f6cea49b14cee7ad634b6301570"},
> + {file = "types_pyyaml-6.0.12.20260518-py3-none-any.whl", hash =
> "sha256:d2150f75a231c9fe9c7463bd29487d93e60bac90400287351384bc2284eba7cd"},
> + {file = "types_pyyaml-6.0.12.20260518.tar.gz", hash =
> "sha256:d917f83fb38462550338c1297faedd860b3ec83912b96b1e3d73255f7473e466"},
> ]
>
> [[package]]
> @@ -701,17 +907,33 @@ version = "4.12.2"
> description = "Backported and Experimental Type Hints for Python 3.8+"
> optional = false
> python-versions = ">=3.8"
> +groups = ["main", "dev"]
> +markers = "python_version < \"3.15\""
> files = [
> {file = "typing_extensions-4.12.2-py3-none-any.whl", hash =
> "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
> {file = "typing_extensions-4.12.2.tar.gz", hash =
> "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
> ]
>
> +[[package]]
> +name = "typing-extensions"
> +version = "4.15.0"
> +description = "Backported and Experimental Type Hints for Python 3.9+"
> +optional = false
> +python-versions = ">=3.9"
> +groups = ["main", "dev"]
> +markers = "python_version >= \"3.15\""
> +files = [
> + {file = "typing_extensions-4.15.0-py3-none-any.whl", hash =
> "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"},
> + {file = "typing_extensions-4.15.0.tar.gz", hash =
> "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"},
> +]
> +
> [[package]]
> name = "wrapt"
> version = "1.17.2"
> description = "Module for decorators, wrappers and monkey patching."
> optional = false
> python-versions = ">=3.8"
> +groups = ["main"]
> files = [
> {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash =
> "sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984"},
> {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash =
> "sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22"},
> @@ -795,6 +1017,6 @@ files = [
> ]
>
> [metadata]
> -lock-version = "2.0"
> +lock-version = "2.1"
> python-versions = "^3.10"
> -content-hash =
> "aa6dff54827602c89ee125019291965de50d7a471ca48add889ea23aa5fd9b2f"
> +content-hash =
> "1ca3cdf5bf98c528845b5e22169322db8912fe437988635f4ebea088b2079463"
> diff --git a/dts/pyproject.toml b/dts/pyproject.toml
> index 8b061c3cee..b639af65b6 100644
> --- a/dts/pyproject.toml
> +++ b/dts/pyproject.toml
> @@ -28,12 +28,12 @@ aenum = "^3.1.15"
> pydantic = "^2.9.2"
>
> [tool.poetry.group.dev.dependencies]
> -mypy = "^1.13.0"
> +mypy = "^2.1.0"
> toml = "^0.10.2"
> -ruff = "^0.8.1"
> -types-paramiko = "^3.5.0.20240928"
> +ruff = "^0.15.16"
> +types-paramiko = "^4.0.0.20260518"
> types-invoke = "^2.0.0.10"
> -types-pyyaml = "^6.0.12.20240917"
> +types-pyyaml = "^6.0.12.20260518"
>
> [build-system]
> requires = ["poetry-core>=1.0.0"]
> diff --git a/dts/tests/TestSuite_cryptodev_throughput.py
> b/dts/tests/TestSuite_cryptodev_throughput.py
> index af0a5680ab..2fc0d8779a 100644
> --- a/dts/tests/TestSuite_cryptodev_throughput.py
> +++ b/dts/tests/TestSuite_cryptodev_throughput.py
> @@ -101,12 +101,12 @@ def _print_stats(self, test_vals: list[dict[str, int
> | float | str]]) -> None:
> print(f"{'Throughput Results'.center(border_len)}\n{'=' *
> border_len}")
> for k, v in test_vals[0].items():
> print(f"|{k.title():<{element_len}}", end="")
> - print(f"|\n{'='*border_len}")
> + print(f"|\n{'=' * border_len}")
>
> for test_val in test_vals:
> for k, v in test_val.items():
> print(f"|{v:<{element_len}}", end="")
> - print(f"|\n{'='*border_len}")
> + print(f"|\n{'=' * border_len}")
>
> def _verify_throughput(
> self,
> diff --git a/dts/tests/TestSuite_port_control.py
> b/dts/tests/TestSuite_port_control.py
> index 6be47838d0..b51fdc2959 100644
> --- a/dts/tests/TestSuite_port_control.py
> +++ b/dts/tests/TestSuite_port_control.py
> @@ -44,8 +44,7 @@ def _send_packets_and_verify(self) -> None:
> recv_pakts = [
> p
> for p in recv_pakts
> - if
> - (
> + if (
> # Remove padding from the bytes.
> hasattr(p, "load") and
> p.load.decode("utf-8").replace("\x00", "") == payload
> )
> diff --git a/dts/tests/TestSuite_single_core_forward_perf.py
> b/dts/tests/TestSuite_single_core_forward_perf.py
> index 1e7ab7b036..acdf8ae2f6 100644
> --- a/dts/tests/TestSuite_single_core_forward_perf.py
> +++ b/dts/tests/TestSuite_single_core_forward_perf.py
> @@ -144,7 +144,7 @@ def single_core_forward_perf(self) -> None:
> for params in self.test_parameters:
> verify(
> params["pass"] is True,
> - f"""Packets forwarded is less than {(1
> -self.delta_tolerance)*100}%
> + f"""Packets forwarded is less than {(1 -
> self.delta_tolerance) * 100}%
> of the expected baseline.
> Measured MPPS = {params["measured_mpps"]}
> Expected MPPS = {params["expected_mpps"]}""",
> --
> 2.54.0
>
>
[-- Attachment #2: Type: text/html, Size: 96411 bytes --]
^ permalink raw reply
* Re: [PATCH v5 02/24] bpf: add format instruction function
From: Stephen Hemminger @ 2026-06-24 17:09 UTC (permalink / raw)
To: Marat Khalili; +Cc: Konstantin Ananyev, dev
In-Reply-To: <20260624121800.40635-3-marat.khalili@huawei.com>
On Wed, 24 Jun 2026 13:17:35 +0100
Marat Khalili <marat.khalili@huawei.com> wrote:
> BPF library already contains BPF instruction formatting functions, but
> they could only be used via `rte_bpf_dump` to dump result into file. Add
> new function `rte_bpf_format` to format instruction in various way
> (hexadecimal, disassembly) into a user-provided buffer, as well as a
> service function `rte_bpf_insn_is_wide` to detect wide instructions.
>
> Signed-off-by: Marat Khalili <marat.khalili@huawei.com>
> Acked-by: Konstantin Ananyev <konstantin.ananyev@huawei.com>
> ---
Is this format similar to what tcpdump -d and objdump produce?
^ permalink raw reply
* [PATCH v5 0/9] bpf: JIT related bug fixes
From: Stephen Hemminger @ 2026-06-24 17:54 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger
In-Reply-To: <20260608203322.1116296-1-stephen@networkplumber.org>
While implementing JIT for packet capture ran into several issues:
1. x86 JIT had a pre-existing bug which would crash.
2. The arm64 JIT was missing the packet-access instructions, found
previously [1].
3. Shift counts were not masked to the operand width as RFC 9669
requires: undefined behavior in the interpreter and an encoding
failure in the arm64 JIT.
4. Tests related to JIT were not being run or were missing coverage.
Fixed all of these. Patches are ordered with the most urgent fix (the
x86 crash) first, each fix followed by the test that exercises it. The
arm64 packet-load support is kept ahead of the "check JIT was generated"
patch so the series bisects cleanly on arm64.
The arm64 epilogue branch fix (patch 6) was originally posted by
Christophe Fontaine [1]; that series stalled, so it is carried here with
his authorship.
Changes since v4:
- address Marat's review of the large-shift test: it now checks the
RFC 9669 masked result instead of a sentinel, which surfaced two more
bugs fixed in this version
- mask shift counts to the operand width: the interpreter shifted by
the raw count (UB, trips UBSan; patch 3) and the arm64 JIT overflowed
the UBFM/SBFM immediate (patch 4)
- reorder so the arm64 BPF_ABS/BPF_IND support precedes the "check JIT
was generated" patch, keeping the suite bisectable on arm64
[1] https://inbox.dpdk.org/dev/20260319114500.9757-2-cfontain@redhat.com/
Christophe Fontaine (1):
bpf/arm64: fix offset type to allow a negative jump
Stephen Hemminger (8):
bpf/x86: fix JIT encoding of fixed-width immediates
test/bpf: add JSET test with small immediate
bpf: mask shift count in interpreter per RFC 9669
bpf/arm64: mask shift count per RFC 9669
test/bpf: add test for large shift
bpf/arm64: add BPF_ABS/BPF_IND packet load support
test/bpf: check that JIT was generated
test/bpf: check that bpf_convert can be JIT'd
app/test/test_bpf.c | 320 +++++++++++++++++++++++++++++++---------
lib/bpf/bpf_exec.c | 31 ++--
lib/bpf/bpf_jit_arm64.c | 165 ++++++++++++++++++++-
lib/bpf/bpf_jit_x86.c | 6 +-
lib/bpf/meson.build | 2 +
5 files changed, 436 insertions(+), 88 deletions(-)
--
2.53.0
^ permalink raw reply
* [PATCH v5 1/9] bpf/x86: fix JIT encoding of fixed-width immediates
From: Stephen Hemminger @ 2026-06-24 17:55 UTC (permalink / raw)
To: dev
Cc: Stephen Hemminger, stable, Marat Khalili, Konstantin Ananyev,
Ferruh Yigit
In-Reply-To: <20260624175815.673064-1-stephen@networkplumber.org>
Several places in the x86 JIT size an immediate with imm_size(), which
returns 1 or 4 bytes depending on the value. That is wrong for opcodes
whose immediate width is fixed by the encoding, and it breaks in both
directions.
TEST (0xF7 /0, used for BPF_JSET) has no imm8 form; the immediate is
always 32 bits. For a small mask such as BPF_JSET | BPF_K #0x1,
imm_size() returns 1, so the JIT emits a 1-byte immediate. The CPU
still consumes 4, swallowing 3 bytes of the following Jcc. The
instruction stream desyncs and the program crashes.
ROR and the shifts (0xC1 group) have the opposite problem: their
immediate is always imm8. For a count >= 128, imm_size() returns 4 and
the JIT emits 3 stray bytes, again desyncing the stream.
Size each immediate by its encoding: 32 bits for TEST, 8 bits for ROR
and the shifts.
Bugzilla ID: 1959
Fixes: cc752e43e079 ("bpf: add JIT compilation for x86_64 ISA")
Cc: stable@dpdk.org
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Marat Khalili <marat.khalili@huawei.com>
---
lib/bpf/bpf_jit_x86.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/lib/bpf/bpf_jit_x86.c b/lib/bpf/bpf_jit_x86.c
index 54eb279643..912d3f69bc 100644
--- a/lib/bpf/bpf_jit_x86.c
+++ b/lib/bpf/bpf_jit_x86.c
@@ -300,7 +300,7 @@ emit_ror_imm(struct bpf_jit_state *st, uint32_t dreg, uint32_t imm)
emit_rex(st, BPF_ALU, 0, dreg);
emit_bytes(st, &ops, sizeof(ops));
emit_modregrm(st, MOD_DIRECT, mods, dreg);
- emit_imm(st, imm, imm_size(imm));
+ emit_imm(st, imm, sizeof(uint8_t));
}
/*
@@ -441,7 +441,7 @@ emit_shift_imm(struct bpf_jit_state *st, uint32_t op, uint32_t dreg,
uint32_t imm)
{
emit_shift(st, op, dreg);
- emit_imm(st, imm, imm_size(imm));
+ emit_imm(st, imm, sizeof(uint8_t));
}
/*
@@ -921,7 +921,7 @@ emit_tst_imm(struct bpf_jit_state *st, uint32_t op, uint32_t dreg, uint32_t imm)
emit_rex(st, op, 0, dreg);
emit_bytes(st, &ops, sizeof(ops));
emit_modregrm(st, MOD_DIRECT, mods, dreg);
- emit_imm(st, imm, imm_size(imm));
+ emit_imm(st, imm, sizeof(int32_t));
}
static void
--
2.53.0
^ permalink raw reply related
* [PATCH v5 2/9] test/bpf: add JSET test with small immediate
From: Stephen Hemminger @ 2026-06-24 17:55 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, Marat Khalili, Konstantin Ananyev
In-Reply-To: <20260624175815.673064-1-stephen@networkplumber.org>
The existing jump test only used a 32-bit JSET mask,
so the broken imm8 encoding of TEST in the x86 JIT was never exercised.
Add a case with a byte-sized mask;
run_test() runs it through the interpreter and the JIT.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Marat Khalili <marat.khalili@huawei.com>
---
app/test/test_bpf.c | 82 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 82 insertions(+)
diff --git a/app/test/test_bpf.c b/app/test/test_bpf.c
index 6b07e72295..232e9e2a98 100644
--- a/app/test/test_bpf.c
+++ b/app/test/test_bpf.c
@@ -3158,7 +3158,89 @@ static const struct ebpf_insn test_ld_mbuf3_prog[] = {
};
/* all bpf test cases */
+/*
+ * JSET with a byte-sized mask: exercises the imm8 path of the TEST
+ * encoding in the x86 JIT (a 32-bit mask takes a different path).
+ */
+static const struct ebpf_insn test_jset1_prog[] = {
+ {
+ .code = (BPF_ALU | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 0,
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_B),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_offset, u8),
+ },
+ /* bit 0 is set in the input: branch is taken */
+ {
+ .code = (BPF_JMP | BPF_JSET | BPF_K),
+ .dst_reg = EBPF_REG_2,
+ .imm = 0x1,
+ .off = 1,
+ },
+ {
+ .code = (BPF_JMP | BPF_JA),
+ .off = 1,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_OR | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 0x1,
+ },
+ /* bit 1 is clear in the input: branch is not taken */
+ {
+ .code = (BPF_JMP | BPF_JSET | BPF_K),
+ .dst_reg = EBPF_REG_2,
+ .imm = 0x2,
+ .off = 1,
+ },
+ {
+ .code = (BPF_JMP | BPF_JA),
+ .off = 1,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_OR | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 0x2,
+ },
+ {
+ .code = (BPF_JMP | EBPF_EXIT),
+ },
+};
+
+static void
+test_jset1_prepare(void *arg)
+{
+ struct dummy_offset *df = arg;
+
+ memset(df, 0, sizeof(*df));
+ df->u8 = 0x1; /* bit 0 set, bit 1 clear */
+}
+
+static int
+test_jset1_check(uint64_t rc, const void *arg)
+{
+ return cmp_res(__func__, 0x1, rc, arg, arg, 0);
+}
+
static const struct bpf_test tests[] = {
+ {
+ .name = "test_jset1",
+ .arg_sz = sizeof(struct dummy_offset),
+ .prm = {
+ .ins = test_jset1_prog,
+ .nb_ins = RTE_DIM(test_jset1_prog),
+ .prog_arg = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(struct dummy_offset),
+ },
+ },
+ .prepare = test_jset1_prepare,
+ .check_result = test_jset1_check,
+ },
{
.name = "test_store1",
.arg_sz = sizeof(struct dummy_offset),
--
2.53.0
^ permalink raw reply related
* [PATCH v5 3/9] bpf: mask shift count in interpreter per RFC 9669
From: Stephen Hemminger @ 2026-06-24 17:55 UTC (permalink / raw)
To: dev
Cc: Stephen Hemminger, stable, Konstantin Ananyev, Marat Khalili,
Ferruh Yigit
In-Reply-To: <20260624175815.673064-1-stephen@networkplumber.org>
The interpreter shifted by the raw immediate or register value, which
is undefined behavior in C when the count is >= the operand width and
trips UBSan. RFC 9669 masks shift counts (0x3f for 64-bit, 0x1f for
32-bit); mask the count in the LSH/RSH/ARSH cases.
Fixes: 94972f35a02e ("bpf: add BPF loading and execution framework")
Cc: stable@dpdk.org
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
lib/bpf/bpf_exec.c | 31 +++++++++++++++++++++----------
1 file changed, 21 insertions(+), 10 deletions(-)
diff --git a/lib/bpf/bpf_exec.c b/lib/bpf/bpf_exec.c
index d423ef28f5..bb03c9cc2c 100644
--- a/lib/bpf/bpf_exec.c
+++ b/lib/bpf/bpf_exec.c
@@ -4,6 +4,7 @@
#include <stdio.h>
#include <stdint.h>
+#include <limits.h>
#include <eal_export.h>
#include <rte_common.h>
@@ -43,6 +44,16 @@
((reg)[(ins)->dst_reg] = \
(type)(reg)[(ins)->dst_reg] op (type)(ins)->imm)
+#define BPF_OP_SHIFT_IMM(reg, ins, op, type) \
+ ((reg)[(ins)->dst_reg] = \
+ (type)(reg)[(ins)->dst_reg] op \
+ ((ins)->imm & (sizeof(type) * CHAR_BIT - 1)))
+
+#define BPF_OP_SHIFT_REG(reg, ins, op, type) \
+ ((reg)[(ins)->dst_reg] = \
+ (type)(reg)[(ins)->dst_reg] op \
+ ((reg)[(ins)->src_reg] & (sizeof(type) * CHAR_BIT - 1)))
+
#define BPF_DIV_ZERO_CHECK(bpf, reg, ins, type) do { \
if ((type)(reg)[(ins)->src_reg] == 0) { \
RTE_BPF_LOG_LINE(ERR, \
@@ -183,10 +194,10 @@ bpf_exec(const struct rte_bpf *bpf, uint64_t reg[EBPF_REG_NUM])
BPF_OP_ALU_IMM(reg, ins, |, uint32_t);
break;
case (BPF_ALU | BPF_LSH | BPF_K):
- BPF_OP_ALU_IMM(reg, ins, <<, uint32_t);
+ BPF_OP_SHIFT_IMM(reg, ins, <<, uint32_t);
break;
case (BPF_ALU | BPF_RSH | BPF_K):
- BPF_OP_ALU_IMM(reg, ins, >>, uint32_t);
+ BPF_OP_SHIFT_IMM(reg, ins, >>, uint32_t);
break;
case (BPF_ALU | BPF_XOR | BPF_K):
BPF_OP_ALU_IMM(reg, ins, ^, uint32_t);
@@ -217,10 +228,10 @@ bpf_exec(const struct rte_bpf *bpf, uint64_t reg[EBPF_REG_NUM])
BPF_OP_ALU_REG(reg, ins, |, uint32_t);
break;
case (BPF_ALU | BPF_LSH | BPF_X):
- BPF_OP_ALU_REG(reg, ins, <<, uint32_t);
+ BPF_OP_SHIFT_REG(reg, ins, <<, uint32_t);
break;
case (BPF_ALU | BPF_RSH | BPF_X):
- BPF_OP_ALU_REG(reg, ins, >>, uint32_t);
+ BPF_OP_SHIFT_REG(reg, ins, >>, uint32_t);
break;
case (BPF_ALU | BPF_XOR | BPF_X):
BPF_OP_ALU_REG(reg, ins, ^, uint32_t);
@@ -262,13 +273,13 @@ bpf_exec(const struct rte_bpf *bpf, uint64_t reg[EBPF_REG_NUM])
BPF_OP_ALU_IMM(reg, ins, |, uint64_t);
break;
case (EBPF_ALU64 | BPF_LSH | BPF_K):
- BPF_OP_ALU_IMM(reg, ins, <<, uint64_t);
+ BPF_OP_SHIFT_IMM(reg, ins, <<, uint64_t);
break;
case (EBPF_ALU64 | BPF_RSH | BPF_K):
- BPF_OP_ALU_IMM(reg, ins, >>, uint64_t);
+ BPF_OP_SHIFT_IMM(reg, ins, >>, uint64_t);
break;
case (EBPF_ALU64 | EBPF_ARSH | BPF_K):
- BPF_OP_ALU_IMM(reg, ins, >>, int64_t);
+ BPF_OP_SHIFT_IMM(reg, ins, >>, int64_t);
break;
case (EBPF_ALU64 | BPF_XOR | BPF_K):
BPF_OP_ALU_IMM(reg, ins, ^, uint64_t);
@@ -299,13 +310,13 @@ bpf_exec(const struct rte_bpf *bpf, uint64_t reg[EBPF_REG_NUM])
BPF_OP_ALU_REG(reg, ins, |, uint64_t);
break;
case (EBPF_ALU64 | BPF_LSH | BPF_X):
- BPF_OP_ALU_REG(reg, ins, <<, uint64_t);
+ BPF_OP_SHIFT_REG(reg, ins, <<, uint64_t);
break;
case (EBPF_ALU64 | BPF_RSH | BPF_X):
- BPF_OP_ALU_REG(reg, ins, >>, uint64_t);
+ BPF_OP_SHIFT_REG(reg, ins, >>, uint64_t);
break;
case (EBPF_ALU64 | EBPF_ARSH | BPF_X):
- BPF_OP_ALU_REG(reg, ins, >>, int64_t);
+ BPF_OP_SHIFT_REG(reg, ins, >>, int64_t);
break;
case (EBPF_ALU64 | BPF_XOR | BPF_X):
BPF_OP_ALU_REG(reg, ins, ^, uint64_t);
--
2.53.0
^ permalink raw reply related
* [PATCH v5 4/9] bpf/arm64: mask shift count per RFC 9669
From: Stephen Hemminger @ 2026-06-24 17:55 UTC (permalink / raw)
To: dev
Cc: Stephen Hemminger, stable, Wathsala Vithanage, Konstantin Ananyev,
Marat Khalili, Jerin Jacob
In-Reply-To: <20260624175815.673064-1-stephen@networkplumber.org>
The ARM JIT was not masking the shift count as required by RFC 9669
(0x3f for 64-bit, 0x1f for 32-bit), so large immediate shift counts
overflowed the UBFM/SBFM encoding and failed the JIT. Mask the
immediate in emit_lsl/emit_lsr/emit_asr.
Fixes: 9f4469d9e83a ("bpf/arm: add logical operations")
Cc: stable@dpdk.org
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
lib/bpf/bpf_jit_arm64.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/lib/bpf/bpf_jit_arm64.c b/lib/bpf/bpf_jit_arm64.c
index ba7ae4d680..7582370062 100644
--- a/lib/bpf/bpf_jit_arm64.c
+++ b/lib/bpf/bpf_jit_arm64.c
@@ -545,12 +545,14 @@ emit_bitfield(struct a64_jit_ctx *ctx, bool is64, uint8_t rd, uint8_t rn,
emit_insn(ctx, insn, check_reg(rd) || check_reg(rn) ||
check_immr_imms(is64, immr, imms));
}
+
static void
emit_lsl(struct a64_jit_ctx *ctx, bool is64, uint8_t rd, uint8_t imm)
{
const unsigned int width = is64 ? 64 : 32;
uint8_t imms, immr;
+ imm &= width - 1;
immr = (width - imm) & (width - 1);
imms = width - 1 - imm;
@@ -560,13 +562,19 @@ emit_lsl(struct a64_jit_ctx *ctx, bool is64, uint8_t rd, uint8_t imm)
static void
emit_lsr(struct a64_jit_ctx *ctx, bool is64, uint8_t rd, uint8_t imm)
{
- emit_bitfield(ctx, is64, rd, rd, imm, is64 ? 63 : 31, A64_UBFM);
+ const unsigned int width = is64 ? 64 : 32;
+
+ imm &= width - 1;
+ emit_bitfield(ctx, is64, rd, rd, imm, width - 1, A64_UBFM);
}
static void
emit_asr(struct a64_jit_ctx *ctx, bool is64, uint8_t rd, uint8_t imm)
{
- emit_bitfield(ctx, is64, rd, rd, imm, is64 ? 63 : 31, A64_SBFM);
+ const unsigned int width = is64 ? 64 : 32;
+
+ imm &= width - 1;
+ emit_bitfield(ctx, is64, rd, rd, imm, width - 1, A64_SBFM);
}
#define A64_AND 0
--
2.53.0
^ permalink raw reply related
* [PATCH v5 5/9] test/bpf: add test for large shift
From: Stephen Hemminger @ 2026-06-24 17:55 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, Konstantin Ananyev, Marat Khalili
In-Reply-To: <20260624175815.673064-1-stephen@networkplumber.org>
There were multiple bugs with immediate values in shift instructions.
The code was not masking as required by RFC.
Add new tests that cover these instructions.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
app/test/test_bpf.c | 59 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 59 insertions(+)
diff --git a/app/test/test_bpf.c b/app/test/test_bpf.c
index 232e9e2a98..0e5894a532 100644
--- a/app/test/test_bpf.c
+++ b/app/test/test_bpf.c
@@ -2005,6 +2005,51 @@ test_div1_check(uint64_t rc, const void *arg)
return cmp_res(__func__, 0, rc, dve.out, dvt->out, sizeof(dve.out));
}
+/*
+ * Shift counts are masked to the operand width (RFC 9669: 0x3f for 64-bit,
+ * 0x1f for 32-bit). Counts >= 128 also exercise the x86 imm_size() path that
+ * used to desync the stream, and the arm64 UBFM/SBFM immediate encoding.
+ */
+static const struct ebpf_insn test_shift_big_imm_prog[] = {
+ {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 1
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_LSH | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 191
+ },
+ {
+ .code = (EBPF_ALU64 | EBPF_ARSH | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 200
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_RSH | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 130
+ },
+ {
+ .code = (BPF_JMP | EBPF_EXIT)
+ },
+};
+
+static void
+test_shift_big_imm_prepare(void *arg)
+{
+ memset(arg, 0, sizeof(struct dummy_offset));
+}
+
+static int
+test_shift_big_imm_check(uint64_t rc, const void *arg)
+{
+ uint64_t expect = 0x3FE0000000000000ULL;
+
+ return cmp_res(__func__, expect, rc, arg, arg, 0);
+}
+
/* call test-cases */
static const struct ebpf_insn test_call1_prog[] = {
@@ -3409,6 +3454,20 @@ static const struct bpf_test tests[] = {
.prepare = test_mul1_prepare,
.check_result = test_div1_check,
},
+ {
+ .name = "test_shift_big_imm",
+ .arg_sz = sizeof(struct dummy_offset),
+ .prm = {
+ .ins = test_shift_big_imm_prog,
+ .nb_ins = RTE_DIM(test_shift_big_imm_prog),
+ .prog_arg = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(struct dummy_offset),
+ },
+ },
+ .prepare = test_shift_big_imm_prepare,
+ .check_result = test_shift_big_imm_check,
+ },
{
.name = "test_call1",
.arg_sz = sizeof(struct dummy_offset),
--
2.53.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox