mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 16:44:58 +02:00
selftests: mptcp: add splice io mode
This patch adds a new 'splice' io mode for mptcp_connect to test the newly added read_sock() and splice_read() functions of MPTCP. do_splice() efficiently transfers data directly between two file descriptors (infd and outfd) without copying to userspace, using Linux's splice() system call. Usage: ./mptcp_connect.sh -m splice Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn> Reviewed-by: Mat Martineau <martineau@kernel.org> Co-developed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org> Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org> Link: https://patch.msgid.link/20260130-net-next-mptcp-splice-v2-5-31332ba70d7f@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
22f3bd9bf8
commit
6a059c6bfb
|
|
@ -52,6 +52,7 @@ enum cfg_mode {
|
|||
CFG_MODE_POLL,
|
||||
CFG_MODE_MMAP,
|
||||
CFG_MODE_SENDFILE,
|
||||
CFG_MODE_SPLICE,
|
||||
};
|
||||
|
||||
enum cfg_peek {
|
||||
|
|
@ -124,7 +125,7 @@ static void die_usage(void)
|
|||
fprintf(stderr, "\t-j -- add additional sleep at connection start and tear down "
|
||||
"-- for MPJ tests\n");
|
||||
fprintf(stderr, "\t-l -- listens mode, accepts incoming connection\n");
|
||||
fprintf(stderr, "\t-m [poll|mmap|sendfile] -- use poll(default)/mmap+write/sendfile\n");
|
||||
fprintf(stderr, "\t-m [poll|mmap|sendfile|splice] -- use poll(default)/mmap+write/sendfile/splice\n");
|
||||
fprintf(stderr, "\t-M mark -- set socket packet mark\n");
|
||||
fprintf(stderr, "\t-o option -- test sockopt <option>\n");
|
||||
fprintf(stderr, "\t-p num -- use port num\n");
|
||||
|
|
@ -935,6 +936,71 @@ static int copyfd_io_sendfile(int infd, int peerfd, int outfd,
|
|||
return err;
|
||||
}
|
||||
|
||||
static int do_splice(const int infd, const int outfd, const size_t len,
|
||||
struct wstate *winfo)
|
||||
{
|
||||
ssize_t in_bytes, out_bytes;
|
||||
int pipefd[2];
|
||||
int err;
|
||||
|
||||
err = pipe(pipefd);
|
||||
if (err) {
|
||||
perror("pipe");
|
||||
return 2;
|
||||
}
|
||||
|
||||
again:
|
||||
in_bytes = splice(infd, NULL, pipefd[1], NULL, len - winfo->total_len,
|
||||
SPLICE_F_MOVE | SPLICE_F_MORE);
|
||||
if (in_bytes < 0) {
|
||||
perror("splice in");
|
||||
err = 3;
|
||||
} else if (in_bytes > 0) {
|
||||
out_bytes = splice(pipefd[0], NULL, outfd, NULL, in_bytes,
|
||||
SPLICE_F_MOVE | SPLICE_F_MORE);
|
||||
if (out_bytes < 0) {
|
||||
perror("splice out");
|
||||
err = 4;
|
||||
} else if (in_bytes != out_bytes) {
|
||||
fprintf(stderr, "Unexpected transfer: %zu vs %zu\n",
|
||||
in_bytes, out_bytes);
|
||||
err = 5;
|
||||
} else {
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
|
||||
close(pipefd[0]);
|
||||
close(pipefd[1]);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int copyfd_io_splice(int infd, int peerfd, int outfd, unsigned int size,
|
||||
bool *in_closed_after_out, struct wstate *winfo)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (listen_mode) {
|
||||
err = do_splice(peerfd, outfd, size, winfo);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = do_splice(infd, peerfd, size, winfo);
|
||||
} else {
|
||||
err = do_splice(infd, peerfd, size, winfo);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
shut_wr(peerfd);
|
||||
|
||||
err = do_splice(peerfd, outfd, size, winfo);
|
||||
*in_closed_after_out = true;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int copyfd_io(int infd, int peerfd, int outfd, bool close_peerfd, struct wstate *winfo)
|
||||
{
|
||||
bool in_closed_after_out = false;
|
||||
|
|
@ -967,6 +1033,14 @@ static int copyfd_io(int infd, int peerfd, int outfd, bool close_peerfd, struct
|
|||
&in_closed_after_out, winfo);
|
||||
break;
|
||||
|
||||
case CFG_MODE_SPLICE:
|
||||
file_size = get_infd_size(infd);
|
||||
if (file_size < 0)
|
||||
return file_size;
|
||||
ret = copyfd_io_splice(infd, peerfd, outfd, file_size,
|
||||
&in_closed_after_out, winfo);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Invalid mode %d\n", cfg_mode);
|
||||
|
||||
|
|
@ -1380,12 +1454,15 @@ int parse_mode(const char *mode)
|
|||
return CFG_MODE_MMAP;
|
||||
if (!strcasecmp(mode, "sendfile"))
|
||||
return CFG_MODE_SENDFILE;
|
||||
if (!strcasecmp(mode, "splice"))
|
||||
return CFG_MODE_SPLICE;
|
||||
|
||||
fprintf(stderr, "Unknown test mode: %s\n", mode);
|
||||
fprintf(stderr, "Supported modes are:\n");
|
||||
fprintf(stderr, "\t\t\"poll\" - interleaved read/write using poll()\n");
|
||||
fprintf(stderr, "\t\t\"mmap\" - send entire input file (mmap+write), then read response (-l will read input first)\n");
|
||||
fprintf(stderr, "\t\t\"sendfile\" - send entire input file (sendfile), then read response (-l will read input first)\n");
|
||||
fprintf(stderr, "\t\t\"splice\" - send entire input file (splice), then read response (-l will read input first)\n");
|
||||
|
||||
die_usage();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user