Hi,
FYI, your patch has been queued to stable release 25.11.3
Note it hasn't been pushed to http://dpdk.org/browse/dpdk-stable yet.
It will be pushed if I get no objections before 08/01/26. So please
shout if anyone has objections.
Also note that after the patch there's a diff of the upstream commit vs the
patch applied to the branch. This will indicate if there was any rebasing
needed to apply to the stable branch. If there were code changes for rebasing
(ie: not only metadata diffs), please double check that the rebase was
correctly done.
Queued patches are on a temporary branch at:
https://github.com/kevintraynor/dpdk-stable
This queued commit can be viewed at:
https://github.com/kevintraynor/dpdk-stable/commit/2f0a3575da5687655c70d03df57b624f9039ab89
Thanks.
Kevin
---
>From 2f0a3575da5687655c70d03df57b624f9039ab89 Mon Sep 17 00:00:00 2001
From: Anatoly Burakov <anatoly.burakov at intel.com>
Date: Fri, 26 Jun 2026 11:33:57 +0100
Subject: [PATCH] ipc: use request ID instead of pointers
[ upstream commit b655b605d2547b52a9ab64c914f07017ea61da33 ]
Initial implementation of async IPC request handling was using request
pointers directly. Because of the nature of how IPC is meant to work and
that requests ownership is disconnected from their creation (as in, freeing
a request may happen due to timeout, or due to received response, or due
to rollback because of a later failure), using pointers as identity is not
safe.
Use numeric request ID for async request lookup instead. This way, we can
safely free requests even if we are already waiting on responses/timeouts
for them, as the pointers themselves will not be referenced directly by
the response/timeout.
Fixes: f05e26051c15 ("eal: add IPC asynchronous request")
Signed-off-by: Anatoly Burakov <anatoly.burakov at intel.com>
---
lib/eal/common/eal_common_proc.c | 68 +++++++++++++++++++++-----------
1 file changed, 46 insertions(+), 22 deletions(-)
diff --git a/lib/eal/common/eal_common_proc.c b/lib/eal/common/eal_common_proc.c
index 6193249e9f..0475aae1bf 100644
--- a/lib/eal/common/eal_common_proc.c
+++ b/lib/eal/common/eal_common_proc.c
@@ -75,4 +75,5 @@ struct async_request_param {
struct pending_request {
TAILQ_ENTRY(pending_request) next;
+ unsigned long id;
enum {
REQUEST_TYPE_SYNC,
@@ -93,4 +94,6 @@ struct pending_request {
};
+static unsigned long next_request_id;
+
TAILQ_HEAD(pending_request_list, pending_request);
@@ -112,7 +115,7 @@ static void
async_reply_handle(void *arg);
-/* for use with process_msg */
+/* for use with alarm callback and process_msg */
static struct pending_request *
-async_reply_handle_thread_unsafe(void *arg);
+async_reply_handle_thread_unsafe(struct pending_request *req);
static void
@@ -120,5 +123,5 @@ trigger_async_action(struct pending_request *req);
static struct pending_request *
-find_pending_request(const char *dst, const char *act_name)
+find_request_by_name(const char *dst, const char *act_name)
{
struct pending_request *r;
@@ -133,4 +136,17 @@ find_pending_request(const char *dst, const char *act_name)
}
+static struct pending_request *
+find_async_request_by_id(unsigned long id)
+{
+ struct pending_request *r;
+
+ TAILQ_FOREACH(r, &pending_requests.requests, next) {
+ if (r->id == id && r->type == REQUEST_TYPE_ASYNC)
+ return r;
+ }
+
+ return NULL;
+}
+
static void
create_socket_path(const char *name, char *buf, int len)
@@ -351,5 +367,5 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
pthread_mutex_lock(&pending_requests.lock);
- pending_req = find_pending_request(s->sun_path, msg->name);
+ pending_req = find_request_by_name(s->sun_path, msg->name);
if (pending_req) {
memcpy(pending_req->reply, msg, sizeof(*msg));
@@ -361,6 +377,5 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
pthread_cond_signal(&pending_req->sync.cond);
else if (pending_req->type == REQUEST_TYPE_ASYNC)
- req = async_reply_handle_thread_unsafe(
- pending_req);
+ req = async_reply_handle_thread_unsafe(pending_req);
} else {
EAL_LOG(ERR, "Drop mp reply: %s", msg->name);
@@ -516,7 +531,6 @@ trigger_async_action(struct pending_request *sr)
static struct pending_request *
-async_reply_handle_thread_unsafe(void *arg)
+async_reply_handle_thread_unsafe(struct pending_request *req)
{
- struct pending_request *req = (struct pending_request *)arg;
enum async_action action;
struct timespec ts_now;
@@ -531,5 +545,5 @@ async_reply_handle_thread_unsafe(void *arg)
TAILQ_REMOVE(&pending_requests.requests, req, next);
- if (rte_eal_alarm_cancel(async_reply_handle, req) < 0) {
+ if (rte_eal_alarm_cancel(async_reply_handle, (void *)(uintptr_t)req->id) < 0) {
/* if we failed to cancel the alarm because it's already in
* progress, don't proceed because otherwise we will end up
@@ -554,7 +568,14 @@ async_reply_handle(void *arg)
{
struct pending_request *req;
+ /* alarm arg carries the request ID packed into a void * via uintptr_t */
+ unsigned long id = (uintptr_t)arg;
+
+ /* ensure request ID matches pointer size */
+ RTE_BUILD_BUG_ON(sizeof(next_request_id) != sizeof(uintptr_t));
pthread_mutex_lock(&pending_requests.lock);
- req = async_reply_handle_thread_unsafe(arg);
+ req = find_async_request_by_id(id);
+ if (req != NULL)
+ req = async_reply_handle_thread_unsafe(req);
pthread_mutex_unlock(&pending_requests.lock);
@@ -864,6 +885,16 @@ mp_request_async(const char *dst, struct rte_mp_msg *req,
struct rte_mp_msg *reply_msg;
struct pending_request *pending_req, *exist;
+ unsigned long id;
int ret = -1;
+ /* queue already locked by caller */
+
+ exist = find_request_by_name(dst, req->name);
+ if (exist) {
+ EAL_LOG(ERR, "A pending request %s:%s", dst, req->name);
+ rte_errno = EEXIST;
+ return -1;
+ }
+
pending_req = calloc(1, sizeof(*pending_req));
reply_msg = calloc(1, sizeof(*reply_msg));
@@ -875,5 +906,7 @@ mp_request_async(const char *dst, struct rte_mp_msg *req,
}
+ id = ++next_request_id;
pending_req->type = REQUEST_TYPE_ASYNC;
+ pending_req->id = id;
strlcpy(pending_req->dst, dst, sizeof(pending_req->dst));
pending_req->request = req;
@@ -881,14 +914,4 @@ mp_request_async(const char *dst, struct rte_mp_msg *req,
pending_req->async.param = param;
- /* queue already locked by caller */
-
- exist = find_pending_request(dst, req->name);
- if (exist) {
- EAL_LOG(ERR, "A pending request %s:%s", dst, req->name);
- rte_errno = EEXIST;
- ret = -1;
- goto fail;
- }
-
ret = send_msg(dst, req, MP_REQ);
if (ret < 0) {
@@ -905,5 +928,5 @@ mp_request_async(const char *dst, struct rte_mp_msg *req,
/* if alarm set fails, we simply ignore the reply */
if (rte_eal_alarm_set(ts->tv_sec * 1000000 + ts->tv_nsec / 1000,
- async_reply_handle, pending_req) < 0) {
+ async_reply_handle, (void *)(uintptr_t)id) < 0) {
EAL_LOG(ERR, "Fail to set alarm for request %s:%s",
dst, req->name);
@@ -938,5 +961,5 @@ mp_request_sync(const char *dst, struct rte_mp_msg *req,
pthread_cond_init(&pending_req.sync.cond, &attr);
- exist = find_pending_request(dst, req->name);
+ exist = find_request_by_name(dst, req->name);
if (exist) {
EAL_LOG(ERR, "A pending request %s:%s", dst, req->name);
@@ -1159,4 +1182,5 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
*/
dummy->type = REQUEST_TYPE_ASYNC;
+ dummy->id = ++next_request_id;
dummy->request = copy;
dummy->reply = NULL;
--
2.55.0
---
Diff of the applied patch vs upstream commit (please double-check if non-empty:
---
--- - 2026-07-28 16:54:52.983494929 +0100
+++ 0075-ipc-use-request-ID-instead-of-pointers.patch 2026-07-28 16:54:50.833301118 +0100
@@ -1 +1 @@
-From b655b605d2547b52a9ab64c914f07017ea61da33 Mon Sep 17 00:00:00 2001
+From 2f0a3575da5687655c70d03df57b624f9039ab89 Mon Sep 17 00:00:00 2001
@@ -5,0 +6,2 @@
+[ upstream commit b655b605d2547b52a9ab64c914f07017ea61da33 ]
+
@@ -19 +20,0 @@
-Cc: stable at dpdk.org
@@ -27 +28 @@
-index 799c6e81b0..31eebae204 100644
+index 6193249e9f..0475aae1bf 100644
@@ -76,3 +77,3 @@
- /*
- * Combine prefix and name(optional) to return unix domain socket path
-@@ -355,5 +371,5 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
+ static void
+ create_socket_path(const char *name, char *buf, int len)
+@@ -351,5 +367,5 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
@@ -85 +86 @@
-@@ -365,6 +381,5 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
+@@ -361,6 +377,5 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
@@ -93 +94 @@
-@@ -520,7 +535,6 @@ trigger_async_action(struct pending_request *sr)
+@@ -516,7 +531,6 @@ trigger_async_action(struct pending_request *sr)
@@ -102 +103 @@
-@@ -535,5 +549,5 @@ async_reply_handle_thread_unsafe(void *arg)
+@@ -531,5 +545,5 @@ async_reply_handle_thread_unsafe(void *arg)
@@ -109 +110 @@
-@@ -558,7 +572,14 @@ async_reply_handle(void *arg)
+@@ -554,7 +568,14 @@ async_reply_handle(void *arg)
@@ -125 +126 @@
-@@ -879,6 +900,16 @@ mp_request_async(const char *dst, struct rte_mp_msg *req,
+@@ -864,6 +885,16 @@ mp_request_async(const char *dst, struct rte_mp_msg *req,
@@ -142 +143 @@
-@@ -890,5 +921,7 @@ mp_request_async(const char *dst, struct rte_mp_msg *req,
+@@ -875,5 +906,7 @@ mp_request_async(const char *dst, struct rte_mp_msg *req,
@@ -150 +151 @@
-@@ -896,14 +929,4 @@ mp_request_async(const char *dst, struct rte_mp_msg *req,
+@@ -881,14 +914,4 @@ mp_request_async(const char *dst, struct rte_mp_msg *req,
@@ -165 +166 @@
-@@ -920,5 +943,5 @@ mp_request_async(const char *dst, struct rte_mp_msg *req,
+@@ -905,5 +928,5 @@ mp_request_async(const char *dst, struct rte_mp_msg *req,
@@ -172 +173 @@
-@@ -953,5 +976,5 @@ mp_request_sync(const char *dst, struct rte_mp_msg *req,
+@@ -938,5 +961,5 @@ mp_request_sync(const char *dst, struct rte_mp_msg *req,
@@ -179 +180 @@
-@@ -1179,4 +1202,5 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
+@@ -1159,4 +1182,5 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,