11// SPDX-License-Identifier: GPL-2.0
22#include <test_progs.h>
3+ #include <io_uring/mini_liburing.h>
34#include "cgroup_helpers.h"
45
56static char bpf_log_buf [4096 ];
@@ -38,6 +39,7 @@ static struct sockopt_test {
3839 socklen_t get_optlen_ret ;
3940
4041 enum sockopt_test_error error ;
42+ bool io_uring_support ;
4143} tests [] = {
4244
4345 /* ==================== getsockopt ==================== */
@@ -251,7 +253,9 @@ static struct sockopt_test {
251253 .attach_type = BPF_CGROUP_GETSOCKOPT ,
252254 .expected_attach_type = BPF_CGROUP_GETSOCKOPT ,
253255
256+ .get_level = SOL_SOCKET ,
254257 .get_optlen = 64 ,
258+ .io_uring_support = true,
255259 },
256260 {
257261 .descr = "getsockopt: deny bigger ctx->optlen" ,
@@ -276,6 +280,7 @@ static struct sockopt_test {
276280 .get_optlen = 64 ,
277281
278282 .error = EFAULT_GETSOCKOPT ,
283+ .io_uring_support = true,
279284 },
280285 {
281286 .descr = "getsockopt: ignore >PAGE_SIZE optlen" ,
@@ -318,6 +323,7 @@ static struct sockopt_test {
318323 .get_optval = {}, /* the changes are ignored */
319324 .get_optlen = PAGE_SIZE + 1 ,
320325 .error = EOPNOTSUPP_GETSOCKOPT ,
326+ .io_uring_support = true,
321327 },
322328 {
323329 .descr = "getsockopt: support smaller ctx->optlen" ,
@@ -337,8 +343,10 @@ static struct sockopt_test {
337343 .attach_type = BPF_CGROUP_GETSOCKOPT ,
338344 .expected_attach_type = BPF_CGROUP_GETSOCKOPT ,
339345
346+ .get_level = SOL_SOCKET ,
340347 .get_optlen = 64 ,
341348 .get_optlen_ret = 32 ,
349+ .io_uring_support = true,
342350 },
343351 {
344352 .descr = "getsockopt: deny writing to ctx->optval" ,
@@ -518,6 +526,7 @@ static struct sockopt_test {
518526 .set_level = 123 ,
519527
520528 .set_optlen = 1 ,
529+ .io_uring_support = true,
521530 },
522531 {
523532 .descr = "setsockopt: allow changing ctx->level" ,
@@ -572,6 +581,7 @@ static struct sockopt_test {
572581 .set_optname = 123 ,
573582
574583 .set_optlen = 1 ,
584+ .io_uring_support = true,
575585 },
576586 {
577587 .descr = "setsockopt: allow changing ctx->optname" ,
@@ -624,6 +634,7 @@ static struct sockopt_test {
624634 .expected_attach_type = BPF_CGROUP_SETSOCKOPT ,
625635
626636 .set_optlen = 64 ,
637+ .io_uring_support = true,
627638 },
628639 {
629640 .descr = "setsockopt: ctx->optlen == -1 is ok" ,
@@ -640,6 +651,7 @@ static struct sockopt_test {
640651 .expected_attach_type = BPF_CGROUP_SETSOCKOPT ,
641652
642653 .set_optlen = 64 ,
654+ .io_uring_support = true,
643655 },
644656 {
645657 .descr = "setsockopt: deny ctx->optlen < 0 (except -1)" ,
@@ -658,6 +670,7 @@ static struct sockopt_test {
658670 .set_optlen = 4 ,
659671
660672 .error = EFAULT_SETSOCKOPT ,
673+ .io_uring_support = true,
661674 },
662675 {
663676 .descr = "setsockopt: deny ctx->optlen > input optlen" ,
@@ -675,6 +688,7 @@ static struct sockopt_test {
675688 .set_optlen = 64 ,
676689
677690 .error = EFAULT_SETSOCKOPT ,
691+ .io_uring_support = true,
678692 },
679693 {
680694 .descr = "setsockopt: ignore >PAGE_SIZE optlen" ,
@@ -940,7 +954,89 @@ static int load_prog(const struct bpf_insn *insns,
940954 return fd ;
941955}
942956
943- static int run_test (int cgroup_fd , struct sockopt_test * test )
957+ /* Core function that handles io_uring ring initialization,
958+ * sending SQE with sockopt command and waiting for the CQE.
959+ */
960+ static int uring_sockopt (int op , int fd , int level , int optname ,
961+ const void * optval , socklen_t optlen )
962+ {
963+ struct io_uring_cqe * cqe ;
964+ struct io_uring_sqe * sqe ;
965+ struct io_uring ring ;
966+ int err ;
967+
968+ err = io_uring_queue_init (1 , & ring , 0 );
969+ if (!ASSERT_OK (err , "io_uring initialization" ))
970+ return err ;
971+
972+ sqe = io_uring_get_sqe (& ring );
973+ if (!ASSERT_NEQ (sqe , NULL , "Get an SQE" )) {
974+ err = -1 ;
975+ goto fail ;
976+ }
977+
978+ io_uring_prep_cmd (sqe , op , fd , level , optname , optval , optlen );
979+
980+ err = io_uring_submit (& ring );
981+ if (!ASSERT_EQ (err , 1 , "Submit SQE" ))
982+ goto fail ;
983+
984+ err = io_uring_wait_cqe (& ring , & cqe );
985+ if (!ASSERT_OK (err , "Wait for CQE" ))
986+ goto fail ;
987+
988+ err = cqe -> res ;
989+
990+ fail :
991+ io_uring_queue_exit (& ring );
992+
993+ return err ;
994+ }
995+
996+ static int uring_setsockopt (int fd , int level , int optname , const void * optval ,
997+ socklen_t optlen )
998+ {
999+ return uring_sockopt (SOCKET_URING_OP_SETSOCKOPT , fd , level , optname ,
1000+ optval , optlen );
1001+ }
1002+
1003+ static int uring_getsockopt (int fd , int level , int optname , void * optval ,
1004+ socklen_t * optlen )
1005+ {
1006+ int ret = uring_sockopt (SOCKET_URING_OP_GETSOCKOPT , fd , level , optname ,
1007+ optval , * optlen );
1008+ if (ret < 0 )
1009+ return ret ;
1010+
1011+ /* Populate optlen back to be compatible with systemcall interface,
1012+ * and simplify the test.
1013+ */
1014+ * optlen = ret ;
1015+
1016+ return 0 ;
1017+ }
1018+
1019+ /* Execute the setsocktopt operation */
1020+ static int call_setsockopt (bool use_io_uring , int fd , int level , int optname ,
1021+ const void * optval , socklen_t optlen )
1022+ {
1023+ if (use_io_uring )
1024+ return uring_setsockopt (fd , level , optname , optval , optlen );
1025+
1026+ return setsockopt (fd , level , optname , optval , optlen );
1027+ }
1028+
1029+ /* Execute the getsocktopt operation */
1030+ static int call_getsockopt (bool use_io_uring , int fd , int level , int optname ,
1031+ void * optval , socklen_t * optlen )
1032+ {
1033+ if (use_io_uring )
1034+ return uring_getsockopt (fd , level , optname , optval , optlen );
1035+
1036+ return getsockopt (fd , level , optname , optval , optlen );
1037+ }
1038+
1039+ static int run_test (int cgroup_fd , struct sockopt_test * test , bool use_io_uring )
9441040{
9451041 int sock_fd , err , prog_fd ;
9461042 void * optval = NULL ;
@@ -980,8 +1076,9 @@ static int run_test(int cgroup_fd, struct sockopt_test *test)
9801076 test -> set_optlen = num_pages * sysconf (_SC_PAGESIZE ) + remainder ;
9811077 }
9821078
983- err = setsockopt (sock_fd , test -> set_level , test -> set_optname ,
984- test -> set_optval , test -> set_optlen );
1079+ err = call_setsockopt (use_io_uring , sock_fd , test -> set_level ,
1080+ test -> set_optname , test -> set_optval ,
1081+ test -> set_optlen );
9851082 if (err ) {
9861083 if (errno == EPERM && test -> error == EPERM_SETSOCKOPT )
9871084 goto close_sock_fd ;
@@ -1008,8 +1105,8 @@ static int run_test(int cgroup_fd, struct sockopt_test *test)
10081105 socklen_t expected_get_optlen = test -> get_optlen_ret ?:
10091106 test -> get_optlen ;
10101107
1011- err = getsockopt ( sock_fd , test -> get_level , test -> get_optname ,
1012- optval , & optlen );
1108+ err = call_getsockopt ( use_io_uring , sock_fd , test -> get_level ,
1109+ test -> get_optname , optval , & optlen );
10131110 if (err ) {
10141111 if (errno == EOPNOTSUPP && test -> error == EOPNOTSUPP_GETSOCKOPT )
10151112 goto free_optval ;
@@ -1063,7 +1160,11 @@ void test_sockopt(void)
10631160 if (!test__start_subtest (tests [i ].descr ))
10641161 continue ;
10651162
1066- ASSERT_OK (run_test (cgroup_fd , & tests [i ]), tests [i ].descr );
1163+ ASSERT_OK (run_test (cgroup_fd , & tests [i ], false),
1164+ tests [i ].descr );
1165+ if (tests [i ].io_uring_support )
1166+ ASSERT_OK (run_test (cgroup_fd , & tests [i ], true),
1167+ tests [i ].descr );
10671168 }
10681169
10691170 close (cgroup_fd );
0 commit comments