public inbox for io-uring@vger.kernel.org
 help / color / mirror / Atom feed
From: Gabriel Krisman Bertazi <krisman@suse.de>
To: Jens Axboe <axboe@kernel.dk>
Cc: Gabriel Krisman Bertazi <krisman@suse.de>,
	io-uring@vger.kernel.org, csander@purestorage.com
Subject: [PATCH liburing v3 2/4] test/bind-listen.t: Use ephemeral port
Date: Wed,  3 Dec 2025 14:52:16 -0500	[thread overview]
Message-ID: <20251203195223.3578559-3-krisman@suse.de> (raw)
In-Reply-To: <20251203195223.3578559-1-krisman@suse.de>

This test fails if port 8000 is already in use by something else.  Now
that we have getsockname with direct file descriptors, use an ephemeral
port instead.  To avoid regressing old systems, bite the bullet and do
the syscall version for older kernels, fixing the test there as well.

Signed-off-by: Gabriel Krisman Bertazi <krisman@suse.de>

---
since v2:
 - don't fail on older kernels
---
 test/bind-listen.c | 89 ++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 79 insertions(+), 10 deletions(-)

diff --git a/test/bind-listen.c b/test/bind-listen.c
index 6f80f177..a468aa94 100644
--- a/test/bind-listen.c
+++ b/test/bind-listen.c
@@ -22,7 +22,7 @@ static void msec_to_ts(struct __kernel_timespec *ts, unsigned int msec)
 }
 
 static const char *magic = "Hello World!";
-static int use_port = 8000;
+static bool no_getsockname = false;
 
 enum {
 	SRV_INDEX = 0,
@@ -74,18 +74,82 @@ static int connect_client(struct io_uring *ring, unsigned short peer_port)
 	return T_SETUP_OK;
 }
 
-static int setup_srv(struct io_uring *ring, struct sockaddr_in *server_addr)
+/*
+ * getsockname was added to the kernel a few releases after bind/listen.
+ * In order to provide a backward-compatible test, fallback to
+ * non-io-uring if we are on an older kernel, allowing the test to
+ * continue.
+ */
+static int do_getsockname(struct io_uring *ring, int direct_socket,
+			  int peer, struct sockaddr *saddr,
+			  socklen_t *saddr_len)
+{
+	struct io_uring_sqe *sqe;
+	struct io_uring_cqe *cqe;
+	int res, fd;
+
+	if (!no_getsockname) {
+		/* attempt io_uring. Commmand might not exist */
+		sqe = io_uring_get_sqe(ring);
+		io_uring_prep_cmd_getsockname(sqe, direct_socket,
+					      saddr, saddr_len, peer);
+		sqe->flags |= IOSQE_FIXED_FILE | IOSQE_IO_LINK;
+		io_uring_submit(ring);
+		io_uring_wait_cqe(ring, &cqe);
+		res = cqe->res;
+		io_uring_cqe_seen(ring, cqe);
+	}
+
+	if (no_getsockname || res == -ENOTSUP) {
+		/*
+		 * Older kernel.  install the fd and use the getsockname
+		 * syscall.
+		 */
+		no_getsockname = true;
+
+		sqe = io_uring_get_sqe(ring);
+		io_uring_prep_fixed_fd_install(sqe, direct_socket, 0);
+		io_uring_submit(ring);
+		io_uring_wait_cqe(ring, &cqe);
+		fd = cqe->res;
+		io_uring_cqe_seen(ring, cqe);
+
+		if (fd < 0) {
+			fprintf(stderr, "installing direct fd failed. %d\n",
+				cqe->res);
+			return T_EXIT_FAIL;
+		}
+		if (peer)
+			res = getpeername(fd, saddr, saddr_len);
+		else
+			res = getsockname(fd, saddr, saddr_len);
+
+		if (res) {
+			fprintf(stderr, "get%sname syscall failed. %d\n",
+				peer? "peer":"sock", errno);
+			return T_EXIT_FAIL;
+		}
+		close(fd);
+	} else if (res < 0) {
+		fprintf(stderr, "getsockname server failed. %d\n", cqe->res);
+		return T_EXIT_FAIL;
+	}
+	return 0;
+}
+
+static int setup_srv(struct io_uring *ring)
 {
+	struct sockaddr_in server_addr;
 	struct io_uring_sqe *sqe;
 	struct io_uring_cqe *cqe;
 	struct __kernel_timespec ts;
 	int ret, val, submitted;
 	unsigned head;
 
-	memset(server_addr, 0, sizeof(struct sockaddr_in));
-	server_addr->sin_family = AF_INET;
-	server_addr->sin_port = htons(use_port++);
-	server_addr->sin_addr.s_addr = htons(INADDR_ANY);
+	memset(&server_addr, 0, sizeof(struct sockaddr_in));
+	server_addr.sin_family = AF_INET;
+	server_addr.sin_port = htons(0);
+	server_addr.sin_addr.s_addr = htons(INADDR_ANY);
 
 	sqe = io_uring_get_sqe(ring);
 	io_uring_prep_socket_direct(sqe, AF_INET, SOCK_STREAM, 0, SRV_INDEX, 0);
@@ -98,7 +162,7 @@ static int setup_srv(struct io_uring *ring, struct sockaddr_in *server_addr)
 	sqe->flags |= IOSQE_FIXED_FILE | IOSQE_IO_LINK;
 
 	sqe = io_uring_get_sqe(ring);
-	io_uring_prep_bind(sqe, SRV_INDEX, (struct sockaddr *) server_addr,
+	io_uring_prep_bind(sqe, SRV_INDEX, (struct sockaddr *) &server_addr,
 			   sizeof(struct sockaddr_in));
 	sqe->flags |= IOSQE_FIXED_FILE | IOSQE_IO_LINK;
 
@@ -132,7 +196,8 @@ static int setup_srv(struct io_uring *ring, struct sockaddr_in *server_addr)
 
 static int test_good_server(unsigned int ring_flags)
 {
-	struct sockaddr_in server_addr;
+	struct sockaddr_in saddr = {};
+	socklen_t saddr_len = sizeof(saddr);
 	struct __kernel_timespec ts;
 	struct io_uring_sqe *sqe;
 	struct io_uring_cqe *cqe;
@@ -155,13 +220,17 @@ static int test_good_server(unsigned int ring_flags)
 		return T_SETUP_SKIP;
 	}
 
-	ret = setup_srv(&ring, &server_addr);
+	ret = setup_srv(&ring);
 	if (ret != T_SETUP_OK) {
 		fprintf(stderr, "srv startup failed.\n");
 		return T_EXIT_FAIL;
 	}
 
-	if (connect_client(&ring, server_addr.sin_port) != T_SETUP_OK) {
+	if (do_getsockname(&ring, SRV_INDEX, 0, (struct sockaddr*) &saddr,
+			   &saddr_len))
+		return T_EXIT_FAIL;
+
+	if (connect_client(&ring, saddr.sin_port) != T_SETUP_OK) {
 		fprintf(stderr, "cli startup failed.\n");
 		return T_SETUP_SKIP;
 	}
-- 
2.52.0


  parent reply	other threads:[~2025-12-03 19:52 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-12-03 19:52 [PATCH liburing v3 0/4] liburing: getsockname support Gabriel Krisman Bertazi
2025-12-03 19:52 ` [PATCH liburing v3 1/4] liburing: Introduce getsockname operation Gabriel Krisman Bertazi
2025-12-03 19:52 ` Gabriel Krisman Bertazi [this message]
2025-12-03 19:52 ` [PATCH liburing v3 3/4] bind-listen.t: Add tests for getsockname Gabriel Krisman Bertazi
2025-12-03 19:52 ` [PATCH liburing v3 4/4] man/io_uring_prep_getsockname.3: Add man page Gabriel Krisman Bertazi
2025-12-03 20:23 ` [PATCH liburing v3 0/4] liburing: getsockname support Jens Axboe

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=20251203195223.3578559-3-krisman@suse.de \
    --to=krisman@suse.de \
    --cc=axboe@kernel.dk \
    --cc=csander@purestorage.com \
    --cc=io-uring@vger.kernel.org \
    /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