@@ -51,6 +51,7 @@ enum cfg_mode {
51
51
CFG_MODE_POLL ,
52
52
CFG_MODE_MMAP ,
53
53
CFG_MODE_SENDFILE ,
54
+ CFG_MODE_SPLICE ,
54
55
};
55
56
56
57
enum cfg_peek {
@@ -123,7 +124,7 @@ static void die_usage(void)
123
124
fprintf (stderr , "\t-j -- add additional sleep at connection start and tear down "
124
125
"-- for MPJ tests\n" );
125
126
fprintf (stderr , "\t-l -- listens mode, accepts incoming connection\n" );
126
- fprintf (stderr , "\t-m [poll|mmap|sendfile] -- use poll(default)/mmap+write/sendfile\n" );
127
+ fprintf (stderr , "\t-m [poll|mmap|sendfile|splice ] -- use poll(default)/mmap+write/sendfile/splice \n" );
127
128
fprintf (stderr , "\t-M mark -- set socket packet mark\n" );
128
129
fprintf (stderr , "\t-o option -- test sockopt <option>\n" );
129
130
fprintf (stderr , "\t-p num -- use port num\n" );
@@ -925,6 +926,53 @@ static int copyfd_io_sendfile(int infd, int peerfd, int outfd,
925
926
return err ;
926
927
}
927
928
929
+ static int do_splice (const int infd , const int outfd , const size_t len )
930
+ {
931
+ int pipefd [2 ];
932
+ ssize_t bytes ;
933
+ int err ;
934
+
935
+ err = pipe (pipefd );
936
+ if (err )
937
+ return err ;
938
+
939
+ while ((bytes = splice (infd , NULL , pipefd [1 ], NULL , len ,
940
+ SPLICE_F_MOVE | SPLICE_F_MORE )) > 0 ) {
941
+ splice (pipefd [0 ], NULL , outfd , NULL , bytes ,
942
+ SPLICE_F_MOVE | SPLICE_F_MORE );
943
+ }
944
+
945
+ close (pipefd [0 ]);
946
+ close (pipefd [1 ]);
947
+
948
+ return 0 ;
949
+ }
950
+
951
+ static int copyfd_io_splice (int infd , int peerfd , int outfd , unsigned int size ,
952
+ bool * in_closed_after_out , struct wstate * winfo )
953
+ {
954
+ int err ;
955
+
956
+ if (listen_mode ) {
957
+ err = do_splice (peerfd , outfd , size );
958
+ if (err )
959
+ return err ;
960
+
961
+ err = do_splice (infd , peerfd , size );
962
+ } else {
963
+ err = do_splice (infd , peerfd , size );
964
+ if (err )
965
+ return err ;
966
+
967
+ shut_wr (peerfd );
968
+
969
+ err = do_splice (peerfd , outfd , size );
970
+ * in_closed_after_out = true;
971
+ }
972
+
973
+ return err ;
974
+ }
975
+
928
976
static int copyfd_io (int infd , int peerfd , int outfd , bool close_peerfd , struct wstate * winfo )
929
977
{
930
978
bool in_closed_after_out = false;
@@ -957,6 +1005,14 @@ static int copyfd_io(int infd, int peerfd, int outfd, bool close_peerfd, struct
957
1005
& in_closed_after_out , winfo );
958
1006
break ;
959
1007
1008
+ case CFG_MODE_SPLICE :
1009
+ file_size = get_infd_size (infd );
1010
+ if (file_size < 0 )
1011
+ return file_size ;
1012
+ ret = copyfd_io_splice (infd , peerfd , outfd , file_size ,
1013
+ & in_closed_after_out , winfo );
1014
+ break ;
1015
+
960
1016
default :
961
1017
fprintf (stderr , "Invalid mode %d\n" , cfg_mode );
962
1018
@@ -1361,12 +1417,15 @@ int parse_mode(const char *mode)
1361
1417
return CFG_MODE_MMAP ;
1362
1418
if (!strcasecmp (mode , "sendfile" ))
1363
1419
return CFG_MODE_SENDFILE ;
1420
+ if (!strcasecmp (mode , "splice" ))
1421
+ return CFG_MODE_SPLICE ;
1364
1422
1365
1423
fprintf (stderr , "Unknown test mode: %s\n" , mode );
1366
1424
fprintf (stderr , "Supported modes are:\n" );
1367
1425
fprintf (stderr , "\t\t\"poll\" - interleaved read/write using poll()\n" );
1368
1426
fprintf (stderr , "\t\t\"mmap\" - send entire input file (mmap+write), then read response (-l will read input first)\n" );
1369
1427
fprintf (stderr , "\t\t\"sendfile\" - send entire input file (sendfile), then read response (-l will read input first)\n" );
1428
+ fprintf (stderr , "\t\t\"splice\" - send entire input file (splice), then read response (-l will read input first)\n" );
1370
1429
1371
1430
die_usage ();
1372
1431
0 commit comments