All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bui Viet Dung <dungvn2345@gmail.com>
To: Pavel Begunkov <asml.silence@gmail.com>, Jens Axboe <axboe@kernel.dk>
Cc: Willem de Bruijn <willemb@google.com>, lollipopkit <a@lolli.tech>,
	io-uring@vger.kernel.org, linux-kernel@vger.kernel.org,
	stable@vger.kernel.org
Subject: Re: [PATCH] io_uring/cmd_net: prevent infinite retry loop on unextractable timestamp skb
Date: Thu, 08 Oct 2026 07:59:16 -0700 (PDT)	[thread overview]
Message-ID: <6ac7afc4.cf15ae49.1a8a2a.2a55@mx.google.com> (raw)
In-Reply-To: <20b406ac-94ec-4b0f-a307-08082092ae08@gmail.com>

On Thu, Oct 8, 2026 at 3:43 PM Pavel Begunkov <asml.silence@gmail.com> wrote:
> Sounds fine since there are only timestamp skbs in this list, do
> you have a test case?

Hi Pavel,

Thanks for the review.

The issue was spotted during code inspection of the error handling path
in io_uring_cmd_timestamp(): specifically when skb_get_tx_timestamp() returns
a negative error (e.g. -ENOENT due to missing PHC bindings with
SOF_TIMESTAMPING_BIND_PHC or unavailable timestamp data). Since the
multishot apoll remains armed on EPOLLERR and the unhandled skb is spliced
back onto the head of sk_error_queue, it immediately re-triggers the command
in a tight busy-loop.

Below is a standalone test program demonstrating the TX_TIMESTAMP command
setup and execution with CQE32:

--- test_ts_cmd.c ---
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/net_tstamp.h>
#include <linux/io_uring.h>
#include <sys/syscall.h>
#include <sys/mman.h>

#define IORING_OP_URING_CMD 46
#define SOCKET_URING_OP_TX_TIMESTAMP 4
#define IORING_SETUP_CQE32 (1U << 11)
#define SOF_TIMESTAMPING_OPT_TSONLY (1 << 11)

int main(void)
{
	int s, r_sock, ring_fd, val;
	struct sockaddr_in r_sin;
	socklen_t r_len = sizeof(r_sin);
	struct io_uring_params p;
	void *sq_ptr, *cq_ptr;
	struct io_uring_sqe *sqes;
	struct io_uring_cqe *cqes;
	unsigned *sq_tail, *sq_array, *cq_head, *cq_tail;
	char dummy = 'A';

	/* Receiver socket */
	r_sock = socket(AF_INET, SOCK_DGRAM, 0);
	memset(&r_sin, 0, sizeof(r_sin));
	r_sin.sin_family = AF_INET;
	r_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
	bind(r_sock, (struct sockaddr *)&r_sin, sizeof(r_sin));
	getsockname(r_sock, (struct sockaddr *)&r_sin, &r_len);

	/* Sender socket with TX software timestamp */
	s = socket(AF_INET, SOCK_DGRAM, 0);
	val = SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_TX_SOFTWARE |
	      SOF_TIMESTAMPING_OPT_ID | SOF_TIMESTAMPING_OPT_TSONLY;
	setsockopt(s, SOL_SOCKET, SO_TIMESTAMPING, &val, sizeof(val));

	/* Send packet to queue timestamp skb into sk_error_queue */
	sendto(s, &dummy, sizeof(dummy), 0, (struct sockaddr *)&r_sin, sizeof(r_sin));
	usleep(10000);

	/* Initialize io_uring with CQE32 */
	memset(&p, 0, sizeof(p));
	p.flags = IORING_SETUP_CQE32;
	ring_fd = syscall(__NR_io_uring_setup, 4, &p);
	if (ring_fd < 0)
		return 1;

	sq_ptr = mmap(NULL, p.sq_off.array + p.sq_entries * sizeof(unsigned),
		      PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE,
		      ring_fd, IORING_OFF_SQ_RING);
	sqes = mmap(NULL, p.sq_entries * sizeof(struct io_uring_sqe),
		    PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE,
		    ring_fd, IORING_OFF_SQES);
	cq_ptr = mmap(NULL, p.cq_off.cqes + p.cq_entries * 2 * sizeof(struct io_uring_cqe),
		      PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE,
		      ring_fd, IORING_OFF_CQ_RING);

	sq_tail = (unsigned *)(sq_ptr + p.sq_off.tail);
	sq_array = (unsigned *)(sq_ptr + p.sq_off.array);
	cq_head = (unsigned *)(cq_ptr + p.cq_off.head);
	cq_tail = (unsigned *)(cq_ptr + p.cq_off.tail);

	memset(&sqes[0], 0, sizeof(struct io_uring_sqe));
	sqes[0].opcode = IORING_OP_URING_CMD;
	sqes[0].fd = s;
	sqes[0].cmd_op = SOCKET_URING_OP_TX_TIMESTAMP;

	sq_array[0] = 0;
	*sq_tail = 1;

	/* Submit command and wait for CQE */
	syscall(__NR_io_uring_enter, ring_fd, 1, 1, 1, NULL, 0);

	close(ring_fd);
	close(s);
	close(r_sock);
	return 0;
}
---

If desired, I can format this into a test case for liburing under
test/timestamp.c.

Thanks,
Bui Viet Dung

  reply	other threads:[~2026-10-08 14:59 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-08  5:07 [PATCH] io_uring/cmd_net: prevent infinite retry loop on unextractable timestamp skb Bui Viet Dung
2026-10-08 14:43 ` Pavel Begunkov
2026-10-08 14:59   ` Bui Viet Dung [this message]
2026-10-09 11:48     ` Pavel Begunkov

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=6ac7afc4.cf15ae49.1a8a2a.2a55@mx.google.com \
    --to=dungvn2345@gmail.com \
    --cc=a@lolli.tech \
    --cc=asml.silence@gmail.com \
    --cc=axboe@kernel.dk \
    --cc=io-uring@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=willemb@google.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.