Expand the BPF sockopt test to use also check for io_uring
{g,s}etsockopt commands operations.

Create infrastructure to run io_uring tests using the mini_liburing
helpers, so, the {g,s}etsockopt operation could either be called from
system calls, or, via io_uring.

Add a 'use_io_uring' parameter to run_test(), to specify if the test
should be run using io_uring if the parameter is set, or via the regular
system calls if false.

Call *all* tests twice, using the regular io_uring path, and the new
io_uring path.

Signed-off-by: Breno Leitao <lei...@debian.org>
---
 .../selftests/bpf/prog_tests/sockopt.c        | 95 +++++++++++++++++--
 1 file changed, 89 insertions(+), 6 deletions(-)

diff --git a/tools/testing/selftests/bpf/prog_tests/sockopt.c 
b/tools/testing/selftests/bpf/prog_tests/sockopt.c
index 9e6a5e3ed4de..40fb4c315ad9 100644
--- a/tools/testing/selftests/bpf/prog_tests/sockopt.c
+++ b/tools/testing/selftests/bpf/prog_tests/sockopt.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <test_progs.h>
+#include <io_uring/mini_liburing.h>
 #include "cgroup_helpers.h"
 
 static char bpf_log_buf[4096];
@@ -940,7 +941,85 @@ static int load_prog(const struct bpf_insn *insns,
        return fd;
 }
 
-static int run_test(int cgroup_fd, struct sockopt_test *test)
+/* Core function that handles io_uring ring initialization,
+ * sending SQE with sockopt command and waiting for the CQE.
+ */
+static int uring_sockopt(int op, int fd, int level, int optname,
+                        const void *optval, socklen_t *optlen)
+{
+       struct io_uring_cqe *cqe;
+       struct io_uring_sqe *sqe;
+       struct io_uring ring;
+       int err;
+
+       err = io_uring_queue_init(1, &ring, 0);
+       if (!ASSERT_OK(err, "Initialize io_uring ring"))
+               return err;
+
+       sqe = io_uring_get_sqe(&ring);
+       if (!ASSERT_NEQ(sqe, NULL, "Get an SQE")) {
+               err = -1;
+               goto fail;
+       }
+
+       if (op == SOCKET_URING_OP_GETSOCKOPT)
+               io_uring_prep_cmd_get(sqe, op, fd, level, optname, optval,
+                                     optlen);
+       else
+               io_uring_prep_cmd(sqe, op, fd, level, optname, optval,
+                                 *optlen);
+
+       err = io_uring_submit(&ring);
+       if (!ASSERT_EQ(err, 1, "Submit SQE"))
+               goto fail;
+
+       err = io_uring_wait_cqe(&ring, &cqe);
+       if (!ASSERT_OK(err, "Wait for CQE"))
+               goto fail;
+
+       err = cqe->res;
+
+fail:
+       io_uring_queue_exit(&ring);
+
+       return err;
+}
+
+static int uring_setsockopt(int fd, int level, int optname, const void *optval,
+                           socklen_t *optlen)
+{
+       return uring_sockopt(SOCKET_URING_OP_SETSOCKOPT, fd, level, optname,
+                            optval, optlen);
+}
+
+static int uring_getsockopt(int fd, int level, int optname, void *optval,
+                           socklen_t *optlen)
+{
+       return uring_sockopt(SOCKET_URING_OP_GETSOCKOPT, fd, level, optname,
+                            optval, optlen);
+}
+
+/* Execute the setsocktopt operation */
+static int call_setsockopt(bool use_io_uring, int fd, int level, int optname,
+                          const void *optval, socklen_t optlen)
+{
+       if (use_io_uring)
+               return uring_setsockopt(fd, level, optname, optval, &optlen);
+
+       return setsockopt(fd, level, optname, optval, optlen);
+}
+
+/* Execute the getsocktopt operation */
+static int call_getsockopt(bool use_io_uring, int fd, int level, int optname,
+                          void *optval, socklen_t *optlen)
+{
+       if (use_io_uring)
+               return uring_getsockopt(fd, level, optname, optval, optlen);
+
+       return getsockopt(fd, level, optname, optval, optlen);
+}
+
+static int run_test(int cgroup_fd, struct sockopt_test *test, bool 
use_io_uring)
 {
        int sock_fd, err, prog_fd;
        void *optval = NULL;
@@ -980,8 +1059,9 @@ static int run_test(int cgroup_fd, struct sockopt_test 
*test)
                        test->set_optlen = num_pages * sysconf(_SC_PAGESIZE) + 
remainder;
                }
 
-               err = setsockopt(sock_fd, test->set_level, test->set_optname,
-                                test->set_optval, test->set_optlen);
+               err = call_setsockopt(use_io_uring, sock_fd, test->set_level,
+                                     test->set_optname, test->set_optval,
+                                     test->set_optlen);
                if (err) {
                        if (errno == EPERM && test->error == EPERM_SETSOCKOPT)
                                goto close_sock_fd;
@@ -1008,8 +1088,8 @@ static int run_test(int cgroup_fd, struct sockopt_test 
*test)
                socklen_t expected_get_optlen = test->get_optlen_ret ?:
                        test->get_optlen;
 
-               err = getsockopt(sock_fd, test->get_level, test->get_optname,
-                                optval, &optlen);
+               err = call_getsockopt(use_io_uring, sock_fd, test->get_level,
+                                     test->get_optname, optval, &optlen);
                if (err) {
                        if (errno == EOPNOTSUPP && test->error == 
EOPNOTSUPP_GETSOCKOPT)
                                goto free_optval;
@@ -1063,7 +1143,10 @@ void test_sockopt(void)
                if (!test__start_subtest(tests[i].descr))
                        continue;
 
-               ASSERT_OK(run_test(cgroup_fd, &tests[i]), tests[i].descr);
+               ASSERT_OK(run_test(cgroup_fd, &tests[i], false),
+                         tests[i].descr);
+               ASSERT_OK(run_test(cgroup_fd, &tests[i], true),
+                         tests[i].descr);
        }
 
        close(cgroup_fd);
-- 
2.34.1

Reply via email to