From nobody Thu Dec 18 03:20:22 2025 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5205E33A013; Fri, 31 Oct 2025 08:05:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761897923; cv=none; b=MuA3GBaHEpGqHM+jK39keTBsBZDylz8XDRfzCB3RiTaKjQzElntgxNYyV4DDHqNy3nWj21NrrCfG+I3zift8vGVNXVun3A6ZLesaiA7zc2AyFzVGu7vb29oB5n8PapJCdCf8sdujoRhcZHlgjUHXJvDx2V6mov14mtpYmRNuARA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761897923; c=relaxed/simple; bh=7rIR5Fb4Tu+IiTrlnjeB13fpGdwhLzRA66oc10X4ihI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=UcevhTGP5/1rRrI2GL1KHorxRTpDCB26pH7FDnXljUpl6CEBMnm4fBrL63UX9irhCX7p2rFG0liknpwSbErEoOwIOSGAEjWjCZqfqwEsWLjUPFiJ6FRMS+2xUOZeHqsCGJ/GB4+MfblpF0+JnT5EXRwyMsNXGBlbjzFQ6QEjn0s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=uWjUblSN; arc=none smtp.client-ip=185.246.84.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="uWjUblSN" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id 0D3FE1A16F8; Fri, 31 Oct 2025 08:05:20 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id D712960704; Fri, 31 Oct 2025 08:05:19 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id EBFC21180FB67; Fri, 31 Oct 2025 09:05:15 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1761897918; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=ra/hdL7bFIx0FXATbz6DjwLlrQ186mo6Jj+Z+L+pjHs=; b=uWjUblSNs/loDBpLX9IKrpYUCgbdwCW6977fYoPj0aZFiNyRWEPCVp/xlTcowjEugjbSM+ MBAmmVve+Bk+lpcjcQygQzGUsG3HBhVUZWZ6oXFW48oZjQLoBxDOeFmvg0T2vJr6deVRzs eH3ztGr74d434ROHrDJwh3SYZnc0iBUoJtA9GdSKBRr550cVJh+ucAP9uyNkg7jEqCh7TE WetyVXLkOT14niJ/Fp0vx59tgWYrt7JZYTcTVO9IpGRMGJw1rND4UWrPitUx+pgYzL7dvg SVX3aRl0A3Bg1tnleku73Xbqnxcu1CjCb1yTf+kRrKbVOYXlWwM5CMgPQpXRpw== From: "Bastien Curutchet (eBPF Foundation)" Date: Fri, 31 Oct 2025 09:04:47 +0100 Subject: [PATCH bpf-next v7 11/15] selftests/bpf: test_xsk: Don't exit immediately when workers fail Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251031-xsk-v7-11-39fe486593a3@bootlin.com> References: <20251031-xsk-v7-0-39fe486593a3@bootlin.com> In-Reply-To: <20251031-xsk-v7-0-39fe486593a3@bootlin.com> To: =?utf-8?q?Bj=C3=B6rn_T=C3=B6pel?= , Magnus Karlsson , Maciej Fijalkowski , Jonathan Lemon , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Mykola Lysenko , Shuah Khan , "David S. Miller" , Jakub Kicinski , Jesper Dangaard Brouer Cc: Thomas Petazzoni , Alexis Lothore , netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, "Bastien Curutchet (eBPF Foundation)" X-Mailer: b4 0.14.2 X-Last-TLS-Session-Version: TLSv1.3 TX and RX workers can fail in many places. These failures trigger a call to exit_with_error() which exits the program immediately. It prevents the following tests from running and isn't compliant with the CI. Add return value to functions that can fail. Handle failures more smoothly through report_failure(). Reviewed-by: Maciej Fijalkowski Signed-off-by: Bastien Curutchet (eBPF Foundation) --- tools/testing/selftests/bpf/test_xsk.c | 110 +++++++++++++++++++++++------= ---- 1 file changed, 76 insertions(+), 34 deletions(-) diff --git a/tools/testing/selftests/bpf/test_xsk.c b/tools/testing/selftes= ts/bpf/test_xsk.c index 2c955e1099439c377cd28f5a9be2a17e65d49f78..19182c1d9730191276084acd35d= a7118780b273e 100644 --- a/tools/testing/selftests/bpf/test_xsk.c +++ b/tools/testing/selftests/bpf/test_xsk.c @@ -132,24 +132,26 @@ static void umem_reset_alloc(struct xsk_umem_info *um= em) umem->next_buffer =3D 0; } =20 -static void enable_busy_poll(struct xsk_socket_info *xsk) +static int enable_busy_poll(struct xsk_socket_info *xsk) { int sock_opt; =20 sock_opt =3D 1; if (setsockopt(xsk_socket__fd(xsk->xsk), SOL_SOCKET, SO_PREFER_BUSY_POLL, (void *)&sock_opt, sizeof(sock_opt)) < 0) - exit_with_error(errno); + return -errno; =20 sock_opt =3D 20; if (setsockopt(xsk_socket__fd(xsk->xsk), SOL_SOCKET, SO_BUSY_POLL, (void *)&sock_opt, sizeof(sock_opt)) < 0) - exit_with_error(errno); + return -errno; =20 sock_opt =3D xsk->batch_size; if (setsockopt(xsk_socket__fd(xsk->xsk), SOL_SOCKET, SO_BUSY_POLL_BUDGET, (void *)&sock_opt, sizeof(sock_opt)) < 0) - exit_with_error(errno); + return -errno; + + return 0; } =20 int xsk_configure_socket(struct xsk_socket_info *xsk, struct xsk_umem_info= *umem, @@ -759,7 +761,7 @@ static bool is_metadata_correct(struct pkt *pkt, void *= buffer, u64 addr) return true; } =20 -static bool is_adjust_tail_supported(struct xsk_xdp_progs *skel_rx) +static int is_adjust_tail_supported(struct xsk_xdp_progs *skel_rx, bool *s= upported) { struct bpf_map *data_map; int adjust_value =3D 0; @@ -769,19 +771,21 @@ static bool is_adjust_tail_supported(struct xsk_xdp_p= rogs *skel_rx) data_map =3D bpf_object__find_map_by_name(skel_rx->obj, "xsk_xdp_.bss"); if (!data_map || !bpf_map__is_internal(data_map)) { ksft_print_msg("Error: could not find bss section of XDP program\n"); - exit_with_error(errno); + return -EINVAL; } =20 ret =3D bpf_map_lookup_elem(bpf_map__fd(data_map), &key, &adjust_value); if (ret) { ksft_print_msg("Error: bpf_map_lookup_elem failed with error %d\n", ret); - exit_with_error(errno); + return ret; } =20 /* Set the 'adjust_value' variable to -EOPNOTSUPP in the XDP program if t= he adjust_tail * helper is not supported. Skip the adjust_tail test case in this scenar= io. */ - return adjust_value !=3D -EOPNOTSUPP; + *supported =3D adjust_value !=3D -EOPNOTSUPP; + + return 0; } =20 static bool is_frag_valid(struct xsk_umem_info *umem, u64 addr, u32 len, u= 32 expected_pkt_nb, @@ -1433,7 +1437,7 @@ static int validate_tx_invalid_descs(struct ifobject = *ifobject) return TEST_PASS; } =20 -static void xsk_configure(struct test_spec *test, struct ifobject *ifobjec= t, +static int xsk_configure(struct test_spec *test, struct ifobject *ifobject, struct xsk_umem_info *umem, bool tx) { int i, ret; @@ -1450,24 +1454,34 @@ static void xsk_configure(struct test_spec *test, s= truct ifobject *ifobject, =20 /* Retry if it fails as xsk_socket__create() is asynchronous */ if (ctr >=3D SOCK_RECONF_CTR) - exit_with_error(-ret); + return ret; usleep(USLEEP_MAX); } - if (ifobject->busy_poll) - enable_busy_poll(&ifobject->xsk_arr[i]); + if (ifobject->busy_poll) { + ret =3D enable_busy_poll(&ifobject->xsk_arr[i]); + if (ret) + return ret; + } } + + return 0; } =20 -static void thread_common_ops_tx(struct test_spec *test, struct ifobject *= ifobject) +static int thread_common_ops_tx(struct test_spec *test, struct ifobject *i= fobject) { - xsk_configure(test, ifobject, test->ifobj_rx->umem, true); + int ret =3D xsk_configure(test, ifobject, test->ifobj_rx->umem, true); + + if (ret) + return ret; ifobject->xsk =3D &ifobject->xsk_arr[0]; ifobject->xskmap =3D test->ifobj_rx->xskmap; memcpy(ifobject->umem, test->ifobj_rx->umem, sizeof(struct xsk_umem_info)= ); ifobject->umem->base_addr =3D 0; + + return 0; } =20 -static void xsk_populate_fill_ring(struct xsk_umem_info *umem, struct pkt_= stream *pkt_stream, +static int xsk_populate_fill_ring(struct xsk_umem_info *umem, struct pkt_s= tream *pkt_stream, bool fill_up) { u32 rx_frame_size =3D umem->frame_size - XDP_PACKET_HEADROOM; @@ -1481,7 +1495,7 @@ static void xsk_populate_fill_ring(struct xsk_umem_in= fo *umem, struct pkt_stream =20 ret =3D xsk_ring_prod__reserve(&umem->fq, buffers_to_fill, &idx); if (ret !=3D buffers_to_fill) - exit_with_error(ENOSPC); + return -ENOSPC; =20 while (filled < buffers_to_fill) { struct pkt *pkt =3D pkt_stream_get_next_rx_pkt(pkt_stream, &nb_pkts); @@ -1509,9 +1523,11 @@ static void xsk_populate_fill_ring(struct xsk_umem_i= nfo *umem, struct pkt_stream =20 pkt_stream_reset(pkt_stream); umem_reset_alloc(umem); + + return 0; } =20 -static void thread_common_ops(struct test_spec *test, struct ifobject *ifo= bject) +static int thread_common_ops(struct test_spec *test, struct ifobject *ifob= ject) { LIBBPF_OPTS(bpf_xdp_query_opts, opts); int mmap_flags; @@ -1531,27 +1547,34 @@ static void thread_common_ops(struct test_spec *tes= t, struct ifobject *ifobject) =20 bufs =3D mmap(NULL, umem_sz, PROT_READ | PROT_WRITE, mmap_flags, -1, 0); if (bufs =3D=3D MAP_FAILED) - exit_with_error(errno); + return -errno; =20 ret =3D xsk_configure_umem(ifobject, ifobject->umem, bufs, umem_sz); if (ret) - exit_with_error(-ret); + return ret; =20 - xsk_configure(test, ifobject, ifobject->umem, false); + ret =3D xsk_configure(test, ifobject, ifobject->umem, false); + if (ret) + return ret; =20 ifobject->xsk =3D &ifobject->xsk_arr[0]; =20 if (!ifobject->rx_on) - return; + return 0; =20 - xsk_populate_fill_ring(ifobject->umem, ifobject->xsk->pkt_stream, ifobjec= t->use_fill_ring); + ret =3D xsk_populate_fill_ring(ifobject->umem, ifobject->xsk->pkt_stream, + ifobject->use_fill_ring); + if (ret) + return ret; =20 for (i =3D 0; i < test->nb_sockets; i++) { ifobject->xsk =3D &ifobject->xsk_arr[i]; ret =3D xsk_update_xskmap(ifobject->xskmap, ifobject->xsk->xsk, i); if (ret) - exit_with_error(errno); + return ret; } + + return 0; } =20 void *worker_testapp_validate_tx(void *arg) @@ -1561,10 +1584,17 @@ void *worker_testapp_validate_tx(void *arg) int err; =20 if (test->current_step =3D=3D 1) { - if (!ifobject->shared_umem) - thread_common_ops(test, ifobject); - else - thread_common_ops_tx(test, ifobject); + if (!ifobject->shared_umem) { + if (thread_common_ops(test, ifobject)) { + test->fail =3D true; + pthread_exit(NULL); + } + } else { + if (thread_common_ops_tx(test, ifobject)) { + test->fail =3D true; + pthread_exit(NULL); + } + } } =20 err =3D send_pkts(test, ifobject); @@ -1584,29 +1614,41 @@ void *worker_testapp_validate_rx(void *arg) int err; =20 if (test->current_step =3D=3D 1) { - thread_common_ops(test, ifobject); + err =3D thread_common_ops(test, ifobject); } else { xsk_clear_xskmap(ifobject->xskmap); err =3D xsk_update_xskmap(ifobject->xskmap, ifobject->xsk->xsk, 0); - if (err) { + if (err) ksft_print_msg("Error: Failed to update xskmap, error %s\n", strerror(-err)); - exit_with_error(-err); - } } =20 pthread_barrier_wait(&barr); =20 + /* We leave only now in case of error to avoid getting stuck in the barri= er */ + if (err) { + test->fail =3D true; + pthread_exit(NULL); + } + err =3D receive_pkts(test); =20 if (!err && ifobject->validation_func) err =3D ifobject->validation_func(ifobject); =20 if (err) { - if (test->adjust_tail && !is_adjust_tail_supported(ifobject->xdp_progs)) - test->adjust_tail_support =3D false; - else + if (!test->adjust_tail) { test->fail =3D true; + } else { + bool supported; + + if (is_adjust_tail_supported(ifobject->xdp_progs, &supported)) + test->fail =3D true; + else if (!supported) + test->adjust_tail_support =3D false; + else + test->fail =3D true; + } } =20 pthread_exit(NULL); --=20 2.51.0