Skip to content

Commit f485295

Browse files
mrpreKernel Patches Daemon
authored andcommitted
selftests/bpf: add splice_read tests for sockmap
Add splice_read coverage to sockmap_basic and sockmap_strp selftests. Each test suite now runs twice: once with normal recv_timeout() and once with splice-based reads, verifying that data read via splice(2) through a pipe produces identical results. A recv_timeout_with_splice() helper is added to sockmap_helpers.h that creates a temporary pipe, splices data from the socket into the pipe, then reads from the pipe into the user buffer. MSG_PEEK calls fall back to native recv since splice does not support peek. Non-TCP sockets also fall back to native recv. The splice subtests are distinguished by appending " splice" to each subtest name via a test__start_subtest macro override. ./test_progs -a sockmap_* ... Summary: 5/830 PASSED, 0 SKIPPED, 0 FAILED Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
1 parent 49500ad commit f485295

File tree

3 files changed

+116
-2
lines changed

3 files changed

+116
-2
lines changed

tools/testing/selftests/bpf/prog_tests/sockmap_basic.c

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,23 @@
1818

1919
#include "sockmap_helpers.h"
2020

21+
static bool use_splice;
22+
23+
static bool __start_subtest(const char *name)
24+
{
25+
if (!use_splice)
26+
return (test__start_subtest)(name);
27+
28+
char buf[MAX_TEST_NAME];
29+
30+
snprintf(buf, sizeof(buf), "%s splice", name);
31+
return (test__start_subtest)(buf);
32+
}
33+
34+
#define test__start_subtest(name) __start_subtest(name)
35+
#define recv_timeout(fd, buf, len, flags, timeout) \
36+
recv_timeout_with_splice(fd, buf, len, flags, timeout, use_splice)
37+
2138
#define TCP_REPAIR 19 /* TCP sock is under repair right now */
2239

2340
#define TCP_REPAIR_ON 1
@@ -1314,7 +1331,7 @@ static void test_sockmap_multi_channels(int sotype)
13141331
test_sockmap_pass_prog__destroy(skel);
13151332
}
13161333

1317-
void test_sockmap_basic(void)
1334+
static void __test_sockmap_basic(void)
13181335
{
13191336
if (test__start_subtest("sockmap create_update_free"))
13201337
test_sockmap_create_update_free(BPF_MAP_TYPE_SOCKMAP);
@@ -1391,3 +1408,12 @@ void test_sockmap_basic(void)
13911408
if (test__start_subtest("sockmap udp multi channels"))
13921409
test_sockmap_multi_channels(SOCK_DGRAM);
13931410
}
1411+
1412+
void test_sockmap_basic(void)
1413+
{
1414+
use_splice = false;
1415+
__test_sockmap_basic();
1416+
1417+
use_splice = true;
1418+
__test_sockmap_basic();
1419+
}

tools/testing/selftests/bpf/prog_tests/sockmap_helpers.h

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,66 @@ static inline int add_to_sockmap(int mapfd, int fd1, int fd2)
8080
return xbpf_map_update_elem(mapfd, &u32(1), &u64(fd2), BPF_NOEXIST);
8181
}
8282

83+
static inline ssize_t recv_timeout_with_splice(int fd, void *buf, size_t len,
84+
int flags,
85+
unsigned int timeout_sec,
86+
bool do_splice)
87+
{
88+
ssize_t total = 0;
89+
int pipefd[2];
90+
int fl;
91+
92+
int sotype, protocol;
93+
socklen_t optlen = sizeof(sotype);
94+
95+
if (!do_splice || (flags & MSG_PEEK) ||
96+
getsockopt(fd, SOL_SOCKET, SO_TYPE, &sotype, &optlen) ||
97+
sotype != SOCK_STREAM ||
98+
getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &protocol, &optlen) ||
99+
protocol != IPPROTO_TCP)
100+
return recv_timeout(fd, buf, len, flags, timeout_sec);
101+
102+
if (poll_read(fd, timeout_sec))
103+
return -1;
104+
105+
if (pipe(pipefd) < 0)
106+
return -1;
107+
108+
/*
109+
* tcp_splice_read() only checks sock->file->f_flags for
110+
* O_NONBLOCK, ignoring SPLICE_F_NONBLOCK for the socket
111+
* side timeout. Set O_NONBLOCK on the fd so the loop won't
112+
* block forever when no more data is available.
113+
*/
114+
fl = fcntl(fd, F_GETFL);
115+
fcntl(fd, F_SETFL, fl | O_NONBLOCK);
116+
117+
/*
118+
* Pipe has limited buffer slots (default 16), so a single
119+
* splice may not transfer all requested bytes. Loop until
120+
* we've read enough or no more data is available.
121+
*/
122+
while (total < (ssize_t)len) {
123+
ssize_t spliced, n;
124+
125+
spliced = splice(fd, NULL, pipefd[1], NULL, len - total,
126+
SPLICE_F_NONBLOCK);
127+
if (spliced <= 0)
128+
break;
129+
130+
n = read(pipefd[0], buf + total, spliced);
131+
if (n <= 0)
132+
break;
133+
134+
total += n;
135+
}
136+
137+
fcntl(fd, F_SETFL, fl);
138+
139+
close(pipefd[0]);
140+
close(pipefd[1]);
141+
142+
return total > 0 ? total : -1;
143+
}
144+
83145
#endif // __SOCKMAP_HELPERS__

tools/testing/selftests/bpf/prog_tests/sockmap_strp.c

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,23 @@
66
#include "test_skmsg_load_helpers.skel.h"
77
#include "test_sockmap_strp.skel.h"
88

9+
static bool use_splice;
10+
11+
static bool __start_subtest(const char *name)
12+
{
13+
if (!use_splice)
14+
return (test__start_subtest)(name);
15+
16+
char buf[MAX_TEST_NAME];
17+
18+
snprintf(buf, sizeof(buf), "%s splice", name);
19+
return (test__start_subtest)(buf);
20+
}
21+
22+
#define test__start_subtest(name) __start_subtest(name)
23+
#define recv_timeout(fd, buf, len, flags, timeout) \
24+
recv_timeout_with_splice(fd, buf, len, flags, timeout, use_splice)
25+
926
#define STRP_PKT_HEAD_LEN 4
1027
#define STRP_PKT_BODY_LEN 6
1128
#define STRP_PKT_FULL_LEN (STRP_PKT_HEAD_LEN + STRP_PKT_BODY_LEN)
@@ -431,7 +448,7 @@ static void test_sockmap_strp_verdict(int family, int sotype)
431448
test_sockmap_strp__destroy(strp);
432449
}
433450

434-
void test_sockmap_strp(void)
451+
static void __test_sockmap_strp(void)
435452
{
436453
if (test__start_subtest("sockmap strp tcp pass"))
437454
test_sockmap_strp_pass(AF_INET, SOCK_STREAM, false);
@@ -452,3 +469,12 @@ void test_sockmap_strp(void)
452469
if (test__start_subtest("sockmap strp tcp dispatch"))
453470
test_sockmap_strp_dispatch_pkt(AF_INET, SOCK_STREAM);
454471
}
472+
473+
void test_sockmap_strp(void)
474+
{
475+
use_splice = false;
476+
__test_sockmap_strp();
477+
478+
use_splice = true;
479+
__test_sockmap_strp();
480+
}

0 commit comments

Comments
 (0)