Re: [net-next,v6,5/6] selftests: net: add multithread server support to iou-zcrx
From: Bobby Eshleman
Date: Wed Sep 09 2026 - 12:29:41 EST
On Wed, Sep 02, 2026 at 11:38:17PM +0000, netdev-bot+sashiko@xxxxxxxxxx wrote:
> Thank you for your contribution! Sashiko AI review found 6 potential
> issue(s) to consider:
>
[...]
> > @@ -356,29 +444,68 @@ static void run_server(void)
> > if (ret < 0)
> > error(1, 0, "bind()");
> >
> > - flags |= IORING_SETUP_COOP_TASKRUN;
> > - flags |= IORING_SETUP_SINGLE_ISSUER;
> > - flags |= IORING_SETUP_DEFER_TASKRUN;
> > - flags |= IORING_SETUP_SUBMIT_ALL;
> > - flags |= IORING_SETUP_CQE32;
> > + pthread_barrier_init(&setup_done, NULL, cfg_num_threads + 1);
> > + pthread_barrier_init(&dispatch_done, NULL, cfg_num_threads + 1);
> > +
> > + for (i = 0; i < cfg_num_threads; i++) {
> > + ctxs[i].queue_id = cfg_queue_id + i;
> > + ctxs[i].setup_done = &setup_done;
> > + ctxs[i].dispatch_done = &dispatch_done;
> > + }
> >
> > - io_uring_queue_init(512, &ctx.ring, flags);
> > + for (i = 0; i < cfg_num_threads; i++) {
> > + ret = pthread_create(&threads[i], NULL,
> > + server_worker, &ctxs[i]);
> > + if (ret)
> > + error(1, ret, "pthread_create()");
> > + }
> >
> > - setup_zcrx(&ctx);
> > if (cfg_dry_run)
> > - return;
> > + goto join;
> >
> > if (listen(fd, 1024) < 0)
> > error(1, 0, "listen()");
> >
> > - add_accept(&ctx, fd);
> > + pthread_barrier_wait(&setup_done);
>
> [Severity: High]
> Is the listen() intentionally moved before the workers have registered
> their ifqs? The main thread creates the threads, calls listen(), and only
> then waits on setup_done, while the workers reach that barrier after
> io_uring_queue_init_params() plus setup_zcrx(), i.e. after
> io_uring_register_ifq() has restarted the device RX queue.
>
> Before the patch the sequence was serialized in one thread:
>
> io_uring_queue_init(512, &ctx.ring, flags);
> setup_zcrx(&ctx);
> ...
> listen(fd, 1024);
>
> so the port only became visible once the memory provider was installed.
>
> Two existing tests depend on that ordering. wait_port_listen() in
> net/lib/py/utils.py polls every 5 ms, so it can now return while
> registration is still in flight:
>
> iou-zcrx.py:test_zcrx_large_chunks() {
> wait_port_listen(cfg.port, proto="tcp")
>
> check_iou_rx_buf_len(cfg, rx_buf_len)
> }
>
> check_iou_rx_buf_len() raises "Expected 1 io-uring page pool, found 0",
> and nk_qlease.py:test_destroy() does queue_get() plus
> ksft_in("io-uring", queue_info) immediately after wait_port_listen() with
> no sleep.
>
> Beyond the harness races, data delivered into the queue before the
> provider exists is serviced by the copy fallback rather than zero copy,
> and the queue restart during registration can drop in-flight frames.
>
> Would moving listen() below pthread_barrier_wait(&setup_done) restore the
> previous guarantee?
Just a heads up that I tested this on BRCM and did find this listen()
ordering issue to cause genuine (but flaky) regression for
nk_qlease.test_destroy. Moving the listen() to after wait(setup_done)
indeed fixed it.
Best,
Bobby