From: Daniel Zahka <daniel.zahka@gmail.com>
To: "David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>,
Paolo Abeni <pabeni@redhat.com>, Simon Horman <horms@kernel.org>,
Donald Hunter <donald.hunter@gmail.com>,
Boris Pismenny <borisp@nvidia.com>,
Saeed Mahameed <saeedm@nvidia.com>,
Leon Romanovsky <leon@kernel.org>,
Tariq Toukan <tariqt@nvidia.com>, Mark Bloch <mbloch@nvidia.com>,
Andrew Lunn <andrew+netdev@lunn.ch>,
Shuah Khan <shuah@kernel.org>,
Willem de Bruijn <willemdebruijn.kernel@gmail.com>
Cc: netdev@vger.kernel.org, linux-kselftest@vger.kernel.org,
Daniel Zahka <daniel.zahka@gmail.com>
Subject: [PATCH net-next 5/9] psp: add driver api for deferred tx key deletion
Date: Wed, 04 Feb 2026 07:20:09 -0800 [thread overview]
Message-ID: <20260204-psp-v1-5-5f034e2dfa36@gmail.com> (raw)
In-Reply-To: <20260204-psp-v1-0-5f034e2dfa36@gmail.com>
There is a race condition during tx key deletion on devices that use
key identifiers in tx metadata, as opposed to inlining keys
directly. When a key is requested to be deleted, there may be skb's in
the tx ring, whose metadata descriptors contain unaccounted references
to a tx key. Under these conditions, the skb sitting in the tx ring
can race against the request to fw to delete the tx key handle.
The solution implemented here is to provide an api for core to defer
tx key deletion operations until after the driver signals that it is
safe to do so.
Core informs the driver that a key deletion grace period is starting
via psp_dev::tx_grace_begin(). While a grace period is active, core
will queue keys to be deleted to the psp_dev::tx_del_next queue.
Core will then periodically query the driver with
psp_dev::tx_grace_end() to determine if it is safe to delete the
keys it has queued. If it is, core will then move the queued keys into
a new list and begin deleting them, allowing the psp_dev::tx_del_next
queue to begin filling for the next grace period.
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
---
include/net/psp/types.h | 32 +++++++++++++++++
net/psp/psp.h | 1 +
net/psp/psp_main.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++
net/psp/psp_sock.c | 13 ++++++-
4 files changed, 138 insertions(+), 1 deletion(-)
diff --git a/include/net/psp/types.h b/include/net/psp/types.h
index 52844ac6f870..280c7fdc713c 100644
--- a/include/net/psp/types.h
+++ b/include/net/psp/types.h
@@ -5,6 +5,7 @@
#include <linux/mutex.h>
#include <linux/refcount.h>
+#include <linux/workqueue.h>
struct netlink_ext_ack;
@@ -58,6 +59,10 @@ struct psp_dev_config {
* @prev_assocs: associations which use old (but still usable)
* device key
* @stale_assocs: associations which use a rotated out key
+ * @tx_del_active: TX keys to be deleted after the current grace period
+ * @tx_del_next: TX keys queued for deletion during current grace period
+ * @tx_del_work: workqueue for periodic grace period checking
+ * @tx_grace_active: true if a grace period is in progress
*
* @stats: statistics maintained by the core
* @stats.rotations: See stats attr key-rotations
@@ -85,6 +90,11 @@ struct psp_dev {
struct list_head prev_assocs;
struct list_head stale_assocs;
+ struct list_head tx_del_active;
+ struct list_head tx_del_next;
+ struct delayed_work tx_del_work;
+ bool tx_grace_active;
+
struct {
unsigned long rotations;
unsigned long stales;
@@ -208,6 +218,28 @@ struct psp_dev_ops {
*/
void (*tx_key_del)(struct psp_dev *psd, struct psp_assoc *pas);
+ /**
+ * @tx_grace_begin: begin TX grace period tracking
+ * Begin a new TX grace period. Core will queue tx keys for deletion
+ * and not delete them until the grace period has elapsed.
+ *
+ * Return: 0 on success, error code otherwise. If the operation fails,
+ * core will try again later and a grace period is not activated.
+ */
+ int (*tx_grace_begin)(struct psp_dev *psd);
+
+ /**
+ * @tx_grace_end: check if TX grace period has ended
+ * Check if the current TX grace period has ended.
+ *
+ * Return:
+ * 0: grace period has ended, core will delete queued tx keys
+ * -EAGAIN: grace period has not ended, core will requery later
+ * other error: internal error (e.g., device reconfigured), core
+ * should return to the tx_grace_begin() phase
+ */
+ int (*tx_grace_end)(struct psp_dev *psd);
+
/**
* @get_stats: get statistics from the device
* Stats required by the spec must be maintained and filled in.
diff --git a/net/psp/psp.h b/net/psp/psp.h
index b86539d5137a..d09fdd956fcb 100644
--- a/net/psp/psp.h
+++ b/net/psp/psp.h
@@ -15,6 +15,7 @@ extern struct mutex psp_devs_lock;
void psp_dev_free(struct psp_dev *psd);
int psp_dev_check_access(struct psp_dev *psd, struct net *net);
+void psp_tx_key_queue_del(struct psp_dev *psd, struct psp_assoc *pas);
void psp_nl_notify_dev(struct psp_dev *psd, u32 cmd);
diff --git a/net/psp/psp_main.c b/net/psp/psp_main.c
index 982c96f74ae3..2fb886edc384 100644
--- a/net/psp/psp_main.c
+++ b/net/psp/psp_main.c
@@ -14,6 +14,10 @@
DEFINE_XARRAY_ALLOC1(psp_devs);
struct mutex psp_devs_lock;
+#define PSP_TX_DEL_INTERVAL_MS 100
+
+static void psp_tx_del_work_fn(struct work_struct *work);
+
/**
* DOC: PSP locking
*
@@ -64,6 +68,9 @@ psp_dev_create(struct net_device *netdev,
!psd_ops->get_stats))
return ERR_PTR(-EINVAL);
+ if (WARN_ON(!!psd_ops->tx_grace_begin != !!psd_ops->tx_grace_end))
+ return ERR_PTR(-EINVAL);
+
psd = kzalloc(sizeof(*psd), GFP_KERNEL);
if (!psd)
return ERR_PTR(-ENOMEM);
@@ -77,6 +84,9 @@ psp_dev_create(struct net_device *netdev,
INIT_LIST_HEAD(&psd->active_assocs);
INIT_LIST_HEAD(&psd->prev_assocs);
INIT_LIST_HEAD(&psd->stale_assocs);
+ INIT_LIST_HEAD(&psd->tx_del_active);
+ INIT_LIST_HEAD(&psd->tx_del_next);
+ INIT_DELAYED_WORK(&psd->tx_del_work, psp_tx_del_work_fn);
refcount_set(&psd->refcnt, 1);
mutex_lock(&psp_devs_lock);
@@ -118,6 +128,8 @@ void psp_dev_unregister(struct psp_dev *psd)
{
struct psp_assoc *pas, *next;
+ cancel_delayed_work_sync(&psd->tx_del_work);
+
mutex_lock(&psp_devs_lock);
mutex_lock(&psd->lock);
@@ -130,6 +142,15 @@ void psp_dev_unregister(struct psp_dev *psd)
xa_store(&psp_devs, psd->id, NULL, GFP_KERNEL);
mutex_unlock(&psp_devs_lock);
+ list_splice_init(&psd->tx_del_active, &psd->tx_del_next);
+ list_for_each_entry_safe(pas, next, &psd->tx_del_next, assocs_list) {
+ list_del(&pas->assocs_list);
+ psp_dev_tx_key_del(psd, pas);
+ psp_assoc_put(pas->prev);
+ psp_dev_put(psd);
+ kfree(pas);
+ }
+
list_splice_init(&psd->active_assocs, &psd->prev_assocs);
list_splice_init(&psd->prev_assocs, &psd->stale_assocs);
list_for_each_entry_safe(pas, next, &psd->stale_assocs, assocs_list) {
@@ -149,6 +170,78 @@ void psp_dev_unregister(struct psp_dev *psd)
}
EXPORT_SYMBOL(psp_dev_unregister);
+void psp_tx_key_queue_del(struct psp_dev *psd, struct psp_assoc *pas)
+{
+ lockdep_assert_held(&psd->lock);
+
+ list_add_tail(&pas->assocs_list, &psd->tx_del_next);
+ if (!delayed_work_pending(&psd->tx_del_work))
+ schedule_delayed_work(&psd->tx_del_work,
+ msecs_to_jiffies(PSP_TX_DEL_INTERVAL_MS));
+}
+
+static void psp_tx_del_work_fn(struct work_struct *work)
+{
+ struct delayed_work *dwork = to_delayed_work(work);
+ struct psp_dev *psd = container_of(dwork, struct psp_dev, tx_del_work);
+ struct psp_assoc *pas, *tmp;
+ bool need_reschedule = false;
+ LIST_HEAD(to_free);
+ int err;
+
+ mutex_lock(&psd->lock);
+
+ if (!psp_dev_is_registered(psd))
+ goto out_unlock;
+
+ if (psd->tx_grace_active) {
+ err = psd->ops->tx_grace_end(psd);
+ if (err == -EAGAIN) {
+ need_reschedule = true;
+ goto out_unlock;
+ }
+ if (err) {
+ /* Driver error, restart grace period */
+ psd->tx_grace_active = false;
+ list_splice_init(&psd->tx_del_active, &psd->tx_del_next);
+ goto start_grace;
+ }
+
+ list_for_each_entry_safe(pas, tmp, &psd->tx_del_active,
+ assocs_list) {
+ list_del(&pas->assocs_list);
+ psp_dev_tx_key_del(psd, pas);
+ list_add_tail(&pas->assocs_list, &to_free);
+ }
+
+ psd->tx_grace_active = false;
+ }
+
+start_grace:
+ if (!list_empty(&psd->tx_del_next)) {
+ err = psd->ops->tx_grace_begin(psd);
+ if (!err) {
+ list_splice_init(&psd->tx_del_next, &psd->tx_del_active);
+ psd->tx_grace_active = true;
+ }
+ need_reschedule = true;
+ }
+
+out_unlock:
+ mutex_unlock(&psd->lock);
+
+ list_for_each_entry_safe(pas, tmp, &to_free, assocs_list) {
+ list_del(&pas->assocs_list);
+ psp_assoc_put(pas->prev);
+ psp_dev_put(psd);
+ kfree(pas);
+ }
+
+ if (need_reschedule)
+ schedule_delayed_work(&psd->tx_del_work,
+ msecs_to_jiffies(PSP_TX_DEL_INTERVAL_MS));
+}
+
unsigned int psp_key_size(u32 version)
{
switch (version) {
diff --git a/net/psp/psp_sock.c b/net/psp/psp_sock.c
index 1a97609564e7..d038da122ebb 100644
--- a/net/psp/psp_sock.c
+++ b/net/psp/psp_sock.c
@@ -88,6 +88,11 @@ void psp_dev_tx_key_del(struct psp_dev *psd, struct psp_assoc *pas)
psd->ops->tx_key_del(psd, pas);
}
+static bool psp_dev_needs_defer(struct psp_dev *psd)
+{
+ return !!psd->ops->tx_grace_begin;
+}
+
static void psp_assoc_free(struct work_struct *work)
{
struct psp_assoc *pas = container_of(work, struct psp_assoc, work);
@@ -96,8 +101,14 @@ static void psp_assoc_free(struct work_struct *work)
mutex_lock(&psd->lock);
if (psd->ops) {
list_del(&pas->assocs_list);
- if (pas->tx.spi && !pas->tx_moved)
+ if (pas->tx.spi && !pas->tx_moved) {
+ if (psp_dev_needs_defer(psd)) {
+ psp_tx_key_queue_del(psd, pas);
+ mutex_unlock(&psd->lock);
+ return;
+ }
psp_dev_tx_key_del(psd, pas);
+ }
}
mutex_unlock(&psd->lock);
psp_assoc_put(pas->prev);
--
2.47.3
next prev parent reply other threads:[~2026-02-04 15:20 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-04 15:20 [PATCH net-next 0/9] psp: support rekeying psp protected tcp connections Daniel Zahka
2026-02-04 15:20 ` [PATCH net-next 1/9] psp: support rx rekey operation Daniel Zahka
2026-02-07 4:24 ` Jakub Kicinski
2026-02-07 4:32 ` [net-next,1/9] " Jakub Kicinski
2026-02-04 15:20 ` [PATCH net-next 2/9] psp: move code from psp_sock_assoc_set_tx() into helper functions Daniel Zahka
2026-02-04 20:46 ` Willem de Bruijn
2026-02-04 15:20 ` [PATCH net-next 3/9] psp: support tx rekey operation Daniel Zahka
2026-02-04 15:20 ` [PATCH net-next 4/9] psp: refactor psp_dev_tx_key_del() Daniel Zahka
2026-02-04 20:46 ` Willem de Bruijn
2026-02-04 15:20 ` Daniel Zahka [this message]
2026-02-04 15:20 ` [PATCH net-next 6/9] psp: add core tracked stats for deferred key deletion Daniel Zahka
2026-02-04 15:20 ` [PATCH net-next 7/9] mlx5: psp: implement deferred tx " Daniel Zahka
2026-02-07 4:30 ` Jakub Kicinski
2026-02-07 4:32 ` [net-next,7/9] " Jakub Kicinski
2026-02-04 15:20 ` [PATCH net-next 8/9] selftests: drv-net: psp: lift psp connection setup out of _data_basic_send() testcase Daniel Zahka
2026-02-04 20:49 ` Willem de Bruijn
2026-02-04 15:20 ` [PATCH net-next 9/9] selftests: drv-net: psp: add tests for rekeying connections Daniel Zahka
2026-02-04 20:45 ` [PATCH net-next 0/9] psp: support rekeying psp protected tcp connections Willem de Bruijn
2026-02-04 21:43 ` Daniel Zahka
2026-02-07 4:18 ` Jakub Kicinski
2026-02-07 4:21 ` Jakub Kicinski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260204-psp-v1-5-5f034e2dfa36@gmail.com \
--to=daniel.zahka@gmail.com \
--cc=andrew+netdev@lunn.ch \
--cc=borisp@nvidia.com \
--cc=davem@davemloft.net \
--cc=donald.hunter@gmail.com \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=leon@kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=mbloch@nvidia.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=saeedm@nvidia.com \
--cc=shuah@kernel.org \
--cc=tariqt@nvidia.com \
--cc=willemdebruijn.kernel@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox