selftests/bpf: Fix a CI failure caused by vsock write
authorXu Kuohai <xukuohai@huawei.com>
Fri, 1 Sep 2023 03:10:37 +0000 (11:10 +0800)
committerDaniel Borkmann <daniel@iogearbox.net>
Fri, 1 Sep 2023 08:56:00 +0000 (10:56 +0200)
While commit 90f0074cd9f9 ("selftests/bpf: fix a CI failure caused by vsock sockmap test")
fixes a receive failure of vsock sockmap test, there is still a write failure:

Error: #211/79 sockmap_listen/sockmap VSOCK test_vsock_redir
Error: #211/79 sockmap_listen/sockmap VSOCK test_vsock_redir
  ./test_progs:vsock_unix_redir_connectible:1501: egress: write: Transport endpoint is not connected
  vsock_unix_redir_connectible:FAIL:1501
  ./test_progs:vsock_unix_redir_connectible:1501: ingress: write: Transport endpoint is not connected
  vsock_unix_redir_connectible:FAIL:1501
  ./test_progs:vsock_unix_redir_connectible:1501: egress: write: Transport endpoint is not connected
  vsock_unix_redir_connectible:FAIL:1501

The reason is that the vsock connection in the test is set to ESTABLISHED state
by function virtio_transport_recv_pkt, which is executed in a workqueue thread,
so when the user space test thread runs before the workqueue thread, this
problem occurs.

To fix it, before writing the connection, wait for it to be connected.

Fixes: d61bd8c1fd02 ("selftests/bpf: add a test case for vsock sockmap")
Signed-off-by: Xu Kuohai <xukuohai@huawei.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20230901031037.3314007-1-xukuohai@huaweicloud.com
tools/testing/selftests/bpf/prog_tests/sockmap_helpers.h
tools/testing/selftests/bpf/prog_tests/sockmap_listen.c

index d12665490a905ffbaccb6eb85c3344fc43e86f7a..36d829a65aa44a70991e124a485ae5e4160f0e7d 100644 (file)
                __ret;                                                         \
        })
 
+static inline int poll_connect(int fd, unsigned int timeout_sec)
+{
+       struct timeval timeout = { .tv_sec = timeout_sec };
+       fd_set wfds;
+       int r, eval;
+       socklen_t esize = sizeof(eval);
+
+       FD_ZERO(&wfds);
+       FD_SET(fd, &wfds);
+
+       r = select(fd + 1, NULL, &wfds, NULL, &timeout);
+       if (r == 0)
+               errno = ETIME;
+       if (r != 1)
+               return -1;
+
+       if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &eval, &esize) < 0)
+               return -1;
+       if (eval != 0) {
+               errno = eval;
+               return -1;
+       }
+
+       return 0;
+}
+
 static inline int poll_read(int fd, unsigned int timeout_sec)
 {
        struct timeval timeout = { .tv_sec = timeout_sec };
index 5674a9d0cacf0e5b7b216e88064224b8b9ab047f..8df8cbb447f10f21dd8f2a4f61637668c38f40db 100644 (file)
@@ -1452,11 +1452,18 @@ static int vsock_socketpair_connectible(int sotype, int *v0, int *v1)
        if (p < 0)
                goto close_cli;
 
+       if (poll_connect(c, IO_TIMEOUT_SEC) < 0) {
+               FAIL_ERRNO("poll_connect");
+               goto close_acc;
+       }
+
        *v0 = p;
        *v1 = c;
 
        return 0;
 
+close_acc:
+       close(p);
 close_cli:
        close(c);
 close_srv: