patch 'ipc: use request ID instead of pointers' has been queued to stable release 24.11.7

luca.boccassi at gmail.com luca.boccassi at gmail.com
Mon Jul 6 12:20:32 CEST 2026


Hi,

FYI, your patch has been queued to stable release 24.11.7

Note it hasn't been pushed to http://dpdk.org/browse/dpdk-stable yet.
It will be pushed if I get no objections before 07/05/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/bluca/dpdk-stable

This queued commit can be viewed at:
https://github.com/bluca/dpdk-stable/commit/4f8725048b29073d0208bdce3454451059d05de9

Thanks.

Luca Boccassi

---
>From 4f8725048b29073d0208bdce3454451059d05de9 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 2e81723979..393854ef57 100644
--- a/lib/eal/common/eal_common_proc.c
+++ b/lib/eal/common/eal_common_proc.c
@@ -73,6 +73,7 @@ struct async_request_param {
 
 struct pending_request {
 	TAILQ_ENTRY(pending_request) next;
+	unsigned long id;
 	enum {
 		REQUEST_TYPE_SYNC,
 		REQUEST_TYPE_ASYNC
@@ -91,6 +92,8 @@ struct pending_request {
 	};
 };
 
+static unsigned long next_request_id;
+
 TAILQ_HEAD(pending_request_list, pending_request);
 
 static struct {
@@ -110,15 +113,15 @@ mp_send(struct rte_mp_msg *msg, const char *peer, int type);
 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
 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;
 
@@ -131,6 +134,19 @@ find_pending_request(const char *dst, const char *act_name)
 	return r;
 }
 
+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)
 {
@@ -346,7 +362,7 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
 		struct pending_request *req = NULL;
 
 		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));
 			/* -1 indicates that we've been asked to ignore */
@@ -356,8 +372,7 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
 			if (pending_req->type == REQUEST_TYPE_SYNC)
 				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);
 			cleanup_msg_fds(msg);
@@ -511,9 +526,8 @@ 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;
 
@@ -526,7 +540,7 @@ 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
 		 * handling the same message twice.
@@ -549,9 +563,16 @@ static void
 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);
 
 	if (req != NULL)
@@ -860,8 +881,18 @@ 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));
 	if (pending_req == NULL || reply_msg == NULL) {
@@ -871,22 +902,14 @@ mp_request_async(const char *dst, struct rte_mp_msg *req,
 		goto fail;
 	}
 
+	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;
 	pending_req->reply = reply_msg;
 	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) {
 		EAL_LOG(ERR, "Fail to send request %s:%s",
@@ -901,7 +924,7 @@ 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);
 		ret = -1;
@@ -934,7 +957,7 @@ mp_request_sync(const char *dst, struct rte_mp_msg *req,
 	pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
 	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);
 		rte_errno = EEXIST;
@@ -1153,6 +1176,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 	 * it, and put it on the queue if we don't send any requests.
 	 */
 	dummy->type = REQUEST_TYPE_ASYNC;
+	dummy->id = ++next_request_id;
 	dummy->request = copy;
 	dummy->reply = NULL;
 	dummy->async.param = param;
-- 
2.47.3

---
  Diff of the applied patch vs upstream commit (please double-check if non-empty:
---
--- -	2026-07-03 12:55:48.224075378 +0100
+++ 0040-ipc-use-request-ID-instead-of-pointers.patch	2026-07-03 12:55:46.670573982 +0100
@@ -1 +1 @@
-From b655b605d2547b52a9ab64c914f07017ea61da33 Mon Sep 17 00:00:00 2001
+From 4f8725048b29073d0208bdce3454451059d05de9 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 2e81723979..393854ef57 100644
@@ -30 +31 @@
-@@ -74,6 +74,7 @@ struct async_request_param {
+@@ -73,6 +73,7 @@ struct async_request_param {
@@ -38 +39 @@
-@@ -92,6 +93,8 @@ struct pending_request {
+@@ -91,6 +92,8 @@ struct pending_request {
@@ -47 +48 @@
-@@ -111,15 +114,15 @@ mp_send(struct rte_mp_msg *msg, const char *peer, int type);
+@@ -110,15 +113,15 @@ mp_send(struct rte_mp_msg *msg, const char *peer, int type);
@@ -66 +67 @@
-@@ -132,6 +135,19 @@ find_pending_request(const char *dst, const char *act_name)
+@@ -131,6 +134,19 @@ find_pending_request(const char *dst, const char *act_name)
@@ -83,4 +84,4 @@
- /*
-  * Combine prefix and name(optional) to return unix domain socket path
-  * return the number of characters that would have been put into buffer.
-@@ -354,7 +370,7 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
+ static void
+ create_socket_path(const char *name, char *buf, int len)
+ {
+@@ -346,7 +362,7 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
@@ -95 +96 @@
-@@ -364,8 +380,7 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
+@@ -356,8 +372,7 @@ process_msg(struct mp_msg_internal *m, struct sockaddr_un *s)
@@ -105 +106 @@
-@@ -519,9 +534,8 @@ trigger_async_action(struct pending_request *sr)
+@@ -511,9 +526,8 @@ trigger_async_action(struct pending_request *sr)
@@ -116 +117 @@
-@@ -534,7 +548,7 @@ async_reply_handle_thread_unsafe(void *arg)
+@@ -526,7 +540,7 @@ async_reply_handle_thread_unsafe(void *arg)
@@ -125 +126 @@
-@@ -557,9 +571,16 @@ static void
+@@ -549,9 +563,16 @@ static void
@@ -143 +144 @@
-@@ -878,8 +899,18 @@ mp_request_async(const char *dst, struct rte_mp_msg *req,
+@@ -860,8 +881,18 @@ mp_request_async(const char *dst, struct rte_mp_msg *req,
@@ -162 +163 @@
-@@ -889,22 +920,14 @@ mp_request_async(const char *dst, struct rte_mp_msg *req,
+@@ -871,22 +902,14 @@ mp_request_async(const char *dst, struct rte_mp_msg *req,
@@ -187 +188 @@
-@@ -919,7 +942,7 @@ mp_request_async(const char *dst, struct rte_mp_msg *req,
+@@ -901,7 +924,7 @@ mp_request_async(const char *dst, struct rte_mp_msg *req,
@@ -196 +197 @@
-@@ -952,7 +975,7 @@ mp_request_sync(const char *dst, struct rte_mp_msg *req,
+@@ -934,7 +957,7 @@ mp_request_sync(const char *dst, struct rte_mp_msg *req,
@@ -205 +206 @@
-@@ -1178,6 +1201,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
+@@ -1153,6 +1176,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,


More information about the stable mailing list